// see License.txt for copyright and terms of use

#include "squash_cmd.h"    // this module
#include "oink_cmd_util.h"      // HANDLE_FLAG
#include "oink_util.h"
#include <cstring>              // strdup
#include <cstdlib>              // atoi

SquashCmd::SquashCmd()
  : squash(true), rewriteDeclaration(true)
  {}

void SquashCmd::readOneArg(int &argc, char **&argv) {
  int old_argc = argc;
  OinkCmd::readOneArg(argc, argv);
  if (old_argc != argc) return; // the superclass read one so we don't

  char *arg = argv[0];
  // please prefix the names of flags with arguments with '-sq-'
  if (streq(arg, "-sq-implementation")) {
    shift(argc, argv);
    className = shift(argc, argv);
    targetClasses.insert(className);
  } else if (streq(arg, "-sq-include")) {
    shift(argc, argv);
    includes.push_back(shift(argc, argv));
  } else if (streq(arg, "-sq-exclude-include")) {
    shift(argc, argv);
    excludes.insert(shift(argc, argv));
  } else if (streq(arg, "-sq-virtual")) {
    shift(argc, argv);
    virtuals.insert(shift(argc, argv));
  } else if (streq(arg, "-sq-rename-member")) {
    shift(argc, argv);
    const char* old = shift(argc, argv);
    memberRenames[old] = shift(argc, argv);
  } else if (streq(arg, "-sq-rewrite-outparams")) {
    shift(argc, argv);
    outparamFile = shift(argc, argv);
  } else if (streq(arg, "-sq-no-squash")) {
    shift(argc, argv);
    squash = false;
  } else if (streq(arg, "-sq-no-rewrite-declaration")) {
    shift(argc, argv);
    rewriteDeclaration = false;
  } else if (streq(arg, "-sq-rewrite-path")) {
    shift(argc, argv);
    std::string from = shift(argc, argv);
    std::string to = shift(argc, argv);
    pathSubstitutions[from] = to;
  }
}

void SquashCmd::printHelp() {
  OinkCmd::printHelp();
  printf
    ("squash flags that take an argument:\n"
     "  -sq-implementation <className>           : move the class members up to the first base class\n"
     "  -sq-include <header>                     : Additional include files. Can be specified multiple times\n"
     "  -sq-exclude-include <header>             : Do not include header file named this. This is useful when the header inference fails. Can be specified multiple times\n"
     "  -sq-virtual <member fuction>             : Keep the specified function virtual\n"
     "  -sq-rename-member <old_member_name>  <new_member_name>   : rename old_member_name of target class to new_member_name\n"
     "  -sq-rewrite-outparams <filename>         : Rewrite out-parameters to be passed by return values.<filename> contains list  of functions to rewrite \n"
     "  -sq-no-rewrite-declaration         : Do not do rewrite class headers \n"
     "  -sq-no-squash                            : Do not do squashing(useful if one only needs to do renames) \n"
     "  -sq-rewrite-path <c:\\from> </something> : Used for .i files produced on another machine/OS \n"
     "");
}

// push the state out to other places where it is needed; return value
// is true unless there is an error
void SquashCmd::initializeFromFlags() {
  OinkCmd::initializeFromFlags();

  // check here if there is some inconsistency between the flags
  if (className.empty() && !memberRenames.size()) {
    throw UserError(USER_ERROR_ExitCode,
                    "Please specify a class to squash with its interface via -sq-implementation");
  }
}
