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

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef __WINDOWS__
#include <unistd.h>
#endif // __WINDOWS__
#include <sys/types.h>

#ifdef __linux__
#include <sys/prctl.h>
#endif // __linux__
#include <sys/types.h>

#include <string>

#include <glog/logging.h>

#include <process/future.hpp>
#include <process/reap.hpp>
#include <process/subprocess.hpp>

#include <stout/error.hpp>
#include <stout/lambda.hpp>
#include <stout/foreach.hpp>
#include <stout/option.hpp>
#include <stout/os.hpp>
#include <stout/strings.hpp>
#include <stout/try.hpp>

using std::map;
using std::string;
using std::vector;

namespace process {

using InputFileDescriptors = Subprocess::IO::InputFileDescriptors;
using OutputFileDescriptors = Subprocess::IO::OutputFileDescriptors;

Subprocess::ParentHook::ParentHook(
    const lambda::function<Try<Nothing>(pid_t)>& _parent_setup)
  : parent_setup(_parent_setup) {}

Subprocess::ChildHook::ChildHook(
    const lambda::function<Try<Nothing>()>& _child_setup)
  : child_setup(_child_setup) {}

Subprocess::ChildHook Subprocess::ChildHook::CHDIR(
    const std::string& working_directory)
{
  return Subprocess::ChildHook([working_directory]() -> Try<Nothing> {
    if (::chdir(working_directory.c_str()) == -1) {
      return Error("Could not chdir");
    }

    return Nothing();
  });
}

Subprocess::ChildHook Subprocess::ChildHook::SETSID()
{
  return Subprocess::ChildHook([]() -> Try<Nothing> {
    // Put child into its own process session to prevent slave suicide
    // on child process SIGKILL/SIGTERM.
    if (::setsid() == -1) {
      return Error("Could not setsid");
    }

    return Nothing();
  });
}

inline void signalHandler(int signal)
{
  // Send SIGKILL to every process in the process group of the
  // calling process.
  kill(0, SIGKILL);
  abort();
}

Subprocess::ChildHook Subprocess::ChildHook::SUPERVISOR()
{
  return Subprocess::ChildHook([]() -> Try<Nothing> {
#ifdef __linux__
    // Send SIGTERM to the current process if the parent (i.e., the
    // slave) exits.
    // NOTE:: This function should always succeed because we are passing
    // in a valid signal.
    prctl(PR_SET_PDEATHSIG, SIGTERM);

    // Put the current process into a separate process group so that
    // we can kill it and all its children easily.
    if (setpgid(0, 0) != 0) {
      return Error("Could not start supervisor process.");
    }

    // Install a SIGTERM handler which will kill the current process
    // group. Since we already setup the death signal above, the
    // signal handler will be triggered when the parent (e.g., the
    // slave) exits.
    if (os::signals::install(SIGTERM, &signalHandler) != 0) {
      return Error("Could not start supervisor process.");
    }

    pid_t pid = fork();
    if (pid == -1) {
      return Error("Could not start supervisor process.");
    } else if (pid == 0) {
      // Child. This is the process that is going to exec the
      // process if zero is returned.

      // We setup death signal for the process as well in case
      // someone, though unlikely, accidentally kill the parent of
      // this process (the bookkeeping process).
      prctl(PR_SET_PDEATHSIG, SIGKILL);

      // NOTE: We don't need to clear the signal handler explicitly
      // because the subsequent 'exec' will clear them.
      return Nothing();
    } else {
      // Parent. This is the bookkeeping process which will wait for
      // the child process to finish.

      // Close the files to prevent interference on the communication
      // between the slave and the child process.
      ::close(STDIN_FILENO);
      ::close(STDOUT_FILENO);
      ::close(STDERR_FILENO);

      // Block until the child process finishes.
      int status = 0;
      if (waitpid(pid, &status, 0) == -1) {
        abort();
      }

      // Forward the exit status if the child process exits normally.
      if (WIFEXITED(status)) {
        _exit(WEXITSTATUS(status));
      }

      abort();
      UNREACHABLE();
    }
#endif
    return Nothing();
  });
}

namespace internal {

static void cleanup(
    const Future<Option<int>>& result,
    Promise<Option<int>>* promise,
    const Subprocess& subprocess)
{
  CHECK(!result.isPending());
  CHECK(!result.isDiscarded());

  if (result.isFailed()) {
    promise->fail(result.failure());
  } else {
    promise->set(result.get());
  }

  delete promise;
}

}  // namespace internal {

// Executes a subprocess.
//
// NOTE: On Windows, components of the `path` and `argv` that need to be quoted
// are expected to have been quoted before they are passed to `subprocess. For
// example, either of these may contain paths with spaces in them, like
// `C:\"Program Files"\foo.exe`, where notably the character sequence `\"` does
// is not escaped quote, but instead a path separator and the start of a path
// component. Since the semantics of quoting are shell-dependent, it is not
// practical to attempt to re-parse the command that is passed in and properly
// escape it. Therefore, incorrectly-quoted command arguments will probably
// lead the child process to terminate with an error.
Try<Subprocess> subprocess(
    const string& path,
    vector<string> argv,
    const Subprocess::IO& in,
    const Subprocess::IO& out,
    const Subprocess::IO& err,
    const flags::FlagsBase* flags,
    const Option<map<string, string>>& environment,
    const Option<lambda::function<
        pid_t(const lambda::function<int()>&)>>& _clone,
    const vector<Subprocess::ParentHook>& parent_hooks,
    const vector<Subprocess::ChildHook>& child_hooks)
{
  // File descriptors for redirecting stdin/stdout/stderr.
  // These file descriptors are used for different purposes depending
  // on the specified I/O modes.
  // See `Subprocess::PIPE`, `Subprocess::PATH`, and `Subprocess::FD`.
  InputFileDescriptors stdinfds;
  OutputFileDescriptors stdoutfds;
  OutputFileDescriptors stderrfds;

  // Prepare the file descriptor(s) for stdin.
  Try<InputFileDescriptors> input = in.input();
  if (input.isError()) {
    return Error(input.error());
  }

  stdinfds = input.get();

  // Prepare the file descriptor(s) for stdout.
  Try<OutputFileDescriptors> output = out.output();
  if (output.isError()) {
    process::internal::close(stdinfds, stdoutfds, stderrfds);
    return Error(output.error());
  }

  stdoutfds = output.get();

  // Prepare the file descriptor(s) for stderr.
  output = err.output();
  if (output.isError()) {
    process::internal::close(stdinfds, stdoutfds, stderrfds);
    return Error(output.error());
  }

  stderrfds = output.get();

#ifndef __WINDOWS__
  // TODO(jieyu): Consider using O_CLOEXEC for atomic close-on-exec.
  Try<Nothing> cloexec = internal::cloexec(stdinfds, stdoutfds, stderrfds);
  if (cloexec.isError()) {
    process::internal::close(stdinfds, stdoutfds, stderrfds);
    return Error("Failed to cloexec: " + cloexec.error());
  }
#endif // __WINDOWS__

  // Prepare the arguments. If the user specifies the 'flags', we will
  // stringify them and append them to the existing arguments.
  if (flags != nullptr) {
    foreachvalue (const flags::Flag& flag, *flags) {
      Option<string> value = flag.stringify(*flags);
      if (value.isSome()) {
        argv.push_back("--" + flag.effective_name().value + "=" + value.get());
      }
    }
  }

  // Parent.
  Subprocess process;

  // Create child, passing in stdin/stdout/stderr handles. We store the
  // information and data structures we need to manage the lifecycle of the
  // child (e.g., the PID of the child) in `process.data`.
  //
  // NOTE: We use lexical blocking around the `#ifdef` to limit use of data
  // structures declared in the `#ifdef`. Since objects like `pid` will go out
  // of scope at the end of the block, there is no chance we will accidentally
  // define something in (say) the `__WINDOWS__` branch and then attempt to use
  // it in the non-`__WINDOWS__` branch.
  {
#ifndef __WINDOWS__
    Try<pid_t> pid = internal::cloneChild(
        path,
        argv,
        environment,
        _clone,
        parent_hooks,
        child_hooks,
        stdinfds,
        stdoutfds,
        stderrfds);

    if (pid.isError()) {
      return Error(pid.error());
    }

    process.data->pid = pid.get();
#else
    // TODO(joerg84): Consider using the childHooks and parentHooks here.
    Try<PROCESS_INFORMATION> processInformation = internal::createChildProcess(
        path, argv, environment, stdinfds, stdoutfds, stderrfds);

    if (processInformation.isError()) {
      process::internal::close(stdinfds, stdoutfds, stderrfds);
      return Error(
          "Could not launch child process" + processInformation.error());
    }

    if (processInformation.get().dwProcessId == -1) {
      // Save the errno as 'close' below might overwrite it.
      ErrnoError error("Failed to clone");
      process::internal::close(stdinfds, stdoutfds, stderrfds);
      return error;
    }

    process.data->processInformation = processInformation.get();
    process.data->pid = processInformation.get().dwProcessId;
#endif // __WINDOWS__
  }

  // Close the child-ends of the file descriptors that are created
  // by this function.
  os::close(stdinfds.read);
  os::close(stdoutfds.write);
  os::close(stderrfds.write);

  // For any pipes, store the parent side of the pipe so that
  // the user can communicate with the subprocess.
  process.data->in = stdinfds.write;
  process.data->out = stdoutfds.read;
  process.data->err = stderrfds.read;

  // Rather than directly exposing the future from process::reap, we
  // must use an explicit promise so that we can ensure we can receive
  // the termination signal. Otherwise, the caller can discard the
  // reap future, and we will not know when it is safe to close the
  // file descriptors.
  Promise<Option<int>>* promise = new Promise<Option<int>>();
  process.data->status = promise->future();

  // We need to bind a copy of this Subprocess into the onAny callback
  // below to ensure that we don't close the file descriptors before
  // the subprocess has terminated (i.e., because the caller doesn't
  // keep a copy of this Subprocess around themselves).
  process::reap(process.data->pid)
    .onAny(lambda::bind(internal::cleanup, lambda::_1, promise, process));

  return process;
}

}  // namespace process {
<commit_msg>Windows: Fixed subprocess and setsid compilation errors.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef __WINDOWS__
#include <unistd.h>
#endif // __WINDOWS__
#include <sys/types.h>

#ifdef __linux__
#include <sys/prctl.h>
#endif // __linux__
#include <sys/types.h>

#include <string>

#include <glog/logging.h>

#include <process/future.hpp>
#include <process/reap.hpp>
#include <process/subprocess.hpp>

#include <stout/error.hpp>
#include <stout/lambda.hpp>
#include <stout/foreach.hpp>
#include <stout/option.hpp>
#include <stout/os.hpp>
#include <stout/strings.hpp>
#include <stout/try.hpp>

using std::map;
using std::string;
using std::vector;

namespace process {

using InputFileDescriptors = Subprocess::IO::InputFileDescriptors;
using OutputFileDescriptors = Subprocess::IO::OutputFileDescriptors;

Subprocess::ParentHook::ParentHook(
    const lambda::function<Try<Nothing>(pid_t)>& _parent_setup)
  : parent_setup(_parent_setup) {}

Subprocess::ChildHook::ChildHook(
    const lambda::function<Try<Nothing>()>& _child_setup)
  : child_setup(_child_setup) {}

Subprocess::ChildHook Subprocess::ChildHook::CHDIR(
    const std::string& working_directory)
{
  return Subprocess::ChildHook([working_directory]() -> Try<Nothing> {
    if (::chdir(working_directory.c_str()) == -1) {
      return Error("Could not chdir");
    }

    return Nothing();
  });
}

Subprocess::ChildHook Subprocess::ChildHook::SETSID()
{
  return Subprocess::ChildHook([]() -> Try<Nothing> {
    // TODO(josephw): By default, child processes on Windows do not
    // terminate when the parent terminates. We need to implement
    // `JobObject` support to change this default.
#ifndef __WINDOWS__
    // Put child into its own process session to prevent slave suicide
    // on child process SIGKILL/SIGTERM.
    if (::setsid() == -1) {
      return Error("Could not setsid");
    }
#endif // __WINDOWS__

    return Nothing();
  });
}

#ifdef __linux__
inline void signalHandler(int signal)
{
  // Send SIGKILL to every process in the process group of the
  // calling process.
  kill(0, SIGKILL);
  abort();
}
#endif // __linux__

Subprocess::ChildHook Subprocess::ChildHook::SUPERVISOR()
{
  return Subprocess::ChildHook([]() -> Try<Nothing> {
#ifdef __linux__
    // Send SIGTERM to the current process if the parent (i.e., the
    // slave) exits.
    // NOTE:: This function should always succeed because we are passing
    // in a valid signal.
    prctl(PR_SET_PDEATHSIG, SIGTERM);

    // Put the current process into a separate process group so that
    // we can kill it and all its children easily.
    if (setpgid(0, 0) != 0) {
      return Error("Could not start supervisor process.");
    }

    // Install a SIGTERM handler which will kill the current process
    // group. Since we already setup the death signal above, the
    // signal handler will be triggered when the parent (e.g., the
    // slave) exits.
    if (os::signals::install(SIGTERM, &signalHandler) != 0) {
      return Error("Could not start supervisor process.");
    }

    pid_t pid = fork();
    if (pid == -1) {
      return Error("Could not start supervisor process.");
    } else if (pid == 0) {
      // Child. This is the process that is going to exec the
      // process if zero is returned.

      // We setup death signal for the process as well in case
      // someone, though unlikely, accidentally kill the parent of
      // this process (the bookkeeping process).
      prctl(PR_SET_PDEATHSIG, SIGKILL);

      // NOTE: We don't need to clear the signal handler explicitly
      // because the subsequent 'exec' will clear them.
      return Nothing();
    } else {
      // Parent. This is the bookkeeping process which will wait for
      // the child process to finish.

      // Close the files to prevent interference on the communication
      // between the slave and the child process.
      ::close(STDIN_FILENO);
      ::close(STDOUT_FILENO);
      ::close(STDERR_FILENO);

      // Block until the child process finishes.
      int status = 0;
      if (waitpid(pid, &status, 0) == -1) {
        abort();
      }

      // Forward the exit status if the child process exits normally.
      if (WIFEXITED(status)) {
        _exit(WEXITSTATUS(status));
      }

      abort();
      UNREACHABLE();
    }
#endif // __linux__
    return Nothing();
  });
}

namespace internal {

static void cleanup(
    const Future<Option<int>>& result,
    Promise<Option<int>>* promise,
    const Subprocess& subprocess)
{
  CHECK(!result.isPending());
  CHECK(!result.isDiscarded());

  if (result.isFailed()) {
    promise->fail(result.failure());
  } else {
    promise->set(result.get());
  }

  delete promise;
}

}  // namespace internal {

// Executes a subprocess.
//
// NOTE: On Windows, components of the `path` and `argv` that need to be quoted
// are expected to have been quoted before they are passed to `subprocess. For
// example, either of these may contain paths with spaces in them, like
// `C:\"Program Files"\foo.exe`, where notably the character sequence `\"` does
// is not escaped quote, but instead a path separator and the start of a path
// component. Since the semantics of quoting are shell-dependent, it is not
// practical to attempt to re-parse the command that is passed in and properly
// escape it. Therefore, incorrectly-quoted command arguments will probably
// lead the child process to terminate with an error.
Try<Subprocess> subprocess(
    const string& path,
    vector<string> argv,
    const Subprocess::IO& in,
    const Subprocess::IO& out,
    const Subprocess::IO& err,
    const flags::FlagsBase* flags,
    const Option<map<string, string>>& environment,
    const Option<lambda::function<
        pid_t(const lambda::function<int()>&)>>& _clone,
    const vector<Subprocess::ParentHook>& parent_hooks,
    const vector<Subprocess::ChildHook>& child_hooks)
{
  // File descriptors for redirecting stdin/stdout/stderr.
  // These file descriptors are used for different purposes depending
  // on the specified I/O modes.
  // See `Subprocess::PIPE`, `Subprocess::PATH`, and `Subprocess::FD`.
  InputFileDescriptors stdinfds;
  OutputFileDescriptors stdoutfds;
  OutputFileDescriptors stderrfds;

  // Prepare the file descriptor(s) for stdin.
  Try<InputFileDescriptors> input = in.input();
  if (input.isError()) {
    return Error(input.error());
  }

  stdinfds = input.get();

  // Prepare the file descriptor(s) for stdout.
  Try<OutputFileDescriptors> output = out.output();
  if (output.isError()) {
    process::internal::close(stdinfds, stdoutfds, stderrfds);
    return Error(output.error());
  }

  stdoutfds = output.get();

  // Prepare the file descriptor(s) for stderr.
  output = err.output();
  if (output.isError()) {
    process::internal::close(stdinfds, stdoutfds, stderrfds);
    return Error(output.error());
  }

  stderrfds = output.get();

#ifndef __WINDOWS__
  // TODO(jieyu): Consider using O_CLOEXEC for atomic close-on-exec.
  Try<Nothing> cloexec = internal::cloexec(stdinfds, stdoutfds, stderrfds);
  if (cloexec.isError()) {
    process::internal::close(stdinfds, stdoutfds, stderrfds);
    return Error("Failed to cloexec: " + cloexec.error());
  }
#endif // __WINDOWS__

  // Prepare the arguments. If the user specifies the 'flags', we will
  // stringify them and append them to the existing arguments.
  if (flags != nullptr) {
    foreachvalue (const flags::Flag& flag, *flags) {
      Option<string> value = flag.stringify(*flags);
      if (value.isSome()) {
        argv.push_back("--" + flag.effective_name().value + "=" + value.get());
      }
    }
  }

  // Parent.
  Subprocess process;

  // Create child, passing in stdin/stdout/stderr handles. We store the
  // information and data structures we need to manage the lifecycle of the
  // child (e.g., the PID of the child) in `process.data`.
  //
  // NOTE: We use lexical blocking around the `#ifdef` to limit use of data
  // structures declared in the `#ifdef`. Since objects like `pid` will go out
  // of scope at the end of the block, there is no chance we will accidentally
  // define something in (say) the `__WINDOWS__` branch and then attempt to use
  // it in the non-`__WINDOWS__` branch.
  {
#ifndef __WINDOWS__
    Try<pid_t> pid = internal::cloneChild(
        path,
        argv,
        environment,
        _clone,
        parent_hooks,
        child_hooks,
        stdinfds,
        stdoutfds,
        stderrfds);

    if (pid.isError()) {
      return Error(pid.error());
    }

    process.data->pid = pid.get();
#else
    // TODO(joerg84): Consider using the childHooks and parentHooks here.
    Try<PROCESS_INFORMATION> processInformation = internal::createChildProcess(
        path, argv, environment, stdinfds, stdoutfds, stderrfds);

    if (processInformation.isError()) {
      process::internal::close(stdinfds, stdoutfds, stderrfds);
      return Error(
          "Could not launch child process" + processInformation.error());
    }

    if (processInformation.get().dwProcessId == -1) {
      // Save the errno as 'close' below might overwrite it.
      ErrnoError error("Failed to clone");
      process::internal::close(stdinfds, stdoutfds, stderrfds);
      return error;
    }

    process.data->processInformation = processInformation.get();
    process.data->pid = processInformation.get().dwProcessId;
#endif // __WINDOWS__
  }

  // Close the child-ends of the file descriptors that are created
  // by this function.
  os::close(stdinfds.read);
  os::close(stdoutfds.write);
  os::close(stderrfds.write);

  // For any pipes, store the parent side of the pipe so that
  // the user can communicate with the subprocess.
  process.data->in = stdinfds.write;
  process.data->out = stdoutfds.read;
  process.data->err = stderrfds.read;

  // Rather than directly exposing the future from process::reap, we
  // must use an explicit promise so that we can ensure we can receive
  // the termination signal. Otherwise, the caller can discard the
  // reap future, and we will not know when it is safe to close the
  // file descriptors.
  Promise<Option<int>>* promise = new Promise<Option<int>>();
  process.data->status = promise->future();

  // We need to bind a copy of this Subprocess into the onAny callback
  // below to ensure that we don't close the file descriptors before
  // the subprocess has terminated (i.e., because the caller doesn't
  // keep a copy of this Subprocess around themselves).
  process::reap(process.data->pid)
    .onAny(lambda::bind(internal::cleanup, lambda::_1, promise, process));

  return process;
}

}  // namespace process {
<|endoftext|>


<commit_before>/*
 * This source file is part of EasyPaint.
 *
 * Copyright (c) 2012 EasyPaint <https://github.com/Gr1N/EasyPaint>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <QtGui/QApplication>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QTranslator>

#include "mainwindow.h"
#include "datasingleton.h"

void printHelpMessage()
{
    qDebug()<<"EasyPaint - simple graphics painting program\n"
              "Usage: easypaint [options] [filename]\n\n"
              "Options:\n"
              "\t-h, --help\t\tshow this help message and exit\n"
              "\t-v, --version\t\tshow program's version number and exit";
}

void printVersion()
{
    qDebug()<<"0.0.1";
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    a.setApplicationName("EasyPaint");
    a.setApplicationVersion("0.0.1");

    QStringList args = a.arguments();

    QRegExp rxArgHelp("--help");
    QRegExp rxArgH("-h");
    QRegExp rxArgVersion("--version");
    QRegExp rxArgV("-v");

    bool isHelp(false), isVer(false);
    QStringList filePaths;

    for(int i(1); i < args.size(); ++i)
    {
        if (rxArgHelp.indexIn(args.at(i)) != -1  ||
                rxArgH.indexIn(args.at(i)) != -1)
        {
            isHelp = true;
        }
        else if (rxArgVersion.indexIn(args.at(i)) != -1  ||
                 rxArgV.indexIn(args.at(i)) != -1)
        {
            isVer = true;
        }
        else
        {
            if(QFile::exists(args.at(i)))
            {
                filePaths.append(args.at(i));
            }
        }

    }

    if(isHelp)
    {
        printHelpMessage();
        return 0;
    }
    else if(isVer)
    {
        printVersion();
        return 0;
    }

    QTranslator appTranslator;
    QString translationsPath("/usr/share/easypaint/translations/");
    QString appLanguage = DataSingleton::Instance()->getAppLanguage();
    if(appLanguage == "system")
    {
        appTranslator.load(translationsPath + "easypaint_" + QLocale::system().name());
    }
    else
    {
        appTranslator.load(translationsPath + appLanguage);
    }
    a.installTranslator(&appTranslator);

    MainWindow w(filePaths);
    w.show();

    return a.exec();
}
<commit_msg>Switch to version 0.1.0<commit_after>/*
 * This source file is part of EasyPaint.
 *
 * Copyright (c) 2012 EasyPaint <https://github.com/Gr1N/EasyPaint>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <QtGui/QApplication>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QTranslator>

#include "mainwindow.h"
#include "datasingleton.h"

void printHelpMessage()
{
    qDebug()<<"EasyPaint - simple graphics painting program\n"
              "Usage: easypaint [options] [filename]\n\n"
              "Options:\n"
              "\t-h, --help\t\tshow this help message and exit\n"
              "\t-v, --version\t\tshow program's version number and exit";
}

void printVersion()
{
    qDebug()<<"0.1.0";
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    a.setApplicationName("EasyPaint");
    a.setApplicationVersion("0.0.1");

    QStringList args = a.arguments();

    QRegExp rxArgHelp("--help");
    QRegExp rxArgH("-h");
    QRegExp rxArgVersion("--version");
    QRegExp rxArgV("-v");

    bool isHelp(false), isVer(false);
    QStringList filePaths;

    for(int i(1); i < args.size(); ++i)
    {
        if (rxArgHelp.indexIn(args.at(i)) != -1  ||
                rxArgH.indexIn(args.at(i)) != -1)
        {
            isHelp = true;
        }
        else if (rxArgVersion.indexIn(args.at(i)) != -1  ||
                 rxArgV.indexIn(args.at(i)) != -1)
        {
            isVer = true;
        }
        else
        {
            if(QFile::exists(args.at(i)))
            {
                filePaths.append(args.at(i));
            }
        }

    }

    if(isHelp)
    {
        printHelpMessage();
        return 0;
    }
    else if(isVer)
    {
        printVersion();
        return 0;
    }

    QTranslator appTranslator;
    QString translationsPath("/usr/share/easypaint/translations/");
    QString appLanguage = DataSingleton::Instance()->getAppLanguage();
    if(appLanguage == "system")
    {
        appTranslator.load(translationsPath + "easypaint_" + QLocale::system().name());
    }
    else
    {
        appTranslator.load(translationsPath + appLanguage);
    }
    a.installTranslator(&appTranslator);

    MainWindow w(filePaths);
    w.show();

    return a.exec();
}
<|endoftext|>


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

#include "controller.h"

#include <QtCore/QProcess>
#include <QtCore/QFileInfo>

#include <QtXml/QDomDocument>

#include <trikKernel/configurer.h>
#include <trikKernel/fileUtils.h>
#include <trikKernel/paths.h>
#include <trikKernel/exceptions/internalErrorException.h>
#include <trikControl/brickFactory.h>
#include <trikNetwork/mailboxFactory.h>
#include <trikNetwork/gamepadFactory.h>
#include <trikWiFi/trikWiFi.h>

#include "runningWidget.h"
#include "autoRunner.h"

using namespace trikGui;

const int communicatorPort = 8888;
const int telemetryPort = 9000;

Controller::Controller(const QString &configPath)
	: mBrick(trikControl::BrickFactory::create(configPath, trikKernel::Paths::mediaPath()))
{
	if (configPath.isEmpty()) {
		throw trikKernel::InternalErrorException("Config path is empty");
	}

	auto correctedConfigPath = configPath.endsWith('/') ? configPath : configPath + '/';

	trikKernel::Configurer configurer(correctedConfigPath + "system-config.xml"
			, correctedConfigPath + "model-config.xml");
	//configurer.attributeByDevice("gamepad", "optional");

	mGamepad.reset(trikNetwork::GamepadFactory::create(configurer));
	connect(mGamepad.data(), SIGNAL(disconnect()), this, SIGNAL(gamepadDisconnected()));
	connect(mGamepad.data(), SIGNAL(connected()), this, SIGNAL(gamepadConnected()));

	mMailbox.reset(trikNetwork::MailboxFactory::create(configurer));
	mTelemetry.reset(new trikTelemetry::TrikTelemetry(*mBrick, *mGamepad));
	mScriptRunner.reset(new trikScriptRunner::TrikScriptRunner(*mBrick, mMailbox.data(), mGamepad.data()));
	mCommunicator.reset(new trikCommunicator::TrikCommunicator(*mScriptRunner, configurer.version()));

	mWiFi.reset(new trikWiFi::TrikWiFi("/tmp/trikwifi", "/var/run/wpa_supplicant/wlan0", this));
	connect(mWiFi.data(), SIGNAL(connected()), this, SIGNAL(wiFiConnected()));
	connect(mWiFi.data(), SIGNAL(disconnected(trikWiFi::DisconnectReason)), this, SIGNAL(wiFiDisconnected()));

	connect(mCommunicator.data(), SIGNAL(stopCommandReceived()), this, SLOT(abortExecution()));
	connect(mCommunicator.data(), SIGNAL(connected()), this, SLOT(updateCommunicatorStatus()));
	connect(mCommunicator.data(), SIGNAL(disconnected()), this, SLOT(updateCommunicatorStatus()));
	connect(mTelemetry.data(), SIGNAL(connected()), this, SLOT(updateCommunicatorStatus()));
	connect(mTelemetry.data(), SIGNAL(disconnected()), this, SLOT(updateCommunicatorStatus()));
	connect(mMailbox.data(), SIGNAL(connectionStatusChanged(bool)), this, SIGNAL(mailboxStatusChanged(bool)));

	connect(mScriptRunner.data(), SIGNAL(completed(QString, int)), this, SLOT(scriptExecutionCompleted(QString, int)));

	connect(mScriptRunner.data(), SIGNAL(startedScript(QString, int))
			, this, SLOT(scriptExecutionFromFileStarted(QString, int)));

	connect(mScriptRunner.data(), SIGNAL(startedDirectScript(int))
			, this, SLOT(directScriptExecutionStarted(int)));

	connect(mBrick.data(), SIGNAL(stopped()), this, SIGNAL(brickStopped()));

	mCommunicator->startServer(communicatorPort);
	mTelemetry->startServer(telemetryPort);

	mAutoRunner.reset(new AutoRunner(*this));

	mBrick->led()->green();
}

Controller::~Controller()
{
	mBrick->led()->orange();
}

void Controller::runFile(const QString &filePath)
{
	QFileInfo const fileInfo(filePath);
	if (fileInfo.suffix() == "qts" || fileInfo.suffix() == "js") {
		mScriptRunner->run(trikKernel::FileUtils::readFromFile(fileInfo.canonicalFilePath()), fileInfo.baseName());
	} else if (fileInfo.suffix() == "wav" || fileInfo.suffix() == "mp3") {
		mScriptRunner->run("brick.playSound(\"" + fileInfo.canonicalFilePath() + "\");", fileInfo.baseName());
	} else if (fileInfo.suffix() == "sh") {
		QProcess::startDetached("sh", {filePath});
	} else if (fileInfo.isExecutable()) {
		QProcess::startDetached(filePath);
	}
}

void Controller::abortExecution()
{
	emit hideScriptWidgets();
	mScriptRunner->abort();

	// Now script engine will stop (after some time maybe) and send "completed" signal, which will be caught and
	// processed as if a script finished by itself.
}

trikControl::BrickInterface &Controller::brick()
{
	return *mBrick;
}

trikNetwork::MailboxInterface *Controller::mailbox()
{
	return mMailbox.data();
}

trikWiFi::TrikWiFi &Controller::wiFi()
{
	return *mWiFi;
}

bool Controller::communicatorConnectionStatus()
{
	return mTelemetry->activeConnections() > 0 && mCommunicator->activeConnections() > 0;
}

bool Controller::gamepadConnectionStatus() const
{
	if (mGamepad != nullptr){
		return mGamepad->isConnected();
	}
	return false;
}

void Controller::updateCommunicatorStatus()
{
	emit communicatorStatusChanged(communicatorConnectionStatus());
}

void Controller::scriptExecutionCompleted(const QString &error, int scriptId)
{
	if (error.isEmpty()) {
		emit hideRunningWidget(scriptId);
	} else {
		mCommunicator->sendMessage("error: " + error);
		emit showError(error, scriptId);
	}

	mBrick->reset();

	if (mMailbox) {
		mMailbox->clearQueue();
	}

	if (mGamepad) {
		mGamepad->reset();
	}

	mBrick->led()->green();
}

void Controller::scriptExecutionFromFileStarted(const QString &fileName, int scriptId)
{
	emit showRunningWidget(fileName, scriptId);
}

void Controller::directScriptExecutionStarted(int scriptId)
{
	scriptExecutionFromFileStarted(tr("direct command"), scriptId);
}
<commit_msg>fixed build<commit_after>/* Copyright 2013 - 2015 Yurii Litvinov and CyberTech Labs Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "controller.h"

#include <QtCore/QProcess>
#include <QtCore/QFileInfo>

#include <QtXml/QDomDocument>

#include <trikKernel/configurer.h>
#include <trikKernel/fileUtils.h>
#include <trikKernel/paths.h>
#include <trikKernel/exceptions/internalErrorException.h>
#include <trikControl/brickFactory.h>
#include <trikNetwork/mailboxFactory.h>
#include <trikNetwork/gamepadFactory.h>
#include <trikWiFi/trikWiFi.h>

#include "runningWidget.h"
#include "autoRunner.h"

using namespace trikGui;

const int communicatorPort = 8888;
const int telemetryPort = 9000;

Controller::Controller(const QString &configPath)
	: mBrick(trikControl::BrickFactory::create(configPath, trikKernel::Paths::mediaPath()))
{
	if (configPath.isEmpty()) {
		throw trikKernel::InternalErrorException("Config path is empty");
	}

	auto correctedConfigPath = configPath.endsWith('/') ? configPath : configPath + '/';

	trikKernel::Configurer configurer(correctedConfigPath + "system-config.xml"
			, correctedConfigPath + "model-config.xml");

	mGamepad.reset(trikNetwork::GamepadFactory::create(configurer));
	connect(mGamepad.data(), SIGNAL(disconnect()), this, SIGNAL(gamepadDisconnected()));
	connect(mGamepad.data(), SIGNAL(connected()), this, SIGNAL(gamepadConnected()));

	mMailbox.reset(trikNetwork::MailboxFactory::create(configurer));
	mTelemetry.reset(new trikTelemetry::TrikTelemetry(*mBrick, *mGamepad));
	mScriptRunner.reset(new trikScriptRunner::TrikScriptRunner(*mBrick, mMailbox.data(), mGamepad.data()));
	mCommunicator.reset(new trikCommunicator::TrikCommunicator(*mScriptRunner, configurer.version()));

	mWiFi.reset(new trikWiFi::TrikWiFi("/tmp/trikwifi", "/var/run/wpa_supplicant/wlan0", this));
	connect(mWiFi.data(), SIGNAL(connected()), this, SIGNAL(wiFiConnected()));
	connect(mWiFi.data(), SIGNAL(disconnected(trikWiFi::DisconnectReason)), this, SIGNAL(wiFiDisconnected()));

	connect(mCommunicator.data(), SIGNAL(stopCommandReceived()), this, SLOT(abortExecution()));
	connect(mCommunicator.data(), SIGNAL(connected()), this, SLOT(updateCommunicatorStatus()));
	connect(mCommunicator.data(), SIGNAL(disconnected()), this, SLOT(updateCommunicatorStatus()));
	connect(mTelemetry.data(), SIGNAL(connected()), this, SLOT(updateCommunicatorStatus()));
	connect(mTelemetry.data(), SIGNAL(disconnected()), this, SLOT(updateCommunicatorStatus()));
	connect(mMailbox.data(), SIGNAL(connectionStatusChanged(bool)), this, SIGNAL(mailboxStatusChanged(bool)));

	connect(mScriptRunner.data(), SIGNAL(completed(QString, int)), this, SLOT(scriptExecutionCompleted(QString, int)));

	connect(mScriptRunner.data(), SIGNAL(startedScript(QString, int))
			, this, SLOT(scriptExecutionFromFileStarted(QString, int)));

	connect(mScriptRunner.data(), SIGNAL(startedDirectScript(int))
			, this, SLOT(directScriptExecutionStarted(int)));

	connect(mBrick.data(), SIGNAL(stopped()), this, SIGNAL(brickStopped()));

	mCommunicator->startServer(communicatorPort);
	mTelemetry->startServer(telemetryPort);

	mAutoRunner.reset(new AutoRunner(*this));

	mBrick->led()->green();
}

Controller::~Controller()
{
	mBrick->led()->orange();
}

void Controller::runFile(const QString &filePath)
{
	QFileInfo const fileInfo(filePath);
	if (fileInfo.suffix() == "qts" || fileInfo.suffix() == "js") {
		mScriptRunner->run(trikKernel::FileUtils::readFromFile(fileInfo.canonicalFilePath()), fileInfo.baseName());
	} else if (fileInfo.suffix() == "wav" || fileInfo.suffix() == "mp3") {
		mScriptRunner->run("brick.playSound(\"" + fileInfo.canonicalFilePath() + "\");", fileInfo.baseName());
	} else if (fileInfo.suffix() == "sh") {
		QProcess::startDetached("sh", {filePath});
	} else if (fileInfo.isExecutable()) {
		QProcess::startDetached(filePath);
	}
}

void Controller::abortExecution()
{
	emit hideScriptWidgets();
	mScriptRunner->abort();

	// Now script engine will stop (after some time maybe) and send "completed" signal, which will be caught and
	// processed as if a script finished by itself.
}

trikControl::BrickInterface &Controller::brick()
{
	return *mBrick;
}

trikNetwork::MailboxInterface *Controller::mailbox()
{
	return mMailbox.data();
}

trikWiFi::TrikWiFi &Controller::wiFi()
{
	return *mWiFi;
}

bool Controller::communicatorConnectionStatus()
{
	return mTelemetry->activeConnections() > 0 && mCommunicator->activeConnections() > 0;
}

bool Controller::gamepadConnectionStatus() const
{
	if (mGamepad != nullptr) {
		return mGamepad->isConnected();
	} else {
	return false;
	}
}

void Controller::updateCommunicatorStatus()
{
	emit communicatorStatusChanged(communicatorConnectionStatus());
}

void Controller::scriptExecutionCompleted(const QString &error, int scriptId)
{
	if (error.isEmpty()) {
		emit hideRunningWidget(scriptId);
	} else {
		mCommunicator->sendMessage("error: " + error);
		emit showError(error, scriptId);
	}

	mBrick->reset();

	if (mMailbox) {
		mMailbox->clearQueue();
	}

	if (mGamepad) {
		mGamepad->reset();
	}

	mBrick->led()->green();
}

void Controller::scriptExecutionFromFileStarted(const QString &fileName, int scriptId)
{
	emit showRunningWidget(fileName, scriptId);
}

void Controller::directScriptExecutionStarted(int scriptId)
{
	scriptExecutionFromFileStarted(tr("direct command"), scriptId);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: edittoolbarcontroller.cxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"

#ifndef __FRAMEWORK_UIELEMENT_EDITTOOLBARCONTROLLER_HXX
#include "uielement/edittoolbarcontroller.hxx"
#endif

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_TOOLBAR_HXX_
#include "uielement/toolbar.hxx"
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/frame/status/ItemStatus.hpp>
#include <com/sun/star/frame/status/ItemState.hpp>
#include <com/sun/star/frame/status/Visibility.hpp>
#include <com/sun/star/frame/XControlNotificationListener.hpp>

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________
#include <svtools/toolboxcontroller.hxx>
#include <vos/mutex.hxx>
#include <vcl/svapp.hxx>
#ifndef _VCL_MNEMONIC_HXX_
#include <vcl/mnemonic.hxx>
#endif
#include <tools/urlobj.hxx>

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::frame::status;
using namespace ::com::sun::star::util;

namespace framework
{

// ------------------------------------------------------------------

// Wrapper class to notify controller about events from edit.
// Unfortunaltly the events are notifed through virtual methods instead
// of Listeners.

class EditControl : public Edit
{
    public:
        EditControl( Window* pParent, WinBits nStyle, IEditListener* pEditListener );
        virtual ~EditControl();

        virtual void Modify();
        virtual void KeyInput( const ::KeyEvent& rKEvt );
        virtual void GetFocus();
        virtual void LoseFocus();
        virtual long PreNotify( NotifyEvent& rNEvt );

    private:
        IEditListener* m_pEditListener;
};

EditControl::EditControl( Window* pParent, WinBits nStyle, IEditListener* pEditListener ) :
    Edit( pParent, nStyle )
    , m_pEditListener( pEditListener )
{
}

EditControl::~EditControl()
{
    m_pEditListener = 0;
}

void EditControl::Modify()
{
    Edit::Modify();
    if ( m_pEditListener )
        m_pEditListener->Modify();
}

void EditControl::KeyInput( const ::KeyEvent& rKEvt )
{
    Edit::KeyInput( rKEvt );
    if ( m_pEditListener )
        m_pEditListener->KeyInput( rKEvt );
}

void EditControl::GetFocus()
{
    Edit::GetFocus();
    if ( m_pEditListener )
        m_pEditListener->GetFocus();
}

void EditControl::LoseFocus()
{
    Edit::LoseFocus();
    if ( m_pEditListener )
        m_pEditListener->LoseFocus();
}

long EditControl::PreNotify( NotifyEvent& rNEvt )
{
    long nRet( 0 );
    if ( m_pEditListener )
        nRet = m_pEditListener->PreNotify( rNEvt );
    if ( nRet == 0 )
        nRet = Edit::PreNotify( rNEvt );

    return nRet;
}

// ------------------------------------------------------------------

EditToolbarController::EditToolbarController(
    const Reference< XMultiServiceFactory >& rServiceManager,
    const Reference< XFrame >&               rFrame,
    ToolBox*                                 pToolbar,
    USHORT                                   nID,
    sal_Int32                                nWidth,
    const OUString&                          aCommand ) :
    ComplexToolbarController( rServiceManager, rFrame, pToolbar, nID, aCommand )
    ,   m_pEditControl( 0 )
{
    m_pEditControl = new EditControl( m_pToolbar, WB_BORDER, this );
    if ( nWidth == 0 )
        nWidth = 100;

    // Calculate height of the edit field according to the application font height
    sal_Int32 nHeight = getFontSizePixel( m_pEditControl ) + 6 + 1;

    m_pEditControl->SetSizePixel( ::Size( nWidth, nHeight ));
    m_pToolbar->SetItemWindow( m_nID, m_pEditControl );
}

// ------------------------------------------------------------------

EditToolbarController::~EditToolbarController()
{
}

// ------------------------------------------------------------------

void SAL_CALL EditToolbarController::dispose()
throw ( RuntimeException )
{
    vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );

    m_pToolbar->SetItemWindow( m_nID, 0 );
    delete m_pEditControl;

    ComplexToolbarController::dispose();

    m_pEditControl = 0;
}

// ------------------------------------------------------------------

void SAL_CALL EditToolbarController::execute( sal_Int16 KeyModifier )
throw ( RuntimeException )
{
    Reference< XDispatch >       xDispatch;
    Reference< XURLTransformer > xURLTransformer;
    OUString                     aCommandURL;
    OUString                     aSelectedText;
    ::com::sun::star::util::URL  aTargetURL;

    {
        vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );

        if ( m_bDisposed )
            throw DisposedException();

        if ( m_bInitialized &&
             m_xFrame.is() &&
             m_xServiceManager.is() &&
             m_aCommandURL.getLength() )
        {
            xURLTransformer = m_xURLTransformer;
            xDispatch = getDispatchFromCommand( m_aCommandURL );
            aCommandURL = m_aCommandURL;
            aTargetURL = getInitializedURL();
            aSelectedText = m_pEditControl->GetText();
        }
    }

    if ( xDispatch.is() && aTargetURL.Complete.getLength() > 0 )
    {
        Sequence<PropertyValue>   aArgs( 2 );

        // Add key modifier to argument list
        aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" ));
        aArgs[0].Value <<= KeyModifier;
        aArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" ));
        aArgs[1].Value <<= aSelectedText;

        // Execute dispatch asynchronously
        ExecuteInfo* pExecuteInfo = new ExecuteInfo;
        pExecuteInfo->xDispatch     = xDispatch;
        pExecuteInfo->aTargetURL    = aTargetURL;
        pExecuteInfo->aArgs         = aArgs;
        Application::PostUserEvent( STATIC_LINK(0, ComplexToolbarController , ExecuteHdl_Impl), pExecuteInfo );
    }
}

// ------------------------------------------------------------------

void EditToolbarController::Modify()
{
    notifyTextChanged( m_pEditControl->GetText() );
}

void EditToolbarController::KeyInput( const ::KeyEvent& /*rKEvt*/ )
{
}

void EditToolbarController::GetFocus()
{
    notifyFocusGet();
}

void EditToolbarController::LoseFocus()
{
    notifyFocusLost();
}

long EditToolbarController::PreNotify( NotifyEvent& rNEvt )
{
    if( rNEvt.GetType() == EVENT_KEYINPUT )
    {
        const ::KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
        const KeyCode& rKeyCode = pKeyEvent->GetKeyCode();
        if(( rKeyCode.GetModifier() | rKeyCode.GetCode()) == KEY_RETURN )
        {
            // Call execute only with non-empty text
            if ( m_pEditControl->GetText().Len() > 0 )
                execute( rKeyCode.GetModifier() );
            return 1;
        }
    }

    return 0;
}

// --------------------------------------------------------

void EditToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand& rControlCommand )
{
    if ( rControlCommand.Command.equalsAsciiL( "SetText", 7 ))
    {
        for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
        {
            if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 ))
            {
                rtl::OUString aText;
                rControlCommand.Arguments[i].Value >>= aText;
                m_pEditControl->SetText( aText );

                // send notification
                notifyTextChanged( aText );
                break;
            }
        }
    }
}

} // namespace
<commit_msg>INTEGRATION: CWS obo30 (1.5.40); FILE MERGED 2008/06/05 14:55:31 obo 1.5.40.2: #i90100# missing EOL 2008/05/29 14:43:45 obo 1.5.40.1: #i90100# ambigous Reference during ENABLE_PCH build<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: edittoolbarcontroller.cxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"

#ifndef __FRAMEWORK_UIELEMENT_EDITTOOLBARCONTROLLER_HXX
#include "uielement/edittoolbarcontroller.hxx"
#endif

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_TOOLBAR_HXX_
#include "uielement/toolbar.hxx"
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/frame/status/ItemStatus.hpp>
#include <com/sun/star/frame/status/ItemState.hpp>
#include <com/sun/star/frame/status/Visibility.hpp>
#include <com/sun/star/frame/XControlNotificationListener.hpp>

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________
#include <svtools/toolboxcontroller.hxx>
#include <vos/mutex.hxx>
#include <vcl/svapp.hxx>
#ifndef _VCL_MNEMONIC_HXX_
#include <vcl/mnemonic.hxx>
#endif
#include <tools/urlobj.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::frame::status;
using namespace ::com::sun::star::util;

namespace framework
{

// ------------------------------------------------------------------

// Wrapper class to notify controller about events from edit.
// Unfortunaltly the events are notifed through virtual methods instead
// of Listeners.

class EditControl : public Edit
{
    public:
        EditControl( Window* pParent, WinBits nStyle, IEditListener* pEditListener );
        virtual ~EditControl();

        virtual void Modify();
        virtual void KeyInput( const ::KeyEvent& rKEvt );
        virtual void GetFocus();
        virtual void LoseFocus();
        virtual long PreNotify( NotifyEvent& rNEvt );

    private:
        IEditListener* m_pEditListener;
};

EditControl::EditControl( Window* pParent, WinBits nStyle, IEditListener* pEditListener ) :
    Edit( pParent, nStyle )
    , m_pEditListener( pEditListener )
{
}

EditControl::~EditControl()
{
    m_pEditListener = 0;
}

void EditControl::Modify()
{
    Edit::Modify();
    if ( m_pEditListener )
        m_pEditListener->Modify();
}

void EditControl::KeyInput( const ::KeyEvent& rKEvt )
{
    Edit::KeyInput( rKEvt );
    if ( m_pEditListener )
        m_pEditListener->KeyInput( rKEvt );
}

void EditControl::GetFocus()
{
    Edit::GetFocus();
    if ( m_pEditListener )
        m_pEditListener->GetFocus();
}

void EditControl::LoseFocus()
{
    Edit::LoseFocus();
    if ( m_pEditListener )
        m_pEditListener->LoseFocus();
}

long EditControl::PreNotify( NotifyEvent& rNEvt )
{
    long nRet( 0 );
    if ( m_pEditListener )
        nRet = m_pEditListener->PreNotify( rNEvt );
    if ( nRet == 0 )
        nRet = Edit::PreNotify( rNEvt );

    return nRet;
}

// ------------------------------------------------------------------

EditToolbarController::EditToolbarController(
    const Reference< XMultiServiceFactory >& rServiceManager,
    const Reference< XFrame >&               rFrame,
    ToolBox*                                 pToolbar,
    USHORT                                   nID,
    sal_Int32                                nWidth,
    const ::rtl::OUString&                          aCommand ) :
    ComplexToolbarController( rServiceManager, rFrame, pToolbar, nID, aCommand )
    ,   m_pEditControl( 0 )
{
    m_pEditControl = new EditControl( m_pToolbar, WB_BORDER, this );
    if ( nWidth == 0 )
        nWidth = 100;

    // Calculate height of the edit field according to the application font height
    sal_Int32 nHeight = getFontSizePixel( m_pEditControl ) + 6 + 1;

    m_pEditControl->SetSizePixel( ::Size( nWidth, nHeight ));
    m_pToolbar->SetItemWindow( m_nID, m_pEditControl );
}

// ------------------------------------------------------------------

EditToolbarController::~EditToolbarController()
{
}

// ------------------------------------------------------------------

void SAL_CALL EditToolbarController::dispose()
throw ( RuntimeException )
{
    vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );

    m_pToolbar->SetItemWindow( m_nID, 0 );
    delete m_pEditControl;

    ComplexToolbarController::dispose();

    m_pEditControl = 0;
}

// ------------------------------------------------------------------

void SAL_CALL EditToolbarController::execute( sal_Int16 KeyModifier )
throw ( RuntimeException )
{
    Reference< XDispatch >       xDispatch;
    Reference< XURLTransformer > xURLTransformer;
    ::rtl::OUString                     aCommandURL;
    ::rtl::OUString                     aSelectedText;
    ::com::sun::star::util::URL  aTargetURL;

    {
        vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );

        if ( m_bDisposed )
            throw DisposedException();

        if ( m_bInitialized &&
             m_xFrame.is() &&
             m_xServiceManager.is() &&
             m_aCommandURL.getLength() )
        {
            xURLTransformer = m_xURLTransformer;
            xDispatch = getDispatchFromCommand( m_aCommandURL );
            aCommandURL = m_aCommandURL;
            aTargetURL = getInitializedURL();
            aSelectedText = m_pEditControl->GetText();
        }
    }

    if ( xDispatch.is() && aTargetURL.Complete.getLength() > 0 )
    {
        Sequence<PropertyValue>   aArgs( 2 );

        // Add key modifier to argument list
        aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" ));
        aArgs[0].Value <<= KeyModifier;
        aArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" ));
        aArgs[1].Value <<= aSelectedText;

        // Execute dispatch asynchronously
        ExecuteInfo* pExecuteInfo = new ExecuteInfo;
        pExecuteInfo->xDispatch     = xDispatch;
        pExecuteInfo->aTargetURL    = aTargetURL;
        pExecuteInfo->aArgs         = aArgs;
        Application::PostUserEvent( STATIC_LINK(0, ComplexToolbarController , ExecuteHdl_Impl), pExecuteInfo );
    }
}

// ------------------------------------------------------------------

void EditToolbarController::Modify()
{
    notifyTextChanged( m_pEditControl->GetText() );
}

void EditToolbarController::KeyInput( const ::KeyEvent& /*rKEvt*/ )
{
}

void EditToolbarController::GetFocus()
{
    notifyFocusGet();
}

void EditToolbarController::LoseFocus()
{
    notifyFocusLost();
}

long EditToolbarController::PreNotify( NotifyEvent& rNEvt )
{
    if( rNEvt.GetType() == EVENT_KEYINPUT )
    {
        const ::KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
        const KeyCode& rKeyCode = pKeyEvent->GetKeyCode();
        if(( rKeyCode.GetModifier() | rKeyCode.GetCode()) == KEY_RETURN )
        {
            // Call execute only with non-empty text
            if ( m_pEditControl->GetText().Len() > 0 )
                execute( rKeyCode.GetModifier() );
            return 1;
        }
    }

    return 0;
}

// --------------------------------------------------------

void EditToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand& rControlCommand )
{
    if ( rControlCommand.Command.equalsAsciiL( "SetText", 7 ))
    {
        for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
        {
            if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 ))
            {
                rtl::OUString aText;
                rControlCommand.Arguments[i].Value >>= aText;
                m_pEditControl->SetText( aText );

                // send notification
                notifyTextChanged( aText );
                break;
            }
        }
    }
}

} // namespace

<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/plat/pegasus/prdfDramRepairs.C $            */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2012,2014              */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

/** @file prdfDramRepairs.C */

#include <diag/prdf/prdfMain.H>
#include <diag/prdf/common/prdf_service_codes.H>
#include "common/iipconst.h"
#include <prdfGlobal.H>
#include <prdfTrace.H>
#include <prdfErrlUtil.H>
#include "common/prdfEnums.H"
#include "common/plat/pegasus/prdfCenMbaCaptureData.H"
#include "common/plat/pegasus/prdfCalloutUtil.H"
#include "common/plat/pegasus/prdfCenDqBitmap.H"
#include "common/plat/pegasus/prdfCenMarkstore.H"
#include "common/plat/pegasus/prdfCenMbaExtraSig.H"
#include "common/plat/pegasus/prdfCenSymbol.H"
#include "common/plat/pegasus/prdfMemoryMru.H"
#include "framework/service/prdfPlatServices.H"
#include "plat/pegasus/prdfPlatCalloutUtil.H"

using namespace HWAS;
using namespace std;
using namespace TARGETING;

namespace PRDF
{

using namespace PlatServices;

namespace RDR // local utility functions to support PRDF::restoreDramRepairs()
{

// Creates and returns an error log.
errlHndl_t createErrl( uint32_t i_reasonCode, TargetHandle_t i_mba,
                       uint32_t i_signature )
{
    uint64_t userdata12 = PRDF_GET_UINT64_FROM_UINT32( getHuid(i_mba), 0 );
    uint64_t userdata34 = PRDF_GET_UINT64_FROM_UINT32( i_signature,    0 );

    // Note that the error log tags are not needed because PRD uses its own
    // signature parser.

    return new ERRORLOG::ErrlEntry(
                            ERRORLOG::ERRL_SEV_PREDICTIVE,  // severity
                            PRDF_RESTORE_DRAM_REPAIR,       // module ID
                            i_reasonCode,                   // reason code
                            userdata12,                     // user data 1 & 2
                            userdata34 );                   // user data 3 & 4
}

//------------------------------------------------------------------------------

// If an error log is given, will add DRAM repairs FFDC and traces to error log,
// then commit the error log.
void commitErrl( errlHndl_t i_errl, TargetHandle_t i_mba )
{
    if ( NULL != i_errl )
    {
        // Add capture data
        CenMbaCaptureData::addMemEccData( i_mba, i_errl );

        // Add traces
        i_errl->collectTrace( PRDF_COMP_NAME, 512 );

        // Commit the error log
        ERRORLOG::errlCommit( i_errl, PRDF_COMP_ID );
    }
}

//------------------------------------------------------------------------------

// If there were analysis errors, will create and commit an error log with 2nd
// level support callout.
void commitSoftError( uint32_t i_reasonCode, TargetHandle_t i_mba,
                      uint32_t i_signature, bool i_analysisErrors )
{
    if ( i_analysisErrors )
    {
        errlHndl_t errl = createErrl( i_reasonCode, i_mba, i_signature );
        errl->addProcedureCallout( EPUB_PRC_LVL_SUPP, SRCI_PRIORITY_HIGH );
        commitErrl( errl, i_mba );
    }
}

//------------------------------------------------------------------------------

bool processRepairedRanks( TargetHandle_t i_mba, uint8_t i_repairedRankMask )
{
    #define PRDF_FUNC "[processRepairedRanks] "

    // The bits in i_repairedRankMask represent ranks that have repairs. Query
    // hardware and compare against RAS policies.

    bool o_calloutMade  = false;
    bool analysisErrors = false;

    errlHndl_t errl = NULL; // Initially NULL, will create if needed.

    for ( uint8_t r = 0; r < MASTER_RANKS_PER_MBA; ++r )
    {
        if ( 0 == (i_repairedRankMask & (0x80 >> r)) )
        {
            continue; // this rank didn't have any repairs
        }

        CenRank rank ( r );
        CenMark mark;

        if ( SUCCESS != mssGetMarkStore(i_mba, rank, mark) )
        {
            PRDF_ERR( PRDF_FUNC"mssGetMarkStore() failed: MBA=0x%08x rank=%d",
                      getHuid(i_mba), rank.getMaster() );
            analysisErrors = true;
            continue; // skip this rank
        }

        CenSymbol sp0, sp1, sp;

        if ( SUCCESS != mssGetSteerMux(i_mba, rank, sp0, sp1, sp))
        {
            PRDF_ERR( PRDF_FUNC"mssGetSteerMux() failed: MBA=0x%08x rank=%d",
                      getHuid(i_mba), rank.getMaster() );
            analysisErrors = true;
            continue; // skip this rank
        }

        if ( (sp0.isValid() || sp1.isValid() || sp.isValid()) &&
             mark.getCM().isValid() )
        {
            // This rank has both a steer and a chip mark. Call out the DIMM
            // with the chip mark.

            if ( NULL == errl )
            {
                errl = createErrl( PRDF_DETECTED_FAIL_HARDWARE, i_mba,
                                   PRDFSIG_RdrRepairsUsed );
            }

            MemoryMru memoryMru( i_mba, rank, mark.getCM() );
            CalloutUtil::calloutMemoryMru( errl, memoryMru,
                                           SRCI_PRIORITY_HIGH,
                                           HWAS::DELAYED_DECONFIG,
                                           HWAS::GARD_Predictive );
            o_calloutMade = true;
        }
    }

    // Commit the error log, if needed.
    commitErrl( errl, i_mba );

    // Commit an additional error log indicating something failed in the
    // analysis, if needed.
    commitSoftError( PRDF_DETECTED_FAIL_SOFTWARE, i_mba,
                     PRDFSIG_RdrInternalFail, analysisErrors );

    return o_calloutMade;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

bool processBadDimms( TargetHandle_t i_mba, uint8_t i_badDimmMask )
{
    #define PRDF_FUNC "[processBadDimms] "

    // The bits in i_badDimmMask represent DIMMs that have exceeded the
    // available repairs. Callout these DIMMs.

    bool o_calloutMade  = false;
    bool analysisErrors = false;

    errlHndl_t errl = NULL; // Initially NULL, will create if needed.

    // Iterate the list of all DIMMs be
    TargetHandleList dimms = getConnected( i_mba, TYPE_DIMM );
    for ( TargetHandleList::iterator i = dimms.begin(); i < dimms.end(); i++ )
    {
        uint8_t port = 0, dimm = 0;

        if ( SUCCESS != getMbaPort(*i, port) )
        {
            PRDF_ERR( PRDF_FUNC"getMbaPort() failed: DIMM=0x%08x", getHuid(*i));
            analysisErrors = true;
            continue; // skip this dimm
        }

        if ( SUCCESS != getMbaDimm(*i, dimm) )
        {
            PRDF_ERR( PRDF_FUNC"getMbaDimm() failed: DIMM=0x%08x", getHuid(*i));
            analysisErrors = true;
            continue; // skip this dimm
        }

        // The 4 bits of i_badDimmMask is defined as p0d0, p0d1, p1d0, and p1d1.
        uint8_t mask = 0x8 >> (port * PORT_SLCT_PER_MBA + dimm);

        if ( 0 != (i_badDimmMask & mask) )
        {
            if ( NULL == errl )
            {
                errl = createErrl( PRDF_DETECTED_FAIL_HARDWARE, i_mba,
                                   PRDFSIG_RdrRepairUnavail );
            }

            o_calloutMade = true;
            errl->addHwCallout( *i, SRCI_PRIORITY_HIGH, HWAS::DELAYED_DECONFIG,
                                HWAS::GARD_Predictive );
        }
    }

    // Commit the error log, if needed.
    commitErrl( errl, i_mba );

    // Commit an additional error log indicating something failed in the
    // analysis, if needed.
    commitSoftError( PRDF_DETECTED_FAIL_SOFTWARE, i_mba,
                     PRDFSIG_RdrInternalFail, analysisErrors );

    return o_calloutMade;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

bool screenBadDqs( TargetHandle_t i_mba, const std::vector<CenRank> & i_ranks )
{
    #define PRDF_FUNC "[screenBadDqs] "

    // Callout any attached DIMMs that have any bad DQs.

    bool o_calloutMade  = false;
    bool analysisErrors = false;

    for ( std::vector<CenRank>::const_iterator rank = i_ranks.begin();
          rank != i_ranks.end(); rank++ )
    {
        // The HW procedure to read the bad DQ attribute will callout the DIMM
        // if it has DRAM Repairs VPD and the DISABLE_DRAM_REPAIRS MNFG policy
        // flag is set. PRD will simply need to iterate through all the ranks
        // to ensure all DIMMs are screen and the procedure will do the rest.

        CenDqBitmap bitmap;
        if ( SUCCESS != getBadDqBitmap(i_mba, *rank, bitmap, true) )
        {
            PRDF_ERR( PRDF_FUNC"getBadDqBitmap() failed: MBA=0x%08x rank=%d",
                      getHuid(i_mba), rank->getMaster() );
            analysisErrors = true;
            continue; // skip this rank
        }
    }

    // Commit an additional error log indicating something failed in the
    // analysis, if needed.
    commitSoftError( PRDF_DETECTED_FAIL_SOFTWARE, i_mba,
                     PRDFSIG_RdrInternalFail, analysisErrors );

    return o_calloutMade;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

void deployDramSpares( TargetHandle_t i_mba,
                       const std::vector<CenRank> & i_ranks )
{
    bool x4 = isDramWidthX4(i_mba);

    for ( std::vector<CenRank>::const_iterator rank = i_ranks.begin();
          rank != i_ranks.end(); rank++ )
    {
        // Doesn't matter which DRAM is spared as long as they are all spared.
        // Also, make sure the ECC spare is on a different DRAM than the spare
        // DRAM.
        CenSymbol symPort0 = CenSymbol::fromDimmDq( i_mba, *rank, 0, 0 );
        CenSymbol symPort1 = CenSymbol::fromDimmDq( i_mba, *rank, 0, 1 );
        CenSymbol symEccSp = CenSymbol::fromDimmDq( i_mba, *rank, 8, 0 );

        int32_t l_rc = SUCCESS;

        l_rc  = mssSetSteerMux( i_mba, *rank, symPort0, false );
        l_rc |= mssSetSteerMux( i_mba, *rank, symPort1, false );

        if ( x4 )
            l_rc |= mssSetSteerMux( i_mba, *rank, symEccSp, true );

        if ( SUCCESS != l_rc )
        {
            // mssSetSteerMux() will print a trace and commit the error log,
            // however, we need to handle the return code or we get a compile
            // warning in Hostboot.
            continue;
        }
    }
}

} // end namespace RDR

//------------------------------------------------------------------------------
// External functions - declared in prdfMain.H
//------------------------------------------------------------------------------

int32_t restoreDramRepairs( TargetHandle_t i_mba )
{
    #define PRDF_FUNC "PRDF::restoreDramRepairs"

    PRDF_ENTER( PRDF_FUNC"(0x%08x)", getHuid(i_mba) );

    // will unlock when going out of scope
    PRDF_SYSTEM_SCOPELOCK;

    bool calloutMade = false;

    do
    {
        std::vector<CenRank> ranks;
        int32_t l_rc = getMasterRanks( i_mba, ranks );
        if ( SUCCESS != l_rc )
        {
            PRDF_ERR( "["PRDF_FUNC"] getMasterRanks() failed" );

            RDR::commitSoftError( PRDF_DETECTED_FAIL_SOFTWARE, i_mba,
                                  PRDFSIG_RdrInternalFail, true );

            break; // Assume user meant to disable DRAM repairs.
        }

        bool spareDramDeploy = mnfgSpareDramDeploy();

        if ( spareDramDeploy )
        {
            // Deploy all spares for MNFG corner tests.
            RDR::deployDramSpares( i_mba, ranks );
        }

        if ( areDramRepairsDisabled() )
        {
            // DRAM Repairs are disabled in MNFG mode, so screen all DIMMs with
            // VPD information.
            if ( RDR::screenBadDqs(i_mba, ranks) ) calloutMade = true;

            // No need to continue because there will not be anything to
            // restore.
            break;
        }

        if ( spareDramDeploy )
        {
            // This is an error. The MNFG spare DRAM deply bit is set, but DRAM
            // Repairs have not been disabled.

            PRDF_ERR( "["PRDF_FUNC"] MNFG spare deploy enabled, but DRAM "
                      "repairs are not disabled" );

            RDR::commitSoftError( PRDF_INVALID_CONFIG, i_mba,
                                  PRDFSIG_RdrInvalidConfig, true );

            break; // Assume user meant to disable DRAM repairs.
        }

        uint8_t rankMask = 0, dimmMask = 0;
        if ( SUCCESS != mssRestoreDramRepairs(i_mba, rankMask, dimmMask) )
        {
            // Can't check anything if this doesn't work.
            PRDF_ERR( "["PRDF_FUNC"] mssRestoreDramRepairs() failed" );
            break;
        }

        // Callout DIMMs with too many bad bits and not enough repairs available
        if ( RDR::processBadDimms(i_mba, dimmMask) ) calloutMade = true;

        // Check repaired ranks for RAS policy violations.
        if ( RDR::processRepairedRanks(i_mba, rankMask) ) calloutMade = true;

    } while(0);

    PRDF_EXIT( PRDF_FUNC"(0x%08x)", getHuid(i_mba) );

    return calloutMade ? FAIL : SUCCESS;

    #undef PRDF_FUNC
}

} // end namespace PRDF

<commit_msg>PRD: add IS DIMM support for restore DRAM repairs<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/plat/pegasus/prdfDramRepairs.C $            */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2013,2014                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

/** @file prdfDramRepairs.C */

#include <diag/prdf/prdfMain.H>
#include <diag/prdf/common/prdf_service_codes.H>
#include "common/iipconst.h"
#include <prdfGlobal.H>
#include <prdfTrace.H>
#include <prdfErrlUtil.H>
#include "common/prdfEnums.H"
#include "common/plat/pegasus/prdfCenMbaCaptureData.H"
#include "common/plat/pegasus/prdfCalloutUtil.H"
#include "common/plat/pegasus/prdfCenDqBitmap.H"
#include "common/plat/pegasus/prdfCenMarkstore.H"
#include "common/plat/pegasus/prdfCenMbaExtraSig.H"
#include "common/plat/pegasus/prdfCenSymbol.H"
#include "common/plat/pegasus/prdfMemoryMru.H"
#include "framework/service/prdfPlatServices.H"
#include "plat/pegasus/prdfPlatCalloutUtil.H"

using namespace HWAS;
using namespace std;
using namespace TARGETING;

namespace PRDF
{

using namespace PlatServices;

namespace RDR // local utility functions to support PRDF::restoreDramRepairs()
{

// Creates and returns an error log.
errlHndl_t createErrl( uint32_t i_reasonCode, TargetHandle_t i_mba,
                       uint32_t i_signature )
{
    uint64_t userdata12 = PRDF_GET_UINT64_FROM_UINT32( getHuid(i_mba), 0 );
    uint64_t userdata34 = PRDF_GET_UINT64_FROM_UINT32( i_signature,    0 );

    // Note that the error log tags are not needed because PRD uses its own
    // signature parser.

    return new ERRORLOG::ErrlEntry(
                            ERRORLOG::ERRL_SEV_PREDICTIVE,  // severity
                            PRDF_RESTORE_DRAM_REPAIR,       // module ID
                            i_reasonCode,                   // reason code
                            userdata12,                     // user data 1 & 2
                            userdata34 );                   // user data 3 & 4
}

//------------------------------------------------------------------------------

// If an error log is given, will add DRAM repairs FFDC and traces to error log,
// then commit the error log.
void commitErrl( errlHndl_t i_errl, TargetHandle_t i_mba )
{
    if ( NULL != i_errl )
    {
        // Add capture data
        CenMbaCaptureData::addMemEccData( i_mba, i_errl );

        // Add traces
        i_errl->collectTrace( PRDF_COMP_NAME, 512 );

        // Commit the error log
        ERRORLOG::errlCommit( i_errl, PRDF_COMP_ID );
    }
}

//------------------------------------------------------------------------------

// If there were analysis errors, will create and commit an error log with 2nd
// level support callout.
void commitSoftError( uint32_t i_reasonCode, TargetHandle_t i_mba,
                      uint32_t i_signature, bool i_analysisErrors )
{
    if ( i_analysisErrors )
    {
        errlHndl_t errl = createErrl( i_reasonCode, i_mba, i_signature );
        errl->addProcedureCallout( EPUB_PRC_LVL_SUPP, SRCI_PRIORITY_HIGH );
        commitErrl( errl, i_mba );
    }
}

//------------------------------------------------------------------------------

bool processRepairedRanks( TargetHandle_t i_mba, uint8_t i_repairedRankMask )
{
    #define PRDF_FUNC "[processRepairedRanks] "

    // The bits in i_repairedRankMask represent ranks that have repairs. Query
    // hardware and compare against RAS policies.

    bool o_calloutMade  = false;
    bool analysisErrors = false;

    errlHndl_t errl = NULL; // Initially NULL, will create if needed.

    bool isCen = false;
    int32_t l_rc = isMembufOnDimm( i_mba, isCen );
    if ( SUCCESS != l_rc )
    {
        PRDF_ERR( PRDF_FUNC"isMembufOnDimm() failed" );
        analysisErrors = true;
    }
    else
    {
        bool isX4 = isDramWidthX4( i_mba );

        for ( uint8_t r = 0; r < MASTER_RANKS_PER_MBA; ++r )
        {
            if ( 0 == (i_repairedRankMask & (0x80 >> r)) )
            {
                continue; // this rank didn't have any repairs
            }

            CenRank rank ( r );
            CenMark mark;

            if ( SUCCESS != mssGetMarkStore(i_mba, rank, mark) )
            {
                PRDF_ERR( PRDF_FUNC"mssGetMarkStore() failed: MBA=0x%08x "
                          "rank=%d", getHuid(i_mba), rank.getMaster() );
                analysisErrors = true;
                continue; // skip this rank
            }

            CenSymbol sp0, sp1, ecc;

            if ( SUCCESS != mssGetSteerMux(i_mba, rank, sp0, sp1, ecc) )
            {
                PRDF_ERR( PRDF_FUNC"mssGetSteerMux() failed: MBA=0x%08x "
                          "rank=%d", getHuid(i_mba), rank.getMaster() );
                analysisErrors = true;
                continue; // skip this rank
            }

            if ( mark.getCM().isValid()                       && // chip mark
                 ( isCen || mark.getSM().isValid()          ) && // symbol mark
                 (!isCen || (sp0.isValid() || sp1.isValid())) && // DRAM spare
                 (!isX4  || ecc.isValid()                   ) )  // ECC spare
            {
                // This rank has both a steer and a chip mark. Call out the DIMM
                // with the chip mark.

                if ( NULL == errl )
                {
                    errl = createErrl( PRDF_DETECTED_FAIL_HARDWARE, i_mba,
                                       PRDFSIG_RdrRepairsUsed );
                }

                MemoryMru memoryMru( i_mba, rank, mark.getCM() );
                CalloutUtil::calloutMemoryMru( errl, memoryMru,
                                               SRCI_PRIORITY_HIGH,
                                               HWAS::DELAYED_DECONFIG,
                                               HWAS::GARD_Predictive );
                o_calloutMade = true;
            }
        }
    }

    // Commit the error log, if needed.
    commitErrl( errl, i_mba );

    // Commit an additional error log indicating something failed in the
    // analysis, if needed.
    commitSoftError( PRDF_DETECTED_FAIL_SOFTWARE, i_mba,
                     PRDFSIG_RdrInternalFail, analysisErrors );

    return o_calloutMade;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

bool processBadDimms( TargetHandle_t i_mba, uint8_t i_badDimmMask )
{
    #define PRDF_FUNC "[processBadDimms] "

    // The bits in i_badDimmMask represent DIMMs that have exceeded the
    // available repairs. Callout these DIMMs.

    bool o_calloutMade  = false;
    bool analysisErrors = false;

    errlHndl_t errl = NULL; // Initially NULL, will create if needed.

    // Iterate the list of all DIMMs be
    TargetHandleList dimms = getConnected( i_mba, TYPE_DIMM );
    for ( TargetHandleList::iterator i = dimms.begin(); i < dimms.end(); i++ )
    {
        uint8_t port = 0, dimm = 0;

        if ( SUCCESS != getMbaPort(*i, port) )
        {
            PRDF_ERR( PRDF_FUNC"getMbaPort() failed: DIMM=0x%08x", getHuid(*i));
            analysisErrors = true;
            continue; // skip this dimm
        }

        if ( SUCCESS != getMbaDimm(*i, dimm) )
        {
            PRDF_ERR( PRDF_FUNC"getMbaDimm() failed: DIMM=0x%08x", getHuid(*i));
            analysisErrors = true;
            continue; // skip this dimm
        }

        // The 4 bits of i_badDimmMask is defined as p0d0, p0d1, p1d0, and p1d1.
        uint8_t mask = 0x8 >> (port * PORT_SLCT_PER_MBA + dimm);

        if ( 0 != (i_badDimmMask & mask) )
        {
            if ( NULL == errl )
            {
                errl = createErrl( PRDF_DETECTED_FAIL_HARDWARE, i_mba,
                                   PRDFSIG_RdrRepairUnavail );
            }

            o_calloutMade = true;
            errl->addHwCallout( *i, SRCI_PRIORITY_HIGH, HWAS::DELAYED_DECONFIG,
                                HWAS::GARD_Predictive );
        }
    }

    // Commit the error log, if needed.
    commitErrl( errl, i_mba );

    // Commit an additional error log indicating something failed in the
    // analysis, if needed.
    commitSoftError( PRDF_DETECTED_FAIL_SOFTWARE, i_mba,
                     PRDFSIG_RdrInternalFail, analysisErrors );

    return o_calloutMade;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

bool screenBadDqs( TargetHandle_t i_mba, const std::vector<CenRank> & i_ranks )
{
    #define PRDF_FUNC "[screenBadDqs] "

    // Callout any attached DIMMs that have any bad DQs.

    bool o_calloutMade  = false;
    bool analysisErrors = false;

    for ( std::vector<CenRank>::const_iterator rank = i_ranks.begin();
          rank != i_ranks.end(); rank++ )
    {
        // The HW procedure to read the bad DQ attribute will callout the DIMM
        // if it has DRAM Repairs VPD and the DISABLE_DRAM_REPAIRS MNFG policy
        // flag is set. PRD will simply need to iterate through all the ranks
        // to ensure all DIMMs are screen and the procedure will do the rest.

        CenDqBitmap bitmap;
        if ( SUCCESS != getBadDqBitmap(i_mba, *rank, bitmap, true) )
        {
            PRDF_ERR( PRDF_FUNC"getBadDqBitmap() failed: MBA=0x%08x rank=%d",
                      getHuid(i_mba), rank->getMaster() );
            analysisErrors = true;
            continue; // skip this rank
        }
    }

    // Commit an additional error log indicating something failed in the
    // analysis, if needed.
    commitSoftError( PRDF_DETECTED_FAIL_SOFTWARE, i_mba,
                     PRDFSIG_RdrInternalFail, analysisErrors );

    return o_calloutMade;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

void deployDramSpares( TargetHandle_t i_mba,
                       const std::vector<CenRank> & i_ranks )
{
    bool x4 = isDramWidthX4(i_mba);

    for ( std::vector<CenRank>::const_iterator rank = i_ranks.begin();
          rank != i_ranks.end(); rank++ )
    {
        // Doesn't matter which DRAM is spared as long as they are all spared.
        // Also, make sure the ECC spare is on a different DRAM than the spare
        // DRAM.
        CenSymbol symPort0 = CenSymbol::fromDimmDq( i_mba, *rank, 0, 0 );
        CenSymbol symPort1 = CenSymbol::fromDimmDq( i_mba, *rank, 0, 1 );
        CenSymbol symEccSp = CenSymbol::fromDimmDq( i_mba, *rank, 8, 0 );

        int32_t l_rc = SUCCESS;

        l_rc  = mssSetSteerMux( i_mba, *rank, symPort0, false );
        l_rc |= mssSetSteerMux( i_mba, *rank, symPort1, false );

        if ( x4 )
            l_rc |= mssSetSteerMux( i_mba, *rank, symEccSp, true );

        if ( SUCCESS != l_rc )
        {
            // mssSetSteerMux() will print a trace and commit the error log,
            // however, we need to handle the return code or we get a compile
            // warning in Hostboot.
            continue;
        }
    }
}

} // end namespace RDR

//------------------------------------------------------------------------------
// External functions - declared in prdfMain.H
//------------------------------------------------------------------------------

int32_t restoreDramRepairs( TargetHandle_t i_mba )
{
    #define PRDF_FUNC "PRDF::restoreDramRepairs"

    PRDF_ENTER( PRDF_FUNC"(0x%08x)", getHuid(i_mba) );

    // will unlock when going out of scope
    PRDF_SYSTEM_SCOPELOCK;

    bool calloutMade = false;

    do
    {
        std::vector<CenRank> ranks;
        int32_t l_rc = getMasterRanks( i_mba, ranks );
        if ( SUCCESS != l_rc )
        {
            PRDF_ERR( "["PRDF_FUNC"] getMasterRanks() failed" );

            RDR::commitSoftError( PRDF_DETECTED_FAIL_SOFTWARE, i_mba,
                                  PRDFSIG_RdrInternalFail, true );

            break; // Assume user meant to disable DRAM repairs.
        }

        bool spareDramDeploy = mnfgSpareDramDeploy();

        if ( spareDramDeploy )
        {
            // Deploy all spares for MNFG corner tests.
            RDR::deployDramSpares( i_mba, ranks );
        }

        if ( areDramRepairsDisabled() )
        {
            // DRAM Repairs are disabled in MNFG mode, so screen all DIMMs with
            // VPD information.
            if ( RDR::screenBadDqs(i_mba, ranks) ) calloutMade = true;

            // No need to continue because there will not be anything to
            // restore.
            break;
        }

        if ( spareDramDeploy )
        {
            // This is an error. The MNFG spare DRAM deply bit is set, but DRAM
            // Repairs have not been disabled.

            PRDF_ERR( "["PRDF_FUNC"] MNFG spare deploy enabled, but DRAM "
                      "repairs are not disabled" );

            RDR::commitSoftError( PRDF_INVALID_CONFIG, i_mba,
                                  PRDFSIG_RdrInvalidConfig, true );

            break; // Assume user meant to disable DRAM repairs.
        }

        uint8_t rankMask = 0, dimmMask = 0;
        if ( SUCCESS != mssRestoreDramRepairs(i_mba, rankMask, dimmMask) )
        {
            // Can't check anything if this doesn't work.
            PRDF_ERR( "["PRDF_FUNC"] mssRestoreDramRepairs() failed" );
            break;
        }

        // Callout DIMMs with too many bad bits and not enough repairs available
        if ( RDR::processBadDimms(i_mba, dimmMask) ) calloutMade = true;

        // Check repaired ranks for RAS policy violations.
        if ( RDR::processRepairedRanks(i_mba, rankMask) ) calloutMade = true;

    } while(0);

    PRDF_EXIT( PRDF_FUNC"(0x%08x)", getHuid(i_mba) );

    return calloutMade ? FAIL : SUCCESS;

    #undef PRDF_FUNC
}

} // end namespace PRDF

<|endoftext|>


<commit_before>/*
 *
 * Copyright (C) 2009, Joacim Jacobsson ( j dot jacobsson at gmail dot com )
 * All rights reserved.
 *
 * See LICENSE file for details
 *
 */

#include "BehaviorTreeNode.h"
#include "../NodeToNodeArrow.h"
#include <btree/btree.h>

#include <QtGui/QtGui>

const char* const g_NodeResourcePaths[_E_MAX_GRIST_TYPES_] = {
	":/nodes/unknown.svg",
	":/nodes/sequence.svg",
	":/nodes/selector.svg",
	":/nodes/parallel.svg",
	":/nodes/dyn_selector.svg",
	":/nodes/decorator.svg",
	":/nodes/action.svg"
};

BehaviorTreeNode::BehaviorTreeNode( Node* n, BehaviorTreeNode* parent )
	: QGraphicsSvgItem( g_NodeResourcePaths[n->m_Grist.m_Type] )
	, m_Node( n )
	, m_PreviousParent( 0x0 )
	, m_MouseState( E_MS_NONE )
{
	setFlag( QGraphicsItem::ItemIsMovable, true );
	setFlag( QGraphicsItem::ItemIsSelectable, true );
	setFlag( QGraphicsItem::ItemStacksBehindParent, false );

	if( parent )
		setParentItem( parent );
	setZValue( 0.0 );
}

void BehaviorTreeNode::removeArrow(NodeToNodeArrow *arrow)
{
	int index = m_Arrows.indexOf(arrow);

	if (index != -1)
		m_Arrows.removeAt(index);
}

void BehaviorTreeNode::removeArrows()
{
	foreach( NodeToNodeArrow *arrow, m_Arrows )
	{
		arrow->startItem()->removeArrow(arrow);
		arrow->endItem()->removeArrow(arrow);
		scene()->removeItem(arrow);
		delete arrow;
	}
}

void BehaviorTreeNode::addArrow(NodeToNodeArrow *arrow)
{
	m_Arrows.append(arrow);
}

QVariant BehaviorTreeNode::itemChange( GraphicsItemChange change, const QVariant &value )
{
	switch( change )
	{
	case ItemSelectedChange:
		update();
		break;
	case ItemPositionChange:
		break;
	}
	return QGraphicsSvgItem::itemChange( change, value );
}

void BehaviorTreeNode::mousePressEvent( QGraphicsSceneMouseEvent* event )
{
	if( event->button() == Qt::LeftButton )
	{
		m_MouseState = E_MS_LB_DOWN;
		m_StartPos = event->screenPos();
		if( parentItem() )
		{
			m_PreviousParent = parentItem();
			QPointF position( scenePos() );
			setParentItem( 0x0 );
			setPos( position );
		}
	}
	QGraphicsSvgItem::mousePressEvent( event );
}

void BehaviorTreeNode::mouseReleaseEvent( QGraphicsSceneMouseEvent* event )
{
	if( event->button() == Qt::LeftButton )
	{
		m_MouseState = E_MS_NONE;
		setZValue( 0.0 );
		if( m_PreviousParent )
		{
			setPos( m_PreviousParent->mapFromScene( scenePos() ) );
			setParentItem( m_PreviousParent );
			m_PreviousParent = 0x0;
		}
	}
	QGraphicsSvgItem::mouseReleaseEvent( event );
}

void BehaviorTreeNode::mouseMoveEvent( QGraphicsSceneMouseEvent* event )
{
	if( m_MouseState == E_MS_LB_DOWN )
	{
		if( m_StartPos != event->screenPos() )
		{
			m_MouseState = E_MS_DRAGGING;
			setZValue( 1.0 );
		}
	}
	QGraphicsSvgItem::mouseMoveEvent( event );
}
<commit_msg>Unlinking node's when dragging.<commit_after>/*
 *
 * Copyright (C) 2009, Joacim Jacobsson ( j dot jacobsson at gmail dot com )
 * All rights reserved.
 *
 * See LICENSE file for details
 *
 */

#include "BehaviorTreeNode.h"
#include "../NodeToNodeArrow.h"
#include <btree/btree.h>

#include <QtGui/QtGui>

const char* const g_NodeResourcePaths[_E_MAX_GRIST_TYPES_] = {
	":/nodes/unknown.svg",
	":/nodes/sequence.svg",
	":/nodes/selector.svg",
	":/nodes/parallel.svg",
	":/nodes/dyn_selector.svg",
	":/nodes/decorator.svg",
	":/nodes/action.svg"
};

BehaviorTreeNode::BehaviorTreeNode( Node* n, BehaviorTreeNode* parent )
	: QGraphicsSvgItem( g_NodeResourcePaths[n->m_Grist.m_Type] )
	, m_Node( n )
	, m_PreviousParent( 0x0 )
	, m_MouseState( E_MS_NONE )
{
	setFlag( QGraphicsItem::ItemIsMovable, true );
	setFlag( QGraphicsItem::ItemIsSelectable, true );
	setFlag( QGraphicsItem::ItemStacksBehindParent, false );

	if( parent )
		setParentItem( parent );
	setZValue( 0.0 );
}

void BehaviorTreeNode::removeArrow(NodeToNodeArrow *arrow)
{
	int index = m_Arrows.indexOf(arrow);

	if (index != -1)
		m_Arrows.removeAt(index);
}

void BehaviorTreeNode::removeArrows()
{
	foreach( NodeToNodeArrow *arrow, m_Arrows )
	{
		arrow->startItem()->removeArrow(arrow);
		arrow->endItem()->removeArrow(arrow);
		scene()->removeItem(arrow);
		delete arrow;
	}
}

void BehaviorTreeNode::addArrow(NodeToNodeArrow *arrow)
{
	m_Arrows.append(arrow);
}

QVariant BehaviorTreeNode::itemChange( GraphicsItemChange change, const QVariant &value )
{
	switch( change )
	{
	case ItemSelectedChange:
		update();
		break;
	case ItemPositionChange:
		break;
	}
	return QGraphicsSvgItem::itemChange( change, value );
}

void BehaviorTreeNode::mousePressEvent( QGraphicsSceneMouseEvent* event )
{
	if( event->button() == Qt::LeftButton )
	{
		m_MouseState = E_MS_LB_DOWN;
		m_StartPos = event->screenPos();
		if( parentItem() )
		{
			m_PreviousParent = parentItem();
			QPointF position( scenePos() );
			setParentItem( 0x0 );
			setPos( position );
		}
	}
	QGraphicsSvgItem::mousePressEvent( event );
}

void BehaviorTreeNode::mouseReleaseEvent( QGraphicsSceneMouseEvent* event )
{
	if( event->button() == Qt::LeftButton )
	{
		m_MouseState = E_MS_NONE;
		setZValue( 0.0 );
		if( m_PreviousParent )
		{
			setPos( m_PreviousParent->mapFromScene( scenePos() ) );
			setParentItem( m_PreviousParent );
			m_PreviousParent = 0x0;
		}
	}
	QGraphicsSvgItem::mouseReleaseEvent( event );
}

void BehaviorTreeNode::mouseMoveEvent( QGraphicsSceneMouseEvent* event )
{
	if( m_MouseState == E_MS_LB_DOWN )
	{
		if( m_StartPos != event->screenPos() )
		{
			m_MouseState = E_MS_DRAGGING;
			setZValue( 1.0 );

			UnlinkNodeFromParentAndSiblings( m_Node );

		}
	}
	QGraphicsSvgItem::mouseMoveEvent( event );
}
<|endoftext|>


<commit_before>/* Copyright © 2016 Taylor C. Richberger <taywee@gmx.com>
 * This code is released under the license described in the LICENSE file
 */

#include <string>
#include <vector>

namespace args
{
    class ArgumentParser
    {
        private:
            std::string prog;
            std::string description;
            std::string epilog;

        public:
            ArgumentParser(
                const std::string &prog,
                const std::string &description,
                const std::string &epilog = std::string()) : prog(prog), description(description), epilog(epilog) {}

            void ParseArgs(const std::vector<std::string> &args)
            {
            }

            void ParseCLI(const int argc, const char * const * const argv)
            {
                std::vector<std::string> args;
                for (int i = 1; i < argc; ++i)
                {
                    args.emplace_back(argv[i]);
                }
                ParseArgs(args);
            }
    };
}
<commit_msg>add validators, add more body to library<commit_after>/* Copyright © 2016 Taylor C. Richberger <taywee@gmx.com>
 * This code is released under the license described in the LICENSE file
 */

#include <string>
#include <vector>
#include <list>
#include <functional>

namespace args
{
    class Base
    {
        protected:
            bool matched;

        public:
            Base() : matched(false) {}
            virtual ~Base() {}

            virtual bool Matched() const
            {
                return matched;
            }
    };

    class Group : public Base
    {
        private:
            std::vector<Base*> children;
            std::function<bool(int, int)> validator;

        public:

            Group(const std::function<bool(int, int)> &validator = Validators::DontCare) : validator(validator) {}
            virtual ~Group() {}

            void Add(Base &child)
            {
                children.emplace_back(&child);
            }

            int MatchedChildren() const
            {
                int sum = 0;
                for (const Base * child: children)
                {
                    if (child->Matched())
                    {
                        ++sum;
                    }
                }
                return sum;
            }

            virtual bool Matched() const override
            {
                return validator(children.size(), MatchedChildren());
            }

            struct Validators
            {
                static bool Xor(int children, int matched)
                {
                    return matched == 1;
                }

                static bool AtLeastOne(int children, int matched)
                {
                    return matched >= 1;
                }

                static bool AtMostOne(int children, int matched)
                {
                    return matched <= 1;
                }

                static bool All(int children, int matched)
                {
                    return children == matched;
                }

                static bool DontCare(int children, int matched)
                {
                    return true;
                }

                static bool CareTooMuch(int children, int matched)
                {
                    return false;
                }

                static bool None(int children, int matched)
                {
                    return matched == 0;
                }
            };
    };

    class ArgumentParser
    {
        private:
            std::string prog;
            std::string description;
            std::string epilog;

            Group args;

        public:
            ArgumentParser(
                const std::string &prog,
                const std::string &description,
                const std::string &epilog = std::string()) : prog(prog), description(description), epilog(epilog) {}

            void ParseArgs(const std::vector<std::string> &args)
            {
            }

            void ParseCLI(const int argc, const char * const * const argv)
            {
                std::vector<std::string> args;
                for (int i = 1; i < argc; ++i)
                {
                    args.emplace_back(argv[i]);
                }
                ParseArgs(args);
            }
    };
}
<|endoftext|>