Remove submodules, third_party, testing, and tools
This is preparing for gclient switching. Build break is expected. Some change in build script is required. Change-Id: I4ebb78d3ae3114318c101ff4927954c89fce9a1d
This commit is contained in:
parent
e2b29552e9
commit
4a8e868e8f
|
@ -1,28 +0,0 @@
|
||||||
[submodule "base"]
|
|
||||||
path = base
|
|
||||||
url = https://chromium.googlesource.com/chromium/src/base.git
|
|
||||||
[submodule "build"]
|
|
||||||
path = build
|
|
||||||
url = https://chromium.googlesource.com/chromium/src/build.git
|
|
||||||
ignore = untracked
|
|
||||||
[submodule "testing/gmock"]
|
|
||||||
path = testing/gmock
|
|
||||||
url = https://chromium.googlesource.com/external/googlemock.git
|
|
||||||
[submodule "testing/gtest"]
|
|
||||||
path = testing/gtest
|
|
||||||
url = https://chromium.googlesource.com/external/googletest.git
|
|
||||||
[submodule "third_party/gold"]
|
|
||||||
path = third_party/gold
|
|
||||||
url = https://chromium.googlesource.com/chromium/deps/gold.git
|
|
||||||
[submodule "third_party/icu"]
|
|
||||||
path = third_party/icu
|
|
||||||
url = https://chromium.googlesource.com/chromium/deps/icu46.git
|
|
||||||
[submodule "third_party/openssl"]
|
|
||||||
path = third_party/openssl
|
|
||||||
url = https://chromium.googlesource.com/chromium/deps/openssl.git
|
|
||||||
[submodule "tools/gyp"]
|
|
||||||
path = tools/gyp
|
|
||||||
url = https://chromium.googlesource.com/external/gyp.git
|
|
||||||
[submodule "tools/valgrind"]
|
|
||||||
path = tools/valgrind
|
|
||||||
url = https://chromium.googlesource.com/chromium/src/tools/valgrind.git
|
|
1
base
1
base
|
@ -1 +0,0 @@
|
||||||
Subproject commit 44f298322368aff31c5a697a2659bd52a5175541
|
|
1
build
1
build
|
@ -1 +0,0 @@
|
||||||
Subproject commit 3f959aa1388b6308e66cae89adee01ae135f1c04
|
|
|
@ -1 +0,0 @@
|
||||||
*
|
|
|
@ -1,25 +0,0 @@
|
||||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
|
|
||||||
"""Top-level presubmit script for testing.
|
|
||||||
|
|
||||||
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
|
|
||||||
details on the presubmit API built into gcl.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def CommonChecks(input_api, output_api):
|
|
||||||
output = []
|
|
||||||
blacklist = [r'gmock.*', r'gtest.*']
|
|
||||||
output.extend(input_api.canned_checks.RunPylint(
|
|
||||||
input_api, output_api, black_list=blacklist))
|
|
||||||
return output
|
|
||||||
|
|
||||||
|
|
||||||
def CheckChangeOnUpload(input_api, output_api):
|
|
||||||
return CommonChecks(input_api, output_api)
|
|
||||||
|
|
||||||
|
|
||||||
def CheckChangeOnCommit(input_api, output_api):
|
|
||||||
return CommonChecks(input_api, output_api)
|
|
|
@ -1,33 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
Use of this source code is governed by a BSD-style license that can be
|
|
||||||
found in the LICENSE file.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="org.chromium.native_test"
|
|
||||||
android:versionCode="1"
|
|
||||||
android:versionName="1.0">
|
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" />
|
|
||||||
|
|
||||||
<application android:label="ChromeNativeTests">
|
|
||||||
<activity android:name=".ChromeNativeTestActivity"
|
|
||||||
android:label="ChromeNativeTest"
|
|
||||||
android:configChanges="orientation|keyboardHidden">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
|
||||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
|
||||||
|
|
||||||
</manifest>
|
|
|
@ -1,2 +0,0 @@
|
||||||
bulach@chromium.org
|
|
||||||
yfriedman@chromium.org
|
|
|
@ -1,2 +0,0 @@
|
||||||
apk-based runner for Chromium unit test bundles. This is a simple wrapper APK
|
|
||||||
that should include a single gtest native library.
|
|
|
@ -1,84 +0,0 @@
|
||||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
package org.chromium.native_test;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.chromium.base.ChromiumActivity;
|
|
||||||
import org.chromium.base.PathUtils;
|
|
||||||
import org.chromium.base.PowerMonitor;
|
|
||||||
|
|
||||||
// TODO(cjhopman): This should not refer to content. NativeLibraries should be moved to base.
|
|
||||||
import org.chromium.content.app.NativeLibraries;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
// Android's NativeActivity is mostly useful for pure-native code.
|
|
||||||
// Our tests need to go up to our own java classes, which is not possible using
|
|
||||||
// the native activity class loader.
|
|
||||||
public class ChromeNativeTestActivity extends ChromiumActivity {
|
|
||||||
private static final String TAG = "ChromeNativeTestActivity";
|
|
||||||
private static final String EXTRA_RUN_IN_SUB_THREAD = "RunInSubThread";
|
|
||||||
// We post a delayed task to run tests so that we do not block onCreate().
|
|
||||||
private static final long RUN_TESTS_DELAY_IN_MS = 300;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
// Needed by path_utils_unittest.cc
|
|
||||||
PathUtils.setPrivateDataDirectorySuffix("chrome");
|
|
||||||
|
|
||||||
// Needed by system_monitor_unittest.cc
|
|
||||||
PowerMonitor.createForTests(this);
|
|
||||||
|
|
||||||
loadLibraries();
|
|
||||||
Bundle extras = this.getIntent().getExtras();
|
|
||||||
if (extras != null && extras.containsKey(EXTRA_RUN_IN_SUB_THREAD)) {
|
|
||||||
// Create a new thread and run tests on it.
|
|
||||||
new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
runTests();
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
} else {
|
|
||||||
// Post a task to run the tests. This allows us to not block
|
|
||||||
// onCreate and still run tests on the main thread.
|
|
||||||
new Handler().postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
runTests();
|
|
||||||
}
|
|
||||||
}, RUN_TESTS_DELAY_IN_MS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runTests() {
|
|
||||||
// This directory is used by build/android/pylib/test_package_apk.py.
|
|
||||||
nativeRunTests(getFilesDir().getAbsolutePath(), getApplicationContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signal a failure of the native test loader to python scripts
|
|
||||||
// which run tests. For example, we look for
|
|
||||||
// RUNNER_FAILED build/android/test_package.py.
|
|
||||||
private void nativeTestFailed() {
|
|
||||||
Log.e(TAG, "[ RUNNER_FAILED ] could not load native library");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadLibraries() {
|
|
||||||
for (String library: NativeLibraries.libraries) {
|
|
||||||
Log.i(TAG, "loading: " + library);
|
|
||||||
System.loadLibrary(library);
|
|
||||||
Log.i(TAG, "loaded: " + library);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private native void nativeRunTests(String filesDir, Context appContext);
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
|
|
||||||
{
|
|
||||||
'conditions': [
|
|
||||||
['OS=="android"', {
|
|
||||||
'targets': [
|
|
||||||
{
|
|
||||||
'target_name': 'native_test_native_code',
|
|
||||||
'message': 'building native pieces of native test package',
|
|
||||||
'type': 'static_library',
|
|
||||||
'sources': [
|
|
||||||
'native_test_launcher.cc',
|
|
||||||
],
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'ldflags!': [
|
|
||||||
# JNI_OnLoad is implemented in a .a and we need to
|
|
||||||
# re-export in the .so.
|
|
||||||
'-Wl,--exclude-libs=ALL',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'dependencies': [
|
|
||||||
'../../base/base.gyp:base',
|
|
||||||
'../../base/base.gyp:test_support_base',
|
|
||||||
'../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
|
|
||||||
'../gtest.gyp:gtest',
|
|
||||||
'native_test_jni_headers',
|
|
||||||
'native_test_util',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'target_name': 'native_test_jni_headers',
|
|
||||||
'type': 'none',
|
|
||||||
'sources': [
|
|
||||||
'java/src/org/chromium/native_test/ChromeNativeTestActivity.java'
|
|
||||||
],
|
|
||||||
'variables': {
|
|
||||||
'jni_gen_package': 'testing',
|
|
||||||
},
|
|
||||||
'includes': [ '../../build/jni_generator.gypi' ],
|
|
||||||
# So generated jni headers can be found by targets that
|
|
||||||
# depend on this.
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'include_dirs': [
|
|
||||||
'<(SHARED_INTERMEDIATE_DIR)',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'target_name': 'native_test_util',
|
|
||||||
'type': 'static_library',
|
|
||||||
'sources': [
|
|
||||||
'native_test_util.cc',
|
|
||||||
'native_test_util.h',
|
|
||||||
],
|
|
||||||
'dependencies': [
|
|
||||||
'../../base/base.gyp:base',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}]
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,202 +0,0 @@
|
||||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
// This class sets up the environment for running the native tests inside an
|
|
||||||
// android application. It outputs (to a fifo) markers identifying the
|
|
||||||
// START/PASSED/CRASH of the test suite, FAILURE/SUCCESS of individual tests,
|
|
||||||
// etc.
|
|
||||||
// These markers are read by the test runner script to generate test results.
|
|
||||||
// It installs signal handlers to detect crashes.
|
|
||||||
|
|
||||||
#include <android/log.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include "base/android/base_jni_registrar.h"
|
|
||||||
#include "base/android/fifo_utils.h"
|
|
||||||
#include "base/android/jni_android.h"
|
|
||||||
#include "base/android/jni_string.h"
|
|
||||||
#include "base/android/scoped_java_ref.h"
|
|
||||||
#include "base/at_exit.h"
|
|
||||||
#include "base/base_switches.h"
|
|
||||||
#include "base/command_line.h"
|
|
||||||
#include "base/file_util.h"
|
|
||||||
#include "base/files/file_path.h"
|
|
||||||
#include "base/logging.h"
|
|
||||||
#include "base/strings/stringprintf.h"
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
#include "testing/android/native_test_util.h"
|
|
||||||
#include "testing/jni/ChromeNativeTestActivity_jni.h"
|
|
||||||
|
|
||||||
using testing::native_test_util::ArgsToArgv;
|
|
||||||
using testing::native_test_util::ParseArgsFromCommandLineFile;
|
|
||||||
using testing::native_test_util::ScopedMainEntryLogger;
|
|
||||||
|
|
||||||
// The main function of the program to be wrapped as a test apk.
|
|
||||||
extern int main(int argc, char** argv);
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// These two command line flags are supported for DumpRenderTree, which needs
|
|
||||||
// three fifos rather than a combined one: one for stderr, stdin and stdout.
|
|
||||||
const char kSeparateStderrFifo[] = "separate-stderr-fifo";
|
|
||||||
const char kCreateStdinFifo[] = "create-stdin-fifo";
|
|
||||||
|
|
||||||
// The test runner script writes the command line file in
|
|
||||||
// "/data/local/tmp".
|
|
||||||
static const char kCommandLineFilePath[] =
|
|
||||||
"/data/local/tmp/chrome-native-tests-command-line";
|
|
||||||
|
|
||||||
const char kLogTag[] = "chromium";
|
|
||||||
const char kCrashedMarker[] = "[ CRASHED ]\n";
|
|
||||||
|
|
||||||
// The list of signals which are considered to be crashes.
|
|
||||||
const int kExceptionSignals[] = {
|
|
||||||
SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, -1
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sigaction g_old_sa[NSIG];
|
|
||||||
|
|
||||||
// This function runs in a compromised context. It should not allocate memory.
|
|
||||||
void SignalHandler(int sig, siginfo_t* info, void* reserved) {
|
|
||||||
// Output the crash marker.
|
|
||||||
write(STDOUT_FILENO, kCrashedMarker, sizeof(kCrashedMarker));
|
|
||||||
g_old_sa[sig].sa_sigaction(sig, info, reserved);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(nileshagrawal): now that we're using FIFO, test scripts can detect EOF.
|
|
||||||
// Remove the signal handlers.
|
|
||||||
void InstallHandlers() {
|
|
||||||
struct sigaction sa;
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
|
||||||
|
|
||||||
sa.sa_sigaction = SignalHandler;
|
|
||||||
sa.sa_flags = SA_SIGINFO;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; kExceptionSignals[i] != -1; ++i) {
|
|
||||||
sigaction(kExceptionSignals[i], &sa, &g_old_sa[kExceptionSignals[i]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes printf() style string to Android's logger where |priority| is one of
|
|
||||||
// the levels defined in <android/log.h>.
|
|
||||||
void AndroidLog(int priority, const char* format, ...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
__android_log_vprint(priority, kLogTag, format, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensures that the fifo at |path| is created by deleting whatever is at |path|
|
|
||||||
// prior to (re)creating the fifo, otherwise logs the error and terminates the
|
|
||||||
// program.
|
|
||||||
void EnsureCreateFIFO(const base::FilePath& path) {
|
|
||||||
unlink(path.value().c_str());
|
|
||||||
if (base::android::CreateFIFO(path, 0666))
|
|
||||||
return;
|
|
||||||
|
|
||||||
AndroidLog(ANDROID_LOG_ERROR, "Failed to create fifo %s: %s\n",
|
|
||||||
path.value().c_str(), strerror(errno));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensures that |stream| is redirected to |path|, otherwise logs the error and
|
|
||||||
// terminates the program.
|
|
||||||
void EnsureRedirectStream(FILE* stream,
|
|
||||||
const base::FilePath& path,
|
|
||||||
const char* mode) {
|
|
||||||
if (base::android::RedirectStream(stream, path, mode))
|
|
||||||
return;
|
|
||||||
|
|
||||||
AndroidLog(ANDROID_LOG_ERROR, "Failed to redirect stream to file: %s: %s\n",
|
|
||||||
path.value().c_str(), strerror(errno));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// This method is called on a separate java thread so that we won't trigger
|
|
||||||
// an ANR.
|
|
||||||
static void RunTests(JNIEnv* env,
|
|
||||||
jobject obj,
|
|
||||||
jstring jfiles_dir,
|
|
||||||
jobject app_context) {
|
|
||||||
base::AtExitManager exit_manager;
|
|
||||||
|
|
||||||
// Command line initialized basically, will be fully initialized later.
|
|
||||||
static const char* const kInitialArgv[] = { "ChromeTestActivity" };
|
|
||||||
CommandLine::Init(arraysize(kInitialArgv), kInitialArgv);
|
|
||||||
|
|
||||||
// Set the application context in base.
|
|
||||||
base::android::ScopedJavaLocalRef<jobject> scoped_context(
|
|
||||||
env, env->NewLocalRef(app_context));
|
|
||||||
base::android::InitApplicationContext(scoped_context);
|
|
||||||
base::android::RegisterJni(env);
|
|
||||||
|
|
||||||
std::vector<std::string> args;
|
|
||||||
ParseArgsFromCommandLineFile(kCommandLineFilePath, &args);
|
|
||||||
|
|
||||||
std::vector<char*> argv;
|
|
||||||
int argc = ArgsToArgv(args, &argv);
|
|
||||||
|
|
||||||
// Fully initialize command line with arguments.
|
|
||||||
CommandLine::ForCurrentProcess()->AppendArguments(
|
|
||||||
CommandLine(argc, &argv[0]), false);
|
|
||||||
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
|
|
||||||
|
|
||||||
base::FilePath files_dir(
|
|
||||||
base::android::ConvertJavaStringToUTF8(env, jfiles_dir));
|
|
||||||
|
|
||||||
// A few options, such "--gtest_list_tests", will just use printf directly
|
|
||||||
// Always redirect stdout to a known file.
|
|
||||||
base::FilePath fifo_path(files_dir.Append(base::FilePath("test.fifo")));
|
|
||||||
EnsureCreateFIFO(fifo_path);
|
|
||||||
|
|
||||||
base::FilePath stderr_fifo_path, stdin_fifo_path;
|
|
||||||
|
|
||||||
// DumpRenderTree needs a separate fifo for the stderr output. For all
|
|
||||||
// other tests, insert stderr content to the same fifo we use for stdout.
|
|
||||||
if (command_line.HasSwitch(kSeparateStderrFifo)) {
|
|
||||||
stderr_fifo_path = files_dir.Append(base::FilePath("stderr.fifo"));
|
|
||||||
EnsureCreateFIFO(stderr_fifo_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DumpRenderTree uses stdin to receive input about which test to run.
|
|
||||||
if (command_line.HasSwitch(kCreateStdinFifo)) {
|
|
||||||
stdin_fifo_path = files_dir.Append(base::FilePath("stdin.fifo"));
|
|
||||||
EnsureCreateFIFO(stdin_fifo_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only redirect the streams after all fifos have been created.
|
|
||||||
EnsureRedirectStream(stdout, fifo_path, "w");
|
|
||||||
if (!stdin_fifo_path.empty())
|
|
||||||
EnsureRedirectStream(stdin, stdin_fifo_path, "r");
|
|
||||||
if (!stderr_fifo_path.empty())
|
|
||||||
EnsureRedirectStream(stderr, stderr_fifo_path, "w");
|
|
||||||
else
|
|
||||||
dup2(STDOUT_FILENO, STDERR_FILENO);
|
|
||||||
|
|
||||||
if (command_line.HasSwitch(switches::kWaitForDebugger)) {
|
|
||||||
AndroidLog(ANDROID_LOG_VERBOSE,
|
|
||||||
"Native test waiting for GDB because flag %s was supplied",
|
|
||||||
switches::kWaitForDebugger);
|
|
||||||
base::debug::WaitForDebugger(24 * 60 * 60, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopedMainEntryLogger scoped_main_entry_logger;
|
|
||||||
main(argc, &argv[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is called by the VM when the shared library is first loaded.
|
|
||||||
JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
|
||||||
// Install signal handlers to detect crashes.
|
|
||||||
InstallHandlers();
|
|
||||||
|
|
||||||
base::android::InitVM(vm);
|
|
||||||
JNIEnv* env = base::android::AttachCurrentThread();
|
|
||||||
if (!RegisterNativesImpl(env)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return JNI_VERSION_1_4;
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "testing/android/native_test_util.h"
|
|
||||||
|
|
||||||
#include "base/file_util.h"
|
|
||||||
#include "base/files/file_path.h"
|
|
||||||
#include "base/strings/string_tokenizer.h"
|
|
||||||
#include "base/strings/string_util.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void ParseArgsFromString(const std::string& command_line,
|
|
||||||
std::vector<std::string>* args) {
|
|
||||||
base::StringTokenizer tokenizer(command_line, kWhitespaceASCII);
|
|
||||||
tokenizer.set_quote_chars("\"");
|
|
||||||
while (tokenizer.GetNext()) {
|
|
||||||
std::string token;
|
|
||||||
RemoveChars(tokenizer.token(), "\"", &token);
|
|
||||||
args->push_back(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
namespace native_test_util {
|
|
||||||
|
|
||||||
void ParseArgsFromCommandLineFile(
|
|
||||||
const char* path, std::vector<std::string>* args) {
|
|
||||||
base::FilePath command_line(path);
|
|
||||||
std::string command_line_string;
|
|
||||||
if (file_util::ReadFileToString(command_line, &command_line_string)) {
|
|
||||||
ParseArgsFromString(command_line_string, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ArgsToArgv(const std::vector<std::string>& args,
|
|
||||||
std::vector<char*>* argv) {
|
|
||||||
// We need to pass in a non-const char**.
|
|
||||||
int argc = args.size();
|
|
||||||
|
|
||||||
argv->resize(argc + 1);
|
|
||||||
for (int i = 0; i < argc; ++i) {
|
|
||||||
(*argv)[i] = const_cast<char*>(args[i].c_str());
|
|
||||||
}
|
|
||||||
(*argv)[argc] = NULL; // argv must be NULL terminated.
|
|
||||||
|
|
||||||
return argc;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace native_test_util
|
|
||||||
} // namespace testing
|
|
|
@ -1,37 +0,0 @@
|
||||||
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef TESTING_ANDROID_NATIVE_TEST_UTIL_
|
|
||||||
#define TESTING_ANDROID_NATIVE_TEST_UTIL_
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
// Helper methods for setting up environment for running gtest tests
|
|
||||||
// inside an APK.
|
|
||||||
namespace testing {
|
|
||||||
namespace native_test_util {
|
|
||||||
|
|
||||||
class ScopedMainEntryLogger {
|
|
||||||
public:
|
|
||||||
ScopedMainEntryLogger() {
|
|
||||||
printf(">>ScopedMainEntryLogger\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
~ScopedMainEntryLogger() {
|
|
||||||
printf("<<ScopedMainEntryLogger\n");
|
|
||||||
fflush(stdout);
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void ParseArgsFromCommandLineFile(
|
|
||||||
const char* path, std::vector<std::string>* args);
|
|
||||||
int ArgsToArgv(const std::vector<std::string>& args, std::vector<char*>* argv);
|
|
||||||
|
|
||||||
} // namespace native_test_util
|
|
||||||
} // namespace testing
|
|
||||||
|
|
||||||
#endif // TESTING_ANDROID_NATIVE_TEST_UTIL_
|
|
|
@ -1,457 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
|
|
||||||
HEADER = """\
|
|
||||||
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
// This file automatically generated by testing/generate_gmock_mutant.py.
|
|
||||||
// DO NOT EDIT.
|
|
||||||
|
|
||||||
#ifndef TESTING_GMOCK_MUTANT_H_
|
|
||||||
#define TESTING_GMOCK_MUTANT_H_
|
|
||||||
|
|
||||||
// The intention of this file is to make possible using GMock actions in
|
|
||||||
// all of its syntactic beauty. Classes and helper functions can be used as
|
|
||||||
// more generic variants of Task and Callback classes (see base/task.h)
|
|
||||||
// Mutant supports both pre-bound arguments (like Task) and call-time
|
|
||||||
// arguments (like Callback) - hence the name. :-)
|
|
||||||
//
|
|
||||||
// DispatchToMethod/Function supports two sets of arguments: pre-bound (P) and
|
|
||||||
// call-time (C). The arguments as well as the return type are templatized.
|
|
||||||
// DispatchToMethod/Function will also try to call the selected method or
|
|
||||||
// function even if provided pre-bound arguments does not match exactly with
|
|
||||||
// the function signature hence the X1, X2 ... XN parameters in CreateFunctor.
|
|
||||||
// DispatchToMethod will try to invoke method that may not belong to the
|
|
||||||
// object's class itself but to the object's class base class.
|
|
||||||
//
|
|
||||||
// Additionally you can bind the object at calltime by binding a pointer to
|
|
||||||
// pointer to the object at creation time - before including this file you
|
|
||||||
// have to #define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING.
|
|
||||||
//
|
|
||||||
// TODO(stoyan): It's yet not clear to me should we use T& and T&* instead
|
|
||||||
// of T* and T** when we invoke CreateFunctor to match the EXPECT_CALL style.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Sample usage with gMock:
|
|
||||||
//
|
|
||||||
// struct Mock : public ObjectDelegate {
|
|
||||||
// MOCK_METHOD2(string, OnRequest(int n, const string& request));
|
|
||||||
// MOCK_METHOD1(void, OnQuit(int exit_code));
|
|
||||||
// MOCK_METHOD2(void, LogMessage(int level, const string& message));
|
|
||||||
//
|
|
||||||
// string HandleFlowers(const string& reply, int n, const string& request) {
|
|
||||||
// string result = SStringPrintf("In request of %d %s ", n, request);
|
|
||||||
// for (int i = 0; i < n; ++i) result.append(reply)
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void DoLogMessage(int level, const string& message) {
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void QuitMessageLoop(int seconds) {
|
|
||||||
// MessageLoop* loop = MessageLoop::current();
|
|
||||||
// loop->PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(),
|
|
||||||
// 1000 * seconds);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// Mock mock;
|
|
||||||
// // Will invoke mock.HandleFlowers("orchids", n, request)
|
|
||||||
// // "orchids" is a pre-bound argument, and <n> and <request> are call-time
|
|
||||||
// // arguments - they are not known until the OnRequest mock is invoked.
|
|
||||||
// EXPECT_CALL(mock, OnRequest(Ge(5), StartsWith("flower"))
|
|
||||||
// .Times(1)
|
|
||||||
// .WillOnce(Invoke(CreateFunctor(&mock, &Mock::HandleFlowers,
|
|
||||||
// string("orchids"))));
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // No pre-bound arguments, two call-time arguments passed
|
|
||||||
// // directly to DoLogMessage
|
|
||||||
// EXPECT_CALL(mock, OnLogMessage(_, _))
|
|
||||||
// .Times(AnyNumber())
|
|
||||||
// .WillAlways(Invoke(CreateFunctor, &mock, &Mock::DoLogMessage));
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // In this case we have a single pre-bound argument - 3. We ignore
|
|
||||||
// // all of the arguments of OnQuit.
|
|
||||||
// EXCEPT_CALL(mock, OnQuit(_))
|
|
||||||
// .Times(1)
|
|
||||||
// .WillOnce(InvokeWithoutArgs(CreateFunctor(
|
|
||||||
// &mock, &Mock::QuitMessageLoop, 3)));
|
|
||||||
//
|
|
||||||
// MessageLoop loop;
|
|
||||||
// loop.Run();
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // Here is another example of how we can set an action that invokes
|
|
||||||
// // method of an object that is not yet created.
|
|
||||||
// struct Mock : public ObjectDelegate {
|
|
||||||
// MOCK_METHOD1(void, DemiurgeCreated(Demiurge*));
|
|
||||||
// MOCK_METHOD2(void, OnRequest(int count, const string&));
|
|
||||||
//
|
|
||||||
// void StoreDemiurge(Demiurge* w) {
|
|
||||||
// demiurge_ = w;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Demiurge* demiurge;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// EXPECT_CALL(mock, DemiurgeCreated(_)).Times(1)
|
|
||||||
// .WillOnce(Invoke(CreateFunctor(&mock, &Mock::StoreDemiurge)));
|
|
||||||
//
|
|
||||||
// EXPECT_CALL(mock, OnRequest(_, StrEq("Moby Dick")))
|
|
||||||
// .Times(AnyNumber())
|
|
||||||
// .WillAlways(WithArgs<0>(Invoke(
|
|
||||||
// CreateFunctor(&mock->demiurge_, &Demiurge::DecreaseMonsters))));
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "base/memory/linked_ptr.h"
|
|
||||||
#include "base/tuple.h" // for Tuple
|
|
||||||
|
|
||||||
namespace testing {"""
|
|
||||||
|
|
||||||
MUTANT = """\
|
|
||||||
|
|
||||||
// Interface that is exposed to the consumer, that does the actual calling
|
|
||||||
// of the method.
|
|
||||||
template <typename R, typename Params>
|
|
||||||
class MutantRunner {
|
|
||||||
public:
|
|
||||||
virtual R RunWithParams(const Params& params) = 0;
|
|
||||||
virtual ~MutantRunner() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Mutant holds pre-bound arguments (like Task). Like Callback
|
|
||||||
// allows call-time arguments. You bind a pointer to the object
|
|
||||||
// at creation time.
|
|
||||||
template <typename R, typename T, typename Method,
|
|
||||||
typename PreBound, typename Params>
|
|
||||||
class Mutant : public MutantRunner<R, Params> {
|
|
||||||
public:
|
|
||||||
Mutant(T* obj, Method method, const PreBound& pb)
|
|
||||||
: obj_(obj), method_(method), pb_(pb) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// MutantRunner implementation
|
|
||||||
virtual R RunWithParams(const Params& params) {
|
|
||||||
return DispatchToMethod<R>(this->obj_, this->method_, pb_, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
T* obj_;
|
|
||||||
Method method_;
|
|
||||||
PreBound pb_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename R, typename Function, typename PreBound, typename Params>
|
|
||||||
class MutantFunction : public MutantRunner<R, Params> {
|
|
||||||
public:
|
|
||||||
MutantFunction(Function function, const PreBound& pb)
|
|
||||||
: function_(function), pb_(pb) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// MutantRunner implementation
|
|
||||||
virtual R RunWithParams(const Params& params) {
|
|
||||||
return DispatchToFunction<R>(function_, pb_, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
Function function_;
|
|
||||||
PreBound pb_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
|
|
||||||
// MutantLateBind is like Mutant, but you bind a pointer to a pointer
|
|
||||||
// to the object. This way you can create actions for an object
|
|
||||||
// that is not yet created (has only storage for a pointer to it).
|
|
||||||
template <typename R, typename T, typename Method,
|
|
||||||
typename PreBound, typename Params>
|
|
||||||
class MutantLateObjectBind : public MutantRunner<R, Params> {
|
|
||||||
public:
|
|
||||||
MutantLateObjectBind(T** obj, Method method, const PreBound& pb)
|
|
||||||
: obj_(obj), method_(method), pb_(pb) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// MutantRunner implementation.
|
|
||||||
virtual R RunWithParams(const Params& params) {
|
|
||||||
EXPECT_THAT(*this->obj_, testing::NotNull());
|
|
||||||
if (NULL == *this->obj_)
|
|
||||||
return R();
|
|
||||||
return DispatchToMethod<R>( *this->obj_, this->method_, pb_, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
T** obj_;
|
|
||||||
Method method_;
|
|
||||||
PreBound pb_;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Simple MutantRunner<> wrapper acting as a functor.
|
|
||||||
// Redirects operator() to MutantRunner<Params>::Run()
|
|
||||||
template <typename R, typename Params>
|
|
||||||
struct MutantFunctor {
|
|
||||||
explicit MutantFunctor(MutantRunner<R, Params>* cb) : impl_(cb) {
|
|
||||||
}
|
|
||||||
|
|
||||||
~MutantFunctor() {
|
|
||||||
}
|
|
||||||
|
|
||||||
inline R operator()() {
|
|
||||||
return impl_->RunWithParams(Tuple0());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Arg1>
|
|
||||||
inline R operator()(const Arg1& a) {
|
|
||||||
return impl_->RunWithParams(Params(a));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Arg1, typename Arg2>
|
|
||||||
inline R operator()(const Arg1& a, const Arg2& b) {
|
|
||||||
return impl_->RunWithParams(Params(a, b));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Arg1, typename Arg2, typename Arg3>
|
|
||||||
inline R operator()(const Arg1& a, const Arg2& b, const Arg3& c) {
|
|
||||||
return impl_->RunWithParams(Params(a, b, c));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
|
|
||||||
inline R operator()(const Arg1& a, const Arg2& b, const Arg3& c,
|
|
||||||
const Arg4& d) {
|
|
||||||
return impl_->RunWithParams(Params(a, b, c, d));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// We need copy constructor since MutantFunctor is copied few times
|
|
||||||
// inside GMock machinery, hence no DISALLOW_EVIL_CONTRUCTORS
|
|
||||||
MutantFunctor();
|
|
||||||
linked_ptr<MutantRunner<R, Params> > impl_;
|
|
||||||
};
|
|
||||||
"""
|
|
||||||
|
|
||||||
FOOTER = """\
|
|
||||||
} // namespace testing
|
|
||||||
|
|
||||||
#endif // TESTING_GMOCK_MUTANT_H_"""
|
|
||||||
|
|
||||||
# Templates for DispatchToMethod/DispatchToFunction functions.
|
|
||||||
# template_params - typename P1, typename P2.. typename C1..
|
|
||||||
# prebound - TupleN<P1, .. PN>
|
|
||||||
# calltime - TupleN<C1, .. CN>
|
|
||||||
# args - p.a, p.b.., c.a, c.b..
|
|
||||||
DISPATCH_TO_METHOD_TEMPLATE = """\
|
|
||||||
template <typename R, typename T, typename Method, %(template_params)s>
|
|
||||||
inline R DispatchToMethod(T* obj, Method method,
|
|
||||||
const %(prebound)s& p,
|
|
||||||
const %(calltime)s& c) {
|
|
||||||
return (obj->*method)(%(args)s);
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
DISPATCH_TO_FUNCTION_TEMPLATE = """\
|
|
||||||
template <typename R, typename Function, %(template_params)s>
|
|
||||||
inline R DispatchToFunction(Function function,
|
|
||||||
const %(prebound)s& p,
|
|
||||||
const %(calltime)s& c) {
|
|
||||||
return (*function)(%(args)s);
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Templates for CreateFunctor functions.
|
|
||||||
# template_params - typename P1, typename P2.. typename C1.. typename X1..
|
|
||||||
# prebound - TupleN<P1, .. PN>
|
|
||||||
# calltime - TupleN<A1, .. AN>
|
|
||||||
# params - X1,.. , A1, ..
|
|
||||||
# args - const P1& p1 ..
|
|
||||||
# call_args - p1, p2, p3..
|
|
||||||
CREATE_METHOD_FUNCTOR_TEMPLATE = """\
|
|
||||||
template <typename R, typename T, typename U, %(template_params)s>
|
|
||||||
inline MutantFunctor<R, %(calltime)s>
|
|
||||||
CreateFunctor(T* obj, R (U::*method)(%(params)s), %(args)s) {
|
|
||||||
MutantRunner<R, %(calltime)s>* t =
|
|
||||||
new Mutant<R, T, R (U::*)(%(params)s),
|
|
||||||
%(prebound)s, %(calltime)s>
|
|
||||||
(obj, method, MakeTuple(%(call_args)s));
|
|
||||||
return MutantFunctor<R, %(calltime)s>(t);
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
CREATE_FUNCTION_FUNCTOR_TEMPLATE = """\
|
|
||||||
template <typename R, %(template_params)s>
|
|
||||||
inline MutantFunctor<R, %(calltime)s>
|
|
||||||
CreateFunctor(R (*function)(%(params)s), %(args)s) {
|
|
||||||
MutantRunner<R, %(calltime)s>* t =
|
|
||||||
new MutantFunction<R, R (*)(%(params)s),
|
|
||||||
%(prebound)s, %(calltime)s>
|
|
||||||
(function, MakeTuple(%(call_args)s));
|
|
||||||
return MutantFunctor<R, %(calltime)s>(t);
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
def SplitLine(line, width):
|
|
||||||
"""Splits a single line at comma, at most |width| characters long."""
|
|
||||||
if len(line) < width:
|
|
||||||
return (line, None)
|
|
||||||
n = 1 + line[:width].rfind(",")
|
|
||||||
if n == 0: # If comma cannot be found give up and return the entire line.
|
|
||||||
return (line, None)
|
|
||||||
# Assume there is a space after the comma
|
|
||||||
assert line[n] == " "
|
|
||||||
return (line[:n], line[n + 1:])
|
|
||||||
|
|
||||||
|
|
||||||
def Wrap(s, width, subsequent_offset=4):
|
|
||||||
"""Wraps a single line |s| at commas so every line is at most |width|
|
|
||||||
characters long.
|
|
||||||
"""
|
|
||||||
w = []
|
|
||||||
spaces = " " * subsequent_offset
|
|
||||||
while s:
|
|
||||||
(f, s) = SplitLine(s, width)
|
|
||||||
w.append(f)
|
|
||||||
if s:
|
|
||||||
s = spaces + s
|
|
||||||
return "\n".join(w)
|
|
||||||
|
|
||||||
|
|
||||||
def Clean(s):
|
|
||||||
"""Cleans artifacts from generated C++ code.
|
|
||||||
|
|
||||||
Our simple string formatting/concatenation may introduce extra commas.
|
|
||||||
"""
|
|
||||||
s = s.replace("<>", "")
|
|
||||||
s = s.replace(", >", ">")
|
|
||||||
s = s.replace(", )", ")")
|
|
||||||
s = s.replace(">>", "> >")
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
def ExpandPattern(pattern, it):
|
|
||||||
"""Return list of expanded pattern strings.
|
|
||||||
|
|
||||||
Each string is created by replacing all '%' in |pattern| with element of |it|.
|
|
||||||
"""
|
|
||||||
return [pattern.replace("%", x) for x in it]
|
|
||||||
|
|
||||||
|
|
||||||
def Gen(pattern, n):
|
|
||||||
"""Expands pattern replacing '%' with sequential integers.
|
|
||||||
|
|
||||||
Expanded patterns will be joined with comma separator.
|
|
||||||
GenAlphs("X%", 3) will return "X1, X2, X3".
|
|
||||||
"""
|
|
||||||
it = string.hexdigits[1:n + 1]
|
|
||||||
return ", ".join(ExpandPattern(pattern, it))
|
|
||||||
|
|
||||||
|
|
||||||
def GenAlpha(pattern, n):
|
|
||||||
"""Expands pattern replacing '%' with sequential small ASCII letters.
|
|
||||||
|
|
||||||
Expanded patterns will be joined with comma separator.
|
|
||||||
GenAlphs("X%", 3) will return "Xa, Xb, Xc".
|
|
||||||
"""
|
|
||||||
it = string.ascii_lowercase[0:n]
|
|
||||||
return ", ".join(ExpandPattern(pattern, it))
|
|
||||||
|
|
||||||
|
|
||||||
def Merge(a):
|
|
||||||
return ", ".join(filter(len, a))
|
|
||||||
|
|
||||||
|
|
||||||
def GenTuple(pattern, n):
|
|
||||||
return Clean("Tuple%d<%s>" % (n, Gen(pattern, n)))
|
|
||||||
|
|
||||||
|
|
||||||
def FixCode(s):
|
|
||||||
lines = Clean(s).splitlines()
|
|
||||||
# Wrap sometimes very long 1st and 3rd line at 80th column.
|
|
||||||
lines[0] = Wrap(lines[0], 80, 10)
|
|
||||||
lines[2] = Wrap(lines[2], 80, 4)
|
|
||||||
return "\n".join(lines)
|
|
||||||
|
|
||||||
|
|
||||||
def GenerateDispatch(prebound, calltime):
|
|
||||||
print "\n// %d - %d" % (prebound, calltime)
|
|
||||||
args = {
|
|
||||||
"template_params": Merge([Gen("typename P%", prebound),
|
|
||||||
Gen("typename C%", calltime)]),
|
|
||||||
"prebound": GenTuple("P%", prebound),
|
|
||||||
"calltime": GenTuple("C%", calltime),
|
|
||||||
"args": Merge([GenAlpha("p.%", prebound), GenAlpha("c.%", calltime)]),
|
|
||||||
}
|
|
||||||
|
|
||||||
print FixCode(DISPATCH_TO_METHOD_TEMPLATE % args)
|
|
||||||
print FixCode(DISPATCH_TO_FUNCTION_TEMPLATE % args)
|
|
||||||
|
|
||||||
|
|
||||||
def GenerateCreateFunctor(prebound, calltime):
|
|
||||||
print "// %d - %d" % (prebound, calltime)
|
|
||||||
args = {
|
|
||||||
"calltime": GenTuple("A%", calltime),
|
|
||||||
"prebound": GenTuple("P%", prebound),
|
|
||||||
"params": Merge([Gen("X%", prebound), Gen("A%", calltime)]),
|
|
||||||
"args": Gen("const P%& p%", prebound),
|
|
||||||
"call_args": Gen("p%", prebound),
|
|
||||||
"template_params": Merge([Gen("typename P%", prebound),
|
|
||||||
Gen("typename A%", calltime),
|
|
||||||
Gen("typename X%", prebound)])
|
|
||||||
}
|
|
||||||
|
|
||||||
mutant = FixCode(CREATE_METHOD_FUNCTOR_TEMPLATE % args)
|
|
||||||
print mutant
|
|
||||||
|
|
||||||
# Slightly different version for free function call.
|
|
||||||
print "\n", FixCode(CREATE_FUNCTION_FUNCTOR_TEMPLATE % args)
|
|
||||||
|
|
||||||
# Functor with pointer to a pointer of the object.
|
|
||||||
print "\n#ifdef GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING"
|
|
||||||
mutant2 = mutant.replace("CreateFunctor(T* obj,", "CreateFunctor(T** obj,")
|
|
||||||
mutant2 = mutant2.replace("new Mutant", "new MutantLateObjectBind")
|
|
||||||
mutant2 = mutant2.replace(" " * 17 + "Tuple", " " * 31 + "Tuple")
|
|
||||||
print mutant2
|
|
||||||
print "#endif // GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING\n"
|
|
||||||
|
|
||||||
# OS_WIN specific. Same functors but with stdcall calling conventions.
|
|
||||||
# These are not for WIN64 (x86_64) because there is only one calling
|
|
||||||
# convention in WIN64.
|
|
||||||
# Functor for method with __stdcall calling conventions.
|
|
||||||
print "#if defined (OS_WIN) && !defined (ARCH_CPU_X86_64)"
|
|
||||||
stdcall_method = CREATE_METHOD_FUNCTOR_TEMPLATE
|
|
||||||
stdcall_method = stdcall_method.replace("U::", "__stdcall U::")
|
|
||||||
stdcall_method = FixCode(stdcall_method % args)
|
|
||||||
print stdcall_method
|
|
||||||
# Functor for free function with __stdcall calling conventions.
|
|
||||||
stdcall_function = CREATE_FUNCTION_FUNCTOR_TEMPLATE
|
|
||||||
stdcall_function = stdcall_function.replace("R (*", "R (__stdcall *")
|
|
||||||
print "\n", FixCode(stdcall_function % args)
|
|
||||||
|
|
||||||
print "#ifdef GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING"
|
|
||||||
stdcall2 = stdcall_method
|
|
||||||
stdcall2 = stdcall2.replace("CreateFunctor(T* obj,", "CreateFunctor(T** obj,")
|
|
||||||
stdcall2 = stdcall2.replace("new Mutant", "new MutantLateObjectBind")
|
|
||||||
stdcall2 = stdcall2.replace(" " * 17 + "Tuple", " " * 31 + "Tuple")
|
|
||||||
print stdcall2
|
|
||||||
print "#endif // GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING"
|
|
||||||
print "#endif // defined (OS_WIN) && !defined (ARCH_CPU_X86_64)\n"
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
print HEADER
|
|
||||||
for prebound in xrange(0, 6 + 1):
|
|
||||||
for args in xrange(0, 6 + 1):
|
|
||||||
GenerateDispatch(prebound, args)
|
|
||||||
print MUTANT
|
|
||||||
for prebound in xrange(0, 6 + 1):
|
|
||||||
for args in xrange(0, 6 + 1):
|
|
||||||
GenerateCreateFunctor(prebound, args)
|
|
||||||
print FOOTER
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 6b1759c3816d574bddde3e1725c51a811c8870e7
|
|
|
@ -1,62 +0,0 @@
|
||||||
# Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
|
|
||||||
{
|
|
||||||
'targets': [
|
|
||||||
{
|
|
||||||
'target_name': 'gmock',
|
|
||||||
'type': 'static_library',
|
|
||||||
'dependencies': [
|
|
||||||
'gtest.gyp:gtest',
|
|
||||||
],
|
|
||||||
'sources': [
|
|
||||||
# Sources based on files in r173 of gmock.
|
|
||||||
'gmock/include/gmock/gmock-actions.h',
|
|
||||||
'gmock/include/gmock/gmock-cardinalities.h',
|
|
||||||
'gmock/include/gmock/gmock-generated-actions.h',
|
|
||||||
'gmock/include/gmock/gmock-generated-function-mockers.h',
|
|
||||||
'gmock/include/gmock/gmock-generated-matchers.h',
|
|
||||||
'gmock/include/gmock/gmock-generated-nice-strict.h',
|
|
||||||
'gmock/include/gmock/gmock-matchers.h',
|
|
||||||
'gmock/include/gmock/gmock-spec-builders.h',
|
|
||||||
'gmock/include/gmock/gmock.h',
|
|
||||||
'gmock/include/gmock/internal/gmock-generated-internal-utils.h',
|
|
||||||
'gmock/include/gmock/internal/gmock-internal-utils.h',
|
|
||||||
'gmock/include/gmock/internal/gmock-port.h',
|
|
||||||
'gmock/src/gmock-all.cc',
|
|
||||||
'gmock/src/gmock-cardinalities.cc',
|
|
||||||
'gmock/src/gmock-internal-utils.cc',
|
|
||||||
'gmock/src/gmock-matchers.cc',
|
|
||||||
'gmock/src/gmock-spec-builders.cc',
|
|
||||||
'gmock/src/gmock.cc',
|
|
||||||
'gmock_mutant.h', # gMock helpers
|
|
||||||
],
|
|
||||||
'sources!': [
|
|
||||||
'gmock/src/gmock-all.cc', # Not needed by our build.
|
|
||||||
],
|
|
||||||
'include_dirs': [
|
|
||||||
'gmock',
|
|
||||||
'gmock/include',
|
|
||||||
],
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'include_dirs': [
|
|
||||||
'gmock/include', # So that gmock headers can find themselves.
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'export_dependent_settings': [
|
|
||||||
'gtest.gyp:gtest',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'target_name': 'gmock_main',
|
|
||||||
'type': 'static_library',
|
|
||||||
'dependencies': [
|
|
||||||
'gmock',
|
|
||||||
],
|
|
||||||
'sources': [
|
|
||||||
'gmock/src/gmock_main.cc',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1 +0,0 @@
|
||||||
Subproject commit 74de57c951aedebc5dfe26a27604353432392b98
|
|
|
@ -1,236 +0,0 @@
|
||||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
|
|
||||||
{
|
|
||||||
'targets': [
|
|
||||||
{
|
|
||||||
'target_name': 'gtest',
|
|
||||||
'type': 'static_library',
|
|
||||||
'sources': [
|
|
||||||
'gtest/include/gtest/gtest-death-test.h',
|
|
||||||
'gtest/include/gtest/gtest-message.h',
|
|
||||||
'gtest/include/gtest/gtest-param-test.h',
|
|
||||||
'gtest/include/gtest/gtest-printers.h',
|
|
||||||
'gtest/include/gtest/gtest-spi.h',
|
|
||||||
'gtest/include/gtest/gtest-test-part.h',
|
|
||||||
'gtest/include/gtest/gtest-typed-test.h',
|
|
||||||
'gtest/include/gtest/gtest.h',
|
|
||||||
'gtest/include/gtest/gtest_pred_impl.h',
|
|
||||||
'gtest/include/gtest/internal/gtest-death-test-internal.h',
|
|
||||||
'gtest/include/gtest/internal/gtest-filepath.h',
|
|
||||||
'gtest/include/gtest/internal/gtest-internal.h',
|
|
||||||
'gtest/include/gtest/internal/gtest-linked_ptr.h',
|
|
||||||
'gtest/include/gtest/internal/gtest-param-util-generated.h',
|
|
||||||
'gtest/include/gtest/internal/gtest-param-util.h',
|
|
||||||
'gtest/include/gtest/internal/gtest-port.h',
|
|
||||||
'gtest/include/gtest/internal/gtest-string.h',
|
|
||||||
'gtest/include/gtest/internal/gtest-tuple.h',
|
|
||||||
'gtest/include/gtest/internal/gtest-type-util.h',
|
|
||||||
'gtest/src/gtest-all.cc',
|
|
||||||
'gtest/src/gtest-death-test.cc',
|
|
||||||
'gtest/src/gtest-filepath.cc',
|
|
||||||
'gtest/src/gtest-internal-inl.h',
|
|
||||||
'gtest/src/gtest-port.cc',
|
|
||||||
'gtest/src/gtest-printers.cc',
|
|
||||||
'gtest/src/gtest-test-part.cc',
|
|
||||||
'gtest/src/gtest-typed-test.cc',
|
|
||||||
'gtest/src/gtest.cc',
|
|
||||||
'multiprocess_func_list.cc',
|
|
||||||
'multiprocess_func_list.h',
|
|
||||||
'platform_test.h',
|
|
||||||
],
|
|
||||||
'sources!': [
|
|
||||||
'gtest/src/gtest-all.cc', # Not needed by our build.
|
|
||||||
],
|
|
||||||
'include_dirs': [
|
|
||||||
'gtest',
|
|
||||||
'gtest/include',
|
|
||||||
],
|
|
||||||
'dependencies': [
|
|
||||||
'gtest_prod',
|
|
||||||
],
|
|
||||||
'conditions': [
|
|
||||||
['OS == "mac" or OS == "ios"', {
|
|
||||||
'sources': [
|
|
||||||
'gtest_mac.h',
|
|
||||||
'gtest_mac.mm',
|
|
||||||
'platform_test_mac.mm'
|
|
||||||
],
|
|
||||||
'link_settings': {
|
|
||||||
'libraries': [
|
|
||||||
'$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
['OS == "ios"', {
|
|
||||||
'dependencies' : [
|
|
||||||
'<(DEPTH)/testing/iossim/iossim.gyp:iossim#host',
|
|
||||||
],
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'target_conditions': [
|
|
||||||
# Turn all tests into bundles on iOS because that's the only
|
|
||||||
# type of executable supported for iOS.
|
|
||||||
['_type=="executable"', {
|
|
||||||
'variables': {
|
|
||||||
# Use a variable so the path gets fixed up so it is always
|
|
||||||
# correct when INFOPLIST_FILE finally gets set.
|
|
||||||
'ios_unittest_info_plist_path':
|
|
||||||
'<(DEPTH)/testing/gtest_ios/unittest-Info.plist',
|
|
||||||
},
|
|
||||||
'mac_bundle': 1,
|
|
||||||
'xcode_settings': {
|
|
||||||
'BUNDLE_ID_TEST_NAME':
|
|
||||||
'>!(echo ">(_target_name)" | sed -e "s/_//g")',
|
|
||||||
'INFOPLIST_FILE': '>(ios_unittest_info_plist_path)',
|
|
||||||
},
|
|
||||||
'mac_bundle_resources': [
|
|
||||||
'<(ios_unittest_info_plist_path)',
|
|
||||||
'<(DEPTH)/testing/gtest_ios/Default-568h@2x.png',
|
|
||||||
],
|
|
||||||
'mac_bundle_resources!': [
|
|
||||||
'<(ios_unittest_info_plist_path)',
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
['OS=="ios" and asan==1', {
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'target_conditions': [
|
|
||||||
# Package the ASan runtime dylib into the test app bundles.
|
|
||||||
['_type=="executable"', {
|
|
||||||
'postbuilds': [
|
|
||||||
{
|
|
||||||
'variables': {
|
|
||||||
# Define copy_asan_dylib_path in a variable ending in
|
|
||||||
# _path so that gyp understands it's a path and
|
|
||||||
# performs proper relativization during dict merging.
|
|
||||||
'copy_asan_dylib_path':
|
|
||||||
'<(DEPTH)/build/mac/copy_asan_runtime_dylib.sh',
|
|
||||||
},
|
|
||||||
'postbuild_name': 'Copy ASan runtime dylib',
|
|
||||||
'action': [
|
|
||||||
'>(copy_asan_dylib_path)',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
['os_posix == 1', {
|
|
||||||
'defines': [
|
|
||||||
# gtest isn't able to figure out when RTTI is disabled for gcc
|
|
||||||
# versions older than 4.3.2, and assumes it's enabled. Our Mac
|
|
||||||
# and Linux builds disable RTTI, and cannot guarantee that the
|
|
||||||
# compiler will be 4.3.2. or newer. The Mac, for example, uses
|
|
||||||
# 4.2.1 as that is the latest available on that platform. gtest
|
|
||||||
# must be instructed that RTTI is disabled here, and for any
|
|
||||||
# direct dependents that might include gtest headers.
|
|
||||||
'GTEST_HAS_RTTI=0',
|
|
||||||
],
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'defines': [
|
|
||||||
'GTEST_HAS_RTTI=0',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
['OS=="android" and android_app_abi=="x86"', {
|
|
||||||
'defines': [
|
|
||||||
'GTEST_HAS_CLONE=0',
|
|
||||||
],
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'defines': [
|
|
||||||
'GTEST_HAS_CLONE=0',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
['OS=="android"', {
|
|
||||||
# We want gtest features that use tr1::tuple, but we currently
|
|
||||||
# don't support the variadic templates used by libstdc++'s
|
|
||||||
# implementation. gtest supports this scenario by providing its
|
|
||||||
# own implementation but we must opt in to it.
|
|
||||||
'defines': [
|
|
||||||
'GTEST_USE_OWN_TR1_TUPLE=1',
|
|
||||||
# GTEST_USE_OWN_TR1_TUPLE only works if GTEST_HAS_TR1_TUPLE is set.
|
|
||||||
# gtest r625 made it so that GTEST_HAS_TR1_TUPLE is set to 0
|
|
||||||
# automatically on android, so it has to be set explicitly here.
|
|
||||||
'GTEST_HAS_TR1_TUPLE=1',
|
|
||||||
],
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'defines': [
|
|
||||||
'GTEST_USE_OWN_TR1_TUPLE=1',
|
|
||||||
'GTEST_HAS_TR1_TUPLE=1',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
['OS=="win" and (MSVS_VERSION=="2012" or MSVS_VERSION=="2012e")', {
|
|
||||||
'defines': [
|
|
||||||
'_VARIADIC_MAX=10',
|
|
||||||
],
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'defines': [
|
|
||||||
'_VARIADIC_MAX=10',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'defines': [
|
|
||||||
'UNIT_TEST',
|
|
||||||
],
|
|
||||||
'include_dirs': [
|
|
||||||
'gtest/include', # So that gtest headers can find themselves.
|
|
||||||
],
|
|
||||||
'target_conditions': [
|
|
||||||
['_type=="executable"', {
|
|
||||||
'test': 1,
|
|
||||||
'conditions': [
|
|
||||||
['OS=="mac"', {
|
|
||||||
'run_as': {
|
|
||||||
'action????': ['${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}'],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
['OS=="ios"', {
|
|
||||||
'variables': {
|
|
||||||
# Use a variable so the path gets fixed up so it is always
|
|
||||||
# correct when the action finally gets used.
|
|
||||||
'ios_run_unittest_script_path':
|
|
||||||
'<(DEPTH)/testing/gtest_ios/run-unittest.sh',
|
|
||||||
},
|
|
||||||
'run_as': {
|
|
||||||
'action????': ['>(ios_run_unittest_script_path)'],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
['OS=="win"', {
|
|
||||||
'run_as': {
|
|
||||||
'action????': ['$(TargetPath)', '--gtest_print_time'],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
'msvs_disabled_warnings': [4800],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'target_name': 'gtest_main',
|
|
||||||
'type': 'static_library',
|
|
||||||
'dependencies': [
|
|
||||||
'gtest',
|
|
||||||
],
|
|
||||||
'sources': [
|
|
||||||
'gtest/src/gtest_main.cc',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'target_name': 'gtest_prod',
|
|
||||||
'toolsets': ['host', 'target'],
|
|
||||||
'type': 'none',
|
|
||||||
'sources': [
|
|
||||||
'gtest/include/gtest/gtest_prod.h',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
|
@ -1,87 +0,0 @@
|
||||||
#!/bin/bash -p
|
|
||||||
|
|
||||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
# Environment sanitization. Set a known-safe PATH. Clear environment variables
|
|
||||||
# that might impact the interpreter's operation. The |bash -p| invocation
|
|
||||||
# on the #! line takes the bite out of BASH_ENV, ENV, and SHELLOPTS (among
|
|
||||||
# other features), but clearing them here ensures that they won't impact any
|
|
||||||
# shell scripts used as utility programs. SHELLOPTS is read-only and can't be
|
|
||||||
# unset, only unexported.
|
|
||||||
export PATH="/usr/bin:/bin:/usr/sbin:/sbin"
|
|
||||||
unset BASH_ENV CDPATH ENV GLOBIGNORE IFS POSIXLY_CORRECT
|
|
||||||
export -n SHELLOPTS
|
|
||||||
|
|
||||||
readonly ScriptDir=$(dirname "$(echo ${0} | sed -e "s,^\([^/]\),$(pwd)/\1,")")
|
|
||||||
readonly ScriptName=$(basename "${0}")
|
|
||||||
readonly ThisScript="${ScriptDir}/${ScriptName}"
|
|
||||||
readonly SimExecutable="${BUILD_DIR}/ninja-iossim/${CONFIGURATION}/iossim"
|
|
||||||
|
|
||||||
# Helper to print a line formatted for Xcodes build output parser.
|
|
||||||
XcodeNote() {
|
|
||||||
echo "${ThisScript}:${1}: note: ${2}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Helper to print a divider to make things stick out in a busy output window.
|
|
||||||
XcodeHeader() {
|
|
||||||
echo "note: _________________________________________________________________"
|
|
||||||
echo "note: _________________________________________________________________"
|
|
||||||
echo "note: _________________________________________________________________"
|
|
||||||
XcodeNote "$1" ">>>>> $2"
|
|
||||||
echo "note: _________________________________________________________________"
|
|
||||||
echo "note: _________________________________________________________________"
|
|
||||||
echo "note: _________________________________________________________________"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Kills the iPhone Simulator if it is running.
|
|
||||||
KillSimulator() {
|
|
||||||
/usr/bin/killall "iPhone Simulator" 2> /dev/null || true
|
|
||||||
}
|
|
||||||
|
|
||||||
# Runs tests via the iPhone Simulator for multiple devices.
|
|
||||||
RunTests() {
|
|
||||||
local -r appPath="${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app"
|
|
||||||
|
|
||||||
if [[ ! -x "${SimExecutable}" ]]; then
|
|
||||||
echo "Unable to run tests: ${SimExecutable} was not found/executable."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
for device in 'iPhone' 'iPad'; do
|
|
||||||
iosVersion="6.1"
|
|
||||||
KillSimulator
|
|
||||||
local command=(
|
|
||||||
"${SimExecutable}" "-d${device}" "-s${iosVersion}" "${appPath}"
|
|
||||||
)
|
|
||||||
# Pass along any command line flags
|
|
||||||
if [[ "$#" -gt 0 ]]; then
|
|
||||||
command+=( "--" "${@}" )
|
|
||||||
fi
|
|
||||||
XcodeHeader ${LINENO} "Launching tests for ${device} (iOS ${iosVersion})"
|
|
||||||
"${command[@]}"
|
|
||||||
|
|
||||||
# If the command didn't exit successfully, abort.
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
exit $?;
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Time to get to work.
|
|
||||||
|
|
||||||
if [[ "${PLATFORM_NAME}" != "iphonesimulator" ]]; then
|
|
||||||
XcodeNote ${LINENO} "Skipping running of unittests for device build."
|
|
||||||
else
|
|
||||||
if [[ "$#" -gt 0 ]]; then
|
|
||||||
RunTests "${@}"
|
|
||||||
else
|
|
||||||
RunTests
|
|
||||||
fi
|
|
||||||
KillSimulator
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>English</string>
|
|
||||||
<key>CFBundleDisplayName</key>
|
|
||||||
<string>${PRODUCT_NAME}</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>${EXECUTABLE_NAME}</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>com.google.gtest.${BUNDLE_ID_TEST_NAME}</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>CFBundleName</key>
|
|
||||||
<string>${PRODUCT_NAME}</string>
|
|
||||||
<key>CFBundlePackageType</key>
|
|
||||||
<string>APPL</string>
|
|
||||||
<key>CFBundleSignature</key>
|
|
||||||
<string>????</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
<key>LSRequiresIPhoneOS</key>
|
|
||||||
<true/>
|
|
||||||
<key>UISupportedInterfaceOrientation</key>
|
|
||||||
<array>
|
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,48 +0,0 @@
|
||||||
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef TESTING_GTEST_MAC_H_
|
|
||||||
#define TESTING_GTEST_MAC_H_
|
|
||||||
|
|
||||||
#include <gtest/internal/gtest-port.h>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#ifdef GTEST_OS_MAC
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// This overloaded version allows comparison between ObjC objects that conform
|
|
||||||
// to the NSObject protocol. Used to implement {ASSERT|EXPECT}_EQ().
|
|
||||||
GTEST_API_ AssertionResult CmpHelperNSEQ(const char* expected_expression,
|
|
||||||
const char* actual_expression,
|
|
||||||
id<NSObject> expected,
|
|
||||||
id<NSObject> actual);
|
|
||||||
|
|
||||||
// This overloaded version allows comparison between ObjC objects that conform
|
|
||||||
// to the NSObject protocol. Used to implement {ASSERT|EXPECT}_NE().
|
|
||||||
GTEST_API_ AssertionResult CmpHelperNSNE(const char* expected_expression,
|
|
||||||
const char* actual_expression,
|
|
||||||
id<NSObject> expected,
|
|
||||||
id<NSObject> actual);
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace testing
|
|
||||||
|
|
||||||
// Tests that [expected isEqual:actual].
|
|
||||||
#define EXPECT_NSEQ(expected, actual) \
|
|
||||||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNSEQ, expected, actual)
|
|
||||||
#define EXPECT_NSNE(val1, val2) \
|
|
||||||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNSNE, val1, val2)
|
|
||||||
|
|
||||||
#define ASSERT_NSEQ(expected, actual) \
|
|
||||||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNSEQ, expected, actual)
|
|
||||||
#define ASSERT_NSNE(val1, val2) \
|
|
||||||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNSNE, val1, val2)
|
|
||||||
|
|
||||||
#endif // GTEST_OS_MAC
|
|
||||||
|
|
||||||
#endif // TESTING_GTEST_MAC_H_
|
|
|
@ -1,61 +0,0 @@
|
||||||
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#import "gtest_mac.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <gtest/internal/gtest-port.h>
|
|
||||||
#include <gtest/internal/gtest-string.h>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#ifdef GTEST_OS_MAC
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// Handles nil values for |obj| properly by using safe printing of %@ in
|
|
||||||
// -stringWithFormat:.
|
|
||||||
static inline const char* StringDescription(id<NSObject> obj) {
|
|
||||||
return [[NSString stringWithFormat:@"%@", obj] UTF8String];
|
|
||||||
}
|
|
||||||
|
|
||||||
// This overloaded version allows comparison between ObjC objects that conform
|
|
||||||
// to the NSObject protocol. Used to implement {ASSERT|EXPECT}_EQ().
|
|
||||||
GTEST_API_ AssertionResult CmpHelperNSEQ(const char* expected_expression,
|
|
||||||
const char* actual_expression,
|
|
||||||
id<NSObject> expected,
|
|
||||||
id<NSObject> actual) {
|
|
||||||
if (expected == actual || [expected isEqual:actual]) {
|
|
||||||
return AssertionSuccess();
|
|
||||||
}
|
|
||||||
return EqFailure(expected_expression,
|
|
||||||
actual_expression,
|
|
||||||
std::string(StringDescription(expected)),
|
|
||||||
std::string(StringDescription(actual)),
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This overloaded version allows comparison between ObjC objects that conform
|
|
||||||
// to the NSObject protocol. Used to implement {ASSERT|EXPECT}_NE().
|
|
||||||
GTEST_API_ AssertionResult CmpHelperNSNE(const char* expected_expression,
|
|
||||||
const char* actual_expression,
|
|
||||||
id<NSObject> expected,
|
|
||||||
id<NSObject> actual) {
|
|
||||||
if (expected != actual && ![expected isEqual:actual]) {
|
|
||||||
return AssertionSuccess();
|
|
||||||
}
|
|
||||||
Message msg;
|
|
||||||
msg << "Expected: (" << expected_expression << ") != (" << actual_expression
|
|
||||||
<< "), actual: " << StringDescription(expected)
|
|
||||||
<< " vs " << StringDescription(actual);
|
|
||||||
return AssertionFailure(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace testing
|
|
||||||
|
|
||||||
#endif // GTEST_OS_MAC
|
|
|
@ -1,57 +0,0 @@
|
||||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
// Note that while this file is in testing/ and tests GTest macros, it is built
|
|
||||||
// as part of Chromium's unit_tests target because the project does not build
|
|
||||||
// or run GTest's internal test suite.
|
|
||||||
|
|
||||||
#import "testing/gtest_mac.h"
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
|
||||||
#include "testing/gtest/include/gtest/internal/gtest-port.h"
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
|
||||||
|
|
||||||
TEST(GTestMac, ExpectNSEQ) {
|
|
||||||
base::mac::ScopedNSAutoreleasePool pool;
|
|
||||||
|
|
||||||
EXPECT_NSEQ(@"a", @"a");
|
|
||||||
|
|
||||||
NSString* s1 = [NSString stringWithUTF8String:"a"];
|
|
||||||
NSString* s2 = @"a";
|
|
||||||
EXPECT_NE(s1, s2);
|
|
||||||
EXPECT_NSEQ(s1, s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(GTestMac, AssertNSEQ) {
|
|
||||||
base::mac::ScopedNSAutoreleasePool pool;
|
|
||||||
|
|
||||||
NSString* s1 = [NSString stringWithUTF8String:"a"];
|
|
||||||
NSString* s2 = @"a";
|
|
||||||
EXPECT_NE(s1, s2);
|
|
||||||
ASSERT_NSEQ(s1, s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(GTestMac, ExpectNSNE) {
|
|
||||||
base::mac::ScopedNSAutoreleasePool pool;
|
|
||||||
|
|
||||||
EXPECT_NSNE([NSNumber numberWithInt:2], [NSNumber numberWithInt:42]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(GTestMac, AssertNSNE) {
|
|
||||||
base::mac::ScopedNSAutoreleasePool pool;
|
|
||||||
|
|
||||||
ASSERT_NSNE(@"a", @"b");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(GTestMac, ExpectNSNil) {
|
|
||||||
base::mac::ScopedNSAutoreleasePool pool;
|
|
||||||
|
|
||||||
EXPECT_NSEQ(nil, nil);
|
|
||||||
EXPECT_NSNE(nil, @"a");
|
|
||||||
EXPECT_NSNE(@"a", nil);
|
|
||||||
|
|
||||||
// TODO(shess): Test that EXPECT_NSNE(nil, nil) fails.
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
lliabraa@chromium.org
|
|
||||||
rohitrao@chromium.org
|
|
||||||
stuartmorgan@chromium.org
|
|
|
@ -1,87 +0,0 @@
|
||||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
|
|
||||||
{
|
|
||||||
'conditions': [
|
|
||||||
['OS!="ios" or "<(GENERATOR)"=="ninja"', {
|
|
||||||
'targets': [
|
|
||||||
{
|
|
||||||
'target_name': 'iossim',
|
|
||||||
'toolsets': ['host'],
|
|
||||||
'type': 'executable',
|
|
||||||
'variables': {
|
|
||||||
'developer_dir': '<!(xcode-select -print-path)',
|
|
||||||
'iphone_sim_path': '<(developer_dir)/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks',
|
|
||||||
'other_frameworks_path': '<(developer_dir)/../OtherFrameworks'
|
|
||||||
},
|
|
||||||
'dependencies': [
|
|
||||||
'third_party/class-dump/class-dump.gyp:class-dump#host',
|
|
||||||
],
|
|
||||||
'include_dirs': [
|
|
||||||
'<(INTERMEDIATE_DIR)/iossim',
|
|
||||||
],
|
|
||||||
'sources': [
|
|
||||||
'iossim.mm',
|
|
||||||
'<(INTERMEDIATE_DIR)/iossim/iPhoneSimulatorRemoteClient.h',
|
|
||||||
],
|
|
||||||
'libraries': [
|
|
||||||
'$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
|
|
||||||
],
|
|
||||||
'actions': [
|
|
||||||
{
|
|
||||||
'action_name': 'generate_iphone_sim_header',
|
|
||||||
'inputs': [
|
|
||||||
'<(iphone_sim_path)/iPhoneSimulatorRemoteClient.framework/Versions/Current/iPhoneSimulatorRemoteClient',
|
|
||||||
'<(PRODUCT_DIR)/class-dump',
|
|
||||||
],
|
|
||||||
'outputs': [
|
|
||||||
'<(INTERMEDIATE_DIR)/iossim/iPhoneSimulatorRemoteClient.h'
|
|
||||||
],
|
|
||||||
'action': [
|
|
||||||
# Actions don't provide a way to redirect stdout, so a custom
|
|
||||||
# script is invoked that will execute the first argument and write
|
|
||||||
# the output to the file specified as the second argument.
|
|
||||||
'./redirect-stdout.sh',
|
|
||||||
'<(PRODUCT_DIR)/class-dump -CiPhoneSimulator <(iphone_sim_path)/iPhoneSimulatorRemoteClient.framework',
|
|
||||||
'<(INTERMEDIATE_DIR)/iossim/iPhoneSimulatorRemoteClient.h',
|
|
||||||
],
|
|
||||||
'message': 'Generating header',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}, { # else, OS=="ios" and "<(GENERATOR)"!="ninja"
|
|
||||||
'variables': {
|
|
||||||
'ninja_output_dir': 'ninja-iossim',
|
|
||||||
'ninja_product_dir':
|
|
||||||
'$(SYMROOT)/<(ninja_output_dir)/<(CONFIGURATION_NAME)',
|
|
||||||
},
|
|
||||||
'targets': [
|
|
||||||
{
|
|
||||||
'target_name': 'iossim',
|
|
||||||
'type': 'none',
|
|
||||||
'variables': {
|
|
||||||
# Gyp to rerun
|
|
||||||
're_run_targets': [
|
|
||||||
'testing/iossim/iossim.gyp',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'includes': ['../../build/ios/mac_build.gypi'],
|
|
||||||
'actions': [
|
|
||||||
{
|
|
||||||
'action_name': 'compile iossim',
|
|
||||||
'inputs': [],
|
|
||||||
'outputs': [],
|
|
||||||
'action': [
|
|
||||||
'<@(ninja_cmd)',
|
|
||||||
'iossim',
|
|
||||||
],
|
|
||||||
'message': 'Generating the iossim executable',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,727 +0,0 @@
|
||||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#include <asl.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
// An executable (iossim) that runs an app in the iOS Simulator.
|
|
||||||
// Run 'iossim -h' for usage information.
|
|
||||||
//
|
|
||||||
// For best results, the iOS Simulator application should not be running when
|
|
||||||
// iossim is invoked.
|
|
||||||
//
|
|
||||||
// Headers for the iPhoneSimulatorRemoteClient framework used in this tool are
|
|
||||||
// generated by class-dump, via GYP.
|
|
||||||
// (class-dump is available at http://www.codethecode.com/projects/class-dump/)
|
|
||||||
//
|
|
||||||
// However, there are some forward declarations required to get things to
|
|
||||||
// compile. Also, the DTiPhoneSimulatorSessionDelegate protocol is referenced
|
|
||||||
// by the iPhoneSimulatorRemoteClient framework, but not defined in the object
|
|
||||||
// file, so it must be defined here before importing the generated
|
|
||||||
// iPhoneSimulatorRemoteClient.h file.
|
|
||||||
|
|
||||||
@class DTiPhoneSimulatorApplicationSpecifier;
|
|
||||||
@class DTiPhoneSimulatorSession;
|
|
||||||
@class DTiPhoneSimulatorSessionConfig;
|
|
||||||
@class DTiPhoneSimulatorSystemRoot;
|
|
||||||
|
|
||||||
@protocol DTiPhoneSimulatorSessionDelegate
|
|
||||||
- (void)session:(DTiPhoneSimulatorSession*)session
|
|
||||||
didEndWithError:(NSError*)error;
|
|
||||||
- (void)session:(DTiPhoneSimulatorSession*)session
|
|
||||||
didStart:(BOOL)started
|
|
||||||
withError:(NSError*)error;
|
|
||||||
@end
|
|
||||||
|
|
||||||
#import "iPhoneSimulatorRemoteClient.h"
|
|
||||||
|
|
||||||
// An undocumented system log key included in messages from launchd. The value
|
|
||||||
// is the PID of the process the message is about (as opposed to launchd's PID).
|
|
||||||
#define ASL_KEY_REF_PID "RefPID"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// Name of environment variables that control the user's home directory in the
|
|
||||||
// simulator.
|
|
||||||
const char* const kUserHomeEnvVariable = "CFFIXED_USER_HOME";
|
|
||||||
const char* const kHomeEnvVariable = "HOME";
|
|
||||||
|
|
||||||
// Device family codes for iPhone and iPad.
|
|
||||||
const int kIPhoneFamily = 1;
|
|
||||||
const int kIPadFamily = 2;
|
|
||||||
|
|
||||||
// Max number of seconds to wait for the simulator session to start.
|
|
||||||
// This timeout must allow time to start up iOS Simulator, install the app
|
|
||||||
// and perform any other black magic that is encoded in the
|
|
||||||
// iPhoneSimulatorRemoteClient framework to kick things off. Normal start up
|
|
||||||
// time is only a couple seconds but machine load, disk caches, etc., can all
|
|
||||||
// affect startup time in the wild so the timeout needs to be fairly generous.
|
|
||||||
// If this timeout occurs iossim will likely exit with non-zero status; the
|
|
||||||
// exception being if the app is invoked and completes execution before the
|
|
||||||
// session is started (this case is handled in session:didStart:withError).
|
|
||||||
const NSTimeInterval kDefaultSessionStartTimeoutSeconds = 30;
|
|
||||||
|
|
||||||
// While the simulated app is running, its stdout is redirected to a file which
|
|
||||||
// is polled by iossim and written to iossim's stdout using the following
|
|
||||||
// polling interval.
|
|
||||||
const NSTimeInterval kOutputPollIntervalSeconds = 0.1;
|
|
||||||
|
|
||||||
// The path within the developer dir of the private Simulator frameworks.
|
|
||||||
NSString* const kSimulatorFrameworkRelativePath =
|
|
||||||
@"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/"
|
|
||||||
@"iPhoneSimulatorRemoteClient.framework";
|
|
||||||
NSString* const kDevToolsFoundationRelativePath =
|
|
||||||
@"../OtherFrameworks/DevToolsFoundation.framework";
|
|
||||||
NSString* const kSimulatorRelativePath =
|
|
||||||
@"Platforms/iPhoneSimulator.platform/Developer/Applications/"
|
|
||||||
@"iPhone Simulator.app";
|
|
||||||
|
|
||||||
// Simulator Error String Key. This can be found by looking in the Simulator's
|
|
||||||
// Localizable.strings files.
|
|
||||||
NSString* const kSimulatorAppQuitErrorKey = @"The simulated application quit.";
|
|
||||||
|
|
||||||
const char* gToolName = "iossim";
|
|
||||||
|
|
||||||
// Exit status codes.
|
|
||||||
const int kExitSuccess = EXIT_SUCCESS;
|
|
||||||
const int kExitFailure = EXIT_FAILURE;
|
|
||||||
const int kExitInvalidArguments = 2;
|
|
||||||
const int kExitInitializationFailure = 3;
|
|
||||||
const int kExitAppFailedToStart = 4;
|
|
||||||
const int kExitAppCrashed = 5;
|
|
||||||
|
|
||||||
void LogError(NSString* format, ...) {
|
|
||||||
va_list list;
|
|
||||||
va_start(list, format);
|
|
||||||
|
|
||||||
NSString* message =
|
|
||||||
[[[NSString alloc] initWithFormat:format arguments:list] autorelease];
|
|
||||||
|
|
||||||
fprintf(stderr, "%s: ERROR: %s\n", gToolName, [message UTF8String]);
|
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
va_end(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LogWarning(NSString* format, ...) {
|
|
||||||
va_list list;
|
|
||||||
va_start(list, format);
|
|
||||||
|
|
||||||
NSString* message =
|
|
||||||
[[[NSString alloc] initWithFormat:format arguments:list] autorelease];
|
|
||||||
|
|
||||||
fprintf(stderr, "%s: WARNING: %s\n", gToolName, [message UTF8String]);
|
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
va_end(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// A delegate that is called when the simulated app is started or ended in the
|
|
||||||
// simulator.
|
|
||||||
@interface SimulatorDelegate : NSObject <DTiPhoneSimulatorSessionDelegate> {
|
|
||||||
@private
|
|
||||||
NSString* stdioPath_;
|
|
||||||
NSString* developerDir_;
|
|
||||||
NSThread* outputThread_;
|
|
||||||
NSBundle* simulatorBundle_;
|
|
||||||
BOOL appRunning_;
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
// An implementation that copies the simulated app's stdio to stdout of this
|
|
||||||
// executable. While it would be nice to get stdout and stderr independently
|
|
||||||
// from iOS Simulator, issues like I/O buffering and interleaved output
|
|
||||||
// between iOS Simulator and the app would cause iossim to display things out
|
|
||||||
// of order here. Printing all output to a single file keeps the order correct.
|
|
||||||
// Instances of this classe should be initialized with the location of the
|
|
||||||
// simulated app's output file. When the simulated app starts, a thread is
|
|
||||||
// started which handles copying data from the simulated app's output file to
|
|
||||||
// the stdout of this executable.
|
|
||||||
@implementation SimulatorDelegate
|
|
||||||
|
|
||||||
// Specifies the file locations of the simulated app's stdout and stderr.
|
|
||||||
- (SimulatorDelegate*)initWithStdioPath:(NSString*)stdioPath
|
|
||||||
developerDir:(NSString*)developerDir {
|
|
||||||
self = [super init];
|
|
||||||
if (self) {
|
|
||||||
stdioPath_ = [stdioPath copy];
|
|
||||||
developerDir_ = [developerDir copy];
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc {
|
|
||||||
[stdioPath_ release];
|
|
||||||
[developerDir_ release];
|
|
||||||
[simulatorBundle_ release];
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads data from the simulated app's output and writes it to stdout. This
|
|
||||||
// method blocks, so it should be called in a separate thread. The iOS
|
|
||||||
// Simulator takes a file path for the simulated app's stdout and stderr, but
|
|
||||||
// this path isn't always available (e.g. when the stdout is Xcode's build
|
|
||||||
// window). As a workaround, iossim creates a temp file to hold output, which
|
|
||||||
// this method reads and copies to stdout.
|
|
||||||
- (void)tailOutput {
|
|
||||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
|
|
||||||
// Copy data to stdout/stderr while the app is running.
|
|
||||||
NSFileHandle* simio = [NSFileHandle fileHandleForReadingAtPath:stdioPath_];
|
|
||||||
NSFileHandle* standardOutput = [NSFileHandle fileHandleWithStandardOutput];
|
|
||||||
while (appRunning_) {
|
|
||||||
NSAutoreleasePool* innerPool = [[NSAutoreleasePool alloc] init];
|
|
||||||
[standardOutput writeData:[simio readDataToEndOfFile]];
|
|
||||||
[NSThread sleepForTimeInterval:kOutputPollIntervalSeconds];
|
|
||||||
[innerPool drain];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Once the app is no longer running, copy any data that was written during
|
|
||||||
// the last sleep cycle.
|
|
||||||
[standardOutput writeData:[simio readDataToEndOfFile]];
|
|
||||||
|
|
||||||
[pool drain];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetches a localized error string from the Simulator.
|
|
||||||
- (NSString *)localizedSimulatorErrorString:(NSString*)stringKey {
|
|
||||||
// Lazy load of the simulator bundle.
|
|
||||||
if (simulatorBundle_ == nil) {
|
|
||||||
NSString* simulatorPath = [developerDir_
|
|
||||||
stringByAppendingPathComponent:kSimulatorRelativePath];
|
|
||||||
simulatorBundle_ = [NSBundle bundleWithPath:simulatorPath];
|
|
||||||
}
|
|
||||||
NSString *localizedStr =
|
|
||||||
[simulatorBundle_ localizedStringForKey:stringKey
|
|
||||||
value:nil
|
|
||||||
table:nil];
|
|
||||||
if ([localizedStr length])
|
|
||||||
return localizedStr;
|
|
||||||
// Failed to get a value, follow Cocoa conventions and use the key as the
|
|
||||||
// string.
|
|
||||||
return stringKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)session:(DTiPhoneSimulatorSession*)session
|
|
||||||
didStart:(BOOL)started
|
|
||||||
withError:(NSError*)error {
|
|
||||||
if (!started) {
|
|
||||||
// If the test executes very quickly (<30ms), the SimulatorDelegate may not
|
|
||||||
// get the initial session:started:withError: message indicating successful
|
|
||||||
// startup of the simulated app. Instead the delegate will get a
|
|
||||||
// session:started:withError: message after the timeout has elapsed. To
|
|
||||||
// account for this case, check if the simulated app's stdio file was
|
|
||||||
// ever created and if it exists dump it to stdout and return success.
|
|
||||||
NSFileManager* fileManager = [NSFileManager defaultManager];
|
|
||||||
if ([fileManager fileExistsAtPath:stdioPath_]) {
|
|
||||||
appRunning_ = NO;
|
|
||||||
[self tailOutput];
|
|
||||||
// Note that exiting in this state leaves a process running
|
|
||||||
// (e.g. /.../iPhoneSimulator4.3.sdk/usr/libexec/installd -t 30) that will
|
|
||||||
// prevent future simulator sessions from being started for 30 seconds
|
|
||||||
// unless the iOS Simulator application is killed altogether.
|
|
||||||
[self session:session didEndWithError:nil];
|
|
||||||
|
|
||||||
// session:didEndWithError should not return (because it exits) so
|
|
||||||
// the execution path should never get here.
|
|
||||||
exit(kExitFailure);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogError(@"Simulator failed to start: \"%@\" (%@:%ld)",
|
|
||||||
[error localizedDescription],
|
|
||||||
[error domain], static_cast<long int>([error code]));
|
|
||||||
exit(kExitAppFailedToStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a thread to write contents of outputPath to stdout.
|
|
||||||
appRunning_ = YES;
|
|
||||||
outputThread_ = [[NSThread alloc] initWithTarget:self
|
|
||||||
selector:@selector(tailOutput)
|
|
||||||
object:nil];
|
|
||||||
[outputThread_ start];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)session:(DTiPhoneSimulatorSession*)session
|
|
||||||
didEndWithError:(NSError*)error {
|
|
||||||
appRunning_ = NO;
|
|
||||||
// Wait for the output thread to finish copying data to stdout.
|
|
||||||
if (outputThread_) {
|
|
||||||
while (![outputThread_ isFinished]) {
|
|
||||||
[NSThread sleepForTimeInterval:kOutputPollIntervalSeconds];
|
|
||||||
}
|
|
||||||
[outputThread_ release];
|
|
||||||
outputThread_ = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
// There appears to be a race condition where sometimes the simulator
|
|
||||||
// framework will end with an error, but the error is that the simulated
|
|
||||||
// app cleanly shut down; try to trap this error and don't fail the
|
|
||||||
// simulator run.
|
|
||||||
NSString* localizedDescription = [error localizedDescription];
|
|
||||||
NSString* ignorableErrorStr =
|
|
||||||
[self localizedSimulatorErrorString:kSimulatorAppQuitErrorKey];
|
|
||||||
if ([ignorableErrorStr isEqual:localizedDescription]) {
|
|
||||||
LogWarning(@"Ignoring that Simulator ended with: \"%@\" (%@:%ld)",
|
|
||||||
localizedDescription, [error domain],
|
|
||||||
static_cast<long int>([error code]));
|
|
||||||
} else {
|
|
||||||
LogError(@"Simulator ended with error: \"%@\" (%@:%ld)",
|
|
||||||
localizedDescription, [error domain],
|
|
||||||
static_cast<long int>([error code]));
|
|
||||||
exit(kExitFailure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the simulated app exited abnormally by looking for system log
|
|
||||||
// messages from launchd that refer to the simulated app's PID. Limit query
|
|
||||||
// to messages in the last minute since PIDs are cyclical.
|
|
||||||
aslmsg query = asl_new(ASL_TYPE_QUERY);
|
|
||||||
asl_set_query(query, ASL_KEY_SENDER, "launchd",
|
|
||||||
ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_SUBSTRING);
|
|
||||||
asl_set_query(query, ASL_KEY_REF_PID,
|
|
||||||
[[[session simulatedApplicationPID] stringValue] UTF8String],
|
|
||||||
ASL_QUERY_OP_EQUAL);
|
|
||||||
asl_set_query(query, ASL_KEY_TIME, "-1m", ASL_QUERY_OP_GREATER_EQUAL);
|
|
||||||
|
|
||||||
// Log any messages found, and take note of any messages that may indicate the
|
|
||||||
// app crashed or did not exit cleanly.
|
|
||||||
aslresponse response = asl_search(NULL, query);
|
|
||||||
BOOL badEntryFound = NO;
|
|
||||||
aslmsg entry;
|
|
||||||
while ((entry = aslresponse_next(response)) != NULL) {
|
|
||||||
const char* message = asl_get(entry, ASL_KEY_MSG);
|
|
||||||
LogWarning(@"Console message: %s", message);
|
|
||||||
// Some messages are harmless, so don't trigger a failure for them.
|
|
||||||
if (strstr(message, "The following job tried to hijack the service"))
|
|
||||||
continue;
|
|
||||||
badEntryFound = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the query returned any nasty-looking results, iossim should exit with
|
|
||||||
// non-zero status.
|
|
||||||
if (badEntryFound) {
|
|
||||||
LogError(@"Simulated app crashed or exited with non-zero status");
|
|
||||||
exit(kExitAppCrashed);
|
|
||||||
}
|
|
||||||
exit(kExitSuccess);
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// Finds the developer dir via xcode-select or the DEVELOPER_DIR environment
|
|
||||||
// variable.
|
|
||||||
NSString* FindDeveloperDir() {
|
|
||||||
// Check the env first.
|
|
||||||
NSDictionary* env = [[NSProcessInfo processInfo] environment];
|
|
||||||
NSString* developerDir = [env objectForKey:@"DEVELOPER_DIR"];
|
|
||||||
if ([developerDir length] > 0)
|
|
||||||
return developerDir;
|
|
||||||
|
|
||||||
// Go look for it via xcode-select.
|
|
||||||
NSTask* xcodeSelectTask = [[[NSTask alloc] init] autorelease];
|
|
||||||
[xcodeSelectTask setLaunchPath:@"/usr/bin/xcode-select"];
|
|
||||||
[xcodeSelectTask setArguments:[NSArray arrayWithObject:@"-print-path"]];
|
|
||||||
|
|
||||||
NSPipe* outputPipe = [NSPipe pipe];
|
|
||||||
[xcodeSelectTask setStandardOutput:outputPipe];
|
|
||||||
NSFileHandle* outputFile = [outputPipe fileHandleForReading];
|
|
||||||
|
|
||||||
[xcodeSelectTask launch];
|
|
||||||
NSData* outputData = [outputFile readDataToEndOfFile];
|
|
||||||
[xcodeSelectTask terminate];
|
|
||||||
|
|
||||||
NSString* output =
|
|
||||||
[[[NSString alloc] initWithData:outputData
|
|
||||||
encoding:NSUTF8StringEncoding] autorelease];
|
|
||||||
output = [output stringByTrimmingCharactersInSet:
|
|
||||||
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
||||||
if ([output length] == 0)
|
|
||||||
output = nil;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loads the Simulator framework from the given developer dir.
|
|
||||||
NSBundle* LoadSimulatorFramework(NSString* developerDir) {
|
|
||||||
// The Simulator framework depends on some of the other Xcode private
|
|
||||||
// frameworks; manually load them first so everything can be linked up.
|
|
||||||
NSString* devToolsFoundationPath = [developerDir
|
|
||||||
stringByAppendingPathComponent:kDevToolsFoundationRelativePath];
|
|
||||||
NSBundle* devToolsFoundationBundle =
|
|
||||||
[NSBundle bundleWithPath:devToolsFoundationPath];
|
|
||||||
if (![devToolsFoundationBundle load])
|
|
||||||
return nil;
|
|
||||||
NSString* simBundlePath = [developerDir
|
|
||||||
stringByAppendingPathComponent:kSimulatorFrameworkRelativePath];
|
|
||||||
NSBundle* simBundle = [NSBundle bundleWithPath:simBundlePath];
|
|
||||||
if (![simBundle load])
|
|
||||||
return nil;
|
|
||||||
return simBundle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper to find a class by name and die if it isn't found.
|
|
||||||
Class FindClassByName(NSString* nameOfClass) {
|
|
||||||
Class theClass = NSClassFromString(nameOfClass);
|
|
||||||
if (!theClass) {
|
|
||||||
LogError(@"Failed to find class %@ at runtime.", nameOfClass);
|
|
||||||
exit(kExitInitializationFailure);
|
|
||||||
}
|
|
||||||
return theClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts the given app path to an application spec, which requires an
|
|
||||||
// absolute path.
|
|
||||||
DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) {
|
|
||||||
Class applicationSpecifierClass =
|
|
||||||
FindClassByName(@"DTiPhoneSimulatorApplicationSpecifier");
|
|
||||||
if (![appPath isAbsolutePath]) {
|
|
||||||
NSString* cwd = [[NSFileManager defaultManager] currentDirectoryPath];
|
|
||||||
appPath = [cwd stringByAppendingPathComponent:appPath];
|
|
||||||
}
|
|
||||||
appPath = [appPath stringByStandardizingPath];
|
|
||||||
return [applicationSpecifierClass specifierWithApplicationPath:appPath];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the system root for the given SDK version. If sdkVersion is nil, the
|
|
||||||
// default system root is returned. Will return nil if the sdkVersion is not
|
|
||||||
// valid.
|
|
||||||
DTiPhoneSimulatorSystemRoot* BuildSystemRoot(NSString* sdkVersion) {
|
|
||||||
Class systemRootClass = FindClassByName(@"DTiPhoneSimulatorSystemRoot");
|
|
||||||
DTiPhoneSimulatorSystemRoot* systemRoot = [systemRootClass defaultRoot];
|
|
||||||
if (sdkVersion)
|
|
||||||
systemRoot = [systemRootClass rootWithSDKVersion:sdkVersion];
|
|
||||||
|
|
||||||
return systemRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Builds a config object for starting the specified app.
|
|
||||||
DTiPhoneSimulatorSessionConfig* BuildSessionConfig(
|
|
||||||
DTiPhoneSimulatorApplicationSpecifier* appSpec,
|
|
||||||
DTiPhoneSimulatorSystemRoot* systemRoot,
|
|
||||||
NSString* stdoutPath,
|
|
||||||
NSString* stderrPath,
|
|
||||||
NSArray* appArgs,
|
|
||||||
NSDictionary* appEnv,
|
|
||||||
NSNumber* deviceFamily) {
|
|
||||||
Class sessionConfigClass = FindClassByName(@"DTiPhoneSimulatorSessionConfig");
|
|
||||||
DTiPhoneSimulatorSessionConfig* sessionConfig =
|
|
||||||
[[[sessionConfigClass alloc] init] autorelease];
|
|
||||||
sessionConfig.applicationToSimulateOnStart = appSpec;
|
|
||||||
sessionConfig.simulatedSystemRoot = systemRoot;
|
|
||||||
sessionConfig.localizedClientName = @"chromium";
|
|
||||||
sessionConfig.simulatedApplicationStdErrPath = stderrPath;
|
|
||||||
sessionConfig.simulatedApplicationStdOutPath = stdoutPath;
|
|
||||||
sessionConfig.simulatedApplicationLaunchArgs = appArgs;
|
|
||||||
sessionConfig.simulatedApplicationLaunchEnvironment = appEnv;
|
|
||||||
sessionConfig.simulatedDeviceFamily = deviceFamily;
|
|
||||||
return sessionConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Builds a simulator session that will use the given delegate.
|
|
||||||
DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) {
|
|
||||||
Class sessionClass = FindClassByName(@"DTiPhoneSimulatorSession");
|
|
||||||
DTiPhoneSimulatorSession* session =
|
|
||||||
[[[sessionClass alloc] init] autorelease];
|
|
||||||
session.delegate = delegate;
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a temporary directory with a unique name based on the provided
|
|
||||||
// template. The template should not contain any path separators and be suffixed
|
|
||||||
// with X's, which will be substituted with a unique alphanumeric string (see
|
|
||||||
// 'man mkdtemp' for details). The directory will be created as a subdirectory
|
|
||||||
// of NSTemporaryDirectory(). For example, if dirNameTemplate is 'test-XXX',
|
|
||||||
// this method would return something like '/path/to/tempdir/test-3n2'.
|
|
||||||
//
|
|
||||||
// Returns the absolute path of the newly-created directory, or nill if unable
|
|
||||||
// to create a unique directory.
|
|
||||||
NSString* CreateTempDirectory(NSString* dirNameTemplate) {
|
|
||||||
NSString* fullPathTemplate =
|
|
||||||
[NSTemporaryDirectory() stringByAppendingPathComponent:dirNameTemplate];
|
|
||||||
char* fullPath = mkdtemp(const_cast<char*>([fullPathTemplate UTF8String]));
|
|
||||||
if (fullPath == NULL)
|
|
||||||
return nil;
|
|
||||||
|
|
||||||
return [NSString stringWithUTF8String:fullPath];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates the necessary directory structure under the given user home directory
|
|
||||||
// path.
|
|
||||||
// Returns YES if successful, NO if unable to create the directories.
|
|
||||||
BOOL CreateHomeDirSubDirs(NSString* userHomePath) {
|
|
||||||
NSFileManager* fileManager = [NSFileManager defaultManager];
|
|
||||||
|
|
||||||
// Create user home and subdirectories.
|
|
||||||
NSArray* subDirsToCreate = [NSArray arrayWithObjects:
|
|
||||||
@"Documents",
|
|
||||||
@"Library/Caches",
|
|
||||||
@"Library/Preferences",
|
|
||||||
nil];
|
|
||||||
for (NSString* subDir in subDirsToCreate) {
|
|
||||||
NSString* path = [userHomePath stringByAppendingPathComponent:subDir];
|
|
||||||
NSError* error;
|
|
||||||
if (![fileManager createDirectoryAtPath:path
|
|
||||||
withIntermediateDirectories:YES
|
|
||||||
attributes:nil
|
|
||||||
error:&error]) {
|
|
||||||
LogError(@"Unable to create directory: %@. Error: %@",
|
|
||||||
path, [error localizedDescription]);
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates the necessary directory structure under the given user home directory
|
|
||||||
// path, then sets the path in the appropriate environment variable.
|
|
||||||
// Returns YES if successful, NO if unable to create or initialize the given
|
|
||||||
// directory.
|
|
||||||
BOOL InitializeSimulatorUserHome(NSString* userHomePath, NSString* deviceName) {
|
|
||||||
if (!CreateHomeDirSubDirs(userHomePath))
|
|
||||||
return NO;
|
|
||||||
|
|
||||||
// Set the device to simulate. Note that the iOS Simulator must not be running
|
|
||||||
// for this setting to take effect.
|
|
||||||
CFStringRef iPhoneSimulatorAppID = CFSTR("com.apple.iphonesimulator");
|
|
||||||
CFPreferencesSetAppValue(CFSTR("SimulateDevice"),
|
|
||||||
deviceName,
|
|
||||||
iPhoneSimulatorAppID);
|
|
||||||
CFPreferencesAppSynchronize(iPhoneSimulatorAppID);
|
|
||||||
|
|
||||||
// Update the environment to use the specified directory as the user home
|
|
||||||
// directory.
|
|
||||||
// Note: the third param of setenv specifies whether or not to overwrite the
|
|
||||||
// variable's value if it has already been set.
|
|
||||||
if ((setenv(kUserHomeEnvVariable, [userHomePath UTF8String], YES) == -1) ||
|
|
||||||
(setenv(kHomeEnvVariable, [userHomePath UTF8String], YES) == -1)) {
|
|
||||||
LogError(@"Unable to set environment variables for home directory.");
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Performs a case-insensitive search to see if |stringToSearch| begins with
|
|
||||||
// |prefixToFind|. Returns true if a match is found.
|
|
||||||
BOOL CaseInsensitivePrefixSearch(NSString* stringToSearch,
|
|
||||||
NSString* prefixToFind) {
|
|
||||||
NSStringCompareOptions options = (NSAnchoredSearch | NSCaseInsensitiveSearch);
|
|
||||||
NSRange range = [stringToSearch rangeOfString:prefixToFind
|
|
||||||
options:options];
|
|
||||||
return range.location != NSNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prints the usage information to stderr.
|
|
||||||
void PrintUsage() {
|
|
||||||
fprintf(stderr, "Usage: iossim [-d device] [-s sdkVersion] [-u homeDir] "
|
|
||||||
"[-e envKey=value]* [-t startupTimeout] <appPath> [<appArgs>]\n"
|
|
||||||
" where <appPath> is the path to the .app directory and appArgs are any"
|
|
||||||
" arguments to send the simulated app.\n"
|
|
||||||
"\n"
|
|
||||||
"Options:\n"
|
|
||||||
" -d Specifies the device (must be one of the values from the iOS"
|
|
||||||
" Simulator's Hardware -> Device menu. Defaults to 'iPhone'.\n"
|
|
||||||
" -s Specifies the SDK version to use (e.g '4.3')."
|
|
||||||
" Will use system default if not specified.\n"
|
|
||||||
" -u Specifies a user home directory for the simulator."
|
|
||||||
" Will create a new directory if not specified.\n"
|
|
||||||
" -e Specifies an environment key=value pair that will be"
|
|
||||||
" set in the simulated application's environment.\n"
|
|
||||||
" -t Specifies the session startup timeout (in seconds)."
|
|
||||||
" Defaults to %d.\n",
|
|
||||||
static_cast<int>(kDefaultSessionStartTimeoutSeconds));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
int main(int argc, char* const argv[]) {
|
|
||||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
|
|
||||||
// basename() may modify the passed in string and it returns a pointer to an
|
|
||||||
// internal buffer. Give it a copy to modify, and copy what it returns.
|
|
||||||
char* worker = strdup(argv[0]);
|
|
||||||
char* toolName = basename(worker);
|
|
||||||
if (toolName != NULL) {
|
|
||||||
toolName = strdup(toolName);
|
|
||||||
if (toolName != NULL)
|
|
||||||
gToolName = toolName;
|
|
||||||
}
|
|
||||||
if (worker != NULL)
|
|
||||||
free(worker);
|
|
||||||
|
|
||||||
NSString* appPath = nil;
|
|
||||||
NSString* appName = nil;
|
|
||||||
NSString* sdkVersion = nil;
|
|
||||||
NSString* deviceName = @"iPhone";
|
|
||||||
NSString* simHomePath = nil;
|
|
||||||
NSMutableArray* appArgs = [NSMutableArray array];
|
|
||||||
NSMutableDictionary* appEnv = [NSMutableDictionary dictionary];
|
|
||||||
NSTimeInterval sessionStartTimeout = kDefaultSessionStartTimeoutSeconds;
|
|
||||||
|
|
||||||
// Parse the optional arguments
|
|
||||||
int c;
|
|
||||||
while ((c = getopt(argc, argv, "hs:d:u:e:t:")) != -1) {
|
|
||||||
switch (c) {
|
|
||||||
case 's':
|
|
||||||
sdkVersion = [NSString stringWithUTF8String:optarg];
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
deviceName = [NSString stringWithUTF8String:optarg];
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
simHomePath = [[NSFileManager defaultManager]
|
|
||||||
stringWithFileSystemRepresentation:optarg length:strlen(optarg)];
|
|
||||||
break;
|
|
||||||
case 'e': {
|
|
||||||
NSString* envLine = [NSString stringWithUTF8String:optarg];
|
|
||||||
NSRange range = [envLine rangeOfString:@"="];
|
|
||||||
if (range.location == NSNotFound) {
|
|
||||||
LogError(@"Invalid key=value argument for -e.");
|
|
||||||
PrintUsage();
|
|
||||||
exit(kExitInvalidArguments);
|
|
||||||
}
|
|
||||||
NSString* key = [envLine substringToIndex:range.location];
|
|
||||||
NSString* value = [envLine substringFromIndex:(range.location + 1)];
|
|
||||||
[appEnv setObject:value forKey:key];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 't': {
|
|
||||||
int timeout = atoi(optarg);
|
|
||||||
if (timeout > 0) {
|
|
||||||
sessionStartTimeout = static_cast<NSTimeInterval>(timeout);
|
|
||||||
} else {
|
|
||||||
LogError(@"Invalid startup timeout (%s).", optarg);
|
|
||||||
PrintUsage();
|
|
||||||
exit(kExitInvalidArguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
PrintUsage();
|
|
||||||
exit(kExitSuccess);
|
|
||||||
default:
|
|
||||||
PrintUsage();
|
|
||||||
exit(kExitInvalidArguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// There should be at least one arg left, specifying the app path. Any
|
|
||||||
// additional args are passed as arguments to the app.
|
|
||||||
if (optind < argc) {
|
|
||||||
appPath = [[NSFileManager defaultManager]
|
|
||||||
stringWithFileSystemRepresentation:argv[optind]
|
|
||||||
length:strlen(argv[optind])];
|
|
||||||
appName = [appPath lastPathComponent];
|
|
||||||
while (++optind < argc) {
|
|
||||||
[appArgs addObject:[NSString stringWithUTF8String:argv[optind]]];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LogError(@"Unable to parse command line arguments.");
|
|
||||||
PrintUsage();
|
|
||||||
exit(kExitInvalidArguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
NSString* developerDir = FindDeveloperDir();
|
|
||||||
if (!developerDir) {
|
|
||||||
LogError(@"Unable to find developer directory.");
|
|
||||||
exit(kExitInitializationFailure);
|
|
||||||
}
|
|
||||||
|
|
||||||
NSBundle* simulatorFramework = LoadSimulatorFramework(developerDir);
|
|
||||||
if (!simulatorFramework) {
|
|
||||||
LogError(@"Failed to load the Simulator Framework.");
|
|
||||||
exit(kExitInitializationFailure);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the app path provided is legit.
|
|
||||||
DTiPhoneSimulatorApplicationSpecifier* appSpec = BuildAppSpec(appPath);
|
|
||||||
if (!appSpec) {
|
|
||||||
LogError(@"Invalid app path: %@", appPath);
|
|
||||||
exit(kExitInitializationFailure);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the SDK path provided is legit (or nil).
|
|
||||||
DTiPhoneSimulatorSystemRoot* systemRoot = BuildSystemRoot(sdkVersion);
|
|
||||||
if (!systemRoot) {
|
|
||||||
LogError(@"Invalid SDK version: %@", sdkVersion);
|
|
||||||
exit(kExitInitializationFailure);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the paths for stdout and stderr so the simulated app's output will show
|
|
||||||
// up in the caller's stdout/stderr.
|
|
||||||
NSString* outputDir = CreateTempDirectory(@"iossim-XXXXXX");
|
|
||||||
NSString* stdioPath = [outputDir stringByAppendingPathComponent:@"stdio.txt"];
|
|
||||||
|
|
||||||
// Determine the deviceFamily based on the deviceName
|
|
||||||
NSNumber* deviceFamily = nil;
|
|
||||||
if (!deviceName || CaseInsensitivePrefixSearch(deviceName, @"iPhone")) {
|
|
||||||
deviceFamily = [NSNumber numberWithInt:kIPhoneFamily];
|
|
||||||
} else if (CaseInsensitivePrefixSearch(deviceName, @"iPad")) {
|
|
||||||
deviceFamily = [NSNumber numberWithInt:kIPadFamily];
|
|
||||||
} else {
|
|
||||||
LogError(@"Invalid device name: %@. Must begin with 'iPhone' or 'iPad'",
|
|
||||||
deviceName);
|
|
||||||
exit(kExitInvalidArguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up the user home directory for the simulator
|
|
||||||
if (!simHomePath) {
|
|
||||||
NSString* dirNameTemplate =
|
|
||||||
[NSString stringWithFormat:@"iossim-%@-%@-XXXXXX", appName, deviceName];
|
|
||||||
simHomePath = CreateTempDirectory(dirNameTemplate);
|
|
||||||
if (!simHomePath) {
|
|
||||||
LogError(@"Unable to create unique directory for template %@",
|
|
||||||
dirNameTemplate);
|
|
||||||
exit(kExitInitializationFailure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!InitializeSimulatorUserHome(simHomePath, deviceName)) {
|
|
||||||
LogError(@"Unable to initialize home directory for simulator: %@",
|
|
||||||
simHomePath);
|
|
||||||
exit(kExitInitializationFailure);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the config and simulator session.
|
|
||||||
DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec,
|
|
||||||
systemRoot,
|
|
||||||
stdioPath,
|
|
||||||
stdioPath,
|
|
||||||
appArgs,
|
|
||||||
appEnv,
|
|
||||||
deviceFamily);
|
|
||||||
SimulatorDelegate* delegate =
|
|
||||||
[[[SimulatorDelegate alloc] initWithStdioPath:stdioPath
|
|
||||||
developerDir:developerDir] autorelease];
|
|
||||||
DTiPhoneSimulatorSession* session = BuildSession(delegate);
|
|
||||||
|
|
||||||
// Start the simulator session.
|
|
||||||
NSError* error;
|
|
||||||
BOOL started = [session requestStartWithConfig:config
|
|
||||||
timeout:sessionStartTimeout
|
|
||||||
error:&error];
|
|
||||||
|
|
||||||
// Spin the runtime indefinitely. When the delegate gets the message that the
|
|
||||||
// app has quit it will exit this program.
|
|
||||||
if (started) {
|
|
||||||
[[NSRunLoop mainRunLoop] run];
|
|
||||||
} else {
|
|
||||||
LogError(@"Simulator failed request to start: \"%@\" (%@:%ld)",
|
|
||||||
[error localizedDescription],
|
|
||||||
[error domain], static_cast<long int>([error code]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that this code is only executed if the simulator fails to start
|
|
||||||
// because once the main run loop is started, only the delegate calling
|
|
||||||
// exit() will end the program.
|
|
||||||
[pool drain];
|
|
||||||
return kExitFailure;
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
#
|
|
||||||
# This script executes the command given as the first argument and redirects
|
|
||||||
# the command's stdout to the file given as the second argument.
|
|
||||||
#
|
|
||||||
# Example: Write the text 'foo' to a file called out.txt:
|
|
||||||
# RedirectStdout.sh "echo foo" out.txt
|
|
||||||
#
|
|
||||||
# This script is invoked from iossim.gyp in order to redirect the output of
|
|
||||||
# class-dump to a file (because gyp actions don't support redirecting output).
|
|
||||||
|
|
||||||
if [ ${#} -ne 2 ] ; then
|
|
||||||
echo "usage: ${0} <command> <output file>"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec $1 > $2
|
|
|
@ -1,57 +0,0 @@
|
||||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "multiprocess_func_list.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
// Helper functions to maintain mapping of "test name"->test func.
|
|
||||||
// The information is accessed via a global map.
|
|
||||||
namespace multi_process_function_list {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
struct ProcessFunctions {
|
|
||||||
ProcessFunctions() : main(NULL), setup(NULL) {}
|
|
||||||
ProcessFunctions(TestMainFunctionPtr main, SetupFunctionPtr setup)
|
|
||||||
: main(main),
|
|
||||||
setup(setup) {
|
|
||||||
}
|
|
||||||
TestMainFunctionPtr main;
|
|
||||||
SetupFunctionPtr setup;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::map<std::string, ProcessFunctions> MultiProcessTestMap;
|
|
||||||
|
|
||||||
// Retrieve a reference to the global 'func name' -> func ptr map.
|
|
||||||
MultiProcessTestMap& GetMultiprocessFuncMap() {
|
|
||||||
static MultiProcessTestMap test_name_to_func_ptr_map;
|
|
||||||
return test_name_to_func_ptr_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
AppendMultiProcessTest::AppendMultiProcessTest(
|
|
||||||
std::string test_name,
|
|
||||||
TestMainFunctionPtr main_func_ptr,
|
|
||||||
SetupFunctionPtr setup_func_ptr) {
|
|
||||||
GetMultiprocessFuncMap()[test_name] =
|
|
||||||
ProcessFunctions(main_func_ptr, setup_func_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int InvokeChildProcessTest(std::string test_name) {
|
|
||||||
MultiProcessTestMap& func_lookup_table = GetMultiprocessFuncMap();
|
|
||||||
MultiProcessTestMap::iterator it = func_lookup_table.find(test_name);
|
|
||||||
if (it != func_lookup_table.end()) {
|
|
||||||
const ProcessFunctions& process_functions = it->second;
|
|
||||||
if (process_functions.setup)
|
|
||||||
(*process_functions.setup)();
|
|
||||||
if (process_functions.main)
|
|
||||||
return (*process_functions.main)();
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace multi_process_function_list
|
|
|
@ -1,70 +0,0 @@
|
||||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef TESTING_MULTIPROCESS_FUNC_LIST_H_
|
|
||||||
#define TESTING_MULTIPROCESS_FUNC_LIST_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// This file provides the plumbing to register functions to be executed
|
|
||||||
// as the main function of a child process in a multi-process test.
|
|
||||||
// This complements the MultiProcessTest class which provides facilities
|
|
||||||
// for launching such tests.
|
|
||||||
//
|
|
||||||
// The MULTIPROCESS_TEST_MAIN() macro registers a string -> func_ptr mapping
|
|
||||||
// by creating a new global instance of the AppendMultiProcessTest() class
|
|
||||||
// this means that by the time that we reach our main() function the mapping
|
|
||||||
// is already in place.
|
|
||||||
//
|
|
||||||
// Example usage:
|
|
||||||
// MULTIPROCESS_TEST_MAIN(a_test_func) {
|
|
||||||
// // Code here runs in a child process.
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// The prototype of a_test_func is implicitly
|
|
||||||
// int test_main_func_name();
|
|
||||||
|
|
||||||
namespace multi_process_function_list {
|
|
||||||
|
|
||||||
// Type for child process main functions.
|
|
||||||
typedef int (*TestMainFunctionPtr)();
|
|
||||||
|
|
||||||
// Type for child setup functions.
|
|
||||||
typedef void (*SetupFunctionPtr)();
|
|
||||||
|
|
||||||
// Helper class to append a test function to the global mapping.
|
|
||||||
// Used by the MULTIPROCESS_TEST_MAIN macro.
|
|
||||||
class AppendMultiProcessTest {
|
|
||||||
public:
|
|
||||||
// |main_func_ptr| is the main function that is run in the child process.
|
|
||||||
// |setup_func_ptr| is a function run when the global mapping is added.
|
|
||||||
AppendMultiProcessTest(std::string test_name,
|
|
||||||
TestMainFunctionPtr main_func_ptr,
|
|
||||||
SetupFunctionPtr setup_func_ptr);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invoke the main function of a test previously registered with
|
|
||||||
// MULTIPROCESS_TEST_MAIN()
|
|
||||||
int InvokeChildProcessTest(std::string test_name);
|
|
||||||
|
|
||||||
// This macro creates a global MultiProcessTest::AppendMultiProcessTest object
|
|
||||||
// whose constructor does the work of adding the global mapping.
|
|
||||||
#define MULTIPROCESS_TEST_MAIN(test_main) \
|
|
||||||
MULTIPROCESS_TEST_MAIN_WITH_SETUP(test_main, NULL)
|
|
||||||
|
|
||||||
// Same as above but lets callers specify a setup method that is run in the
|
|
||||||
// child process, just before the main function is run. This facilitates
|
|
||||||
// adding a generic one-time setup function for multiple tests.
|
|
||||||
#define MULTIPROCESS_TEST_MAIN_WITH_SETUP(test_main, test_setup) \
|
|
||||||
int test_main(); \
|
|
||||||
namespace { \
|
|
||||||
multi_process_function_list::AppendMultiProcessTest \
|
|
||||||
AddMultiProcessTest##_##test_main(#test_main, (test_main), (test_setup)); \
|
|
||||||
} \
|
|
||||||
int test_main()
|
|
||||||
|
|
||||||
} // namespace multi_process_function_list
|
|
||||||
|
|
||||||
#endif // TESTING_MULTIPROCESS_FUNC_LIST_H_
|
|
|
@ -1,36 +0,0 @@
|
||||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef TESTING_PLATFORM_TEST_H_
|
|
||||||
#define TESTING_PLATFORM_TEST_H_
|
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#if defined(GTEST_OS_MAC)
|
|
||||||
#ifdef __OBJC__
|
|
||||||
@class NSAutoreleasePool;
|
|
||||||
#else
|
|
||||||
class NSAutoreleasePool;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The purpose of this class us to provide a hook for platform-specific
|
|
||||||
// operations across unit tests. For example, on the Mac, it creates and
|
|
||||||
// releases an outer NSAutoreleasePool for each test case. For now, it's only
|
|
||||||
// implemented on the Mac. To enable this for another platform, just adjust
|
|
||||||
// the #ifdefs and add a platform_test_<platform>.cc implementation file.
|
|
||||||
class PlatformTest : public testing::Test {
|
|
||||||
public:
|
|
||||||
virtual ~PlatformTest();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
PlatformTest();
|
|
||||||
|
|
||||||
private:
|
|
||||||
NSAutoreleasePool* pool_;
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
typedef testing::Test PlatformTest;
|
|
||||||
#endif // GTEST_OS_MAC
|
|
||||||
|
|
||||||
#endif // TESTING_PLATFORM_TEST_H_
|
|
|
@ -1,15 +0,0 @@
|
||||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "platform_test.h"
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
PlatformTest::PlatformTest()
|
|
||||||
: pool_([[NSAutoreleasePool alloc] init]) {
|
|
||||||
}
|
|
||||||
|
|
||||||
PlatformTest::~PlatformTest() {
|
|
||||||
[pool_ release];
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
|
|
||||||
"""Sets environment variables needed to run a chromium unit test."""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import stat
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# This is hardcoded to be src/ relative to this script.
|
|
||||||
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
|
|
||||||
CHROME_SANDBOX_ENV = 'CHROME_DEVEL_SANDBOX'
|
|
||||||
CHROME_SANDBOX_PATH = '/opt/chromium/chrome_sandbox'
|
|
||||||
|
|
||||||
|
|
||||||
def should_enable_sandbox(sandbox_path):
|
|
||||||
"""Return a boolean indicating that the current slave is capable of using the
|
|
||||||
sandbox and should enable it. This should return True iff the slave is a
|
|
||||||
Linux host with the sandbox file present and configured correctly."""
|
|
||||||
if not (sys.platform.startswith('linux') and
|
|
||||||
os.path.exists(sandbox_path)):
|
|
||||||
return False
|
|
||||||
sandbox_stat = os.stat(sandbox_path)
|
|
||||||
if ((sandbox_stat.st_mode & stat.S_ISUID) and
|
|
||||||
(sandbox_stat.st_mode & stat.S_IRUSR) and
|
|
||||||
(sandbox_stat.st_mode & stat.S_IXUSR) and
|
|
||||||
(sandbox_stat.st_uid == 0)):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def enable_sandbox_if_required(env, verbose=False):
|
|
||||||
"""Checks enables the sandbox if it is required, otherwise it disables it."""
|
|
||||||
chrome_sandbox_path = env.get(CHROME_SANDBOX_ENV, CHROME_SANDBOX_PATH)
|
|
||||||
|
|
||||||
if should_enable_sandbox(chrome_sandbox_path):
|
|
||||||
if verbose:
|
|
||||||
print 'Enabling sandbox. Setting environment variable:'
|
|
||||||
print ' %s="%s"' % (CHROME_SANDBOX_ENV, chrome_sandbox_path)
|
|
||||||
env[CHROME_SANDBOX_ENV] = chrome_sandbox_path
|
|
||||||
else:
|
|
||||||
if verbose:
|
|
||||||
print 'Sandbox not properly installed. Unsetting:'
|
|
||||||
print ' %s' % CHROME_SANDBOX_ENV
|
|
||||||
# The variable should be removed from the environment, making
|
|
||||||
# the variable empty silently disables the sandbox.
|
|
||||||
if env.get(CHROME_SANDBOX_ENV):
|
|
||||||
env.pop(CHROME_SANDBOX_ENV)
|
|
||||||
|
|
||||||
|
|
||||||
def fix_python_path(cmd):
|
|
||||||
"""Returns the fixed command line to call the right python executable."""
|
|
||||||
out = cmd[:]
|
|
||||||
if out[0] == 'python':
|
|
||||||
out[0] = sys.executable
|
|
||||||
elif out[0].endswith('.py'):
|
|
||||||
out.insert(0, sys.executable)
|
|
||||||
return out
|
|
||||||
|
|
||||||
|
|
||||||
def run_executable(cmd, env):
|
|
||||||
"""Runs an executable with:
|
|
||||||
- environment variable CR_SOURCE_ROOT set to the root directory.
|
|
||||||
- environment variable LANGUAGE to en_US.UTF-8.
|
|
||||||
- environment variable CHROME_DEVEL_SANDBOX set if need
|
|
||||||
- Reuses sys.executable automatically.
|
|
||||||
"""
|
|
||||||
# Many tests assume a English interface...
|
|
||||||
env['LANG'] = 'en_US.UTF-8'
|
|
||||||
# Used by base/base_paths_linux.cc as an override. Just make sure the default
|
|
||||||
# logic is used.
|
|
||||||
env.pop('CR_SOURCE_ROOT', None)
|
|
||||||
enable_sandbox_if_required(env)
|
|
||||||
# Ensure paths are correctly separated on windows.
|
|
||||||
cmd[0] = cmd[0].replace('/', os.path.sep)
|
|
||||||
cmd = fix_python_path(cmd)
|
|
||||||
try:
|
|
||||||
return subprocess.call(cmd, env=env)
|
|
||||||
except OSError:
|
|
||||||
print >> sys.stderr, 'Failed to start %s' % cmd
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
return run_executable(sys.argv[1:], os.environ.copy())
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
133
testing/xvfb.py
133
testing/xvfb.py
|
@ -1,133 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
|
|
||||||
"""Runs the test with xvfb on linux. Runs the test normally on other platforms.
|
|
||||||
|
|
||||||
For simplicity in gyp targets, this script just runs the test normal on
|
|
||||||
non-linux platforms.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import platform
|
|
||||||
import signal
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import test_env
|
|
||||||
|
|
||||||
|
|
||||||
def kill(pid):
|
|
||||||
"""Kills a process and traps exception if the process doesn't exist anymore.
|
|
||||||
"""
|
|
||||||
# If the process doesn't exist, it raises an exception that we can ignore.
|
|
||||||
try:
|
|
||||||
os.kill(pid, signal.SIGKILL)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def get_xvfb_path(server_dir):
|
|
||||||
"""Figures out which X server to use."""
|
|
||||||
xvfb_path = os.path.join(server_dir, 'Xvfb.' + platform.architecture()[0])
|
|
||||||
if not os.path.exists(xvfb_path):
|
|
||||||
xvfb_path = os.path.join(server_dir, 'Xvfb')
|
|
||||||
if not os.path.exists(xvfb_path):
|
|
||||||
print >> sys.stderr, (
|
|
||||||
'No Xvfb found in designated server path: %s' % server_dir)
|
|
||||||
raise Exception('No virtual server')
|
|
||||||
return xvfb_path
|
|
||||||
|
|
||||||
|
|
||||||
def start_xvfb(xvfb_path, display):
|
|
||||||
"""Starts a virtual X server that we run the tests in.
|
|
||||||
|
|
||||||
This makes it so we can run the tests even if we didn't start the tests from
|
|
||||||
an X session.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
xvfb_path: Path to Xvfb.
|
|
||||||
"""
|
|
||||||
cmd = [xvfb_path, display, '-screen', '0', '1024x768x24', '-ac']
|
|
||||||
try:
|
|
||||||
proc = subprocess.Popen(
|
|
||||||
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
||||||
except OSError:
|
|
||||||
print >> sys.stderr, 'Failed to run %s' % ' '.join(cmd)
|
|
||||||
return 0
|
|
||||||
return proc.pid
|
|
||||||
|
|
||||||
|
|
||||||
def wait_for_xvfb(xdisplaycheck, env):
|
|
||||||
"""Waits for xvfb to be fully initialized by using xdisplaycheck."""
|
|
||||||
try:
|
|
||||||
subprocess.check_call(
|
|
||||||
[xdisplaycheck],
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.STDOUT,
|
|
||||||
env=env)
|
|
||||||
except OSError:
|
|
||||||
print >> sys.stderr, 'Failed to load %s with cwd=%s' % (
|
|
||||||
xdisplaycheck, os.getcwd())
|
|
||||||
return False
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
print >> sys.stderr, (
|
|
||||||
'Xvfb failed to load properly while trying to run %s' % xdisplaycheck)
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def run_executable(cmd, build_dir, env):
|
|
||||||
"""Runs an executable within a xvfb buffer on linux or normally on other
|
|
||||||
platforms.
|
|
||||||
|
|
||||||
Requires that both xvfb and icewm are installed on linux.
|
|
||||||
|
|
||||||
Detects recursion with an environment variable and do not create a recursive X
|
|
||||||
buffer if present.
|
|
||||||
"""
|
|
||||||
# First look if we are inside a display.
|
|
||||||
if env.get('_CHROMIUM_INSIDE_XVFB') == '1':
|
|
||||||
# No need to recurse.
|
|
||||||
return test_env.run_executable(cmd, env)
|
|
||||||
|
|
||||||
pid = None
|
|
||||||
xvfb = 'Xvfb'
|
|
||||||
try:
|
|
||||||
if sys.platform == 'linux2':
|
|
||||||
# Defaults to X display 9.
|
|
||||||
display = ':9'
|
|
||||||
pid = start_xvfb(xvfb, display)
|
|
||||||
if not pid:
|
|
||||||
return 1
|
|
||||||
env['DISPLAY'] = display
|
|
||||||
if not wait_for_xvfb(os.path.join(build_dir, 'xdisplaycheck'), env):
|
|
||||||
return 3
|
|
||||||
# Inhibit recursion.
|
|
||||||
env['_CHROMIUM_INSIDE_XVFB'] = '1'
|
|
||||||
# Some ChromeOS tests need a window manager. Technically, it could be
|
|
||||||
# another script but that would be overkill.
|
|
||||||
try:
|
|
||||||
ice_cmd = ['icewm']
|
|
||||||
subprocess.Popen(
|
|
||||||
ice_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
|
|
||||||
except OSError:
|
|
||||||
print >> sys.stderr, 'Failed to run %s' % ' '.join(ice_cmd)
|
|
||||||
return 1
|
|
||||||
return test_env.run_executable(cmd, env)
|
|
||||||
finally:
|
|
||||||
if pid:
|
|
||||||
kill(pid)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if len(sys.argv) < 3:
|
|
||||||
print >> sys.stderr, (
|
|
||||||
'Usage: xvfb.py [path to build_dir] [command args...]')
|
|
||||||
return 2
|
|
||||||
return run_executable(sys.argv[2:], sys.argv[1], os.environ.copy())
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
|
@ -1,28 +0,0 @@
|
||||||
Copyright (c) 2006, Google Inc.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
@ -1,27 +0,0 @@
|
||||||
URL: http://code.google.com/p/gflags/
|
|
||||||
Version: 2.0
|
|
||||||
License: New BSD
|
|
||||||
License File: LICENSE
|
|
||||||
|
|
||||||
Description:
|
|
||||||
The gflags package contains a library that implements commandline
|
|
||||||
flags processing. As such it's a replacement for getopt(). It has
|
|
||||||
increased flexibility, including built-in support for C++ types like
|
|
||||||
string, and the ability to define flags in the source file in which
|
|
||||||
they're used.
|
|
||||||
|
|
||||||
Local Modifications: None
|
|
||||||
|
|
||||||
Refer to README.webrtc on how to update platform configuration files.
|
|
||||||
|
|
||||||
A brief description of the source files:
|
|
||||||
|
|
||||||
README.packager: this file.
|
|
||||||
|
|
||||||
Files under src/:
|
|
||||||
Cloned from https://github.com/schuhschuh/gflags
|
|
||||||
SHA eb92d6edceb2bfde33cb1b6e1c74a432b63017e7.
|
|
||||||
|
|
||||||
All other files:
|
|
||||||
Fetched from webrtc:
|
|
||||||
https://code.google.com/p/webrtc/source/browse/trunk/third_party/gflags r5342.
|
|
|
@ -1,28 +0,0 @@
|
||||||
URL: http://code.google.com/p/gflags/
|
|
||||||
Version: 2.0
|
|
||||||
License: New BSD
|
|
||||||
License File: LICENSE
|
|
||||||
|
|
||||||
Description:
|
|
||||||
The gflags package contains a library that implements commandline
|
|
||||||
flags processing. As such it's a replacement for getopt(). It has
|
|
||||||
increased flexibility, including built-in support for C++ types like
|
|
||||||
string, and the ability to define flags in the source file in which
|
|
||||||
they're used.
|
|
||||||
|
|
||||||
Local Modifications: None
|
|
||||||
|
|
||||||
|
|
||||||
How to update platform configuration files:
|
|
||||||
The gen/ directory contains pre-generated configuration header files.
|
|
||||||
Historically, all operating systems and architectures have generated
|
|
||||||
similar configurations except for Windows. This is why there's only
|
|
||||||
posix and win directories below gen/.
|
|
||||||
When rolling gflags to a newer version, it's a good idea to check if
|
|
||||||
new configuration files needs to be generated as well.
|
|
||||||
Do this by running ./configure in the newly checked out version of
|
|
||||||
gflags. Then diff the generated files with the ones below gen/.
|
|
||||||
If you notice a diff, update the files with the updated ones.
|
|
||||||
If you suspect platform dependend changes other than Windows, you'll
|
|
||||||
have to checkout gflags on the other platforms as well and run
|
|
||||||
./configure there too.
|
|
|
@ -1,592 +0,0 @@
|
||||||
// Copyright (c) 2006, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
// Author: Ray Sidney
|
|
||||||
// Revamped and reorganized by Craig Silverstein
|
|
||||||
//
|
|
||||||
// This is the file that should be included by any file which declares
|
|
||||||
// or defines a command line flag or wants to parse command line flags
|
|
||||||
// or print a program usage message (which will include information about
|
|
||||||
// flags). Executive summary, in the form of an example foo.cc file:
|
|
||||||
//
|
|
||||||
// #include "foo.h" // foo.h has a line "DECLARE_int32(start);"
|
|
||||||
// #include "validators.h" // hypothetical file defining ValidateIsFile()
|
|
||||||
//
|
|
||||||
// DEFINE_int32(end, 1000, "The last record to read");
|
|
||||||
//
|
|
||||||
// DEFINE_string(filename, "my_file.txt", "The file to read");
|
|
||||||
// // Crash if the specified file does not exist.
|
|
||||||
// static bool dummy = RegisterFlagValidator(&FLAGS_filename,
|
|
||||||
// &ValidateIsFile);
|
|
||||||
//
|
|
||||||
// DECLARE_bool(verbose); // some other file has a DEFINE_bool(verbose, ...)
|
|
||||||
//
|
|
||||||
// void MyFunc() {
|
|
||||||
// if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Then, at the command-line:
|
|
||||||
// ./foo --noverbose --start=5 --end=100
|
|
||||||
//
|
|
||||||
// For more details, see
|
|
||||||
// doc/gflags.html
|
|
||||||
//
|
|
||||||
// --- A note about thread-safety:
|
|
||||||
//
|
|
||||||
// We describe many functions in this routine as being thread-hostile,
|
|
||||||
// thread-compatible, or thread-safe. Here are the meanings we use:
|
|
||||||
//
|
|
||||||
// thread-safe: it is safe for multiple threads to call this routine
|
|
||||||
// (or, when referring to a class, methods of this class)
|
|
||||||
// concurrently.
|
|
||||||
// thread-hostile: it is not safe for multiple threads to call this
|
|
||||||
// routine (or methods of this class) concurrently. In gflags,
|
|
||||||
// most thread-hostile routines are intended to be called early in,
|
|
||||||
// or even before, main() -- that is, before threads are spawned.
|
|
||||||
// thread-compatible: it is safe for multiple threads to read from
|
|
||||||
// this variable (when applied to variables), or to call const
|
|
||||||
// methods of this class (when applied to classes), as long as no
|
|
||||||
// other thread is writing to the variable or calling non-const
|
|
||||||
// methods of this class.
|
|
||||||
|
|
||||||
#ifndef GOOGLE_GFLAGS_H_
|
|
||||||
#define GOOGLE_GFLAGS_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
// We care a lot about number of bits things take up. Unfortunately,
|
|
||||||
// systems define their bit-specific ints in a lot of different ways.
|
|
||||||
// We use our own way, and have a typedef to get there.
|
|
||||||
// Note: these commands below may look like "#if 1" or "#if 0", but
|
|
||||||
// that's because they were constructed that way at ./configure time.
|
|
||||||
// Look at gflags.h.in to see how they're calculated (based on your config).
|
|
||||||
#if 1
|
|
||||||
#include <stdint.h> // the normal place uint16_t is defined
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
#include <sys/types.h> // the normal place u_int16_t is defined
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
#include <inttypes.h> // a third place for uint16_t or u_int16_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace google {
|
|
||||||
|
|
||||||
#if 1 // the C99 format
|
|
||||||
typedef int32_t int32;
|
|
||||||
typedef uint32_t uint32;
|
|
||||||
typedef int64_t int64;
|
|
||||||
typedef uint64_t uint64;
|
|
||||||
#elif 1 // the BSD format
|
|
||||||
typedef int32_t int32;
|
|
||||||
typedef u_int32_t uint32;
|
|
||||||
typedef int64_t int64;
|
|
||||||
typedef u_int64_t uint64;
|
|
||||||
#elif 0 // the windows (vc7) format
|
|
||||||
typedef __int32 int32;
|
|
||||||
typedef unsigned __int32 uint32;
|
|
||||||
typedef __int64 int64;
|
|
||||||
typedef unsigned __int64 uint64;
|
|
||||||
#else
|
|
||||||
#error Do not know how to define a 32-bit integer quantity on your system
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO(kjellander): update generated .h's for new gflags.
|
|
||||||
// https://code.google.com/p/webrtc/issues/detail?id=2251
|
|
||||||
extern const char* VersionString();
|
|
||||||
extern void SetVersionString(const std::string& version);
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// To actually define a flag in a file, use DEFINE_bool,
|
|
||||||
// DEFINE_string, etc. at the bottom of this file. You may also find
|
|
||||||
// it useful to register a validator with the flag. This ensures that
|
|
||||||
// when the flag is parsed from the commandline, or is later set via
|
|
||||||
// SetCommandLineOption, we call the validation function. It is _not_
|
|
||||||
// called when you assign the value to the flag directly using the = operator.
|
|
||||||
//
|
|
||||||
// The validation function should return true if the flag value is valid, and
|
|
||||||
// false otherwise. If the function returns false for the new setting of the
|
|
||||||
// flag, the flag will retain its current value. If it returns false for the
|
|
||||||
// default value, ParseCommandLineFlags() will die.
|
|
||||||
//
|
|
||||||
// This function is safe to call at global construct time (as in the
|
|
||||||
// example below).
|
|
||||||
//
|
|
||||||
// Example use:
|
|
||||||
// static bool ValidatePort(const char* flagname, int32 value) {
|
|
||||||
// if (value > 0 && value < 32768) // value is ok
|
|
||||||
// return true;
|
|
||||||
// printf("Invalid value for --%s: %d\n", flagname, (int)value);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// DEFINE_int32(port, 0, "What port to listen on");
|
|
||||||
// static bool dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort);
|
|
||||||
|
|
||||||
// Returns true if successfully registered, false if not (because the
|
|
||||||
// first argument doesn't point to a command-line flag, or because a
|
|
||||||
// validator is already registered for this flag).
|
|
||||||
bool RegisterFlagValidator(const bool* flag,
|
|
||||||
bool (*validate_fn)(const char*, bool));
|
|
||||||
bool RegisterFlagValidator(const int32* flag,
|
|
||||||
bool (*validate_fn)(const char*, int32));
|
|
||||||
bool RegisterFlagValidator(const int64* flag,
|
|
||||||
bool (*validate_fn)(const char*, int64));
|
|
||||||
bool RegisterFlagValidator(const uint64* flag,
|
|
||||||
bool (*validate_fn)(const char*, uint64));
|
|
||||||
bool RegisterFlagValidator(const double* flag,
|
|
||||||
bool (*validate_fn)(const char*, double));
|
|
||||||
bool RegisterFlagValidator(const std::string* flag,
|
|
||||||
bool (*validate_fn)(const char*, const std::string&));
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// These methods are the best way to get access to info about the
|
|
||||||
// list of commandline flags. Note that these routines are pretty slow.
|
|
||||||
// GetAllFlags: mostly-complete info about the list, sorted by file.
|
|
||||||
// ShowUsageWithFlags: pretty-prints the list to stdout (what --help does)
|
|
||||||
// ShowUsageWithFlagsRestrict: limit to filenames with restrict as a substr
|
|
||||||
//
|
|
||||||
// In addition to accessing flags, you can also access argv[0] (the program
|
|
||||||
// name) and argv (the entire commandline), which we sock away a copy of.
|
|
||||||
// These variables are static, so you should only set them once.
|
|
||||||
|
|
||||||
struct CommandLineFlagInfo {
|
|
||||||
std::string name; // the name of the flag
|
|
||||||
std::string type; // the type of the flag: int32, etc
|
|
||||||
std::string description; // the "help text" associated with the flag
|
|
||||||
std::string current_value; // the current value, as a string
|
|
||||||
std::string default_value; // the default value, as a string
|
|
||||||
std::string filename; // 'cleaned' version of filename holding the flag
|
|
||||||
bool has_validator_fn; // true if RegisterFlagValidator called on flag
|
|
||||||
bool is_default; // true if the flag has the default value and
|
|
||||||
// has not been set explicitly from the cmdline
|
|
||||||
// or via SetCommandLineOption
|
|
||||||
const void* flag_ptr;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// Using this inside of a validator is a recipe for a deadlock.
|
|
||||||
// TODO(wojtekm) Fix locking when validators are running, to make it safe to
|
|
||||||
// call validators during ParseAllFlags.
|
|
||||||
// Also make sure then to uncomment the corresponding unit test in
|
|
||||||
// commandlineflags_unittest.sh
|
|
||||||
extern void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
|
|
||||||
// These two are actually defined in commandlineflags_reporting.cc.
|
|
||||||
extern void ShowUsageWithFlags(const char *argv0); // what --help does
|
|
||||||
extern void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
|
|
||||||
|
|
||||||
// Create a descriptive string for a flag.
|
|
||||||
// Goes to some trouble to make pretty line breaks.
|
|
||||||
extern std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
|
|
||||||
|
|
||||||
// Thread-hostile; meant to be called before any threads are spawned.
|
|
||||||
extern void SetArgv(int argc, const char** argv);
|
|
||||||
// The following functions are thread-safe as long as SetArgv() is
|
|
||||||
// only called before any threads start.
|
|
||||||
extern const std::vector<std::string>& GetArgvs(); // all of argv as a vector
|
|
||||||
extern const char* GetArgv(); // all of argv as a string
|
|
||||||
extern const char* GetArgv0(); // only argv0
|
|
||||||
extern uint32 GetArgvSum(); // simple checksum of argv
|
|
||||||
extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
|
|
||||||
extern const char* ProgramInvocationShortName(); // basename(argv0)
|
|
||||||
// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
|
|
||||||
// called before any threads start.
|
|
||||||
extern const char* ProgramUsage(); // string set by SetUsageMessage()
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Normally you access commandline flags by just saying "if (FLAGS_foo)"
|
|
||||||
// or whatever, and set them by calling "FLAGS_foo = bar" (or, more
|
|
||||||
// commonly, via the DEFINE_foo macro). But if you need a bit more
|
|
||||||
// control, we have programmatic ways to get/set the flags as well.
|
|
||||||
// These programmatic ways to access flags are thread-safe, but direct
|
|
||||||
// access is only thread-compatible.
|
|
||||||
|
|
||||||
// Return true iff the flagname was found.
|
|
||||||
// OUTPUT is set to the flag's value, or unchanged if we return false.
|
|
||||||
extern bool GetCommandLineOption(const char* name, std::string* OUTPUT);
|
|
||||||
|
|
||||||
// Return true iff the flagname was found. OUTPUT is set to the flag's
|
|
||||||
// CommandLineFlagInfo or unchanged if we return false.
|
|
||||||
extern bool GetCommandLineFlagInfo(const char* name,
|
|
||||||
CommandLineFlagInfo* OUTPUT);
|
|
||||||
|
|
||||||
// Return the CommandLineFlagInfo of the flagname. exit() if name not found.
|
|
||||||
// Example usage, to check if a flag's value is currently the default value:
|
|
||||||
// if (GetCommandLineFlagInfoOrDie("foo").is_default) ...
|
|
||||||
extern CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
|
|
||||||
|
|
||||||
enum FlagSettingMode {
|
|
||||||
// update the flag's value (can call this multiple times).
|
|
||||||
SET_FLAGS_VALUE,
|
|
||||||
// update the flag's value, but *only if* it has not yet been updated
|
|
||||||
// with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
|
|
||||||
SET_FLAG_IF_DEFAULT,
|
|
||||||
// set the flag's default value to this. If the flag has not yet updated
|
|
||||||
// yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
|
|
||||||
// change the flag's current value to the new default value as well.
|
|
||||||
SET_FLAGS_DEFAULT
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set a particular flag ("command line option"). Returns a string
|
|
||||||
// describing the new value that the option has been set to. The
|
|
||||||
// return value API is not well-specified, so basically just depend on
|
|
||||||
// it to be empty if the setting failed for some reason -- the name is
|
|
||||||
// not a valid flag name, or the value is not a valid value -- and
|
|
||||||
// non-empty else.
|
|
||||||
|
|
||||||
// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
|
|
||||||
extern std::string SetCommandLineOption(const char* name, const char* value);
|
|
||||||
extern std::string SetCommandLineOptionWithMode(const char* name, const char* value,
|
|
||||||
FlagSettingMode set_mode);
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Saves the states (value, default value, whether the user has set
|
|
||||||
// the flag, registered validators, etc) of all flags, and restores
|
|
||||||
// them when the FlagSaver is destroyed. This is very useful in
|
|
||||||
// tests, say, when you want to let your tests change the flags, but
|
|
||||||
// make sure that they get reverted to the original states when your
|
|
||||||
// test is complete.
|
|
||||||
//
|
|
||||||
// Example usage:
|
|
||||||
// void TestFoo() {
|
|
||||||
// FlagSaver s1;
|
|
||||||
// FLAG_foo = false;
|
|
||||||
// FLAG_bar = "some value";
|
|
||||||
//
|
|
||||||
// // test happens here. You can return at any time
|
|
||||||
// // without worrying about restoring the FLAG values.
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Note: This class is marked with __attribute__((unused)) because all the
|
|
||||||
// work is done in the constructor and destructor, so in the standard
|
|
||||||
// usage example above, the compiler would complain that it's an
|
|
||||||
// unused variable.
|
|
||||||
//
|
|
||||||
// This class is thread-safe.
|
|
||||||
|
|
||||||
class FlagSaver {
|
|
||||||
public:
|
|
||||||
FlagSaver();
|
|
||||||
~FlagSaver();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class FlagSaverImpl* impl_; // we use pimpl here to keep API steady
|
|
||||||
|
|
||||||
FlagSaver(const FlagSaver&); // no copying!
|
|
||||||
void operator=(const FlagSaver&);
|
|
||||||
} __attribute__ ((unused));
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Some deprecated or hopefully-soon-to-be-deprecated functions.
|
|
||||||
|
|
||||||
// This is often used for logging. TODO(csilvers): figure out a better way
|
|
||||||
extern std::string CommandlineFlagsIntoString();
|
|
||||||
// Usually where this is used, a FlagSaver should be used instead.
|
|
||||||
extern bool ReadFlagsFromString(const std::string& flagfilecontents,
|
|
||||||
const char* prog_name,
|
|
||||||
bool errors_are_fatal); // uses SET_FLAGS_VALUE
|
|
||||||
|
|
||||||
// These let you manually implement --flagfile functionality.
|
|
||||||
// DEPRECATED.
|
|
||||||
extern bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
|
|
||||||
extern bool SaveCommandFlags(); // actually defined in google.cc !
|
|
||||||
extern bool ReadFromFlagsFile(const std::string& filename, const char* prog_name,
|
|
||||||
bool errors_are_fatal); // uses SET_FLAGS_VALUE
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Useful routines for initializing flags from the environment.
|
|
||||||
// In each case, if 'varname' does not exist in the environment
|
|
||||||
// return defval. If 'varname' does exist but is not valid
|
|
||||||
// (e.g., not a number for an int32 flag), abort with an error.
|
|
||||||
// Otherwise, return the value. NOTE: for booleans, for true use
|
|
||||||
// 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'.
|
|
||||||
|
|
||||||
extern bool BoolFromEnv(const char *varname, bool defval);
|
|
||||||
extern int32 Int32FromEnv(const char *varname, int32 defval);
|
|
||||||
extern int64 Int64FromEnv(const char *varname, int64 defval);
|
|
||||||
extern uint64 Uint64FromEnv(const char *varname, uint64 defval);
|
|
||||||
extern double DoubleFromEnv(const char *varname, double defval);
|
|
||||||
extern const char *StringFromEnv(const char *varname, const char *defval);
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// The next two functions parse commandlineflags from main():
|
|
||||||
|
|
||||||
// Set the "usage" message for this program. For example:
|
|
||||||
// string usage("This program does nothing. Sample usage:\n");
|
|
||||||
// usage += argv[0] + " <uselessarg1> <uselessarg2>";
|
|
||||||
// SetUsageMessage(usage);
|
|
||||||
// Do not include commandline flags in the usage: we do that for you!
|
|
||||||
// Thread-hostile; meant to be called before any threads are spawned.
|
|
||||||
extern void SetUsageMessage(const std::string& usage);
|
|
||||||
|
|
||||||
// Looks for flags in argv and parses them. Rearranges argv to put
|
|
||||||
// flags first, or removes them entirely if remove_flags is true.
|
|
||||||
// If a flag is defined more than once in the command line or flag
|
|
||||||
// file, the last definition is used. Returns the index (into argv)
|
|
||||||
// of the first non-flag argument.
|
|
||||||
// See top-of-file for more details on this function.
|
|
||||||
#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead.
|
|
||||||
extern uint32 ParseCommandLineFlags(int *argc, char*** argv,
|
|
||||||
bool remove_flags);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Calls to ParseCommandLineNonHelpFlags and then to
|
|
||||||
// HandleCommandLineHelpFlags can be used instead of a call to
|
|
||||||
// ParseCommandLineFlags during initialization, in order to allow for
|
|
||||||
// changing default values for some FLAGS (via
|
|
||||||
// e.g. SetCommandLineOptionWithMode calls) between the time of
|
|
||||||
// command line parsing and the time of dumping help information for
|
|
||||||
// the flags as a result of command line parsing. If a flag is
|
|
||||||
// defined more than once in the command line or flag file, the last
|
|
||||||
// definition is used. Returns the index (into argv) of the first
|
|
||||||
// non-flag argument. (If remove_flags is true, will always return 1.)
|
|
||||||
extern uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv,
|
|
||||||
bool remove_flags);
|
|
||||||
// This is actually defined in commandlineflags_reporting.cc.
|
|
||||||
// This function is misnamed (it also handles --version, etc.), but
|
|
||||||
// it's too late to change that now. :-(
|
|
||||||
extern void HandleCommandLineHelpFlags(); // in commandlineflags_reporting.cc
|
|
||||||
|
|
||||||
// Allow command line reparsing. Disables the error normally
|
|
||||||
// generated when an unknown flag is found, since it may be found in a
|
|
||||||
// later parse. Thread-hostile; meant to be called before any threads
|
|
||||||
// are spawned.
|
|
||||||
extern void AllowCommandLineReparsing();
|
|
||||||
|
|
||||||
// Reparse the flags that have not yet been recognized. Only flags
|
|
||||||
// registered since the last parse will be recognized. Any flag value
|
|
||||||
// must be provided as part of the argument using "=", not as a
|
|
||||||
// separate command line argument that follows the flag argument.
|
|
||||||
// Intended for handling flags from dynamically loaded libraries,
|
|
||||||
// since their flags are not registered until they are loaded.
|
|
||||||
// Returns the index (into the original argv) of the first non-flag
|
|
||||||
// argument. (If remove_flags is true, will always return 1.)
|
|
||||||
extern void ReparseCommandLineNonHelpFlags();
|
|
||||||
|
|
||||||
// Clean up memory allocated by flags. This is only needed to reduce
|
|
||||||
// the quantity of "potentially leaked" reports emitted by memory
|
|
||||||
// debugging tools such as valgrind. It is not required for normal
|
|
||||||
// operation, or for the perftools heap-checker. It must only be called
|
|
||||||
// when the process is about to exit, and all threads that might
|
|
||||||
// access flags are quiescent. Referencing flags after this is called
|
|
||||||
// will have unexpected consequences. This is not safe to run when
|
|
||||||
// multiple threads might be running: the function is thread-hostile.
|
|
||||||
extern void ShutDownCommandLineFlags();
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Now come the command line flag declaration/definition macros that
|
|
||||||
// will actually be used. They're kind of hairy. A major reason
|
|
||||||
// for this is initialization: we want people to be able to access
|
|
||||||
// variables in global constructors and have that not crash, even if
|
|
||||||
// their global constructor runs before the global constructor here.
|
|
||||||
// (Obviously, we can't guarantee the flags will have the correct
|
|
||||||
// default value in that case, but at least accessing them is safe.)
|
|
||||||
// The only way to do that is have flags point to a static buffer.
|
|
||||||
// So we make one, using a union to ensure proper alignment, and
|
|
||||||
// then use placement-new to actually set up the flag with the
|
|
||||||
// correct default value. In the same vein, we have to worry about
|
|
||||||
// flag access in global destructors, so FlagRegisterer has to be
|
|
||||||
// careful never to destroy the flag-values it constructs.
|
|
||||||
//
|
|
||||||
// Note that when we define a flag variable FLAGS_<name>, we also
|
|
||||||
// preemptively define a junk variable, FLAGS_no<name>. This is to
|
|
||||||
// cause a link-time error if someone tries to define 2 flags with
|
|
||||||
// names like "logging" and "nologging". We do this because a bool
|
|
||||||
// flag FLAG can be set from the command line to true with a "-FLAG"
|
|
||||||
// argument, and to false with a "-noFLAG" argument, and so this can
|
|
||||||
// potentially avert confusion.
|
|
||||||
//
|
|
||||||
// We also put flags into their own namespace. It is purposefully
|
|
||||||
// named in an opaque way that people should have trouble typing
|
|
||||||
// directly. The idea is that DEFINE puts the flag in the weird
|
|
||||||
// namespace, and DECLARE imports the flag from there into the current
|
|
||||||
// namespace. The net result is to force people to use DECLARE to get
|
|
||||||
// access to a flag, rather than saying "extern bool FLAGS_whatever;"
|
|
||||||
// or some such instead. We want this so we can put extra
|
|
||||||
// functionality (like sanity-checking) in DECLARE if we want, and
|
|
||||||
// make sure it is picked up everywhere.
|
|
||||||
//
|
|
||||||
// We also put the type of the variable in the namespace, so that
|
|
||||||
// people can't DECLARE_int32 something that they DEFINE_bool'd
|
|
||||||
// elsewhere.
|
|
||||||
|
|
||||||
class FlagRegisterer {
|
|
||||||
public:
|
|
||||||
FlagRegisterer(const char* name, const char* type,
|
|
||||||
const char* help, const char* filename,
|
|
||||||
void* current_storage, void* defvalue_storage);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern bool FlagsTypeWarn(const char *name);
|
|
||||||
|
|
||||||
// If your application #defines STRIP_FLAG_HELP to a non-zero value
|
|
||||||
// before #including this file, we remove the help message from the
|
|
||||||
// binary file. This can reduce the size of the resulting binary
|
|
||||||
// somewhat, and may also be useful for security reasons.
|
|
||||||
|
|
||||||
extern const char kStrippedFlagHelp[];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef SWIG // In swig, ignore the main flag declarations
|
|
||||||
|
|
||||||
#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
|
|
||||||
// Need this construct to avoid the 'defined but not used' warning.
|
|
||||||
#define MAYBE_STRIPPED_HELP(txt) (false ? (txt) : ::google::kStrippedFlagHelp)
|
|
||||||
#else
|
|
||||||
#define MAYBE_STRIPPED_HELP(txt) txt
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Each command-line flag has two variables associated with it: one
|
|
||||||
// with the current value, and one with the default value. However,
|
|
||||||
// we have a third variable, which is where value is assigned; it's a
|
|
||||||
// constant. This guarantees that FLAG_##value is initialized at
|
|
||||||
// static initialization time (e.g. before program-start) rather than
|
|
||||||
// than global construction time (which is after program-start but
|
|
||||||
// before main), at least when 'value' is a compile-time constant. We
|
|
||||||
// use a small trick for the "default value" variable, and call it
|
|
||||||
// FLAGS_no<name>. This serves the second purpose of assuring a
|
|
||||||
// compile error if someone tries to define a flag named no<name>
|
|
||||||
// which is illegal (--foo and --nofoo both affect the "foo" flag).
|
|
||||||
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
|
|
||||||
namespace fL##shorttype { \
|
|
||||||
static const type FLAGS_nono##name = value; \
|
|
||||||
type FLAGS_##name = FLAGS_nono##name; \
|
|
||||||
type FLAGS_no##name = FLAGS_nono##name; \
|
|
||||||
static ::google::FlagRegisterer o_##name( \
|
|
||||||
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
|
|
||||||
&FLAGS_##name, &FLAGS_no##name); \
|
|
||||||
} \
|
|
||||||
using fL##shorttype::FLAGS_##name
|
|
||||||
|
|
||||||
#define DECLARE_VARIABLE(type, shorttype, name) \
|
|
||||||
namespace fL##shorttype { \
|
|
||||||
extern type FLAGS_##name; \
|
|
||||||
} \
|
|
||||||
using fL##shorttype::FLAGS_##name
|
|
||||||
|
|
||||||
// For DEFINE_bool, we want to do the extra check that the passed-in
|
|
||||||
// value is actually a bool, and not a string or something that can be
|
|
||||||
// coerced to a bool. These declarations (no definition needed!) will
|
|
||||||
// help us do that, and never evaluate From, which is important.
|
|
||||||
// We'll use 'sizeof(IsBool(val))' to distinguish. This code requires
|
|
||||||
// that the compiler have different sizes for bool & double. Since
|
|
||||||
// this is not guaranteed by the standard, we check it with a
|
|
||||||
// compile-time assert (msg[-1] will give a compile-time error).
|
|
||||||
namespace fLB {
|
|
||||||
struct CompileAssert {};
|
|
||||||
typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[
|
|
||||||
(sizeof(double) != sizeof(bool)) ? 1 : -1];
|
|
||||||
template<typename From> double IsBoolFlag(const From& from);
|
|
||||||
bool IsBoolFlag(bool from);
|
|
||||||
} // namespace fLB
|
|
||||||
|
|
||||||
#define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name)
|
|
||||||
#define DEFINE_bool(name, val, txt) \
|
|
||||||
namespace fLB { \
|
|
||||||
typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \
|
|
||||||
(sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \
|
|
||||||
} \
|
|
||||||
DEFINE_VARIABLE(bool, B, name, val, txt)
|
|
||||||
|
|
||||||
#define DECLARE_int32(name) DECLARE_VARIABLE(::google::int32, I, name)
|
|
||||||
#define DEFINE_int32(name,val,txt) DEFINE_VARIABLE(::google::int32, I, name, val, txt)
|
|
||||||
|
|
||||||
#define DECLARE_int64(name) DECLARE_VARIABLE(::google::int64, I64, name)
|
|
||||||
#define DEFINE_int64(name,val,txt) DEFINE_VARIABLE(::google::int64, I64, name, val, txt)
|
|
||||||
|
|
||||||
#define DECLARE_uint64(name) DECLARE_VARIABLE(::google::uint64, U64, name)
|
|
||||||
#define DEFINE_uint64(name,val,txt) DEFINE_VARIABLE(::google::uint64, U64, name, val, txt)
|
|
||||||
|
|
||||||
#define DECLARE_double(name) DECLARE_VARIABLE(double, D, name)
|
|
||||||
#define DEFINE_double(name, val, txt) DEFINE_VARIABLE(double, D, name, val, txt)
|
|
||||||
|
|
||||||
// Strings are trickier, because they're not a POD, so we can't
|
|
||||||
// construct them at static-initialization time (instead they get
|
|
||||||
// constructed at global-constructor time, which is much later). To
|
|
||||||
// try to avoid crashes in that case, we use a char buffer to store
|
|
||||||
// the string, which we can static-initialize, and then placement-new
|
|
||||||
// into it later. It's not perfect, but the best we can do.
|
|
||||||
|
|
||||||
namespace fLS {
|
|
||||||
// The meaning of "string" might be different between now and when the
|
|
||||||
// macros below get invoked (e.g., if someone is experimenting with
|
|
||||||
// other string implementations that get defined after this file is
|
|
||||||
// included). Save the current meaning now and use it in the macros.
|
|
||||||
typedef std::string clstring;
|
|
||||||
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
const char *value) {
|
|
||||||
return new(stringspot) clstring(value);
|
|
||||||
}
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
const clstring &value) {
|
|
||||||
return new(stringspot) clstring(value);
|
|
||||||
}
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
int value);
|
|
||||||
} // namespace fLS
|
|
||||||
|
|
||||||
#define DECLARE_string(name) namespace fLS { extern ::fLS::clstring& FLAGS_##name; } \
|
|
||||||
using fLS::FLAGS_##name
|
|
||||||
|
|
||||||
// We need to define a var named FLAGS_no##name so people don't define
|
|
||||||
// --string and --nostring. And we need a temporary place to put val
|
|
||||||
// so we don't have to evaluate it twice. Two great needs that go
|
|
||||||
// great together!
|
|
||||||
// The weird 'using' + 'extern' inside the fLS namespace is to work around
|
|
||||||
// an unknown compiler bug/issue with the gcc 4.2.1 on SUSE 10. See
|
|
||||||
// http://code.google.com/p/google-gflags/issues/detail?id=20
|
|
||||||
#define DEFINE_string(name, val, txt) \
|
|
||||||
namespace fLS { \
|
|
||||||
using ::fLS::clstring; \
|
|
||||||
static union { void* align; char s[sizeof(clstring)]; } s_##name[2]; \
|
|
||||||
clstring* const FLAGS_no##name = ::fLS:: \
|
|
||||||
dont_pass0toDEFINE_string(s_##name[0].s, \
|
|
||||||
val); \
|
|
||||||
static ::google::FlagRegisterer o_##name( \
|
|
||||||
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
|
|
||||||
s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
|
|
||||||
extern clstring& FLAGS_##name; \
|
|
||||||
using fLS::FLAGS_##name; \
|
|
||||||
clstring& FLAGS_##name = *FLAGS_no##name; \
|
|
||||||
} \
|
|
||||||
using fLS::FLAGS_##name
|
|
||||||
|
|
||||||
#endif // SWIG
|
|
||||||
|
|
||||||
#endif // GOOGLE_GFLAGS_H_
|
|
|
@ -1,121 +0,0 @@
|
||||||
// Copyright (c) 2008, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// ---
|
|
||||||
// Author: Dave Nicponski
|
|
||||||
//
|
|
||||||
// Implement helpful bash-style command line flag completions
|
|
||||||
//
|
|
||||||
// ** Functional API:
|
|
||||||
// HandleCommandLineCompletions() should be called early during
|
|
||||||
// program startup, but after command line flag code has been
|
|
||||||
// initialized, such as the beginning of HandleCommandLineHelpFlags().
|
|
||||||
// It checks the value of the flag --tab_completion_word. If this
|
|
||||||
// flag is empty, nothing happens here. If it contains a string,
|
|
||||||
// however, then HandleCommandLineCompletions() will hijack the
|
|
||||||
// process, attempting to identify the intention behind this
|
|
||||||
// completion. Regardless of the outcome of this deduction, the
|
|
||||||
// process will be terminated, similar to --helpshort flag
|
|
||||||
// handling.
|
|
||||||
//
|
|
||||||
// ** Overview of Bash completions:
|
|
||||||
// Bash can be told to programatically determine completions for the
|
|
||||||
// current 'cursor word'. It does this by (in this case) invoking a
|
|
||||||
// command with some additional arguments identifying the command
|
|
||||||
// being executed, the word being completed, and the previous word
|
|
||||||
// (if any). Bash then expects a sequence of output lines to be
|
|
||||||
// printed to stdout. If these lines all contain a common prefix
|
|
||||||
// longer than the cursor word, bash will replace the cursor word
|
|
||||||
// with that common prefix, and display nothing. If there isn't such
|
|
||||||
// a common prefix, bash will display the lines in pages using 'more'.
|
|
||||||
//
|
|
||||||
// ** Strategy taken for command line completions:
|
|
||||||
// If we can deduce either the exact flag intended, or a common flag
|
|
||||||
// prefix, we'll output exactly that. Otherwise, if information
|
|
||||||
// must be displayed to the user, we'll take the opportunity to add
|
|
||||||
// some helpful information beyond just the flag name (specifically,
|
|
||||||
// we'll include the default flag value and as much of the flag's
|
|
||||||
// description as can fit on a single terminal line width, as specified
|
|
||||||
// by the flag --tab_completion_columns). Furthermore, we'll try to
|
|
||||||
// make bash order the output such that the most useful or relevent
|
|
||||||
// flags are the most likely to be shown at the top.
|
|
||||||
//
|
|
||||||
// ** Additional features:
|
|
||||||
// To assist in finding that one really useful flag, substring matching
|
|
||||||
// was implemented. Before pressing a <TAB> to get completion for the
|
|
||||||
// current word, you can append one or more '?' to the flag to do
|
|
||||||
// substring matching. Here's the semantics:
|
|
||||||
// --foo<TAB> Show me all flags with names prefixed by 'foo'
|
|
||||||
// --foo?<TAB> Show me all flags with 'foo' somewhere in the name
|
|
||||||
// --foo??<TAB> Same as prior case, but also search in module
|
|
||||||
// definition path for 'foo'
|
|
||||||
// --foo???<TAB> Same as prior case, but also search in flag
|
|
||||||
// descriptions for 'foo'
|
|
||||||
// Finally, we'll trim the output to a relatively small number of
|
|
||||||
// flags to keep bash quiet about the verbosity of output. If one
|
|
||||||
// really wanted to see all possible matches, appending a '+' to the
|
|
||||||
// search word will force the exhaustive list of matches to be printed.
|
|
||||||
//
|
|
||||||
// ** How to have bash accept completions from a binary:
|
|
||||||
// Bash requires that it be informed about each command that programmatic
|
|
||||||
// completion should be enabled for. Example addition to a .bashrc
|
|
||||||
// file would be (your path to gflags_completions.sh file may differ):
|
|
||||||
|
|
||||||
/*
|
|
||||||
$ complete -o bashdefault -o default -o nospace -C \
|
|
||||||
'/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \
|
|
||||||
time env binary_name another_binary [...]
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This would allow the following to work:
|
|
||||||
// $ /path/to/binary_name --vmodule<TAB>
|
|
||||||
// Or:
|
|
||||||
// $ ./bin/path/another_binary --gfs_u<TAB>
|
|
||||||
// (etc)
|
|
||||||
//
|
|
||||||
// Sadly, it appears that bash gives no easy way to force this behavior for
|
|
||||||
// all commands. That's where the "time" in the above example comes in.
|
|
||||||
// If you haven't specifically added a command to the list of completion
|
|
||||||
// supported commands, you can still get completions by prefixing the
|
|
||||||
// entire command with "env".
|
|
||||||
// $ env /some/brand/new/binary --vmod<TAB>
|
|
||||||
// Assuming that "binary" is a newly compiled binary, this should still
|
|
||||||
// produce the expected completion output.
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef GOOGLE_GFLAGS_COMPLETIONS_H_
|
|
||||||
#define GOOGLE_GFLAGS_COMPLETIONS_H_
|
|
||||||
|
|
||||||
namespace google {
|
|
||||||
|
|
||||||
void HandleCommandLineCompletions(void);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GOOGLE_GFLAGS_COMPLETIONS_H_
|
|
|
@ -1,110 +0,0 @@
|
||||||
/* src/config.h. Generated from config.h.in by configure. */
|
|
||||||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
|
||||||
|
|
||||||
/* Always the empty-string on non-windows systems. On windows, should be
|
|
||||||
"__declspec(dllexport)". This way, when we compile the dll, we export our
|
|
||||||
functions/classes. It's safe to define this here because config.h is only
|
|
||||||
used internally, to compile the DLL, and every DLL source file #includes
|
|
||||||
"config.h" before anything else. */
|
|
||||||
#define GFLAGS_DLL_DECL /**/
|
|
||||||
|
|
||||||
/* Namespace for Google classes */
|
|
||||||
#define GOOGLE_NAMESPACE ::google
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#define HAVE_DLFCN_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fnmatch.h> header file. */
|
|
||||||
#define HAVE_FNMATCH_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#define HAVE_INTTYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#define HAVE_MEMORY_H 1
|
|
||||||
|
|
||||||
/* define if the compiler implements namespaces */
|
|
||||||
#define HAVE_NAMESPACES 1
|
|
||||||
|
|
||||||
/* Define if you have POSIX threads libraries and header files. */
|
|
||||||
#define HAVE_PTHREAD 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `putenv' function. */
|
|
||||||
#define HAVE_PUTENV 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `setenv' function. */
|
|
||||||
#define HAVE_SETENV 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#define HAVE_STDINT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#define HAVE_STDLIB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#define HAVE_STRINGS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoll' function. */
|
|
||||||
#define HAVE_STRTOLL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoq' function. */
|
|
||||||
#define HAVE_STRTOQ 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#define HAVE_SYS_STAT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#define HAVE_UNISTD_H 1
|
|
||||||
|
|
||||||
/* define if your compiler has __attribute__ */
|
|
||||||
#define HAVE___ATTRIBUTE__ 1
|
|
||||||
|
|
||||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
|
||||||
*/
|
|
||||||
#define LT_OBJDIR ".libs/"
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#define PACKAGE "gflags"
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#define PACKAGE_BUGREPORT "opensource@google.com"
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#define PACKAGE_NAME "gflags"
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#define PACKAGE_STRING "gflags 1.5"
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#define PACKAGE_TARNAME "gflags"
|
|
||||||
|
|
||||||
/* Define to the home page for this package. */
|
|
||||||
#define PACKAGE_URL ""
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#define PACKAGE_VERSION "1.5"
|
|
||||||
|
|
||||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
|
||||||
your system. */
|
|
||||||
/* #undef PTHREAD_CREATE_JOINABLE */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* the namespace where STL code like vector<> is defined */
|
|
||||||
#define STL_NAMESPACE std
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#define VERSION "1.5"
|
|
||||||
|
|
||||||
/* Stops putting the code inside the Google namespace */
|
|
||||||
#define _END_GOOGLE_NAMESPACE_ }
|
|
||||||
|
|
||||||
/* Puts following code inside the Google namespace */
|
|
||||||
#define _START_GOOGLE_NAMESPACE_ namespace google {
|
|
|
@ -1,607 +0,0 @@
|
||||||
// Copyright (c) 2006, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
// Author: Ray Sidney
|
|
||||||
// Revamped and reorganized by Craig Silverstein
|
|
||||||
//
|
|
||||||
// This is the file that should be included by any file which declares
|
|
||||||
// or defines a command line flag or wants to parse command line flags
|
|
||||||
// or print a program usage message (which will include information about
|
|
||||||
// flags). Executive summary, in the form of an example foo.cc file:
|
|
||||||
//
|
|
||||||
// #include "foo.h" // foo.h has a line "DECLARE_int32(start);"
|
|
||||||
// #include "validators.h" // hypothetical file defining ValidateIsFile()
|
|
||||||
//
|
|
||||||
// DEFINE_int32(end, 1000, "The last record to read");
|
|
||||||
//
|
|
||||||
// DEFINE_string(filename, "my_file.txt", "The file to read");
|
|
||||||
// // Crash if the specified file does not exist.
|
|
||||||
// static bool dummy = RegisterFlagValidator(&FLAGS_filename,
|
|
||||||
// &ValidateIsFile);
|
|
||||||
//
|
|
||||||
// DECLARE_bool(verbose); // some other file has a DEFINE_bool(verbose, ...)
|
|
||||||
//
|
|
||||||
// void MyFunc() {
|
|
||||||
// if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Then, at the command-line:
|
|
||||||
// ./foo --noverbose --start=5 --end=100
|
|
||||||
//
|
|
||||||
// For more details, see
|
|
||||||
// doc/gflags.html
|
|
||||||
//
|
|
||||||
// --- A note about thread-safety:
|
|
||||||
//
|
|
||||||
// We describe many functions in this routine as being thread-hostile,
|
|
||||||
// thread-compatible, or thread-safe. Here are the meanings we use:
|
|
||||||
//
|
|
||||||
// thread-safe: it is safe for multiple threads to call this routine
|
|
||||||
// (or, when referring to a class, methods of this class)
|
|
||||||
// concurrently.
|
|
||||||
// thread-hostile: it is not safe for multiple threads to call this
|
|
||||||
// routine (or methods of this class) concurrently. In gflags,
|
|
||||||
// most thread-hostile routines are intended to be called early in,
|
|
||||||
// or even before, main() -- that is, before threads are spawned.
|
|
||||||
// thread-compatible: it is safe for multiple threads to read from
|
|
||||||
// this variable (when applied to variables), or to call const
|
|
||||||
// methods of this class (when applied to classes), as long as no
|
|
||||||
// other thread is writing to the variable or calling non-const
|
|
||||||
// methods of this class.
|
|
||||||
|
|
||||||
#ifndef GOOGLE_GFLAGS_H_
|
|
||||||
#define GOOGLE_GFLAGS_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
// We care a lot about number of bits things take up. Unfortunately,
|
|
||||||
// systems define their bit-specific ints in a lot of different ways.
|
|
||||||
// We use our own way, and have a typedef to get there.
|
|
||||||
// Note: these commands below may look like "#if 1" or "#if 0", but
|
|
||||||
// that's because they were constructed that way at ./configure time.
|
|
||||||
// Look at gflags.h.in to see how they're calculated (based on your config).
|
|
||||||
#if 0
|
|
||||||
#include <stdint.h> // the normal place uint16_t is defined
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
#include <sys/types.h> // the normal place u_int16_t is defined
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
#include <inttypes.h> // a third place for uint16_t or u_int16_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Annoying stuff for windows -- makes sure clients can import these functions
|
|
||||||
#if defined(_WIN32)
|
|
||||||
# ifndef GFLAGS_DLL_DECL
|
|
||||||
# define GFLAGS_DLL_DECL __declspec(dllimport)
|
|
||||||
# endif
|
|
||||||
# ifndef GFLAGS_DLL_DECLARE_FLAG
|
|
||||||
# define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport)
|
|
||||||
# endif
|
|
||||||
# ifndef GFLAGS_DLL_DEFINE_FLAG
|
|
||||||
# define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport)
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# ifndef GFLAGS_DLL_DECL
|
|
||||||
# define GFLAGS_DLL_DECL
|
|
||||||
# endif
|
|
||||||
# ifndef GFLAGS_DLL_DECLARE_FLAG
|
|
||||||
# define GFLAGS_DLL_DECLARE_FLAG
|
|
||||||
# endif
|
|
||||||
# ifndef GFLAGS_DLL_DEFINE_FLAG
|
|
||||||
# define GFLAGS_DLL_DEFINE_FLAG
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace google {
|
|
||||||
|
|
||||||
#if 0 // the C99 format
|
|
||||||
typedef int32_t int32;
|
|
||||||
typedef uint32_t uint32;
|
|
||||||
typedef int64_t int64;
|
|
||||||
typedef uint64_t uint64;
|
|
||||||
#elif 0 // the BSD format
|
|
||||||
typedef int32_t int32;
|
|
||||||
typedef u_int32_t uint32;
|
|
||||||
typedef int64_t int64;
|
|
||||||
typedef u_int64_t uint64;
|
|
||||||
#elif 1 // the windows (vc7) format
|
|
||||||
typedef __int32 int32;
|
|
||||||
typedef unsigned __int32 uint32;
|
|
||||||
typedef __int64 int64;
|
|
||||||
typedef unsigned __int64 uint64;
|
|
||||||
#else
|
|
||||||
#error Do not know how to define a 32-bit integer quantity on your system
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO(kjellander): update generated .h's for new gflags.
|
|
||||||
// https://code.google.com/p/webrtc/issues/detail?id=2251
|
|
||||||
extern const char* VersionString();
|
|
||||||
extern void SetVersionString(const std::string& version);
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// To actually define a flag in a file, use DEFINE_bool,
|
|
||||||
// DEFINE_string, etc. at the bottom of this file. You may also find
|
|
||||||
// it useful to register a validator with the flag. This ensures that
|
|
||||||
// when the flag is parsed from the commandline, or is later set via
|
|
||||||
// SetCommandLineOption, we call the validation function. It is _not_
|
|
||||||
// called when you assign the value to the flag directly using the = operator.
|
|
||||||
//
|
|
||||||
// The validation function should return true if the flag value is valid, and
|
|
||||||
// false otherwise. If the function returns false for the new setting of the
|
|
||||||
// flag, the flag will retain its current value. If it returns false for the
|
|
||||||
// default value, ParseCommandLineFlags() will die.
|
|
||||||
//
|
|
||||||
// This function is safe to call at global construct time (as in the
|
|
||||||
// example below).
|
|
||||||
//
|
|
||||||
// Example use:
|
|
||||||
// static bool ValidatePort(const char* flagname, int32 value) {
|
|
||||||
// if (value > 0 && value < 32768) // value is ok
|
|
||||||
// return true;
|
|
||||||
// printf("Invalid value for --%s: %d\n", flagname, (int)value);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// DEFINE_int32(port, 0, "What port to listen on");
|
|
||||||
// static bool dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort);
|
|
||||||
|
|
||||||
// Returns true if successfully registered, false if not (because the
|
|
||||||
// first argument doesn't point to a command-line flag, or because a
|
|
||||||
// validator is already registered for this flag).
|
|
||||||
GFLAGS_DLL_DECL bool RegisterFlagValidator(const bool* flag,
|
|
||||||
bool (*validate_fn)(const char*, bool));
|
|
||||||
GFLAGS_DLL_DECL bool RegisterFlagValidator(const int32* flag,
|
|
||||||
bool (*validate_fn)(const char*, int32));
|
|
||||||
GFLAGS_DLL_DECL bool RegisterFlagValidator(const int64* flag,
|
|
||||||
bool (*validate_fn)(const char*, int64));
|
|
||||||
GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint64* flag,
|
|
||||||
bool (*validate_fn)(const char*, uint64));
|
|
||||||
GFLAGS_DLL_DECL bool RegisterFlagValidator(const double* flag,
|
|
||||||
bool (*validate_fn)(const char*, double));
|
|
||||||
GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag,
|
|
||||||
bool (*validate_fn)(const char*, const std::string&));
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// These methods are the best way to get access to info about the
|
|
||||||
// list of commandline flags. Note that these routines are pretty slow.
|
|
||||||
// GetAllFlags: mostly-complete info about the list, sorted by file.
|
|
||||||
// ShowUsageWithFlags: pretty-prints the list to stdout (what --help does)
|
|
||||||
// ShowUsageWithFlagsRestrict: limit to filenames with restrict as a substr
|
|
||||||
//
|
|
||||||
// In addition to accessing flags, you can also access argv[0] (the program
|
|
||||||
// name) and argv (the entire commandline), which we sock away a copy of.
|
|
||||||
// These variables are static, so you should only set them once.
|
|
||||||
|
|
||||||
struct GFLAGS_DLL_DECL CommandLineFlagInfo {
|
|
||||||
std::string name; // the name of the flag
|
|
||||||
std::string type; // the type of the flag: int32, etc
|
|
||||||
std::string description; // the "help text" associated with the flag
|
|
||||||
std::string current_value; // the current value, as a string
|
|
||||||
std::string default_value; // the default value, as a string
|
|
||||||
std::string filename; // 'cleaned' version of filename holding the flag
|
|
||||||
bool has_validator_fn; // true if RegisterFlagValidator called on flag
|
|
||||||
bool is_default; // true if the flag has the default value and
|
|
||||||
// has not been set explicitly from the cmdline
|
|
||||||
// or via SetCommandLineOption
|
|
||||||
const void* flag_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Using this inside of a validator is a recipe for a deadlock.
|
|
||||||
// TODO(wojtekm) Fix locking when validators are running, to make it safe to
|
|
||||||
// call validators during ParseAllFlags.
|
|
||||||
// Also make sure then to uncomment the corresponding unit test in
|
|
||||||
// commandlineflags_unittest.sh
|
|
||||||
extern GFLAGS_DLL_DECL void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
|
|
||||||
// These two are actually defined in commandlineflags_reporting.cc.
|
|
||||||
extern GFLAGS_DLL_DECL void ShowUsageWithFlags(const char *argv0); // what --help does
|
|
||||||
extern GFLAGS_DLL_DECL void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
|
|
||||||
|
|
||||||
// Create a descriptive string for a flag.
|
|
||||||
// Goes to some trouble to make pretty line breaks.
|
|
||||||
extern GFLAGS_DLL_DECL std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
|
|
||||||
|
|
||||||
// Thread-hostile; meant to be called before any threads are spawned.
|
|
||||||
extern GFLAGS_DLL_DECL void SetArgv(int argc, const char** argv);
|
|
||||||
// The following functions are thread-safe as long as SetArgv() is
|
|
||||||
// only called before any threads start.
|
|
||||||
extern GFLAGS_DLL_DECL const std::vector<std::string>& GetArgvs(); // all of argv as a vector
|
|
||||||
extern GFLAGS_DLL_DECL const char* GetArgv(); // all of argv as a string
|
|
||||||
extern GFLAGS_DLL_DECL const char* GetArgv0(); // only argv0
|
|
||||||
extern GFLAGS_DLL_DECL uint32 GetArgvSum(); // simple checksum of argv
|
|
||||||
extern GFLAGS_DLL_DECL const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
|
|
||||||
extern GFLAGS_DLL_DECL const char* ProgramInvocationShortName(); // basename(argv0)
|
|
||||||
// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
|
|
||||||
// called before any threads start.
|
|
||||||
extern GFLAGS_DLL_DECL const char* ProgramUsage(); // string set by SetUsageMessage()
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Normally you access commandline flags by just saying "if (FLAGS_foo)"
|
|
||||||
// or whatever, and set them by calling "FLAGS_foo = bar" (or, more
|
|
||||||
// commonly, via the DEFINE_foo macro). But if you need a bit more
|
|
||||||
// control, we have programmatic ways to get/set the flags as well.
|
|
||||||
// These programmatic ways to access flags are thread-safe, but direct
|
|
||||||
// access is only thread-compatible.
|
|
||||||
|
|
||||||
// Return true iff the flagname was found.
|
|
||||||
// OUTPUT is set to the flag's value, or unchanged if we return false.
|
|
||||||
extern GFLAGS_DLL_DECL bool GetCommandLineOption(const char* name, std::string* OUTPUT);
|
|
||||||
|
|
||||||
// Return true iff the flagname was found. OUTPUT is set to the flag's
|
|
||||||
// CommandLineFlagInfo or unchanged if we return false.
|
|
||||||
extern GFLAGS_DLL_DECL bool GetCommandLineFlagInfo(const char* name,
|
|
||||||
CommandLineFlagInfo* OUTPUT);
|
|
||||||
|
|
||||||
// Return the CommandLineFlagInfo of the flagname. exit() if name not found.
|
|
||||||
// Example usage, to check if a flag's value is currently the default value:
|
|
||||||
// if (GetCommandLineFlagInfoOrDie("foo").is_default) ...
|
|
||||||
extern GFLAGS_DLL_DECL CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
|
|
||||||
|
|
||||||
enum GFLAGS_DLL_DECL FlagSettingMode {
|
|
||||||
// update the flag's value (can call this multiple times).
|
|
||||||
SET_FLAGS_VALUE,
|
|
||||||
// update the flag's value, but *only if* it has not yet been updated
|
|
||||||
// with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
|
|
||||||
SET_FLAG_IF_DEFAULT,
|
|
||||||
// set the flag's default value to this. If the flag has not yet updated
|
|
||||||
// yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
|
|
||||||
// change the flag's current value to the new default value as well.
|
|
||||||
SET_FLAGS_DEFAULT
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set a particular flag ("command line option"). Returns a string
|
|
||||||
// describing the new value that the option has been set to. The
|
|
||||||
// return value API is not well-specified, so basically just depend on
|
|
||||||
// it to be empty if the setting failed for some reason -- the name is
|
|
||||||
// not a valid flag name, or the value is not a valid value -- and
|
|
||||||
// non-empty else.
|
|
||||||
|
|
||||||
// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
|
|
||||||
extern GFLAGS_DLL_DECL std::string SetCommandLineOption(const char* name, const char* value);
|
|
||||||
extern GFLAGS_DLL_DECL std::string SetCommandLineOptionWithMode(const char* name, const char* value,
|
|
||||||
FlagSettingMode set_mode);
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Saves the states (value, default value, whether the user has set
|
|
||||||
// the flag, registered validators, etc) of all flags, and restores
|
|
||||||
// them when the FlagSaver is destroyed. This is very useful in
|
|
||||||
// tests, say, when you want to let your tests change the flags, but
|
|
||||||
// make sure that they get reverted to the original states when your
|
|
||||||
// test is complete.
|
|
||||||
//
|
|
||||||
// Example usage:
|
|
||||||
// void TestFoo() {
|
|
||||||
// FlagSaver s1;
|
|
||||||
// FLAG_foo = false;
|
|
||||||
// FLAG_bar = "some value";
|
|
||||||
//
|
|
||||||
// // test happens here. You can return at any time
|
|
||||||
// // without worrying about restoring the FLAG values.
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Note: This class is marked with __attribute__((unused)) because all the
|
|
||||||
// work is done in the constructor and destructor, so in the standard
|
|
||||||
// usage example above, the compiler would complain that it's an
|
|
||||||
// unused variable.
|
|
||||||
//
|
|
||||||
// This class is thread-safe.
|
|
||||||
|
|
||||||
class GFLAGS_DLL_DECL FlagSaver {
|
|
||||||
public:
|
|
||||||
FlagSaver();
|
|
||||||
~FlagSaver();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class FlagSaverImpl* impl_; // we use pimpl here to keep API steady
|
|
||||||
|
|
||||||
FlagSaver(const FlagSaver&); // no copying!
|
|
||||||
void operator=(const FlagSaver&);
|
|
||||||
} ;
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Some deprecated or hopefully-soon-to-be-deprecated functions.
|
|
||||||
|
|
||||||
// This is often used for logging. TODO(csilvers): figure out a better way
|
|
||||||
extern GFLAGS_DLL_DECL std::string CommandlineFlagsIntoString();
|
|
||||||
// Usually where this is used, a FlagSaver should be used instead.
|
|
||||||
extern GFLAGS_DLL_DECL bool ReadFlagsFromString(const std::string& flagfilecontents,
|
|
||||||
const char* prog_name,
|
|
||||||
bool errors_are_fatal); // uses SET_FLAGS_VALUE
|
|
||||||
|
|
||||||
// These let you manually implement --flagfile functionality.
|
|
||||||
// DEPRECATED.
|
|
||||||
extern GFLAGS_DLL_DECL bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
|
|
||||||
extern GFLAGS_DLL_DECL bool SaveCommandFlags(); // actually defined in google.cc !
|
|
||||||
extern GFLAGS_DLL_DECL bool ReadFromFlagsFile(const std::string& filename, const char* prog_name,
|
|
||||||
bool errors_are_fatal); // uses SET_FLAGS_VALUE
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Useful routines for initializing flags from the environment.
|
|
||||||
// In each case, if 'varname' does not exist in the environment
|
|
||||||
// return defval. If 'varname' does exist but is not valid
|
|
||||||
// (e.g., not a number for an int32 flag), abort with an error.
|
|
||||||
// Otherwise, return the value. NOTE: for booleans, for true use
|
|
||||||
// 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'.
|
|
||||||
|
|
||||||
extern GFLAGS_DLL_DECL bool BoolFromEnv(const char *varname, bool defval);
|
|
||||||
extern GFLAGS_DLL_DECL int32 Int32FromEnv(const char *varname, int32 defval);
|
|
||||||
extern GFLAGS_DLL_DECL int64 Int64FromEnv(const char *varname, int64 defval);
|
|
||||||
extern GFLAGS_DLL_DECL uint64 Uint64FromEnv(const char *varname, uint64 defval);
|
|
||||||
extern GFLAGS_DLL_DECL double DoubleFromEnv(const char *varname, double defval);
|
|
||||||
extern GFLAGS_DLL_DECL const char *StringFromEnv(const char *varname, const char *defval);
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// The next two functions parse commandlineflags from main():
|
|
||||||
|
|
||||||
// Set the "usage" message for this program. For example:
|
|
||||||
// string usage("This program does nothing. Sample usage:\n");
|
|
||||||
// usage += argv[0] + " <uselessarg1> <uselessarg2>";
|
|
||||||
// SetUsageMessage(usage);
|
|
||||||
// Do not include commandline flags in the usage: we do that for you!
|
|
||||||
// Thread-hostile; meant to be called before any threads are spawned.
|
|
||||||
extern GFLAGS_DLL_DECL void SetUsageMessage(const std::string& usage);
|
|
||||||
|
|
||||||
// Looks for flags in argv and parses them. Rearranges argv to put
|
|
||||||
// flags first, or removes them entirely if remove_flags is true.
|
|
||||||
// If a flag is defined more than once in the command line or flag
|
|
||||||
// file, the last definition is used.
|
|
||||||
// See top-of-file for more details on this function.
|
|
||||||
#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead.
|
|
||||||
extern GFLAGS_DLL_DECL uint32 ParseCommandLineFlags(int *argc, char*** argv,
|
|
||||||
bool remove_flags);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Calls to ParseCommandLineNonHelpFlags and then to
|
|
||||||
// HandleCommandLineHelpFlags can be used instead of a call to
|
|
||||||
// ParseCommandLineFlags during initialization, in order to allow for
|
|
||||||
// changing default values for some FLAGS (via
|
|
||||||
// e.g. SetCommandLineOptionWithMode calls) between the time of
|
|
||||||
// command line parsing and the time of dumping help information for
|
|
||||||
// the flags as a result of command line parsing.
|
|
||||||
// If a flag is defined more than once in the command line or flag
|
|
||||||
// file, the last definition is used.
|
|
||||||
extern GFLAGS_DLL_DECL uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv,
|
|
||||||
bool remove_flags);
|
|
||||||
// This is actually defined in commandlineflags_reporting.cc.
|
|
||||||
// This function is misnamed (it also handles --version, etc.), but
|
|
||||||
// it's too late to change that now. :-(
|
|
||||||
extern GFLAGS_DLL_DECL void HandleCommandLineHelpFlags(); // in commandlineflags_reporting.cc
|
|
||||||
|
|
||||||
// Allow command line reparsing. Disables the error normally
|
|
||||||
// generated when an unknown flag is found, since it may be found in a
|
|
||||||
// later parse. Thread-hostile; meant to be called before any threads
|
|
||||||
// are spawned.
|
|
||||||
extern GFLAGS_DLL_DECL void AllowCommandLineReparsing();
|
|
||||||
|
|
||||||
// Reparse the flags that have not yet been recognized.
|
|
||||||
// Only flags registered since the last parse will be recognized.
|
|
||||||
// Any flag value must be provided as part of the argument using "=",
|
|
||||||
// not as a separate command line argument that follows the flag argument.
|
|
||||||
// Intended for handling flags from dynamically loaded libraries,
|
|
||||||
// since their flags are not registered until they are loaded.
|
|
||||||
extern GFLAGS_DLL_DECL void ReparseCommandLineNonHelpFlags();
|
|
||||||
|
|
||||||
// Clean up memory allocated by flags. This is only needed to reduce
|
|
||||||
// the quantity of "potentially leaked" reports emitted by memory
|
|
||||||
// debugging tools such as valgrind. It is not required for normal
|
|
||||||
// operation, or for the perftools heap-checker. It must only be called
|
|
||||||
// when the process is about to exit, and all threads that might
|
|
||||||
// access flags are quiescent. Referencing flags after this is called
|
|
||||||
// will have unexpected consequences. This is not safe to run when
|
|
||||||
// multiple threads might be running: the function is thread-hostile.
|
|
||||||
extern GFLAGS_DLL_DECL void ShutDownCommandLineFlags();
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Now come the command line flag declaration/definition macros that
|
|
||||||
// will actually be used. They're kind of hairy. A major reason
|
|
||||||
// for this is initialization: we want people to be able to access
|
|
||||||
// variables in global constructors and have that not crash, even if
|
|
||||||
// their global constructor runs before the global constructor here.
|
|
||||||
// (Obviously, we can't guarantee the flags will have the correct
|
|
||||||
// default value in that case, but at least accessing them is safe.)
|
|
||||||
// The only way to do that is have flags point to a static buffer.
|
|
||||||
// So we make one, using a union to ensure proper alignment, and
|
|
||||||
// then use placement-new to actually set up the flag with the
|
|
||||||
// correct default value. In the same vein, we have to worry about
|
|
||||||
// flag access in global destructors, so FlagRegisterer has to be
|
|
||||||
// careful never to destroy the flag-values it constructs.
|
|
||||||
//
|
|
||||||
// Note that when we define a flag variable FLAGS_<name>, we also
|
|
||||||
// preemptively define a junk variable, FLAGS_no<name>. This is to
|
|
||||||
// cause a link-time error if someone tries to define 2 flags with
|
|
||||||
// names like "logging" and "nologging". We do this because a bool
|
|
||||||
// flag FLAG can be set from the command line to true with a "-FLAG"
|
|
||||||
// argument, and to false with a "-noFLAG" argument, and so this can
|
|
||||||
// potentially avert confusion.
|
|
||||||
//
|
|
||||||
// We also put flags into their own namespace. It is purposefully
|
|
||||||
// named in an opaque way that people should have trouble typing
|
|
||||||
// directly. The idea is that DEFINE puts the flag in the weird
|
|
||||||
// namespace, and DECLARE imports the flag from there into the current
|
|
||||||
// namespace. The net result is to force people to use DECLARE to get
|
|
||||||
// access to a flag, rather than saying "extern bool FLAGS_whatever;"
|
|
||||||
// or some such instead. We want this so we can put extra
|
|
||||||
// functionality (like sanity-checking) in DECLARE if we want, and
|
|
||||||
// make sure it is picked up everywhere.
|
|
||||||
//
|
|
||||||
// We also put the type of the variable in the namespace, so that
|
|
||||||
// people can't DECLARE_int32 something that they DEFINE_bool'd
|
|
||||||
// elsewhere.
|
|
||||||
|
|
||||||
class GFLAGS_DLL_DECL FlagRegisterer {
|
|
||||||
public:
|
|
||||||
FlagRegisterer(const char* name, const char* type,
|
|
||||||
const char* help, const char* filename,
|
|
||||||
void* current_storage, void* defvalue_storage);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern bool FlagsTypeWarn(const char *name);
|
|
||||||
|
|
||||||
// If your application #defines STRIP_FLAG_HELP to a non-zero value
|
|
||||||
// before #including this file, we remove the help message from the
|
|
||||||
// binary file. This can reduce the size of the resulting binary
|
|
||||||
// somewhat, and may also be useful for security reasons.
|
|
||||||
|
|
||||||
extern const char kStrippedFlagHelp[];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef SWIG // In swig, ignore the main flag declarations
|
|
||||||
|
|
||||||
#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
|
|
||||||
// Need this construct to avoid the 'defined but not used' warning.
|
|
||||||
#define MAYBE_STRIPPED_HELP(txt) (false ? (txt) : kStrippedFlagHelp)
|
|
||||||
#else
|
|
||||||
#define MAYBE_STRIPPED_HELP(txt) txt
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Each command-line flag has two variables associated with it: one
|
|
||||||
// with the current value, and one with the default value. However,
|
|
||||||
// we have a third variable, which is where value is assigned; it's a
|
|
||||||
// constant. This guarantees that FLAG_##value is initialized at
|
|
||||||
// static initialization time (e.g. before program-start) rather than
|
|
||||||
// than global construction time (which is after program-start but
|
|
||||||
// before main), at least when 'value' is a compile-time constant. We
|
|
||||||
// use a small trick for the "default value" variable, and call it
|
|
||||||
// FLAGS_no<name>. This serves the second purpose of assuring a
|
|
||||||
// compile error if someone tries to define a flag named no<name>
|
|
||||||
// which is illegal (--foo and --nofoo both affect the "foo" flag).
|
|
||||||
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
|
|
||||||
namespace fL##shorttype { \
|
|
||||||
static const type FLAGS_nono##name = value; \
|
|
||||||
/* We always want to export defined variables, dll or no */ \
|
|
||||||
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
|
|
||||||
type FLAGS_no##name = FLAGS_nono##name; \
|
|
||||||
static ::google::FlagRegisterer o_##name( \
|
|
||||||
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
|
|
||||||
&FLAGS_##name, &FLAGS_no##name); \
|
|
||||||
} \
|
|
||||||
using fL##shorttype::FLAGS_##name
|
|
||||||
|
|
||||||
#define DECLARE_VARIABLE(type, shorttype, name) \
|
|
||||||
namespace fL##shorttype { \
|
|
||||||
/* We always want to import declared variables, dll or no */ \
|
|
||||||
extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; \
|
|
||||||
} \
|
|
||||||
using fL##shorttype::FLAGS_##name
|
|
||||||
|
|
||||||
// For DEFINE_bool, we want to do the extra check that the passed-in
|
|
||||||
// value is actually a bool, and not a string or something that can be
|
|
||||||
// coerced to a bool. These declarations (no definition needed!) will
|
|
||||||
// help us do that, and never evaluate From, which is important.
|
|
||||||
// We'll use 'sizeof(IsBool(val))' to distinguish. This code requires
|
|
||||||
// that the compiler have different sizes for bool & double. Since
|
|
||||||
// this is not guaranteed by the standard, we check it with a
|
|
||||||
// compile-time assert (msg[-1] will give a compile-time error).
|
|
||||||
namespace fLB {
|
|
||||||
struct CompileAssert {};
|
|
||||||
typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[
|
|
||||||
(sizeof(double) != sizeof(bool)) ? 1 : -1];
|
|
||||||
template<typename From> GFLAGS_DLL_DECL double IsBoolFlag(const From& from);
|
|
||||||
GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
|
|
||||||
} // namespace fLB
|
|
||||||
|
|
||||||
#define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name)
|
|
||||||
#define DEFINE_bool(name, val, txt) \
|
|
||||||
namespace fLB { \
|
|
||||||
typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \
|
|
||||||
(sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \
|
|
||||||
} \
|
|
||||||
DEFINE_VARIABLE(bool, B, name, val, txt)
|
|
||||||
|
|
||||||
#define DECLARE_int32(name) DECLARE_VARIABLE(::google::int32, I, name)
|
|
||||||
#define DEFINE_int32(name,val,txt) DEFINE_VARIABLE(::google::int32, I, name, val, txt)
|
|
||||||
|
|
||||||
#define DECLARE_int64(name) DECLARE_VARIABLE(::google::int64, I64, name)
|
|
||||||
#define DEFINE_int64(name,val,txt) DEFINE_VARIABLE(::google::int64, I64, name, val, txt)
|
|
||||||
|
|
||||||
#define DECLARE_uint64(name) DECLARE_VARIABLE(::google::uint64, U64, name)
|
|
||||||
#define DEFINE_uint64(name,val,txt) DEFINE_VARIABLE(::google::uint64, U64, name, val, txt)
|
|
||||||
|
|
||||||
#define DECLARE_double(name) DECLARE_VARIABLE(double, D, name)
|
|
||||||
#define DEFINE_double(name, val, txt) DEFINE_VARIABLE(double, D, name, val, txt)
|
|
||||||
|
|
||||||
// Strings are trickier, because they're not a POD, so we can't
|
|
||||||
// construct them at static-initialization time (instead they get
|
|
||||||
// constructed at global-constructor time, which is much later). To
|
|
||||||
// try to avoid crashes in that case, we use a char buffer to store
|
|
||||||
// the string, which we can static-initialize, and then placement-new
|
|
||||||
// into it later. It's not perfect, but the best we can do.
|
|
||||||
|
|
||||||
namespace fLS {
|
|
||||||
// The meaning of "string" might be different between now and when the
|
|
||||||
// macros below get invoked (e.g., if someone is experimenting with
|
|
||||||
// other string implementations that get defined after this file is
|
|
||||||
// included). Save the current meaning now and use it in the macros.
|
|
||||||
typedef std::string clstring;
|
|
||||||
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
const char *value) {
|
|
||||||
return new(stringspot) clstring(value);
|
|
||||||
}
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
const clstring &value) {
|
|
||||||
return new(stringspot) clstring(value);
|
|
||||||
}
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
int value);
|
|
||||||
} // namespace fLS
|
|
||||||
|
|
||||||
#define DECLARE_string(name) namespace fLS { extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; } \
|
|
||||||
using fLS::FLAGS_##name
|
|
||||||
|
|
||||||
// We need to define a var named FLAGS_no##name so people don't define
|
|
||||||
// --string and --nostring. And we need a temporary place to put val
|
|
||||||
// so we don't have to evaluate it twice. Two great needs that go
|
|
||||||
// great together!
|
|
||||||
#define DEFINE_string(name, val, txt) \
|
|
||||||
namespace fLS { \
|
|
||||||
using ::fLS::clstring; \
|
|
||||||
static union { void* align; char s[sizeof(clstring)]; } s_##name[2]; \
|
|
||||||
clstring* const FLAGS_no##name = ::fLS:: \
|
|
||||||
dont_pass0toDEFINE_string(s_##name[0].s, \
|
|
||||||
val); \
|
|
||||||
static ::google::FlagRegisterer o_##name( \
|
|
||||||
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
|
|
||||||
s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
|
|
||||||
GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name = *FLAGS_no##name; \
|
|
||||||
} \
|
|
||||||
using fLS::FLAGS_##name
|
|
||||||
|
|
||||||
#endif // SWIG
|
|
||||||
|
|
||||||
#endif // GOOGLE_GFLAGS_H_
|
|
|
@ -1,130 +0,0 @@
|
||||||
// Copyright (c) 2008, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// ---
|
|
||||||
// Author: Dave Nicponski
|
|
||||||
//
|
|
||||||
// Implement helpful bash-style command line flag completions
|
|
||||||
//
|
|
||||||
// ** Functional API:
|
|
||||||
// HandleCommandLineCompletions() should be called early during
|
|
||||||
// program startup, but after command line flag code has been
|
|
||||||
// initialized, such as the beginning of HandleCommandLineHelpFlags().
|
|
||||||
// It checks the value of the flag --tab_completion_word. If this
|
|
||||||
// flag is empty, nothing happens here. If it contains a string,
|
|
||||||
// however, then HandleCommandLineCompletions() will hijack the
|
|
||||||
// process, attempting to identify the intention behind this
|
|
||||||
// completion. Regardless of the outcome of this deduction, the
|
|
||||||
// process will be terminated, similar to --helpshort flag
|
|
||||||
// handling.
|
|
||||||
//
|
|
||||||
// ** Overview of Bash completions:
|
|
||||||
// Bash can be told to programatically determine completions for the
|
|
||||||
// current 'cursor word'. It does this by (in this case) invoking a
|
|
||||||
// command with some additional arguments identifying the command
|
|
||||||
// being executed, the word being completed, and the previous word
|
|
||||||
// (if any). Bash then expects a sequence of output lines to be
|
|
||||||
// printed to stdout. If these lines all contain a common prefix
|
|
||||||
// longer than the cursor word, bash will replace the cursor word
|
|
||||||
// with that common prefix, and display nothing. If there isn't such
|
|
||||||
// a common prefix, bash will display the lines in pages using 'more'.
|
|
||||||
//
|
|
||||||
// ** Strategy taken for command line completions:
|
|
||||||
// If we can deduce either the exact flag intended, or a common flag
|
|
||||||
// prefix, we'll output exactly that. Otherwise, if information
|
|
||||||
// must be displayed to the user, we'll take the opportunity to add
|
|
||||||
// some helpful information beyond just the flag name (specifically,
|
|
||||||
// we'll include the default flag value and as much of the flag's
|
|
||||||
// description as can fit on a single terminal line width, as specified
|
|
||||||
// by the flag --tab_completion_columns). Furthermore, we'll try to
|
|
||||||
// make bash order the output such that the most useful or relevent
|
|
||||||
// flags are the most likely to be shown at the top.
|
|
||||||
//
|
|
||||||
// ** Additional features:
|
|
||||||
// To assist in finding that one really useful flag, substring matching
|
|
||||||
// was implemented. Before pressing a <TAB> to get completion for the
|
|
||||||
// current word, you can append one or more '?' to the flag to do
|
|
||||||
// substring matching. Here's the semantics:
|
|
||||||
// --foo<TAB> Show me all flags with names prefixed by 'foo'
|
|
||||||
// --foo?<TAB> Show me all flags with 'foo' somewhere in the name
|
|
||||||
// --foo??<TAB> Same as prior case, but also search in module
|
|
||||||
// definition path for 'foo'
|
|
||||||
// --foo???<TAB> Same as prior case, but also search in flag
|
|
||||||
// descriptions for 'foo'
|
|
||||||
// Finally, we'll trim the output to a relatively small number of
|
|
||||||
// flags to keep bash quiet about the verbosity of output. If one
|
|
||||||
// really wanted to see all possible matches, appending a '+' to the
|
|
||||||
// search word will force the exhaustive list of matches to be printed.
|
|
||||||
//
|
|
||||||
// ** How to have bash accept completions from a binary:
|
|
||||||
// Bash requires that it be informed about each command that programmatic
|
|
||||||
// completion should be enabled for. Example addition to a .bashrc
|
|
||||||
// file would be (your path to gflags_completions.sh file may differ):
|
|
||||||
|
|
||||||
/*
|
|
||||||
$ complete -o bashdefault -o default -o nospace -C \
|
|
||||||
'/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \
|
|
||||||
time env binary_name another_binary [...]
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This would allow the following to work:
|
|
||||||
// $ /path/to/binary_name --vmodule<TAB>
|
|
||||||
// Or:
|
|
||||||
// $ ./bin/path/another_binary --gfs_u<TAB>
|
|
||||||
// (etc)
|
|
||||||
//
|
|
||||||
// Sadly, it appears that bash gives no easy way to force this behavior for
|
|
||||||
// all commands. That's where the "time" in the above example comes in.
|
|
||||||
// If you haven't specifically added a command to the list of completion
|
|
||||||
// supported commands, you can still get completions by prefixing the
|
|
||||||
// entire command with "env".
|
|
||||||
// $ env /some/brand/new/binary --vmod<TAB>
|
|
||||||
// Assuming that "binary" is a newly compiled binary, this should still
|
|
||||||
// produce the expected completion output.
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef GOOGLE_GFLAGS_COMPLETIONS_H_
|
|
||||||
#define GOOGLE_GFLAGS_COMPLETIONS_H_
|
|
||||||
|
|
||||||
// Annoying stuff for windows -- makes sure clients can import these functions
|
|
||||||
#ifndef GFLAGS_DLL_DECL
|
|
||||||
# ifdef _WIN32
|
|
||||||
# define GFLAGS_DLL_DECL __declspec(dllimport)
|
|
||||||
# else
|
|
||||||
# define GFLAGS_DLL_DECL
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace google {
|
|
||||||
|
|
||||||
GFLAGS_DLL_DECL void HandleCommandLineCompletions(void);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GOOGLE_GFLAGS_COMPLETIONS_H_
|
|
|
@ -1,139 +0,0 @@
|
||||||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
|
||||||
|
|
||||||
/* Sometimes we accidentally #include this config.h instead of the one
|
|
||||||
in .. -- this is particularly true for msys/mingw, which uses the
|
|
||||||
unix config.h but also runs code in the windows directory.
|
|
||||||
*/
|
|
||||||
#ifdef __MINGW32__
|
|
||||||
#include "../config.h"
|
|
||||||
#define GOOGLE_GFLAGS_WINDOWS_CONFIG_H_
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef GOOGLE_GFLAGS_WINDOWS_CONFIG_H_
|
|
||||||
#define GOOGLE_GFLAGS_WINDOWS_CONFIG_H_
|
|
||||||
|
|
||||||
/* Always the empty-string on non-windows systems. On windows, should be
|
|
||||||
"__declspec(dllexport)". This way, when we compile the dll, we export our
|
|
||||||
functions/classes. It's safe to define this here because config.h is only
|
|
||||||
used internally, to compile the DLL, and every DLL source file #includes
|
|
||||||
"config.h" before anything else. */
|
|
||||||
#ifndef GFLAGS_DLL_DECL
|
|
||||||
# define GFLAGS_IS_A_DLL 1 /* not set if you're statically linking */
|
|
||||||
# define GFLAGS_DLL_DECL __declspec(dllexport)
|
|
||||||
# define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Namespace for Google classes */
|
|
||||||
#define GOOGLE_NAMESPACE ::google
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#undef HAVE_DLFCN_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fnmatch.h> header file. */
|
|
||||||
#undef HAVE_FNMATCH_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#undef HAVE_INTTYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#undef HAVE_MEMORY_H
|
|
||||||
|
|
||||||
/* define if the compiler implements namespaces */
|
|
||||||
#define HAVE_NAMESPACES 1
|
|
||||||
|
|
||||||
/* Define if you have POSIX threads libraries and header files. */
|
|
||||||
#undef HAVE_PTHREAD
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `putenv' function. */
|
|
||||||
#define HAVE_PUTENV 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `setenv' function. */
|
|
||||||
#undef HAVE_SETENV
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#undef HAVE_STDINT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#define HAVE_STDLIB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#undef HAVE_STRINGS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoll' function. */
|
|
||||||
#define HAVE_STRTOLL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoq' function. */
|
|
||||||
#define HAVE_STRTOQ 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#define HAVE_SYS_STAT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#undef HAVE_UNISTD_H
|
|
||||||
|
|
||||||
/* define if your compiler has __attribute__ */
|
|
||||||
#undef HAVE___ATTRIBUTE__
|
|
||||||
|
|
||||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
|
||||||
*/
|
|
||||||
#undef LT_OBJDIR
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#undef PACKAGE
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#undef PACKAGE_BUGREPORT
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#undef PACKAGE_NAME
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#undef PACKAGE_STRING
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#undef PACKAGE_TARNAME
|
|
||||||
|
|
||||||
/* Define to the home page for this package. */
|
|
||||||
#undef PACKAGE_URL
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#undef PACKAGE_VERSION
|
|
||||||
|
|
||||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
|
||||||
your system. */
|
|
||||||
#undef PTHREAD_CREATE_JOINABLE
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* the namespace where STL code like vector<> is defined */
|
|
||||||
#define STL_NAMESPACE std
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#undef VERSION
|
|
||||||
|
|
||||||
/* Stops putting the code inside the Google namespace */
|
|
||||||
#define _END_GOOGLE_NAMESPACE_ }
|
|
||||||
|
|
||||||
/* Puts following code inside the Google namespace */
|
|
||||||
#define _START_GOOGLE_NAMESPACE_ namespace google {
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
// Extra stuff not found in config.h.in
|
|
||||||
|
|
||||||
// This must be defined before the windows.h is included. It's needed
|
|
||||||
// for mutex.h, to give access to the TryLock method.
|
|
||||||
#ifndef _WIN32_WINNT
|
|
||||||
# define _WIN32_WINNT 0x0400
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO(csilvers): include windows/port.h in every relevant source file instead?
|
|
||||||
#include "windows/port.h"
|
|
||||||
|
|
||||||
#endif /* GOOGLE_GFLAGS_WINDOWS_CONFIG_H_ */
|
|
|
@ -1,78 +0,0 @@
|
||||||
# Copyright 2011 Google Inc.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
{
|
|
||||||
'variables': {
|
|
||||||
'gflags_root': '<(DEPTH)/third_party/gflags',
|
|
||||||
'conditions': [
|
|
||||||
['OS=="win"', {
|
|
||||||
'gflags_gen_arch_root': '<(gflags_root)/gen/win',
|
|
||||||
}, {
|
|
||||||
'gflags_gen_arch_root': '<(gflags_root)/gen/posix',
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'targets': [
|
|
||||||
{
|
|
||||||
'target_name': 'gflags',
|
|
||||||
'type': 'static_library',
|
|
||||||
'include_dirs': [
|
|
||||||
'<(gflags_gen_arch_root)/include/private', # For config.h
|
|
||||||
'<(gflags_gen_arch_root)/include', # For configured files.
|
|
||||||
'<(gflags_root)/src', # For everything else.
|
|
||||||
],
|
|
||||||
'defines': [
|
|
||||||
# These macros exist so flags and symbols are properly
|
|
||||||
# exported when building DLLs. Since we don't build DLLs, we
|
|
||||||
# need to disable them.
|
|
||||||
'GFLAGS_DLL_DECL=',
|
|
||||||
'GFLAGS_DLL_DECLARE_FLAG=',
|
|
||||||
'GFLAGS_DLL_DEFINE_FLAG=',
|
|
||||||
],
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'include_dirs': [
|
|
||||||
'<(gflags_gen_arch_root)/include', # For configured files.
|
|
||||||
'<(gflags_root)/src', # For everything else.
|
|
||||||
],
|
|
||||||
'defines': [
|
|
||||||
'GFLAGS_DLL_DECL=',
|
|
||||||
'GFLAGS_DLL_DECLARE_FLAG=',
|
|
||||||
'GFLAGS_DLL_DEFINE_FLAG=',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'sources': [
|
|
||||||
'src/gflags.cc',
|
|
||||||
'src/gflags_completions.cc',
|
|
||||||
'src/gflags_reporting.cc',
|
|
||||||
],
|
|
||||||
'conditions': [
|
|
||||||
['OS=="win"', {
|
|
||||||
'sources': [
|
|
||||||
'src/windows/port.cc',
|
|
||||||
],
|
|
||||||
# Suppress warnings about WIN32_LEAN_AND_MEAN and size_t truncation.
|
|
||||||
'msvs_disabled_warnings': [4005, 4267],
|
|
||||||
}],
|
|
||||||
# TODO(andrew): Look into fixing this warning upstream:
|
|
||||||
# http://code.google.com/p/webrtc/issues/detail?id=760
|
|
||||||
['clang==1', {
|
|
||||||
'cflags!': ['-Wheader-hygiene',],
|
|
||||||
'xcode_settings': {
|
|
||||||
'WARNING_CFLAGS!': ['-Wheader-hygiene',],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,106 +0,0 @@
|
||||||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
|
||||||
|
|
||||||
/* Always the empty-string on non-windows systems. On windows, should be
|
|
||||||
"__declspec(dllexport)". This way, when we compile the dll, we export our
|
|
||||||
functions/classes. It's safe to define this here because config.h is only
|
|
||||||
used internally, to compile the DLL, and every DLL source file #includes
|
|
||||||
"config.h" before anything else. */
|
|
||||||
#undef GFLAGS_DLL_DECL
|
|
||||||
|
|
||||||
/* Namespace for Google classes */
|
|
||||||
#undef GOOGLE_NAMESPACE
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#undef HAVE_DLFCN_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fnmatch.h> header file. */
|
|
||||||
#undef HAVE_FNMATCH_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#undef HAVE_INTTYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#undef HAVE_MEMORY_H
|
|
||||||
|
|
||||||
/* define if the compiler implements namespaces */
|
|
||||||
#undef HAVE_NAMESPACES
|
|
||||||
|
|
||||||
/* Define if you have POSIX threads libraries and header files. */
|
|
||||||
#undef HAVE_PTHREAD
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#undef HAVE_STDINT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#undef HAVE_STDLIB_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#undef HAVE_STRINGS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#undef HAVE_STRING_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoll' function. */
|
|
||||||
#undef HAVE_STRTOLL
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoq' function. */
|
|
||||||
#undef HAVE_STRTOQ
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#undef HAVE_SYS_STAT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#undef HAVE_SYS_TYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#undef HAVE_UNISTD_H
|
|
||||||
|
|
||||||
/* define if your compiler has __attribute__ */
|
|
||||||
#undef HAVE___ATTRIBUTE__
|
|
||||||
|
|
||||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
|
||||||
*/
|
|
||||||
#undef LT_OBJDIR
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#undef PACKAGE
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#undef PACKAGE_BUGREPORT
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#undef PACKAGE_NAME
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#undef PACKAGE_STRING
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#undef PACKAGE_TARNAME
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#undef PACKAGE_VERSION
|
|
||||||
|
|
||||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
|
||||||
your system. */
|
|
||||||
#undef PTHREAD_CREATE_JOINABLE
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#undef STDC_HEADERS
|
|
||||||
|
|
||||||
/* the namespace where STL code like vector<> is defined */
|
|
||||||
#undef STL_NAMESPACE
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#undef VERSION
|
|
||||||
|
|
||||||
/* Stops putting the code inside the Google namespace */
|
|
||||||
#undef _END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
/* Puts following code inside the Google namespace */
|
|
||||||
#undef _START_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
|
|
||||||
#if defined( __MINGW32__) || defined(__MINGW64__)
|
|
||||||
#include "windows/port.h"
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
// Copyright (c) 2007, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
// All Rights Reserved.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// This file is needed for windows -- unittests are not part of the
|
|
||||||
// gflags dll, but still want to include config.h just like the
|
|
||||||
// dll does, so they can use internal tools and APIs for testing.
|
|
||||||
//
|
|
||||||
// The problem is that config.h declares GFLAGS_DLL_DECL to be
|
|
||||||
// for exporting symbols, but the unittest needs to *import* symbols
|
|
||||||
// (since it's not the dll).
|
|
||||||
//
|
|
||||||
// The solution is to have this file, which is just like config.h but
|
|
||||||
// sets GFLAGS_DLL_DECL to do a dllimport instead of a dllexport.
|
|
||||||
//
|
|
||||||
// The reason we need this extra GFLAGS_DLL_DECL_FOR_UNITTESTS
|
|
||||||
// variable is in case people want to set GFLAGS_DLL_DECL explicitly
|
|
||||||
// to something other than __declspec(dllexport). In that case, they
|
|
||||||
// may want to use something other than __declspec(dllimport) for the
|
|
||||||
// unittest case. For that, we allow folks to define both
|
|
||||||
// GFLAGS_DLL_DECL and GFLAGS_DLL_DECL_FOR_UNITTESTS explicitly.
|
|
||||||
//
|
|
||||||
// NOTE: This file is equivalent to config.h on non-windows systems,
|
|
||||||
// which never defined GFLAGS_DLL_DECL_FOR_UNITTESTS and always
|
|
||||||
// define GFLAGS_DLL_DECL to the empty string.
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#undef GFLAGS_DLL_DECL
|
|
||||||
#ifdef GFLAGS_DLL_DECL_FOR_UNITTESTS
|
|
||||||
# define GFLAGS_DLL_DECL GFLAGS_DLL_DECL_FOR_UNITTESTS
|
|
||||||
#else
|
|
||||||
# define GFLAGS_DLL_DECL // if DLL_DECL_FOR_UNITTESTS isn't defined, use ""
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,570 +0,0 @@
|
||||||
// Copyright (c) 2006, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
// Revamped and reorganized by Craig Silverstein
|
|
||||||
//
|
|
||||||
// This is the file that should be included by any file which declares
|
|
||||||
// or defines a command line flag or wants to parse command line flags
|
|
||||||
// or print a program usage message (which will include information about
|
|
||||||
// flags). Executive summary, in the form of an example foo.cc file:
|
|
||||||
//
|
|
||||||
// #include "foo.h" // foo.h has a line "DECLARE_int32(start);"
|
|
||||||
// #include "validators.h" // hypothetical file defining ValidateIsFile()
|
|
||||||
//
|
|
||||||
// DEFINE_int32(end, 1000, "The last record to read");
|
|
||||||
//
|
|
||||||
// DEFINE_string(filename, "my_file.txt", "The file to read");
|
|
||||||
// // Crash if the specified file does not exist.
|
|
||||||
// static bool dummy = RegisterFlagValidator(&FLAGS_filename,
|
|
||||||
// &ValidateIsFile);
|
|
||||||
//
|
|
||||||
// DECLARE_bool(verbose); // some other file has a DEFINE_bool(verbose, ...)
|
|
||||||
//
|
|
||||||
// void MyFunc() {
|
|
||||||
// if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Then, at the command-line:
|
|
||||||
// ./foo --noverbose --start=5 --end=100
|
|
||||||
//
|
|
||||||
// For more details, see
|
|
||||||
// doc/gflags.html
|
|
||||||
//
|
|
||||||
// --- A note about thread-safety:
|
|
||||||
//
|
|
||||||
// We describe many functions in this routine as being thread-hostile,
|
|
||||||
// thread-compatible, or thread-safe. Here are the meanings we use:
|
|
||||||
//
|
|
||||||
// thread-safe: it is safe for multiple threads to call this routine
|
|
||||||
// (or, when referring to a class, methods of this class)
|
|
||||||
// concurrently.
|
|
||||||
// thread-hostile: it is not safe for multiple threads to call this
|
|
||||||
// routine (or methods of this class) concurrently. In gflags,
|
|
||||||
// most thread-hostile routines are intended to be called early in,
|
|
||||||
// or even before, main() -- that is, before threads are spawned.
|
|
||||||
// thread-compatible: it is safe for multiple threads to read from
|
|
||||||
// this variable (when applied to variables), or to call const
|
|
||||||
// methods of this class (when applied to classes), as long as no
|
|
||||||
// other thread is writing to the variable or calling non-const
|
|
||||||
// methods of this class.
|
|
||||||
|
|
||||||
#ifndef GFLAGS_GFLAGS_H_
|
|
||||||
#define GFLAGS_GFLAGS_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <gflags/gflags_declare.h> // IWYU pragma: export
|
|
||||||
@ac_google_start_namespace@
|
|
||||||
|
|
||||||
//
|
|
||||||
// NOTE: all functions below MUST have an explicit 'extern' before
|
|
||||||
// them. Our automated opensourcing tools use this as a signal to do
|
|
||||||
// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
|
|
||||||
//
|
|
||||||
#define GFLAGS_DLL_DECL /* rewritten to be non-empty in windows dir */
|
|
||||||
#define GFLAGS_DLL_DEFINE_FLAG /* rewritten to be non-empty in windows dir */
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// To actually define a flag in a file, use DEFINE_bool,
|
|
||||||
// DEFINE_string, etc. at the bottom of this file. You may also find
|
|
||||||
// it useful to register a validator with the flag. This ensures that
|
|
||||||
// when the flag is parsed from the commandline, or is later set via
|
|
||||||
// SetCommandLineOption, we call the validation function. It is _not_
|
|
||||||
// called when you assign the value to the flag directly using the = operator.
|
|
||||||
//
|
|
||||||
// The validation function should return true if the flag value is valid, and
|
|
||||||
// false otherwise. If the function returns false for the new setting of the
|
|
||||||
// flag, the flag will retain its current value. If it returns false for the
|
|
||||||
// default value, ParseCommandLineFlags() will die.
|
|
||||||
//
|
|
||||||
// This function is safe to call at global construct time (as in the
|
|
||||||
// example below).
|
|
||||||
//
|
|
||||||
// Example use:
|
|
||||||
// static bool ValidatePort(const char* flagname, int32 value) {
|
|
||||||
// if (value > 0 && value < 32768) // value is ok
|
|
||||||
// return true;
|
|
||||||
// printf("Invalid value for --%s: %d\n", flagname, (int)value);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// DEFINE_int32(port, 0, "What port to listen on");
|
|
||||||
// static bool dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort);
|
|
||||||
|
|
||||||
// Returns true if successfully registered, false if not (because the
|
|
||||||
// first argument doesn't point to a command-line flag, or because a
|
|
||||||
// validator is already registered for this flag).
|
|
||||||
extern bool RegisterFlagValidator(const bool* flag,
|
|
||||||
bool (*validate_fn)(const char*, bool));
|
|
||||||
extern bool RegisterFlagValidator(const int32* flag,
|
|
||||||
bool (*validate_fn)(const char*, int32));
|
|
||||||
extern bool RegisterFlagValidator(const int64* flag,
|
|
||||||
bool (*validate_fn)(const char*, int64));
|
|
||||||
extern bool RegisterFlagValidator(const uint64* flag,
|
|
||||||
bool (*validate_fn)(const char*, uint64));
|
|
||||||
extern bool RegisterFlagValidator(const double* flag,
|
|
||||||
bool (*validate_fn)(const char*, double));
|
|
||||||
extern bool RegisterFlagValidator(const std::string* flag,
|
|
||||||
bool (*validate_fn)(const char*,
|
|
||||||
const std::string&));
|
|
||||||
|
|
||||||
// Convenience macro for the registration of a flag validator
|
|
||||||
#define DEFINE_validator(name, validator) \
|
|
||||||
static const bool name##_validator_registered = \
|
|
||||||
@ac_google_namespace@::RegisterFlagValidator(&FLAGS_##name, validator)
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// These methods are the best way to get access to info about the
|
|
||||||
// list of commandline flags. Note that these routines are pretty slow.
|
|
||||||
// GetAllFlags: mostly-complete info about the list, sorted by file.
|
|
||||||
// ShowUsageWithFlags: pretty-prints the list to stdout (what --help does)
|
|
||||||
// ShowUsageWithFlagsRestrict: limit to filenames with restrict as a substr
|
|
||||||
//
|
|
||||||
// In addition to accessing flags, you can also access argv[0] (the program
|
|
||||||
// name) and argv (the entire commandline), which we sock away a copy of.
|
|
||||||
// These variables are static, so you should only set them once.
|
|
||||||
|
|
||||||
struct GFLAGS_DLL_DECL CommandLineFlagInfo {
|
|
||||||
std::string name; // the name of the flag
|
|
||||||
std::string type; // the type of the flag: int32, etc
|
|
||||||
std::string description; // the "help text" associated with the flag
|
|
||||||
std::string current_value; // the current value, as a string
|
|
||||||
std::string default_value; // the default value, as a string
|
|
||||||
std::string filename; // 'cleaned' version of filename holding the flag
|
|
||||||
bool has_validator_fn; // true if RegisterFlagValidator called on this flag
|
|
||||||
bool is_default; // true if the flag has the default value and
|
|
||||||
// has not been set explicitly from the cmdline
|
|
||||||
// or via SetCommandLineOption
|
|
||||||
const void* flag_ptr; // pointer to the flag's current value (i.e. FLAGS_foo)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Using this inside of a validator is a recipe for a deadlock.
|
|
||||||
// TODO(user) Fix locking when validators are running, to make it safe to
|
|
||||||
// call validators during ParseAllFlags.
|
|
||||||
// Also make sure then to uncomment the corresponding unit test in
|
|
||||||
// gflags_unittest.sh
|
|
||||||
extern void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
|
|
||||||
// These two are actually defined in gflags_reporting.cc.
|
|
||||||
extern void ShowUsageWithFlags(const char *argv0); // what --help does
|
|
||||||
extern void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
|
|
||||||
|
|
||||||
// Create a descriptive string for a flag.
|
|
||||||
// Goes to some trouble to make pretty line breaks.
|
|
||||||
extern std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
|
|
||||||
|
|
||||||
// Thread-hostile; meant to be called before any threads are spawned.
|
|
||||||
extern void SetArgv(int argc, const char** argv);
|
|
||||||
|
|
||||||
// The following functions are thread-safe as long as SetArgv() is
|
|
||||||
// only called before any threads start.
|
|
||||||
extern const std::vector<std::string>& GetArgvs();
|
|
||||||
extern const char* GetArgv(); // all of argv as a string
|
|
||||||
extern const char* GetArgv0(); // only argv0
|
|
||||||
extern uint32 GetArgvSum(); // simple checksum of argv
|
|
||||||
extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
|
|
||||||
extern const char* ProgramInvocationShortName(); // basename(argv0)
|
|
||||||
|
|
||||||
// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
|
|
||||||
// called before any threads start.
|
|
||||||
extern const char* ProgramUsage(); // string set by SetUsageMessage()
|
|
||||||
|
|
||||||
// VersionString() is thread-safe as long as SetVersionString() is only
|
|
||||||
// called before any threads start.
|
|
||||||
extern const char* VersionString(); // string set by SetVersionString()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Normally you access commandline flags by just saying "if (FLAGS_foo)"
|
|
||||||
// or whatever, and set them by calling "FLAGS_foo = bar" (or, more
|
|
||||||
// commonly, via the DEFINE_foo macro). But if you need a bit more
|
|
||||||
// control, we have programmatic ways to get/set the flags as well.
|
|
||||||
// These programmatic ways to access flags are thread-safe, but direct
|
|
||||||
// access is only thread-compatible.
|
|
||||||
|
|
||||||
// Return true iff the flagname was found.
|
|
||||||
// OUTPUT is set to the flag's value, or unchanged if we return false.
|
|
||||||
extern bool GetCommandLineOption(const char* name, std::string* OUTPUT);
|
|
||||||
|
|
||||||
// Return true iff the flagname was found. OUTPUT is set to the flag's
|
|
||||||
// CommandLineFlagInfo or unchanged if we return false.
|
|
||||||
extern bool GetCommandLineFlagInfo(const char* name,
|
|
||||||
CommandLineFlagInfo* OUTPUT);
|
|
||||||
|
|
||||||
// Return the CommandLineFlagInfo of the flagname. exit() if name not found.
|
|
||||||
// Example usage, to check if a flag's value is currently the default value:
|
|
||||||
// if (GetCommandLineFlagInfoOrDie("foo").is_default) ...
|
|
||||||
extern CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
|
|
||||||
|
|
||||||
enum GFLAGS_DLL_DECL FlagSettingMode {
|
|
||||||
// update the flag's value (can call this multiple times).
|
|
||||||
SET_FLAGS_VALUE,
|
|
||||||
// update the flag's value, but *only if* it has not yet been updated
|
|
||||||
// with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
|
|
||||||
SET_FLAG_IF_DEFAULT,
|
|
||||||
// set the flag's default value to this. If the flag has not yet updated
|
|
||||||
// yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
|
|
||||||
// change the flag's current value to the new default value as well.
|
|
||||||
SET_FLAGS_DEFAULT
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set a particular flag ("command line option"). Returns a string
|
|
||||||
// describing the new value that the option has been set to. The
|
|
||||||
// return value API is not well-specified, so basically just depend on
|
|
||||||
// it to be empty if the setting failed for some reason -- the name is
|
|
||||||
// not a valid flag name, or the value is not a valid value -- and
|
|
||||||
// non-empty else.
|
|
||||||
|
|
||||||
// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
|
|
||||||
extern std::string SetCommandLineOption(const char* name, const char* value);
|
|
||||||
extern std::string SetCommandLineOptionWithMode(const char* name, const char* value,
|
|
||||||
FlagSettingMode set_mode);
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Saves the states (value, default value, whether the user has set
|
|
||||||
// the flag, registered validators, etc) of all flags, and restores
|
|
||||||
// them when the FlagSaver is destroyed. This is very useful in
|
|
||||||
// tests, say, when you want to let your tests change the flags, but
|
|
||||||
// make sure that they get reverted to the original states when your
|
|
||||||
// test is complete.
|
|
||||||
//
|
|
||||||
// Example usage:
|
|
||||||
// void TestFoo() {
|
|
||||||
// FlagSaver s1;
|
|
||||||
// FLAG_foo = false;
|
|
||||||
// FLAG_bar = "some value";
|
|
||||||
//
|
|
||||||
// // test happens here. You can return at any time
|
|
||||||
// // without worrying about restoring the FLAG values.
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Note: This class is marked with ATTRIBUTE_UNUSED because all the
|
|
||||||
// work is done in the constructor and destructor, so in the standard
|
|
||||||
// usage example above, the compiler would complain that it's an
|
|
||||||
// unused variable.
|
|
||||||
//
|
|
||||||
// This class is thread-safe. However, its destructor writes to
|
|
||||||
// exactly the set of flags that have changed value during its
|
|
||||||
// lifetime, so concurrent _direct_ access to those flags
|
|
||||||
// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe.
|
|
||||||
|
|
||||||
class GFLAGS_DLL_DECL FlagSaver {
|
|
||||||
public:
|
|
||||||
FlagSaver();
|
|
||||||
~FlagSaver();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class FlagSaverImpl* impl_; // we use pimpl here to keep API steady
|
|
||||||
|
|
||||||
FlagSaver(const FlagSaver&); // no copying!
|
|
||||||
void operator=(const FlagSaver&);
|
|
||||||
}
|
|
||||||
@ac_cv___attribute__unused@;
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Some deprecated or hopefully-soon-to-be-deprecated functions.
|
|
||||||
|
|
||||||
// This is often used for logging. TODO(csilvers): figure out a better way
|
|
||||||
extern std::string CommandlineFlagsIntoString();
|
|
||||||
// Usually where this is used, a FlagSaver should be used instead.
|
|
||||||
extern bool ReadFlagsFromString(const std::string& flagfilecontents,
|
|
||||||
const char* prog_name,
|
|
||||||
bool errors_are_fatal); // uses SET_FLAGS_VALUE
|
|
||||||
|
|
||||||
// These let you manually implement --flagfile functionality.
|
|
||||||
// DEPRECATED.
|
|
||||||
extern bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
|
|
||||||
extern bool ReadFromFlagsFile(const std::string& filename, const char* prog_name,
|
|
||||||
bool errors_are_fatal); // uses SET_FLAGS_VALUE
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Useful routines for initializing flags from the environment.
|
|
||||||
// In each case, if 'varname' does not exist in the environment
|
|
||||||
// return defval. If 'varname' does exist but is not valid
|
|
||||||
// (e.g., not a number for an int32 flag), abort with an error.
|
|
||||||
// Otherwise, return the value. NOTE: for booleans, for true use
|
|
||||||
// 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'.
|
|
||||||
|
|
||||||
extern bool BoolFromEnv(const char *varname, bool defval);
|
|
||||||
extern int32 Int32FromEnv(const char *varname, int32 defval);
|
|
||||||
extern int64 Int64FromEnv(const char *varname, int64 defval);
|
|
||||||
extern uint64 Uint64FromEnv(const char *varname, uint64 defval);
|
|
||||||
extern double DoubleFromEnv(const char *varname, double defval);
|
|
||||||
extern const char *StringFromEnv(const char *varname, const char *defval);
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// The next two functions parse gflags from main():
|
|
||||||
|
|
||||||
// Set the "usage" message for this program. For example:
|
|
||||||
// string usage("This program does nothing. Sample usage:\n");
|
|
||||||
// usage += argv[0] + " <uselessarg1> <uselessarg2>";
|
|
||||||
// SetUsageMessage(usage);
|
|
||||||
// Do not include commandline flags in the usage: we do that for you!
|
|
||||||
// Thread-hostile; meant to be called before any threads are spawned.
|
|
||||||
extern void SetUsageMessage(const std::string& usage);
|
|
||||||
|
|
||||||
// Sets the version string, which is emitted with --version.
|
|
||||||
// For instance: SetVersionString("1.3");
|
|
||||||
// Thread-hostile; meant to be called before any threads are spawned.
|
|
||||||
extern void SetVersionString(const std::string& version);
|
|
||||||
|
|
||||||
|
|
||||||
// Looks for flags in argv and parses them. Rearranges argv to put
|
|
||||||
// flags first, or removes them entirely if remove_flags is true.
|
|
||||||
// If a flag is defined more than once in the command line or flag
|
|
||||||
// file, the last definition is used. Returns the index (into argv)
|
|
||||||
// of the first non-flag argument.
|
|
||||||
// See top-of-file for more details on this function.
|
|
||||||
#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead.
|
|
||||||
extern uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Calls to ParseCommandLineNonHelpFlags and then to
|
|
||||||
// HandleCommandLineHelpFlags can be used instead of a call to
|
|
||||||
// ParseCommandLineFlags during initialization, in order to allow for
|
|
||||||
// changing default values for some FLAGS (via
|
|
||||||
// e.g. SetCommandLineOptionWithMode calls) between the time of
|
|
||||||
// command line parsing and the time of dumping help information for
|
|
||||||
// the flags as a result of command line parsing. If a flag is
|
|
||||||
// defined more than once in the command line or flag file, the last
|
|
||||||
// definition is used. Returns the index (into argv) of the first
|
|
||||||
// non-flag argument. (If remove_flags is true, will always return 1.)
|
|
||||||
extern uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv,
|
|
||||||
bool remove_flags);
|
|
||||||
// This is actually defined in gflags_reporting.cc.
|
|
||||||
// This function is misnamed (it also handles --version, etc.), but
|
|
||||||
// it's too late to change that now. :-(
|
|
||||||
extern void HandleCommandLineHelpFlags(); // in gflags_reporting.cc
|
|
||||||
|
|
||||||
// Allow command line reparsing. Disables the error normally
|
|
||||||
// generated when an unknown flag is found, since it may be found in a
|
|
||||||
// later parse. Thread-hostile; meant to be called before any threads
|
|
||||||
// are spawned.
|
|
||||||
extern void AllowCommandLineReparsing();
|
|
||||||
|
|
||||||
// Reparse the flags that have not yet been recognized. Only flags
|
|
||||||
// registered since the last parse will be recognized. Any flag value
|
|
||||||
// must be provided as part of the argument using "=", not as a
|
|
||||||
// separate command line argument that follows the flag argument.
|
|
||||||
// Intended for handling flags from dynamically loaded libraries,
|
|
||||||
// since their flags are not registered until they are loaded.
|
|
||||||
extern void ReparseCommandLineNonHelpFlags();
|
|
||||||
|
|
||||||
// Clean up memory allocated by flags. This is only needed to reduce
|
|
||||||
// the quantity of "potentially leaked" reports emitted by memory
|
|
||||||
// debugging tools such as valgrind. It is not required for normal
|
|
||||||
// operation, or for the google perftools heap-checker. It must only
|
|
||||||
// be called when the process is about to exit, and all threads that
|
|
||||||
// might access flags are quiescent. Referencing flags after this is
|
|
||||||
// called will have unexpected consequences. This is not safe to run
|
|
||||||
// when multiple threads might be running: the function is
|
|
||||||
// thread-hostile.
|
|
||||||
extern void ShutDownCommandLineFlags();
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Now come the command line flag declaration/definition macros that
|
|
||||||
// will actually be used. They're kind of hairy. A major reason
|
|
||||||
// for this is initialization: we want people to be able to access
|
|
||||||
// variables in global constructors and have that not crash, even if
|
|
||||||
// their global constructor runs before the global constructor here.
|
|
||||||
// (Obviously, we can't guarantee the flags will have the correct
|
|
||||||
// default value in that case, but at least accessing them is safe.)
|
|
||||||
// The only way to do that is have flags point to a static buffer.
|
|
||||||
// So we make one, using a union to ensure proper alignment, and
|
|
||||||
// then use placement-new to actually set up the flag with the
|
|
||||||
// correct default value. In the same vein, we have to worry about
|
|
||||||
// flag access in global destructors, so FlagRegisterer has to be
|
|
||||||
// careful never to destroy the flag-values it constructs.
|
|
||||||
//
|
|
||||||
// Note that when we define a flag variable FLAGS_<name>, we also
|
|
||||||
// preemptively define a junk variable, FLAGS_no<name>. This is to
|
|
||||||
// cause a link-time error if someone tries to define 2 flags with
|
|
||||||
// names like "logging" and "nologging". We do this because a bool
|
|
||||||
// flag FLAG can be set from the command line to true with a "-FLAG"
|
|
||||||
// argument, and to false with a "-noFLAG" argument, and so this can
|
|
||||||
// potentially avert confusion.
|
|
||||||
//
|
|
||||||
// We also put flags into their own namespace. It is purposefully
|
|
||||||
// named in an opaque way that people should have trouble typing
|
|
||||||
// directly. The idea is that DEFINE puts the flag in the weird
|
|
||||||
// namespace, and DECLARE imports the flag from there into the current
|
|
||||||
// namespace. The net result is to force people to use DECLARE to get
|
|
||||||
// access to a flag, rather than saying "extern bool FLAGS_whatever;"
|
|
||||||
// or some such instead. We want this so we can put extra
|
|
||||||
// functionality (like sanity-checking) in DECLARE if we want, and
|
|
||||||
// make sure it is picked up everywhere.
|
|
||||||
//
|
|
||||||
// We also put the type of the variable in the namespace, so that
|
|
||||||
// people can't DECLARE_int32 something that they DEFINE_bool'd
|
|
||||||
// elsewhere.
|
|
||||||
|
|
||||||
class GFLAGS_DLL_DECL FlagRegisterer {
|
|
||||||
public:
|
|
||||||
FlagRegisterer(const char* name, const char* type,
|
|
||||||
const char* help, const char* filename,
|
|
||||||
void* current_storage, void* defvalue_storage);
|
|
||||||
};
|
|
||||||
|
|
||||||
// If your application #defines STRIP_FLAG_HELP to a non-zero value
|
|
||||||
// before #including this file, we remove the help message from the
|
|
||||||
// binary file. This can reduce the size of the resulting binary
|
|
||||||
// somewhat, and may also be useful for security reasons.
|
|
||||||
|
|
||||||
extern const char kStrippedFlagHelp[];
|
|
||||||
|
|
||||||
@ac_google_end_namespace@
|
|
||||||
|
|
||||||
#ifndef SWIG // In swig, ignore the main flag declarations
|
|
||||||
|
|
||||||
#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
|
|
||||||
// Need this construct to avoid the 'defined but not used' warning.
|
|
||||||
#define MAYBE_STRIPPED_HELP(txt) \
|
|
||||||
(false ? (txt) : @ac_google_namespace@::kStrippedFlagHelp)
|
|
||||||
#else
|
|
||||||
#define MAYBE_STRIPPED_HELP(txt) txt
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Each command-line flag has two variables associated with it: one
|
|
||||||
// with the current value, and one with the default value. However,
|
|
||||||
// we have a third variable, which is where value is assigned; it's a
|
|
||||||
// constant. This guarantees that FLAG_##value is initialized at
|
|
||||||
// static initialization time (e.g. before program-start) rather than
|
|
||||||
// than global construction time (which is after program-start but
|
|
||||||
// before main), at least when 'value' is a compile-time constant. We
|
|
||||||
// use a small trick for the "default value" variable, and call it
|
|
||||||
// FLAGS_no<name>. This serves the second purpose of assuring a
|
|
||||||
// compile error if someone tries to define a flag named no<name>
|
|
||||||
// which is illegal (--foo and --nofoo both affect the "foo" flag).
|
|
||||||
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
|
|
||||||
namespace fL##shorttype { \
|
|
||||||
static const type FLAGS_nono##name = value; \
|
|
||||||
/* We always want to export defined variables, dll or no */ \
|
|
||||||
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
|
|
||||||
type FLAGS_no##name = FLAGS_nono##name; \
|
|
||||||
static @ac_google_namespace@::FlagRegisterer o_##name( \
|
|
||||||
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
|
|
||||||
&FLAGS_##name, &FLAGS_no##name); \
|
|
||||||
} \
|
|
||||||
using fL##shorttype::FLAGS_##name
|
|
||||||
|
|
||||||
// For DEFINE_bool, we want to do the extra check that the passed-in
|
|
||||||
// value is actually a bool, and not a string or something that can be
|
|
||||||
// coerced to a bool. These declarations (no definition needed!) will
|
|
||||||
// help us do that, and never evaluate From, which is important.
|
|
||||||
// We'll use 'sizeof(IsBool(val))' to distinguish. This code requires
|
|
||||||
// that the compiler have different sizes for bool & double. Since
|
|
||||||
// this is not guaranteed by the standard, we check it with a
|
|
||||||
// COMPILE_ASSERT.
|
|
||||||
namespace fLB {
|
|
||||||
struct CompileAssert {};
|
|
||||||
typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[
|
|
||||||
(sizeof(double) != sizeof(bool)) ? 1 : -1];
|
|
||||||
template<typename From> double GFLAGS_DLL_DECL IsBoolFlag(const From& from);
|
|
||||||
GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
|
|
||||||
} // namespace fLB
|
|
||||||
|
|
||||||
// Here are the actual DEFINE_*-macros. The respective DECLARE_*-macros
|
|
||||||
// are in a separate include, gflags_declare.h, for reducing
|
|
||||||
// the physical transitive size for DECLARE use.
|
|
||||||
#define DEFINE_bool(name, val, txt) \
|
|
||||||
namespace fLB { \
|
|
||||||
typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \
|
|
||||||
(sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \
|
|
||||||
} \
|
|
||||||
DEFINE_VARIABLE(bool, B, name, val, txt)
|
|
||||||
|
|
||||||
#define DEFINE_int32(name, val, txt) \
|
|
||||||
DEFINE_VARIABLE(@ac_google_namespace@::int32, I, \
|
|
||||||
name, val, txt)
|
|
||||||
|
|
||||||
#define DEFINE_int64(name, val, txt) \
|
|
||||||
DEFINE_VARIABLE(@ac_google_namespace@::int64, I64, \
|
|
||||||
name, val, txt)
|
|
||||||
|
|
||||||
#define DEFINE_uint64(name,val, txt) \
|
|
||||||
DEFINE_VARIABLE(@ac_google_namespace@::uint64, U64, \
|
|
||||||
name, val, txt)
|
|
||||||
|
|
||||||
#define DEFINE_double(name, val, txt) \
|
|
||||||
DEFINE_VARIABLE(double, D, name, val, txt)
|
|
||||||
|
|
||||||
// Strings are trickier, because they're not a POD, so we can't
|
|
||||||
// construct them at static-initialization time (instead they get
|
|
||||||
// constructed at global-constructor time, which is much later). To
|
|
||||||
// try to avoid crashes in that case, we use a char buffer to store
|
|
||||||
// the string, which we can static-initialize, and then placement-new
|
|
||||||
// into it later. It's not perfect, but the best we can do.
|
|
||||||
|
|
||||||
namespace fLS {
|
|
||||||
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
const char *value) {
|
|
||||||
return new(stringspot) clstring(value);
|
|
||||||
}
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
const clstring &value) {
|
|
||||||
return new(stringspot) clstring(value);
|
|
||||||
}
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
int value);
|
|
||||||
} // namespace fLS
|
|
||||||
|
|
||||||
// We need to define a var named FLAGS_no##name so people don't define
|
|
||||||
// --string and --nostring. And we need a temporary place to put val
|
|
||||||
// so we don't have to evaluate it twice. Two great needs that go
|
|
||||||
// great together!
|
|
||||||
// The weird 'using' + 'extern' inside the fLS namespace is to work around
|
|
||||||
// an unknown compiler bug/issue with the gcc 4.2.1 on SUSE 10. See
|
|
||||||
// http://code.google.com/p/google-gflags/issues/detail?id=20
|
|
||||||
#define DEFINE_string(name, val, txt) \
|
|
||||||
namespace fLS { \
|
|
||||||
using ::fLS::clstring; \
|
|
||||||
static union { void* align; char s[sizeof(clstring)]; } s_##name[2]; \
|
|
||||||
clstring* const FLAGS_no##name = ::fLS:: \
|
|
||||||
dont_pass0toDEFINE_string(s_##name[0].s, \
|
|
||||||
val); \
|
|
||||||
static @ac_google_namespace@::FlagRegisterer o_##name( \
|
|
||||||
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
|
|
||||||
s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
|
|
||||||
extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \
|
|
||||||
using fLS::FLAGS_##name; \
|
|
||||||
clstring& FLAGS_##name = *FLAGS_no##name; \
|
|
||||||
} \
|
|
||||||
using fLS::FLAGS_##name
|
|
||||||
|
|
||||||
#endif // SWIG
|
|
||||||
|
|
||||||
#endif // GFLAGS_GFLAGS_H_
|
|
|
@ -1,130 +0,0 @@
|
||||||
// Copyright (c) 2008, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// ---
|
|
||||||
|
|
||||||
//
|
|
||||||
// Implement helpful bash-style command line flag completions
|
|
||||||
//
|
|
||||||
// ** Functional API:
|
|
||||||
// HandleCommandLineCompletions() should be called early during
|
|
||||||
// program startup, but after command line flag code has been
|
|
||||||
// initialized, such as the beginning of HandleCommandLineHelpFlags().
|
|
||||||
// It checks the value of the flag --tab_completion_word. If this
|
|
||||||
// flag is empty, nothing happens here. If it contains a string,
|
|
||||||
// however, then HandleCommandLineCompletions() will hijack the
|
|
||||||
// process, attempting to identify the intention behind this
|
|
||||||
// completion. Regardless of the outcome of this deduction, the
|
|
||||||
// process will be terminated, similar to --helpshort flag
|
|
||||||
// handling.
|
|
||||||
//
|
|
||||||
// ** Overview of Bash completions:
|
|
||||||
// Bash can be told to programatically determine completions for the
|
|
||||||
// current 'cursor word'. It does this by (in this case) invoking a
|
|
||||||
// command with some additional arguments identifying the command
|
|
||||||
// being executed, the word being completed, and the previous word
|
|
||||||
// (if any). Bash then expects a sequence of output lines to be
|
|
||||||
// printed to stdout. If these lines all contain a common prefix
|
|
||||||
// longer than the cursor word, bash will replace the cursor word
|
|
||||||
// with that common prefix, and display nothing. If there isn't such
|
|
||||||
// a common prefix, bash will display the lines in pages using 'more'.
|
|
||||||
//
|
|
||||||
// ** Strategy taken for command line completions:
|
|
||||||
// If we can deduce either the exact flag intended, or a common flag
|
|
||||||
// prefix, we'll output exactly that. Otherwise, if information
|
|
||||||
// must be displayed to the user, we'll take the opportunity to add
|
|
||||||
// some helpful information beyond just the flag name (specifically,
|
|
||||||
// we'll include the default flag value and as much of the flag's
|
|
||||||
// description as can fit on a single terminal line width, as specified
|
|
||||||
// by the flag --tab_completion_columns). Furthermore, we'll try to
|
|
||||||
// make bash order the output such that the most useful or relevent
|
|
||||||
// flags are the most likely to be shown at the top.
|
|
||||||
//
|
|
||||||
// ** Additional features:
|
|
||||||
// To assist in finding that one really useful flag, substring matching
|
|
||||||
// was implemented. Before pressing a <TAB> to get completion for the
|
|
||||||
// current word, you can append one or more '?' to the flag to do
|
|
||||||
// substring matching. Here's the semantics:
|
|
||||||
// --foo<TAB> Show me all flags with names prefixed by 'foo'
|
|
||||||
// --foo?<TAB> Show me all flags with 'foo' somewhere in the name
|
|
||||||
// --foo??<TAB> Same as prior case, but also search in module
|
|
||||||
// definition path for 'foo'
|
|
||||||
// --foo???<TAB> Same as prior case, but also search in flag
|
|
||||||
// descriptions for 'foo'
|
|
||||||
// Finally, we'll trim the output to a relatively small number of
|
|
||||||
// flags to keep bash quiet about the verbosity of output. If one
|
|
||||||
// really wanted to see all possible matches, appending a '+' to the
|
|
||||||
// search word will force the exhaustive list of matches to be printed.
|
|
||||||
//
|
|
||||||
// ** How to have bash accept completions from a binary:
|
|
||||||
// Bash requires that it be informed about each command that programmatic
|
|
||||||
// completion should be enabled for. Example addition to a .bashrc
|
|
||||||
// file would be (your path to gflags_completions.sh file may differ):
|
|
||||||
|
|
||||||
/*
|
|
||||||
$ complete -o bashdefault -o default -o nospace -C \
|
|
||||||
'/home/build/eng/bash/bash_completions.sh --tab_completion_columns $COLUMNS' \
|
|
||||||
time env binary_name another_binary [...]
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This would allow the following to work:
|
|
||||||
// $ /path/to/binary_name --vmodule<TAB>
|
|
||||||
// Or:
|
|
||||||
// $ ./bin/path/another_binary --gfs_u<TAB>
|
|
||||||
// (etc)
|
|
||||||
//
|
|
||||||
// Sadly, it appears that bash gives no easy way to force this behavior for
|
|
||||||
// all commands. That's where the "time" in the above example comes in.
|
|
||||||
// If you haven't specifically added a command to the list of completion
|
|
||||||
// supported commands, you can still get completions by prefixing the
|
|
||||||
// entire command with "env".
|
|
||||||
// $ env /some/brand/new/binary --vmod<TAB>
|
|
||||||
// Assuming that "binary" is a newly compiled binary, this should still
|
|
||||||
// produce the expected completion output.
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef GFLAGS_COMPLETIONS_H_
|
|
||||||
#define GFLAGS_COMPLETIONS_H_
|
|
||||||
|
|
||||||
// Annoying stuff for windows -- makes sure clients can import these functions
|
|
||||||
//
|
|
||||||
// NOTE: all functions below MUST have an explicit 'extern' before
|
|
||||||
// them. Our automated opensourcing tools use this as a signal to do
|
|
||||||
// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
|
|
||||||
//
|
|
||||||
#define GFLAGS_DLL_DECL /* rewritten to be non-empty in windows dir */
|
|
||||||
|
|
||||||
|
|
||||||
@ac_google_start_namespace@
|
|
||||||
|
|
||||||
extern void HandleCommandLineCompletions(void);
|
|
||||||
|
|
||||||
@ac_google_end_namespace@
|
|
||||||
|
|
||||||
#endif // GFLAGS_COMPLETIONS_H_
|
|
|
@ -1,112 +0,0 @@
|
||||||
// Copyright (c) 1999, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
//
|
|
||||||
// Revamped and reorganized by Craig Silverstein
|
|
||||||
//
|
|
||||||
// This is the file that should be included by any file which declares
|
|
||||||
// command line flag.
|
|
||||||
|
|
||||||
#ifndef GFLAGS_DECLARE_H_
|
|
||||||
#define GFLAGS_DECLARE_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#if @ac_cv_have_stdint_h@
|
|
||||||
#include <stdint.h> // the normal place uint16_t is defined
|
|
||||||
#endif
|
|
||||||
#if @ac_cv_have_systypes_h@
|
|
||||||
#include <sys/types.h> // the normal place u_int16_t is defined
|
|
||||||
#endif
|
|
||||||
#if @ac_cv_have_inttypes_h@
|
|
||||||
#include <inttypes.h> // a third place for uint16_t or u_int16_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@ac_google_start_namespace@
|
|
||||||
#if @ac_cv_have_uint16_t@ // the C99 format
|
|
||||||
typedef int32_t int32;
|
|
||||||
typedef uint32_t uint32;
|
|
||||||
typedef int64_t int64;
|
|
||||||
typedef uint64_t uint64;
|
|
||||||
#elif @ac_cv_have_u_int16_t@ // the BSD format
|
|
||||||
typedef int32_t int32;
|
|
||||||
typedef u_int32_t uint32;
|
|
||||||
typedef int64_t int64;
|
|
||||||
typedef u_int64_t uint64;
|
|
||||||
#elif @ac_cv_have___int16@ // the windows (vc7) format
|
|
||||||
typedef __int32 int32;
|
|
||||||
typedef unsigned __int32 uint32;
|
|
||||||
typedef __int64 int64;
|
|
||||||
typedef unsigned __int64 uint64;
|
|
||||||
#else
|
|
||||||
#error Do not know how to define a 32-bit integer quantity on your system
|
|
||||||
#endif
|
|
||||||
@ac_google_end_namespace@
|
|
||||||
|
|
||||||
|
|
||||||
#define GFLAGS_DLL_DECLARE_FLAG /* rewritten to be non-empty in windows dir */
|
|
||||||
|
|
||||||
namespace fLS {
|
|
||||||
|
|
||||||
// The meaning of "string" might be different between now and when the
|
|
||||||
// macros below get invoked (e.g., if someone is experimenting with
|
|
||||||
// other string implementations that get defined after this file is
|
|
||||||
// included). Save the current meaning now and use it in the macros.
|
|
||||||
typedef std::string clstring;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DECLARE_VARIABLE(type, shorttype, name) \
|
|
||||||
/* We always want to import declared variables, dll or no */ \
|
|
||||||
namespace fL##shorttype { extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; } \
|
|
||||||
using fL##shorttype::FLAGS_##name
|
|
||||||
|
|
||||||
#define DECLARE_bool(name) \
|
|
||||||
DECLARE_VARIABLE(bool, B, name)
|
|
||||||
|
|
||||||
#define DECLARE_int32(name) \
|
|
||||||
DECLARE_VARIABLE(@ac_google_namespace@::int32, I, name)
|
|
||||||
|
|
||||||
#define DECLARE_int64(name) \
|
|
||||||
DECLARE_VARIABLE(@ac_google_namespace@::int64, I64, name)
|
|
||||||
|
|
||||||
#define DECLARE_uint64(name) \
|
|
||||||
DECLARE_VARIABLE(@ac_google_namespace@::uint64, U64, name)
|
|
||||||
|
|
||||||
#define DECLARE_double(name) \
|
|
||||||
DECLARE_VARIABLE(double, D, name)
|
|
||||||
|
|
||||||
#define DECLARE_string(name) \
|
|
||||||
namespace fLS { \
|
|
||||||
using ::fLS::clstring; \
|
|
||||||
extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \
|
|
||||||
} \
|
|
||||||
using fLS::FLAGS_##name
|
|
||||||
|
|
||||||
#endif // GFLAGS_DECLARE_H_
|
|
|
@ -1,768 +0,0 @@
|
||||||
// Copyright (c) 2008, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// ---
|
|
||||||
|
|
||||||
// Bash-style command line flag completion for C++ binaries
|
|
||||||
//
|
|
||||||
// This module implements bash-style completions. It achieves this
|
|
||||||
// goal in the following broad chunks:
|
|
||||||
//
|
|
||||||
// 1) Take a to-be-completed word, and examine it for search hints
|
|
||||||
// 2) Identify all potentially matching flags
|
|
||||||
// 2a) If there are no matching flags, do nothing.
|
|
||||||
// 2b) If all matching flags share a common prefix longer than the
|
|
||||||
// completion word, output just that matching prefix
|
|
||||||
// 3) Categorize those flags to produce a rough ordering of relevence.
|
|
||||||
// 4) Potentially trim the set of flags returned to a smaller number
|
|
||||||
// that bash is happier with
|
|
||||||
// 5) Output the matching flags in groups ordered by relevence.
|
|
||||||
// 5a) Force bash to place most-relevent groups at the top of the list
|
|
||||||
// 5b) Trim most flag's descriptions to fit on a single terminal line
|
|
||||||
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h> // for strlen
|
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
using std::set;
|
|
||||||
using std::string;
|
|
||||||
using std::vector;
|
|
||||||
|
|
||||||
#ifndef PATH_SEPARATOR
|
|
||||||
#define PATH_SEPARATOR '/'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DEFINE_string(tab_completion_word, "",
|
|
||||||
"If non-empty, HandleCommandLineCompletions() will hijack the "
|
|
||||||
"process and attempt to do bash-style command line flag "
|
|
||||||
"completion on this value.");
|
|
||||||
DEFINE_int32(tab_completion_columns, 80,
|
|
||||||
"Number of columns to use in output for tab completion");
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
// Function prototypes and Type forward declarations. Code may be
|
|
||||||
// more easily understood if it is roughly ordered according to
|
|
||||||
// control flow, rather than by C's "declare before use" ordering
|
|
||||||
struct CompletionOptions;
|
|
||||||
struct NotableFlags;
|
|
||||||
|
|
||||||
// The entry point if flag completion is to be used.
|
|
||||||
static void PrintFlagCompletionInfo(void);
|
|
||||||
|
|
||||||
|
|
||||||
// 1) Examine search word
|
|
||||||
static void CanonicalizeCursorWordAndSearchOptions(
|
|
||||||
const string &cursor_word,
|
|
||||||
string *canonical_search_token,
|
|
||||||
CompletionOptions *options);
|
|
||||||
|
|
||||||
static bool RemoveTrailingChar(string *str, char c);
|
|
||||||
|
|
||||||
|
|
||||||
// 2) Find all matches
|
|
||||||
static void FindMatchingFlags(
|
|
||||||
const vector<CommandLineFlagInfo> &all_flags,
|
|
||||||
const CompletionOptions &options,
|
|
||||||
const string &match_token,
|
|
||||||
set<const CommandLineFlagInfo *> *all_matches,
|
|
||||||
string *longest_common_prefix);
|
|
||||||
|
|
||||||
static bool DoesSingleFlagMatch(
|
|
||||||
const CommandLineFlagInfo &flag,
|
|
||||||
const CompletionOptions &options,
|
|
||||||
const string &match_token);
|
|
||||||
|
|
||||||
|
|
||||||
// 3) Categorize matches
|
|
||||||
static void CategorizeAllMatchingFlags(
|
|
||||||
const set<const CommandLineFlagInfo *> &all_matches,
|
|
||||||
const string &search_token,
|
|
||||||
const string &module,
|
|
||||||
const string &package_dir,
|
|
||||||
NotableFlags *notable_flags);
|
|
||||||
|
|
||||||
static void TryFindModuleAndPackageDir(
|
|
||||||
const vector<CommandLineFlagInfo> all_flags,
|
|
||||||
string *module,
|
|
||||||
string *package_dir);
|
|
||||||
|
|
||||||
|
|
||||||
// 4) Decide which flags to use
|
|
||||||
static void FinalizeCompletionOutput(
|
|
||||||
const set<const CommandLineFlagInfo *> &matching_flags,
|
|
||||||
CompletionOptions *options,
|
|
||||||
NotableFlags *notable_flags,
|
|
||||||
vector<string> *completions);
|
|
||||||
|
|
||||||
static void RetrieveUnusedFlags(
|
|
||||||
const set<const CommandLineFlagInfo *> &matching_flags,
|
|
||||||
const NotableFlags ¬able_flags,
|
|
||||||
set<const CommandLineFlagInfo *> *unused_flags);
|
|
||||||
|
|
||||||
|
|
||||||
// 5) Output matches
|
|
||||||
static void OutputSingleGroupWithLimit(
|
|
||||||
const set<const CommandLineFlagInfo *> &group,
|
|
||||||
const string &line_indentation,
|
|
||||||
const string &header,
|
|
||||||
const string &footer,
|
|
||||||
bool long_output_format,
|
|
||||||
int *remaining_line_limit,
|
|
||||||
size_t *completion_elements_added,
|
|
||||||
vector<string> *completions);
|
|
||||||
|
|
||||||
// (helpers for #5)
|
|
||||||
static string GetShortFlagLine(
|
|
||||||
const string &line_indentation,
|
|
||||||
const CommandLineFlagInfo &info);
|
|
||||||
|
|
||||||
static string GetLongFlagLine(
|
|
||||||
const string &line_indentation,
|
|
||||||
const CommandLineFlagInfo &info);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Useful types
|
|
||||||
|
|
||||||
// Try to deduce the intentions behind this completion attempt. Return the
|
|
||||||
// canonical search term in 'canonical_search_token'. Binary search options
|
|
||||||
// are returned in the various booleans, which should all have intuitive
|
|
||||||
// semantics, possibly except:
|
|
||||||
// - return_all_matching_flags: Generally, we'll trim the number of
|
|
||||||
// returned candidates to some small number, showing those that are
|
|
||||||
// most likely to be useful first. If this is set, however, the user
|
|
||||||
// really does want us to return every single flag as an option.
|
|
||||||
// - force_no_update: Any time we output lines, all of which share a
|
|
||||||
// common prefix, bash will 'helpfully' not even bother to show the
|
|
||||||
// output, instead changing the current word to be that common prefix.
|
|
||||||
// If it's clear this shouldn't happen, we'll set this boolean
|
|
||||||
struct CompletionOptions {
|
|
||||||
bool flag_name_substring_search;
|
|
||||||
bool flag_location_substring_search;
|
|
||||||
bool flag_description_substring_search;
|
|
||||||
bool return_all_matching_flags;
|
|
||||||
bool force_no_update;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Notable flags are flags that are special or preferred for some
|
|
||||||
// reason. For example, flags that are defined in the binary's module
|
|
||||||
// are expected to be much more relevent than flags defined in some
|
|
||||||
// other random location. These sets are specified roughly in precedence
|
|
||||||
// order. Once a flag is placed in one of these 'higher' sets, it won't
|
|
||||||
// be placed in any of the 'lower' sets.
|
|
||||||
struct NotableFlags {
|
|
||||||
typedef set<const CommandLineFlagInfo *> FlagSet;
|
|
||||||
FlagSet perfect_match_flag;
|
|
||||||
FlagSet module_flags; // Found in module file
|
|
||||||
FlagSet package_flags; // Found in same directory as module file
|
|
||||||
FlagSet most_common_flags; // One of the XXX most commonly supplied flags
|
|
||||||
FlagSet subpackage_flags; // Found in subdirectories of package
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Tab completion implementation - entry point
|
|
||||||
static void PrintFlagCompletionInfo(void) {
|
|
||||||
string cursor_word = FLAGS_tab_completion_word;
|
|
||||||
string canonical_token;
|
|
||||||
CompletionOptions options = { };
|
|
||||||
CanonicalizeCursorWordAndSearchOptions(
|
|
||||||
cursor_word,
|
|
||||||
&canonical_token,
|
|
||||||
&options);
|
|
||||||
|
|
||||||
DVLOG(1) << "Identified canonical_token: '" << canonical_token << "'";
|
|
||||||
|
|
||||||
vector<CommandLineFlagInfo> all_flags;
|
|
||||||
set<const CommandLineFlagInfo *> matching_flags;
|
|
||||||
GetAllFlags(&all_flags);
|
|
||||||
DVLOG(2) << "Found " << all_flags.size() << " flags overall";
|
|
||||||
|
|
||||||
string longest_common_prefix;
|
|
||||||
FindMatchingFlags(
|
|
||||||
all_flags,
|
|
||||||
options,
|
|
||||||
canonical_token,
|
|
||||||
&matching_flags,
|
|
||||||
&longest_common_prefix);
|
|
||||||
DVLOG(1) << "Identified " << matching_flags.size() << " matching flags";
|
|
||||||
DVLOG(1) << "Identified " << longest_common_prefix
|
|
||||||
<< " as longest common prefix.";
|
|
||||||
if (longest_common_prefix.size() > canonical_token.size()) {
|
|
||||||
// There's actually a shared common prefix to all matching flags,
|
|
||||||
// so may as well output that and quit quickly.
|
|
||||||
DVLOG(1) << "The common prefix '" << longest_common_prefix
|
|
||||||
<< "' was longer than the token '" << canonical_token
|
|
||||||
<< "'. Returning just this prefix for completion.";
|
|
||||||
fprintf(stdout, "--%s", longest_common_prefix.c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (matching_flags.empty()) {
|
|
||||||
VLOG(1) << "There were no matching flags, returning nothing.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string module;
|
|
||||||
string package_dir;
|
|
||||||
TryFindModuleAndPackageDir(all_flags, &module, &package_dir);
|
|
||||||
DVLOG(1) << "Identified module: '" << module << "'";
|
|
||||||
DVLOG(1) << "Identified package_dir: '" << package_dir << "'";
|
|
||||||
|
|
||||||
NotableFlags notable_flags;
|
|
||||||
CategorizeAllMatchingFlags(
|
|
||||||
matching_flags,
|
|
||||||
canonical_token,
|
|
||||||
module,
|
|
||||||
package_dir,
|
|
||||||
¬able_flags);
|
|
||||||
DVLOG(2) << "Categorized matching flags:";
|
|
||||||
DVLOG(2) << " perfect_match: " << notable_flags.perfect_match_flag.size();
|
|
||||||
DVLOG(2) << " module: " << notable_flags.module_flags.size();
|
|
||||||
DVLOG(2) << " package: " << notable_flags.package_flags.size();
|
|
||||||
DVLOG(2) << " most common: " << notable_flags.most_common_flags.size();
|
|
||||||
DVLOG(2) << " subpackage: " << notable_flags.subpackage_flags.size();
|
|
||||||
|
|
||||||
vector<string> completions;
|
|
||||||
FinalizeCompletionOutput(
|
|
||||||
matching_flags,
|
|
||||||
&options,
|
|
||||||
¬able_flags,
|
|
||||||
&completions);
|
|
||||||
|
|
||||||
if (options.force_no_update)
|
|
||||||
completions.push_back("~");
|
|
||||||
|
|
||||||
DVLOG(1) << "Finalized with " << completions.size()
|
|
||||||
<< " chosen completions";
|
|
||||||
|
|
||||||
for (vector<string>::const_iterator it = completions.begin();
|
|
||||||
it != completions.end();
|
|
||||||
++it) {
|
|
||||||
DVLOG(9) << " Completion entry: '" << *it << "'";
|
|
||||||
fprintf(stdout, "%s\n", it->c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 1) Examine search word (and helper method)
|
|
||||||
static void CanonicalizeCursorWordAndSearchOptions(
|
|
||||||
const string &cursor_word,
|
|
||||||
string *canonical_search_token,
|
|
||||||
CompletionOptions *options) {
|
|
||||||
*canonical_search_token = cursor_word;
|
|
||||||
if (canonical_search_token->empty()) return;
|
|
||||||
|
|
||||||
// Get rid of leading quotes and dashes in the search term
|
|
||||||
if ((*canonical_search_token)[0] == '"')
|
|
||||||
*canonical_search_token = canonical_search_token->substr(1);
|
|
||||||
while ((*canonical_search_token)[0] == '-')
|
|
||||||
*canonical_search_token = canonical_search_token->substr(1);
|
|
||||||
|
|
||||||
options->flag_name_substring_search = false;
|
|
||||||
options->flag_location_substring_search = false;
|
|
||||||
options->flag_description_substring_search = false;
|
|
||||||
options->return_all_matching_flags = false;
|
|
||||||
options->force_no_update = false;
|
|
||||||
|
|
||||||
// Look for all search options we can deduce now. Do this by walking
|
|
||||||
// backwards through the term, looking for up to three '?' and up to
|
|
||||||
// one '+' as suffixed characters. Consume them if found, and remove
|
|
||||||
// them from the canonical search token.
|
|
||||||
int found_question_marks = 0;
|
|
||||||
int found_plusses = 0;
|
|
||||||
while (true) {
|
|
||||||
if (found_question_marks < 3 &&
|
|
||||||
RemoveTrailingChar(canonical_search_token, '?')) {
|
|
||||||
++found_question_marks;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (found_plusses < 1 &&
|
|
||||||
RemoveTrailingChar(canonical_search_token, '+')) {
|
|
||||||
++found_plusses;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (found_question_marks) { // all fallthroughs
|
|
||||||
case 3: options->flag_description_substring_search = true;
|
|
||||||
case 2: options->flag_location_substring_search = true;
|
|
||||||
case 1: options->flag_name_substring_search = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
options->return_all_matching_flags = (found_plusses > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if a char was removed
|
|
||||||
static bool RemoveTrailingChar(string *str, char c) {
|
|
||||||
if (str->empty()) return false;
|
|
||||||
if ((*str)[str->size() - 1] == c) {
|
|
||||||
*str = str->substr(0, str->size() - 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 2) Find all matches (and helper methods)
|
|
||||||
static void FindMatchingFlags(
|
|
||||||
const vector<CommandLineFlagInfo> &all_flags,
|
|
||||||
const CompletionOptions &options,
|
|
||||||
const string &match_token,
|
|
||||||
set<const CommandLineFlagInfo *> *all_matches,
|
|
||||||
string *longest_common_prefix) {
|
|
||||||
all_matches->clear();
|
|
||||||
bool first_match = true;
|
|
||||||
for (vector<CommandLineFlagInfo>::const_iterator it = all_flags.begin();
|
|
||||||
it != all_flags.end();
|
|
||||||
++it) {
|
|
||||||
if (DoesSingleFlagMatch(*it, options, match_token)) {
|
|
||||||
all_matches->insert(&*it);
|
|
||||||
if (first_match) {
|
|
||||||
first_match = false;
|
|
||||||
*longest_common_prefix = it->name;
|
|
||||||
} else {
|
|
||||||
if (longest_common_prefix->empty() || it->name.empty()) {
|
|
||||||
longest_common_prefix->clear();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
string::size_type pos = 0;
|
|
||||||
while (pos < longest_common_prefix->size() &&
|
|
||||||
pos < it->name.size() &&
|
|
||||||
(*longest_common_prefix)[pos] == it->name[pos])
|
|
||||||
++pos;
|
|
||||||
longest_common_prefix->erase(pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given the set of all flags, the parsed match options, and the
|
|
||||||
// canonical search token, produce the set of all candidate matching
|
|
||||||
// flags for subsequent analysis or filtering.
|
|
||||||
static bool DoesSingleFlagMatch(
|
|
||||||
const CommandLineFlagInfo &flag,
|
|
||||||
const CompletionOptions &options,
|
|
||||||
const string &match_token) {
|
|
||||||
// Is there a prefix match?
|
|
||||||
string::size_type pos = flag.name.find(match_token);
|
|
||||||
if (pos == 0) return true;
|
|
||||||
|
|
||||||
// Is there a substring match if we want it?
|
|
||||||
if (options.flag_name_substring_search &&
|
|
||||||
pos != string::npos)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Is there a location match if we want it?
|
|
||||||
if (options.flag_location_substring_search &&
|
|
||||||
flag.filename.find(match_token) != string::npos)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// TODO(user): All searches should probably be case-insensitive
|
|
||||||
// (especially this one...)
|
|
||||||
if (options.flag_description_substring_search &&
|
|
||||||
flag.description.find(match_token) != string::npos)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3) Categorize matches (and helper method)
|
|
||||||
|
|
||||||
// Given a set of matching flags, categorize them by
|
|
||||||
// likely relevence to this specific binary
|
|
||||||
static void CategorizeAllMatchingFlags(
|
|
||||||
const set<const CommandLineFlagInfo *> &all_matches,
|
|
||||||
const string &search_token,
|
|
||||||
const string &module, // empty if we couldn't find any
|
|
||||||
const string &package_dir, // empty if we couldn't find any
|
|
||||||
NotableFlags *notable_flags) {
|
|
||||||
notable_flags->perfect_match_flag.clear();
|
|
||||||
notable_flags->module_flags.clear();
|
|
||||||
notable_flags->package_flags.clear();
|
|
||||||
notable_flags->most_common_flags.clear();
|
|
||||||
notable_flags->subpackage_flags.clear();
|
|
||||||
|
|
||||||
for (set<const CommandLineFlagInfo *>::const_iterator it =
|
|
||||||
all_matches.begin();
|
|
||||||
it != all_matches.end();
|
|
||||||
++it) {
|
|
||||||
DVLOG(2) << "Examining match '" << (*it)->name << "'";
|
|
||||||
DVLOG(7) << " filename: '" << (*it)->filename << "'";
|
|
||||||
string::size_type pos = string::npos;
|
|
||||||
if (!package_dir.empty())
|
|
||||||
pos = (*it)->filename.find(package_dir);
|
|
||||||
string::size_type slash = string::npos;
|
|
||||||
if (pos != string::npos) // candidate for package or subpackage match
|
|
||||||
slash = (*it)->filename.find(
|
|
||||||
PATH_SEPARATOR,
|
|
||||||
pos + package_dir.size() + 1);
|
|
||||||
|
|
||||||
if ((*it)->name == search_token) {
|
|
||||||
// Exact match on some flag's name
|
|
||||||
notable_flags->perfect_match_flag.insert(*it);
|
|
||||||
DVLOG(3) << "Result: perfect match";
|
|
||||||
} else if (!module.empty() && (*it)->filename == module) {
|
|
||||||
// Exact match on module filename
|
|
||||||
notable_flags->module_flags.insert(*it);
|
|
||||||
DVLOG(3) << "Result: module match";
|
|
||||||
} else if (!package_dir.empty() &&
|
|
||||||
pos != string::npos && slash == string::npos) {
|
|
||||||
// In the package, since there was no slash after the package portion
|
|
||||||
notable_flags->package_flags.insert(*it);
|
|
||||||
DVLOG(3) << "Result: package match";
|
|
||||||
} else if (false) {
|
|
||||||
// In the list of the XXX most commonly supplied flags overall
|
|
||||||
// TODO(user): Compile this list.
|
|
||||||
DVLOG(3) << "Result: most-common match";
|
|
||||||
} else if (!package_dir.empty() &&
|
|
||||||
pos != string::npos && slash != string::npos) {
|
|
||||||
// In a subdirectory of the package
|
|
||||||
notable_flags->subpackage_flags.insert(*it);
|
|
||||||
DVLOG(3) << "Result: subpackage match";
|
|
||||||
}
|
|
||||||
|
|
||||||
DVLOG(3) << "Result: not special match";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PushNameWithSuffix(vector<string>* suffixes, const char* suffix) {
|
|
||||||
suffixes->push_back(
|
|
||||||
StringPrintf("/%s%s", ProgramInvocationShortName(), suffix));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TryFindModuleAndPackageDir(
|
|
||||||
const vector<CommandLineFlagInfo> all_flags,
|
|
||||||
string *module,
|
|
||||||
string *package_dir) {
|
|
||||||
module->clear();
|
|
||||||
package_dir->clear();
|
|
||||||
|
|
||||||
vector<string> suffixes;
|
|
||||||
// TODO(user): There's some inherant ambiguity here - multiple directories
|
|
||||||
// could share the same trailing folder and file structure (and even worse,
|
|
||||||
// same file names), causing us to be unsure as to which of the two is the
|
|
||||||
// actual package for this binary. In this case, we'll arbitrarily choose.
|
|
||||||
PushNameWithSuffix(&suffixes, ".");
|
|
||||||
PushNameWithSuffix(&suffixes, "-main.");
|
|
||||||
PushNameWithSuffix(&suffixes, "_main.");
|
|
||||||
// These four are new but probably merited?
|
|
||||||
PushNameWithSuffix(&suffixes, "-test.");
|
|
||||||
PushNameWithSuffix(&suffixes, "_test.");
|
|
||||||
PushNameWithSuffix(&suffixes, "-unittest.");
|
|
||||||
PushNameWithSuffix(&suffixes, "_unittest.");
|
|
||||||
|
|
||||||
for (vector<CommandLineFlagInfo>::const_iterator it = all_flags.begin();
|
|
||||||
it != all_flags.end();
|
|
||||||
++it) {
|
|
||||||
for (vector<string>::const_iterator suffix = suffixes.begin();
|
|
||||||
suffix != suffixes.end();
|
|
||||||
++suffix) {
|
|
||||||
// TODO(user): Make sure the match is near the end of the string
|
|
||||||
if (it->filename.find(*suffix) != string::npos) {
|
|
||||||
*module = it->filename;
|
|
||||||
string::size_type sep = it->filename.rfind(PATH_SEPARATOR);
|
|
||||||
*package_dir = it->filename.substr(0, (sep == string::npos) ? 0 : sep);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can't specialize template type on a locally defined type. Silly C++...
|
|
||||||
struct DisplayInfoGroup {
|
|
||||||
const char* header;
|
|
||||||
const char* footer;
|
|
||||||
set<const CommandLineFlagInfo *> *group;
|
|
||||||
|
|
||||||
int SizeInLines() const {
|
|
||||||
int size_in_lines = static_cast<int>(group->size()) + 1;
|
|
||||||
if (strlen(header) > 0) {
|
|
||||||
size_in_lines++;
|
|
||||||
}
|
|
||||||
if (strlen(footer) > 0) {
|
|
||||||
size_in_lines++;
|
|
||||||
}
|
|
||||||
return size_in_lines;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 4) Finalize and trim output flag set
|
|
||||||
static void FinalizeCompletionOutput(
|
|
||||||
const set<const CommandLineFlagInfo *> &matching_flags,
|
|
||||||
CompletionOptions *options,
|
|
||||||
NotableFlags *notable_flags,
|
|
||||||
vector<string> *completions) {
|
|
||||||
|
|
||||||
// We want to output lines in groups. Each group needs to be indented
|
|
||||||
// the same to keep its lines together. Unless otherwise required,
|
|
||||||
// only 99 lines should be output to prevent bash from harassing the
|
|
||||||
// user.
|
|
||||||
|
|
||||||
// First, figure out which output groups we'll actually use. For each
|
|
||||||
// nonempty group, there will be ~3 lines of header & footer, plus all
|
|
||||||
// output lines themselves.
|
|
||||||
int max_desired_lines = // "999999 flags should be enough for anyone. -dave"
|
|
||||||
(options->return_all_matching_flags ? 999999 : 98);
|
|
||||||
int lines_so_far = 0;
|
|
||||||
|
|
||||||
vector<DisplayInfoGroup> output_groups;
|
|
||||||
bool perfect_match_found = false;
|
|
||||||
if (lines_so_far < max_desired_lines &&
|
|
||||||
!notable_flags->perfect_match_flag.empty()) {
|
|
||||||
perfect_match_found = true;
|
|
||||||
DisplayInfoGroup group =
|
|
||||||
{ "",
|
|
||||||
"==========",
|
|
||||||
¬able_flags->perfect_match_flag };
|
|
||||||
lines_so_far += group.SizeInLines();
|
|
||||||
output_groups.push_back(group);
|
|
||||||
}
|
|
||||||
if (lines_so_far < max_desired_lines &&
|
|
||||||
!notable_flags->module_flags.empty()) {
|
|
||||||
DisplayInfoGroup group = {
|
|
||||||
"-* Matching module flags *-",
|
|
||||||
"===========================",
|
|
||||||
¬able_flags->module_flags };
|
|
||||||
lines_so_far += group.SizeInLines();
|
|
||||||
output_groups.push_back(group);
|
|
||||||
}
|
|
||||||
if (lines_so_far < max_desired_lines &&
|
|
||||||
!notable_flags->package_flags.empty()) {
|
|
||||||
DisplayInfoGroup group = {
|
|
||||||
"-* Matching package flags *-",
|
|
||||||
"============================",
|
|
||||||
¬able_flags->package_flags };
|
|
||||||
lines_so_far += group.SizeInLines();
|
|
||||||
output_groups.push_back(group);
|
|
||||||
}
|
|
||||||
if (lines_so_far < max_desired_lines &&
|
|
||||||
!notable_flags->most_common_flags.empty()) {
|
|
||||||
DisplayInfoGroup group = {
|
|
||||||
"-* Commonly used flags *-",
|
|
||||||
"=========================",
|
|
||||||
¬able_flags->most_common_flags };
|
|
||||||
lines_so_far += group.SizeInLines();
|
|
||||||
output_groups.push_back(group);
|
|
||||||
}
|
|
||||||
if (lines_so_far < max_desired_lines &&
|
|
||||||
!notable_flags->subpackage_flags.empty()) {
|
|
||||||
DisplayInfoGroup group = {
|
|
||||||
"-* Matching sub-package flags *-",
|
|
||||||
"================================",
|
|
||||||
¬able_flags->subpackage_flags };
|
|
||||||
lines_so_far += group.SizeInLines();
|
|
||||||
output_groups.push_back(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
set<const CommandLineFlagInfo *> obscure_flags; // flags not notable
|
|
||||||
if (lines_so_far < max_desired_lines) {
|
|
||||||
RetrieveUnusedFlags(matching_flags, *notable_flags, &obscure_flags);
|
|
||||||
if (!obscure_flags.empty()) {
|
|
||||||
DisplayInfoGroup group = {
|
|
||||||
"-* Other flags *-",
|
|
||||||
"",
|
|
||||||
&obscure_flags };
|
|
||||||
lines_so_far += group.SizeInLines();
|
|
||||||
output_groups.push_back(group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second, go through each of the chosen output groups and output
|
|
||||||
// as many of those flags as we can, while remaining below our limit
|
|
||||||
int remaining_lines = max_desired_lines;
|
|
||||||
size_t completions_output = 0;
|
|
||||||
int indent = static_cast<int>(output_groups.size()) - 1;
|
|
||||||
for (vector<DisplayInfoGroup>::const_iterator it =
|
|
||||||
output_groups.begin();
|
|
||||||
it != output_groups.end();
|
|
||||||
++it, --indent) {
|
|
||||||
OutputSingleGroupWithLimit(
|
|
||||||
*it->group, // group
|
|
||||||
string(indent, ' '), // line indentation
|
|
||||||
string(it->header), // header
|
|
||||||
string(it->footer), // footer
|
|
||||||
perfect_match_found, // long format
|
|
||||||
&remaining_lines, // line limit - reduces this by number printed
|
|
||||||
&completions_output, // completions (not lines) added
|
|
||||||
completions); // produced completions
|
|
||||||
perfect_match_found = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completions_output != matching_flags.size()) {
|
|
||||||
options->force_no_update = false;
|
|
||||||
completions->push_back("~ (Remaining flags hidden) ~");
|
|
||||||
} else {
|
|
||||||
options->force_no_update = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void RetrieveUnusedFlags(
|
|
||||||
const set<const CommandLineFlagInfo *> &matching_flags,
|
|
||||||
const NotableFlags ¬able_flags,
|
|
||||||
set<const CommandLineFlagInfo *> *unused_flags) {
|
|
||||||
// Remove from 'matching_flags' set all members of the sets of
|
|
||||||
// flags we've already printed (specifically, those in notable_flags)
|
|
||||||
for (set<const CommandLineFlagInfo *>::const_iterator it =
|
|
||||||
matching_flags.begin();
|
|
||||||
it != matching_flags.end();
|
|
||||||
++it) {
|
|
||||||
if (notable_flags.perfect_match_flag.count(*it) ||
|
|
||||||
notable_flags.module_flags.count(*it) ||
|
|
||||||
notable_flags.package_flags.count(*it) ||
|
|
||||||
notable_flags.most_common_flags.count(*it) ||
|
|
||||||
notable_flags.subpackage_flags.count(*it))
|
|
||||||
continue;
|
|
||||||
unused_flags->insert(*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5) Output matches (and helper methods)
|
|
||||||
|
|
||||||
static void OutputSingleGroupWithLimit(
|
|
||||||
const set<const CommandLineFlagInfo *> &group,
|
|
||||||
const string &line_indentation,
|
|
||||||
const string &header,
|
|
||||||
const string &footer,
|
|
||||||
bool long_output_format,
|
|
||||||
int *remaining_line_limit,
|
|
||||||
size_t *completion_elements_output,
|
|
||||||
vector<string> *completions) {
|
|
||||||
if (group.empty()) return;
|
|
||||||
if (!header.empty()) {
|
|
||||||
if (*remaining_line_limit < 2) return;
|
|
||||||
*remaining_line_limit -= 2;
|
|
||||||
completions->push_back(line_indentation + header);
|
|
||||||
completions->push_back(line_indentation + string(header.size(), '-'));
|
|
||||||
}
|
|
||||||
for (set<const CommandLineFlagInfo *>::const_iterator it = group.begin();
|
|
||||||
it != group.end() && *remaining_line_limit > 0;
|
|
||||||
++it) {
|
|
||||||
--*remaining_line_limit;
|
|
||||||
++*completion_elements_output;
|
|
||||||
completions->push_back(
|
|
||||||
(long_output_format
|
|
||||||
? GetLongFlagLine(line_indentation, **it)
|
|
||||||
: GetShortFlagLine(line_indentation, **it)));
|
|
||||||
}
|
|
||||||
if (!footer.empty()) {
|
|
||||||
if (*remaining_line_limit < 1) return;
|
|
||||||
--*remaining_line_limit;
|
|
||||||
completions->push_back(line_indentation + footer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static string GetShortFlagLine(
|
|
||||||
const string &line_indentation,
|
|
||||||
const CommandLineFlagInfo &info) {
|
|
||||||
string prefix;
|
|
||||||
bool is_string = (info.type == "string");
|
|
||||||
SStringPrintf(&prefix, "%s--%s [%s%s%s] ",
|
|
||||||
line_indentation.c_str(),
|
|
||||||
info.name.c_str(),
|
|
||||||
(is_string ? "'" : ""),
|
|
||||||
info.default_value.c_str(),
|
|
||||||
(is_string ? "'" : ""));
|
|
||||||
int remainder =
|
|
||||||
FLAGS_tab_completion_columns - static_cast<int>(prefix.size());
|
|
||||||
string suffix;
|
|
||||||
if (remainder > 0)
|
|
||||||
suffix =
|
|
||||||
(static_cast<int>(info.description.size()) > remainder ?
|
|
||||||
(info.description.substr(0, remainder - 3) + "...").c_str() :
|
|
||||||
info.description.c_str());
|
|
||||||
return prefix + suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
static string GetLongFlagLine(
|
|
||||||
const string &line_indentation,
|
|
||||||
const CommandLineFlagInfo &info) {
|
|
||||||
|
|
||||||
string output = DescribeOneFlag(info);
|
|
||||||
|
|
||||||
// Replace '-' with '--', and remove trailing newline before appending
|
|
||||||
// the module definition location.
|
|
||||||
string old_flagname = "-" + info.name;
|
|
||||||
output.replace(
|
|
||||||
output.find(old_flagname),
|
|
||||||
old_flagname.size(),
|
|
||||||
"-" + old_flagname);
|
|
||||||
// Stick a newline and indentation in front of the type and default
|
|
||||||
// portions of DescribeOneFlag()s description
|
|
||||||
static const char kNewlineWithIndent[] = "\n ";
|
|
||||||
output.replace(output.find(" type:"), 1, string(kNewlineWithIndent));
|
|
||||||
output.replace(output.find(" default:"), 1, string(kNewlineWithIndent));
|
|
||||||
output = StringPrintf("%s Details for '--%s':\n"
|
|
||||||
"%s defined: %s",
|
|
||||||
line_indentation.c_str(),
|
|
||||||
info.name.c_str(),
|
|
||||||
output.c_str(),
|
|
||||||
info.filename.c_str());
|
|
||||||
|
|
||||||
// Eliminate any doubled newlines that crept in. Specifically, if
|
|
||||||
// DescribeOneFlag() decided to break the line just before "type"
|
|
||||||
// or "default", we don't want to introduce an extra blank line
|
|
||||||
static const string line_of_spaces(FLAGS_tab_completion_columns, ' ');
|
|
||||||
static const char kDoubledNewlines[] = "\n \n";
|
|
||||||
for (string::size_type newlines = output.find(kDoubledNewlines);
|
|
||||||
newlines != string::npos;
|
|
||||||
newlines = output.find(kDoubledNewlines))
|
|
||||||
// Replace each 'doubled newline' with a single newline
|
|
||||||
output.replace(newlines, sizeof(kDoubledNewlines) - 1, string("\n"));
|
|
||||||
|
|
||||||
for (string::size_type newline = output.find('\n');
|
|
||||||
newline != string::npos;
|
|
||||||
newline = output.find('\n')) {
|
|
||||||
int newline_pos = static_cast<int>(newline) % FLAGS_tab_completion_columns;
|
|
||||||
int missing_spaces = FLAGS_tab_completion_columns - newline_pos;
|
|
||||||
output.replace(newline, 1, line_of_spaces, 1, missing_spaces);
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
} // anonymous
|
|
||||||
|
|
||||||
void HandleCommandLineCompletions(void) {
|
|
||||||
if (FLAGS_tab_completion_word.empty()) return;
|
|
||||||
PrintFlagCompletionInfo();
|
|
||||||
gflags_exitfunc(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
|
@ -1,117 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Copyright (c) 2008, Google Inc.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions are
|
|
||||||
# met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# * Redistributions in binary form must reproduce the above
|
|
||||||
# copyright notice, this list of conditions and the following disclaimer
|
|
||||||
# in the documentation and/or other materials provided with the
|
|
||||||
# distribution.
|
|
||||||
# * Neither the name of Google Inc. nor the names of its
|
|
||||||
# contributors may be used to endorse or promote products derived from
|
|
||||||
# this software without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# ---
|
|
||||||
# Author: Dave Nicponski
|
|
||||||
#
|
|
||||||
# This script is invoked by bash in response to a matching compspec. When
|
|
||||||
# this happens, bash calls this script using the command shown in the -C
|
|
||||||
# block of the complete entry, but also appends 3 arguments. They are:
|
|
||||||
# - The command being used for completion
|
|
||||||
# - The word being completed
|
|
||||||
# - The word preceding the completion word.
|
|
||||||
#
|
|
||||||
# Here's an example of how you might use this script:
|
|
||||||
# $ complete -o bashdefault -o default -o nospace -C \
|
|
||||||
# '/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \
|
|
||||||
# time env binary_name another_binary [...]
|
|
||||||
|
|
||||||
# completion_word_index gets the index of the (N-1)th argument for
|
|
||||||
# this command line. completion_word gets the actual argument from
|
|
||||||
# this command line at the (N-1)th position
|
|
||||||
completion_word_index="$(($# - 1))"
|
|
||||||
completion_word="${!completion_word_index}"
|
|
||||||
|
|
||||||
# TODO(user): Replace this once gflags_completions.cc has
|
|
||||||
# a bool parameter indicating unambiguously to hijack the process for
|
|
||||||
# completion purposes.
|
|
||||||
if [ -z "$completion_word" ]; then
|
|
||||||
# Until an empty value for the completion word stops being misunderstood
|
|
||||||
# by binaries, don't actually execute the binary or the process
|
|
||||||
# won't be hijacked!
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# binary_index gets the index of the command being completed (which bash
|
|
||||||
# places in the (N-2)nd position. binary gets the actual command from
|
|
||||||
# this command line at that (N-2)nd position
|
|
||||||
binary_index="$(($# - 2))"
|
|
||||||
binary="${!binary_index}"
|
|
||||||
|
|
||||||
# For completions to be universal, we may have setup the compspec to
|
|
||||||
# trigger on 'harmless pass-through' commands, like 'time' or 'env'.
|
|
||||||
# If the command being completed is one of those two, we'll need to
|
|
||||||
# identify the actual command being executed. To do this, we need
|
|
||||||
# the actual command line that the <TAB> was pressed on. Bash helpfully
|
|
||||||
# places this in the $COMP_LINE variable.
|
|
||||||
if [ "$binary" == "time" ] || [ "$binary" == "env" ]; then
|
|
||||||
# we'll assume that the first 'argument' is actually the
|
|
||||||
# binary
|
|
||||||
|
|
||||||
|
|
||||||
# TODO(user): This is not perfect - the 'env' command, for instance,
|
|
||||||
# is allowed to have options between the 'env' and 'the command to
|
|
||||||
# be executed'. For example, consider:
|
|
||||||
# $ env FOO="bar" bin/do_something --help<TAB>
|
|
||||||
# In this case, we'll mistake the FOO="bar" portion as the binary.
|
|
||||||
# Perhaps we should continuing consuming leading words until we
|
|
||||||
# either run out of words, or find a word that is a valid file
|
|
||||||
# marked as executable. I can't think of any reason this wouldn't
|
|
||||||
# work.
|
|
||||||
|
|
||||||
# Break up the 'original command line' (not this script's command line,
|
|
||||||
# rather the one the <TAB> was pressed on) and find the second word.
|
|
||||||
parts=( ${COMP_LINE} )
|
|
||||||
binary=${parts[1]}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Build the command line to use for completion. Basically it involves
|
|
||||||
# passing through all the arguments given to this script (except the 3
|
|
||||||
# that bash added), and appending a '--tab_completion_word "WORD"' to
|
|
||||||
# the arguments.
|
|
||||||
params=""
|
|
||||||
for ((i=1; i<=$(($# - 3)); ++i)); do
|
|
||||||
params="$params \"${!i}\"";
|
|
||||||
done
|
|
||||||
params="$params --tab_completion_word \"$completion_word\""
|
|
||||||
|
|
||||||
# TODO(user): Perhaps stash the output in a temporary file somewhere
|
|
||||||
# in /tmp, and only cat it to stdout if the command returned a success
|
|
||||||
# code, to prevent false positives
|
|
||||||
|
|
||||||
# If we think we have a reasonable command to execute, then execute it
|
|
||||||
# and hope for the best.
|
|
||||||
candidate=$(type -p "$binary")
|
|
||||||
if [ ! -z "$candidate" ]; then
|
|
||||||
eval "$candidate 2>/dev/null $params"
|
|
||||||
elif [ -f "$binary" ] && [ -x "$binary" ]; then
|
|
||||||
eval "$binary 2>/dev/null $params"
|
|
||||||
fi
|
|
|
@ -1,68 +0,0 @@
|
||||||
// Copyright (c) 2009, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
//
|
|
||||||
// A negative comiple test for gflags.
|
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
|
||||||
|
|
||||||
#if defined(TEST_SWAPPED_ARGS)
|
|
||||||
|
|
||||||
DEFINE_bool(some_bool_flag,
|
|
||||||
"the default value should go here, not the description",
|
|
||||||
false);
|
|
||||||
|
|
||||||
|
|
||||||
#elif defined(TEST_INT_INSTEAD_OF_BOOL)
|
|
||||||
|
|
||||||
DEFINE_bool(some_bool_flag_2,
|
|
||||||
0,
|
|
||||||
"should have been an int32 flag but mistakenly used bool instead");
|
|
||||||
|
|
||||||
#elif defined(TEST_BOOL_IN_QUOTES)
|
|
||||||
|
|
||||||
|
|
||||||
DEFINE_bool(some_bool_flag_3,
|
|
||||||
"false",
|
|
||||||
"false in in quotes, which is wrong");
|
|
||||||
|
|
||||||
#elif defined(TEST_SANITY)
|
|
||||||
|
|
||||||
DEFINE_bool(some_bool_flag_4,
|
|
||||||
true,
|
|
||||||
"this is the correct usage of DEFINE_bool");
|
|
||||||
|
|
||||||
#elif defined(TEST_DEFINE_STRING_WITH_0)
|
|
||||||
|
|
||||||
DEFINE_string(some_string_flag,
|
|
||||||
0,
|
|
||||||
"Trying to construct a string by passing 0 would cause a crash.");
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,447 +0,0 @@
|
||||||
// Copyright (c) 1999, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
//
|
|
||||||
// Revamped and reorganized by Craig Silverstein
|
|
||||||
//
|
|
||||||
// This file contains code for handling the 'reporting' flags. These
|
|
||||||
// are flags that, when present, cause the program to report some
|
|
||||||
// information and then exit. --help and --version are the canonical
|
|
||||||
// reporting flags, but we also have flags like --helpxml, etc.
|
|
||||||
//
|
|
||||||
// There's only one function that's meant to be called externally:
|
|
||||||
// HandleCommandLineHelpFlags(). (Well, actually, ShowUsageWithFlags(),
|
|
||||||
// ShowUsageWithFlagsRestrict(), and DescribeOneFlag() can be called
|
|
||||||
// externally too, but there's little need for it.) These are all
|
|
||||||
// declared in the main gflags.h header file.
|
|
||||||
//
|
|
||||||
// HandleCommandLineHelpFlags() will check what 'reporting' flags have
|
|
||||||
// been defined, if any -- the "help" part of the function name is a
|
|
||||||
// bit misleading -- and do the relevant reporting. It should be
|
|
||||||
// called after all flag-values have been assigned, that is, after
|
|
||||||
// parsing the command-line.
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <gflags/gflags.h>
|
|
||||||
#include <gflags/gflags_completions.h>
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#ifndef PATH_SEPARATOR
|
|
||||||
#define PATH_SEPARATOR '/'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The 'reporting' flags. They all call gflags_exitfunc().
|
|
||||||
DEFINE_bool(help, false,
|
|
||||||
"show help on all flags [tip: all flags can have two dashes]");
|
|
||||||
DEFINE_bool(helpfull, false,
|
|
||||||
"show help on all flags -- same as -help");
|
|
||||||
DEFINE_bool(helpshort, false,
|
|
||||||
"show help on only the main module for this program");
|
|
||||||
DEFINE_string(helpon, "",
|
|
||||||
"show help on the modules named by this flag value");
|
|
||||||
DEFINE_string(helpmatch, "",
|
|
||||||
"show help on modules whose name contains the specified substr");
|
|
||||||
DEFINE_bool(helppackage, false,
|
|
||||||
"show help on all modules in the main package");
|
|
||||||
DEFINE_bool(helpxml, false,
|
|
||||||
"produce an xml version of help");
|
|
||||||
DEFINE_bool(version, false,
|
|
||||||
"show version and build info and exit");
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
using std::string;
|
|
||||||
using std::vector;
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// DescribeOneFlag()
|
|
||||||
// DescribeOneFlagInXML()
|
|
||||||
// Routines that pretty-print info about a flag. These use
|
|
||||||
// a CommandLineFlagInfo, which is the way the gflags
|
|
||||||
// API exposes static info about a flag.
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
|
|
||||||
static const int kLineLength = 80;
|
|
||||||
|
|
||||||
static void AddString(const string& s,
|
|
||||||
string* final_string, int* chars_in_line) {
|
|
||||||
const int slen = static_cast<int>(s.length());
|
|
||||||
if (*chars_in_line + 1 + slen >= kLineLength) { // < 80 chars/line
|
|
||||||
*final_string += "\n ";
|
|
||||||
*chars_in_line = 6;
|
|
||||||
} else {
|
|
||||||
*final_string += " ";
|
|
||||||
*chars_in_line += 1;
|
|
||||||
}
|
|
||||||
*final_string += s;
|
|
||||||
*chars_in_line += slen;
|
|
||||||
}
|
|
||||||
|
|
||||||
static string PrintStringFlagsWithQuotes(const CommandLineFlagInfo& flag,
|
|
||||||
const string& text, bool current) {
|
|
||||||
const char* c_string = (current ? flag.current_value.c_str() :
|
|
||||||
flag.default_value.c_str());
|
|
||||||
if (strcmp(flag.type.c_str(), "string") == 0) { // add quotes for strings
|
|
||||||
return StringPrintf("%s: \"%s\"", text.c_str(), c_string);
|
|
||||||
} else {
|
|
||||||
return StringPrintf("%s: %s", text.c_str(), c_string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a descriptive string for a flag.
|
|
||||||
// Goes to some trouble to make pretty line breaks.
|
|
||||||
string DescribeOneFlag(const CommandLineFlagInfo& flag) {
|
|
||||||
string main_part;
|
|
||||||
SStringPrintf(&main_part, " -%s (%s)",
|
|
||||||
flag.name.c_str(),
|
|
||||||
flag.description.c_str());
|
|
||||||
const char* c_string = main_part.c_str();
|
|
||||||
int chars_left = static_cast<int>(main_part.length());
|
|
||||||
string final_string = "";
|
|
||||||
int chars_in_line = 0; // how many chars in current line so far?
|
|
||||||
while (1) {
|
|
||||||
assert(chars_left == strlen(c_string)); // Unless there's a \0 in there?
|
|
||||||
const char* newline = strchr(c_string, '\n');
|
|
||||||
if (newline == NULL && chars_in_line+chars_left < kLineLength) {
|
|
||||||
// The whole remainder of the string fits on this line
|
|
||||||
final_string += c_string;
|
|
||||||
chars_in_line += chars_left;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (newline != NULL && newline - c_string < kLineLength - chars_in_line) {
|
|
||||||
int n = static_cast<int>(newline - c_string);
|
|
||||||
final_string.append(c_string, n);
|
|
||||||
chars_left -= n + 1;
|
|
||||||
c_string += n + 1;
|
|
||||||
} else {
|
|
||||||
// Find the last whitespace on this 80-char line
|
|
||||||
int whitespace = kLineLength-chars_in_line-1; // < 80 chars/line
|
|
||||||
while ( whitespace > 0 && !isspace(c_string[whitespace]) ) {
|
|
||||||
--whitespace;
|
|
||||||
}
|
|
||||||
if (whitespace <= 0) {
|
|
||||||
// Couldn't find any whitespace to make a line break. Just dump the
|
|
||||||
// rest out!
|
|
||||||
final_string += c_string;
|
|
||||||
chars_in_line = kLineLength; // next part gets its own line for sure!
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
final_string += string(c_string, whitespace);
|
|
||||||
chars_in_line += whitespace;
|
|
||||||
while (isspace(c_string[whitespace])) ++whitespace;
|
|
||||||
c_string += whitespace;
|
|
||||||
chars_left -= whitespace;
|
|
||||||
}
|
|
||||||
if (*c_string == '\0')
|
|
||||||
break;
|
|
||||||
StringAppendF(&final_string, "\n ");
|
|
||||||
chars_in_line = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append data type
|
|
||||||
AddString(string("type: ") + flag.type, &final_string, &chars_in_line);
|
|
||||||
// The listed default value will be the actual default from the flag
|
|
||||||
// definition in the originating source file, unless the value has
|
|
||||||
// subsequently been modified using SetCommandLineOptionWithMode() with mode
|
|
||||||
// SET_FLAGS_DEFAULT, or by setting FLAGS_foo = bar before ParseCommandLineFlags().
|
|
||||||
AddString(PrintStringFlagsWithQuotes(flag, "default", false), &final_string,
|
|
||||||
&chars_in_line);
|
|
||||||
if (!flag.is_default) {
|
|
||||||
AddString(PrintStringFlagsWithQuotes(flag, "currently", true),
|
|
||||||
&final_string, &chars_in_line);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringAppendF(&final_string, "\n");
|
|
||||||
return final_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple routine to xml-escape a string: escape & and < only.
|
|
||||||
static string XMLText(const string& txt) {
|
|
||||||
string ans = txt;
|
|
||||||
for (string::size_type pos = 0; (pos = ans.find("&", pos)) != string::npos; )
|
|
||||||
ans.replace(pos++, 1, "&");
|
|
||||||
for (string::size_type pos = 0; (pos = ans.find("<", pos)) != string::npos; )
|
|
||||||
ans.replace(pos++, 1, "<");
|
|
||||||
return ans;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void AddXMLTag(string* r, const char* tag, const string& txt) {
|
|
||||||
StringAppendF(r, "<%s>%s</%s>", tag, XMLText(txt).c_str(), tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static string DescribeOneFlagInXML(const CommandLineFlagInfo& flag) {
|
|
||||||
// The file and flagname could have been attributes, but default
|
|
||||||
// and meaning need to avoid attribute normalization. This way it
|
|
||||||
// can be parsed by simple programs, in addition to xml parsers.
|
|
||||||
string r("<flag>");
|
|
||||||
AddXMLTag(&r, "file", flag.filename);
|
|
||||||
AddXMLTag(&r, "name", flag.name);
|
|
||||||
AddXMLTag(&r, "meaning", flag.description);
|
|
||||||
AddXMLTag(&r, "default", flag.default_value);
|
|
||||||
AddXMLTag(&r, "current", flag.current_value);
|
|
||||||
AddXMLTag(&r, "type", flag.type);
|
|
||||||
r += "</flag>";
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// ShowUsageWithFlags()
|
|
||||||
// ShowUsageWithFlagsRestrict()
|
|
||||||
// ShowXMLOfFlags()
|
|
||||||
// These routines variously expose the registry's list of flag
|
|
||||||
// values. ShowUsage*() prints the flag-value information
|
|
||||||
// to stdout in a user-readable format (that's what --help uses).
|
|
||||||
// The Restrict() version limits what flags are shown.
|
|
||||||
// ShowXMLOfFlags() prints the flag-value information to stdout
|
|
||||||
// in a machine-readable format. In all cases, the flags are
|
|
||||||
// sorted: first by filename they are defined in, then by flagname.
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
|
|
||||||
static const char* Basename(const char* filename) {
|
|
||||||
const char* sep = strrchr(filename, PATH_SEPARATOR);
|
|
||||||
return sep ? sep + 1 : filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
static string Dirname(const string& filename) {
|
|
||||||
string::size_type sep = filename.rfind(PATH_SEPARATOR);
|
|
||||||
return filename.substr(0, (sep == string::npos) ? 0 : sep);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test whether a filename contains at least one of the substrings.
|
|
||||||
static bool FileMatchesSubstring(const string& filename,
|
|
||||||
const vector<string>& substrings) {
|
|
||||||
for (vector<string>::const_iterator target = substrings.begin();
|
|
||||||
target != substrings.end();
|
|
||||||
++target) {
|
|
||||||
if (strstr(filename.c_str(), target->c_str()) != NULL)
|
|
||||||
return true;
|
|
||||||
// If the substring starts with a '/', that means that we want
|
|
||||||
// the string to be at the beginning of a directory component.
|
|
||||||
// That should match the first directory component as well, so
|
|
||||||
// we allow '/foo' to match a filename of 'foo'.
|
|
||||||
if (!target->empty() && (*target)[0] == '/' &&
|
|
||||||
strncmp(filename.c_str(), target->c_str() + 1,
|
|
||||||
strlen(target->c_str() + 1)) == 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show help for every filename which matches any of the target substrings.
|
|
||||||
// If substrings is empty, shows help for every file. If a flag's help message
|
|
||||||
// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1'
|
|
||||||
// before including gflags/gflags.h), then this flag will not be displayed
|
|
||||||
// by '--help' and its variants.
|
|
||||||
static void ShowUsageWithFlagsMatching(const char *argv0,
|
|
||||||
const vector<string> &substrings) {
|
|
||||||
fprintf(stdout, "%s: %s\n", Basename(argv0), ProgramUsage());
|
|
||||||
|
|
||||||
vector<CommandLineFlagInfo> flags;
|
|
||||||
GetAllFlags(&flags); // flags are sorted by filename, then flagname
|
|
||||||
|
|
||||||
string last_filename; // so we know when we're at a new file
|
|
||||||
bool first_directory = true; // controls blank lines between dirs
|
|
||||||
bool found_match = false; // stays false iff no dir matches restrict
|
|
||||||
for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
|
|
||||||
flag != flags.end();
|
|
||||||
++flag) {
|
|
||||||
if (substrings.empty() ||
|
|
||||||
FileMatchesSubstring(flag->filename, substrings)) {
|
|
||||||
// If the flag has been stripped, pretend that it doesn't exist.
|
|
||||||
if (flag->description == kStrippedFlagHelp) continue;
|
|
||||||
found_match = true; // this flag passed the match!
|
|
||||||
if (flag->filename != last_filename) { // new file
|
|
||||||
if (Dirname(flag->filename) != Dirname(last_filename)) { // new dir!
|
|
||||||
if (!first_directory)
|
|
||||||
fprintf(stdout, "\n\n"); // put blank lines between directories
|
|
||||||
first_directory = false;
|
|
||||||
}
|
|
||||||
fprintf(stdout, "\n Flags from %s:\n", flag->filename.c_str());
|
|
||||||
last_filename = flag->filename;
|
|
||||||
}
|
|
||||||
// Now print this flag
|
|
||||||
fprintf(stdout, "%s", DescribeOneFlag(*flag).c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found_match && !substrings.empty()) {
|
|
||||||
fprintf(stdout, "\n No modules matched: use -help\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict) {
|
|
||||||
vector<string> substrings;
|
|
||||||
if (restrict != NULL && *restrict != '\0') {
|
|
||||||
substrings.push_back(restrict);
|
|
||||||
}
|
|
||||||
ShowUsageWithFlagsMatching(argv0, substrings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShowUsageWithFlags(const char *argv0) {
|
|
||||||
ShowUsageWithFlagsRestrict(argv0, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the help, program, and usage to xml.
|
|
||||||
static void ShowXMLOfFlags(const char *prog_name) {
|
|
||||||
vector<CommandLineFlagInfo> flags;
|
|
||||||
GetAllFlags(&flags); // flags are sorted: by filename, then flagname
|
|
||||||
|
|
||||||
// XML. There is no corresponding schema yet
|
|
||||||
fprintf(stdout, "<?xml version=\"1.0\"?>\n");
|
|
||||||
// The document
|
|
||||||
fprintf(stdout, "<AllFlags>\n");
|
|
||||||
// the program name and usage
|
|
||||||
fprintf(stdout, "<program>%s</program>\n",
|
|
||||||
XMLText(Basename(prog_name)).c_str());
|
|
||||||
fprintf(stdout, "<usage>%s</usage>\n",
|
|
||||||
XMLText(ProgramUsage()).c_str());
|
|
||||||
// All the flags
|
|
||||||
for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
|
|
||||||
flag != flags.end();
|
|
||||||
++flag) {
|
|
||||||
if (flag->description != kStrippedFlagHelp)
|
|
||||||
fprintf(stdout, "%s\n", DescribeOneFlagInXML(*flag).c_str());
|
|
||||||
}
|
|
||||||
// The end of the document
|
|
||||||
fprintf(stdout, "</AllFlags>\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// ShowVersion()
|
|
||||||
// Called upon --version. Prints build-related info.
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
|
|
||||||
static void ShowVersion() {
|
|
||||||
const char* version_string = VersionString();
|
|
||||||
if (version_string && *version_string) {
|
|
||||||
fprintf(stdout, "%s version %s\n",
|
|
||||||
ProgramInvocationShortName(), version_string);
|
|
||||||
} else {
|
|
||||||
fprintf(stdout, "%s\n", ProgramInvocationShortName());
|
|
||||||
}
|
|
||||||
# if !defined(NDEBUG)
|
|
||||||
fprintf(stdout, "Debug build (NDEBUG not #defined)\n");
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void AppendPrognameStrings(vector<string>* substrings,
|
|
||||||
const char* progname) {
|
|
||||||
string r("/");
|
|
||||||
r += progname;
|
|
||||||
substrings->push_back(r + ".");
|
|
||||||
substrings->push_back(r + "-main.");
|
|
||||||
substrings->push_back(r + "_main.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// HandleCommandLineHelpFlags()
|
|
||||||
// Checks all the 'reporting' commandline flags to see if any
|
|
||||||
// have been set. If so, handles them appropriately. Note
|
|
||||||
// that all of them, by definition, cause the program to exit
|
|
||||||
// if they trigger.
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
|
|
||||||
void HandleCommandLineHelpFlags() {
|
|
||||||
const char* progname = ProgramInvocationShortName();
|
|
||||||
|
|
||||||
HandleCommandLineCompletions();
|
|
||||||
|
|
||||||
vector<string> substrings;
|
|
||||||
AppendPrognameStrings(&substrings, progname);
|
|
||||||
|
|
||||||
if (FLAGS_helpshort) {
|
|
||||||
// show only flags related to this binary:
|
|
||||||
// E.g. for fileutil.cc, want flags containing ... "/fileutil." cc
|
|
||||||
ShowUsageWithFlagsMatching(progname, substrings);
|
|
||||||
gflags_exitfunc(1);
|
|
||||||
|
|
||||||
} else if (FLAGS_help || FLAGS_helpfull) {
|
|
||||||
// show all options
|
|
||||||
ShowUsageWithFlagsRestrict(progname, ""); // empty restrict
|
|
||||||
gflags_exitfunc(1);
|
|
||||||
|
|
||||||
} else if (!FLAGS_helpon.empty()) {
|
|
||||||
string restrict = "/" + FLAGS_helpon + ".";
|
|
||||||
ShowUsageWithFlagsRestrict(progname, restrict.c_str());
|
|
||||||
gflags_exitfunc(1);
|
|
||||||
|
|
||||||
} else if (!FLAGS_helpmatch.empty()) {
|
|
||||||
ShowUsageWithFlagsRestrict(progname, FLAGS_helpmatch.c_str());
|
|
||||||
gflags_exitfunc(1);
|
|
||||||
|
|
||||||
} else if (FLAGS_helppackage) {
|
|
||||||
// Shows help for all files in the same directory as main(). We
|
|
||||||
// don't want to resort to looking at dirname(progname), because
|
|
||||||
// the user can pick progname, and it may not relate to the file
|
|
||||||
// where main() resides. So instead, we search the flags for a
|
|
||||||
// filename like "/progname.cc", and take the dirname of that.
|
|
||||||
vector<CommandLineFlagInfo> flags;
|
|
||||||
GetAllFlags(&flags);
|
|
||||||
string last_package;
|
|
||||||
for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
|
|
||||||
flag != flags.end();
|
|
||||||
++flag) {
|
|
||||||
if (!FileMatchesSubstring(flag->filename, substrings))
|
|
||||||
continue;
|
|
||||||
const string package = Dirname(flag->filename) + "/";
|
|
||||||
if (package != last_package) {
|
|
||||||
ShowUsageWithFlagsRestrict(progname, package.c_str());
|
|
||||||
VLOG(7) << "Found package: " << package;
|
|
||||||
if (!last_package.empty()) { // means this isn't our first pkg
|
|
||||||
LOG(WARNING) << "Multiple packages contain a file=" << progname;
|
|
||||||
}
|
|
||||||
last_package = package;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (last_package.empty()) { // never found a package to print
|
|
||||||
LOG(WARNING) << "Unable to find a package for file=" << progname;
|
|
||||||
}
|
|
||||||
gflags_exitfunc(1);
|
|
||||||
|
|
||||||
} else if (FLAGS_helpxml) {
|
|
||||||
ShowXMLOfFlags(progname);
|
|
||||||
gflags_exitfunc(1);
|
|
||||||
|
|
||||||
} else if (FLAGS_version) {
|
|
||||||
ShowVersion();
|
|
||||||
// Unlike help, we may be asking for version in a script, so return 0
|
|
||||||
gflags_exitfunc(0);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
|
@ -1,61 +0,0 @@
|
||||||
// Copyright (c) 2011, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// ---
|
|
||||||
// Author: csilvers@google.com (Craig Silverstein)
|
|
||||||
//
|
|
||||||
// A simple program that uses STRIP_FLAG_HELP. We'll have a shell
|
|
||||||
// script that runs 'strings' over this program and makes sure
|
|
||||||
// that the help string is not in there.
|
|
||||||
|
|
||||||
#include "config_for_unittests.h"
|
|
||||||
#define STRIP_FLAG_HELP 1
|
|
||||||
#include <gflags/gflags.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
using GOOGLE_NAMESPACE::SetUsageMessage;
|
|
||||||
using GOOGLE_NAMESPACE::ParseCommandLineFlags;
|
|
||||||
|
|
||||||
|
|
||||||
DEFINE_bool(test, true, "This text should be stripped out");
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
SetUsageMessage("Usage message");
|
|
||||||
ParseCommandLineFlags(&argc, &argv, false);
|
|
||||||
|
|
||||||
// Unfortunately, for us, libtool can replace executables with a shell
|
|
||||||
// script that does some work before calling the 'real' executable
|
|
||||||
// under a different name. We need the 'real' executable name to run
|
|
||||||
// 'strings' on it, so we construct this binary to print the real
|
|
||||||
// name (argv[0]) on stdout when run.
|
|
||||||
puts(argv[0]);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# Copyright (c) 2011, Google Inc.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions are
|
|
||||||
# met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# * Redistributions in binary form must reproduce the above
|
|
||||||
# copyright notice, this list of conditions and the following disclaimer
|
|
||||||
# in the documentation and/or other materials provided with the
|
|
||||||
# distribution.
|
|
||||||
# * Neither the name of Google Inc. nor the names of its
|
|
||||||
# contributors may be used to endorse or promote products derived from
|
|
||||||
# this software without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# ---
|
|
||||||
# Author: csilvers@google.com (Craig Silverstein)
|
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "USAGE: $0 <unittest exe>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
BINARY="$1"
|
|
||||||
|
|
||||||
# Make sure the binary exists...
|
|
||||||
if ! "$BINARY" >/dev/null 2>/dev/null
|
|
||||||
then
|
|
||||||
echo "Cannot run binary $BINARY"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Make sure the --help output doesn't print the stripped text.
|
|
||||||
if "$BINARY" --help | grep "This text should be stripped out" >/dev/null 2>&1
|
|
||||||
then
|
|
||||||
echo "Text not stripped from --help like it should be: $BINARY"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Make sure the stripped text isn't in the binary at all.
|
|
||||||
if strings --help >/dev/null 2>&1 # make sure the binary exists
|
|
||||||
then
|
|
||||||
# Unfortunately, for us, libtool can replace executables with a
|
|
||||||
# shell script that does some work before calling the 'real'
|
|
||||||
# executable under a different name. We need the 'real'
|
|
||||||
# executable name to run 'strings' on it, so we construct this
|
|
||||||
# binary to print the real name (argv[0]) on stdout when run.
|
|
||||||
REAL_BINARY=`"$BINARY"`
|
|
||||||
# On cygwin, we may need to add a '.exe' extension by hand.
|
|
||||||
[ -f "$REAL_BINARY.exe" ] && REAL_BINARY="$REAL_BINARY.exe"
|
|
||||||
if strings "$REAL_BINARY" | grep "This text should be stripped" >/dev/null 2>&1
|
|
||||||
then
|
|
||||||
echo "Text not stripped from binary like it should be: $BINARY"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Let's also do a sanity check to make sure strings is working properly
|
|
||||||
if ! strings "$REAL_BINARY" | grep "Usage message" >/dev/null 2>&1
|
|
||||||
then
|
|
||||||
echo "Usage text not found in binary like it should be: $BINARY"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "PASS"
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,237 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Copyright (c) 2006, Google Inc.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions are
|
|
||||||
# met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# * Redistributions in binary form must reproduce the above
|
|
||||||
# copyright notice, this list of conditions and the following disclaimer
|
|
||||||
# in the documentation and/or other materials provided with the
|
|
||||||
# distribution.
|
|
||||||
# * Neither the name of Google Inc. nor the names of its
|
|
||||||
# contributors may be used to endorse or promote products derived from
|
|
||||||
# this software without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
# ---
|
|
||||||
# Author: Craig Silverstein
|
|
||||||
#
|
|
||||||
# Just tries to run the gflags_unittest with various flags
|
|
||||||
# defined in gflags.cc, and make sure they give the
|
|
||||||
# appropriate exit status and appropriate error message.
|
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "USAGE: $0 <unittest exe> [top_srcdir] [tmpdir]"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
EXE="$1"
|
|
||||||
SRCDIR="${2:-./}"
|
|
||||||
TMPDIR="${3:-/tmp/gflags}"
|
|
||||||
EXE2="${EXE}2" # eg, gflags_unittest2
|
|
||||||
EXE3="${EXE}3" # eg, gflags_unittest3
|
|
||||||
|
|
||||||
# $1: executable
|
|
||||||
# $2: line-number $3: expected return code. $4: substring of expected output.
|
|
||||||
# $5: a substring you *don't* expect to find in the output. $6+ flags
|
|
||||||
ExpectExe() {
|
|
||||||
local executable="$1"
|
|
||||||
shift
|
|
||||||
local line_number="$1"
|
|
||||||
shift
|
|
||||||
local expected_rc="$1"
|
|
||||||
shift
|
|
||||||
local expected_output="$1"
|
|
||||||
shift
|
|
||||||
local unexpected_output="$1"
|
|
||||||
shift
|
|
||||||
|
|
||||||
# We always add --srcdir because it's needed for correctness
|
|
||||||
"$executable" --srcdir="$SRCDIR" "$@" > "$TMPDIR/test.$line_number" 2>&1
|
|
||||||
|
|
||||||
local actual_rc=$?
|
|
||||||
if [ $actual_rc != $expected_rc ]; then
|
|
||||||
echo "Test on line $line_number failed:" \
|
|
||||||
"expected rc $expected_rc, got $actual_rc"
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
if [ -n "$expected_output" ] &&
|
|
||||||
! fgrep -e "$expected_output" "$TMPDIR/test.$line_number" >/dev/null; then
|
|
||||||
echo "Test on line $line_number failed:" \
|
|
||||||
"did not find expected substring '$expected_output'"
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
if [ -n "$unexpected_output" ] &&
|
|
||||||
fgrep -e "$unexpected_output" "$TMPDIR/test.$line_number" >/dev/null; then
|
|
||||||
echo "Test line $line_number failed:" \
|
|
||||||
"found unexpected substring '$unexpected_output'"
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# $1: line-number $2: expected return code. $3: substring of expected output.
|
|
||||||
# $4: a substring you *don't* expect to find in the output. $5+ flags
|
|
||||||
Expect() {
|
|
||||||
ExpectExe "$EXE" "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
rm -rf "$TMPDIR"
|
|
||||||
mkdir "$TMPDIR" || exit 2
|
|
||||||
|
|
||||||
# Create a few flagfiles we can use later
|
|
||||||
echo "--version" > "$TMPDIR/flagfile.1"
|
|
||||||
echo "--foo=bar" > "$TMPDIR/flagfile.2"
|
|
||||||
echo "--nounused_bool" >> "$TMPDIR/flagfile.2"
|
|
||||||
echo "--flagfile=$TMPDIR/flagfile.2" > "$TMPDIR/flagfile.3"
|
|
||||||
|
|
||||||
# Set a few environment variables (useful for --tryfromenv)
|
|
||||||
export FLAGS_undefok=foo,bar
|
|
||||||
export FLAGS_weirdo=
|
|
||||||
export FLAGS_version=true
|
|
||||||
export FLAGS_help=false
|
|
||||||
|
|
||||||
# First, just make sure the unittest works as-is
|
|
||||||
Expect $LINENO 0 "PASS" ""
|
|
||||||
|
|
||||||
# --help should show all flags, including flags from gflags_reporting
|
|
||||||
Expect $LINENO 1 "/gflags_reporting.cc" "" --help
|
|
||||||
|
|
||||||
# Make sure that --help prints even very long helpstrings.
|
|
||||||
Expect $LINENO 1 "end of a long helpstring" "" --help
|
|
||||||
|
|
||||||
# Make sure --help reflects flag changes made before flag-parsing
|
|
||||||
Expect $LINENO 1 \
|
|
||||||
"-changed_bool1 (changed) type: bool default: true" "" --help
|
|
||||||
Expect $LINENO 1 \
|
|
||||||
"-changed_bool2 (changed) type: bool default: false currently: true" "" \
|
|
||||||
--help
|
|
||||||
# And on the command-line, too
|
|
||||||
Expect $LINENO 1 \
|
|
||||||
"-changeable_string_var () type: string default: \"1\" currently: \"2\"" \
|
|
||||||
"" --changeable_string_var 2 --help
|
|
||||||
|
|
||||||
# --nohelp and --help=false should be as if we didn't say anything
|
|
||||||
Expect $LINENO 0 "PASS" "" --nohelp
|
|
||||||
Expect $LINENO 0 "PASS" "" --help=false
|
|
||||||
|
|
||||||
# --helpfull is the same as help
|
|
||||||
Expect $LINENO 1 "/gflags_reporting.cc" "" -helpfull
|
|
||||||
|
|
||||||
# --helpshort should show only flags from the unittest itself
|
|
||||||
Expect $LINENO 1 "/gflags_unittest.cc" \
|
|
||||||
"/gflags_reporting.cc" --helpshort
|
|
||||||
|
|
||||||
# --helpshort should show the tldflag we created in the unittest dir
|
|
||||||
Expect $LINENO 1 "tldflag1" "/google.cc" --helpshort
|
|
||||||
Expect $LINENO 1 "tldflag2" "/google.cc" --helpshort
|
|
||||||
|
|
||||||
# --helpshort should work if the main source file is suffixed with [_-]main
|
|
||||||
ExpectExe "$EXE2" $LINENO 1 "/gflags_unittest-main.cc" \
|
|
||||||
"/gflags_reporting.cc" --helpshort
|
|
||||||
ExpectExe "$EXE3" $LINENO 1 "/gflags_unittest_main.cc" \
|
|
||||||
"/gflags_reporting.cc" --helpshort
|
|
||||||
|
|
||||||
# --helpon needs an argument
|
|
||||||
Expect $LINENO 1 \
|
|
||||||
"'--helpon' is missing its argument; flag description: show help on" \
|
|
||||||
"" --helpon
|
|
||||||
|
|
||||||
# --helpon argument indicates what file we'll show args from
|
|
||||||
Expect $LINENO 1 "/gflags.cc" "/gflags_unittest.cc" \
|
|
||||||
--helpon=gflags
|
|
||||||
|
|
||||||
# another way of specifying the argument
|
|
||||||
Expect $LINENO 1 "/gflags.cc" "/gflags_unittest.cc" \
|
|
||||||
--helpon gflags
|
|
||||||
|
|
||||||
# test another argument
|
|
||||||
Expect $LINENO 1 "/gflags_unittest.cc" "/gflags.cc" \
|
|
||||||
--helpon=gflags_unittest
|
|
||||||
|
|
||||||
# helpmatch is like helpon but takes substrings
|
|
||||||
Expect $LINENO 1 "/gflags_reporting.cc" \
|
|
||||||
"/gflags_unittest.cc" -helpmatch reporting
|
|
||||||
Expect $LINENO 1 "/gflags_unittest.cc" \
|
|
||||||
"/gflags.cc" -helpmatch=unittest
|
|
||||||
|
|
||||||
# if no flags are found with helpmatch or helpon, suggest --help
|
|
||||||
Expect $LINENO 1 "No modules matched" "/gflags_unittest.cc" \
|
|
||||||
-helpmatch=nosuchsubstring
|
|
||||||
Expect $LINENO 1 "No modules matched" "/gflags_unittest.cc" \
|
|
||||||
-helpon=nosuchmodule
|
|
||||||
|
|
||||||
# helppackage shows all the flags in the same dir as this unittest
|
|
||||||
# --help should show all flags, including flags from google.cc
|
|
||||||
Expect $LINENO 1 "/gflags_reporting.cc" "" --helppackage
|
|
||||||
|
|
||||||
# xml!
|
|
||||||
Expect $LINENO 1 "/gflags_unittest.cc</file>" \
|
|
||||||
"/gflags_unittest.cc:" --helpxml
|
|
||||||
|
|
||||||
# just print the version info and exit
|
|
||||||
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" --version
|
|
||||||
Expect $LINENO 0 "version test_version" "gflags_unittest.cc" --version
|
|
||||||
|
|
||||||
# --undefok is a fun flag...
|
|
||||||
Expect $LINENO 1 "unknown command line flag 'foo'" "" --undefok= --foo --unused_bool
|
|
||||||
Expect $LINENO 0 "PASS" "" --undefok=foo --foo --unused_bool
|
|
||||||
# If you say foo is ok to be undefined, we'll accept --nofoo as well
|
|
||||||
Expect $LINENO 0 "PASS" "" --undefok=foo --nofoo --unused_bool
|
|
||||||
# It's ok if the foo is in the middle
|
|
||||||
Expect $LINENO 0 "PASS" "" --undefok=fee,fi,foo,fum --foo --unused_bool
|
|
||||||
# But the spelling has to be just right...
|
|
||||||
Expect $LINENO 1 "unknown command line flag 'foo'" "" --undefok=fo --foo --unused_bool
|
|
||||||
Expect $LINENO 1 "unknown command line flag 'foo'" "" --undefok=foot --foo --unused_bool
|
|
||||||
|
|
||||||
# See if we can successfully load our flags from the flagfile
|
|
||||||
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
|
|
||||||
--flagfile="$TMPDIR/flagfile.1"
|
|
||||||
Expect $LINENO 0 "PASS" "" --flagfile="$TMPDIR/flagfile.2"
|
|
||||||
Expect $LINENO 0 "PASS" "" --flagfile="$TMPDIR/flagfile.3"
|
|
||||||
|
|
||||||
# Also try to load flags from the environment
|
|
||||||
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
|
|
||||||
--fromenv=version
|
|
||||||
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
|
|
||||||
--tryfromenv=version
|
|
||||||
Expect $LINENO 0 "PASS" "" --fromenv=help
|
|
||||||
Expect $LINENO 0 "PASS" "" --tryfromenv=help
|
|
||||||
Expect $LINENO 1 "helpfull not found in environment" "" --fromenv=helpfull
|
|
||||||
Expect $LINENO 0 "PASS" "" --tryfromenv=helpfull
|
|
||||||
Expect $LINENO 0 "PASS" "" --tryfromenv=undefok --foo
|
|
||||||
Expect $LINENO 1 "unknown command line flag" "" --tryfromenv=weirdo
|
|
||||||
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
|
|
||||||
--tryfromenv=test_bool,version,unused_bool
|
|
||||||
Expect $LINENO 1 "not found in environment" "" --fromenv=test_bool
|
|
||||||
Expect $LINENO 1 "unknown command line flag" "" --fromenv=test_bool,ok
|
|
||||||
# Here, the --version overrides the fromenv
|
|
||||||
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
|
|
||||||
--fromenv=test_bool,version,ok
|
|
||||||
|
|
||||||
# Make sure -- by itself stops argv processing
|
|
||||||
Expect $LINENO 0 "PASS" "" -- --help
|
|
||||||
|
|
||||||
|
|
||||||
# And we should die if the flag value doesn't pass the validator
|
|
||||||
Expect $LINENO 1 "ERROR: failed validation of new value 'true' for flag 'always_fail'" "" --always_fail
|
|
||||||
|
|
||||||
# TODO(user) And if locking in validators fails.
|
|
||||||
# Expect $LINENO 0 "PASS" "" --deadlock_if_cant_lock
|
|
||||||
|
|
||||||
echo "PASS"
|
|
||||||
exit 0
|
|
|
@ -1,2 +0,0 @@
|
||||||
--test_flag=1
|
|
||||||
--test_flag=2
|
|
|
@ -1,34 +0,0 @@
|
||||||
// Copyright (c) 2006, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// Header files have moved from the google directory to the gflags
|
|
||||||
// directory. This forwarding file is provided only for backwards
|
|
||||||
// compatibility. Use gflags/gflags.h in all new code.
|
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
|
|
@ -1,34 +0,0 @@
|
||||||
// Copyright (c) 2008, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// Header files have moved from the google directory to the gflags
|
|
||||||
// directory. This forwarding file is provided only for backwards
|
|
||||||
// compatibility. Use gflags/gflags_completions.h in all new code.
|
|
||||||
|
|
||||||
#include <gflags/gflags_completions.h>
|
|
|
@ -1,356 +0,0 @@
|
||||||
// Copyright (c) 2007, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// ---
|
|
||||||
//
|
|
||||||
// A simple mutex wrapper, supporting locks and read-write locks.
|
|
||||||
// You should assume the locks are *not* re-entrant.
|
|
||||||
//
|
|
||||||
// To use: you should define the following macros in your configure.ac:
|
|
||||||
// ACX_PTHREAD
|
|
||||||
// AC_RWLOCK
|
|
||||||
// The latter is defined in ../autoconf.
|
|
||||||
//
|
|
||||||
// This class is meant to be internal-only and should be wrapped by an
|
|
||||||
// internal namespace. Before you use this module, please give the
|
|
||||||
// name of your internal namespace for this module. Or, if you want
|
|
||||||
// to expose it, you'll want to move it to the Google namespace. We
|
|
||||||
// cannot put this class in global namespace because there can be some
|
|
||||||
// problems when we have multiple versions of Mutex in each shared object.
|
|
||||||
//
|
|
||||||
// NOTE: by default, we have #ifdef'ed out the TryLock() method.
|
|
||||||
// This is for two reasons:
|
|
||||||
// 1) TryLock() under Windows is a bit annoying (it requires a
|
|
||||||
// #define to be defined very early).
|
|
||||||
// 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG
|
|
||||||
// mode.
|
|
||||||
// If you need TryLock(), and either these two caveats are not a
|
|
||||||
// problem for you, or you're willing to work around them, then
|
|
||||||
// feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs
|
|
||||||
// in the code below.
|
|
||||||
//
|
|
||||||
// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy:
|
|
||||||
// http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html
|
|
||||||
// Because of that, we might as well use windows locks for
|
|
||||||
// cygwin. They seem to be more reliable than the cygwin pthreads layer.
|
|
||||||
//
|
|
||||||
// TRICKY IMPLEMENTATION NOTE:
|
|
||||||
// This class is designed to be safe to use during
|
|
||||||
// dynamic-initialization -- that is, by global constructors that are
|
|
||||||
// run before main() starts. The issue in this case is that
|
|
||||||
// dynamic-initialization happens in an unpredictable order, and it
|
|
||||||
// could be that someone else's dynamic initializer could call a
|
|
||||||
// function that tries to acquire this mutex -- but that all happens
|
|
||||||
// before this mutex's constructor has run. (This can happen even if
|
|
||||||
// the mutex and the function that uses the mutex are in the same .cc
|
|
||||||
// file.) Basically, because Mutex does non-trivial work in its
|
|
||||||
// constructor, it's not, in the naive implementation, safe to use
|
|
||||||
// before dynamic initialization has run on it.
|
|
||||||
//
|
|
||||||
// The solution used here is to pair the actual mutex primitive with a
|
|
||||||
// bool that is set to true when the mutex is dynamically initialized.
|
|
||||||
// (Before that it's false.) Then we modify all mutex routines to
|
|
||||||
// look at the bool, and not try to lock/unlock until the bool makes
|
|
||||||
// it to true (which happens after the Mutex constructor has run.)
|
|
||||||
//
|
|
||||||
// This works because before main() starts -- particularly, during
|
|
||||||
// dynamic initialization -- there are no threads, so a) it's ok that
|
|
||||||
// the mutex operations are a no-op, since we don't need locking then
|
|
||||||
// anyway; and b) we can be quite confident our bool won't change
|
|
||||||
// state between a call to Lock() and a call to Unlock() (that would
|
|
||||||
// require a global constructor in one translation unit to call Lock()
|
|
||||||
// and another global constructor in another translation unit to call
|
|
||||||
// Unlock() later, which is pretty perverse).
|
|
||||||
//
|
|
||||||
// That said, it's tricky, and can conceivably fail; it's safest to
|
|
||||||
// avoid trying to acquire a mutex in a global constructor, if you
|
|
||||||
// can. One way it can fail is that a really smart compiler might
|
|
||||||
// initialize the bool to true at static-initialization time (too
|
|
||||||
// early) rather than at dynamic-initialization time. To discourage
|
|
||||||
// that, we set is_safe_ to true in code (not the constructor
|
|
||||||
// colon-initializer) and set it to true via a function that always
|
|
||||||
// evaluates to true, but that the compiler can't know always
|
|
||||||
// evaluates to true. This should be good enough.
|
|
||||||
//
|
|
||||||
// A related issue is code that could try to access the mutex
|
|
||||||
// after it's been destroyed in the global destructors (because
|
|
||||||
// the Mutex global destructor runs before some other global
|
|
||||||
// destructor, that tries to acquire the mutex). The way we
|
|
||||||
// deal with this is by taking a constructor arg that global
|
|
||||||
// mutexes should pass in, that causes the destructor to do no
|
|
||||||
// work. We still depend on the compiler not doing anything
|
|
||||||
// weird to a Mutex's memory after it is destroyed, but for a
|
|
||||||
// static global variable, that's pretty safe.
|
|
||||||
|
|
||||||
#ifndef GOOGLE_MUTEX_H_
|
|
||||||
#define GOOGLE_MUTEX_H_
|
|
||||||
|
|
||||||
#include "config.h" // to figure out pthreads support
|
|
||||||
|
|
||||||
#if defined(NO_THREADS)
|
|
||||||
typedef int MutexType; // to keep a lock-count
|
|
||||||
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
|
|
||||||
# ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
|
|
||||||
# endif
|
|
||||||
# ifndef NOMINMAX
|
|
||||||
# define NOMINMAX // Don't want windows to override min()/max()
|
|
||||||
# endif
|
|
||||||
# ifdef GMUTEX_TRYLOCK
|
|
||||||
// We need Windows NT or later for TryEnterCriticalSection(). If you
|
|
||||||
// don't need that functionality, you can remove these _WIN32_WINNT
|
|
||||||
// lines, and change TryLock() to assert(0) or something.
|
|
||||||
# ifndef _WIN32_WINNT
|
|
||||||
# define _WIN32_WINNT 0x0400
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
# include <windows.h>
|
|
||||||
typedef CRITICAL_SECTION MutexType;
|
|
||||||
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
|
|
||||||
// Needed for pthread_rwlock_*. If it causes problems, you could take it
|
|
||||||
// out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
|
|
||||||
// *does* cause problems for FreeBSD, or MacOSX, but isn't needed
|
|
||||||
// for locking there.)
|
|
||||||
# ifdef __linux__
|
|
||||||
# if _XOPEN_SOURCE < 500 // including not being defined at all
|
|
||||||
# undef _XOPEN_SOURCE
|
|
||||||
# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
# include <pthread.h>
|
|
||||||
typedef pthread_rwlock_t MutexType;
|
|
||||||
#elif defined(HAVE_PTHREAD)
|
|
||||||
# include <pthread.h>
|
|
||||||
typedef pthread_mutex_t MutexType;
|
|
||||||
#else
|
|
||||||
# error Need to implement mutex.h for your architecture, or #define NO_THREADS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h> // for abort()
|
|
||||||
|
|
||||||
#define MUTEX_NAMESPACE gflags_mutex_namespace
|
|
||||||
|
|
||||||
namespace MUTEX_NAMESPACE {
|
|
||||||
|
|
||||||
class Mutex {
|
|
||||||
public:
|
|
||||||
// This is used for the single-arg constructor
|
|
||||||
enum LinkerInitialized { LINKER_INITIALIZED };
|
|
||||||
|
|
||||||
// Create a Mutex that is not held by anybody. This constructor is
|
|
||||||
// typically used for Mutexes allocated on the heap or the stack.
|
|
||||||
inline Mutex();
|
|
||||||
// This constructor should be used for global, static Mutex objects.
|
|
||||||
// It inhibits work being done by the destructor, which makes it
|
|
||||||
// safer for code that tries to acqiure this mutex in their global
|
|
||||||
// destructor.
|
|
||||||
inline Mutex(LinkerInitialized);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
inline ~Mutex();
|
|
||||||
|
|
||||||
inline void Lock(); // Block if needed until free then acquire exclusively
|
|
||||||
inline void Unlock(); // Release a lock acquired via Lock()
|
|
||||||
#ifdef GMUTEX_TRYLOCK
|
|
||||||
inline bool TryLock(); // If free, Lock() and return true, else return false
|
|
||||||
#endif
|
|
||||||
// Note that on systems that don't support read-write locks, these may
|
|
||||||
// be implemented as synonyms to Lock() and Unlock(). So you can use
|
|
||||||
// these for efficiency, but don't use them anyplace where being able
|
|
||||||
// to do shared reads is necessary to avoid deadlock.
|
|
||||||
inline void ReaderLock(); // Block until free or shared then acquire a share
|
|
||||||
inline void ReaderUnlock(); // Release a read share of this Mutex
|
|
||||||
inline void WriterLock() { Lock(); } // Acquire an exclusive lock
|
|
||||||
inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
|
|
||||||
|
|
||||||
private:
|
|
||||||
MutexType mutex_;
|
|
||||||
// We want to make sure that the compiler sets is_safe_ to true only
|
|
||||||
// when we tell it to, and never makes assumptions is_safe_ is
|
|
||||||
// always true. volatile is the most reliable way to do that.
|
|
||||||
volatile bool is_safe_;
|
|
||||||
// This indicates which constructor was called.
|
|
||||||
bool destroy_;
|
|
||||||
|
|
||||||
inline void SetIsSafe() { is_safe_ = true; }
|
|
||||||
|
|
||||||
// Catch the error of writing Mutex when intending MutexLock.
|
|
||||||
Mutex(Mutex* /*ignored*/) {}
|
|
||||||
// Disallow "evil" constructors
|
|
||||||
Mutex(const Mutex&);
|
|
||||||
void operator=(const Mutex&);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Now the implementation of Mutex for various systems
|
|
||||||
#if defined(NO_THREADS)
|
|
||||||
|
|
||||||
// When we don't have threads, we can be either reading or writing,
|
|
||||||
// but not both. We can have lots of readers at once (in no-threads
|
|
||||||
// mode, that's most likely to happen in recursive function calls),
|
|
||||||
// but only one writer. We represent this by having mutex_ be -1 when
|
|
||||||
// writing and a number > 0 when reading (and 0 when no lock is held).
|
|
||||||
//
|
|
||||||
// In debug mode, we assert these invariants, while in non-debug mode
|
|
||||||
// we do nothing, for efficiency. That's why everything is in an
|
|
||||||
// assert.
|
|
||||||
|
|
||||||
Mutex::Mutex() : mutex_(0) { }
|
|
||||||
Mutex::Mutex(Mutex::LinkerInitialized) : mutex_(0) { }
|
|
||||||
Mutex::~Mutex() { assert(mutex_ == 0); }
|
|
||||||
void Mutex::Lock() { assert(--mutex_ == -1); }
|
|
||||||
void Mutex::Unlock() { assert(mutex_++ == -1); }
|
|
||||||
#ifdef GMUTEX_TRYLOCK
|
|
||||||
bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; }
|
|
||||||
#endif
|
|
||||||
void Mutex::ReaderLock() { assert(++mutex_ > 0); }
|
|
||||||
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
|
|
||||||
|
|
||||||
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
|
|
||||||
|
|
||||||
Mutex::Mutex() : destroy_(true) {
|
|
||||||
InitializeCriticalSection(&mutex_);
|
|
||||||
SetIsSafe();
|
|
||||||
}
|
|
||||||
Mutex::Mutex(LinkerInitialized) : destroy_(false) {
|
|
||||||
InitializeCriticalSection(&mutex_);
|
|
||||||
SetIsSafe();
|
|
||||||
}
|
|
||||||
Mutex::~Mutex() { if (destroy_) DeleteCriticalSection(&mutex_); }
|
|
||||||
void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); }
|
|
||||||
void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); }
|
|
||||||
#ifdef GMUTEX_TRYLOCK
|
|
||||||
bool Mutex::TryLock() { return is_safe_ ?
|
|
||||||
TryEnterCriticalSection(&mutex_) != 0 : true; }
|
|
||||||
#endif
|
|
||||||
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
|
|
||||||
void Mutex::ReaderUnlock() { Unlock(); }
|
|
||||||
|
|
||||||
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
|
|
||||||
|
|
||||||
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
|
|
||||||
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
Mutex::Mutex() : destroy_(true) {
|
|
||||||
SetIsSafe();
|
|
||||||
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
|
|
||||||
}
|
|
||||||
Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
|
|
||||||
SetIsSafe();
|
|
||||||
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
|
|
||||||
}
|
|
||||||
Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_rwlock_destroy); }
|
|
||||||
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
|
|
||||||
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
|
|
||||||
#ifdef GMUTEX_TRYLOCK
|
|
||||||
bool Mutex::TryLock() { return is_safe_ ?
|
|
||||||
pthread_rwlock_trywrlock(&mutex_) == 0 : true; }
|
|
||||||
#endif
|
|
||||||
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
|
|
||||||
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
|
|
||||||
#undef SAFE_PTHREAD
|
|
||||||
|
|
||||||
#elif defined(HAVE_PTHREAD)
|
|
||||||
|
|
||||||
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
|
|
||||||
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
Mutex::Mutex() : destroy_(true) {
|
|
||||||
SetIsSafe();
|
|
||||||
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
|
|
||||||
}
|
|
||||||
Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
|
|
||||||
SetIsSafe();
|
|
||||||
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
|
|
||||||
}
|
|
||||||
Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_mutex_destroy); }
|
|
||||||
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
|
|
||||||
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
|
|
||||||
#ifdef GMUTEX_TRYLOCK
|
|
||||||
bool Mutex::TryLock() { return is_safe_ ?
|
|
||||||
pthread_mutex_trylock(&mutex_) == 0 : true; }
|
|
||||||
#endif
|
|
||||||
void Mutex::ReaderLock() { Lock(); }
|
|
||||||
void Mutex::ReaderUnlock() { Unlock(); }
|
|
||||||
#undef SAFE_PTHREAD
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
// Some helper classes
|
|
||||||
|
|
||||||
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
|
|
||||||
class MutexLock {
|
|
||||||
public:
|
|
||||||
explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
|
|
||||||
~MutexLock() { mu_->Unlock(); }
|
|
||||||
private:
|
|
||||||
Mutex * const mu_;
|
|
||||||
// Disallow "evil" constructors
|
|
||||||
MutexLock(const MutexLock&);
|
|
||||||
void operator=(const MutexLock&);
|
|
||||||
};
|
|
||||||
|
|
||||||
// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
|
|
||||||
class ReaderMutexLock {
|
|
||||||
public:
|
|
||||||
explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
|
|
||||||
~ReaderMutexLock() { mu_->ReaderUnlock(); }
|
|
||||||
private:
|
|
||||||
Mutex * const mu_;
|
|
||||||
// Disallow "evil" constructors
|
|
||||||
ReaderMutexLock(const ReaderMutexLock&);
|
|
||||||
void operator=(const ReaderMutexLock&);
|
|
||||||
};
|
|
||||||
|
|
||||||
class WriterMutexLock {
|
|
||||||
public:
|
|
||||||
explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
|
|
||||||
~WriterMutexLock() { mu_->WriterUnlock(); }
|
|
||||||
private:
|
|
||||||
Mutex * const mu_;
|
|
||||||
// Disallow "evil" constructors
|
|
||||||
WriterMutexLock(const WriterMutexLock&);
|
|
||||||
void operator=(const WriterMutexLock&);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
|
|
||||||
#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
|
|
||||||
#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
|
|
||||||
#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
|
|
||||||
|
|
||||||
} // namespace MUTEX_NAMESPACE
|
|
||||||
|
|
||||||
using namespace MUTEX_NAMESPACE;
|
|
||||||
|
|
||||||
#undef MUTEX_NAMESPACE
|
|
||||||
|
|
||||||
#endif /* #define GOOGLE_MUTEX_H__ */
|
|
|
@ -1,51 +0,0 @@
|
||||||
# libstdc++.la - a libtool library file
|
|
||||||
# Generated by ltmain.sh - GNU libtool 1.4a-GCC3.0 (1.641.2.256 2001/05/28 20:09:07 with GCC-local changes)
|
|
||||||
#
|
|
||||||
# Please DO NOT delete this file!
|
|
||||||
# It is necessary for linking the library.
|
|
||||||
|
|
||||||
# ---
|
|
||||||
# NOTE: This file lives in /usr/sfw/lib on Solaris 10. Unfortunately,
|
|
||||||
# due to an apparent bug in the Solaris 10 6/06 release,
|
|
||||||
# /usr/sfw/lib/libstdc++.la is empty. Below is the correct content,
|
|
||||||
# according to
|
|
||||||
# http://forum.java.sun.com/thread.jspa?threadID=5073150
|
|
||||||
# By passing LDFLAGS='-Lsrc/solaris' to configure, make will pick up
|
|
||||||
# this copy of the file rather than the empty copy in /usr/sfw/lib.
|
|
||||||
#
|
|
||||||
# Also see
|
|
||||||
# http://www.technicalarticles.org/index.php/Compiling_MySQL_5.0_on_Solaris_10
|
|
||||||
#
|
|
||||||
# Note: this is for 32-bit systems. If you have a 64-bit system,
|
|
||||||
# uncomment the appropriate dependency_libs line below.
|
|
||||||
# ----
|
|
||||||
|
|
||||||
# The name that we can dlopen(3).
|
|
||||||
dlname='libstdc++.so.6'
|
|
||||||
|
|
||||||
# Names of this library.
|
|
||||||
library_names='libstdc++.so.6.0.3 libstdc++.so.6 libstdc++.so'
|
|
||||||
|
|
||||||
# The name of the static archive.
|
|
||||||
old_library='libstdc++.a'
|
|
||||||
|
|
||||||
# Libraries that this one depends upon.
|
|
||||||
# 32-bit version:
|
|
||||||
dependency_libs='-lc -lm -L/usr/sfw/lib -lgcc_s'
|
|
||||||
# 64-bit version:
|
|
||||||
#dependency_libs='-L/lib/64 -lc -lm -L/usr/sfw/lib/64 -lgcc_s'
|
|
||||||
|
|
||||||
# Version information for libstdc++.
|
|
||||||
current=6
|
|
||||||
age=0
|
|
||||||
revision=3
|
|
||||||
|
|
||||||
# Is this an already installed library?
|
|
||||||
installed=yes
|
|
||||||
|
|
||||||
# Files to dlopen/dlpreopen
|
|
||||||
dlopen=''
|
|
||||||
dlpreopen=''
|
|
||||||
|
|
||||||
# Directory that this library needs to be installed in:
|
|
||||||
libdir='/usr/sfw/lib'
|
|
|
@ -1,325 +0,0 @@
|
||||||
// Copyright (c) 2011, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
// ---
|
|
||||||
//
|
|
||||||
// Some generically useful utility routines that in google-land would
|
|
||||||
// be their own projects. We make a shortened version here.
|
|
||||||
|
|
||||||
#ifndef GFLAGS_UTIL_H_
|
|
||||||
#define GFLAGS_UTIL_H_
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <config.h>
|
|
||||||
#ifdef HAVE_INTTYPES_H
|
|
||||||
# include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
#include <stdarg.h> // for va_*
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#ifdef HAVE_SYS_STAT_H
|
|
||||||
# include <sys/stat.h>
|
|
||||||
#endif // for mkdir()
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
// This is used for unittests for death-testing. It is defined in gflags.cc.
|
|
||||||
extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int);
|
|
||||||
|
|
||||||
// Work properly if either strtoll or strtoq is on this system
|
|
||||||
#ifdef HAVE_STRTOLL
|
|
||||||
# define strto64 strtoll
|
|
||||||
# define strtou64 strtoull
|
|
||||||
#elif HAVE_STRTOQ
|
|
||||||
# define strto64 strtoq
|
|
||||||
# define strtou64 strtouq
|
|
||||||
#else
|
|
||||||
// Neither strtoll nor strtoq are defined. I hope strtol works!
|
|
||||||
# define strto64 strtol
|
|
||||||
# define strtou64 strtoul
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// If we have inttypes.h, it will have defined PRId32/etc for us. If
|
|
||||||
// not, take our best guess.
|
|
||||||
#ifndef PRId32
|
|
||||||
# define PRId32 "d"
|
|
||||||
#endif
|
|
||||||
#ifndef PRId64
|
|
||||||
# define PRId64 "lld"
|
|
||||||
#endif
|
|
||||||
#ifndef PRIu64
|
|
||||||
# define PRIu64 "llu"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef signed char int8;
|
|
||||||
typedef unsigned char uint8;
|
|
||||||
|
|
||||||
// -- utility macros ---------------------------------------------------------
|
|
||||||
|
|
||||||
template <bool> struct CompileAssert {};
|
|
||||||
#define COMPILE_ASSERT(expr, msg) \
|
|
||||||
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
|
|
||||||
|
|
||||||
// Returns the number of elements in an array.
|
|
||||||
#define arraysize(arr) (sizeof(arr)/sizeof(*(arr)))
|
|
||||||
|
|
||||||
|
|
||||||
// -- logging and testing ---------------------------------------------------
|
|
||||||
|
|
||||||
// For now, we ignore the level for logging, and don't show *VLOG's at
|
|
||||||
// all, except by hand-editing the lines below
|
|
||||||
#define LOG(level) std::cerr
|
|
||||||
#define VLOG(level) if (true) {} else std::cerr
|
|
||||||
#define DVLOG(level) if (true) {} else std::cerr
|
|
||||||
|
|
||||||
// CHECK dies with a fatal error if condition is not true. It is *not*
|
|
||||||
// controlled by NDEBUG, so the check will be executed regardless of
|
|
||||||
// compilation mode. Therefore, it is safe to do things like:
|
|
||||||
// CHECK(fp->Write(x) == 4)
|
|
||||||
// We allow stream-like objects after this for debugging, but they're ignored.
|
|
||||||
#define EXPECT_TRUE(condition) \
|
|
||||||
if (true) { \
|
|
||||||
if (!(condition)) { \
|
|
||||||
fprintf(stderr, "Check failed: %s\n", #condition); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} else std::cerr << ""
|
|
||||||
|
|
||||||
#define EXPECT_OP(op, val1, val2) \
|
|
||||||
if (true) { \
|
|
||||||
if (!((val1) op (val2))) { \
|
|
||||||
fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} else std::cerr << ""
|
|
||||||
|
|
||||||
#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
|
|
||||||
#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
|
|
||||||
#define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2)
|
|
||||||
#define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2)
|
|
||||||
#define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2)
|
|
||||||
#define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2)
|
|
||||||
#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
|
|
||||||
|
|
||||||
// C99 declares isnan and isinf should be macros, so the #ifdef test
|
|
||||||
// should be reliable everywhere. Of course, it's not, but these
|
|
||||||
// are testing pertty marginal functionality anyway, so it's ok to
|
|
||||||
// not-run them even in situations they might, with effort, be made to work.
|
|
||||||
#ifdef isnan // Some compilers, like sun's for Solaris 10, don't define this
|
|
||||||
#define EXPECT_NAN(arg) \
|
|
||||||
do { \
|
|
||||||
if (!isnan(arg)) { \
|
|
||||||
fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
#define EXPECT_NAN(arg)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef isinf // Some compilers, like sun's for Solaris 10, don't define this
|
|
||||||
#define EXPECT_INF(arg) \
|
|
||||||
do { \
|
|
||||||
if (!isinf(arg)) { \
|
|
||||||
fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
#define EXPECT_INF(arg)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define EXPECT_DOUBLE_EQ(val1, val2) \
|
|
||||||
do { \
|
|
||||||
if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
|
|
||||||
fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define EXPECT_STREQ(val1, val2) \
|
|
||||||
do { \
|
|
||||||
if (strcmp((val1), (val2)) != 0) { \
|
|
||||||
fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
// Call this in a .cc file where you will later call RUN_ALL_TESTS in main().
|
|
||||||
#define TEST_INIT \
|
|
||||||
static std::vector<void (*)()> g_testlist; /* the tests to run */ \
|
|
||||||
static int RUN_ALL_TESTS() { \
|
|
||||||
std::vector<void (*)()>::const_iterator it; \
|
|
||||||
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \
|
|
||||||
(*it)(); /* The test will error-exit if there's a problem. */ \
|
|
||||||
} \
|
|
||||||
fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \
|
|
||||||
static_cast<int>(g_testlist.size())); \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that this macro uses a FlagSaver to keep tests isolated.
|
|
||||||
#define TEST(a, b) \
|
|
||||||
struct Test_##a##_##b { \
|
|
||||||
Test_##a##_##b() { g_testlist.push_back(&Run); } \
|
|
||||||
static void Run() { \
|
|
||||||
FlagSaver fs; \
|
|
||||||
fprintf(stderr, "Running test %s/%s\n", #a, #b); \
|
|
||||||
RunTest(); \
|
|
||||||
} \
|
|
||||||
static void RunTest(); \
|
|
||||||
}; \
|
|
||||||
static Test_##a##_##b g_test_##a##_##b; \
|
|
||||||
void Test_##a##_##b::RunTest()
|
|
||||||
|
|
||||||
// This is a dummy class that eases the google->opensource transition.
|
|
||||||
namespace testing {
|
|
||||||
class Test {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call this in a .cc file where you will later call EXPECT_DEATH
|
|
||||||
#define EXPECT_DEATH_INIT \
|
|
||||||
static bool g_called_exit; \
|
|
||||||
static void CalledExit(int) { g_called_exit = true; }
|
|
||||||
|
|
||||||
#define EXPECT_DEATH(fn, msg) \
|
|
||||||
do { \
|
|
||||||
g_called_exit = false; \
|
|
||||||
gflags_exitfunc = &CalledExit; \
|
|
||||||
fn; \
|
|
||||||
gflags_exitfunc = &exit; /* set back to its default */ \
|
|
||||||
if (!g_called_exit) { \
|
|
||||||
fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define GTEST_HAS_DEATH_TEST 1
|
|
||||||
|
|
||||||
// -- path routines ----------------------------------------------------------
|
|
||||||
|
|
||||||
// Tries to create the directory path as a temp-dir. If it fails,
|
|
||||||
// changes path to some directory it *can* create.
|
|
||||||
#if defined(__MINGW32__)
|
|
||||||
#include <io.h>
|
|
||||||
inline void MakeTmpdir(std::string* path) {
|
|
||||||
// I had trouble creating a directory in /tmp from mingw
|
|
||||||
*path = "./gflags_unittest_testdir";
|
|
||||||
mkdir(path->c_str()); // mingw has a weird one-arg mkdir
|
|
||||||
}
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
#include <direct.h>
|
|
||||||
inline void MakeTmpdir(std::string* path) {
|
|
||||||
char tmppath_buffer[1024];
|
|
||||||
int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
|
|
||||||
assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
|
|
||||||
assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it
|
|
||||||
*path = std::string(tmppath_buffer) + "gflags_unittest_testdir";
|
|
||||||
_mkdir(path->c_str());
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
inline void MakeTmpdir(std::string* path) {
|
|
||||||
mkdir(path->c_str(), 0755);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// -- string routines --------------------------------------------------------
|
|
||||||
|
|
||||||
inline void InternalStringPrintf(std::string* output, const char* format,
|
|
||||||
va_list ap) {
|
|
||||||
char space[128]; // try a small buffer and hope it fits
|
|
||||||
|
|
||||||
// It's possible for methods that use a va_list to invalidate
|
|
||||||
// the data in it upon use. The fix is to make a copy
|
|
||||||
// of the structure before using it and use that copy instead.
|
|
||||||
va_list backup_ap;
|
|
||||||
va_copy(backup_ap, ap);
|
|
||||||
int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
|
|
||||||
va_end(backup_ap);
|
|
||||||
|
|
||||||
if ((bytes_written >= 0) && (static_cast<size_t>(bytes_written) < sizeof(space))) {
|
|
||||||
output->append(space, bytes_written);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repeatedly increase buffer size until it fits.
|
|
||||||
int length = sizeof(space);
|
|
||||||
while (true) {
|
|
||||||
if (bytes_written < 0) {
|
|
||||||
// Older snprintf() behavior. :-( Just try doubling the buffer size
|
|
||||||
length *= 2;
|
|
||||||
} else {
|
|
||||||
// We need exactly "bytes_written+1" characters
|
|
||||||
length = bytes_written+1;
|
|
||||||
}
|
|
||||||
char* buf = new char[length];
|
|
||||||
|
|
||||||
// Restore the va_list before we use it again
|
|
||||||
va_copy(backup_ap, ap);
|
|
||||||
bytes_written = vsnprintf(buf, length, format, backup_ap);
|
|
||||||
va_end(backup_ap);
|
|
||||||
|
|
||||||
if ((bytes_written >= 0) && (bytes_written < length)) {
|
|
||||||
output->append(buf, bytes_written);
|
|
||||||
delete[] buf;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
delete[] buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clears output before writing to it.
|
|
||||||
inline void SStringPrintf(std::string* output, const char* format, ...) {
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, format);
|
|
||||||
output->clear();
|
|
||||||
InternalStringPrintf(output, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void StringAppendF(std::string* output, const char* format, ...) {
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, format);
|
|
||||||
InternalStringPrintf(output, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string StringPrintf(const char* format, ...) {
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, format);
|
|
||||||
std::string output;
|
|
||||||
InternalStringPrintf(&output, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
#endif // GFLAGS_UTIL_H_
|
|
|
@ -1,139 +0,0 @@
|
||||||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
|
||||||
|
|
||||||
/* Sometimes we accidentally #include this config.h instead of the one
|
|
||||||
in .. -- this is particularly true for msys/mingw, which uses the
|
|
||||||
unix config.h but also runs code in the windows directory.
|
|
||||||
*/
|
|
||||||
#ifdef __MINGW32__
|
|
||||||
#include "../config.h"
|
|
||||||
#define GOOGLE_GFLAGS_WINDOWS_CONFIG_H_
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef GOOGLE_GFLAGS_WINDOWS_CONFIG_H_
|
|
||||||
#define GOOGLE_GFLAGS_WINDOWS_CONFIG_H_
|
|
||||||
|
|
||||||
/* Always the empty-string on non-windows systems. On windows, should be
|
|
||||||
"__declspec(dllexport)". This way, when we compile the dll, we export our
|
|
||||||
functions/classes. It's safe to define this here because config.h is only
|
|
||||||
used internally, to compile the DLL, and every DLL source file #includes
|
|
||||||
"config.h" before anything else. */
|
|
||||||
#ifndef GFLAGS_DLL_DECL
|
|
||||||
# define GFLAGS_IS_A_DLL 1 /* not set if you're statically linking */
|
|
||||||
# define GFLAGS_DLL_DECL __declspec(dllexport)
|
|
||||||
# define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Namespace for Google classes */
|
|
||||||
#define GOOGLE_NAMESPACE ::google
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#undef HAVE_DLFCN_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fnmatch.h> header file. */
|
|
||||||
#undef HAVE_FNMATCH_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#undef HAVE_INTTYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#undef HAVE_MEMORY_H
|
|
||||||
|
|
||||||
/* define if the compiler implements namespaces */
|
|
||||||
#define HAVE_NAMESPACES 1
|
|
||||||
|
|
||||||
/* Define if you have POSIX threads libraries and header files. */
|
|
||||||
#undef HAVE_PTHREAD
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `putenv' function. */
|
|
||||||
#define HAVE_PUTENV 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `setenv' function. */
|
|
||||||
#undef HAVE_SETENV
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#undef HAVE_STDINT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#define HAVE_STDLIB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#undef HAVE_STRINGS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoll' function. */
|
|
||||||
#define HAVE_STRTOLL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoq' function. */
|
|
||||||
#define HAVE_STRTOQ 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#define HAVE_SYS_STAT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#undef HAVE_UNISTD_H
|
|
||||||
|
|
||||||
/* define if your compiler has __attribute__ */
|
|
||||||
#undef HAVE___ATTRIBUTE__
|
|
||||||
|
|
||||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
|
||||||
*/
|
|
||||||
#undef LT_OBJDIR
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#undef PACKAGE
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#undef PACKAGE_BUGREPORT
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#undef PACKAGE_NAME
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#undef PACKAGE_STRING
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#undef PACKAGE_TARNAME
|
|
||||||
|
|
||||||
/* Define to the home page for this package. */
|
|
||||||
#undef PACKAGE_URL
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#undef PACKAGE_VERSION
|
|
||||||
|
|
||||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
|
||||||
your system. */
|
|
||||||
#undef PTHREAD_CREATE_JOINABLE
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* the namespace where STL code like vector<> is defined */
|
|
||||||
#define STL_NAMESPACE std
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#undef VERSION
|
|
||||||
|
|
||||||
/* Stops putting the code inside the Google namespace */
|
|
||||||
#define _END_GOOGLE_NAMESPACE_ }
|
|
||||||
|
|
||||||
/* Puts following code inside the Google namespace */
|
|
||||||
#define _START_GOOGLE_NAMESPACE_ namespace google {
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
// Extra stuff not found in config.h.in
|
|
||||||
|
|
||||||
// This must be defined before the windows.h is included. It's needed
|
|
||||||
// for mutex.h, to give access to the TryLock method.
|
|
||||||
#ifndef _WIN32_WINNT
|
|
||||||
# define _WIN32_WINNT 0x0400
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO(csilvers): include windows/port.h in every relevant source file instead?
|
|
||||||
#include "windows/port.h"
|
|
||||||
|
|
||||||
#endif /* GOOGLE_GFLAGS_WINDOWS_CONFIG_H_ */
|
|
|
@ -1,569 +0,0 @@
|
||||||
// Copyright (c) 2006, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
// Revamped and reorganized by Craig Silverstein
|
|
||||||
//
|
|
||||||
// This is the file that should be included by any file which declares
|
|
||||||
// or defines a command line flag or wants to parse command line flags
|
|
||||||
// or print a program usage message (which will include information about
|
|
||||||
// flags). Executive summary, in the form of an example foo.cc file:
|
|
||||||
//
|
|
||||||
// #include "foo.h" // foo.h has a line "DECLARE_int32(start);"
|
|
||||||
// #include "validators.h" // hypothetical file defining ValidateIsFile()
|
|
||||||
//
|
|
||||||
// DEFINE_int32(end, 1000, "The last record to read");
|
|
||||||
//
|
|
||||||
// DEFINE_string(filename, "my_file.txt", "The file to read");
|
|
||||||
// // Crash if the specified file does not exist.
|
|
||||||
// static bool dummy = RegisterFlagValidator(&FLAGS_filename,
|
|
||||||
// &ValidateIsFile);
|
|
||||||
//
|
|
||||||
// DECLARE_bool(verbose); // some other file has a DEFINE_bool(verbose, ...)
|
|
||||||
//
|
|
||||||
// void MyFunc() {
|
|
||||||
// if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Then, at the command-line:
|
|
||||||
// ./foo --noverbose --start=5 --end=100
|
|
||||||
//
|
|
||||||
// For more details, see
|
|
||||||
// doc/gflags.html
|
|
||||||
//
|
|
||||||
// --- A note about thread-safety:
|
|
||||||
//
|
|
||||||
// We describe many functions in this routine as being thread-hostile,
|
|
||||||
// thread-compatible, or thread-safe. Here are the meanings we use:
|
|
||||||
//
|
|
||||||
// thread-safe: it is safe for multiple threads to call this routine
|
|
||||||
// (or, when referring to a class, methods of this class)
|
|
||||||
// concurrently.
|
|
||||||
// thread-hostile: it is not safe for multiple threads to call this
|
|
||||||
// routine (or methods of this class) concurrently. In gflags,
|
|
||||||
// most thread-hostile routines are intended to be called early in,
|
|
||||||
// or even before, main() -- that is, before threads are spawned.
|
|
||||||
// thread-compatible: it is safe for multiple threads to read from
|
|
||||||
// this variable (when applied to variables), or to call const
|
|
||||||
// methods of this class (when applied to classes), as long as no
|
|
||||||
// other thread is writing to the variable or calling non-const
|
|
||||||
// methods of this class.
|
|
||||||
|
|
||||||
#ifndef BASE_COMMANDLINEFLAGS_H_
|
|
||||||
#define BASE_COMMANDLINEFLAGS_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <gflags/gflags_declare.h> // IWYU pragma: export
|
|
||||||
namespace google {
|
|
||||||
|
|
||||||
//
|
|
||||||
// NOTE: all functions below MUST have an explicit 'extern' before
|
|
||||||
// them. Our automated opensourcing tools use this as a signal to do
|
|
||||||
// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
|
|
||||||
//
|
|
||||||
#if defined(_MSC_VER) && !defined(GFLAGS_DLL_DECL)
|
|
||||||
# define GFLAGS_DLL_DECL __declspec(dllimport)
|
|
||||||
#endif
|
|
||||||
#if defined(_MSC_VER) && !defined(GFLAGS_DLL_DEFINE_FLAG)
|
|
||||||
# define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// To actually define a flag in a file, use DEFINE_bool,
|
|
||||||
// DEFINE_string, etc. at the bottom of this file. You may also find
|
|
||||||
// it useful to register a validator with the flag. This ensures that
|
|
||||||
// when the flag is parsed from the commandline, or is later set via
|
|
||||||
// SetCommandLineOption, we call the validation function. It is _not_
|
|
||||||
// called when you assign the value to the flag directly using the = operator.
|
|
||||||
//
|
|
||||||
// The validation function should return true if the flag value is valid, and
|
|
||||||
// false otherwise. If the function returns false for the new setting of the
|
|
||||||
// flag, the flag will retain its current value. If it returns false for the
|
|
||||||
// default value, ParseCommandLineFlags() will die.
|
|
||||||
//
|
|
||||||
// This function is safe to call at global construct time (as in the
|
|
||||||
// example below).
|
|
||||||
//
|
|
||||||
// Example use:
|
|
||||||
// static bool ValidatePort(const char* flagname, int32 value) {
|
|
||||||
// if (value > 0 && value < 32768) // value is ok
|
|
||||||
// return true;
|
|
||||||
// printf("Invalid value for --%s: %d\n", flagname, (int)value);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// DEFINE_int32(port, 0, "What port to listen on");
|
|
||||||
// static bool dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort);
|
|
||||||
|
|
||||||
// Returns true if successfully registered, false if not (because the
|
|
||||||
// first argument doesn't point to a command-line flag, or because a
|
|
||||||
// validator is already registered for this flag).
|
|
||||||
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const bool* flag,
|
|
||||||
bool (*validate_fn)(const char*, bool));
|
|
||||||
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int32* flag,
|
|
||||||
bool (*validate_fn)(const char*, int32));
|
|
||||||
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int64* flag,
|
|
||||||
bool (*validate_fn)(const char*, int64));
|
|
||||||
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint64* flag,
|
|
||||||
bool (*validate_fn)(const char*, uint64));
|
|
||||||
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const double* flag,
|
|
||||||
bool (*validate_fn)(const char*, double));
|
|
||||||
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag,
|
|
||||||
bool (*validate_fn)(const char*,
|
|
||||||
const std::string&));
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// These methods are the best way to get access to info about the
|
|
||||||
// list of commandline flags. Note that these routines are pretty slow.
|
|
||||||
// GetAllFlags: mostly-complete info about the list, sorted by file.
|
|
||||||
// ShowUsageWithFlags: pretty-prints the list to stdout (what --help does)
|
|
||||||
// ShowUsageWithFlagsRestrict: limit to filenames with restrict as a substr
|
|
||||||
//
|
|
||||||
// In addition to accessing flags, you can also access argv[0] (the program
|
|
||||||
// name) and argv (the entire commandline), which we sock away a copy of.
|
|
||||||
// These variables are static, so you should only set them once.
|
|
||||||
|
|
||||||
struct GFLAGS_DLL_DECL CommandLineFlagInfo {
|
|
||||||
std::string name; // the name of the flag
|
|
||||||
std::string type; // the type of the flag: int32, etc
|
|
||||||
std::string description; // the "help text" associated with the flag
|
|
||||||
std::string current_value; // the current value, as a string
|
|
||||||
std::string default_value; // the default value, as a string
|
|
||||||
std::string filename; // 'cleaned' version of filename holding the flag
|
|
||||||
bool has_validator_fn; // true if RegisterFlagValidator called on this flag
|
|
||||||
bool is_default; // true if the flag has the default value and
|
|
||||||
// has not been set explicitly from the cmdline
|
|
||||||
// or via SetCommandLineOption
|
|
||||||
const void* flag_ptr; // pointer to the flag's current value (i.e. FLAGS_foo)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Using this inside of a validator is a recipe for a deadlock.
|
|
||||||
// TODO(user) Fix locking when validators are running, to make it safe to
|
|
||||||
// call validators during ParseAllFlags.
|
|
||||||
// Also make sure then to uncomment the corresponding unit test in
|
|
||||||
// gflags_unittest.sh
|
|
||||||
extern GFLAGS_DLL_DECL void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
|
|
||||||
// These two are actually defined in gflags_reporting.cc.
|
|
||||||
extern GFLAGS_DLL_DECL void ShowUsageWithFlags(const char *argv0); // what --help does
|
|
||||||
extern GFLAGS_DLL_DECL void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
|
|
||||||
|
|
||||||
// Create a descriptive string for a flag.
|
|
||||||
// Goes to some trouble to make pretty line breaks.
|
|
||||||
extern GFLAGS_DLL_DECL std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
|
|
||||||
|
|
||||||
// Thread-hostile; meant to be called before any threads are spawned.
|
|
||||||
extern GFLAGS_DLL_DECL void SetArgv(int argc, const char** argv);
|
|
||||||
|
|
||||||
// The following functions are thread-safe as long as SetArgv() is
|
|
||||||
// only called before any threads start.
|
|
||||||
extern GFLAGS_DLL_DECL const std::vector<std::string>& GetArgvs();
|
|
||||||
extern GFLAGS_DLL_DECL const char* GetArgv(); // all of argv as a string
|
|
||||||
extern GFLAGS_DLL_DECL const char* GetArgv0(); // only argv0
|
|
||||||
extern GFLAGS_DLL_DECL uint32 GetArgvSum(); // simple checksum of argv
|
|
||||||
extern GFLAGS_DLL_DECL const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
|
|
||||||
extern GFLAGS_DLL_DECL const char* ProgramInvocationShortName(); // basename(argv0)
|
|
||||||
|
|
||||||
// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
|
|
||||||
// called before any threads start.
|
|
||||||
extern GFLAGS_DLL_DECL const char* ProgramUsage(); // string set by SetUsageMessage()
|
|
||||||
|
|
||||||
// VersionString() is thread-safe as long as SetVersionString() is only
|
|
||||||
// called before any threads start.
|
|
||||||
extern GFLAGS_DLL_DECL const char* VersionString(); // string set by SetVersionString()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Normally you access commandline flags by just saying "if (FLAGS_foo)"
|
|
||||||
// or whatever, and set them by calling "FLAGS_foo = bar" (or, more
|
|
||||||
// commonly, via the DEFINE_foo macro). But if you need a bit more
|
|
||||||
// control, we have programmatic ways to get/set the flags as well.
|
|
||||||
// These programmatic ways to access flags are thread-safe, but direct
|
|
||||||
// access is only thread-compatible.
|
|
||||||
|
|
||||||
// Return true iff the flagname was found.
|
|
||||||
// OUTPUT is set to the flag's value, or unchanged if we return false.
|
|
||||||
extern GFLAGS_DLL_DECL bool GetCommandLineOption(const char* name, std::string* OUTPUT);
|
|
||||||
|
|
||||||
// Return true iff the flagname was found. OUTPUT is set to the flag's
|
|
||||||
// CommandLineFlagInfo or unchanged if we return false.
|
|
||||||
extern GFLAGS_DLL_DECL bool GetCommandLineFlagInfo(const char* name,
|
|
||||||
CommandLineFlagInfo* OUTPUT);
|
|
||||||
|
|
||||||
// Return the CommandLineFlagInfo of the flagname. exit() if name not found.
|
|
||||||
// Example usage, to check if a flag's value is currently the default value:
|
|
||||||
// if (GetCommandLineFlagInfoOrDie("foo").is_default) ...
|
|
||||||
extern GFLAGS_DLL_DECL CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
|
|
||||||
|
|
||||||
enum GFLAGS_DLL_DECL FlagSettingMode {
|
|
||||||
// update the flag's value (can call this multiple times).
|
|
||||||
SET_FLAGS_VALUE,
|
|
||||||
// update the flag's value, but *only if* it has not yet been updated
|
|
||||||
// with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
|
|
||||||
SET_FLAG_IF_DEFAULT,
|
|
||||||
// set the flag's default value to this. If the flag has not yet updated
|
|
||||||
// yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
|
|
||||||
// change the flag's current value to the new default value as well.
|
|
||||||
SET_FLAGS_DEFAULT
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set a particular flag ("command line option"). Returns a string
|
|
||||||
// describing the new value that the option has been set to. The
|
|
||||||
// return value API is not well-specified, so basically just depend on
|
|
||||||
// it to be empty if the setting failed for some reason -- the name is
|
|
||||||
// not a valid flag name, or the value is not a valid value -- and
|
|
||||||
// non-empty else.
|
|
||||||
|
|
||||||
// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
|
|
||||||
extern GFLAGS_DLL_DECL std::string SetCommandLineOption(const char* name, const char* value);
|
|
||||||
extern GFLAGS_DLL_DECL std::string SetCommandLineOptionWithMode(const char* name, const char* value,
|
|
||||||
FlagSettingMode set_mode);
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Saves the states (value, default value, whether the user has set
|
|
||||||
// the flag, registered validators, etc) of all flags, and restores
|
|
||||||
// them when the FlagSaver is destroyed. This is very useful in
|
|
||||||
// tests, say, when you want to let your tests change the flags, but
|
|
||||||
// make sure that they get reverted to the original states when your
|
|
||||||
// test is complete.
|
|
||||||
//
|
|
||||||
// Example usage:
|
|
||||||
// void TestFoo() {
|
|
||||||
// FlagSaver s1;
|
|
||||||
// FLAG_foo = false;
|
|
||||||
// FLAG_bar = "some value";
|
|
||||||
//
|
|
||||||
// // test happens here. You can return at any time
|
|
||||||
// // without worrying about restoring the FLAG values.
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Note: This class is marked with ATTRIBUTE_UNUSED because all the
|
|
||||||
// work is done in the constructor and destructor, so in the standard
|
|
||||||
// usage example above, the compiler would complain that it's an
|
|
||||||
// unused variable.
|
|
||||||
//
|
|
||||||
// This class is thread-safe. However, its destructor writes to
|
|
||||||
// exactly the set of flags that have changed value during its
|
|
||||||
// lifetime, so concurrent _direct_ access to those flags
|
|
||||||
// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe.
|
|
||||||
|
|
||||||
class GFLAGS_DLL_DECL FlagSaver {
|
|
||||||
public:
|
|
||||||
FlagSaver();
|
|
||||||
~FlagSaver();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class FlagSaverImpl* impl_; // we use pimpl here to keep API steady
|
|
||||||
|
|
||||||
FlagSaver(const FlagSaver&); // no copying!
|
|
||||||
void operator=(const FlagSaver&);
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Some deprecated or hopefully-soon-to-be-deprecated functions.
|
|
||||||
|
|
||||||
// This is often used for logging. TODO(csilvers): figure out a better way
|
|
||||||
extern GFLAGS_DLL_DECL std::string CommandlineFlagsIntoString();
|
|
||||||
// Usually where this is used, a FlagSaver should be used instead.
|
|
||||||
extern GFLAGS_DLL_DECL bool ReadFlagsFromString(const std::string& flagfilecontents,
|
|
||||||
const char* prog_name,
|
|
||||||
bool errors_are_fatal); // uses SET_FLAGS_VALUE
|
|
||||||
|
|
||||||
// These let you manually implement --flagfile functionality.
|
|
||||||
// DEPRECATED.
|
|
||||||
extern GFLAGS_DLL_DECL bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
|
|
||||||
extern GFLAGS_DLL_DECL bool ReadFromFlagsFile(const std::string& filename, const char* prog_name,
|
|
||||||
bool errors_are_fatal); // uses SET_FLAGS_VALUE
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Useful routines for initializing flags from the environment.
|
|
||||||
// In each case, if 'varname' does not exist in the environment
|
|
||||||
// return defval. If 'varname' does exist but is not valid
|
|
||||||
// (e.g., not a number for an int32 flag), abort with an error.
|
|
||||||
// Otherwise, return the value. NOTE: for booleans, for true use
|
|
||||||
// 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'.
|
|
||||||
|
|
||||||
extern GFLAGS_DLL_DECL bool BoolFromEnv(const char *varname, bool defval);
|
|
||||||
extern GFLAGS_DLL_DECL int32 Int32FromEnv(const char *varname, int32 defval);
|
|
||||||
extern GFLAGS_DLL_DECL int64 Int64FromEnv(const char *varname, int64 defval);
|
|
||||||
extern GFLAGS_DLL_DECL uint64 Uint64FromEnv(const char *varname, uint64 defval);
|
|
||||||
extern GFLAGS_DLL_DECL double DoubleFromEnv(const char *varname, double defval);
|
|
||||||
extern GFLAGS_DLL_DECL const char *StringFromEnv(const char *varname, const char *defval);
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// The next two functions parse gflags from main():
|
|
||||||
|
|
||||||
// Set the "usage" message for this program. For example:
|
|
||||||
// string usage("This program does nothing. Sample usage:\n");
|
|
||||||
// usage += argv[0] + " <uselessarg1> <uselessarg2>";
|
|
||||||
// SetUsageMessage(usage);
|
|
||||||
// Do not include commandline flags in the usage: we do that for you!
|
|
||||||
// Thread-hostile; meant to be called before any threads are spawned.
|
|
||||||
extern GFLAGS_DLL_DECL void SetUsageMessage(const std::string& usage);
|
|
||||||
|
|
||||||
// Sets the version string, which is emitted with --version.
|
|
||||||
// For instance: SetVersionString("1.3");
|
|
||||||
// Thread-hostile; meant to be called before any threads are spawned.
|
|
||||||
extern GFLAGS_DLL_DECL void SetVersionString(const std::string& version);
|
|
||||||
|
|
||||||
|
|
||||||
// Looks for flags in argv and parses them. Rearranges argv to put
|
|
||||||
// flags first, or removes them entirely if remove_flags is true.
|
|
||||||
// If a flag is defined more than once in the command line or flag
|
|
||||||
// file, the last definition is used. Returns the index (into argv)
|
|
||||||
// of the first non-flag argument.
|
|
||||||
// See top-of-file for more details on this function.
|
|
||||||
#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead.
|
|
||||||
extern GFLAGS_DLL_DECL uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Calls to ParseCommandLineNonHelpFlags and then to
|
|
||||||
// HandleCommandLineHelpFlags can be used instead of a call to
|
|
||||||
// ParseCommandLineFlags during initialization, in order to allow for
|
|
||||||
// changing default values for some FLAGS (via
|
|
||||||
// e.g. SetCommandLineOptionWithMode calls) between the time of
|
|
||||||
// command line parsing and the time of dumping help information for
|
|
||||||
// the flags as a result of command line parsing. If a flag is
|
|
||||||
// defined more than once in the command line or flag file, the last
|
|
||||||
// definition is used. Returns the index (into argv) of the first
|
|
||||||
// non-flag argument. (If remove_flags is true, will always return 1.)
|
|
||||||
extern GFLAGS_DLL_DECL uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv,
|
|
||||||
bool remove_flags);
|
|
||||||
// This is actually defined in gflags_reporting.cc.
|
|
||||||
// This function is misnamed (it also handles --version, etc.), but
|
|
||||||
// it's too late to change that now. :-(
|
|
||||||
extern GFLAGS_DLL_DECL void HandleCommandLineHelpFlags(); // in gflags_reporting.cc
|
|
||||||
|
|
||||||
// Allow command line reparsing. Disables the error normally
|
|
||||||
// generated when an unknown flag is found, since it may be found in a
|
|
||||||
// later parse. Thread-hostile; meant to be called before any threads
|
|
||||||
// are spawned.
|
|
||||||
extern GFLAGS_DLL_DECL void AllowCommandLineReparsing();
|
|
||||||
|
|
||||||
// Reparse the flags that have not yet been recognized. Only flags
|
|
||||||
// registered since the last parse will be recognized. Any flag value
|
|
||||||
// must be provided as part of the argument using "=", not as a
|
|
||||||
// separate command line argument that follows the flag argument.
|
|
||||||
// Intended for handling flags from dynamically loaded libraries,
|
|
||||||
// since their flags are not registered until they are loaded.
|
|
||||||
extern GFLAGS_DLL_DECL void ReparseCommandLineNonHelpFlags();
|
|
||||||
|
|
||||||
// Clean up memory allocated by flags. This is only needed to reduce
|
|
||||||
// the quantity of "potentially leaked" reports emitted by memory
|
|
||||||
// debugging tools such as valgrind. It is not required for normal
|
|
||||||
// operation, or for the google perftools heap-checker. It must only
|
|
||||||
// be called when the process is about to exit, and all threads that
|
|
||||||
// might access flags are quiescent. Referencing flags after this is
|
|
||||||
// called will have unexpected consequences. This is not safe to run
|
|
||||||
// when multiple threads might be running: the function is
|
|
||||||
// thread-hostile.
|
|
||||||
extern GFLAGS_DLL_DECL void ShutDownCommandLineFlags();
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// Now come the command line flag declaration/definition macros that
|
|
||||||
// will actually be used. They're kind of hairy. A major reason
|
|
||||||
// for this is initialization: we want people to be able to access
|
|
||||||
// variables in global constructors and have that not crash, even if
|
|
||||||
// their global constructor runs before the global constructor here.
|
|
||||||
// (Obviously, we can't guarantee the flags will have the correct
|
|
||||||
// default value in that case, but at least accessing them is safe.)
|
|
||||||
// The only way to do that is have flags point to a static buffer.
|
|
||||||
// So we make one, using a union to ensure proper alignment, and
|
|
||||||
// then use placement-new to actually set up the flag with the
|
|
||||||
// correct default value. In the same vein, we have to worry about
|
|
||||||
// flag access in global destructors, so FlagRegisterer has to be
|
|
||||||
// careful never to destroy the flag-values it constructs.
|
|
||||||
//
|
|
||||||
// Note that when we define a flag variable FLAGS_<name>, we also
|
|
||||||
// preemptively define a junk variable, FLAGS_no<name>. This is to
|
|
||||||
// cause a link-time error if someone tries to define 2 flags with
|
|
||||||
// names like "logging" and "nologging". We do this because a bool
|
|
||||||
// flag FLAG can be set from the command line to true with a "-FLAG"
|
|
||||||
// argument, and to false with a "-noFLAG" argument, and so this can
|
|
||||||
// potentially avert confusion.
|
|
||||||
//
|
|
||||||
// We also put flags into their own namespace. It is purposefully
|
|
||||||
// named in an opaque way that people should have trouble typing
|
|
||||||
// directly. The idea is that DEFINE puts the flag in the weird
|
|
||||||
// namespace, and DECLARE imports the flag from there into the current
|
|
||||||
// namespace. The net result is to force people to use DECLARE to get
|
|
||||||
// access to a flag, rather than saying "extern bool FLAGS_whatever;"
|
|
||||||
// or some such instead. We want this so we can put extra
|
|
||||||
// functionality (like sanity-checking) in DECLARE if we want, and
|
|
||||||
// make sure it is picked up everywhere.
|
|
||||||
//
|
|
||||||
// We also put the type of the variable in the namespace, so that
|
|
||||||
// people can't DECLARE_int32 something that they DEFINE_bool'd
|
|
||||||
// elsewhere.
|
|
||||||
|
|
||||||
class GFLAGS_DLL_DECL FlagRegisterer {
|
|
||||||
public:
|
|
||||||
FlagRegisterer(const char* name, const char* type,
|
|
||||||
const char* help, const char* filename,
|
|
||||||
void* current_storage, void* defvalue_storage);
|
|
||||||
};
|
|
||||||
|
|
||||||
// If your application #defines STRIP_FLAG_HELP to a non-zero value
|
|
||||||
// before #including this file, we remove the help message from the
|
|
||||||
// binary file. This can reduce the size of the resulting binary
|
|
||||||
// somewhat, and may also be useful for security reasons.
|
|
||||||
|
|
||||||
extern GFLAGS_DLL_DECL const char kStrippedFlagHelp[];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef SWIG // In swig, ignore the main flag declarations
|
|
||||||
|
|
||||||
#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
|
|
||||||
// Need this construct to avoid the 'defined but not used' warning.
|
|
||||||
#define MAYBE_STRIPPED_HELP(txt) \
|
|
||||||
(false ? (txt) : ::google::kStrippedFlagHelp)
|
|
||||||
#else
|
|
||||||
#define MAYBE_STRIPPED_HELP(txt) txt
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Each command-line flag has two variables associated with it: one
|
|
||||||
// with the current value, and one with the default value. However,
|
|
||||||
// we have a third variable, which is where value is assigned; it's a
|
|
||||||
// constant. This guarantees that FLAG_##value is initialized at
|
|
||||||
// static initialization time (e.g. before program-start) rather than
|
|
||||||
// than global construction time (which is after program-start but
|
|
||||||
// before main), at least when 'value' is a compile-time constant. We
|
|
||||||
// use a small trick for the "default value" variable, and call it
|
|
||||||
// FLAGS_no<name>. This serves the second purpose of assuring a
|
|
||||||
// compile error if someone tries to define a flag named no<name>
|
|
||||||
// which is illegal (--foo and --nofoo both affect the "foo" flag).
|
|
||||||
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
|
|
||||||
namespace fL##shorttype { \
|
|
||||||
static const type FLAGS_nono##name = value; \
|
|
||||||
/* We always want to export defined variables, dll or no */ \
|
|
||||||
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
|
|
||||||
type FLAGS_no##name = FLAGS_nono##name; \
|
|
||||||
static ::google::FlagRegisterer o_##name( \
|
|
||||||
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
|
|
||||||
&FLAGS_##name, &FLAGS_no##name); \
|
|
||||||
} \
|
|
||||||
using fL##shorttype::FLAGS_##name
|
|
||||||
|
|
||||||
// For DEFINE_bool, we want to do the extra check that the passed-in
|
|
||||||
// value is actually a bool, and not a string or something that can be
|
|
||||||
// coerced to a bool. These declarations (no definition needed!) will
|
|
||||||
// help us do that, and never evaluate From, which is important.
|
|
||||||
// We'll use 'sizeof(IsBool(val))' to distinguish. This code requires
|
|
||||||
// that the compiler have different sizes for bool & double. Since
|
|
||||||
// this is not guaranteed by the standard, we check it with a
|
|
||||||
// COMPILE_ASSERT.
|
|
||||||
namespace fLB {
|
|
||||||
struct CompileAssert {};
|
|
||||||
typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[
|
|
||||||
(sizeof(double) != sizeof(bool)) ? 1 : -1];
|
|
||||||
template<typename From> double GFLAGS_DLL_DECL IsBoolFlag(const From& from);
|
|
||||||
GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
|
|
||||||
} // namespace fLB
|
|
||||||
|
|
||||||
// Here are the actual DEFINE_*-macros. The respective DECLARE_*-macros
|
|
||||||
// are in a separate include, gflags_declare.h, for reducing
|
|
||||||
// the physical transitive size for DECLARE use.
|
|
||||||
#define DEFINE_bool(name, val, txt) \
|
|
||||||
namespace fLB { \
|
|
||||||
typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \
|
|
||||||
(sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \
|
|
||||||
} \
|
|
||||||
DEFINE_VARIABLE(bool, B, name, val, txt)
|
|
||||||
|
|
||||||
#define DEFINE_int32(name, val, txt) \
|
|
||||||
DEFINE_VARIABLE(::google::int32, I, \
|
|
||||||
name, val, txt)
|
|
||||||
|
|
||||||
#define DEFINE_int64(name, val, txt) \
|
|
||||||
DEFINE_VARIABLE(::google::int64, I64, \
|
|
||||||
name, val, txt)
|
|
||||||
|
|
||||||
#define DEFINE_uint64(name,val, txt) \
|
|
||||||
DEFINE_VARIABLE(::google::uint64, U64, \
|
|
||||||
name, val, txt)
|
|
||||||
|
|
||||||
#define DEFINE_double(name, val, txt) \
|
|
||||||
DEFINE_VARIABLE(double, D, name, val, txt)
|
|
||||||
|
|
||||||
// Strings are trickier, because they're not a POD, so we can't
|
|
||||||
// construct them at static-initialization time (instead they get
|
|
||||||
// constructed at global-constructor time, which is much later). To
|
|
||||||
// try to avoid crashes in that case, we use a char buffer to store
|
|
||||||
// the string, which we can static-initialize, and then placement-new
|
|
||||||
// into it later. It's not perfect, but the best we can do.
|
|
||||||
|
|
||||||
namespace fLS {
|
|
||||||
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
const char *value) {
|
|
||||||
return new(stringspot) clstring(value);
|
|
||||||
}
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
const clstring &value) {
|
|
||||||
return new(stringspot) clstring(value);
|
|
||||||
}
|
|
||||||
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
|
|
||||||
int value);
|
|
||||||
} // namespace fLS
|
|
||||||
|
|
||||||
// We need to define a var named FLAGS_no##name so people don't define
|
|
||||||
// --string and --nostring. And we need a temporary place to put val
|
|
||||||
// so we don't have to evaluate it twice. Two great needs that go
|
|
||||||
// great together!
|
|
||||||
// The weird 'using' + 'extern' inside the fLS namespace is to work around
|
|
||||||
// an unknown compiler bug/issue with the gcc 4.2.1 on SUSE 10. See
|
|
||||||
// http://code.google.com/p/google-gflags/issues/detail?id=20
|
|
||||||
#define DEFINE_string(name, val, txt) \
|
|
||||||
namespace fLS { \
|
|
||||||
using ::fLS::clstring; \
|
|
||||||
static union { void* align; char s[sizeof(clstring)]; } s_##name[2]; \
|
|
||||||
clstring* const FLAGS_no##name = ::fLS:: \
|
|
||||||
dont_pass0toDEFINE_string(s_##name[0].s, \
|
|
||||||
val); \
|
|
||||||
static ::google::FlagRegisterer o_##name( \
|
|
||||||
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
|
|
||||||
s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
|
|
||||||
extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \
|
|
||||||
using fLS::FLAGS_##name; \
|
|
||||||
clstring& FLAGS_##name = *FLAGS_no##name; \
|
|
||||||
} \
|
|
||||||
using fLS::FLAGS_##name
|
|
||||||
|
|
||||||
#endif // SWIG
|
|
||||||
|
|
||||||
#endif // BASE_COMMANDLINEFLAGS_H_
|
|
|
@ -1,132 +0,0 @@
|
||||||
// Copyright (c) 2008, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// ---
|
|
||||||
|
|
||||||
//
|
|
||||||
// Implement helpful bash-style command line flag completions
|
|
||||||
//
|
|
||||||
// ** Functional API:
|
|
||||||
// HandleCommandLineCompletions() should be called early during
|
|
||||||
// program startup, but after command line flag code has been
|
|
||||||
// initialized, such as the beginning of HandleCommandLineHelpFlags().
|
|
||||||
// It checks the value of the flag --tab_completion_word. If this
|
|
||||||
// flag is empty, nothing happens here. If it contains a string,
|
|
||||||
// however, then HandleCommandLineCompletions() will hijack the
|
|
||||||
// process, attempting to identify the intention behind this
|
|
||||||
// completion. Regardless of the outcome of this deduction, the
|
|
||||||
// process will be terminated, similar to --helpshort flag
|
|
||||||
// handling.
|
|
||||||
//
|
|
||||||
// ** Overview of Bash completions:
|
|
||||||
// Bash can be told to programatically determine completions for the
|
|
||||||
// current 'cursor word'. It does this by (in this case) invoking a
|
|
||||||
// command with some additional arguments identifying the command
|
|
||||||
// being executed, the word being completed, and the previous word
|
|
||||||
// (if any). Bash then expects a sequence of output lines to be
|
|
||||||
// printed to stdout. If these lines all contain a common prefix
|
|
||||||
// longer than the cursor word, bash will replace the cursor word
|
|
||||||
// with that common prefix, and display nothing. If there isn't such
|
|
||||||
// a common prefix, bash will display the lines in pages using 'more'.
|
|
||||||
//
|
|
||||||
// ** Strategy taken for command line completions:
|
|
||||||
// If we can deduce either the exact flag intended, or a common flag
|
|
||||||
// prefix, we'll output exactly that. Otherwise, if information
|
|
||||||
// must be displayed to the user, we'll take the opportunity to add
|
|
||||||
// some helpful information beyond just the flag name (specifically,
|
|
||||||
// we'll include the default flag value and as much of the flag's
|
|
||||||
// description as can fit on a single terminal line width, as specified
|
|
||||||
// by the flag --tab_completion_columns). Furthermore, we'll try to
|
|
||||||
// make bash order the output such that the most useful or relevent
|
|
||||||
// flags are the most likely to be shown at the top.
|
|
||||||
//
|
|
||||||
// ** Additional features:
|
|
||||||
// To assist in finding that one really useful flag, substring matching
|
|
||||||
// was implemented. Before pressing a <TAB> to get completion for the
|
|
||||||
// current word, you can append one or more '?' to the flag to do
|
|
||||||
// substring matching. Here's the semantics:
|
|
||||||
// --foo<TAB> Show me all flags with names prefixed by 'foo'
|
|
||||||
// --foo?<TAB> Show me all flags with 'foo' somewhere in the name
|
|
||||||
// --foo??<TAB> Same as prior case, but also search in module
|
|
||||||
// definition path for 'foo'
|
|
||||||
// --foo???<TAB> Same as prior case, but also search in flag
|
|
||||||
// descriptions for 'foo'
|
|
||||||
// Finally, we'll trim the output to a relatively small number of
|
|
||||||
// flags to keep bash quiet about the verbosity of output. If one
|
|
||||||
// really wanted to see all possible matches, appending a '+' to the
|
|
||||||
// search word will force the exhaustive list of matches to be printed.
|
|
||||||
//
|
|
||||||
// ** How to have bash accept completions from a binary:
|
|
||||||
// Bash requires that it be informed about each command that programmatic
|
|
||||||
// completion should be enabled for. Example addition to a .bashrc
|
|
||||||
// file would be (your path to gflags_completions.sh file may differ):
|
|
||||||
|
|
||||||
/*
|
|
||||||
$ complete -o bashdefault -o default -o nospace -C \
|
|
||||||
'/home/build/eng/bash/bash_completions.sh --tab_completion_columns $COLUMNS' \
|
|
||||||
time env binary_name another_binary [...]
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This would allow the following to work:
|
|
||||||
// $ /path/to/binary_name --vmodule<TAB>
|
|
||||||
// Or:
|
|
||||||
// $ ./bin/path/another_binary --gfs_u<TAB>
|
|
||||||
// (etc)
|
|
||||||
//
|
|
||||||
// Sadly, it appears that bash gives no easy way to force this behavior for
|
|
||||||
// all commands. That's where the "time" in the above example comes in.
|
|
||||||
// If you haven't specifically added a command to the list of completion
|
|
||||||
// supported commands, you can still get completions by prefixing the
|
|
||||||
// entire command with "env".
|
|
||||||
// $ env /some/brand/new/binary --vmod<TAB>
|
|
||||||
// Assuming that "binary" is a newly compiled binary, this should still
|
|
||||||
// produce the expected completion output.
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
|
|
||||||
#define BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
|
|
||||||
|
|
||||||
// Annoying stuff for windows -- makes sure clients can import these functions
|
|
||||||
//
|
|
||||||
// NOTE: all functions below MUST have an explicit 'extern' before
|
|
||||||
// them. Our automated opensourcing tools use this as a signal to do
|
|
||||||
// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
|
|
||||||
//
|
|
||||||
#if defined(_MSC_VER) && !defined(GFLAGS_DLL_DECL)
|
|
||||||
# define GFLAGS_DLL_DECL __declspec(dllimport)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace google {
|
|
||||||
|
|
||||||
extern GFLAGS_DLL_DECL void HandleCommandLineCompletions(void);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
|
|
|
@ -1,114 +0,0 @@
|
||||||
// Copyright (c) 1999, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
//
|
|
||||||
// Revamped and reorganized by Craig Silverstein
|
|
||||||
//
|
|
||||||
// This is the file that should be included by any file which declares
|
|
||||||
// command line flag.
|
|
||||||
|
|
||||||
#ifndef BASE_COMMANDLINEFLAGS_DECLARE_H_
|
|
||||||
#define BASE_COMMANDLINEFLAGS_DECLARE_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#if 0
|
|
||||||
#include <stdint.h> // the normal place uint16_t is defined
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
#include <sys/types.h> // the normal place u_int16_t is defined
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
#include <inttypes.h> // a third place for uint16_t or u_int16_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace google {
|
|
||||||
#if 0 // the C99 format
|
|
||||||
typedef int32_t int32;
|
|
||||||
typedef uint32_t uint32;
|
|
||||||
typedef int64_t int64;
|
|
||||||
typedef uint64_t uint64;
|
|
||||||
#elif 0 // the BSD format
|
|
||||||
typedef int32_t int32;
|
|
||||||
typedef u_int32_t uint32;
|
|
||||||
typedef int64_t int64;
|
|
||||||
typedef u_int64_t uint64;
|
|
||||||
#elif 1 // the windows (vc7) format
|
|
||||||
typedef __int32 int32;
|
|
||||||
typedef unsigned __int32 uint32;
|
|
||||||
typedef __int64 int64;
|
|
||||||
typedef unsigned __int64 uint64;
|
|
||||||
#else
|
|
||||||
#error Do not know how to define a 32-bit integer quantity on your system
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(GFLAGS_DLL_DECLARE_FLAG)
|
|
||||||
# define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace fLS {
|
|
||||||
|
|
||||||
// The meaning of "string" might be different between now and when the
|
|
||||||
// macros below get invoked (e.g., if someone is experimenting with
|
|
||||||
// other string implementations that get defined after this file is
|
|
||||||
// included). Save the current meaning now and use it in the macros.
|
|
||||||
typedef std::string clstring;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DECLARE_VARIABLE(type, shorttype, name) \
|
|
||||||
/* We always want to import declared variables, dll or no */ \
|
|
||||||
namespace fL##shorttype { extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; } \
|
|
||||||
using fL##shorttype::FLAGS_##name
|
|
||||||
|
|
||||||
#define DECLARE_bool(name) \
|
|
||||||
DECLARE_VARIABLE(bool, B, name)
|
|
||||||
|
|
||||||
#define DECLARE_int32(name) \
|
|
||||||
DECLARE_VARIABLE(::google::int32, I, name)
|
|
||||||
|
|
||||||
#define DECLARE_int64(name) \
|
|
||||||
DECLARE_VARIABLE(::google::int64, I64, name)
|
|
||||||
|
|
||||||
#define DECLARE_uint64(name) \
|
|
||||||
DECLARE_VARIABLE(::google::uint64, U64, name)
|
|
||||||
|
|
||||||
#define DECLARE_double(name) \
|
|
||||||
DECLARE_VARIABLE(double, D, name)
|
|
||||||
|
|
||||||
#define DECLARE_string(name) \
|
|
||||||
namespace fLS { \
|
|
||||||
using ::fLS::clstring; \
|
|
||||||
extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \
|
|
||||||
} \
|
|
||||||
using fLS::FLAGS_##name
|
|
||||||
|
|
||||||
#endif // BASE_COMMANDLINEFLAGS_DECLARE_H_
|
|
|
@ -1,62 +0,0 @@
|
||||||
/* Copyright (c) 2009, Google Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following disclaimer
|
|
||||||
* in the documentation and/or other materials provided with the
|
|
||||||
* distribution.
|
|
||||||
* * Neither the name of Google Inc. nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived from
|
|
||||||
* this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* ---
|
|
||||||
* Author: Craig Silverstein
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
# error You should only be including windows/port.cc in a windows environment!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <string.h> // for strlen(), memset(), memcmp()
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdarg.h> // for va_list, va_start, va_end
|
|
||||||
#include <windows.h>
|
|
||||||
#include "port.h"
|
|
||||||
|
|
||||||
// These call the windows _vsnprintf, but always NUL-terminate.
|
|
||||||
#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
|
|
||||||
int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
|
|
||||||
if (size == 0) // not even room for a \0?
|
|
||||||
return -1; // not what C99 says to do, but what windows does
|
|
||||||
str[size-1] = '\0';
|
|
||||||
return _vsnprintf(str, size-1, format, ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
int snprintf(char *str, size_t size, const char *format, ...) {
|
|
||||||
int r;
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, format);
|
|
||||||
r = vsnprintf(str, size, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
|
|
|
@ -1,116 +0,0 @@
|
||||||
/* Copyright (c) 2009, Google Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following disclaimer
|
|
||||||
* in the documentation and/or other materials provided with the
|
|
||||||
* distribution.
|
|
||||||
* * Neither the name of Google Inc. nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived from
|
|
||||||
* this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* ---
|
|
||||||
* Author: Craig Silverstein
|
|
||||||
*
|
|
||||||
* These are some portability typedefs and defines to make it a bit
|
|
||||||
* easier to compile this code under VC++.
|
|
||||||
*
|
|
||||||
* Several of these are taken from glib:
|
|
||||||
* http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GOOGLE_GFLAGS_WINDOWS_PORT_H_
|
|
||||||
#define GOOGLE_GFLAGS_WINDOWS_PORT_H_
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
|
|
||||||
#endif
|
|
||||||
#include <windows.h>
|
|
||||||
#include <direct.h> /* for mkdir */
|
|
||||||
#include <stdlib.h> /* for _putenv, getenv */
|
|
||||||
#include <stdio.h> /* need this to override stdio's snprintf, also defines _unlink used by unit tests */
|
|
||||||
#include <stdarg.h> /* util.h uses va_copy */
|
|
||||||
#include <string.h> /* for _stricmp and _strdup */
|
|
||||||
|
|
||||||
/* We can't just use _vsnprintf and _snprintf as drop-in-replacements,
|
|
||||||
* because they don't always NUL-terminate. :-( We also can't use the
|
|
||||||
* name vsnprintf, since windows defines that (but not snprintf (!)).
|
|
||||||
*/
|
|
||||||
#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
|
|
||||||
extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size,
|
|
||||||
const char *format, ...);
|
|
||||||
extern int GFLAGS_DLL_DECL safe_vsnprintf(char *str, size_t size,
|
|
||||||
const char *format, va_list ap);
|
|
||||||
#define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap)
|
|
||||||
#define va_copy(dst, src) (dst) = (src)
|
|
||||||
#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
|
|
||||||
|
|
||||||
inline void setenv(const char* name, const char* value, int) {
|
|
||||||
// In windows, it's impossible to set a variable to the empty string.
|
|
||||||
// We handle this by setting it to "0" and the NUL-ing out the \0.
|
|
||||||
// That is, we putenv("FOO=0") and then find out where in memory the
|
|
||||||
// putenv wrote "FOO=0", and change it in-place to "FOO=\0".
|
|
||||||
// c.f. http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508
|
|
||||||
static const char* const kFakeZero = "0";
|
|
||||||
if (*value == '\0')
|
|
||||||
value = kFakeZero;
|
|
||||||
// Apparently the semantics of putenv() is that the input
|
|
||||||
// must live forever, so we leak memory here. :-(
|
|
||||||
const int nameval_len = strlen(name) + 1 + strlen(value) + 1;
|
|
||||||
char* nameval = reinterpret_cast<char*>(malloc(nameval_len));
|
|
||||||
snprintf(nameval, nameval_len, "%s=%s", name, value);
|
|
||||||
_putenv(nameval);
|
|
||||||
if (value == kFakeZero) {
|
|
||||||
nameval[nameval_len - 2] = '\0'; // works when putenv() makes no copy
|
|
||||||
if (*getenv(name) != '\0')
|
|
||||||
*getenv(name) = '\0'; // works when putenv() copies nameval
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define strcasecmp _stricmp
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
|
||||||
#define strdup _strdup
|
|
||||||
#define unlink _unlink
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define PRId32 "d"
|
|
||||||
#define PRIu32 "u"
|
|
||||||
#define PRId64 "I64d"
|
|
||||||
#define PRIu64 "I64u"
|
|
||||||
|
|
||||||
#ifndef __MINGW32__
|
|
||||||
#define strtoq _strtoi64
|
|
||||||
#define strtouq _strtoui64
|
|
||||||
#define strtoll _strtoi64
|
|
||||||
#define strtoull _strtoui64
|
|
||||||
#define atoll _atoi64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
|
||||||
#define PATH_MAX 1024
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
#endif /* GOOGLE_GFLAGS_WINDOWS_PORT_H_ */
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit b471bdbb6e7c0ab8c5f105cc1489177fa4105778
|
|
|
@ -1,20 +1,13 @@
|
||||||
Name: happyhttp
|
Name: happyhttp
|
||||||
URL: http://scumways.com/happyhttp/happyhttp.html
|
URL: https://github.com/Zintinio/HappyHTTP
|
||||||
Version: 0.1 SHA 7306b1606a09063ac38c264afe59f0ad0b441750
|
Version: 0.1
|
||||||
License: zlib/libpng
|
License: zlib/libpng
|
||||||
License File: http://opensource.org/licenses/zlib-license.php
|
License File: http://opensource.org/licenses/zlib-license.php
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
The src/ directory contains a snapshot of the happyhttp library
|
HappyHTTP is a simple C++ library for issuing HTTP requests and processing
|
||||||
with the patches in the patches/ directories applied.
|
responses.
|
||||||
See the files in that directory for discussion of their effects.
|
|
||||||
|
|
||||||
Modifications:
|
Modifications:
|
||||||
- Fix _stricmp undefined problem in linux. Use strcasecmp instead.
|
- Fix _stricmp undefined problem in linux. Use strcasecmp instead.
|
||||||
- "www.scumways.com" should be "scumways.com" in test.cpp.
|
- "www.scumways.com" should be "scumways.com" in test.cpp.
|
||||||
|
|
||||||
To import a new snapshot of libxml:
|
|
||||||
- Git clone from https://github.com/Zintinio/HappyHTTP.
|
|
||||||
- Copy the files into src/ directory
|
|
||||||
- Apply the patches in patches/ and fix any problems.
|
|
||||||
- Update this README to reflect the new version number.
|
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
# to build for windows, use make WIN32=1
|
|
||||||
|
|
||||||
EXE = test
|
|
||||||
SRCS = test.cpp happyhttp.cpp
|
|
||||||
|
|
||||||
CXXFLAGS = -ggdb
|
|
||||||
LDFLAGS =
|
|
||||||
|
|
||||||
ifdef WIN32
|
|
||||||
# need to link with winsock2
|
|
||||||
LDFLAGS += -lws2_32
|
|
||||||
EXE = test.exe
|
|
||||||
endif
|
|
||||||
|
|
||||||
OBJS = $(patsubst %.cpp,%.o,$(SRCS) )
|
|
||||||
|
|
||||||
|
|
||||||
# -------------
|
|
||||||
|
|
||||||
|
|
||||||
$(EXE): $(OBJS)
|
|
||||||
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
|
|
||||||
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJS)
|
|
||||||
rm -f .depend
|
|
||||||
|
|
||||||
|
|
||||||
# automatically generate dependencies from our .cpp files
|
|
||||||
# (-MM tells the compiler to just output makefile rules)
|
|
||||||
depend:
|
|
||||||
$(CXX) -MM $(CPPFLAGS) $(CXXFLAGS) $(SRCS) > .depend
|
|
||||||
|
|
||||||
ifeq ($(wildcard .depend),.depend)
|
|
||||||
include .depend
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,224 +0,0 @@
|
||||||
HappyHTTP
|
|
||||||
=========
|
|
||||||
|
|
||||||
*a simple HTTP library*
|
|
||||||
|
|
||||||
Fork of [http://www.scumways.com/happyhttp/happyhttp.html](http://www.scumways.com/happyhttp/happyhttp.html)
|
|
||||||
|
|
||||||
Contents
|
|
||||||
--------
|
|
||||||
|
|
||||||
- [Overview](#overview)
|
|
||||||
- [Download](#download)
|
|
||||||
- [Usage](#usage)
|
|
||||||
- [Example](#example)
|
|
||||||
- [TODO](#todo)
|
|
||||||
- [License](#license)
|
|
||||||
|
|
||||||
* * * * *
|
|
||||||
|
|
||||||
Overview
|
|
||||||
--------
|
|
||||||
|
|
||||||
HappyHTTP is a simple C++ library for issuing HTTP requests and
|
|
||||||
processing responses.
|
|
||||||
|
|
||||||
- Simple to integrate - just drop in the [.h](happyhttp.h) and
|
|
||||||
[.cpp](happyhttp.cpp) files
|
|
||||||
- Easy-to-use interface ([example](#example))
|
|
||||||
- Non-blocking operation, suitable for use in game update loops
|
|
||||||
- Supports pipelining. You can issue multiple requests without waiting
|
|
||||||
for responses.
|
|
||||||
- Licensed under the [zlib/libpng
|
|
||||||
license](http://www.opensource.org/licenses/zlib-license.php).
|
|
||||||
- Cross-platform (Linux, OSX, Windows)
|
|
||||||
|
|
||||||
* * * * *
|
|
||||||
|
|
||||||
Download
|
|
||||||
--------
|
|
||||||
|
|
||||||
Latest Version is 0.1:
|
|
||||||
[happyhttp-0.1.tar.gz](http://www.scumways.com/happyhttp/happyhttp-0.1.tar.gz)
|
|
||||||
|
|
||||||
* * * * *
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
|
|
||||||
The interface is based loosely on Python's
|
|
||||||
[httplib](http://docs.python.org/lib/module-httplib.html).
|
|
||||||
|
|
||||||
All HappyHTTP code is kept within the `happyhttp::` namespace
|
|
||||||
|
|
||||||
To issue and process a HTTP request, the basic steps are:
|
|
||||||
|
|
||||||
1. Create a connection object
|
|
||||||
2. Set up callbacks for handling responses
|
|
||||||
3. Issue request(s)
|
|
||||||
4. 'pump' the connection at regular intervals. As responses are
|
|
||||||
received, the callbacks will be invoked.
|
|
||||||
|
|
||||||
### Connection object methods
|
|
||||||
|
|
||||||
**`Connection( const char* host, int port )`**
|
|
||||||
Constructor. Specifies host and port, but connection isn't made until
|
|
||||||
request is issued or connect() is called.
|
|
||||||
|
|
||||||
**`~Connection()`**
|
|
||||||
Destructor. If connection is open, it'll be closed, and any outstanding
|
|
||||||
requests will be discarded.
|
|
||||||
|
|
||||||
**`void setcallbacks( ResponseBegin_CB begincb, ResponseData_CB datacb, ResponseComplete_CB completecb, void* userdata )`**
|
|
||||||
Set up the response handling callbacks. These will be invoked during
|
|
||||||
calls to pump().
|
|
||||||
`begincb` - called when the responses headers have been received\
|
|
||||||
`datacb` - called repeatedly to handle body data
|
|
||||||
`completecb` - response is completed
|
|
||||||
`userdata` - passed as a param to all callbacks.
|
|
||||||
|
|
||||||
**`void connect()`**
|
|
||||||
Don't need to call connect() explicitly as issuing a request will call
|
|
||||||
it automatically if needed. But it could block (for name lookup etc), so
|
|
||||||
you might prefer to call it in advance.
|
|
||||||
|
|
||||||
**`void close()`**
|
|
||||||
// close connection, discarding any pending requests.
|
|
||||||
|
|
||||||
**`void pump()`**
|
|
||||||
Update the connection (non-blocking) Just keep calling this regularly
|
|
||||||
to service outstanding requests. As responses are received, the
|
|
||||||
callbacks will be invoked.
|
|
||||||
|
|
||||||
**`bool outstanding() const`**
|
|
||||||
Returns true if any requests are still outstanding.
|
|
||||||
|
|
||||||
**`void request( const char* method, const char* url, const char* headers[], const unsigned char* body, int bodysize )`**
|
|
||||||
High-level request interface. Issues a request.
|
|
||||||
`method` - "GET", "POST" etc...
|
|
||||||
`url` - eg "/index.html"
|
|
||||||
`headers` - array of name/value pairs, terminated by a null-ptr
|
|
||||||
`body, bodysize` - specify body data of request (eg values for a form)
|
|
||||||
|
|
||||||
**`void putrequest( const char* method, const char* url )`**
|
|
||||||
(part of low-level request interface)
|
|
||||||
Begin a request
|
|
||||||
method is "GET", "POST" etc...
|
|
||||||
url is only path part: eg "/index.html"
|
|
||||||
|
|
||||||
**`void putheader( const char* header, const char* value )`**
|
|
||||||
**`void putheader( const char* header, int numericvalue )`**
|
|
||||||
(part of low-level request interface)
|
|
||||||
Add a header to the request (call after putrequest() )
|
|
||||||
|
|
||||||
**`void endheaders()`**
|
|
||||||
(part of low-level request interface)
|
|
||||||
Indicate that your are finished adding headers and the request can be
|
|
||||||
issued.
|
|
||||||
|
|
||||||
`void send( const unsigned char* buf, int numbytes )`
|
|
||||||
(part of low-level request interface)
|
|
||||||
send body data if any. To be called after endheaders()
|
|
||||||
|
|
||||||
### Callback types
|
|
||||||
|
|
||||||
**`typedef void (*ResponseBegin_CB)( const Response* r, void* userdata )`**
|
|
||||||
Invoked when all the headers for a response have been received.\
|
|
||||||
The Response object can be queried to determine status and header
|
|
||||||
values.
|
|
||||||
`userdata` is the same value that was passed in to
|
|
||||||
`Connection::setcallbacks()`.
|
|
||||||
|
|
||||||
**`typedef void (*ResponseData_CB)( const Response* r, void* userdata, const unsigned char* data, int numbytes )`**
|
|
||||||
This callback is invoked to pass out data from the body of the
|
|
||||||
response. It may be called multiple times, or not at all (if there is no
|
|
||||||
body).
|
|
||||||
|
|
||||||
**`typedef void (*ResponseComplete_CB)( const Response* r, void* userdata )`**
|
|
||||||
Once a response is completed, this callback is invoked. When the
|
|
||||||
callback returns, the respsonse object will be destroyed.
|
|
||||||
|
|
||||||
### Response object methods
|
|
||||||
|
|
||||||
When a callback is invoked, a response object is passed to it. The
|
|
||||||
following member functions can be used to query the response:
|
|
||||||
|
|
||||||
**`const char* getheader( const char* name ) const`**
|
|
||||||
retrieve the value of a header (returns 0 if not present)
|
|
||||||
|
|
||||||
**`int getstatus() const`**
|
|
||||||
Get the HTTP status code returned by the server
|
|
||||||
|
|
||||||
**`const char* getreason() const`**
|
|
||||||
Get the HTTP response reason string returned by the server
|
|
||||||
|
|
||||||
### Error Handling
|
|
||||||
|
|
||||||
If an error occurs, a `Wobbly` is thrown. The `Wobbly::what()` method
|
|
||||||
returns a text description.
|
|
||||||
|
|
||||||
* * * * *
|
|
||||||
|
|
||||||
Example
|
|
||||||
-------
|
|
||||||
|
|
||||||
For more examples, see [test.cpp](test.cpp).
|
|
||||||
|
|
||||||
|
|
||||||
static int count=0;
|
|
||||||
|
|
||||||
// invoked when response headers have been received
|
|
||||||
void OnBegin( const happyhttp::Response* r, void* userdata )
|
|
||||||
{
|
|
||||||
printf( "BEGIN (%d %s)\n", r->getstatus(), r->getreason() );
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// invoked to process response body data (may be called multiple times)
|
|
||||||
void OnData( const happyhttp::Response* r, void* userdata, const unsigned char* data, int n )
|
|
||||||
{
|
|
||||||
fwrite( data,1,n, stdout );
|
|
||||||
count += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// invoked when response is complete
|
|
||||||
void OnComplete( const happyhttp::Response* r, void* userdata )
|
|
||||||
{
|
|
||||||
printf( "COMPLETE (%d bytes)\n", count );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TestGET()
|
|
||||||
{
|
|
||||||
happyhttp::Connection conn( "www.scumways.com", 80 );
|
|
||||||
conn.setcallbacks( OnBegin, OnData, OnComplete, 0 );
|
|
||||||
|
|
||||||
conn.request( "GET", "/happyhttp/test.php" );
|
|
||||||
|
|
||||||
while( conn.outstanding() )
|
|
||||||
conn.pump();
|
|
||||||
}
|
|
||||||
|
|
||||||
* * * * *
|
|
||||||
|
|
||||||
TODO
|
|
||||||
----
|
|
||||||
|
|
||||||
- Proxy support
|
|
||||||
- Add helper functions for URL wrangling
|
|
||||||
- Improve error text (and maybe some more exception types?)
|
|
||||||
- HTTP 0.9 support
|
|
||||||
- Improved documentation and examples
|
|
||||||
|
|
||||||
* * * * *
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
HappyHTTP is licensed under the [zlib/libpng
|
|
||||||
license](http://www.opensource.org/licenses/zlib-license.php).
|
|
||||||
|
|
||||||
You are free to use this library however you wish, but if you
|
|
||||||
make changes, please send a patch!
|
|
||||||
|
|
||||||
If you use it, let us know.
|
|
|
@ -1,938 +0,0 @@
|
||||||
/*
|
|
||||||
* HappyHTTP - a simple HTTP library
|
|
||||||
* Version 0.1
|
|
||||||
*
|
|
||||||
* Copyright (c) 2006 Ben Campbell
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Permission is granted to anyone to use this software for any purpose,
|
|
||||||
* including commercial applications, and to alter it and redistribute it
|
|
||||||
* freely, subject to the following restrictions:
|
|
||||||
*
|
|
||||||
* 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
* claim that you wrote the original software. If you use this software in a
|
|
||||||
* product, an acknowledgment in the product documentation would be
|
|
||||||
* appreciated but is not required.
|
|
||||||
*
|
|
||||||
* 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
* be misrepresented as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source distribution.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "happyhttp.h"
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
// #include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netdb.h> // for gethostbyname()
|
|
||||||
#include <errno.h>
|
|
||||||
#else
|
|
||||||
#include <WinSock2.h>
|
|
||||||
#define vsnprintf _vsnprintf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdarg>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#define _stricmp strcasecmp
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
|
|
||||||
namespace happyhttp
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
const char* GetWinsockErrorString( int err );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
// Helper functions
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void BailOnSocketError( const char* context )
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
|
|
||||||
int e = WSAGetLastError();
|
|
||||||
const char* msg = GetWinsockErrorString( e );
|
|
||||||
#else
|
|
||||||
const char* msg = strerror( errno );
|
|
||||||
#endif
|
|
||||||
throw Wobbly( "%s: %s", context, msg );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
|
|
||||||
const char* GetWinsockErrorString( int err )
|
|
||||||
{
|
|
||||||
switch( err)
|
|
||||||
{
|
|
||||||
case 0: return "No error";
|
|
||||||
case WSAEINTR: return "Interrupted system call";
|
|
||||||
case WSAEBADF: return "Bad file number";
|
|
||||||
case WSAEACCES: return "Permission denied";
|
|
||||||
case WSAEFAULT: return "Bad address";
|
|
||||||
case WSAEINVAL: return "Invalid argument";
|
|
||||||
case WSAEMFILE: return "Too many open sockets";
|
|
||||||
case WSAEWOULDBLOCK: return "Operation would block";
|
|
||||||
case WSAEINPROGRESS: return "Operation now in progress";
|
|
||||||
case WSAEALREADY: return "Operation already in progress";
|
|
||||||
case WSAENOTSOCK: return "Socket operation on non-socket";
|
|
||||||
case WSAEDESTADDRREQ: return "Destination address required";
|
|
||||||
case WSAEMSGSIZE: return "Message too long";
|
|
||||||
case WSAEPROTOTYPE: return "Protocol wrong type for socket";
|
|
||||||
case WSAENOPROTOOPT: return "Bad protocol option";
|
|
||||||
case WSAEPROTONOSUPPORT: return "Protocol not supported";
|
|
||||||
case WSAESOCKTNOSUPPORT: return "Socket type not supported";
|
|
||||||
case WSAEOPNOTSUPP: return "Operation not supported on socket";
|
|
||||||
case WSAEPFNOSUPPORT: return "Protocol family not supported";
|
|
||||||
case WSAEAFNOSUPPORT: return "Address family not supported";
|
|
||||||
case WSAEADDRINUSE: return "Address already in use";
|
|
||||||
case WSAEADDRNOTAVAIL: return "Can't assign requested address";
|
|
||||||
case WSAENETDOWN: return "Network is down";
|
|
||||||
case WSAENETUNREACH: return "Network is unreachable";
|
|
||||||
case WSAENETRESET: return "Net connection reset";
|
|
||||||
case WSAECONNABORTED: return "Software caused connection abort";
|
|
||||||
case WSAECONNRESET: return "Connection reset by peer";
|
|
||||||
case WSAENOBUFS: return "No buffer space available";
|
|
||||||
case WSAEISCONN: return "Socket is already connected";
|
|
||||||
case WSAENOTCONN: return "Socket is not connected";
|
|
||||||
case WSAESHUTDOWN: return "Can't send after socket shutdown";
|
|
||||||
case WSAETOOMANYREFS: return "Too many references, can't splice";
|
|
||||||
case WSAETIMEDOUT: return "Connection timed out";
|
|
||||||
case WSAECONNREFUSED: return "Connection refused";
|
|
||||||
case WSAELOOP: return "Too many levels of symbolic links";
|
|
||||||
case WSAENAMETOOLONG: return "File name too long";
|
|
||||||
case WSAEHOSTDOWN: return "Host is down";
|
|
||||||
case WSAEHOSTUNREACH: return "No route to host";
|
|
||||||
case WSAENOTEMPTY: return "Directory not empty";
|
|
||||||
case WSAEPROCLIM: return "Too many processes";
|
|
||||||
case WSAEUSERS: return "Too many users";
|
|
||||||
case WSAEDQUOT: return "Disc quota exceeded";
|
|
||||||
case WSAESTALE: return "Stale NFS file handle";
|
|
||||||
case WSAEREMOTE: return "Too many levels of remote in path";
|
|
||||||
case WSASYSNOTREADY: return "Network system is unavailable";
|
|
||||||
case WSAVERNOTSUPPORTED: return "Winsock version out of range";
|
|
||||||
case WSANOTINITIALISED: return "WSAStartup not yet called";
|
|
||||||
case WSAEDISCON: return "Graceful shutdown in progress";
|
|
||||||
case WSAHOST_NOT_FOUND: return "Host not found";
|
|
||||||
case WSANO_DATA: return "No host data of that type was found";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "unknown";
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // WIN32
|
|
||||||
|
|
||||||
|
|
||||||
// return true if socket has data waiting to be read
|
|
||||||
bool datawaiting( int sock )
|
|
||||||
{
|
|
||||||
fd_set fds;
|
|
||||||
FD_ZERO( &fds );
|
|
||||||
FD_SET( sock, &fds );
|
|
||||||
|
|
||||||
struct timeval tv;
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
|
|
||||||
int r = select( sock+1, &fds, NULL, NULL, &tv);
|
|
||||||
if (r < 0)
|
|
||||||
BailOnSocketError( "select" );
|
|
||||||
|
|
||||||
if( FD_ISSET( sock, &fds ) )
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Try to work out address from string
|
|
||||||
// returns 0 if bad
|
|
||||||
struct in_addr *atoaddr( const char* address)
|
|
||||||
{
|
|
||||||
struct hostent *host;
|
|
||||||
static struct in_addr saddr;
|
|
||||||
|
|
||||||
// First try nnn.nnn.nnn.nnn form
|
|
||||||
saddr.s_addr = inet_addr(address);
|
|
||||||
if (saddr.s_addr != -1)
|
|
||||||
return &saddr;
|
|
||||||
|
|
||||||
host = gethostbyname(address);
|
|
||||||
if( host )
|
|
||||||
return (struct in_addr *) *host->h_addr_list;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Exception class
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
Wobbly::Wobbly( const char* fmt, ... )
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start( ap,fmt);
|
|
||||||
int n = vsnprintf( m_Message, MAXLEN, fmt, ap );
|
|
||||||
va_end( ap );
|
|
||||||
if(n==MAXLEN)
|
|
||||||
m_Message[MAXLEN-1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Connection
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
Connection::Connection( const char* host, int port ) :
|
|
||||||
m_ResponseBeginCB(0),
|
|
||||||
m_ResponseDataCB(0),
|
|
||||||
m_ResponseCompleteCB(0),
|
|
||||||
m_UserData(0),
|
|
||||||
m_State( IDLE ),
|
|
||||||
m_Host( host ),
|
|
||||||
m_Port( port ),
|
|
||||||
m_Sock(-1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Connection::setcallbacks(
|
|
||||||
ResponseBegin_CB begincb,
|
|
||||||
ResponseData_CB datacb,
|
|
||||||
ResponseComplete_CB completecb,
|
|
||||||
void* userdata )
|
|
||||||
{
|
|
||||||
m_ResponseBeginCB = begincb;
|
|
||||||
m_ResponseDataCB = datacb;
|
|
||||||
m_ResponseCompleteCB = completecb;
|
|
||||||
m_UserData = userdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Connection::connect()
|
|
||||||
{
|
|
||||||
in_addr* addr = atoaddr( m_Host.c_str() );
|
|
||||||
if( !addr )
|
|
||||||
throw Wobbly( "Invalid network address" );
|
|
||||||
|
|
||||||
sockaddr_in address;
|
|
||||||
memset( (char*)&address, 0, sizeof(address) );
|
|
||||||
address.sin_family = AF_INET;
|
|
||||||
address.sin_port = htons( m_Port );
|
|
||||||
address.sin_addr.s_addr = addr->s_addr;
|
|
||||||
|
|
||||||
m_Sock = socket( AF_INET, SOCK_STREAM, 0 );
|
|
||||||
if( m_Sock < 0 )
|
|
||||||
BailOnSocketError( "socket()" );
|
|
||||||
|
|
||||||
// printf("Connecting to %s on port %d.\n",inet_ntoa(*addr), port);
|
|
||||||
|
|
||||||
if( ::connect( m_Sock, (sockaddr const*)&address, sizeof(address) ) < 0 )
|
|
||||||
BailOnSocketError( "connect()" );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Connection::close()
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
if( m_Sock >= 0 )
|
|
||||||
::closesocket( m_Sock );
|
|
||||||
#else
|
|
||||||
if( m_Sock >= 0 )
|
|
||||||
::close( m_Sock );
|
|
||||||
#endif
|
|
||||||
m_Sock = -1;
|
|
||||||
|
|
||||||
// discard any incomplete responses
|
|
||||||
while( !m_Outstanding.empty() )
|
|
||||||
{
|
|
||||||
delete m_Outstanding.front();
|
|
||||||
m_Outstanding.pop_front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Connection::~Connection()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::request( const char* method,
|
|
||||||
const char* url,
|
|
||||||
const char* headers[],
|
|
||||||
const unsigned char* body,
|
|
||||||
int bodysize )
|
|
||||||
{
|
|
||||||
|
|
||||||
bool gotcontentlength = false; // already in headers?
|
|
||||||
|
|
||||||
// check headers for content-length
|
|
||||||
// TODO: check for "Host" and "Accept-Encoding" too
|
|
||||||
// and avoid adding them ourselves in putrequest()
|
|
||||||
if( headers )
|
|
||||||
{
|
|
||||||
const char** h = headers;
|
|
||||||
while( *h )
|
|
||||||
{
|
|
||||||
const char* name = *h++;
|
|
||||||
const char* value = *h++;
|
|
||||||
assert( value != 0 ); // name with no value!
|
|
||||||
|
|
||||||
if( 0==_stricmp( name, "content-length" ) )
|
|
||||||
gotcontentlength = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
putrequest( method, url );
|
|
||||||
|
|
||||||
if( body && !gotcontentlength )
|
|
||||||
putheader( "Content-Length", bodysize );
|
|
||||||
|
|
||||||
if( headers )
|
|
||||||
{
|
|
||||||
const char** h = headers;
|
|
||||||
while( *h )
|
|
||||||
{
|
|
||||||
const char* name = *h++;
|
|
||||||
const char* value = *h++;
|
|
||||||
putheader( name, value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endheaders();
|
|
||||||
|
|
||||||
if( body )
|
|
||||||
send( body, bodysize );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Connection::putrequest( const char* method, const char* url )
|
|
||||||
{
|
|
||||||
if( m_State != IDLE )
|
|
||||||
throw Wobbly( "Request already issued" );
|
|
||||||
|
|
||||||
m_State = REQ_STARTED;
|
|
||||||
|
|
||||||
char req[ 512 ];
|
|
||||||
sprintf( req, "%s %s HTTP/1.1", method, url );
|
|
||||||
m_Buffer.push_back( req );
|
|
||||||
|
|
||||||
putheader( "Host", m_Host.c_str() ); // required for HTTP1.1
|
|
||||||
|
|
||||||
// don't want any fancy encodings please
|
|
||||||
putheader("Accept-Encoding", "identity");
|
|
||||||
|
|
||||||
// Push a new response onto the queue
|
|
||||||
Response *r = new Response( method, *this );
|
|
||||||
m_Outstanding.push_back( r );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Connection::putheader( const char* header, const char* value )
|
|
||||||
{
|
|
||||||
if( m_State != REQ_STARTED )
|
|
||||||
throw Wobbly( "putheader() failed" );
|
|
||||||
m_Buffer.push_back( string(header) + ": " + string( value ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::putheader( const char* header, int numericvalue )
|
|
||||||
{
|
|
||||||
char buf[32];
|
|
||||||
sprintf( buf, "%d", numericvalue );
|
|
||||||
putheader( header, buf );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::endheaders()
|
|
||||||
{
|
|
||||||
if( m_State != REQ_STARTED )
|
|
||||||
throw Wobbly( "Cannot send header" );
|
|
||||||
m_State = IDLE;
|
|
||||||
|
|
||||||
m_Buffer.push_back( "" );
|
|
||||||
|
|
||||||
string msg;
|
|
||||||
vector< string>::const_iterator it;
|
|
||||||
for( it = m_Buffer.begin(); it != m_Buffer.end(); ++it )
|
|
||||||
msg += (*it) + "\r\n";
|
|
||||||
|
|
||||||
m_Buffer.clear();
|
|
||||||
|
|
||||||
// printf( "%s", msg.c_str() );
|
|
||||||
send( (const unsigned char*)msg.c_str(), msg.size() );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Connection::send( const unsigned char* buf, int numbytes )
|
|
||||||
{
|
|
||||||
// fwrite( buf, 1,numbytes, stdout );
|
|
||||||
|
|
||||||
if( m_Sock < 0 )
|
|
||||||
connect();
|
|
||||||
|
|
||||||
while( numbytes > 0 )
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
int n = ::send( m_Sock, (const char*)buf, numbytes, 0 );
|
|
||||||
#else
|
|
||||||
int n = ::send( m_Sock, buf, numbytes, 0 );
|
|
||||||
#endif
|
|
||||||
if( n<0 )
|
|
||||||
BailOnSocketError( "send()" );
|
|
||||||
numbytes -= n;
|
|
||||||
buf += n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Connection::pump()
|
|
||||||
{
|
|
||||||
if( m_Outstanding.empty() )
|
|
||||||
return; // no requests outstanding
|
|
||||||
|
|
||||||
assert( m_Sock >0 ); // outstanding requests but no connection!
|
|
||||||
|
|
||||||
if( !datawaiting( m_Sock ) )
|
|
||||||
return; // recv will block
|
|
||||||
|
|
||||||
unsigned char buf[ 2048 ];
|
|
||||||
int a = recv( m_Sock, (char*)buf, sizeof(buf), 0 );
|
|
||||||
if( a<0 )
|
|
||||||
BailOnSocketError( "recv()" );
|
|
||||||
|
|
||||||
if( a== 0 )
|
|
||||||
{
|
|
||||||
// connection has closed
|
|
||||||
|
|
||||||
Response* r = m_Outstanding.front();
|
|
||||||
r->notifyconnectionclosed();
|
|
||||||
assert( r->completed() );
|
|
||||||
delete r;
|
|
||||||
m_Outstanding.pop_front();
|
|
||||||
|
|
||||||
// any outstanding requests will be discarded
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int used = 0;
|
|
||||||
while( used < a && !m_Outstanding.empty() )
|
|
||||||
{
|
|
||||||
|
|
||||||
Response* r = m_Outstanding.front();
|
|
||||||
int u = r->pump( &buf[used], a-used );
|
|
||||||
|
|
||||||
// delete response once completed
|
|
||||||
if( r->completed() )
|
|
||||||
{
|
|
||||||
delete r;
|
|
||||||
m_Outstanding.pop_front();
|
|
||||||
}
|
|
||||||
used += u;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: will lose bytes if response queue goes empty
|
|
||||||
// (but server shouldn't be sending anything if we don't have
|
|
||||||
// anything outstanding anyway)
|
|
||||||
assert( used == a ); // all bytes should be used up by here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Response
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
Response::Response( const char* method, Connection& conn ) :
|
|
||||||
m_Connection( conn ),
|
|
||||||
m_State( STATUSLINE ),
|
|
||||||
m_Method( method ),
|
|
||||||
m_Version( 0 ),
|
|
||||||
m_Status(0),
|
|
||||||
m_BytesRead(0),
|
|
||||||
m_Chunked(false),
|
|
||||||
m_ChunkLeft(0),
|
|
||||||
m_Length(-1),
|
|
||||||
m_WillClose(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char* Response::getheader( const char* name ) const
|
|
||||||
{
|
|
||||||
std::string lname( name );
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
std::transform( lname.begin(), lname.end(), lname.begin(), tolower );
|
|
||||||
#else
|
|
||||||
std::transform( lname.begin(), lname.end(), lname.begin(), ::tolower );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::map< std::string, std::string >::const_iterator it = m_Headers.find( lname );
|
|
||||||
if( it == m_Headers.end() )
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return it->second.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int Response::getstatus() const
|
|
||||||
{
|
|
||||||
// only valid once we've got the statusline
|
|
||||||
assert( m_State != STATUSLINE );
|
|
||||||
return m_Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char* Response::getreason() const
|
|
||||||
{
|
|
||||||
// only valid once we've got the statusline
|
|
||||||
assert( m_State != STATUSLINE );
|
|
||||||
return m_Reason.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Connection has closed
|
|
||||||
void Response::notifyconnectionclosed()
|
|
||||||
{
|
|
||||||
if( m_State == COMPLETE )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// eof can be valid...
|
|
||||||
if( m_State == BODY &&
|
|
||||||
!m_Chunked &&
|
|
||||||
m_Length == -1 )
|
|
||||||
{
|
|
||||||
Finish(); // we're all done!
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw Wobbly( "Connection closed unexpectedly" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int Response::pump( const unsigned char* data, int datasize )
|
|
||||||
{
|
|
||||||
assert( datasize != 0 );
|
|
||||||
int count = datasize;
|
|
||||||
|
|
||||||
while( count > 0 && m_State != COMPLETE )
|
|
||||||
{
|
|
||||||
if( m_State == STATUSLINE ||
|
|
||||||
m_State == HEADERS ||
|
|
||||||
m_State == TRAILERS ||
|
|
||||||
m_State == CHUNKLEN ||
|
|
||||||
m_State == CHUNKEND )
|
|
||||||
{
|
|
||||||
// we want to accumulate a line
|
|
||||||
while( count > 0 )
|
|
||||||
{
|
|
||||||
char c = (char)*data++;
|
|
||||||
--count;
|
|
||||||
if( c == '\n' )
|
|
||||||
{
|
|
||||||
// now got a whole line!
|
|
||||||
switch( m_State )
|
|
||||||
{
|
|
||||||
case STATUSLINE:
|
|
||||||
ProcessStatusLine( m_LineBuf );
|
|
||||||
break;
|
|
||||||
case HEADERS:
|
|
||||||
ProcessHeaderLine( m_LineBuf );
|
|
||||||
break;
|
|
||||||
case TRAILERS:
|
|
||||||
ProcessTrailerLine( m_LineBuf );
|
|
||||||
break;
|
|
||||||
case CHUNKLEN:
|
|
||||||
ProcessChunkLenLine( m_LineBuf );
|
|
||||||
break;
|
|
||||||
case CHUNKEND:
|
|
||||||
// just soak up the crlf after body and go to next state
|
|
||||||
assert( m_Chunked == true );
|
|
||||||
m_State = CHUNKLEN;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
m_LineBuf.clear();
|
|
||||||
break; // break out of line accumulation!
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( c != '\r' ) // just ignore CR
|
|
||||||
m_LineBuf += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( m_State == BODY )
|
|
||||||
{
|
|
||||||
int bytesused = 0;
|
|
||||||
if( m_Chunked )
|
|
||||||
bytesused = ProcessDataChunked( data, count );
|
|
||||||
else
|
|
||||||
bytesused = ProcessDataNonChunked( data, count );
|
|
||||||
data += bytesused;
|
|
||||||
count -= bytesused;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return number of bytes used
|
|
||||||
return datasize - count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Response::ProcessChunkLenLine( std::string const& line )
|
|
||||||
{
|
|
||||||
// chunklen in hex at beginning of line
|
|
||||||
m_ChunkLeft = strtol( line.c_str(), NULL, 16 );
|
|
||||||
|
|
||||||
if( m_ChunkLeft == 0 )
|
|
||||||
{
|
|
||||||
// got the whole body, now check for trailing headers
|
|
||||||
m_State = TRAILERS;
|
|
||||||
m_HeaderAccum.clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_State = BODY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// handle some body data in chunked mode
|
|
||||||
// returns number of bytes used.
|
|
||||||
int Response::ProcessDataChunked( const unsigned char* data, int count )
|
|
||||||
{
|
|
||||||
assert( m_Chunked );
|
|
||||||
|
|
||||||
int n = count;
|
|
||||||
if( n>m_ChunkLeft )
|
|
||||||
n = m_ChunkLeft;
|
|
||||||
|
|
||||||
// invoke callback to pass out the data
|
|
||||||
if( m_Connection.m_ResponseDataCB )
|
|
||||||
(m_Connection.m_ResponseDataCB)( this, m_Connection.m_UserData, data, n );
|
|
||||||
|
|
||||||
m_BytesRead += n;
|
|
||||||
|
|
||||||
m_ChunkLeft -= n;
|
|
||||||
assert( m_ChunkLeft >= 0);
|
|
||||||
if( m_ChunkLeft == 0 )
|
|
||||||
{
|
|
||||||
// chunk completed! now soak up the trailing CRLF before next chunk
|
|
||||||
m_State = CHUNKEND;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle some body data in non-chunked mode.
|
|
||||||
// returns number of bytes used.
|
|
||||||
int Response::ProcessDataNonChunked( const unsigned char* data, int count )
|
|
||||||
{
|
|
||||||
int n = count;
|
|
||||||
if( m_Length != -1 )
|
|
||||||
{
|
|
||||||
// we know how many bytes to expect
|
|
||||||
int remaining = m_Length - m_BytesRead;
|
|
||||||
if( n > remaining )
|
|
||||||
n = remaining;
|
|
||||||
}
|
|
||||||
|
|
||||||
// invoke callback to pass out the data
|
|
||||||
if( m_Connection.m_ResponseDataCB )
|
|
||||||
(m_Connection.m_ResponseDataCB)( this, m_Connection.m_UserData, data, n );
|
|
||||||
|
|
||||||
m_BytesRead += n;
|
|
||||||
|
|
||||||
// Finish if we know we're done. Else we're waiting for connection close.
|
|
||||||
if( m_Length != -1 && m_BytesRead == m_Length )
|
|
||||||
Finish();
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Response::Finish()
|
|
||||||
{
|
|
||||||
m_State = COMPLETE;
|
|
||||||
|
|
||||||
// invoke the callback
|
|
||||||
if( m_Connection.m_ResponseCompleteCB )
|
|
||||||
(m_Connection.m_ResponseCompleteCB)( this, m_Connection.m_UserData );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Response::ProcessStatusLine( std::string const& line )
|
|
||||||
{
|
|
||||||
const char* p = line.c_str();
|
|
||||||
|
|
||||||
// skip any leading space
|
|
||||||
while( *p && *p == ' ' )
|
|
||||||
++p;
|
|
||||||
|
|
||||||
// get version
|
|
||||||
while( *p && *p != ' ' )
|
|
||||||
m_VersionString += *p++;
|
|
||||||
while( *p && *p == ' ' )
|
|
||||||
++p;
|
|
||||||
|
|
||||||
// get status code
|
|
||||||
std::string status;
|
|
||||||
while( *p && *p != ' ' )
|
|
||||||
status += *p++;
|
|
||||||
while( *p && *p == ' ' )
|
|
||||||
++p;
|
|
||||||
|
|
||||||
// rest of line is reason
|
|
||||||
while( *p )
|
|
||||||
m_Reason += *p++;
|
|
||||||
|
|
||||||
m_Status = atoi( status.c_str() );
|
|
||||||
if( m_Status < 100 || m_Status > 999 )
|
|
||||||
throw Wobbly( "BadStatusLine (%s)", line.c_str() );
|
|
||||||
|
|
||||||
/*
|
|
||||||
printf( "version: '%s'\n", m_VersionString.c_str() );
|
|
||||||
printf( "status: '%d'\n", m_Status );
|
|
||||||
printf( "reason: '%s'\n", m_Reason.c_str() );
|
|
||||||
*/
|
|
||||||
|
|
||||||
if( m_VersionString == "HTTP:/1.0" )
|
|
||||||
m_Version = 10;
|
|
||||||
else if( 0==m_VersionString.compare( 0,7,"HTTP/1." ) )
|
|
||||||
m_Version = 11;
|
|
||||||
else
|
|
||||||
throw Wobbly( "UnknownProtocol (%s)", m_VersionString.c_str() );
|
|
||||||
// TODO: support for HTTP/0.9
|
|
||||||
|
|
||||||
|
|
||||||
// OK, now we expect headers!
|
|
||||||
m_State = HEADERS;
|
|
||||||
m_HeaderAccum.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// process accumulated header data
|
|
||||||
void Response::FlushHeader()
|
|
||||||
{
|
|
||||||
if( m_HeaderAccum.empty() )
|
|
||||||
return; // no flushing required
|
|
||||||
|
|
||||||
const char* p = m_HeaderAccum.c_str();
|
|
||||||
|
|
||||||
std::string header;
|
|
||||||
std::string value;
|
|
||||||
while( *p && *p != ':' )
|
|
||||||
header += tolower( *p++ );
|
|
||||||
|
|
||||||
// skip ':'
|
|
||||||
if( *p )
|
|
||||||
++p;
|
|
||||||
|
|
||||||
// skip space
|
|
||||||
while( *p && (*p ==' ' || *p=='\t') )
|
|
||||||
++p;
|
|
||||||
|
|
||||||
value = p; // rest of line is value
|
|
||||||
|
|
||||||
m_Headers[ header ] = value;
|
|
||||||
// printf("header: ['%s': '%s']\n", header.c_str(), value.c_str() );
|
|
||||||
|
|
||||||
m_HeaderAccum.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Response::ProcessHeaderLine( std::string const& line )
|
|
||||||
{
|
|
||||||
const char* p = line.c_str();
|
|
||||||
if( line.empty() )
|
|
||||||
{
|
|
||||||
FlushHeader();
|
|
||||||
// end of headers
|
|
||||||
|
|
||||||
// HTTP code 100 handling (we ignore 'em)
|
|
||||||
if( m_Status == CONTINUE )
|
|
||||||
m_State = STATUSLINE; // reset parsing, expect new status line
|
|
||||||
else
|
|
||||||
BeginBody(); // start on body now!
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( isspace(*p) )
|
|
||||||
{
|
|
||||||
// it's a continuation line - just add it to previous data
|
|
||||||
++p;
|
|
||||||
while( *p && isspace( *p ) )
|
|
||||||
++p;
|
|
||||||
|
|
||||||
m_HeaderAccum += ' ';
|
|
||||||
m_HeaderAccum += p;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// begin a new header
|
|
||||||
FlushHeader();
|
|
||||||
m_HeaderAccum = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Response::ProcessTrailerLine( std::string const& line )
|
|
||||||
{
|
|
||||||
// TODO: handle trailers?
|
|
||||||
// (python httplib doesn't seem to!)
|
|
||||||
if( line.empty() )
|
|
||||||
Finish();
|
|
||||||
|
|
||||||
// just ignore all the trailers...
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// OK, we've now got all the headers read in, so we're ready to start
|
|
||||||
// on the body. But we need to see what info we can glean from the headers
|
|
||||||
// first...
|
|
||||||
void Response::BeginBody()
|
|
||||||
{
|
|
||||||
|
|
||||||
m_Chunked = false;
|
|
||||||
m_Length = -1; // unknown
|
|
||||||
m_WillClose = false;
|
|
||||||
|
|
||||||
// using chunked encoding?
|
|
||||||
const char* trenc = getheader( "transfer-encoding" );
|
|
||||||
if( trenc && 0==_stricmp( trenc, "chunked") )
|
|
||||||
{
|
|
||||||
m_Chunked = true;
|
|
||||||
m_ChunkLeft = -1; // unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
m_WillClose = CheckClose();
|
|
||||||
|
|
||||||
// length supplied?
|
|
||||||
const char* contentlen = getheader( "content-length" );
|
|
||||||
if( contentlen && !m_Chunked )
|
|
||||||
{
|
|
||||||
m_Length = atoi( contentlen );
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for various cases where we expect zero-length body
|
|
||||||
if( m_Status == NO_CONTENT ||
|
|
||||||
m_Status == NOT_MODIFIED ||
|
|
||||||
( m_Status >= 100 && m_Status < 200 ) || // 1xx codes have no body
|
|
||||||
m_Method == "HEAD" )
|
|
||||||
{
|
|
||||||
m_Length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// if we're not using chunked mode, and no length has been specified,
|
|
||||||
// assume connection will close at end.
|
|
||||||
if( !m_WillClose && !m_Chunked && m_Length == -1 )
|
|
||||||
m_WillClose = true;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Invoke the user callback, if any
|
|
||||||
if( m_Connection.m_ResponseBeginCB )
|
|
||||||
(m_Connection.m_ResponseBeginCB)( this, m_Connection.m_UserData );
|
|
||||||
|
|
||||||
/*
|
|
||||||
printf("---------BeginBody()--------\n");
|
|
||||||
printf("Length: %d\n", m_Length );
|
|
||||||
printf("WillClose: %d\n", (int)m_WillClose );
|
|
||||||
printf("Chunked: %d\n", (int)m_Chunked );
|
|
||||||
printf("ChunkLeft: %d\n", (int)m_ChunkLeft );
|
|
||||||
printf("----------------------------\n");
|
|
||||||
*/
|
|
||||||
// now start reading body data!
|
|
||||||
if( m_Chunked )
|
|
||||||
m_State = CHUNKLEN;
|
|
||||||
else
|
|
||||||
m_State = BODY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return true if we think server will automatically close connection
|
|
||||||
bool Response::CheckClose()
|
|
||||||
{
|
|
||||||
if( m_Version == 11 )
|
|
||||||
{
|
|
||||||
// HTTP1.1
|
|
||||||
// the connection stays open unless "connection: close" is specified.
|
|
||||||
const char* conn = getheader( "connection" );
|
|
||||||
if( conn && 0==_stricmp( conn, "close" ) )
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Older HTTP
|
|
||||||
// keep-alive header indicates persistant connection
|
|
||||||
if( getheader( "keep-alive" ) )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// TODO: some special case handling for Akamai and netscape maybe?
|
|
||||||
// (see _check_close() in python httplib.py for details)
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // end namespace happyhttp
|
|
||||||
|
|
||||||
|
|
|
@ -1,333 +0,0 @@
|
||||||
/*
|
|
||||||
* HappyHTTP - a simple HTTP library
|
|
||||||
* Version 0.1
|
|
||||||
*
|
|
||||||
* Copyright (c) 2006 Ben Campbell
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Permission is granted to anyone to use this software for any purpose,
|
|
||||||
* including commercial applications, and to alter it and redistribute it
|
|
||||||
* freely, subject to the following restrictions:
|
|
||||||
*
|
|
||||||
* 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
* claim that you wrote the original software. If you use this software in a
|
|
||||||
* product, an acknowledgment in the product documentation would be
|
|
||||||
* appreciated but is not required.
|
|
||||||
*
|
|
||||||
* 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
* be misrepresented as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source distribution.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HAPPYHTTP_H
|
|
||||||
#define HAPPYHTTP_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
#include <deque>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// forward decl
|
|
||||||
struct in_addr;
|
|
||||||
|
|
||||||
namespace happyhttp
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
class Response;
|
|
||||||
|
|
||||||
// Helper Functions
|
|
||||||
void BailOnSocketError( const char* context );
|
|
||||||
struct in_addr *atoaddr( const char* address);
|
|
||||||
|
|
||||||
|
|
||||||
typedef void (*ResponseBegin_CB)( const Response* r, void* userdata );
|
|
||||||
typedef void (*ResponseData_CB)( const Response* r, void* userdata, const unsigned char* data, int numbytes );
|
|
||||||
typedef void (*ResponseComplete_CB)( const Response* r, void* userdata );
|
|
||||||
|
|
||||||
|
|
||||||
// HTTP status codes
|
|
||||||
enum {
|
|
||||||
// 1xx informational
|
|
||||||
CONTINUE = 100,
|
|
||||||
SWITCHING_PROTOCOLS = 101,
|
|
||||||
PROCESSING = 102,
|
|
||||||
|
|
||||||
// 2xx successful
|
|
||||||
OK = 200,
|
|
||||||
CREATED = 201,
|
|
||||||
ACCEPTED = 202,
|
|
||||||
NON_AUTHORITATIVE_INFORMATION = 203,
|
|
||||||
NO_CONTENT = 204,
|
|
||||||
RESET_CONTENT = 205,
|
|
||||||
PARTIAL_CONTENT = 206,
|
|
||||||
MULTI_STATUS = 207,
|
|
||||||
IM_USED = 226,
|
|
||||||
|
|
||||||
// 3xx redirection
|
|
||||||
MULTIPLE_CHOICES = 300,
|
|
||||||
MOVED_PERMANENTLY = 301,
|
|
||||||
FOUND = 302,
|
|
||||||
SEE_OTHER = 303,
|
|
||||||
NOT_MODIFIED = 304,
|
|
||||||
USE_PROXY = 305,
|
|
||||||
TEMPORARY_REDIRECT = 307,
|
|
||||||
|
|
||||||
// 4xx client error
|
|
||||||
BAD_REQUEST = 400,
|
|
||||||
UNAUTHORIZED = 401,
|
|
||||||
PAYMENT_REQUIRED = 402,
|
|
||||||
FORBIDDEN = 403,
|
|
||||||
NOT_FOUND = 404,
|
|
||||||
METHOD_NOT_ALLOWED = 405,
|
|
||||||
NOT_ACCEPTABLE = 406,
|
|
||||||
PROXY_AUTHENTICATION_REQUIRED = 407,
|
|
||||||
REQUEST_TIMEOUT = 408,
|
|
||||||
CONFLICT = 409,
|
|
||||||
GONE = 410,
|
|
||||||
LENGTH_REQUIRED = 411,
|
|
||||||
PRECONDITION_FAILED = 412,
|
|
||||||
REQUEST_ENTITY_TOO_LARGE = 413,
|
|
||||||
REQUEST_URI_TOO_LONG = 414,
|
|
||||||
UNSUPPORTED_MEDIA_TYPE = 415,
|
|
||||||
REQUESTED_RANGE_NOT_SATISFIABLE = 416,
|
|
||||||
EXPECTATION_FAILED = 417,
|
|
||||||
UNPROCESSABLE_ENTITY = 422,
|
|
||||||
LOCKED = 423,
|
|
||||||
FAILED_DEPENDENCY = 424,
|
|
||||||
UPGRADE_REQUIRED = 426,
|
|
||||||
|
|
||||||
// 5xx server error
|
|
||||||
INTERNAL_SERVER_ERROR = 500,
|
|
||||||
NOT_IMPLEMENTED = 501,
|
|
||||||
BAD_GATEWAY = 502,
|
|
||||||
SERVICE_UNAVAILABLE = 503,
|
|
||||||
GATEWAY_TIMEOUT = 504,
|
|
||||||
HTTP_VERSION_NOT_SUPPORTED = 505,
|
|
||||||
INSUFFICIENT_STORAGE = 507,
|
|
||||||
NOT_EXTENDED = 510,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Exception class
|
|
||||||
|
|
||||||
class Wobbly
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Wobbly( const char* fmt, ... );
|
|
||||||
const char* what() const
|
|
||||||
{ return m_Message; }
|
|
||||||
protected:
|
|
||||||
enum { MAXLEN=256 };
|
|
||||||
char m_Message[ MAXLEN ];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// Connection
|
|
||||||
//
|
|
||||||
// Handles the socket connection, issuing of requests and managing
|
|
||||||
// responses.
|
|
||||||
// ------------------------------------------------
|
|
||||||
|
|
||||||
class Connection
|
|
||||||
{
|
|
||||||
friend class Response;
|
|
||||||
public:
|
|
||||||
// doesn't connect immediately
|
|
||||||
Connection( const char* host, int port );
|
|
||||||
~Connection();
|
|
||||||
|
|
||||||
// Set up the response handling callbacks. These will be invoked during
|
|
||||||
// calls to pump().
|
|
||||||
// begincb - called when the responses headers have been received
|
|
||||||
// datacb - called repeatedly to handle body data
|
|
||||||
// completecb - response is completed
|
|
||||||
// userdata is passed as a param to all callbacks.
|
|
||||||
void setcallbacks(
|
|
||||||
ResponseBegin_CB begincb,
|
|
||||||
ResponseData_CB datacb,
|
|
||||||
ResponseComplete_CB completecb,
|
|
||||||
void* userdata );
|
|
||||||
|
|
||||||
// Don't need to call connect() explicitly as issuing a request will
|
|
||||||
// call it automatically if needed.
|
|
||||||
// But it could block (for name lookup etc), so you might prefer to
|
|
||||||
// call it in advance.
|
|
||||||
void connect();
|
|
||||||
|
|
||||||
// close connection, discarding any pending requests.
|
|
||||||
void close();
|
|
||||||
|
|
||||||
// Update the connection (non-blocking)
|
|
||||||
// Just keep calling this regularly to service outstanding requests.
|
|
||||||
void pump();
|
|
||||||
|
|
||||||
// any requests still outstanding?
|
|
||||||
bool outstanding() const
|
|
||||||
{ return !m_Outstanding.empty(); }
|
|
||||||
|
|
||||||
// ---------------------------
|
|
||||||
// high-level request interface
|
|
||||||
// ---------------------------
|
|
||||||
|
|
||||||
// method is "GET", "POST" etc...
|
|
||||||
// url is only path part: eg "/index.html"
|
|
||||||
// headers is array of name/value pairs, terminated by a null-ptr
|
|
||||||
// body & bodysize specify body data of request (eg values for a form)
|
|
||||||
void request( const char* method, const char* url, const char* headers[]=0,
|
|
||||||
const unsigned char* body=0, int bodysize=0 );
|
|
||||||
|
|
||||||
// ---------------------------
|
|
||||||
// low-level request interface
|
|
||||||
// ---------------------------
|
|
||||||
|
|
||||||
// begin request
|
|
||||||
// method is "GET", "POST" etc...
|
|
||||||
// url is only path part: eg "/index.html"
|
|
||||||
void putrequest( const char* method, const char* url );
|
|
||||||
|
|
||||||
// Add a header to the request (call after putrequest() )
|
|
||||||
void putheader( const char* header, const char* value );
|
|
||||||
void putheader( const char* header, int numericvalue ); // alternate version
|
|
||||||
|
|
||||||
// Finished adding headers, issue the request.
|
|
||||||
void endheaders();
|
|
||||||
|
|
||||||
// send body data if any.
|
|
||||||
// To be called after endheaders()
|
|
||||||
void send( const unsigned char* buf, int numbytes );
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// some bits of implementation exposed to Response class
|
|
||||||
|
|
||||||
// callbacks
|
|
||||||
ResponseBegin_CB m_ResponseBeginCB;
|
|
||||||
ResponseData_CB m_ResponseDataCB;
|
|
||||||
ResponseComplete_CB m_ResponseCompleteCB;
|
|
||||||
void* m_UserData;
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum { IDLE, REQ_STARTED, REQ_SENT } m_State;
|
|
||||||
std::string m_Host;
|
|
||||||
int m_Port;
|
|
||||||
int m_Sock;
|
|
||||||
std::vector< std::string > m_Buffer; // lines of request
|
|
||||||
|
|
||||||
std::deque< Response* > m_Outstanding; // responses for outstanding requests
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// Response
|
|
||||||
//
|
|
||||||
// Handles parsing of response data.
|
|
||||||
// ------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
class Response
|
|
||||||
{
|
|
||||||
friend class Connection;
|
|
||||||
public:
|
|
||||||
|
|
||||||
// retrieve a header (returns 0 if not present)
|
|
||||||
const char* getheader( const char* name ) const;
|
|
||||||
|
|
||||||
bool completed() const
|
|
||||||
{ return m_State == COMPLETE; }
|
|
||||||
|
|
||||||
|
|
||||||
// get the HTTP status code
|
|
||||||
int getstatus() const;
|
|
||||||
|
|
||||||
// get the HTTP response reason string
|
|
||||||
const char* getreason() const;
|
|
||||||
|
|
||||||
// true if connection is expected to close after this response.
|
|
||||||
bool willclose() const
|
|
||||||
{ return m_WillClose; }
|
|
||||||
protected:
|
|
||||||
// interface used by Connection
|
|
||||||
|
|
||||||
// only Connection creates Responses.
|
|
||||||
Response( const char* method, Connection& conn );
|
|
||||||
|
|
||||||
// pump some data in for processing.
|
|
||||||
// Returns the number of bytes used.
|
|
||||||
// Will always return 0 when response is complete.
|
|
||||||
int pump( const unsigned char* data, int datasize );
|
|
||||||
|
|
||||||
// tell response that connection has closed
|
|
||||||
void notifyconnectionclosed();
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
STATUSLINE, // start here. status line is first line of response.
|
|
||||||
HEADERS, // reading in header lines
|
|
||||||
BODY, // waiting for some body data (all or a chunk)
|
|
||||||
CHUNKLEN, // expecting a chunk length indicator (in hex)
|
|
||||||
CHUNKEND, // got the chunk, now expecting a trailing blank line
|
|
||||||
TRAILERS, // reading trailers after body.
|
|
||||||
COMPLETE, // response is complete!
|
|
||||||
} m_State;
|
|
||||||
|
|
||||||
Connection& m_Connection; // to access callback ptrs
|
|
||||||
std::string m_Method; // req method: "GET", "POST" etc...
|
|
||||||
|
|
||||||
// status line
|
|
||||||
std::string m_VersionString; // HTTP-Version
|
|
||||||
int m_Version; // 10: HTTP/1.0 11: HTTP/1.x (where x>=1)
|
|
||||||
int m_Status; // Status-Code
|
|
||||||
std::string m_Reason; // Reason-Phrase
|
|
||||||
|
|
||||||
// header/value pairs
|
|
||||||
std::map<std::string,std::string> m_Headers;
|
|
||||||
|
|
||||||
int m_BytesRead; // body bytes read so far
|
|
||||||
bool m_Chunked; // response is chunked?
|
|
||||||
int m_ChunkLeft; // bytes left in current chunk
|
|
||||||
int m_Length; // -1 if unknown
|
|
||||||
bool m_WillClose; // connection will close at response end?
|
|
||||||
|
|
||||||
std::string m_LineBuf; // line accumulation for states that want it
|
|
||||||
std::string m_HeaderAccum; // accumulation buffer for headers
|
|
||||||
|
|
||||||
|
|
||||||
void FlushHeader();
|
|
||||||
void ProcessStatusLine( std::string const& line );
|
|
||||||
void ProcessHeaderLine( std::string const& line );
|
|
||||||
void ProcessTrailerLine( std::string const& line );
|
|
||||||
void ProcessChunkLenLine( std::string const& line );
|
|
||||||
|
|
||||||
int ProcessDataChunked( const unsigned char* data, int count );
|
|
||||||
int ProcessDataNonChunked( const unsigned char* data, int count );
|
|
||||||
|
|
||||||
void BeginBody();
|
|
||||||
bool CheckClose();
|
|
||||||
void Finish();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // end namespace happyhttp
|
|
||||||
|
|
||||||
|
|
||||||
#endif // HAPPYHTTP_H
|
|
||||||
|
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
#include "happyhttp.h"
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <winsock2.h>
|
|
||||||
#endif // WIN32
|
|
||||||
|
|
||||||
int count=0;
|
|
||||||
|
|
||||||
void OnBegin( const happyhttp::Response* r, void* userdata )
|
|
||||||
{
|
|
||||||
printf( "BEGIN (%d %s)\n", r->getstatus(), r->getreason() );
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnData( const happyhttp::Response* r, void* userdata, const unsigned char* data, int n )
|
|
||||||
{
|
|
||||||
fwrite( data,1,n, stdout );
|
|
||||||
count += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnComplete( const happyhttp::Response* r, void* userdata )
|
|
||||||
{
|
|
||||||
printf( "COMPLETE (%d bytes)\n", count );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Test1()
|
|
||||||
{
|
|
||||||
puts("-----------------Test1------------------------" );
|
|
||||||
// simple simple GET
|
|
||||||
happyhttp::Connection conn( "scumways.com", 80 );
|
|
||||||
conn.setcallbacks( OnBegin, OnData, OnComplete, 0 );
|
|
||||||
|
|
||||||
conn.request( "GET", "/happyhttp/test.php", 0, 0,0 );
|
|
||||||
|
|
||||||
while( conn.outstanding() )
|
|
||||||
conn.pump();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Test2()
|
|
||||||
{
|
|
||||||
puts("-----------------Test2------------------------" );
|
|
||||||
// POST using high-level request interface
|
|
||||||
|
|
||||||
const char* headers[] =
|
|
||||||
{
|
|
||||||
"Connection", "close",
|
|
||||||
"Content-type", "application/x-www-form-urlencoded",
|
|
||||||
"Accept", "text/plain",
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* body = "answer=42&name=Bubba";
|
|
||||||
|
|
||||||
happyhttp::Connection conn( "scumways.com", 80 );
|
|
||||||
conn.setcallbacks( OnBegin, OnData, OnComplete, 0 );
|
|
||||||
conn.request( "POST",
|
|
||||||
"/happyhttp/test.php",
|
|
||||||
headers,
|
|
||||||
(const unsigned char*)body,
|
|
||||||
strlen(body) );
|
|
||||||
|
|
||||||
while( conn.outstanding() )
|
|
||||||
conn.pump();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Test3()
|
|
||||||
{
|
|
||||||
puts("-----------------Test3------------------------" );
|
|
||||||
// POST example using lower-level interface
|
|
||||||
|
|
||||||
const char* params = "answer=42&foo=bar";
|
|
||||||
int l = strlen(params);
|
|
||||||
|
|
||||||
happyhttp::Connection conn( "scumways.com", 80 );
|
|
||||||
conn.setcallbacks( OnBegin, OnData, OnComplete, 0 );
|
|
||||||
|
|
||||||
conn.putrequest( "POST", "/happyhttp/test.php" );
|
|
||||||
conn.putheader( "Connection", "close" );
|
|
||||||
conn.putheader( "Content-Length", l );
|
|
||||||
conn.putheader( "Content-type", "application/x-www-form-urlencoded" );
|
|
||||||
conn.putheader( "Accept", "text/plain" );
|
|
||||||
conn.endheaders();
|
|
||||||
conn.send( (const unsigned char*)params, l );
|
|
||||||
|
|
||||||
while( conn.outstanding() )
|
|
||||||
conn.pump();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main( int argc, char* argv[] )
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
WSAData wsaData;
|
|
||||||
int code = WSAStartup(MAKEWORD(1, 1), &wsaData);
|
|
||||||
if( code != 0 )
|
|
||||||
{
|
|
||||||
fprintf(stderr, "shite. %d\n",code);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif //WIN32
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Test1();
|
|
||||||
Test2();
|
|
||||||
Test3();
|
|
||||||
}
|
|
||||||
|
|
||||||
catch( happyhttp::Wobbly& e )
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Exception:\n%s\n", e.what() );
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
WSACleanup();
|
|
||||||
#endif // WIN32
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit e49b610806e6ba6063384ffd7f45d5b7cd561e65
|
|
|
@ -1,201 +0,0 @@
|
||||||
Changes in 1.4.13-stable:
|
|
||||||
o If the kernel tells us that there are a negative number of bytes to read from a socket, do not believe it. Fixes bug 2841177; found by Alexander Pronchenkov.
|
|
||||||
o Do not allocate the maximum event queue and fd array for the epoll backend at startup. Instead, start out accepting 32 events at a time, and double the queue's size when it seems that the OS is generating events faster than we're requesting them. Saves up to 512K per epoll-based event_base. Resolves bug 2839240.
|
|
||||||
o Fix compilation on Android, which forgot to define fd_mask in its sys/select.h
|
|
||||||
o Do not drop data from evbuffer when out of memory; reported by Jacek Masiulaniec
|
|
||||||
o Rename our replacement compat/sys/_time.h header to avoid build a conflict on HPUX; reported by Kathryn Hogg.
|
|
||||||
o Build kqueue.c correctly on GNU/kFreeBSD platforms. Patch pulled upstream from Debian.
|
|
||||||
o Fix a problem with excessive memory allocation when using multiple event priorities.
|
|
||||||
o When running set[ug]id, don't check the environment. Based on a patch from OpenBSD.
|
|
||||||
|
|
||||||
|
|
||||||
Changes in 1.4.12-stable:
|
|
||||||
o Try to contain degree of failure when running on a win32 version so heavily firewalled that we can't fake a socketpair.
|
|
||||||
o Fix an obscure timing-dependent, allocator-dependent crash in the evdns code.
|
|
||||||
o Use __VA_ARGS__ syntax for varargs macros in event_rpcgen when compiler is not GCC.
|
|
||||||
o Activate fd events in a pseudorandom order with O(N) backends, so that we don't systematically favor low fds (select) or earlier-added fds (poll, win32).
|
|
||||||
o Fix another pair of fencepost bugs in epoll.c. [Patch from Adam Langley.]
|
|
||||||
o Do not break evdns connections to nameservers when our IP changes.
|
|
||||||
o Set truncated flag correctly in evdns server replies.
|
|
||||||
o Disable strict aliasing with GCC: our code is not compliant with it.
|
|
||||||
|
|
||||||
Changes in 1.4.11-stable:
|
|
||||||
o Fix a bug when removing a timeout from the heap. [Patch from Marko Kreen]
|
|
||||||
o Remove the limit on size of HTTP headers by removing static buffers.
|
|
||||||
o Fix a nasty dangling pointer bug in epoll.c that could occur after epoll_recalc(). [Patch from Kevin Springborn]
|
|
||||||
o Distribute Win32-Code/event-config.h, not ./event-config.h
|
|
||||||
|
|
||||||
Changes in 1.4.10-stable:
|
|
||||||
o clean up buffered http connection data on reset; reported by Brian O'Kelley
|
|
||||||
o bug fix and potential race condition in signal handling; from Alexander Drozdov
|
|
||||||
o rename the Solaris event ports backend to evport
|
|
||||||
o support compilation on Haiku
|
|
||||||
o fix signal processing when a signal callback delivers a signal; from Alexander Drozdov
|
|
||||||
o const-ify some arguments to evdns functions.
|
|
||||||
o off-by-one error in epoll_recalc; reported by Victor Goya
|
|
||||||
o include Doxyfile in tar ball; from Jeff Garzik
|
|
||||||
o correctly parse queries with encoded \r, \n or + characters
|
|
||||||
|
|
||||||
Changes in 1.4.9-stable:
|
|
||||||
o event_add would not return error for some backends; from Dean McNamee
|
|
||||||
o Clear the timer cache on entering the event loop; reported by Victor Chang
|
|
||||||
o Only bind the socket on connect when a local address has been provided; reported by Alejo Sanchez
|
|
||||||
o Allow setting of local port for evhttp connections to support millions of connections from a single system; from Richard Jones.
|
|
||||||
o Clear the timer cache when leaving the event loop; reported by Robin Haberkorn
|
|
||||||
o Fix a typo in setting the global event base; reported by lance.
|
|
||||||
o Fix a memory leak when reading multi-line headers
|
|
||||||
o Fix a memory leak by not running explicit close detection for server connections
|
|
||||||
|
|
||||||
Changes in 1.4.8-stable:
|
|
||||||
o Match the query in DNS replies to the query in the request; from Vsevolod Stakhov.
|
|
||||||
o Fix a merge problem in which name_from_addr returned pointers to the stack; found by Jiang Hong.
|
|
||||||
o Do not remove Accept-Encoding header
|
|
||||||
|
|
||||||
Changes in 1.4.7-stable:
|
|
||||||
o Fix a bug where headers arriving in multiple packets were not parsed; fix from Jiang Hong; test by me.
|
|
||||||
|
|
||||||
Changes in 1.4.6-stable:
|
|
||||||
o evutil.h now includes <stdarg.h> directly
|
|
||||||
o switch all uses of [v]snprintf over to evutil
|
|
||||||
o Correct handling of trailing headers in chunked replies; from Scott Lamb.
|
|
||||||
o Support multi-line HTTP headers; based on a patch from Moshe Litvin
|
|
||||||
o Reject negative Content-Length headers; anonymous bug report
|
|
||||||
o Detect CLOCK_MONOTONIC at runtime for evdns; anonymous bug report
|
|
||||||
o Fix a bug where deleting signals with the kqueue backend would cause subsequent adds to fail
|
|
||||||
o Support multiple events listening on the same signal; make signals regular events that go on the same event queue; problem report by Alexander Drozdov.
|
|
||||||
o Deal with evbuffer_read() returning -1 on EINTR|EAGAIN; from Adam Langley.
|
|
||||||
o Fix a bug in which the DNS server would incorrectly set the type of a cname reply to a.
|
|
||||||
o Fix a bug where setting the timeout on a bufferevent would take not effect if the event was already pending.
|
|
||||||
o Fix a memory leak when using signals for some event bases; reported by Alexander Drozdov.
|
|
||||||
o Add libevent.vcproj file to distribution to help with Windows build.
|
|
||||||
o Fix a problem with epoll() and reinit; problem report by Alexander Drozdov.
|
|
||||||
o Fix off-by-one errors in devpoll; from Ian Bell
|
|
||||||
o Make event_add not change any state if it fails; reported by Ian Bell.
|
|
||||||
o Do not warn on accept when errno is either EAGAIN or EINTR
|
|
||||||
|
|
||||||
Changes in 1.4.5-stable:
|
|
||||||
o Fix connection keep-alive behavior for HTTP/1.0
|
|
||||||
o Fix use of freed memory in event_reinit; pointed out by Peter Postma
|
|
||||||
o Constify struct timeval * where possible; pointed out by Forest Wilkinson
|
|
||||||
o allow min_heap_erase to be called on removed members; from liusifan.
|
|
||||||
o Rename INPUT and OUTPUT to EVRPC_INPUT and EVRPC_OUTPUT. Retain INPUT/OUTPUT aliases on on-win32 platforms for backwards compatibility.
|
|
||||||
o Do not use SO_REUSEADDR when connecting
|
|
||||||
o Fix Windows build
|
|
||||||
o Fix a bug in event_rpcgen when generated fixed-sized entries
|
|
||||||
|
|
||||||
Changes in 1.4.4-stable:
|
|
||||||
o Correct the documentation on buffer printf functions.
|
|
||||||
o Don't warn on unimplemented epoll_create(): this isn't a problem, just a reason to fall back to poll or select.
|
|
||||||
o Correctly handle timeouts larger than 35 minutes on Linux with epoll.c. This is probably a kernel defect, but we'll have to support old kernels anyway even if it gets fixed.
|
|
||||||
o Fix a potential stack corruption bug in tagging on 64-bit CPUs.
|
|
||||||
o expose bufferevent_setwatermark via header files and fix high watermark on read
|
|
||||||
o fix a bug in bufferevent read water marks and add a test for them
|
|
||||||
o introduce bufferevent_setcb and bufferevent_setfd to allow better manipulation of bufferevents
|
|
||||||
o use libevent's internal timercmp on all platforms, to avoid bugs on old platforms where timercmp(a,b,<=) is buggy.
|
|
||||||
o reduce system calls for getting current time by caching it.
|
|
||||||
o fix evhttp_bind_socket() so that multiple sockets can be bound by the same http server.
|
|
||||||
o Build test directory correctly with CPPFLAGS set.
|
|
||||||
o Fix build under Visual C++ 2005.
|
|
||||||
o Expose evhttp_accept_socket() API.
|
|
||||||
o Merge windows gettimeofday() replacement into a new evutil_gettimeofday() function.
|
|
||||||
o Fix autoconf script behavior on IRIX.
|
|
||||||
o Make sure winsock2.h include always comes before windows.h include.
|
|
||||||
|
|
||||||
Changes in 1.4.3-stable:
|
|
||||||
o include Content-Length in reply for HTTP/1.0 requests with keep-alive
|
|
||||||
o Patch from Tani Hosokawa: make some functions in http.c threadsafe.
|
|
||||||
o Do not free the kqop file descriptor in other processes, also allow it to be 0; from Andrei Nigmatulin
|
|
||||||
o make event_rpcgen.py generate code include event-config.h; reported by Sam Banks.
|
|
||||||
o make event methods static so that they are not exported; from Andrei Nigmatulin
|
|
||||||
o make RPC replies use application/octet-stream as mime type
|
|
||||||
o do not delete uninitialized timeout event in evdns
|
|
||||||
|
|
||||||
Changes in 1.4.2-rc:
|
|
||||||
o remove pending timeouts on event_base_free()
|
|
||||||
o also check EAGAIN for Solaris' event ports; from W.C.A. Wijngaards
|
|
||||||
o devpoll and evport need reinit; tested by W.C.A Wijngaards
|
|
||||||
o event_base_get_method; from Springande Ulv
|
|
||||||
o Send CRLF after each chunk in HTTP output, for compliance with RFC2626. Patch from "propanbutan". Fixes bug 1894184.
|
|
||||||
o Add a int64_t parsing function, with unit tests, so we can apply Scott Lamb's fix to allow large HTTP values.
|
|
||||||
o Use a 64-bit field to hold HTTP content-lengths. Patch from Scott Lamb.
|
|
||||||
o Allow regression code to build even without Python installed
|
|
||||||
o remove NDEBUG ifdefs from evdns.c
|
|
||||||
o update documentation of event_loop and event_base_loop; from Tani Hosokawa.
|
|
||||||
o detect integer types properly on platforms without stdint.h
|
|
||||||
o Remove "AM_MAINTAINER_MODE" declaration in configure.in: now makefiles and configure should get re-generated automatically when Makefile.am or configure.in chanes.
|
|
||||||
o do not insert event into list when evsel->add fails
|
|
||||||
|
|
||||||
Changes in 1.4.1-beta:
|
|
||||||
o free minheap on event_base_free(); from Christopher Layne
|
|
||||||
o debug cleanups in signal.c; from Christopher Layne
|
|
||||||
o provide event_base_new() that does not set the current_base global
|
|
||||||
o bufferevent_write now uses a const source argument; report from Charles Kerr
|
|
||||||
o better documentation for event_base_loopexit; from Scott Lamb.
|
|
||||||
o Make kqueue have the same behavior as other backends when a signal is caught between event_add() and event_loop(). Previously, it would catch and ignore such signals.
|
|
||||||
o Make kqueue restore signal handlers correctly when event_del() is called.
|
|
||||||
o provide event_reinit() to reintialize an event_base after fork
|
|
||||||
o small improvements to evhttp documentation
|
|
||||||
o always generate Date and Content-Length headers for HTTP/1.1 replies
|
|
||||||
o set the correct event base for HTTP close events
|
|
||||||
o New function, event_{base_}loopbreak. Like event_loopexit, it makes an event loop stop executing and return. Unlike event_loopexit, it keeps subsequent pending events from getting executed. Patch from Scott Lamb
|
|
||||||
o Removed obsoleted recalc code
|
|
||||||
o pull setters/getters out of RPC structures into a base class to which we just need to store a pointer; this reduces the memory footprint of these structures.
|
|
||||||
o fix a bug with event_rpcgen for integers
|
|
||||||
o move EV_PERSIST handling out of the event backends
|
|
||||||
o support for 32-bit tag numbers in rpc structures; this is wire compatible, but changes the API slightly.
|
|
||||||
o prefix {encode,decode}_tag functions with evtag to avoid collisions
|
|
||||||
o Correctly handle DNS replies with no answers set (Fixes bug 1846282)
|
|
||||||
o The configure script now takes an --enable-gcc-warnigns option that turns on many optional gcc warnings. (Nick has been building with these for a while, but they might be useful to other developers.)
|
|
||||||
o When building with GCC, use the "format" attribute to verify type correctness of calls to printf-like functions.
|
|
||||||
o removed linger from http server socket; reported by Ilya Martynov
|
|
||||||
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
|
|
||||||
o demote most http warnings to debug messages
|
|
||||||
o Fix Solaris compilation; from Magne Mahre
|
|
||||||
o Add a "Date" header to HTTP responses, as required by HTTP 1.1.
|
|
||||||
o Support specifying the local address of an evhttp_connection using set_local_address
|
|
||||||
o Fix a memory leak in which failed HTTP connections would not free the request object
|
|
||||||
o Make adding of array members in event_rpcgen more efficient, but doubling memory allocation
|
|
||||||
o Fix a memory leak in the DNS server
|
|
||||||
o Fix compilation when DNS_USE_OPENSSL_FOR_ID is enabled
|
|
||||||
o Fix buffer size and string generation in evdns_resolve_reverse_ipv6().
|
|
||||||
o Respond to nonstandard DNS queries with "NOTIMPL" rather than by ignoring them.
|
|
||||||
o In DNS responses, the CD flag should be preserved, not the TC flag.
|
|
||||||
o Fix http.c to compile properly with USE_DEBUG; from Christopher Layne
|
|
||||||
o Handle NULL timeouts correctly on Solaris; from Trond Norbye
|
|
||||||
o Recalculate pending events properly when reallocating event array on Solaris; from Trond Norbye
|
|
||||||
o Add Doxygen documentation to header files; from Mark Heily
|
|
||||||
o Add a evdns_set_transaction_id_fn() function to override the default
|
|
||||||
transaction ID generation code.
|
|
||||||
o Add an evutil module (with header evutil.h) to implement our standard cross-platform hacks, on the theory that somebody else would like to use them too.
|
|
||||||
o Fix signals implementation on windows.
|
|
||||||
o Fix http module on windows to close sockets properly.
|
|
||||||
o Make autogen.sh script run correctly on systems where /bin/sh isn't bash. (Patch from Trond Norbye, rewritten by Hagne Mahre and then Hannah Schroeter.)
|
|
||||||
o Skip calling gettime() in timeout_process if we are not in fact waiting for any events. (Patch from Trond Norbye)
|
|
||||||
o Make test subdirectory compile under mingw.
|
|
||||||
o Fix win32 buffer.c behavior so that it is correct for sockets (which do not like ReadFile and WriteFile).
|
|
||||||
o Make the test.sh script run unit tests for the evpoll method.
|
|
||||||
o Make the entire evdns.h header enclosed in "extern C" as appropriate.
|
|
||||||
o Fix implementation of strsep on platforms that lack it
|
|
||||||
o Fix implementation of getaddrinfo on platforms that lack it; mainly, this will make Windows http.c work better. Original patch by Lubomir Marinov.
|
|
||||||
o Fix evport implementation: port_disassociate called on unassociated events resulting in bogus errors; more efficient memory management; from Trond Norbye and Prakash Sangappa
|
|
||||||
o support for hooks on rpc input and output; can be used to implement rpc independent processing such as compression or authentication.
|
|
||||||
o use a min heap instead of a red-black tree for timeouts; as a result finding the min is a O(1) operation now; from Maxim Yegorushkin
|
|
||||||
o associate an event base with an rpc pool
|
|
||||||
o added two additional libraries: libevent_core and libevent_extra in addition to the regular libevent. libevent_core contains only the event core whereas libevent_extra contains dns, http and rpc support
|
|
||||||
o Begin using libtool's library versioning support correctly. If we don't mess up, this will more or less guarantee binaries linked against old versions of libevent continue working when we make changes to libevent that do not break backward compatibility.
|
|
||||||
o Fix evhttp.h compilation when TAILQ_ENTRY is not defined.
|
|
||||||
o Small code cleanups in epoll_dispatch().
|
|
||||||
o Increase the maximum number of addresses read from a packet in evdns to 32.
|
|
||||||
o Remove support for the rtsig method: it hasn't compiled for a while, and nobody seems to miss it very much. Let us know if there's a good reason to put it back in.
|
|
||||||
o Rename the "class" field in evdns_server_request to dns_question_class, so that it won't break compilation under C++. Use a macro so that old code won't break. Mark the macro as deprecated.
|
|
||||||
o Fix DNS unit tests so that having a DNS server with broken IPv6 support is no longer cause for aborting the unit tests.
|
|
||||||
o Make event_base_free() succeed even if there are pending non-internal events on a base. This may still leak memory and fds, but at least it no longer crashes.
|
|
||||||
o Post-process the config.h file into a new, installed event-config.h file that we can install, and whose macros will be safe to include in header files.
|
|
||||||
o Remove the long-deprecated acconfig.h file.
|
|
||||||
o Do not require #include <sys/types.h> before #include <event.h>.
|
|
||||||
o Add new evutil_timer* functions to wrap (or replace) the regular timeval manipulation functions.
|
|
||||||
o Fix many build issues when using the Microsoft C compiler.
|
|
||||||
o Remove a bash-ism in autogen.sh
|
|
||||||
o When calling event_del on a signal, restore the signal handler's previous value rather than setting it to SIG_DFL. Patch from Christopher Layne.
|
|
||||||
o Make the logic for active events work better with internal events; patch from Christopher Layne.
|
|
||||||
o We do not need to specially remove a timeout before calling event_del; patch from Christopher Layne.
|
|
|
@ -1,24 +0,0 @@
|
||||||
Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
|
|
||||||
Copyright 2007-2009 Niels Provos and Nick Mathewson
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
3. The name of the author may not be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
@ -1,124 +0,0 @@
|
||||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
|
||||||
|
|
||||||
# This is the point release for libevent. It shouldn't include any
|
|
||||||
# a/b/c/d/e notations.
|
|
||||||
RELEASE = 1.4
|
|
||||||
|
|
||||||
# This is the version info for the libevent binary API. It has three
|
|
||||||
# numbers:
|
|
||||||
# Current -- the number of the binary API that we're implementing
|
|
||||||
# Revision -- which iteration of the implementation of the binary
|
|
||||||
# API are we supplying?
|
|
||||||
# Age -- How many previous binary API versions do we also
|
|
||||||
# support?
|
|
||||||
#
|
|
||||||
# If we release a new version that does not change the binary API,
|
|
||||||
# increment Revision.
|
|
||||||
#
|
|
||||||
# If we release a new version that changes the binary API, but does
|
|
||||||
# not break programs compiled against the old binary API, increment
|
|
||||||
# Current and Age. Set Revision to 0, since this is the first
|
|
||||||
# implementation of the new API.
|
|
||||||
#
|
|
||||||
# Otherwise, we're changing the binary API and breaking bakward
|
|
||||||
# compatibility with old binaries. Increment Current. Set Age to 0,
|
|
||||||
# since we're backward compatible with no previous APIs. Set Revision
|
|
||||||
# to 0 too.
|
|
||||||
|
|
||||||
# History:
|
|
||||||
# Libevent 1.4.1 was 2:0:0
|
|
||||||
# Libevent 1.4.2 should be 3:0:0
|
|
||||||
# Libevent 1.4.5 is 3:0:1 (we forgot to increment in the past)
|
|
||||||
VERSION_INFO = 3:3:1
|
|
||||||
|
|
||||||
bin_SCRIPTS = event_rpcgen.py
|
|
||||||
|
|
||||||
EXTRA_DIST = autogen.sh event.h event-internal.h log.h evsignal.h evdns.3 \
|
|
||||||
evrpc.h evrpc-internal.h min_heap.h \
|
|
||||||
event.3 \
|
|
||||||
Doxyfile \
|
|
||||||
kqueue.c epoll_sub.c epoll.c select.c poll.c signal.c \
|
|
||||||
evport.c devpoll.c event_rpcgen.py \
|
|
||||||
sample/Makefile.am sample/Makefile.in sample/event-test.c \
|
|
||||||
sample/signal-test.c sample/time-test.c \
|
|
||||||
test/Makefile.am test/Makefile.in test/bench.c test/regress.c \
|
|
||||||
test/test-eof.c test/test-weof.c test/test-time.c \
|
|
||||||
test/test-init.c test/test.sh \
|
|
||||||
compat/sys/queue.h compat/sys/_libevent_time.h \
|
|
||||||
WIN32-Code/config.h \
|
|
||||||
WIN32-Code/event-config.h \
|
|
||||||
WIN32-Code/win32.c \
|
|
||||||
WIN32-Code/tree.h \
|
|
||||||
WIN32-Prj/event_test/event_test.dsp \
|
|
||||||
WIN32-Prj/event_test/test.txt WIN32-Prj/libevent.dsp \
|
|
||||||
WIN32-Prj/libevent.dsw WIN32-Prj/signal_test/signal_test.dsp \
|
|
||||||
WIN32-Prj/time_test/time_test.dsp WIN32-Prj/regress/regress.vcproj \
|
|
||||||
WIN32-Prj/libevent.sln WIN32-Prj/libevent.vcproj
|
|
||||||
|
|
||||||
lib_LTLIBRARIES = libevent.la libevent_core.la libevent_extra.la
|
|
||||||
|
|
||||||
if BUILD_WIN32
|
|
||||||
|
|
||||||
SUBDIRS = . sample
|
|
||||||
SYS_LIBS = -lws2_32
|
|
||||||
SYS_SRC = WIN32-Code/win32.c
|
|
||||||
SYS_INCLUDES = -IWIN32-Code
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
SUBDIRS = . sample test
|
|
||||||
SYS_LIBS =
|
|
||||||
SYS_SRC =
|
|
||||||
SYS_INCLUDES =
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
BUILT_SOURCES = event-config.h
|
|
||||||
|
|
||||||
event-config.h: config.h
|
|
||||||
echo '/* event-config.h' > $@
|
|
||||||
echo ' * Generated by autoconf; post-processed by libevent.' >> $@
|
|
||||||
echo ' * Do not edit this file.' >> $@
|
|
||||||
echo ' * Do not rely on macros in this file existing in later versions.'>> $@
|
|
||||||
echo ' */' >> $@
|
|
||||||
echo '#ifndef _EVENT_CONFIG_H_' >> $@
|
|
||||||
echo '#define _EVENT_CONFIG_H_' >> $@
|
|
||||||
|
|
||||||
sed -e 's/#define /#define _EVENT_/' \
|
|
||||||
-e 's/#undef /#undef _EVENT_/' \
|
|
||||||
-e 's/#ifndef /#ifndef _EVENT_/' < config.h >> $@
|
|
||||||
echo "#endif" >> $@
|
|
||||||
|
|
||||||
CORE_SRC = event.c buffer.c evbuffer.c log.c evutil.c $(SYS_SRC)
|
|
||||||
EXTRA_SRC = event_tagging.c http.c evhttp.h http-internal.h evdns.c \
|
|
||||||
evdns.h evrpc.c evrpc.h evrpc-internal.h \
|
|
||||||
strlcpy.c strlcpy-internal.h strlcpy-internal.h
|
|
||||||
|
|
||||||
libevent_la_SOURCES = $(CORE_SRC) $(EXTRA_SRC)
|
|
||||||
libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
|
|
||||||
libevent_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO)
|
|
||||||
|
|
||||||
libevent_core_la_SOURCES = $(CORE_SRC)
|
|
||||||
libevent_core_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
|
|
||||||
libevent_core_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO)
|
|
||||||
|
|
||||||
libevent_extra_la_SOURCES = $(EXTRA_SRC)
|
|
||||||
libevent_extra_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
|
|
||||||
libevent_extra_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO)
|
|
||||||
|
|
||||||
include_HEADERS = event.h evhttp.h evdns.h evrpc.h evutil.h
|
|
||||||
|
|
||||||
nodist_include_HEADERS = event-config.h
|
|
||||||
|
|
||||||
INCLUDES = -I$(srcdir)/compat $(SYS_INCLUDES)
|
|
||||||
|
|
||||||
man_MANS = event.3 evdns.3
|
|
||||||
|
|
||||||
verify: libevent.la
|
|
||||||
cd test && make verify
|
|
||||||
|
|
||||||
doxygen: FORCE
|
|
||||||
doxygen $(srcdir)/Doxyfile
|
|
||||||
FORCE:
|
|
||||||
|
|
||||||
DISTCLEANFILES = *~ event-config.h
|
|
|
@ -1,976 +0,0 @@
|
||||||
# Makefile.in generated by automake 1.10.1 from Makefile.am.
|
|
||||||
# @configure_input@
|
|
||||||
|
|
||||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
|
||||||
# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
|
||||||
# This Makefile.in is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
|
||||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
# PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
@SET_MAKE@
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VPATH = @srcdir@
|
|
||||||
pkgdatadir = $(datadir)/@PACKAGE@
|
|
||||||
pkglibdir = $(libdir)/@PACKAGE@
|
|
||||||
pkgincludedir = $(includedir)/@PACKAGE@
|
|
||||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
|
||||||
install_sh_DATA = $(install_sh) -c -m 644
|
|
||||||
install_sh_PROGRAM = $(install_sh) -c
|
|
||||||
install_sh_SCRIPT = $(install_sh) -c
|
|
||||||
INSTALL_HEADER = $(INSTALL_DATA)
|
|
||||||
transform = $(program_transform_name)
|
|
||||||
NORMAL_INSTALL = :
|
|
||||||
PRE_INSTALL = :
|
|
||||||
POST_INSTALL = :
|
|
||||||
NORMAL_UNINSTALL = :
|
|
||||||
PRE_UNINSTALL = :
|
|
||||||
POST_UNINSTALL = :
|
|
||||||
build_triplet = @build@
|
|
||||||
host_triplet = @host@
|
|
||||||
subdir = .
|
|
||||||
DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \
|
|
||||||
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
|
|
||||||
$(srcdir)/config.h.in $(top_srcdir)/configure ChangeLog \
|
|
||||||
config.guess config.sub devpoll.c epoll.c epoll_sub.c evport.c \
|
|
||||||
install-sh kqueue.c ltmain.sh missing mkinstalldirs poll.c \
|
|
||||||
select.c signal.c
|
|
||||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
|
||||||
am__aclocal_m4_deps = $(top_srcdir)/configure.in
|
|
||||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
|
||||||
$(ACLOCAL_M4)
|
|
||||||
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
|
||||||
configure.lineno config.status.lineno
|
|
||||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
|
||||||
CONFIG_HEADER = config.h
|
|
||||||
CONFIG_CLEAN_FILES =
|
|
||||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
|
||||||
am__vpath_adj = case $$p in \
|
|
||||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
|
||||||
*) f=$$p;; \
|
|
||||||
esac;
|
|
||||||
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
|
||||||
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
|
|
||||||
"$(DESTDIR)$(man3dir)" "$(DESTDIR)$(includedir)" \
|
|
||||||
"$(DESTDIR)$(includedir)"
|
|
||||||
libLTLIBRARIES_INSTALL = $(INSTALL)
|
|
||||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
|
||||||
am__DEPENDENCIES_1 =
|
|
||||||
libevent_la_DEPENDENCIES = @LTLIBOBJS@ $(am__DEPENDENCIES_1)
|
|
||||||
am__libevent_la_SOURCES_DIST = event.c buffer.c evbuffer.c log.c \
|
|
||||||
evutil.c WIN32-Code/win32.c event_tagging.c http.c evhttp.h \
|
|
||||||
http-internal.h evdns.c evdns.h evrpc.c evrpc.h \
|
|
||||||
evrpc-internal.h strlcpy.c strlcpy-internal.h
|
|
||||||
@BUILD_WIN32_TRUE@am__objects_1 = win32.lo
|
|
||||||
am__objects_2 = event.lo buffer.lo evbuffer.lo log.lo evutil.lo \
|
|
||||||
$(am__objects_1)
|
|
||||||
am__objects_3 = event_tagging.lo http.lo evdns.lo evrpc.lo strlcpy.lo
|
|
||||||
am_libevent_la_OBJECTS = $(am__objects_2) $(am__objects_3)
|
|
||||||
libevent_la_OBJECTS = $(am_libevent_la_OBJECTS)
|
|
||||||
libevent_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
|
||||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
|
||||||
$(libevent_la_LDFLAGS) $(LDFLAGS) -o $@
|
|
||||||
libevent_core_la_DEPENDENCIES = @LTLIBOBJS@ $(am__DEPENDENCIES_1)
|
|
||||||
am__libevent_core_la_SOURCES_DIST = event.c buffer.c evbuffer.c log.c \
|
|
||||||
evutil.c WIN32-Code/win32.c
|
|
||||||
am_libevent_core_la_OBJECTS = $(am__objects_2)
|
|
||||||
libevent_core_la_OBJECTS = $(am_libevent_core_la_OBJECTS)
|
|
||||||
libevent_core_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
|
||||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
|
||||||
$(libevent_core_la_LDFLAGS) $(LDFLAGS) -o $@
|
|
||||||
libevent_extra_la_DEPENDENCIES = @LTLIBOBJS@ $(am__DEPENDENCIES_1)
|
|
||||||
am_libevent_extra_la_OBJECTS = $(am__objects_3)
|
|
||||||
libevent_extra_la_OBJECTS = $(am_libevent_extra_la_OBJECTS)
|
|
||||||
libevent_extra_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
|
||||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
|
||||||
$(libevent_extra_la_LDFLAGS) $(LDFLAGS) -o $@
|
|
||||||
binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
|
|
||||||
SCRIPTS = $(bin_SCRIPTS)
|
|
||||||
DEFAULT_INCLUDES = -I.@am__isrc@
|
|
||||||
depcomp =
|
|
||||||
am__depfiles_maybe =
|
|
||||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
|
||||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
|
||||||
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
|
||||||
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
|
||||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
|
||||||
CCLD = $(CC)
|
|
||||||
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
|
||||||
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
|
|
||||||
$(LDFLAGS) -o $@
|
|
||||||
SOURCES = $(libevent_la_SOURCES) $(libevent_core_la_SOURCES) \
|
|
||||||
$(libevent_extra_la_SOURCES)
|
|
||||||
DIST_SOURCES = $(am__libevent_la_SOURCES_DIST) \
|
|
||||||
$(am__libevent_core_la_SOURCES_DIST) \
|
|
||||||
$(libevent_extra_la_SOURCES)
|
|
||||||
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
|
||||||
html-recursive info-recursive install-data-recursive \
|
|
||||||
install-dvi-recursive install-exec-recursive \
|
|
||||||
install-html-recursive install-info-recursive \
|
|
||||||
install-pdf-recursive install-ps-recursive install-recursive \
|
|
||||||
installcheck-recursive installdirs-recursive pdf-recursive \
|
|
||||||
ps-recursive uninstall-recursive
|
|
||||||
man3dir = $(mandir)/man3
|
|
||||||
NROFF = nroff
|
|
||||||
MANS = $(man_MANS)
|
|
||||||
includeHEADERS_INSTALL = $(INSTALL_HEADER)
|
|
||||||
nodist_includeHEADERS_INSTALL = $(INSTALL_HEADER)
|
|
||||||
HEADERS = $(include_HEADERS) $(nodist_include_HEADERS)
|
|
||||||
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
|
||||||
distclean-recursive maintainer-clean-recursive
|
|
||||||
ETAGS = etags
|
|
||||||
CTAGS = ctags
|
|
||||||
DIST_SUBDIRS = . sample test
|
|
||||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
|
||||||
distdir = $(PACKAGE)-$(VERSION)
|
|
||||||
top_distdir = $(distdir)
|
|
||||||
am__remove_distdir = \
|
|
||||||
{ test ! -d $(distdir) \
|
|
||||||
|| { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
|
|
||||||
&& rm -fr $(distdir); }; }
|
|
||||||
DIST_ARCHIVES = $(distdir).tar.gz
|
|
||||||
GZIP_ENV = --best
|
|
||||||
distuninstallcheck_listfiles = find . -type f -print
|
|
||||||
distcleancheck_listfiles = find . -type f -print
|
|
||||||
ACLOCAL = @ACLOCAL@
|
|
||||||
AMTAR = @AMTAR@
|
|
||||||
AR = @AR@
|
|
||||||
AUTOCONF = @AUTOCONF@
|
|
||||||
AUTOHEADER = @AUTOHEADER@
|
|
||||||
AUTOMAKE = @AUTOMAKE@
|
|
||||||
AWK = @AWK@
|
|
||||||
CC = @CC@
|
|
||||||
CCDEPMODE = @CCDEPMODE@
|
|
||||||
CFLAGS = @CFLAGS@
|
|
||||||
CPP = @CPP@
|
|
||||||
CPPFLAGS = @CPPFLAGS@
|
|
||||||
CXX = @CXX@
|
|
||||||
CXXCPP = @CXXCPP@
|
|
||||||
CXXDEPMODE = @CXXDEPMODE@
|
|
||||||
CXXFLAGS = @CXXFLAGS@
|
|
||||||
CYGPATH_W = @CYGPATH_W@
|
|
||||||
DEFS = @DEFS@
|
|
||||||
DEPDIR = @DEPDIR@
|
|
||||||
DSYMUTIL = @DSYMUTIL@
|
|
||||||
ECHO = @ECHO@
|
|
||||||
ECHO_C = @ECHO_C@
|
|
||||||
ECHO_N = @ECHO_N@
|
|
||||||
ECHO_T = @ECHO_T@
|
|
||||||
EGREP = @EGREP@
|
|
||||||
EXEEXT = @EXEEXT@
|
|
||||||
F77 = @F77@
|
|
||||||
FFLAGS = @FFLAGS@
|
|
||||||
GREP = @GREP@
|
|
||||||
INSTALL = @INSTALL@
|
|
||||||
INSTALL_DATA = @INSTALL_DATA@
|
|
||||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
|
||||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
|
||||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
|
||||||
LDFLAGS = @LDFLAGS@
|
|
||||||
LIBOBJS = @LIBOBJS@
|
|
||||||
LIBS = @LIBS@
|
|
||||||
LIBTOOL = @LIBTOOL@
|
|
||||||
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
|
||||||
LN_S = @LN_S@
|
|
||||||
LTLIBOBJS = @LTLIBOBJS@
|
|
||||||
MAKEINFO = @MAKEINFO@
|
|
||||||
MKDIR_P = @MKDIR_P@
|
|
||||||
NMEDIT = @NMEDIT@
|
|
||||||
OBJEXT = @OBJEXT@
|
|
||||||
PACKAGE = @PACKAGE@
|
|
||||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
|
||||||
PACKAGE_NAME = @PACKAGE_NAME@
|
|
||||||
PACKAGE_STRING = @PACKAGE_STRING@
|
|
||||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
|
||||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
|
||||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
|
||||||
RANLIB = @RANLIB@
|
|
||||||
SED = @SED@
|
|
||||||
SET_MAKE = @SET_MAKE@
|
|
||||||
SHELL = @SHELL@
|
|
||||||
STRIP = @STRIP@
|
|
||||||
VERSION = @VERSION@
|
|
||||||
abs_builddir = @abs_builddir@
|
|
||||||
abs_srcdir = @abs_srcdir@
|
|
||||||
abs_top_builddir = @abs_top_builddir@
|
|
||||||
abs_top_srcdir = @abs_top_srcdir@
|
|
||||||
ac_ct_CC = @ac_ct_CC@
|
|
||||||
ac_ct_CXX = @ac_ct_CXX@
|
|
||||||
ac_ct_F77 = @ac_ct_F77@
|
|
||||||
am__include = @am__include@
|
|
||||||
am__leading_dot = @am__leading_dot@
|
|
||||||
am__quote = @am__quote@
|
|
||||||
am__tar = @am__tar@
|
|
||||||
am__untar = @am__untar@
|
|
||||||
bindir = @bindir@
|
|
||||||
build = @build@
|
|
||||||
build_alias = @build_alias@
|
|
||||||
build_cpu = @build_cpu@
|
|
||||||
build_os = @build_os@
|
|
||||||
build_vendor = @build_vendor@
|
|
||||||
builddir = @builddir@
|
|
||||||
datadir = @datadir@
|
|
||||||
datarootdir = @datarootdir@
|
|
||||||
docdir = @docdir@
|
|
||||||
dvidir = @dvidir@
|
|
||||||
exec_prefix = @exec_prefix@
|
|
||||||
host = @host@
|
|
||||||
host_alias = @host_alias@
|
|
||||||
host_cpu = @host_cpu@
|
|
||||||
host_os = @host_os@
|
|
||||||
host_vendor = @host_vendor@
|
|
||||||
htmldir = @htmldir@
|
|
||||||
includedir = @includedir@
|
|
||||||
infodir = @infodir@
|
|
||||||
install_sh = @install_sh@
|
|
||||||
libdir = @libdir@
|
|
||||||
libexecdir = @libexecdir@
|
|
||||||
localedir = @localedir@
|
|
||||||
localstatedir = @localstatedir@
|
|
||||||
mandir = @mandir@
|
|
||||||
mkdir_p = @mkdir_p@
|
|
||||||
oldincludedir = @oldincludedir@
|
|
||||||
pdfdir = @pdfdir@
|
|
||||||
prefix = @prefix@
|
|
||||||
program_transform_name = @program_transform_name@
|
|
||||||
psdir = @psdir@
|
|
||||||
sbindir = @sbindir@
|
|
||||||
sharedstatedir = @sharedstatedir@
|
|
||||||
srcdir = @srcdir@
|
|
||||||
sysconfdir = @sysconfdir@
|
|
||||||
target_alias = @target_alias@
|
|
||||||
top_build_prefix = @top_build_prefix@
|
|
||||||
top_builddir = @top_builddir@
|
|
||||||
top_srcdir = @top_srcdir@
|
|
||||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
|
||||||
|
|
||||||
# This is the point release for libevent. It shouldn't include any
|
|
||||||
# a/b/c/d/e notations.
|
|
||||||
RELEASE = 1.4
|
|
||||||
|
|
||||||
# This is the version info for the libevent binary API. It has three
|
|
||||||
# numbers:
|
|
||||||
# Current -- the number of the binary API that we're implementing
|
|
||||||
# Revision -- which iteration of the implementation of the binary
|
|
||||||
# API are we supplying?
|
|
||||||
# Age -- How many previous binary API versions do we also
|
|
||||||
# support?
|
|
||||||
#
|
|
||||||
# If we release a new version that does not change the binary API,
|
|
||||||
# increment Revision.
|
|
||||||
#
|
|
||||||
# If we release a new version that changes the binary API, but does
|
|
||||||
# not break programs compiled against the old binary API, increment
|
|
||||||
# Current and Age. Set Revision to 0, since this is the first
|
|
||||||
# implementation of the new API.
|
|
||||||
#
|
|
||||||
# Otherwise, we're changing the binary API and breaking bakward
|
|
||||||
# compatibility with old binaries. Increment Current. Set Age to 0,
|
|
||||||
# since we're backward compatible with no previous APIs. Set Revision
|
|
||||||
# to 0 too.
|
|
||||||
|
|
||||||
# History:
|
|
||||||
# Libevent 1.4.1 was 2:0:0
|
|
||||||
# Libevent 1.4.2 should be 3:0:0
|
|
||||||
# Libevent 1.4.5 is 3:0:1 (we forgot to increment in the past)
|
|
||||||
VERSION_INFO = 3:3:1
|
|
||||||
bin_SCRIPTS = event_rpcgen.py
|
|
||||||
EXTRA_DIST = autogen.sh event.h event-internal.h log.h evsignal.h evdns.3 \
|
|
||||||
evrpc.h evrpc-internal.h min_heap.h \
|
|
||||||
event.3 \
|
|
||||||
Doxyfile \
|
|
||||||
kqueue.c epoll_sub.c epoll.c select.c poll.c signal.c \
|
|
||||||
evport.c devpoll.c event_rpcgen.py \
|
|
||||||
sample/Makefile.am sample/Makefile.in sample/event-test.c \
|
|
||||||
sample/signal-test.c sample/time-test.c \
|
|
||||||
test/Makefile.am test/Makefile.in test/bench.c test/regress.c \
|
|
||||||
test/test-eof.c test/test-weof.c test/test-time.c \
|
|
||||||
test/test-init.c test/test.sh \
|
|
||||||
compat/sys/queue.h compat/sys/_libevent_time.h \
|
|
||||||
WIN32-Code/config.h \
|
|
||||||
WIN32-Code/event-config.h \
|
|
||||||
WIN32-Code/win32.c \
|
|
||||||
WIN32-Code/tree.h \
|
|
||||||
WIN32-Prj/event_test/event_test.dsp \
|
|
||||||
WIN32-Prj/event_test/test.txt WIN32-Prj/libevent.dsp \
|
|
||||||
WIN32-Prj/libevent.dsw WIN32-Prj/signal_test/signal_test.dsp \
|
|
||||||
WIN32-Prj/time_test/time_test.dsp WIN32-Prj/regress/regress.vcproj \
|
|
||||||
WIN32-Prj/libevent.sln WIN32-Prj/libevent.vcproj
|
|
||||||
|
|
||||||
lib_LTLIBRARIES = libevent.la libevent_core.la libevent_extra.la
|
|
||||||
@BUILD_WIN32_FALSE@SUBDIRS = . sample test
|
|
||||||
@BUILD_WIN32_TRUE@SUBDIRS = . sample
|
|
||||||
@BUILD_WIN32_FALSE@SYS_LIBS =
|
|
||||||
@BUILD_WIN32_TRUE@SYS_LIBS = -lws2_32
|
|
||||||
@BUILD_WIN32_FALSE@SYS_SRC =
|
|
||||||
@BUILD_WIN32_TRUE@SYS_SRC = WIN32-Code/win32.c
|
|
||||||
@BUILD_WIN32_FALSE@SYS_INCLUDES =
|
|
||||||
@BUILD_WIN32_TRUE@SYS_INCLUDES = -IWIN32-Code
|
|
||||||
BUILT_SOURCES = event-config.h
|
|
||||||
CORE_SRC = event.c buffer.c evbuffer.c log.c evutil.c $(SYS_SRC)
|
|
||||||
EXTRA_SRC = event_tagging.c http.c evhttp.h http-internal.h evdns.c \
|
|
||||||
evdns.h evrpc.c evrpc.h evrpc-internal.h \
|
|
||||||
strlcpy.c strlcpy-internal.h strlcpy-internal.h
|
|
||||||
|
|
||||||
libevent_la_SOURCES = $(CORE_SRC) $(EXTRA_SRC)
|
|
||||||
libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
|
|
||||||
libevent_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO)
|
|
||||||
libevent_core_la_SOURCES = $(CORE_SRC)
|
|
||||||
libevent_core_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
|
|
||||||
libevent_core_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO)
|
|
||||||
libevent_extra_la_SOURCES = $(EXTRA_SRC)
|
|
||||||
libevent_extra_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
|
|
||||||
libevent_extra_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO)
|
|
||||||
include_HEADERS = event.h evhttp.h evdns.h evrpc.h evutil.h
|
|
||||||
nodist_include_HEADERS = event-config.h
|
|
||||||
INCLUDES = -I$(srcdir)/compat $(SYS_INCLUDES)
|
|
||||||
man_MANS = event.3 evdns.3
|
|
||||||
DISTCLEANFILES = *~ event-config.h
|
|
||||||
all: $(BUILT_SOURCES) config.h
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
|
||||||
|
|
||||||
.SUFFIXES:
|
|
||||||
.SUFFIXES: .c .lo .o .obj
|
|
||||||
am--refresh:
|
|
||||||
@:
|
|
||||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
|
||||||
@for dep in $?; do \
|
|
||||||
case '$(am__configure_deps)' in \
|
|
||||||
*$$dep*) \
|
|
||||||
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
|
|
||||||
cd $(srcdir) && $(AUTOMAKE) --foreign \
|
|
||||||
&& exit 0; \
|
|
||||||
exit 1;; \
|
|
||||||
esac; \
|
|
||||||
done; \
|
|
||||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
|
|
||||||
cd $(top_srcdir) && \
|
|
||||||
$(AUTOMAKE) --foreign Makefile
|
|
||||||
.PRECIOUS: Makefile
|
|
||||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
|
||||||
@case '$?' in \
|
|
||||||
*config.status*) \
|
|
||||||
echo ' $(SHELL) ./config.status'; \
|
|
||||||
$(SHELL) ./config.status;; \
|
|
||||||
*) \
|
|
||||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
|
|
||||||
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
|
|
||||||
esac;
|
|
||||||
|
|
||||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
|
||||||
$(SHELL) ./config.status --recheck
|
|
||||||
|
|
||||||
$(top_srcdir)/configure: $(am__configure_deps)
|
|
||||||
cd $(srcdir) && $(AUTOCONF)
|
|
||||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
|
||||||
cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
|
||||||
|
|
||||||
config.h: stamp-h1
|
|
||||||
@if test ! -f $@; then \
|
|
||||||
rm -f stamp-h1; \
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
|
|
||||||
else :; fi
|
|
||||||
|
|
||||||
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
|
|
||||||
@rm -f stamp-h1
|
|
||||||
cd $(top_builddir) && $(SHELL) ./config.status config.h
|
|
||||||
$(srcdir)/config.h.in: $(am__configure_deps)
|
|
||||||
cd $(top_srcdir) && $(AUTOHEADER)
|
|
||||||
rm -f stamp-h1
|
|
||||||
touch $@
|
|
||||||
|
|
||||||
distclean-hdr:
|
|
||||||
-rm -f config.h stamp-h1
|
|
||||||
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
|
|
||||||
@$(NORMAL_INSTALL)
|
|
||||||
test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
|
|
||||||
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
|
|
||||||
if test -f $$p; then \
|
|
||||||
f=$(am__strip_dir) \
|
|
||||||
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
|
|
||||||
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
|
|
||||||
else :; fi; \
|
|
||||||
done
|
|
||||||
|
|
||||||
uninstall-libLTLIBRARIES:
|
|
||||||
@$(NORMAL_UNINSTALL)
|
|
||||||
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
|
|
||||||
p=$(am__strip_dir) \
|
|
||||||
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
|
|
||||||
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
|
|
||||||
done
|
|
||||||
|
|
||||||
clean-libLTLIBRARIES:
|
|
||||||
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
|
|
||||||
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
|
|
||||||
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
|
|
||||||
test "$$dir" != "$$p" || dir=.; \
|
|
||||||
echo "rm -f \"$${dir}/so_locations\""; \
|
|
||||||
rm -f "$${dir}/so_locations"; \
|
|
||||||
done
|
|
||||||
libevent.la: $(libevent_la_OBJECTS) $(libevent_la_DEPENDENCIES)
|
|
||||||
$(libevent_la_LINK) -rpath $(libdir) $(libevent_la_OBJECTS) $(libevent_la_LIBADD) $(LIBS)
|
|
||||||
libevent_core.la: $(libevent_core_la_OBJECTS) $(libevent_core_la_DEPENDENCIES)
|
|
||||||
$(libevent_core_la_LINK) -rpath $(libdir) $(libevent_core_la_OBJECTS) $(libevent_core_la_LIBADD) $(LIBS)
|
|
||||||
libevent_extra.la: $(libevent_extra_la_OBJECTS) $(libevent_extra_la_DEPENDENCIES)
|
|
||||||
$(libevent_extra_la_LINK) -rpath $(libdir) $(libevent_extra_la_OBJECTS) $(libevent_extra_la_LIBADD) $(LIBS)
|
|
||||||
install-binSCRIPTS: $(bin_SCRIPTS)
|
|
||||||
@$(NORMAL_INSTALL)
|
|
||||||
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
|
|
||||||
@list='$(bin_SCRIPTS)'; for p in $$list; do \
|
|
||||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
|
||||||
if test -f $$d$$p; then \
|
|
||||||
f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
|
|
||||||
echo " $(binSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(bindir)/$$f'"; \
|
|
||||||
$(binSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(bindir)/$$f"; \
|
|
||||||
else :; fi; \
|
|
||||||
done
|
|
||||||
|
|
||||||
uninstall-binSCRIPTS:
|
|
||||||
@$(NORMAL_UNINSTALL)
|
|
||||||
@list='$(bin_SCRIPTS)'; for p in $$list; do \
|
|
||||||
f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
|
|
||||||
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
|
|
||||||
rm -f "$(DESTDIR)$(bindir)/$$f"; \
|
|
||||||
done
|
|
||||||
|
|
||||||
mostlyclean-compile:
|
|
||||||
-rm -f *.$(OBJEXT)
|
|
||||||
|
|
||||||
distclean-compile:
|
|
||||||
-rm -f *.tab.c
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(COMPILE) -c $<
|
|
||||||
|
|
||||||
.c.obj:
|
|
||||||
$(COMPILE) -c `$(CYGPATH_W) '$<'`
|
|
||||||
|
|
||||||
.c.lo:
|
|
||||||
$(LTCOMPILE) -c -o $@ $<
|
|
||||||
|
|
||||||
win32.lo: WIN32-Code/win32.c
|
|
||||||
$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o win32.lo `test -f 'WIN32-Code/win32.c' || echo '$(srcdir)/'`WIN32-Code/win32.c
|
|
||||||
|
|
||||||
mostlyclean-libtool:
|
|
||||||
-rm -f *.lo
|
|
||||||
|
|
||||||
clean-libtool:
|
|
||||||
-rm -rf .libs _libs
|
|
||||||
|
|
||||||
distclean-libtool:
|
|
||||||
-rm -f libtool
|
|
||||||
install-man3: $(man3_MANS) $(man_MANS)
|
|
||||||
@$(NORMAL_INSTALL)
|
|
||||||
test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)"
|
|
||||||
@list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \
|
|
||||||
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
|
|
||||||
for i in $$l2; do \
|
|
||||||
case "$$i" in \
|
|
||||||
*.3*) list="$$list $$i" ;; \
|
|
||||||
esac; \
|
|
||||||
done; \
|
|
||||||
for i in $$list; do \
|
|
||||||
if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
|
|
||||||
else file=$$i; fi; \
|
|
||||||
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
|
|
||||||
case "$$ext" in \
|
|
||||||
3*) ;; \
|
|
||||||
*) ext='3' ;; \
|
|
||||||
esac; \
|
|
||||||
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
|
|
||||||
inst=`echo $$inst | sed -e 's/^.*\///'`; \
|
|
||||||
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
|
|
||||||
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \
|
|
||||||
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst"; \
|
|
||||||
done
|
|
||||||
uninstall-man3:
|
|
||||||
@$(NORMAL_UNINSTALL)
|
|
||||||
@list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \
|
|
||||||
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
|
|
||||||
for i in $$l2; do \
|
|
||||||
case "$$i" in \
|
|
||||||
*.3*) list="$$list $$i" ;; \
|
|
||||||
esac; \
|
|
||||||
done; \
|
|
||||||
for i in $$list; do \
|
|
||||||
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
|
|
||||||
case "$$ext" in \
|
|
||||||
3*) ;; \
|
|
||||||
*) ext='3' ;; \
|
|
||||||
esac; \
|
|
||||||
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
|
|
||||||
inst=`echo $$inst | sed -e 's/^.*\///'`; \
|
|
||||||
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
|
|
||||||
echo " rm -f '$(DESTDIR)$(man3dir)/$$inst'"; \
|
|
||||||
rm -f "$(DESTDIR)$(man3dir)/$$inst"; \
|
|
||||||
done
|
|
||||||
install-includeHEADERS: $(include_HEADERS)
|
|
||||||
@$(NORMAL_INSTALL)
|
|
||||||
test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
|
|
||||||
@list='$(include_HEADERS)'; for p in $$list; do \
|
|
||||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
|
||||||
f=$(am__strip_dir) \
|
|
||||||
echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
|
|
||||||
$(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
|
|
||||||
done
|
|
||||||
|
|
||||||
uninstall-includeHEADERS:
|
|
||||||
@$(NORMAL_UNINSTALL)
|
|
||||||
@list='$(include_HEADERS)'; for p in $$list; do \
|
|
||||||
f=$(am__strip_dir) \
|
|
||||||
echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
|
|
||||||
rm -f "$(DESTDIR)$(includedir)/$$f"; \
|
|
||||||
done
|
|
||||||
install-nodist_includeHEADERS: $(nodist_include_HEADERS)
|
|
||||||
@$(NORMAL_INSTALL)
|
|
||||||
test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
|
|
||||||
@list='$(nodist_include_HEADERS)'; for p in $$list; do \
|
|
||||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
|
||||||
f=$(am__strip_dir) \
|
|
||||||
echo " $(nodist_includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
|
|
||||||
$(nodist_includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
|
|
||||||
done
|
|
||||||
|
|
||||||
uninstall-nodist_includeHEADERS:
|
|
||||||
@$(NORMAL_UNINSTALL)
|
|
||||||
@list='$(nodist_include_HEADERS)'; for p in $$list; do \
|
|
||||||
f=$(am__strip_dir) \
|
|
||||||
echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
|
|
||||||
rm -f "$(DESTDIR)$(includedir)/$$f"; \
|
|
||||||
done
|
|
||||||
|
|
||||||
# This directory's subdirectories are mostly independent; you can cd
|
|
||||||
# into them and run `make' without going through this Makefile.
|
|
||||||
# To change the values of `make' variables: instead of editing Makefiles,
|
|
||||||
# (1) if the variable is set in `config.status', edit `config.status'
|
|
||||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
|
||||||
# (2) otherwise, pass the desired values on the `make' command line.
|
|
||||||
$(RECURSIVE_TARGETS):
|
|
||||||
@failcom='exit 1'; \
|
|
||||||
for f in x $$MAKEFLAGS; do \
|
|
||||||
case $$f in \
|
|
||||||
*=* | --[!k]*);; \
|
|
||||||
*k*) failcom='fail=yes';; \
|
|
||||||
esac; \
|
|
||||||
done; \
|
|
||||||
dot_seen=no; \
|
|
||||||
target=`echo $@ | sed s/-recursive//`; \
|
|
||||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
|
||||||
echo "Making $$target in $$subdir"; \
|
|
||||||
if test "$$subdir" = "."; then \
|
|
||||||
dot_seen=yes; \
|
|
||||||
local_target="$$target-am"; \
|
|
||||||
else \
|
|
||||||
local_target="$$target"; \
|
|
||||||
fi; \
|
|
||||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
|
||||||
|| eval $$failcom; \
|
|
||||||
done; \
|
|
||||||
if test "$$dot_seen" = "no"; then \
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
|
||||||
fi; test -z "$$fail"
|
|
||||||
|
|
||||||
$(RECURSIVE_CLEAN_TARGETS):
|
|
||||||
@failcom='exit 1'; \
|
|
||||||
for f in x $$MAKEFLAGS; do \
|
|
||||||
case $$f in \
|
|
||||||
*=* | --[!k]*);; \
|
|
||||||
*k*) failcom='fail=yes';; \
|
|
||||||
esac; \
|
|
||||||
done; \
|
|
||||||
dot_seen=no; \
|
|
||||||
case "$@" in \
|
|
||||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
|
||||||
*) list='$(SUBDIRS)' ;; \
|
|
||||||
esac; \
|
|
||||||
rev=''; for subdir in $$list; do \
|
|
||||||
if test "$$subdir" = "."; then :; else \
|
|
||||||
rev="$$subdir $$rev"; \
|
|
||||||
fi; \
|
|
||||||
done; \
|
|
||||||
rev="$$rev ."; \
|
|
||||||
target=`echo $@ | sed s/-recursive//`; \
|
|
||||||
for subdir in $$rev; do \
|
|
||||||
echo "Making $$target in $$subdir"; \
|
|
||||||
if test "$$subdir" = "."; then \
|
|
||||||
local_target="$$target-am"; \
|
|
||||||
else \
|
|
||||||
local_target="$$target"; \
|
|
||||||
fi; \
|
|
||||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
|
||||||
|| eval $$failcom; \
|
|
||||||
done && test -z "$$fail"
|
|
||||||
tags-recursive:
|
|
||||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
|
||||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
|
|
||||||
done
|
|
||||||
ctags-recursive:
|
|
||||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
|
||||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
|
|
||||||
done
|
|
||||||
|
|
||||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
|
||||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
|
||||||
unique=`for i in $$list; do \
|
|
||||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
|
||||||
done | \
|
|
||||||
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
|
|
||||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
|
||||||
mkid -fID $$unique
|
|
||||||
tags: TAGS
|
|
||||||
|
|
||||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
|
|
||||||
$(TAGS_FILES) $(LISP)
|
|
||||||
tags=; \
|
|
||||||
here=`pwd`; \
|
|
||||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
|
||||||
include_option=--etags-include; \
|
|
||||||
empty_fix=.; \
|
|
||||||
else \
|
|
||||||
include_option=--include; \
|
|
||||||
empty_fix=; \
|
|
||||||
fi; \
|
|
||||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
|
||||||
if test "$$subdir" = .; then :; else \
|
|
||||||
test ! -f $$subdir/TAGS || \
|
|
||||||
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
|
|
||||||
fi; \
|
|
||||||
done; \
|
|
||||||
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
|
|
||||||
unique=`for i in $$list; do \
|
|
||||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
|
||||||
done | \
|
|
||||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
|
||||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
|
||||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
|
||||||
test -n "$$unique" || unique=$$empty_fix; \
|
|
||||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
|
||||||
$$tags $$unique; \
|
|
||||||
fi
|
|
||||||
ctags: CTAGS
|
|
||||||
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
|
|
||||||
$(TAGS_FILES) $(LISP)
|
|
||||||
tags=; \
|
|
||||||
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
|
|
||||||
unique=`for i in $$list; do \
|
|
||||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
|
||||||
done | \
|
|
||||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
|
||||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
|
||||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
|
||||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
|
||||||
$$tags $$unique
|
|
||||||
|
|
||||||
GTAGS:
|
|
||||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
|
||||||
&& cd $(top_srcdir) \
|
|
||||||
&& gtags -i $(GTAGS_ARGS) $$here
|
|
||||||
|
|
||||||
distclean-tags:
|
|
||||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
|
||||||
|
|
||||||
distdir: $(DISTFILES)
|
|
||||||
$(am__remove_distdir)
|
|
||||||
test -d $(distdir) || mkdir $(distdir)
|
|
||||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
|
||||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
|
||||||
list='$(DISTFILES)'; \
|
|
||||||
dist_files=`for file in $$list; do echo $$file; done | \
|
|
||||||
sed -e "s|^$$srcdirstrip/||;t" \
|
|
||||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
|
||||||
case $$dist_files in \
|
|
||||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
|
||||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
|
||||||
sort -u` ;; \
|
|
||||||
esac; \
|
|
||||||
for file in $$dist_files; do \
|
|
||||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
|
||||||
if test -d $$d/$$file; then \
|
|
||||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
|
||||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
|
||||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
|
||||||
fi; \
|
|
||||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
|
||||||
else \
|
|
||||||
test -f $(distdir)/$$file \
|
|
||||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
|
||||||
|| exit 1; \
|
|
||||||
fi; \
|
|
||||||
done
|
|
||||||
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
|
||||||
if test "$$subdir" = .; then :; else \
|
|
||||||
test -d "$(distdir)/$$subdir" \
|
|
||||||
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
|
||||||
|| exit 1; \
|
|
||||||
distdir=`$(am__cd) $(distdir) && pwd`; \
|
|
||||||
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
|
|
||||||
(cd $$subdir && \
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) \
|
|
||||||
top_distdir="$$top_distdir" \
|
|
||||||
distdir="$$distdir/$$subdir" \
|
|
||||||
am__remove_distdir=: \
|
|
||||||
am__skip_length_check=: \
|
|
||||||
distdir) \
|
|
||||||
|| exit 1; \
|
|
||||||
fi; \
|
|
||||||
done
|
|
||||||
-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
|
|
||||||
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
|
||||||
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
|
||||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
|
||||||
|| chmod -R a+r $(distdir)
|
|
||||||
dist-gzip: distdir
|
|
||||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
|
||||||
$(am__remove_distdir)
|
|
||||||
|
|
||||||
dist-bzip2: distdir
|
|
||||||
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
|
|
||||||
$(am__remove_distdir)
|
|
||||||
|
|
||||||
dist-lzma: distdir
|
|
||||||
tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
|
|
||||||
$(am__remove_distdir)
|
|
||||||
|
|
||||||
dist-tarZ: distdir
|
|
||||||
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
|
|
||||||
$(am__remove_distdir)
|
|
||||||
|
|
||||||
dist-shar: distdir
|
|
||||||
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
|
|
||||||
$(am__remove_distdir)
|
|
||||||
|
|
||||||
dist-zip: distdir
|
|
||||||
-rm -f $(distdir).zip
|
|
||||||
zip -rq $(distdir).zip $(distdir)
|
|
||||||
$(am__remove_distdir)
|
|
||||||
|
|
||||||
dist dist-all: distdir
|
|
||||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
|
||||||
$(am__remove_distdir)
|
|
||||||
|
|
||||||
# This target untars the dist file and tries a VPATH configuration. Then
|
|
||||||
# it guarantees that the distribution is self-contained by making another
|
|
||||||
# tarfile.
|
|
||||||
distcheck: dist
|
|
||||||
case '$(DIST_ARCHIVES)' in \
|
|
||||||
*.tar.gz*) \
|
|
||||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
|
|
||||||
*.tar.bz2*) \
|
|
||||||
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
|
|
||||||
*.tar.lzma*) \
|
|
||||||
unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
|
|
||||||
*.tar.Z*) \
|
|
||||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
|
||||||
*.shar.gz*) \
|
|
||||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
|
|
||||||
*.zip*) \
|
|
||||||
unzip $(distdir).zip ;;\
|
|
||||||
esac
|
|
||||||
chmod -R a-w $(distdir); chmod a+w $(distdir)
|
|
||||||
mkdir $(distdir)/_build
|
|
||||||
mkdir $(distdir)/_inst
|
|
||||||
chmod a-w $(distdir)
|
|
||||||
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
|
|
||||||
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
|
|
||||||
&& cd $(distdir)/_build \
|
|
||||||
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
|
|
||||||
$(DISTCHECK_CONFIGURE_FLAGS) \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
|
|
||||||
distuninstallcheck \
|
|
||||||
&& chmod -R a-w "$$dc_install_base" \
|
|
||||||
&& ({ \
|
|
||||||
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
|
|
||||||
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
|
|
||||||
} || { rm -rf "$$dc_destdir"; exit 1; }) \
|
|
||||||
&& rm -rf "$$dc_destdir" \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) dist \
|
|
||||||
&& rm -rf $(DIST_ARCHIVES) \
|
|
||||||
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck
|
|
||||||
$(am__remove_distdir)
|
|
||||||
@(echo "$(distdir) archives ready for distribution: "; \
|
|
||||||
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
|
|
||||||
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
|
|
||||||
distuninstallcheck:
|
|
||||||
@cd $(distuninstallcheck_dir) \
|
|
||||||
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|
|
||||||
|| { echo "ERROR: files left after uninstall:" ; \
|
|
||||||
if test -n "$(DESTDIR)"; then \
|
|
||||||
echo " (check DESTDIR support)"; \
|
|
||||||
fi ; \
|
|
||||||
$(distuninstallcheck_listfiles) ; \
|
|
||||||
exit 1; } >&2
|
|
||||||
distcleancheck: distclean
|
|
||||||
@if test '$(srcdir)' = . ; then \
|
|
||||||
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
|
|
||||||
exit 1 ; \
|
|
||||||
fi
|
|
||||||
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|
|
||||||
|| { echo "ERROR: files left in build directory after distclean:" ; \
|
|
||||||
$(distcleancheck_listfiles) ; \
|
|
||||||
exit 1; } >&2
|
|
||||||
check-am: all-am
|
|
||||||
check: $(BUILT_SOURCES)
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) check-recursive
|
|
||||||
all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) $(MANS) $(HEADERS) config.h
|
|
||||||
installdirs: installdirs-recursive
|
|
||||||
installdirs-am:
|
|
||||||
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"; do \
|
|
||||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
|
||||||
done
|
|
||||||
install: $(BUILT_SOURCES)
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) install-recursive
|
|
||||||
install-exec: install-exec-recursive
|
|
||||||
install-data: install-data-recursive
|
|
||||||
uninstall: uninstall-recursive
|
|
||||||
|
|
||||||
install-am: all-am
|
|
||||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
|
||||||
|
|
||||||
installcheck: installcheck-recursive
|
|
||||||
install-strip:
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
|
||||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
|
||||||
`test -z '$(STRIP)' || \
|
|
||||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
|
||||||
mostlyclean-generic:
|
|
||||||
|
|
||||||
clean-generic:
|
|
||||||
|
|
||||||
distclean-generic:
|
|
||||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
|
||||||
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
|
|
||||||
|
|
||||||
maintainer-clean-generic:
|
|
||||||
@echo "This command is intended for maintainers to use"
|
|
||||||
@echo "it deletes files that may require special tools to rebuild."
|
|
||||||
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
|
||||||
clean: clean-recursive
|
|
||||||
|
|
||||||
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
|
|
||||||
mostlyclean-am
|
|
||||||
|
|
||||||
distclean: distclean-recursive
|
|
||||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
|
||||||
-rm -f Makefile
|
|
||||||
distclean-am: clean-am distclean-compile distclean-generic \
|
|
||||||
distclean-hdr distclean-libtool distclean-tags
|
|
||||||
|
|
||||||
dvi: dvi-recursive
|
|
||||||
|
|
||||||
dvi-am:
|
|
||||||
|
|
||||||
html: html-recursive
|
|
||||||
|
|
||||||
info: info-recursive
|
|
||||||
|
|
||||||
info-am:
|
|
||||||
|
|
||||||
install-data-am: install-includeHEADERS install-man \
|
|
||||||
install-nodist_includeHEADERS
|
|
||||||
|
|
||||||
install-dvi: install-dvi-recursive
|
|
||||||
|
|
||||||
install-exec-am: install-binSCRIPTS install-libLTLIBRARIES
|
|
||||||
|
|
||||||
install-html: install-html-recursive
|
|
||||||
|
|
||||||
install-info: install-info-recursive
|
|
||||||
|
|
||||||
install-man: install-man3
|
|
||||||
|
|
||||||
install-pdf: install-pdf-recursive
|
|
||||||
|
|
||||||
install-ps: install-ps-recursive
|
|
||||||
|
|
||||||
installcheck-am:
|
|
||||||
|
|
||||||
maintainer-clean: maintainer-clean-recursive
|
|
||||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
|
||||||
-rm -rf $(top_srcdir)/autom4te.cache
|
|
||||||
-rm -f Makefile
|
|
||||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
|
||||||
|
|
||||||
mostlyclean: mostlyclean-recursive
|
|
||||||
|
|
||||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
|
||||||
mostlyclean-libtool
|
|
||||||
|
|
||||||
pdf: pdf-recursive
|
|
||||||
|
|
||||||
pdf-am:
|
|
||||||
|
|
||||||
ps: ps-recursive
|
|
||||||
|
|
||||||
ps-am:
|
|
||||||
|
|
||||||
uninstall-am: uninstall-binSCRIPTS uninstall-includeHEADERS \
|
|
||||||
uninstall-libLTLIBRARIES uninstall-man \
|
|
||||||
uninstall-nodist_includeHEADERS
|
|
||||||
|
|
||||||
uninstall-man: uninstall-man3
|
|
||||||
|
|
||||||
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
|
|
||||||
install-strip
|
|
||||||
|
|
||||||
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
|
|
||||||
all all-am am--refresh check check-am clean clean-generic \
|
|
||||||
clean-libLTLIBRARIES clean-libtool ctags ctags-recursive dist \
|
|
||||||
dist-all dist-bzip2 dist-gzip dist-lzma dist-shar dist-tarZ \
|
|
||||||
dist-zip distcheck distclean distclean-compile \
|
|
||||||
distclean-generic distclean-hdr distclean-libtool \
|
|
||||||
distclean-tags distcleancheck distdir distuninstallcheck dvi \
|
|
||||||
dvi-am html html-am info info-am install install-am \
|
|
||||||
install-binSCRIPTS install-data install-data-am install-dvi \
|
|
||||||
install-dvi-am install-exec install-exec-am install-html \
|
|
||||||
install-html-am install-includeHEADERS install-info \
|
|
||||||
install-info-am install-libLTLIBRARIES install-man \
|
|
||||||
install-man3 install-nodist_includeHEADERS install-pdf \
|
|
||||||
install-pdf-am install-ps install-ps-am install-strip \
|
|
||||||
installcheck installcheck-am installdirs installdirs-am \
|
|
||||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
|
||||||
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
|
|
||||||
pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
|
|
||||||
uninstall-binSCRIPTS uninstall-includeHEADERS \
|
|
||||||
uninstall-libLTLIBRARIES uninstall-man uninstall-man3 \
|
|
||||||
uninstall-nodist_includeHEADERS
|
|
||||||
|
|
||||||
|
|
||||||
event-config.h: config.h
|
|
||||||
echo '/* event-config.h' > $@
|
|
||||||
echo ' * Generated by autoconf; post-processed by libevent.' >> $@
|
|
||||||
echo ' * Do not edit this file.' >> $@
|
|
||||||
echo ' * Do not rely on macros in this file existing in later versions.'>> $@
|
|
||||||
echo ' */' >> $@
|
|
||||||
echo '#ifndef _EVENT_CONFIG_H_' >> $@
|
|
||||||
echo '#define _EVENT_CONFIG_H_' >> $@
|
|
||||||
|
|
||||||
sed -e 's/#define /#define _EVENT_/' \
|
|
||||||
-e 's/#undef /#undef _EVENT_/' \
|
|
||||||
-e 's/#ifndef /#ifndef _EVENT_/' < config.h >> $@
|
|
||||||
echo "#endif" >> $@
|
|
||||||
|
|
||||||
verify: libevent.la
|
|
||||||
cd test && make verify
|
|
||||||
|
|
||||||
doxygen: FORCE
|
|
||||||
doxygen $(srcdir)/Doxyfile
|
|
||||||
FORCE:
|
|
||||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
|
||||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
|
||||||
.NOEXPORT:
|
|
|
@ -1,57 +0,0 @@
|
||||||
To build libevent, type
|
|
||||||
|
|
||||||
$ ./configure && make
|
|
||||||
|
|
||||||
(If you got libevent from the subversion repository, you will
|
|
||||||
first need to run the included "autogen.sh" script in order to
|
|
||||||
generate the configure script.)
|
|
||||||
|
|
||||||
Install as root via
|
|
||||||
|
|
||||||
# make install
|
|
||||||
|
|
||||||
You can run the regression tests by
|
|
||||||
|
|
||||||
$ make verify
|
|
||||||
|
|
||||||
Before, reporting any problems, please run the regression tests.
|
|
||||||
|
|
||||||
To enable the low-level tracing build the library as:
|
|
||||||
|
|
||||||
CFLAGS=-DUSE_DEBUG ./configure [...]
|
|
||||||
|
|
||||||
Acknowledgements:
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
The following people have helped with suggestions, ideas, code or
|
|
||||||
fixing bugs:
|
|
||||||
|
|
||||||
Alejo
|
|
||||||
Weston Andros Adamson
|
|
||||||
William Ahern
|
|
||||||
Stas Bekman
|
|
||||||
Andrew Danforth
|
|
||||||
Mike Davis
|
|
||||||
Shie Erlich
|
|
||||||
Alexander von Gernler
|
|
||||||
Artur Grabowski
|
|
||||||
Aaron Hopkins
|
|
||||||
Claudio Jeker
|
|
||||||
Scott Lamb
|
|
||||||
Adam Langley
|
|
||||||
Philip Lewis
|
|
||||||
David Libenzi
|
|
||||||
Nick Mathewson
|
|
||||||
Andrey Matveev
|
|
||||||
Richard Nyberg
|
|
||||||
Jon Oberheide
|
|
||||||
Phil Oleson
|
|
||||||
Dave Pacheco
|
|
||||||
Tassilo von Parseval
|
|
||||||
Pierre Phaneuf
|
|
||||||
Jon Poland
|
|
||||||
Bert JW Regeer
|
|
||||||
Dug Song
|
|
||||||
Taral
|
|
||||||
|
|
||||||
If I have forgotten your name, please contact me.
|
|
|
@ -1,20 +0,0 @@
|
||||||
Name: libevent
|
|
||||||
URL: http://www.monkey.org/~provos/libevent/
|
|
||||||
Version: 1.4.13
|
|
||||||
License: BSD
|
|
||||||
Security Critical: yes
|
|
||||||
|
|
||||||
Local Modifications:
|
|
||||||
Rather than use libevent's own build system, we just build a Chrome
|
|
||||||
static library using GYP.
|
|
||||||
|
|
||||||
1) Run configure and "make event-config.h" on Linux, FreeBSD, Solaris,
|
|
||||||
and Mac and copy config.h and event-config.h to linux/, freebsd/,
|
|
||||||
solaris/, and mac/ respectively.
|
|
||||||
2) Add libevent.gyp.
|
|
||||||
3) chromium.patch is applied to allow libevent to be used without
|
|
||||||
being installed.
|
|
||||||
4) The directories WIN32-Code and WIN32-Prj are not included.
|
|
||||||
5) Apply r87338.
|
|
||||||
6) The configs for android were copied from Linux's which were very close to
|
|
||||||
android one with the exception of HAVE_FD_MASK and HAVE_STRLCPY.
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,266 +0,0 @@
|
||||||
/* Copied from Linux version and changed the features according Android, which
|
|
||||||
* is close to Linux */
|
|
||||||
|
|
||||||
/* Define if clock_gettime is available in libc */
|
|
||||||
#define DNS_USE_CPU_CLOCK_FOR_ID 1
|
|
||||||
|
|
||||||
/* Define is no secure id variant is available */
|
|
||||||
/* #undef DNS_USE_GETTIMEOFDAY_FOR_ID */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `clock_gettime' function. */
|
|
||||||
#define HAVE_CLOCK_GETTIME 1
|
|
||||||
|
|
||||||
/* Define if /dev/poll is available */
|
|
||||||
/* #undef HAVE_DEVPOLL */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#define HAVE_DLFCN_H 1
|
|
||||||
|
|
||||||
/* Define if your system supports the epoll system calls */
|
|
||||||
#define HAVE_EPOLL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
|
||||||
#define HAVE_EPOLL_CTL 1
|
|
||||||
|
|
||||||
/* Define if your system supports event ports */
|
|
||||||
/* #undef HAVE_EVENT_PORTS */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `fcntl' function. */
|
|
||||||
#define HAVE_FCNTL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
|
||||||
#define HAVE_FCNTL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `fd_mask'. */
|
|
||||||
/* #undef HAVE_FD_MASK */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
|
||||||
#define HAVE_GETADDRINFO 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `getegid' function. */
|
|
||||||
#define HAVE_GETEGID 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `geteuid' function. */
|
|
||||||
#define HAVE_GETEUID 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `getnameinfo' function. */
|
|
||||||
#define HAVE_GETNAMEINFO 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `gettimeofday' function. */
|
|
||||||
#define HAVE_GETTIMEOFDAY 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `inet_ntop' function. */
|
|
||||||
#define HAVE_INET_NTOP 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#define HAVE_INTTYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `issetugid' function. */
|
|
||||||
/* #undef HAVE_ISSETUGID */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `kqueue' function. */
|
|
||||||
/* #undef HAVE_KQUEUE */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `nsl' library (-lnsl). */
|
|
||||||
#define HAVE_LIBNSL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `resolv' library (-lresolv). */
|
|
||||||
#define HAVE_LIBRESOLV 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `rt' library (-lrt). */
|
|
||||||
#define HAVE_LIBRT 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
|
||||||
/* #undef HAVE_LIBSOCKET */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#define HAVE_MEMORY_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <netinet/in6.h> header file. */
|
|
||||||
/* #undef HAVE_NETINET_IN6_H */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `poll' function. */
|
|
||||||
#define HAVE_POLL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <poll.h> header file. */
|
|
||||||
#define HAVE_POLL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `port_create' function. */
|
|
||||||
/* #undef HAVE_PORT_CREATE */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <port.h> header file. */
|
|
||||||
/* #undef HAVE_PORT_H */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `select' function. */
|
|
||||||
#define HAVE_SELECT 1
|
|
||||||
|
|
||||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
|
||||||
#define HAVE_SETFD 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `sigaction' function. */
|
|
||||||
#define HAVE_SIGACTION 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `signal' function. */
|
|
||||||
#define HAVE_SIGNAL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <signal.h> header file. */
|
|
||||||
#define HAVE_SIGNAL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
|
||||||
#define HAVE_STDARG_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#define HAVE_STDINT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#define HAVE_STDLIB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#define HAVE_STRINGS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strlcpy' function. */
|
|
||||||
#define HAVE_STRLCPY 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strsep' function. */
|
|
||||||
#define HAVE_STRSEP 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtok_r' function. */
|
|
||||||
#define HAVE_STRTOK_R 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoll' function. */
|
|
||||||
#define HAVE_STRTOLL 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct in6_addr'. */
|
|
||||||
#define HAVE_STRUCT_IN6_ADDR 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/devpoll.h> header file. */
|
|
||||||
/* #undef HAVE_SYS_DEVPOLL_H */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
|
||||||
#define HAVE_SYS_EPOLL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
|
||||||
/* #undef HAVE_SYS_EVENT_H */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
|
||||||
#define HAVE_SYS_IOCTL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
|
||||||
#define HAVE_SYS_PARAM_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
|
||||||
#define HAVE_SYS_QUEUE_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
|
||||||
#define HAVE_SYS_SELECT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
|
||||||
#define HAVE_SYS_SOCKET_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#define HAVE_SYS_STAT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
|
||||||
#define HAVE_SYS_TIME_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
|
||||||
#define HAVE_TAILQFOREACH 1
|
|
||||||
|
|
||||||
/* Define if timeradd is defined in <sys/time.h> */
|
|
||||||
#define HAVE_TIMERADD 1
|
|
||||||
|
|
||||||
/* Define if timerclear is defined in <sys/time.h> */
|
|
||||||
#define HAVE_TIMERCLEAR 1
|
|
||||||
|
|
||||||
/* Define if timercmp is defined in <sys/time.h> */
|
|
||||||
#define HAVE_TIMERCMP 1
|
|
||||||
|
|
||||||
/* Define if timerisset is defined in <sys/time.h> */
|
|
||||||
#define HAVE_TIMERISSET 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint16_t'. */
|
|
||||||
#define HAVE_UINT16_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint32_t'. */
|
|
||||||
#define HAVE_UINT32_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint64_t'. */
|
|
||||||
#define HAVE_UINT64_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint8_t'. */
|
|
||||||
#define HAVE_UINT8_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#define HAVE_UNISTD_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `vasprintf' function. */
|
|
||||||
#define HAVE_VASPRINTF 1
|
|
||||||
|
|
||||||
/* Define if kqueue works correctly with pipes */
|
|
||||||
/* #undef HAVE_WORKING_KQUEUE */
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#define PACKAGE "libevent"
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#define PACKAGE_BUGREPORT ""
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#define PACKAGE_NAME ""
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#define PACKAGE_STRING ""
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#define PACKAGE_TARNAME ""
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#define PACKAGE_VERSION ""
|
|
||||||
|
|
||||||
/* The size of `int', as computed by sizeof. */
|
|
||||||
#define SIZEOF_INT 4
|
|
||||||
|
|
||||||
/* The size of `long', as computed by sizeof. */
|
|
||||||
#define SIZEOF_LONG 8
|
|
||||||
|
|
||||||
/* The size of `long long', as computed by sizeof. */
|
|
||||||
#define SIZEOF_LONG_LONG 8
|
|
||||||
|
|
||||||
/* The size of `short', as computed by sizeof. */
|
|
||||||
#define SIZEOF_SHORT 2
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
|
||||||
#define TIME_WITH_SYS_TIME 1
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#define VERSION "1.4.13-stable"
|
|
||||||
|
|
||||||
/* Define to appropriate substitue if compiler doesnt have __func__ */
|
|
||||||
/* #undef __func__ */
|
|
||||||
|
|
||||||
/* Define to empty if `const' does not conform to ANSI C. */
|
|
||||||
/* #undef const */
|
|
||||||
|
|
||||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
|
||||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
|
||||||
#ifndef __cplusplus
|
|
||||||
/* #undef inline */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define to `int' if <sys/types.h> does not define. */
|
|
||||||
/* #undef pid_t */
|
|
||||||
|
|
||||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
|
||||||
/* #undef size_t */
|
|
||||||
|
|
||||||
/* Define to unsigned int if you dont have it */
|
|
||||||
/* #undef socklen_t */
|
|
|
@ -1,271 +0,0 @@
|
||||||
/* Copied from Linux version and changed the features according Android, which
|
|
||||||
* is close to Linux */
|
|
||||||
#ifndef _EVENT_CONFIG_H_
|
|
||||||
#define _EVENT_CONFIG_H_
|
|
||||||
/* config.h. Generated from config.h.in by configure. */
|
|
||||||
/* config.h.in. Generated from configure.in by autoheader. */
|
|
||||||
|
|
||||||
/* Define if clock_gettime is available in libc */
|
|
||||||
#define _EVENT_DNS_USE_CPU_CLOCK_FOR_ID 1
|
|
||||||
|
|
||||||
/* Define is no secure id variant is available */
|
|
||||||
/* #undef _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `clock_gettime' function. */
|
|
||||||
#define _EVENT_HAVE_CLOCK_GETTIME 1
|
|
||||||
|
|
||||||
/* Define if /dev/poll is available */
|
|
||||||
/* #undef _EVENT_HAVE_DEVPOLL */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#define _EVENT_HAVE_DLFCN_H 1
|
|
||||||
|
|
||||||
/* Define if your system supports the epoll system calls */
|
|
||||||
#define _EVENT_HAVE_EPOLL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
|
||||||
#define _EVENT_HAVE_EPOLL_CTL 1
|
|
||||||
|
|
||||||
/* Define if your system supports event ports */
|
|
||||||
/* #undef _EVENT_HAVE_EVENT_PORTS */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `fcntl' function. */
|
|
||||||
#define _EVENT_HAVE_FCNTL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
|
||||||
#define _EVENT_HAVE_FCNTL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `fd_mask'. */
|
|
||||||
/* #undef _EVENT_HAVE_FD_MASK 1 */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
|
||||||
#define _EVENT_HAVE_GETADDRINFO 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `getegid' function. */
|
|
||||||
#define _EVENT_HAVE_GETEGID 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `geteuid' function. */
|
|
||||||
#define _EVENT_HAVE_GETEUID 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `getnameinfo' function. */
|
|
||||||
#define _EVENT_HAVE_GETNAMEINFO 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `gettimeofday' function. */
|
|
||||||
#define _EVENT_HAVE_GETTIMEOFDAY 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `inet_ntop' function. */
|
|
||||||
#define _EVENT_HAVE_INET_NTOP 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#define _EVENT_HAVE_INTTYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `issetugid' function. */
|
|
||||||
/* #undef _EVENT_HAVE_ISSETUGID */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `kqueue' function. */
|
|
||||||
/* #undef _EVENT_HAVE_KQUEUE */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `nsl' library (-lnsl). */
|
|
||||||
#define _EVENT_HAVE_LIBNSL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `resolv' library (-lresolv). */
|
|
||||||
#define _EVENT_HAVE_LIBRESOLV 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `rt' library (-lrt). */
|
|
||||||
#define _EVENT_HAVE_LIBRT 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
|
||||||
/* #undef _EVENT_HAVE_LIBSOCKET */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#define _EVENT_HAVE_MEMORY_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <netinet/in6.h> header file. */
|
|
||||||
/* #undef _EVENT_HAVE_NETINET_IN6_H */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `poll' function. */
|
|
||||||
#define _EVENT_HAVE_POLL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <poll.h> header file. */
|
|
||||||
#define _EVENT_HAVE_POLL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `port_create' function. */
|
|
||||||
/* #undef _EVENT_HAVE_PORT_CREATE */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <port.h> header file. */
|
|
||||||
/* #undef _EVENT_HAVE_PORT_H */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `select' function. */
|
|
||||||
#define _EVENT_HAVE_SELECT 1
|
|
||||||
|
|
||||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
|
||||||
#define _EVENT_HAVE_SETFD 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `sigaction' function. */
|
|
||||||
#define _EVENT_HAVE_SIGACTION 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `signal' function. */
|
|
||||||
#define _EVENT_HAVE_SIGNAL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <signal.h> header file. */
|
|
||||||
#define _EVENT_HAVE_SIGNAL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
|
||||||
#define _EVENT_HAVE_STDARG_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#define _EVENT_HAVE_STDINT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#define _EVENT_HAVE_STDLIB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#define _EVENT_HAVE_STRINGS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define _EVENT_HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strlcpy' function. */
|
|
||||||
#define _EVENT_HAVE_STRLCPY 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strsep' function. */
|
|
||||||
#define _EVENT_HAVE_STRSEP 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtok_r' function. */
|
|
||||||
#define _EVENT_HAVE_STRTOK_R 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoll' function. */
|
|
||||||
#define _EVENT_HAVE_STRTOLL 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct in6_addr'. */
|
|
||||||
#define _EVENT_HAVE_STRUCT_IN6_ADDR 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/devpoll.h> header file. */
|
|
||||||
/* #undef _EVENT_HAVE_SYS_DEVPOLL_H */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
|
||||||
#define _EVENT_HAVE_SYS_EPOLL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
|
||||||
/* #undef _EVENT_HAVE_SYS_EVENT_H */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
|
||||||
#define _EVENT_HAVE_SYS_IOCTL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
|
||||||
#define _EVENT_HAVE_SYS_PARAM_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
|
||||||
#define _EVENT_HAVE_SYS_QUEUE_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
|
||||||
#define _EVENT_HAVE_SYS_SELECT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
|
||||||
#define _EVENT_HAVE_SYS_SOCKET_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#define _EVENT_HAVE_SYS_STAT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
|
||||||
#define _EVENT_HAVE_SYS_TIME_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define _EVENT_HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
|
||||||
#define _EVENT_HAVE_TAILQFOREACH 1
|
|
||||||
|
|
||||||
/* Define if timeradd is defined in <sys/time.h> */
|
|
||||||
#define _EVENT_HAVE_TIMERADD 1
|
|
||||||
|
|
||||||
/* Define if timerclear is defined in <sys/time.h> */
|
|
||||||
#define _EVENT_HAVE_TIMERCLEAR 1
|
|
||||||
|
|
||||||
/* Define if timercmp is defined in <sys/time.h> */
|
|
||||||
#define _EVENT_HAVE_TIMERCMP 1
|
|
||||||
|
|
||||||
/* Define if timerisset is defined in <sys/time.h> */
|
|
||||||
#define _EVENT_HAVE_TIMERISSET 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint16_t'. */
|
|
||||||
#define _EVENT_HAVE_UINT16_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint32_t'. */
|
|
||||||
#define _EVENT_HAVE_UINT32_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint64_t'. */
|
|
||||||
#define _EVENT_HAVE_UINT64_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint8_t'. */
|
|
||||||
#define _EVENT_HAVE_UINT8_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#define _EVENT_HAVE_UNISTD_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `vasprintf' function. */
|
|
||||||
#define _EVENT_HAVE_VASPRINTF 1
|
|
||||||
|
|
||||||
/* Define if kqueue works correctly with pipes */
|
|
||||||
/* #undef _EVENT_HAVE_WORKING_KQUEUE */
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#define _EVENT_PACKAGE "libevent"
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#define _EVENT_PACKAGE_BUGREPORT ""
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#define _EVENT_PACKAGE_NAME ""
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#define _EVENT_PACKAGE_STRING ""
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#define _EVENT_PACKAGE_TARNAME ""
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#define _EVENT_PACKAGE_VERSION ""
|
|
||||||
|
|
||||||
/* The size of `int', as computed by sizeof. */
|
|
||||||
#define _EVENT_SIZEOF_INT 4
|
|
||||||
|
|
||||||
/* The size of `long', as computed by sizeof. */
|
|
||||||
#define _EVENT_SIZEOF_LONG 8
|
|
||||||
|
|
||||||
/* The size of `long long', as computed by sizeof. */
|
|
||||||
#define _EVENT_SIZEOF_LONG_LONG 8
|
|
||||||
|
|
||||||
/* The size of `short', as computed by sizeof. */
|
|
||||||
#define _EVENT_SIZEOF_SHORT 2
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define _EVENT_STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
|
||||||
#define _EVENT_TIME_WITH_SYS_TIME 1
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#define _EVENT_VERSION "1.4.13-stable"
|
|
||||||
|
|
||||||
/* Define to appropriate substitue if compiler doesnt have __func__ */
|
|
||||||
/* #undef _EVENT___func__ */
|
|
||||||
|
|
||||||
/* Define to empty if `const' does not conform to ANSI C. */
|
|
||||||
/* #undef _EVENT_const */
|
|
||||||
|
|
||||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
|
||||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
|
||||||
#ifndef _EVENT___cplusplus
|
|
||||||
/* #undef _EVENT_inline */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define to `int' if <sys/types.h> does not define. */
|
|
||||||
/* #undef _EVENT_pid_t */
|
|
||||||
|
|
||||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
|
||||||
/* #undef _EVENT_size_t */
|
|
||||||
|
|
||||||
/* Define to unsigned int if you dont have it */
|
|
||||||
/* #undef _EVENT_socklen_t */
|
|
||||||
#endif
|
|
|
@ -1,11 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
LIBTOOLIZE=libtoolize
|
|
||||||
SYSNAME=`uname`
|
|
||||||
if [ "x$SYSNAME" = "xDarwin" ] ; then
|
|
||||||
LIBTOOLIZE=glibtoolize
|
|
||||||
fi
|
|
||||||
aclocal && \
|
|
||||||
autoheader && \
|
|
||||||
$LIBTOOLIZE && \
|
|
||||||
autoconf && \
|
|
||||||
automake --add-missing --copy
|
|
|
@ -1,450 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <winsock2.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_VASPRINTF
|
|
||||||
/* If we have vasprintf, we need to define this before we include stdio.h. */
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_TIME_H
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_IOCTL_H
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#ifdef HAVE_STDARG_H
|
|
||||||
#include <stdarg.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "event.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "evutil.h"
|
|
||||||
|
|
||||||
struct evbuffer *
|
|
||||||
evbuffer_new(void)
|
|
||||||
{
|
|
||||||
struct evbuffer *buffer;
|
|
||||||
|
|
||||||
buffer = calloc(1, sizeof(struct evbuffer));
|
|
||||||
|
|
||||||
return (buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
evbuffer_free(struct evbuffer *buffer)
|
|
||||||
{
|
|
||||||
if (buffer->orig_buffer != NULL)
|
|
||||||
free(buffer->orig_buffer);
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is a destructive add. The data from one buffer moves into
|
|
||||||
* the other buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SWAP(x,y) do { \
|
|
||||||
(x)->buffer = (y)->buffer; \
|
|
||||||
(x)->orig_buffer = (y)->orig_buffer; \
|
|
||||||
(x)->misalign = (y)->misalign; \
|
|
||||||
(x)->totallen = (y)->totallen; \
|
|
||||||
(x)->off = (y)->off; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
int
|
|
||||||
evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
|
|
||||||
/* Short cut for better performance */
|
|
||||||
if (outbuf->off == 0) {
|
|
||||||
struct evbuffer tmp;
|
|
||||||
size_t oldoff = inbuf->off;
|
|
||||||
|
|
||||||
/* Swap them directly */
|
|
||||||
SWAP(&tmp, outbuf);
|
|
||||||
SWAP(outbuf, inbuf);
|
|
||||||
SWAP(inbuf, &tmp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Optimization comes with a price; we need to notify the
|
|
||||||
* buffer if necessary of the changes. oldoff is the amount
|
|
||||||
* of data that we transfered from inbuf to outbuf
|
|
||||||
*/
|
|
||||||
if (inbuf->off != oldoff && inbuf->cb != NULL)
|
|
||||||
(*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
|
|
||||||
if (oldoff && outbuf->cb != NULL)
|
|
||||||
(*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
|
|
||||||
if (res == 0) {
|
|
||||||
/* We drain the input buffer on success */
|
|
||||||
evbuffer_drain(inbuf, inbuf->off);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (res);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
size_t space;
|
|
||||||
size_t oldoff = buf->off;
|
|
||||||
int sz;
|
|
||||||
va_list aq;
|
|
||||||
|
|
||||||
/* make sure that at least some space is available */
|
|
||||||
evbuffer_expand(buf, 64);
|
|
||||||
for (;;) {
|
|
||||||
size_t used = buf->misalign + buf->off;
|
|
||||||
buffer = (char *)buf->buffer + buf->off;
|
|
||||||
assert(buf->totallen >= used);
|
|
||||||
space = buf->totallen - used;
|
|
||||||
|
|
||||||
#ifndef va_copy
|
|
||||||
#define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list))
|
|
||||||
#endif
|
|
||||||
va_copy(aq, ap);
|
|
||||||
|
|
||||||
sz = evutil_vsnprintf(buffer, space, fmt, aq);
|
|
||||||
|
|
||||||
va_end(aq);
|
|
||||||
|
|
||||||
if (sz < 0)
|
|
||||||
return (-1);
|
|
||||||
if ((size_t)sz < space) {
|
|
||||||
buf->off += sz;
|
|
||||||
if (buf->cb != NULL)
|
|
||||||
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
|
|
||||||
return (sz);
|
|
||||||
}
|
|
||||||
if (evbuffer_expand(buf, sz + 1) == -1)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
}
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
int res = -1;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
res = evbuffer_add_vprintf(buf, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
return (res);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reads data from an event buffer and drains the bytes read */
|
|
||||||
|
|
||||||
int
|
|
||||||
evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
|
|
||||||
{
|
|
||||||
size_t nread = datlen;
|
|
||||||
if (nread >= buf->off)
|
|
||||||
nread = buf->off;
|
|
||||||
|
|
||||||
memcpy(data, buf->buffer, nread);
|
|
||||||
evbuffer_drain(buf, nread);
|
|
||||||
|
|
||||||
return (nread);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'.
|
|
||||||
* The returned buffer needs to be freed by the called.
|
|
||||||
*/
|
|
||||||
|
|
||||||
char *
|
|
||||||
evbuffer_readline(struct evbuffer *buffer)
|
|
||||||
{
|
|
||||||
u_char *data = EVBUFFER_DATA(buffer);
|
|
||||||
size_t len = EVBUFFER_LENGTH(buffer);
|
|
||||||
char *line;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
if (data[i] == '\r' || data[i] == '\n')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == len)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
if ((line = malloc(i + 1)) == NULL) {
|
|
||||||
fprintf(stderr, "%s: out of memory\n", __func__);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(line, data, i);
|
|
||||||
line[i] = '\0';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Some protocols terminate a line with '\r\n', so check for
|
|
||||||
* that, too.
|
|
||||||
*/
|
|
||||||
if ( i < len - 1 ) {
|
|
||||||
char fch = data[i], sch = data[i+1];
|
|
||||||
|
|
||||||
/* Drain one more character if needed */
|
|
||||||
if ( (sch == '\r' || sch == '\n') && sch != fch )
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
evbuffer_drain(buffer, i + 1);
|
|
||||||
|
|
||||||
return (line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adds data to an event buffer */
|
|
||||||
|
|
||||||
static void
|
|
||||||
evbuffer_align(struct evbuffer *buf)
|
|
||||||
{
|
|
||||||
memmove(buf->orig_buffer, buf->buffer, buf->off);
|
|
||||||
buf->buffer = buf->orig_buffer;
|
|
||||||
buf->misalign = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expands the available space in the event buffer to at least datlen */
|
|
||||||
|
|
||||||
int
|
|
||||||
evbuffer_expand(struct evbuffer *buf, size_t datlen)
|
|
||||||
{
|
|
||||||
size_t need = buf->misalign + buf->off + datlen;
|
|
||||||
|
|
||||||
/* If we can fit all the data, then we don't have to do anything */
|
|
||||||
if (buf->totallen >= need)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the misalignment fulfills our data needs, we just force an
|
|
||||||
* alignment to happen. Afterwards, we have enough space.
|
|
||||||
*/
|
|
||||||
if (buf->misalign >= datlen) {
|
|
||||||
evbuffer_align(buf);
|
|
||||||
} else {
|
|
||||||
void *newbuf;
|
|
||||||
size_t length = buf->totallen;
|
|
||||||
|
|
||||||
if (length < 256)
|
|
||||||
length = 256;
|
|
||||||
while (length < need)
|
|
||||||
length <<= 1;
|
|
||||||
|
|
||||||
if (buf->orig_buffer != buf->buffer)
|
|
||||||
evbuffer_align(buf);
|
|
||||||
if ((newbuf = realloc(buf->buffer, length)) == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
buf->orig_buffer = buf->buffer = newbuf;
|
|
||||||
buf->totallen = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen)
|
|
||||||
{
|
|
||||||
size_t need = buf->misalign + buf->off + datlen;
|
|
||||||
size_t oldoff = buf->off;
|
|
||||||
|
|
||||||
if (buf->totallen < need) {
|
|
||||||
if (evbuffer_expand(buf, datlen) == -1)
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buf->buffer + buf->off, data, datlen);
|
|
||||||
buf->off += datlen;
|
|
||||||
|
|
||||||
if (datlen && buf->cb != NULL)
|
|
||||||
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
evbuffer_drain(struct evbuffer *buf, size_t len)
|
|
||||||
{
|
|
||||||
size_t oldoff = buf->off;
|
|
||||||
|
|
||||||
if (len >= buf->off) {
|
|
||||||
buf->off = 0;
|
|
||||||
buf->buffer = buf->orig_buffer;
|
|
||||||
buf->misalign = 0;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf->buffer += len;
|
|
||||||
buf->misalign += len;
|
|
||||||
|
|
||||||
buf->off -= len;
|
|
||||||
|
|
||||||
done:
|
|
||||||
/* Tell someone about changes in this buffer */
|
|
||||||
if (buf->off != oldoff && buf->cb != NULL)
|
|
||||||
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reads data from a file descriptor into a buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define EVBUFFER_MAX_READ 4096
|
|
||||||
|
|
||||||
int
|
|
||||||
evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
|
|
||||||
{
|
|
||||||
u_char *p;
|
|
||||||
size_t oldoff = buf->off;
|
|
||||||
int n = EVBUFFER_MAX_READ;
|
|
||||||
|
|
||||||
#if defined(FIONREAD)
|
|
||||||
#ifdef WIN32
|
|
||||||
long lng = n;
|
|
||||||
if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) <= 0) {
|
|
||||||
#else
|
|
||||||
if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) {
|
|
||||||
#endif
|
|
||||||
n = EVBUFFER_MAX_READ;
|
|
||||||
} else if (n > EVBUFFER_MAX_READ && n > howmuch) {
|
|
||||||
/*
|
|
||||||
* It's possible that a lot of data is available for
|
|
||||||
* reading. We do not want to exhaust resources
|
|
||||||
* before the reader has a chance to do something
|
|
||||||
* about it. If the reader does not tell us how much
|
|
||||||
* data we should read, we artifically limit it.
|
|
||||||
*/
|
|
||||||
if ((size_t)n > buf->totallen << 2)
|
|
||||||
n = buf->totallen << 2;
|
|
||||||
if (n < EVBUFFER_MAX_READ)
|
|
||||||
n = EVBUFFER_MAX_READ;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (howmuch < 0 || howmuch > n)
|
|
||||||
howmuch = n;
|
|
||||||
|
|
||||||
/* If we don't have FIONREAD, we might waste some space here */
|
|
||||||
if (evbuffer_expand(buf, howmuch) == -1)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
/* We can append new data at this point */
|
|
||||||
p = buf->buffer + buf->off;
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
n = read(fd, p, howmuch);
|
|
||||||
#else
|
|
||||||
n = recv(fd, p, howmuch, 0);
|
|
||||||
#endif
|
|
||||||
if (n == -1)
|
|
||||||
return (-1);
|
|
||||||
if (n == 0)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
buf->off += n;
|
|
||||||
|
|
||||||
/* Tell someone about changes in this buffer */
|
|
||||||
if (buf->off != oldoff && buf->cb != NULL)
|
|
||||||
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
|
|
||||||
|
|
||||||
return (n);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
evbuffer_write(struct evbuffer *buffer, int fd)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
n = write(fd, buffer->buffer, buffer->off);
|
|
||||||
#else
|
|
||||||
n = send(fd, buffer->buffer, buffer->off, 0);
|
|
||||||
#endif
|
|
||||||
if (n == -1)
|
|
||||||
return (-1);
|
|
||||||
if (n == 0)
|
|
||||||
return (0);
|
|
||||||
evbuffer_drain(buffer, n);
|
|
||||||
|
|
||||||
return (n);
|
|
||||||
}
|
|
||||||
|
|
||||||
u_char *
|
|
||||||
evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len)
|
|
||||||
{
|
|
||||||
u_char *search = buffer->buffer, *end = search + buffer->off;
|
|
||||||
u_char *p;
|
|
||||||
|
|
||||||
while (search < end &&
|
|
||||||
(p = memchr(search, *what, end - search)) != NULL) {
|
|
||||||
if (p + len > end)
|
|
||||||
break;
|
|
||||||
if (memcmp(p, what, len) == 0)
|
|
||||||
return (p);
|
|
||||||
search = p + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void evbuffer_setcb(struct evbuffer *buffer,
|
|
||||||
void (*cb)(struct evbuffer *, size_t, size_t, void *),
|
|
||||||
void *cbarg)
|
|
||||||
{
|
|
||||||
buffer->cb = cb;
|
|
||||||
buffer->cbarg = cbarg;
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
diff --git a/third_party/libevent/evdns.c b/third_party/libevent/evdns.c
|
|
||||||
index f07ecc9..da6ea19 100644
|
|
||||||
--- a/third_party/libevent/evdns.c
|
|
||||||
+++ b/third_party/libevent/evdns.c
|
|
||||||
@@ -134,7 +134,7 @@
|
|
||||||
typedef ev_uint8_t u_char;
|
|
||||||
typedef unsigned int uint;
|
|
||||||
#endif
|
|
||||||
-#include <event.h>
|
|
||||||
+#include "event.h"
|
|
||||||
|
|
||||||
#define u64 ev_uint64_t
|
|
||||||
#define u32 ev_uint32_t
|
|
||||||
diff --git a/third_party/libevent/evdns.h b/third_party/libevent/evdns.h
|
|
||||||
index 1eb5c38..fca4ac3 100644
|
|
||||||
--- a/third_party/libevent/evdns.h
|
|
||||||
+++ b/third_party/libevent/evdns.h
|
|
||||||
@@ -165,7 +165,7 @@ extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* For integer types. */
|
|
||||||
-#include <evutil.h>
|
|
||||||
+#include "evutil.h"
|
|
||||||
|
|
||||||
/** Error codes 0-5 are as described in RFC 1035. */
|
|
||||||
#define DNS_ERR_NONE 0
|
|
||||||
diff --git a/third_party/libevent/event-config.h b/third_party/libevent/event-config.h
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..78a4727
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/third_party/libevent/event-config.h
|
|
||||||
@@ -0,0 +1,16 @@
|
|
||||||
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
|
||||||
+// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
+// found in the LICENSE file.
|
|
||||||
+
|
|
||||||
+// This file is Chromium-specific, and brings in the appropriate
|
|
||||||
+// event-config.h depending on your platform.
|
|
||||||
+
|
|
||||||
+#if defined(__APPLE__)
|
|
||||||
+#include "mac/event-config.h"
|
|
||||||
+#elif defined(__linux__)
|
|
||||||
+#include "linux/event-config.h"
|
|
||||||
+#elif defined(__FreeBSD__)
|
|
||||||
+#include "freebsd/event-config.h"
|
|
||||||
+#else
|
|
||||||
+#error generate event-config.h for your platform
|
|
||||||
+#endif
|
|
||||||
diff --git a/third_party/libevent/event.h b/third_party/libevent/event.h
|
|
||||||
index cfa0fc3..72e9b8b 100644
|
|
||||||
--- a/third_party/libevent/event.h
|
|
||||||
+++ b/third_party/libevent/event.h
|
|
||||||
@@ -159,7 +159,7 @@
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-#include <event-config.h>
|
|
||||||
+#include "event-config.h"
|
|
||||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
@@ -172,7 +172,7 @@ extern "C" {
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
/* For int types. */
|
|
||||||
-#include <evutil.h>
|
|
||||||
+#include "evutil.h"
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
diff --git a/third_party/libevent/evutil.h b/third_party/libevent/evutil.h
|
|
||||||
index dcb0013..8b664b9 100644
|
|
||||||
--- a/third_party/libevent/evutil.h
|
|
||||||
+++ b/third_party/libevent/evutil.h
|
|
||||||
@@ -38,7 +38,7 @@
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-#include <event-config.h>
|
|
||||||
+#include "event-config.h"
|
|
||||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
|
@ -1,163 +0,0 @@
|
||||||
/* $OpenBSD: time.h,v 1.11 2000/10/10 13:36:48 itojun Exp $ */
|
|
||||||
/* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1982, 1986, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)time.h 8.2 (Berkeley) 7/10/94
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SYS_TIME_H_
|
|
||||||
#define _SYS_TIME_H_
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Structure returned by gettimeofday(2) system call,
|
|
||||||
* and used in other calls.
|
|
||||||
*/
|
|
||||||
struct timeval {
|
|
||||||
long tv_sec; /* seconds */
|
|
||||||
long tv_usec; /* and microseconds */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Structure defined by POSIX.1b to be like a timeval.
|
|
||||||
*/
|
|
||||||
struct timespec {
|
|
||||||
time_t tv_sec; /* seconds */
|
|
||||||
long tv_nsec; /* and nanoseconds */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TIMEVAL_TO_TIMESPEC(tv, ts) { \
|
|
||||||
(ts)->tv_sec = (tv)->tv_sec; \
|
|
||||||
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
|
|
||||||
}
|
|
||||||
#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
|
|
||||||
(tv)->tv_sec = (ts)->tv_sec; \
|
|
||||||
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
|
|
||||||
}
|
|
||||||
|
|
||||||
struct timezone {
|
|
||||||
int tz_minuteswest; /* minutes west of Greenwich */
|
|
||||||
int tz_dsttime; /* type of dst correction */
|
|
||||||
};
|
|
||||||
#define DST_NONE 0 /* not on dst */
|
|
||||||
#define DST_USA 1 /* USA style dst */
|
|
||||||
#define DST_AUST 2 /* Australian style dst */
|
|
||||||
#define DST_WET 3 /* Western European dst */
|
|
||||||
#define DST_MET 4 /* Middle European dst */
|
|
||||||
#define DST_EET 5 /* Eastern European dst */
|
|
||||||
#define DST_CAN 6 /* Canada */
|
|
||||||
|
|
||||||
/* Operations on timevals. */
|
|
||||||
#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
|
|
||||||
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
|
|
||||||
#define timercmp(tvp, uvp, cmp) \
|
|
||||||
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
|
|
||||||
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
|
|
||||||
((tvp)->tv_sec cmp (uvp)->tv_sec))
|
|
||||||
#define timeradd(tvp, uvp, vvp) \
|
|
||||||
do { \
|
|
||||||
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
|
|
||||||
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
|
|
||||||
if ((vvp)->tv_usec >= 1000000) { \
|
|
||||||
(vvp)->tv_sec++; \
|
|
||||||
(vvp)->tv_usec -= 1000000; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#define timersub(tvp, uvp, vvp) \
|
|
||||||
do { \
|
|
||||||
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
|
|
||||||
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
|
|
||||||
if ((vvp)->tv_usec < 0) { \
|
|
||||||
(vvp)->tv_sec--; \
|
|
||||||
(vvp)->tv_usec += 1000000; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Operations on timespecs. */
|
|
||||||
#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0
|
|
||||||
#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec)
|
|
||||||
#define timespeccmp(tsp, usp, cmp) \
|
|
||||||
(((tsp)->tv_sec == (usp)->tv_sec) ? \
|
|
||||||
((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
|
|
||||||
((tsp)->tv_sec cmp (usp)->tv_sec))
|
|
||||||
#define timespecadd(tsp, usp, vsp) \
|
|
||||||
do { \
|
|
||||||
(vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \
|
|
||||||
(vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \
|
|
||||||
if ((vsp)->tv_nsec >= 1000000000L) { \
|
|
||||||
(vsp)->tv_sec++; \
|
|
||||||
(vsp)->tv_nsec -= 1000000000L; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#define timespecsub(tsp, usp, vsp) \
|
|
||||||
do { \
|
|
||||||
(vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
|
|
||||||
(vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
|
|
||||||
if ((vsp)->tv_nsec < 0) { \
|
|
||||||
(vsp)->tv_sec--; \
|
|
||||||
(vsp)->tv_nsec += 1000000000L; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Names of the interval timers, and structure
|
|
||||||
* defining a timer setting.
|
|
||||||
*/
|
|
||||||
#define ITIMER_REAL 0
|
|
||||||
#define ITIMER_VIRTUAL 1
|
|
||||||
#define ITIMER_PROF 2
|
|
||||||
|
|
||||||
struct itimerval {
|
|
||||||
struct timeval it_interval; /* timer interval */
|
|
||||||
struct timeval it_value; /* current value */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Getkerninfo clock information structure
|
|
||||||
*/
|
|
||||||
struct clockinfo {
|
|
||||||
int hz; /* clock frequency */
|
|
||||||
int tick; /* micro-seconds per hz tick */
|
|
||||||
int tickadj; /* clock skew rate for adjtime() */
|
|
||||||
int stathz; /* statistics clock frequency */
|
|
||||||
int profhz; /* profiling clock frequency */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CLOCK_REALTIME 0
|
|
||||||
#define CLOCK_VIRTUAL 1
|
|
||||||
#define CLOCK_PROF 2
|
|
||||||
|
|
||||||
#define TIMER_RELTIME 0x0 /* relative timer */
|
|
||||||
#define TIMER_ABSTIME 0x1 /* absolute timer */
|
|
||||||
|
|
||||||
/* --- stuff got cut here - niels --- */
|
|
||||||
|
|
||||||
#endif /* !_SYS_TIME_H_ */
|
|
|
@ -1,163 +0,0 @@
|
||||||
/* $OpenBSD: time.h,v 1.11 2000/10/10 13:36:48 itojun Exp $ */
|
|
||||||
/* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1982, 1986, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)time.h 8.2 (Berkeley) 7/10/94
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SYS_TIME_H_
|
|
||||||
#define _SYS_TIME_H_
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Structure returned by gettimeofday(2) system call,
|
|
||||||
* and used in other calls.
|
|
||||||
*/
|
|
||||||
struct timeval {
|
|
||||||
long tv_sec; /* seconds */
|
|
||||||
long tv_usec; /* and microseconds */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Structure defined by POSIX.1b to be like a timeval.
|
|
||||||
*/
|
|
||||||
struct timespec {
|
|
||||||
time_t tv_sec; /* seconds */
|
|
||||||
long tv_nsec; /* and nanoseconds */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TIMEVAL_TO_TIMESPEC(tv, ts) { \
|
|
||||||
(ts)->tv_sec = (tv)->tv_sec; \
|
|
||||||
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
|
|
||||||
}
|
|
||||||
#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
|
|
||||||
(tv)->tv_sec = (ts)->tv_sec; \
|
|
||||||
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
|
|
||||||
}
|
|
||||||
|
|
||||||
struct timezone {
|
|
||||||
int tz_minuteswest; /* minutes west of Greenwich */
|
|
||||||
int tz_dsttime; /* type of dst correction */
|
|
||||||
};
|
|
||||||
#define DST_NONE 0 /* not on dst */
|
|
||||||
#define DST_USA 1 /* USA style dst */
|
|
||||||
#define DST_AUST 2 /* Australian style dst */
|
|
||||||
#define DST_WET 3 /* Western European dst */
|
|
||||||
#define DST_MET 4 /* Middle European dst */
|
|
||||||
#define DST_EET 5 /* Eastern European dst */
|
|
||||||
#define DST_CAN 6 /* Canada */
|
|
||||||
|
|
||||||
/* Operations on timevals. */
|
|
||||||
#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
|
|
||||||
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
|
|
||||||
#define timercmp(tvp, uvp, cmp) \
|
|
||||||
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
|
|
||||||
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
|
|
||||||
((tvp)->tv_sec cmp (uvp)->tv_sec))
|
|
||||||
#define timeradd(tvp, uvp, vvp) \
|
|
||||||
do { \
|
|
||||||
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
|
|
||||||
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
|
|
||||||
if ((vvp)->tv_usec >= 1000000) { \
|
|
||||||
(vvp)->tv_sec++; \
|
|
||||||
(vvp)->tv_usec -= 1000000; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#define timersub(tvp, uvp, vvp) \
|
|
||||||
do { \
|
|
||||||
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
|
|
||||||
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
|
|
||||||
if ((vvp)->tv_usec < 0) { \
|
|
||||||
(vvp)->tv_sec--; \
|
|
||||||
(vvp)->tv_usec += 1000000; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Operations on timespecs. */
|
|
||||||
#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0
|
|
||||||
#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec)
|
|
||||||
#define timespeccmp(tsp, usp, cmp) \
|
|
||||||
(((tsp)->tv_sec == (usp)->tv_sec) ? \
|
|
||||||
((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
|
|
||||||
((tsp)->tv_sec cmp (usp)->tv_sec))
|
|
||||||
#define timespecadd(tsp, usp, vsp) \
|
|
||||||
do { \
|
|
||||||
(vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \
|
|
||||||
(vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \
|
|
||||||
if ((vsp)->tv_nsec >= 1000000000L) { \
|
|
||||||
(vsp)->tv_sec++; \
|
|
||||||
(vsp)->tv_nsec -= 1000000000L; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#define timespecsub(tsp, usp, vsp) \
|
|
||||||
do { \
|
|
||||||
(vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
|
|
||||||
(vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
|
|
||||||
if ((vsp)->tv_nsec < 0) { \
|
|
||||||
(vsp)->tv_sec--; \
|
|
||||||
(vsp)->tv_nsec += 1000000000L; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Names of the interval timers, and structure
|
|
||||||
* defining a timer setting.
|
|
||||||
*/
|
|
||||||
#define ITIMER_REAL 0
|
|
||||||
#define ITIMER_VIRTUAL 1
|
|
||||||
#define ITIMER_PROF 2
|
|
||||||
|
|
||||||
struct itimerval {
|
|
||||||
struct timeval it_interval; /* timer interval */
|
|
||||||
struct timeval it_value; /* current value */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Getkerninfo clock information structure
|
|
||||||
*/
|
|
||||||
struct clockinfo {
|
|
||||||
int hz; /* clock frequency */
|
|
||||||
int tick; /* micro-seconds per hz tick */
|
|
||||||
int tickadj; /* clock skew rate for adjtime() */
|
|
||||||
int stathz; /* statistics clock frequency */
|
|
||||||
int profhz; /* profiling clock frequency */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CLOCK_REALTIME 0
|
|
||||||
#define CLOCK_VIRTUAL 1
|
|
||||||
#define CLOCK_PROF 2
|
|
||||||
|
|
||||||
#define TIMER_RELTIME 0x0 /* relative timer */
|
|
||||||
#define TIMER_ABSTIME 0x1 /* absolute timer */
|
|
||||||
|
|
||||||
/* --- stuff got cut here - niels --- */
|
|
||||||
|
|
||||||
#endif /* !_SYS_TIME_H_ */
|
|
|
@ -1,488 +0,0 @@
|
||||||
/* $OpenBSD: queue.h,v 1.16 2000/09/07 19:47:59 art Exp $ */
|
|
||||||
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SYS_QUEUE_H_
|
|
||||||
#define _SYS_QUEUE_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file defines five types of data structures: singly-linked lists,
|
|
||||||
* lists, simple queues, tail queues, and circular queues.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* A singly-linked list is headed by a single forward pointer. The elements
|
|
||||||
* are singly linked for minimum space and pointer manipulation overhead at
|
|
||||||
* the expense of O(n) removal for arbitrary elements. New elements can be
|
|
||||||
* added to the list after an existing element or at the head of the list.
|
|
||||||
* Elements being removed from the head of the list should use the explicit
|
|
||||||
* macro for this purpose for optimum efficiency. A singly-linked list may
|
|
||||||
* only be traversed in the forward direction. Singly-linked lists are ideal
|
|
||||||
* for applications with large datasets and few or no removals or for
|
|
||||||
* implementing a LIFO queue.
|
|
||||||
*
|
|
||||||
* A list is headed by a single forward pointer (or an array of forward
|
|
||||||
* pointers for a hash table header). The elements are doubly linked
|
|
||||||
* so that an arbitrary element can be removed without a need to
|
|
||||||
* traverse the list. New elements can be added to the list before
|
|
||||||
* or after an existing element or at the head of the list. A list
|
|
||||||
* may only be traversed in the forward direction.
|
|
||||||
*
|
|
||||||
* A simple queue is headed by a pair of pointers, one the head of the
|
|
||||||
* list and the other to the tail of the list. The elements are singly
|
|
||||||
* linked to save space, so elements can only be removed from the
|
|
||||||
* head of the list. New elements can be added to the list before or after
|
|
||||||
* an existing element, at the head of the list, or at the end of the
|
|
||||||
* list. A simple queue may only be traversed in the forward direction.
|
|
||||||
*
|
|
||||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
|
||||||
* list and the other to the tail of the list. The elements are doubly
|
|
||||||
* linked so that an arbitrary element can be removed without a need to
|
|
||||||
* traverse the list. New elements can be added to the list before or
|
|
||||||
* after an existing element, at the head of the list, or at the end of
|
|
||||||
* the list. A tail queue may be traversed in either direction.
|
|
||||||
*
|
|
||||||
* A circle queue is headed by a pair of pointers, one to the head of the
|
|
||||||
* list and the other to the tail of the list. The elements are doubly
|
|
||||||
* linked so that an arbitrary element can be removed without a need to
|
|
||||||
* traverse the list. New elements can be added to the list before or after
|
|
||||||
* an existing element, at the head of the list, or at the end of the list.
|
|
||||||
* A circle queue may be traversed in either direction, but has a more
|
|
||||||
* complex end of list detection.
|
|
||||||
*
|
|
||||||
* For details on the use of these macros, see the queue(3) manual page.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Singly-linked List definitions.
|
|
||||||
*/
|
|
||||||
#define SLIST_HEAD(name, type) \
|
|
||||||
struct name { \
|
|
||||||
struct type *slh_first; /* first element */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SLIST_HEAD_INITIALIZER(head) \
|
|
||||||
{ NULL }
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#define SLIST_ENTRY(type) \
|
|
||||||
struct { \
|
|
||||||
struct type *sle_next; /* next element */ \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Singly-linked List access methods.
|
|
||||||
*/
|
|
||||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
|
||||||
#define SLIST_END(head) NULL
|
|
||||||
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
|
|
||||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
|
||||||
|
|
||||||
#define SLIST_FOREACH(var, head, field) \
|
|
||||||
for((var) = SLIST_FIRST(head); \
|
|
||||||
(var) != SLIST_END(head); \
|
|
||||||
(var) = SLIST_NEXT(var, field))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Singly-linked List functions.
|
|
||||||
*/
|
|
||||||
#define SLIST_INIT(head) { \
|
|
||||||
SLIST_FIRST(head) = SLIST_END(head); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
|
||||||
(elm)->field.sle_next = (slistelm)->field.sle_next; \
|
|
||||||
(slistelm)->field.sle_next = (elm); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
|
||||||
(elm)->field.sle_next = (head)->slh_first; \
|
|
||||||
(head)->slh_first = (elm); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
|
||||||
(head)->slh_first = (head)->slh_first->field.sle_next; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* List definitions.
|
|
||||||
*/
|
|
||||||
#define LIST_HEAD(name, type) \
|
|
||||||
struct name { \
|
|
||||||
struct type *lh_first; /* first element */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LIST_HEAD_INITIALIZER(head) \
|
|
||||||
{ NULL }
|
|
||||||
|
|
||||||
#define LIST_ENTRY(type) \
|
|
||||||
struct { \
|
|
||||||
struct type *le_next; /* next element */ \
|
|
||||||
struct type **le_prev; /* address of previous next element */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* List access methods
|
|
||||||
*/
|
|
||||||
#define LIST_FIRST(head) ((head)->lh_first)
|
|
||||||
#define LIST_END(head) NULL
|
|
||||||
#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
|
|
||||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
|
||||||
|
|
||||||
#define LIST_FOREACH(var, head, field) \
|
|
||||||
for((var) = LIST_FIRST(head); \
|
|
||||||
(var)!= LIST_END(head); \
|
|
||||||
(var) = LIST_NEXT(var, field))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* List functions.
|
|
||||||
*/
|
|
||||||
#define LIST_INIT(head) do { \
|
|
||||||
LIST_FIRST(head) = LIST_END(head); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
|
||||||
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
|
|
||||||
(listelm)->field.le_next->field.le_prev = \
|
|
||||||
&(elm)->field.le_next; \
|
|
||||||
(listelm)->field.le_next = (elm); \
|
|
||||||
(elm)->field.le_prev = &(listelm)->field.le_next; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
|
||||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
|
||||||
(elm)->field.le_next = (listelm); \
|
|
||||||
*(listelm)->field.le_prev = (elm); \
|
|
||||||
(listelm)->field.le_prev = &(elm)->field.le_next; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
|
||||||
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
|
|
||||||
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
|
|
||||||
(head)->lh_first = (elm); \
|
|
||||||
(elm)->field.le_prev = &(head)->lh_first; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define LIST_REMOVE(elm, field) do { \
|
|
||||||
if ((elm)->field.le_next != NULL) \
|
|
||||||
(elm)->field.le_next->field.le_prev = \
|
|
||||||
(elm)->field.le_prev; \
|
|
||||||
*(elm)->field.le_prev = (elm)->field.le_next; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define LIST_REPLACE(elm, elm2, field) do { \
|
|
||||||
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
|
|
||||||
(elm2)->field.le_next->field.le_prev = \
|
|
||||||
&(elm2)->field.le_next; \
|
|
||||||
(elm2)->field.le_prev = (elm)->field.le_prev; \
|
|
||||||
*(elm2)->field.le_prev = (elm2); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Simple queue definitions.
|
|
||||||
*/
|
|
||||||
#define SIMPLEQ_HEAD(name, type) \
|
|
||||||
struct name { \
|
|
||||||
struct type *sqh_first; /* first element */ \
|
|
||||||
struct type **sqh_last; /* addr of last next element */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SIMPLEQ_HEAD_INITIALIZER(head) \
|
|
||||||
{ NULL, &(head).sqh_first }
|
|
||||||
|
|
||||||
#define SIMPLEQ_ENTRY(type) \
|
|
||||||
struct { \
|
|
||||||
struct type *sqe_next; /* next element */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Simple queue access methods.
|
|
||||||
*/
|
|
||||||
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
|
|
||||||
#define SIMPLEQ_END(head) NULL
|
|
||||||
#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
|
|
||||||
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
|
|
||||||
|
|
||||||
#define SIMPLEQ_FOREACH(var, head, field) \
|
|
||||||
for((var) = SIMPLEQ_FIRST(head); \
|
|
||||||
(var) != SIMPLEQ_END(head); \
|
|
||||||
(var) = SIMPLEQ_NEXT(var, field))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Simple queue functions.
|
|
||||||
*/
|
|
||||||
#define SIMPLEQ_INIT(head) do { \
|
|
||||||
(head)->sqh_first = NULL; \
|
|
||||||
(head)->sqh_last = &(head)->sqh_first; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
|
|
||||||
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
|
|
||||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
|
||||||
(head)->sqh_first = (elm); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
|
|
||||||
(elm)->field.sqe_next = NULL; \
|
|
||||||
*(head)->sqh_last = (elm); \
|
|
||||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
|
||||||
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
|
|
||||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
|
||||||
(listelm)->field.sqe_next = (elm); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \
|
|
||||||
if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \
|
|
||||||
(head)->sqh_last = &(head)->sqh_first; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tail queue definitions.
|
|
||||||
*/
|
|
||||||
#define TAILQ_HEAD(name, type) \
|
|
||||||
struct name { \
|
|
||||||
struct type *tqh_first; /* first element */ \
|
|
||||||
struct type **tqh_last; /* addr of last next element */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
|
||||||
{ NULL, &(head).tqh_first }
|
|
||||||
|
|
||||||
#define TAILQ_ENTRY(type) \
|
|
||||||
struct { \
|
|
||||||
struct type *tqe_next; /* next element */ \
|
|
||||||
struct type **tqe_prev; /* address of previous next element */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* tail queue access methods
|
|
||||||
*/
|
|
||||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
|
||||||
#define TAILQ_END(head) NULL
|
|
||||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
|
||||||
#define TAILQ_LAST(head, headname) \
|
|
||||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
|
||||||
/* XXX */
|
|
||||||
#define TAILQ_PREV(elm, headname, field) \
|
|
||||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
|
||||||
#define TAILQ_EMPTY(head) \
|
|
||||||
(TAILQ_FIRST(head) == TAILQ_END(head))
|
|
||||||
|
|
||||||
#define TAILQ_FOREACH(var, head, field) \
|
|
||||||
for((var) = TAILQ_FIRST(head); \
|
|
||||||
(var) != TAILQ_END(head); \
|
|
||||||
(var) = TAILQ_NEXT(var, field))
|
|
||||||
|
|
||||||
#define TAILQ_FOREACH_REVERSE(var, head, field, headname) \
|
|
||||||
for((var) = TAILQ_LAST(head, headname); \
|
|
||||||
(var) != TAILQ_END(head); \
|
|
||||||
(var) = TAILQ_PREV(var, headname, field))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tail queue functions.
|
|
||||||
*/
|
|
||||||
#define TAILQ_INIT(head) do { \
|
|
||||||
(head)->tqh_first = NULL; \
|
|
||||||
(head)->tqh_last = &(head)->tqh_first; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
|
||||||
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
|
|
||||||
(head)->tqh_first->field.tqe_prev = \
|
|
||||||
&(elm)->field.tqe_next; \
|
|
||||||
else \
|
|
||||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
|
||||||
(head)->tqh_first = (elm); \
|
|
||||||
(elm)->field.tqe_prev = &(head)->tqh_first; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
|
||||||
(elm)->field.tqe_next = NULL; \
|
|
||||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
|
||||||
*(head)->tqh_last = (elm); \
|
|
||||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
|
||||||
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
|
|
||||||
(elm)->field.tqe_next->field.tqe_prev = \
|
|
||||||
&(elm)->field.tqe_next; \
|
|
||||||
else \
|
|
||||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
|
||||||
(listelm)->field.tqe_next = (elm); \
|
|
||||||
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
|
||||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
|
||||||
(elm)->field.tqe_next = (listelm); \
|
|
||||||
*(listelm)->field.tqe_prev = (elm); \
|
|
||||||
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
|
||||||
if (((elm)->field.tqe_next) != NULL) \
|
|
||||||
(elm)->field.tqe_next->field.tqe_prev = \
|
|
||||||
(elm)->field.tqe_prev; \
|
|
||||||
else \
|
|
||||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
|
||||||
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TAILQ_REPLACE(head, elm, elm2, field) do { \
|
|
||||||
if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
|
|
||||||
(elm2)->field.tqe_next->field.tqe_prev = \
|
|
||||||
&(elm2)->field.tqe_next; \
|
|
||||||
else \
|
|
||||||
(head)->tqh_last = &(elm2)->field.tqe_next; \
|
|
||||||
(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
|
|
||||||
*(elm2)->field.tqe_prev = (elm2); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Circular queue definitions.
|
|
||||||
*/
|
|
||||||
#define CIRCLEQ_HEAD(name, type) \
|
|
||||||
struct name { \
|
|
||||||
struct type *cqh_first; /* first element */ \
|
|
||||||
struct type *cqh_last; /* last element */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CIRCLEQ_HEAD_INITIALIZER(head) \
|
|
||||||
{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
|
|
||||||
|
|
||||||
#define CIRCLEQ_ENTRY(type) \
|
|
||||||
struct { \
|
|
||||||
struct type *cqe_next; /* next element */ \
|
|
||||||
struct type *cqe_prev; /* previous element */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Circular queue access methods
|
|
||||||
*/
|
|
||||||
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
|
|
||||||
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
|
|
||||||
#define CIRCLEQ_END(head) ((void *)(head))
|
|
||||||
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
|
|
||||||
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
|
|
||||||
#define CIRCLEQ_EMPTY(head) \
|
|
||||||
(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
|
|
||||||
|
|
||||||
#define CIRCLEQ_FOREACH(var, head, field) \
|
|
||||||
for((var) = CIRCLEQ_FIRST(head); \
|
|
||||||
(var) != CIRCLEQ_END(head); \
|
|
||||||
(var) = CIRCLEQ_NEXT(var, field))
|
|
||||||
|
|
||||||
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
|
|
||||||
for((var) = CIRCLEQ_LAST(head); \
|
|
||||||
(var) != CIRCLEQ_END(head); \
|
|
||||||
(var) = CIRCLEQ_PREV(var, field))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Circular queue functions.
|
|
||||||
*/
|
|
||||||
#define CIRCLEQ_INIT(head) do { \
|
|
||||||
(head)->cqh_first = CIRCLEQ_END(head); \
|
|
||||||
(head)->cqh_last = CIRCLEQ_END(head); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
|
||||||
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
|
|
||||||
(elm)->field.cqe_prev = (listelm); \
|
|
||||||
if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
|
|
||||||
(head)->cqh_last = (elm); \
|
|
||||||
else \
|
|
||||||
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
|
|
||||||
(listelm)->field.cqe_next = (elm); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
|
|
||||||
(elm)->field.cqe_next = (listelm); \
|
|
||||||
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
|
|
||||||
if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
|
|
||||||
(head)->cqh_first = (elm); \
|
|
||||||
else \
|
|
||||||
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
|
|
||||||
(listelm)->field.cqe_prev = (elm); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
|
|
||||||
(elm)->field.cqe_next = (head)->cqh_first; \
|
|
||||||
(elm)->field.cqe_prev = CIRCLEQ_END(head); \
|
|
||||||
if ((head)->cqh_last == CIRCLEQ_END(head)) \
|
|
||||||
(head)->cqh_last = (elm); \
|
|
||||||
else \
|
|
||||||
(head)->cqh_first->field.cqe_prev = (elm); \
|
|
||||||
(head)->cqh_first = (elm); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
|
|
||||||
(elm)->field.cqe_next = CIRCLEQ_END(head); \
|
|
||||||
(elm)->field.cqe_prev = (head)->cqh_last; \
|
|
||||||
if ((head)->cqh_first == CIRCLEQ_END(head)) \
|
|
||||||
(head)->cqh_first = (elm); \
|
|
||||||
else \
|
|
||||||
(head)->cqh_last->field.cqe_next = (elm); \
|
|
||||||
(head)->cqh_last = (elm); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define CIRCLEQ_REMOVE(head, elm, field) do { \
|
|
||||||
if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
|
|
||||||
(head)->cqh_last = (elm)->field.cqe_prev; \
|
|
||||||
else \
|
|
||||||
(elm)->field.cqe_next->field.cqe_prev = \
|
|
||||||
(elm)->field.cqe_prev; \
|
|
||||||
if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
|
|
||||||
(head)->cqh_first = (elm)->field.cqe_next; \
|
|
||||||
else \
|
|
||||||
(elm)->field.cqe_prev->field.cqe_next = \
|
|
||||||
(elm)->field.cqe_next; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
|
|
||||||
if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
|
|
||||||
CIRCLEQ_END(head)) \
|
|
||||||
(head).cqh_last = (elm2); \
|
|
||||||
else \
|
|
||||||
(elm2)->field.cqe_next->field.cqe_prev = (elm2); \
|
|
||||||
if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
|
|
||||||
CIRCLEQ_END(head)) \
|
|
||||||
(head).cqh_first = (elm2); \
|
|
||||||
else \
|
|
||||||
(elm2)->field.cqe_prev->field.cqe_next = (elm2); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#endif /* !_SYS_QUEUE_H_ */
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,265 +0,0 @@
|
||||||
/* config.h.in. Generated from configure.in by autoheader. */
|
|
||||||
|
|
||||||
/* Define if clock_gettime is available in libc */
|
|
||||||
#undef DNS_USE_CPU_CLOCK_FOR_ID
|
|
||||||
|
|
||||||
/* Define is no secure id variant is available */
|
|
||||||
#undef DNS_USE_GETTIMEOFDAY_FOR_ID
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `clock_gettime' function. */
|
|
||||||
#undef HAVE_CLOCK_GETTIME
|
|
||||||
|
|
||||||
/* Define if /dev/poll is available */
|
|
||||||
#undef HAVE_DEVPOLL
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#undef HAVE_DLFCN_H
|
|
||||||
|
|
||||||
/* Define if your system supports the epoll system calls */
|
|
||||||
#undef HAVE_EPOLL
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
|
||||||
#undef HAVE_EPOLL_CTL
|
|
||||||
|
|
||||||
/* Define if your system supports event ports */
|
|
||||||
#undef HAVE_EVENT_PORTS
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `fcntl' function. */
|
|
||||||
#undef HAVE_FCNTL
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
|
||||||
#undef HAVE_FCNTL_H
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `fd_mask'. */
|
|
||||||
#undef HAVE_FD_MASK
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
|
||||||
#undef HAVE_GETADDRINFO
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `getegid' function. */
|
|
||||||
#undef HAVE_GETEGID
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `geteuid' function. */
|
|
||||||
#undef HAVE_GETEUID
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `getnameinfo' function. */
|
|
||||||
#undef HAVE_GETNAMEINFO
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `gettimeofday' function. */
|
|
||||||
#undef HAVE_GETTIMEOFDAY
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `inet_ntop' function. */
|
|
||||||
#undef HAVE_INET_NTOP
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#undef HAVE_INTTYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `issetugid' function. */
|
|
||||||
#undef HAVE_ISSETUGID
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `kqueue' function. */
|
|
||||||
#undef HAVE_KQUEUE
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `nsl' library (-lnsl). */
|
|
||||||
#undef HAVE_LIBNSL
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `resolv' library (-lresolv). */
|
|
||||||
#undef HAVE_LIBRESOLV
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `rt' library (-lrt). */
|
|
||||||
#undef HAVE_LIBRT
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
|
||||||
#undef HAVE_LIBSOCKET
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#undef HAVE_MEMORY_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <netinet/in6.h> header file. */
|
|
||||||
#undef HAVE_NETINET_IN6_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `poll' function. */
|
|
||||||
#undef HAVE_POLL
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <poll.h> header file. */
|
|
||||||
#undef HAVE_POLL_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `port_create' function. */
|
|
||||||
#undef HAVE_PORT_CREATE
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <port.h> header file. */
|
|
||||||
#undef HAVE_PORT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `select' function. */
|
|
||||||
#undef HAVE_SELECT
|
|
||||||
|
|
||||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
|
||||||
#undef HAVE_SETFD
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `sigaction' function. */
|
|
||||||
#undef HAVE_SIGACTION
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `signal' function. */
|
|
||||||
#undef HAVE_SIGNAL
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <signal.h> header file. */
|
|
||||||
#undef HAVE_SIGNAL_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
|
||||||
#undef HAVE_STDARG_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#undef HAVE_STDINT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#undef HAVE_STDLIB_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#undef HAVE_STRINGS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#undef HAVE_STRING_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strlcpy' function. */
|
|
||||||
#undef HAVE_STRLCPY
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strsep' function. */
|
|
||||||
#undef HAVE_STRSEP
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtok_r' function. */
|
|
||||||
#undef HAVE_STRTOK_R
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoll' function. */
|
|
||||||
#undef HAVE_STRTOLL
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct in6_addr'. */
|
|
||||||
#undef HAVE_STRUCT_IN6_ADDR
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/devpoll.h> header file. */
|
|
||||||
#undef HAVE_SYS_DEVPOLL_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
|
||||||
#undef HAVE_SYS_EPOLL_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
|
||||||
#undef HAVE_SYS_EVENT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
|
||||||
#undef HAVE_SYS_IOCTL_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
|
||||||
#undef HAVE_SYS_PARAM_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
|
||||||
#undef HAVE_SYS_QUEUE_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
|
||||||
#undef HAVE_SYS_SELECT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
|
||||||
#undef HAVE_SYS_SOCKET_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#undef HAVE_SYS_STAT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
|
||||||
#undef HAVE_SYS_TIME_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#undef HAVE_SYS_TYPES_H
|
|
||||||
|
|
||||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
|
||||||
#undef HAVE_TAILQFOREACH
|
|
||||||
|
|
||||||
/* Define if timeradd is defined in <sys/time.h> */
|
|
||||||
#undef HAVE_TIMERADD
|
|
||||||
|
|
||||||
/* Define if timerclear is defined in <sys/time.h> */
|
|
||||||
#undef HAVE_TIMERCLEAR
|
|
||||||
|
|
||||||
/* Define if timercmp is defined in <sys/time.h> */
|
|
||||||
#undef HAVE_TIMERCMP
|
|
||||||
|
|
||||||
/* Define if timerisset is defined in <sys/time.h> */
|
|
||||||
#undef HAVE_TIMERISSET
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint16_t'. */
|
|
||||||
#undef HAVE_UINT16_T
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint32_t'. */
|
|
||||||
#undef HAVE_UINT32_T
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint64_t'. */
|
|
||||||
#undef HAVE_UINT64_T
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint8_t'. */
|
|
||||||
#undef HAVE_UINT8_T
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#undef HAVE_UNISTD_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `vasprintf' function. */
|
|
||||||
#undef HAVE_VASPRINTF
|
|
||||||
|
|
||||||
/* Define if kqueue works correctly with pipes */
|
|
||||||
#undef HAVE_WORKING_KQUEUE
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#undef PACKAGE
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#undef PACKAGE_BUGREPORT
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#undef PACKAGE_NAME
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#undef PACKAGE_STRING
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#undef PACKAGE_TARNAME
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#undef PACKAGE_VERSION
|
|
||||||
|
|
||||||
/* The size of `int', as computed by sizeof. */
|
|
||||||
#undef SIZEOF_INT
|
|
||||||
|
|
||||||
/* The size of `long', as computed by sizeof. */
|
|
||||||
#undef SIZEOF_LONG
|
|
||||||
|
|
||||||
/* The size of `long long', as computed by sizeof. */
|
|
||||||
#undef SIZEOF_LONG_LONG
|
|
||||||
|
|
||||||
/* The size of `short', as computed by sizeof. */
|
|
||||||
#undef SIZEOF_SHORT
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#undef STDC_HEADERS
|
|
||||||
|
|
||||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
|
||||||
#undef TIME_WITH_SYS_TIME
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#undef VERSION
|
|
||||||
|
|
||||||
/* Define to appropriate substitue if compiler doesnt have __func__ */
|
|
||||||
#undef __func__
|
|
||||||
|
|
||||||
/* Define to empty if `const' does not conform to ANSI C. */
|
|
||||||
#undef const
|
|
||||||
|
|
||||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
|
||||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
|
||||||
#ifndef __cplusplus
|
|
||||||
#undef inline
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define to `int' if <sys/types.h> does not define. */
|
|
||||||
#undef pid_t
|
|
||||||
|
|
||||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
|
||||||
#undef size_t
|
|
||||||
|
|
||||||
/* Define to unsigned int if you dont have it */
|
|
||||||
#undef socklen_t
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,395 +0,0 @@
|
||||||
dnl configure.in for libevent
|
|
||||||
dnl Dug Song <dugsong@monkey.org>
|
|
||||||
AC_INIT(event.c)
|
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE(libevent,1.4.13-stable)
|
|
||||||
AM_CONFIG_HEADER(config.h)
|
|
||||||
dnl AM_MAINTAINER_MODE
|
|
||||||
|
|
||||||
dnl Initialize prefix.
|
|
||||||
if test "$prefix" = "NONE"; then
|
|
||||||
prefix="/usr/local"
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl Checks for programs.
|
|
||||||
AC_PROG_CC
|
|
||||||
AC_PROG_INSTALL
|
|
||||||
AC_PROG_LN_S
|
|
||||||
|
|
||||||
AC_PROG_GCC_TRADITIONAL
|
|
||||||
if test "$GCC" = yes ; then
|
|
||||||
CFLAGS="$CFLAGS -Wall"
|
|
||||||
# And disable the strict-aliasing optimization, since it breaks
|
|
||||||
# our sockaddr-handling code in strange ways.
|
|
||||||
CFLAGS="$CFLAGS -fno-strict-aliasing"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(gcc-warnings,
|
|
||||||
AS_HELP_STRING(--enable-gcc-warnings, enable verbose warnings with GCC))
|
|
||||||
|
|
||||||
AC_PROG_LIBTOOL
|
|
||||||
|
|
||||||
dnl Uncomment "AC_DISABLE_SHARED" to make shared librraries not get
|
|
||||||
dnl built by default. You can also turn shared libs on and off from
|
|
||||||
dnl the command line with --enable-shared and --disable-shared.
|
|
||||||
dnl AC_DISABLE_SHARED
|
|
||||||
AC_SUBST(LIBTOOL_DEPS)
|
|
||||||
|
|
||||||
dnl Checks for libraries.
|
|
||||||
AC_CHECK_LIB(socket, socket)
|
|
||||||
AC_CHECK_LIB(resolv, inet_aton)
|
|
||||||
AC_CHECK_LIB(rt, clock_gettime)
|
|
||||||
AC_CHECK_LIB(nsl, inet_ntoa)
|
|
||||||
|
|
||||||
dnl Checks for header files.
|
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in6.h sys/socket.h)
|
|
||||||
if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
|
|
||||||
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
|
|
||||||
AC_EGREP_CPP(yes,
|
|
||||||
[
|
|
||||||
#include <sys/queue.h>
|
|
||||||
#ifdef TAILQ_FOREACH
|
|
||||||
yes
|
|
||||||
#endif
|
|
||||||
], [AC_MSG_RESULT(yes)
|
|
||||||
AC_DEFINE(HAVE_TAILQFOREACH, 1,
|
|
||||||
[Define if TAILQ_FOREACH is defined in <sys/queue.h>])],
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
|
|
||||||
AC_MSG_CHECKING(for timeradd in sys/time.h)
|
|
||||||
AC_EGREP_CPP(yes,
|
|
||||||
[
|
|
||||||
#include <sys/time.h>
|
|
||||||
#ifdef timeradd
|
|
||||||
yes
|
|
||||||
#endif
|
|
||||||
], [ AC_DEFINE(HAVE_TIMERADD, 1,
|
|
||||||
[Define if timeradd is defined in <sys/time.h>])
|
|
||||||
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
|
|
||||||
AC_MSG_CHECKING(for timercmp in sys/time.h)
|
|
||||||
AC_EGREP_CPP(yes,
|
|
||||||
[
|
|
||||||
#include <sys/time.h>
|
|
||||||
#ifdef timercmp
|
|
||||||
yes
|
|
||||||
#endif
|
|
||||||
], [ AC_DEFINE(HAVE_TIMERCMP, 1,
|
|
||||||
[Define if timercmp is defined in <sys/time.h>])
|
|
||||||
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
|
|
||||||
AC_MSG_CHECKING(for timerclear in sys/time.h)
|
|
||||||
AC_EGREP_CPP(yes,
|
|
||||||
[
|
|
||||||
#include <sys/time.h>
|
|
||||||
#ifdef timerclear
|
|
||||||
yes
|
|
||||||
#endif
|
|
||||||
], [ AC_DEFINE(HAVE_TIMERCLEAR, 1,
|
|
||||||
[Define if timerclear is defined in <sys/time.h>])
|
|
||||||
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
|
|
||||||
AC_MSG_CHECKING(for timerisset in sys/time.h)
|
|
||||||
AC_EGREP_CPP(yes,
|
|
||||||
[
|
|
||||||
#include <sys/time.h>
|
|
||||||
#ifdef timerisset
|
|
||||||
yes
|
|
||||||
#endif
|
|
||||||
], [ AC_DEFINE(HAVE_TIMERISSET, 1,
|
|
||||||
[Define if timerisset is defined in <sys/time.h>])
|
|
||||||
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl - check if the macro WIN32 is defined on this compiler.
|
|
||||||
dnl - (this is how we check for a windows version of GCC)
|
|
||||||
AC_MSG_CHECKING(for WIN32)
|
|
||||||
AC_TRY_COMPILE(,
|
|
||||||
[
|
|
||||||
#ifndef WIN32
|
|
||||||
die horribly
|
|
||||||
#endif
|
|
||||||
],
|
|
||||||
bwin32=true; AC_MSG_RESULT(yes),
|
|
||||||
bwin32=false; AC_MSG_RESULT(no),
|
|
||||||
)
|
|
||||||
|
|
||||||
AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue)
|
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
|
||||||
AC_C_CONST
|
|
||||||
AC_C_INLINE
|
|
||||||
AC_HEADER_TIME
|
|
||||||
|
|
||||||
dnl Checks for library functions.
|
|
||||||
AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime strtok_r strsep getaddrinfo getnameinfo strlcpy inet_ntop signal sigaction strtoll issetugid geteuid getegid)
|
|
||||||
|
|
||||||
AC_CHECK_SIZEOF(long)
|
|
||||||
|
|
||||||
if test "x$ac_cv_func_clock_gettime" = "xyes"; then
|
|
||||||
AC_DEFINE(DNS_USE_CPU_CLOCK_FOR_ID, 1, [Define if clock_gettime is available in libc])
|
|
||||||
else
|
|
||||||
AC_DEFINE(DNS_USE_GETTIMEOFDAY_FOR_ID, 1, [Define is no secure id variant is available])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_MSG_CHECKING(for F_SETFD in fcntl.h)
|
|
||||||
AC_EGREP_CPP(yes,
|
|
||||||
[
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <fcntl.h>
|
|
||||||
#ifdef F_SETFD
|
|
||||||
yes
|
|
||||||
#endif
|
|
||||||
], [ AC_DEFINE(HAVE_SETFD, 1,
|
|
||||||
[Define if F_SETFD is defined in <fcntl.h>])
|
|
||||||
AC_MSG_RESULT(yes) ], AC_MSG_RESULT(no))
|
|
||||||
|
|
||||||
needsignal=no
|
|
||||||
haveselect=no
|
|
||||||
AC_CHECK_FUNCS(select, [haveselect=yes], )
|
|
||||||
if test "x$haveselect" = "xyes" ; then
|
|
||||||
AC_LIBOBJ(select)
|
|
||||||
needsignal=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
havepoll=no
|
|
||||||
AC_CHECK_FUNCS(poll, [havepoll=yes], )
|
|
||||||
if test "x$havepoll" = "xyes" ; then
|
|
||||||
AC_LIBOBJ(poll)
|
|
||||||
needsignal=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
haveepoll=no
|
|
||||||
AC_CHECK_FUNCS(epoll_ctl, [haveepoll=yes], )
|
|
||||||
if test "x$haveepoll" = "xyes" ; then
|
|
||||||
AC_DEFINE(HAVE_EPOLL, 1,
|
|
||||||
[Define if your system supports the epoll system calls])
|
|
||||||
AC_LIBOBJ(epoll)
|
|
||||||
needsignal=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
havedevpoll=no
|
|
||||||
if test "x$ac_cv_header_sys_devpoll_h" = "xyes"; then
|
|
||||||
AC_DEFINE(HAVE_DEVPOLL, 1,
|
|
||||||
[Define if /dev/poll is available])
|
|
||||||
AC_LIBOBJ(devpoll)
|
|
||||||
fi
|
|
||||||
|
|
||||||
havekqueue=no
|
|
||||||
if test "x$ac_cv_header_sys_event_h" = "xyes"; then
|
|
||||||
AC_CHECK_FUNCS(kqueue, [havekqueue=yes], )
|
|
||||||
if test "x$havekqueue" = "xyes" ; then
|
|
||||||
AC_MSG_CHECKING(for working kqueue)
|
|
||||||
AC_TRY_RUN(
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/event.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int kq;
|
|
||||||
int n;
|
|
||||||
int fd[[2]];
|
|
||||||
struct kevent ev;
|
|
||||||
struct timespec ts;
|
|
||||||
char buf[[8000]];
|
|
||||||
|
|
||||||
if (pipe(fd) == -1)
|
|
||||||
exit(1);
|
|
||||||
if (fcntl(fd[[1]], F_SETFL, O_NONBLOCK) == -1)
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
while ((n = write(fd[[1]], buf, sizeof(buf))) == sizeof(buf))
|
|
||||||
;
|
|
||||||
|
|
||||||
if ((kq = kqueue()) == -1)
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
ev.ident = fd[[1]];
|
|
||||||
ev.filter = EVFILT_WRITE;
|
|
||||||
ev.flags = EV_ADD | EV_ENABLE;
|
|
||||||
n = kevent(kq, &ev, 1, NULL, 0, NULL);
|
|
||||||
if (n == -1)
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
read(fd[[0]], buf, sizeof(buf));
|
|
||||||
|
|
||||||
ts.tv_sec = 0;
|
|
||||||
ts.tv_nsec = 0;
|
|
||||||
n = kevent(kq, NULL, 0, &ev, 1, &ts);
|
|
||||||
if (n == -1 || n == 0)
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}, [AC_MSG_RESULT(yes)
|
|
||||||
AC_DEFINE(HAVE_WORKING_KQUEUE, 1,
|
|
||||||
[Define if kqueue works correctly with pipes])
|
|
||||||
AC_LIBOBJ(kqueue)], AC_MSG_RESULT(no), AC_MSG_RESULT(no))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
haveepollsyscall=no
|
|
||||||
if test "x$ac_cv_header_sys_epoll_h" = "xyes"; then
|
|
||||||
if test "x$haveepoll" = "xno" ; then
|
|
||||||
AC_MSG_CHECKING(for epoll system call)
|
|
||||||
AC_TRY_RUN(
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
#include <sys/epoll.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
epoll_create(int size)
|
|
||||||
{
|
|
||||||
return (syscall(__NR_epoll_create, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int epfd;
|
|
||||||
|
|
||||||
epfd = epoll_create(256);
|
|
||||||
exit (epfd == -1 ? 1 : 0);
|
|
||||||
}, [AC_MSG_RESULT(yes)
|
|
||||||
AC_DEFINE(HAVE_EPOLL, 1,
|
|
||||||
[Define if your system supports the epoll system calls])
|
|
||||||
needsignal=yes
|
|
||||||
AC_LIBOBJ(epoll_sub)
|
|
||||||
AC_LIBOBJ(epoll)], AC_MSG_RESULT(no), AC_MSG_RESULT(no))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
haveeventports=no
|
|
||||||
AC_CHECK_FUNCS(port_create, [haveeventports=yes], )
|
|
||||||
if test "x$haveeventports" = "xyes" ; then
|
|
||||||
AC_DEFINE(HAVE_EVENT_PORTS, 1,
|
|
||||||
[Define if your system supports event ports])
|
|
||||||
AC_LIBOBJ(evport)
|
|
||||||
needsignal=yes
|
|
||||||
fi
|
|
||||||
if test "x$bwin32" = "xtrue"; then
|
|
||||||
needsignal=yes
|
|
||||||
fi
|
|
||||||
if test "x$bwin32" = "xtrue"; then
|
|
||||||
needsignal=yes
|
|
||||||
fi
|
|
||||||
if test "x$needsignal" = "xyes" ; then
|
|
||||||
AC_LIBOBJ(signal)
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_TYPE_PID_T
|
|
||||||
AC_TYPE_SIZE_T
|
|
||||||
AC_CHECK_TYPES([uint64_t, uint32_t, uint16_t, uint8_t], , ,
|
|
||||||
[#ifdef HAVE_STDINT_H
|
|
||||||
#include <stdint.h>
|
|
||||||
#elif defined(HAVE_INTTYPES_H)
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif])
|
|
||||||
AC_CHECK_TYPES([fd_mask], , ,
|
|
||||||
[#ifdef HAVE_SYS_TYPES_H
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SELECT_H
|
|
||||||
#include <select.h>
|
|
||||||
#endif])
|
|
||||||
|
|
||||||
AC_CHECK_SIZEOF(long long)
|
|
||||||
AC_CHECK_SIZEOF(int)
|
|
||||||
AC_CHECK_SIZEOF(short)
|
|
||||||
AC_CHECK_TYPES([struct in6_addr], , ,
|
|
||||||
[#ifdef WIN32
|
|
||||||
#include <winsock2.h>
|
|
||||||
#else
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_NETINET_IN6_H
|
|
||||||
#include <netinet/in6.h>
|
|
||||||
#endif])
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([for socklen_t])
|
|
||||||
AC_TRY_COMPILE([
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>],
|
|
||||||
[socklen_t x;],
|
|
||||||
AC_MSG_RESULT([yes]),
|
|
||||||
[AC_MSG_RESULT([no])
|
|
||||||
AC_DEFINE(socklen_t, unsigned int,
|
|
||||||
[Define to unsigned int if you dont have it])]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether our compiler supports __func__])
|
|
||||||
AC_TRY_COMPILE([],
|
|
||||||
[ const char *cp = __func__; ],
|
|
||||||
AC_MSG_RESULT([yes]),
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
AC_MSG_CHECKING([whether our compiler supports __FUNCTION__])
|
|
||||||
AC_TRY_COMPILE([],
|
|
||||||
[ const char *cp = __FUNCTION__; ],
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
AC_DEFINE(__func__, __FUNCTION__,
|
|
||||||
[Define to appropriate substitue if compiler doesnt have __func__]),
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
AC_DEFINE(__func__, __FILE__,
|
|
||||||
[Define to appropriate substitue if compiler doesnt have __func__])))
|
|
||||||
|
|
||||||
|
|
||||||
# Add some more warnings which we use in development but not in the
|
|
||||||
# released versions. (Some relevant gcc versions can't handle these.)
|
|
||||||
if test x$enable_gcc_warnings = xyes; then
|
|
||||||
|
|
||||||
AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], [
|
|
||||||
#if !defined(__GNUC__) || (__GNUC__ < 4)
|
|
||||||
#error
|
|
||||||
#endif]), have_gcc4=yes, have_gcc4=no)
|
|
||||||
|
|
||||||
AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], [
|
|
||||||
#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)
|
|
||||||
#error
|
|
||||||
#endif]), have_gcc42=yes, have_gcc42=no)
|
|
||||||
|
|
||||||
CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror"
|
|
||||||
CFLAGS="$CFLAGS -Wno-unused-parameter -Wno-sign-compare -Wstrict-aliasing"
|
|
||||||
|
|
||||||
if test x$have_gcc4 = xyes ; then
|
|
||||||
# These warnings break gcc 3.3.5 and work on gcc 4.0.2
|
|
||||||
CFLAGS="$CFLAGS -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement"
|
|
||||||
#CFLAGS="$CFLAGS -Wold-style-definition"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$have_gcc42 = xyes ; then
|
|
||||||
# These warnings break gcc 4.0.2 and work on gcc 4.2
|
|
||||||
CFLAGS="$CFLAGS -Waddress -Wnormalized=id -Woverride-init"
|
|
||||||
fi
|
|
||||||
|
|
||||||
##This will break the world on some 64-bit architectures
|
|
||||||
# CFLAGS="$CFLAGS -Winline"
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_OUTPUT(Makefile test/Makefile sample/Makefile)
|
|
|
@ -1,417 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2000-2004 Niels Provos <provos@citi.umich.edu>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#ifdef HAVE_SYS_TIME_H
|
|
||||||
#include <sys/time.h>
|
|
||||||
#else
|
|
||||||
#include <sys/_libevent_time.h>
|
|
||||||
#endif
|
|
||||||
#include <sys/queue.h>
|
|
||||||
#include <sys/devpoll.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "event.h"
|
|
||||||
#include "event-internal.h"
|
|
||||||
#include "evsignal.h"
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
/* due to limitations in the devpoll interface, we need to keep track of
|
|
||||||
* all file descriptors outself.
|
|
||||||
*/
|
|
||||||
struct evdevpoll {
|
|
||||||
struct event *evread;
|
|
||||||
struct event *evwrite;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct devpollop {
|
|
||||||
struct evdevpoll *fds;
|
|
||||||
int nfds;
|
|
||||||
struct pollfd *events;
|
|
||||||
int nevents;
|
|
||||||
int dpfd;
|
|
||||||
struct pollfd *changes;
|
|
||||||
int nchanges;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void *devpoll_init (struct event_base *);
|
|
||||||
static int devpoll_add (void *, struct event *);
|
|
||||||
static int devpoll_del (void *, struct event *);
|
|
||||||
static int devpoll_dispatch (struct event_base *, void *, struct timeval *);
|
|
||||||
static void devpoll_dealloc (struct event_base *, void *);
|
|
||||||
|
|
||||||
const struct eventop devpollops = {
|
|
||||||
"devpoll",
|
|
||||||
devpoll_init,
|
|
||||||
devpoll_add,
|
|
||||||
devpoll_del,
|
|
||||||
devpoll_dispatch,
|
|
||||||
devpoll_dealloc,
|
|
||||||
1 /* need reinit */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NEVENT 32000
|
|
||||||
|
|
||||||
static int
|
|
||||||
devpoll_commit(struct devpollop *devpollop)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Due to a bug in Solaris, we have to use pwrite with an offset of 0.
|
|
||||||
* Write is limited to 2GB of data, until it will fail.
|
|
||||||
*/
|
|
||||||
if (pwrite(devpollop->dpfd, devpollop->changes,
|
|
||||||
sizeof(struct pollfd) * devpollop->nchanges, 0) == -1)
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
devpollop->nchanges = 0;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
devpoll_queue(struct devpollop *devpollop, int fd, int events) {
|
|
||||||
struct pollfd *pfd;
|
|
||||||
|
|
||||||
if (devpollop->nchanges >= devpollop->nevents) {
|
|
||||||
/*
|
|
||||||
* Change buffer is full, must commit it to /dev/poll before
|
|
||||||
* adding more
|
|
||||||
*/
|
|
||||||
if (devpoll_commit(devpollop) != 0)
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pfd = &devpollop->changes[devpollop->nchanges++];
|
|
||||||
pfd->fd = fd;
|
|
||||||
pfd->events = events;
|
|
||||||
pfd->revents = 0;
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
devpoll_init(struct event_base *base)
|
|
||||||
{
|
|
||||||
int dpfd, nfiles = NEVENT;
|
|
||||||
struct rlimit rl;
|
|
||||||
struct devpollop *devpollop;
|
|
||||||
|
|
||||||
/* Disable devpoll when this environment variable is set */
|
|
||||||
if (evutil_getenv("EVENT_NODEVPOLL"))
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
if (!(devpollop = calloc(1, sizeof(struct devpollop))))
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
|
|
||||||
rl.rlim_cur != RLIM_INFINITY)
|
|
||||||
nfiles = rl.rlim_cur;
|
|
||||||
|
|
||||||
/* Initialize the kernel queue */
|
|
||||||
if ((dpfd = open("/dev/poll", O_RDWR)) == -1) {
|
|
||||||
event_warn("open: /dev/poll");
|
|
||||||
free(devpollop);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
devpollop->dpfd = dpfd;
|
|
||||||
|
|
||||||
/* Initialize fields */
|
|
||||||
devpollop->events = calloc(nfiles, sizeof(struct pollfd));
|
|
||||||
if (devpollop->events == NULL) {
|
|
||||||
free(devpollop);
|
|
||||||
close(dpfd);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
devpollop->nevents = nfiles;
|
|
||||||
|
|
||||||
devpollop->fds = calloc(nfiles, sizeof(struct evdevpoll));
|
|
||||||
if (devpollop->fds == NULL) {
|
|
||||||
free(devpollop->events);
|
|
||||||
free(devpollop);
|
|
||||||
close(dpfd);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
devpollop->nfds = nfiles;
|
|
||||||
|
|
||||||
devpollop->changes = calloc(nfiles, sizeof(struct pollfd));
|
|
||||||
if (devpollop->changes == NULL) {
|
|
||||||
free(devpollop->fds);
|
|
||||||
free(devpollop->events);
|
|
||||||
free(devpollop);
|
|
||||||
close(dpfd);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
evsignal_init(base);
|
|
||||||
|
|
||||||
return (devpollop);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
devpoll_recalc(struct event_base *base, void *arg, int max)
|
|
||||||
{
|
|
||||||
struct devpollop *devpollop = arg;
|
|
||||||
|
|
||||||
if (max >= devpollop->nfds) {
|
|
||||||
struct evdevpoll *fds;
|
|
||||||
int nfds;
|
|
||||||
|
|
||||||
nfds = devpollop->nfds;
|
|
||||||
while (nfds <= max)
|
|
||||||
nfds <<= 1;
|
|
||||||
|
|
||||||
fds = realloc(devpollop->fds, nfds * sizeof(struct evdevpoll));
|
|
||||||
if (fds == NULL) {
|
|
||||||
event_warn("realloc");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
devpollop->fds = fds;
|
|
||||||
memset(fds + devpollop->nfds, 0,
|
|
||||||
(nfds - devpollop->nfds) * sizeof(struct evdevpoll));
|
|
||||||
devpollop->nfds = nfds;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
devpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
|
||||||
{
|
|
||||||
struct devpollop *devpollop = arg;
|
|
||||||
struct pollfd *events = devpollop->events;
|
|
||||||
struct dvpoll dvp;
|
|
||||||
struct evdevpoll *evdp;
|
|
||||||
int i, res, timeout = -1;
|
|
||||||
|
|
||||||
if (devpollop->nchanges)
|
|
||||||
devpoll_commit(devpollop);
|
|
||||||
|
|
||||||
if (tv != NULL)
|
|
||||||
timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
|
||||||
|
|
||||||
dvp.dp_fds = devpollop->events;
|
|
||||||
dvp.dp_nfds = devpollop->nevents;
|
|
||||||
dvp.dp_timeout = timeout;
|
|
||||||
|
|
||||||
res = ioctl(devpollop->dpfd, DP_POLL, &dvp);
|
|
||||||
|
|
||||||
if (res == -1) {
|
|
||||||
if (errno != EINTR) {
|
|
||||||
event_warn("ioctl: DP_POLL");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
evsignal_process(base);
|
|
||||||
return (0);
|
|
||||||
} else if (base->sig.evsignal_caught) {
|
|
||||||
evsignal_process(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
event_debug(("%s: devpoll_wait reports %d", __func__, res));
|
|
||||||
|
|
||||||
for (i = 0; i < res; i++) {
|
|
||||||
int which = 0;
|
|
||||||
int what = events[i].revents;
|
|
||||||
struct event *evread = NULL, *evwrite = NULL;
|
|
||||||
|
|
||||||
assert(events[i].fd < devpollop->nfds);
|
|
||||||
evdp = &devpollop->fds[events[i].fd];
|
|
||||||
|
|
||||||
if (what & POLLHUP)
|
|
||||||
what |= POLLIN | POLLOUT;
|
|
||||||
else if (what & POLLERR)
|
|
||||||
what |= POLLIN | POLLOUT;
|
|
||||||
|
|
||||||
if (what & POLLIN) {
|
|
||||||
evread = evdp->evread;
|
|
||||||
which |= EV_READ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (what & POLLOUT) {
|
|
||||||
evwrite = evdp->evwrite;
|
|
||||||
which |= EV_WRITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!which)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (evread != NULL && !(evread->ev_events & EV_PERSIST))
|
|
||||||
event_del(evread);
|
|
||||||
if (evwrite != NULL && evwrite != evread &&
|
|
||||||
!(evwrite->ev_events & EV_PERSIST))
|
|
||||||
event_del(evwrite);
|
|
||||||
|
|
||||||
if (evread != NULL)
|
|
||||||
event_active(evread, EV_READ, 1);
|
|
||||||
if (evwrite != NULL)
|
|
||||||
event_active(evwrite, EV_WRITE, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
devpoll_add(void *arg, struct event *ev)
|
|
||||||
{
|
|
||||||
struct devpollop *devpollop = arg;
|
|
||||||
struct evdevpoll *evdp;
|
|
||||||
int fd, events;
|
|
||||||
|
|
||||||
if (ev->ev_events & EV_SIGNAL)
|
|
||||||
return (evsignal_add(ev));
|
|
||||||
|
|
||||||
fd = ev->ev_fd;
|
|
||||||
if (fd >= devpollop->nfds) {
|
|
||||||
/* Extend the file descriptor array as necessary */
|
|
||||||
if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1)
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
evdp = &devpollop->fds[fd];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* It's not necessary to OR the existing read/write events that we
|
|
||||||
* are currently interested in with the new event we are adding.
|
|
||||||
* The /dev/poll driver ORs any new events with the existing events
|
|
||||||
* that it has cached for the fd.
|
|
||||||
*/
|
|
||||||
|
|
||||||
events = 0;
|
|
||||||
if (ev->ev_events & EV_READ) {
|
|
||||||
if (evdp->evread && evdp->evread != ev) {
|
|
||||||
/* There is already a different read event registered */
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
events |= POLLIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ev->ev_events & EV_WRITE) {
|
|
||||||
if (evdp->evwrite && evdp->evwrite != ev) {
|
|
||||||
/* There is already a different write event registered */
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
events |= POLLOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (devpoll_queue(devpollop, fd, events) != 0)
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
/* Update events responsible */
|
|
||||||
if (ev->ev_events & EV_READ)
|
|
||||||
evdp->evread = ev;
|
|
||||||
if (ev->ev_events & EV_WRITE)
|
|
||||||
evdp->evwrite = ev;
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
devpoll_del(void *arg, struct event *ev)
|
|
||||||
{
|
|
||||||
struct devpollop *devpollop = arg;
|
|
||||||
struct evdevpoll *evdp;
|
|
||||||
int fd, events;
|
|
||||||
int needwritedelete = 1, needreaddelete = 1;
|
|
||||||
|
|
||||||
if (ev->ev_events & EV_SIGNAL)
|
|
||||||
return (evsignal_del(ev));
|
|
||||||
|
|
||||||
fd = ev->ev_fd;
|
|
||||||
if (fd >= devpollop->nfds)
|
|
||||||
return (0);
|
|
||||||
evdp = &devpollop->fds[fd];
|
|
||||||
|
|
||||||
events = 0;
|
|
||||||
if (ev->ev_events & EV_READ)
|
|
||||||
events |= POLLIN;
|
|
||||||
if (ev->ev_events & EV_WRITE)
|
|
||||||
events |= POLLOUT;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The only way to remove an fd from the /dev/poll monitored set is
|
|
||||||
* to use POLLREMOVE by itself. This removes ALL events for the fd
|
|
||||||
* provided so if we care about two events and are only removing one
|
|
||||||
* we must re-add the other event after POLLREMOVE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0)
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
if ((events & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) {
|
|
||||||
/*
|
|
||||||
* We're not deleting all events, so we must resubmit the
|
|
||||||
* event that we are still interested in if one exists.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((events & POLLIN) && evdp->evwrite != NULL) {
|
|
||||||
/* Deleting read, still care about write */
|
|
||||||
devpoll_queue(devpollop, fd, POLLOUT);
|
|
||||||
needwritedelete = 0;
|
|
||||||
} else if ((events & POLLOUT) && evdp->evread != NULL) {
|
|
||||||
/* Deleting write, still care about read */
|
|
||||||
devpoll_queue(devpollop, fd, POLLIN);
|
|
||||||
needreaddelete = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needreaddelete)
|
|
||||||
evdp->evread = NULL;
|
|
||||||
if (needwritedelete)
|
|
||||||
evdp->evwrite = NULL;
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
devpoll_dealloc(struct event_base *base, void *arg)
|
|
||||||
{
|
|
||||||
struct devpollop *devpollop = arg;
|
|
||||||
|
|
||||||
evsignal_dealloc(base);
|
|
||||||
if (devpollop->fds)
|
|
||||||
free(devpollop->fds);
|
|
||||||
if (devpollop->events)
|
|
||||||
free(devpollop->events);
|
|
||||||
if (devpollop->changes)
|
|
||||||
free(devpollop->changes);
|
|
||||||
if (devpollop->dpfd >= 0)
|
|
||||||
close(devpollop->dpfd);
|
|
||||||
|
|
||||||
memset(devpollop, 0, sizeof(struct devpollop));
|
|
||||||
free(devpollop);
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue