/**
 * Processes an command line argument for a GCC like command.
 *
 * @param state_ the current state of the parser.
 * @param arg_ the current command line argument.
 * @param action the current action.
 * @return the new state.
 */
static GccArgsState processArgument(
  GccArgsState state_,
  const char* arg_,
  LoggerAction* action_)
{
  char argToAdd[PATH_MAX];
  strcpy(argToAdd, arg_);

  if (state_ == InOutputArg)
  {
    if (!loggerMakePathAbs(arg_, argToAdd, 0))
    {
      strcpy(argToAdd, arg_);
    }

    loggerFileInitFromPath(&action_->output, argToAdd);
    state_ = Normal;
  }
  else if (strcmp(arg_, "-o") == 0)
  {
    state_ = InOutputArg;
  }
  else if (arg_[0] == '-' && ((arg_[1] == 'W' && (arg_[2] == 'l' || arg_[2] == 'p')) || arg_[1] == 'M'))
  {
    /* This is a -Wl linker option
     *  -Wl,-Map,output.map
     *  or a -Wp prepocessor option
     *  -Wp,option
     *  also matches for options like -Wpedantic
     *  handled here to skip for matching source files in
     *  these arguments
     */
    strcpy(argToAdd, arg_);
  }
  else if (arg_[0] == '-' && arg_[1] == 'D')
  {
    /*  Match for macro definition -D
     *  handled here to skip for matching source files in
     *  these arguments
     */
    strcpy(argToAdd, arg_);
  }
  else if (arg_[0] == '-' && (arg_[1] == 'I' || arg_[1] == 'L') && arg_[2])
  {
    /* This is a -I or -L option with a path */
    char fullPath[PATH_MAX];
    if (loggerMakePathAbs(arg_ + 2, fullPath, 0))
    {
      argToAdd[2] = 0;
      strcat(argToAdd, fullPath);
    }
  }
  else
  {
    char fullPath[PATH_MAX];
    if (loggerMakePathAbs(argToAdd, fullPath, 1))
    {
      char* ext = loggerGetFileExt(fullPath, 1);
      if (ext)
      {
        int i;
        for (i = 0; srcExts[i]; ++i)
        {
          if (strcmp(srcExts[i], ext) == 0)
          {
            strcpy(argToAdd, fullPath);
            loggerVectorAddUnique(&action_->sources,  loggerStrDup(fullPath),
              (LoggerCmpFuc) &strcmp);
            break;
          }
        }
      }

      free(ext);
    }
  }

  if (argToAdd[0])
  {
    loggerVectorAdd(&action_->arguments, loggerStrDup(argToAdd));
  }

  return state_;
}
/**
 * Processes an command line argument for a GCC like command.
 *
 * @param state_ the current state of the parser.
 * @param arg_ the current command line argument.
 * @param action the current action.
 * @return the new state.
 */
static GccArgsState processArgument(
  GccArgsState state_,
  const char* arg_,
  LoggerAction* action_)
{
  char argToAdd[PATH_MAX];
  strcpy(argToAdd, arg_);

  if (state_ == InOutputArg)
  {
    if (!loggerMakePathAbs(arg_, argToAdd, 0))
    {
      strcpy(argToAdd, arg_);
    }

    loggerFileInitFromPath(&action_->output, argToAdd);
    state_ = Normal;
  }
  else if (strcmp(arg_, "-o") == 0)
  {
    state_ = InOutputArg;
  }
  else if (arg_[0] == '-' && (arg_[1] == 'I' || arg_[1] == 'L') && arg_[2])
  {
    /* This is a -I or -L option with a path */
    char fullPath[PATH_MAX];
    if (loggerMakePathAbs(arg_ + 2, fullPath, 0))
    {
      argToAdd[2] = 0;
      strcat(argToAdd, fullPath);
    }
  }
  else
  {
    char fullPath[PATH_MAX];
    if (loggerMakePathAbs(argToAdd, fullPath, 1))
    {
      char* ext = loggerGetFileExt(fullPath, 1);
      if (ext)
      {
        int i;
        for (i = 0; srcExts[i]; ++i)
        {
          if (strcmp(srcExts[i], ext) == 0)
          {
            strcpy(argToAdd, fullPath);
            loggerVectorAddUnique(&action_->sources,  loggerStrDup(fullPath),
              (LoggerCmpFuc) &strcmp);
            break;
          }
        }
      }

      free(ext);
    }
  }

  if (argToAdd[0])
  {
    loggerVectorAdd(&action_->arguments, loggerStrDup(argToAdd));
  }

  return state_;
}
/**
 * Processes a single argument.
 *
 * @param arg_ the current argument.
 * @param data_ the state data of the parser function.
 */
static void processArg(const char* arg_, ParserData* data_)
{
  size_t argToAddSize = PATH_MAX;
  char* argToAdd ;
  char* ext;

  argToAdd = (char*) malloc(sizeof(char) * argToAddSize);
  if (!argToAdd)
  {
    /* NO MEM! */
    return;
  }

  strcpy(argToAdd, arg_);

  if (data_->state == InClassDir)
  {
    if (!loggerMakePathAbs(arg_, data_->classdir, 0))
    {
      strcpy(data_->classdir, arg_);
    }

    strcpy(argToAdd, data_->classdir);
    data_->state = Normal;
  }
  else if (data_->state == InClassPath)
  {
    handleClassPath(&argToAdd, &argToAddSize, arg_);
    data_->state = Normal;
  }
  else if (strcmp(arg_, "-sourcepath") == 0)
  {
    data_->hasSourcePath = 1;
  }
  else if (strcmp(arg_, "-d") == 0)
  {
    data_->state = InClassDir;
  }
  else if (strcmp(arg_, "-cp") == 0 || strcmp(arg_, "-classpath") == 0)
  {
    data_->state = InClassPath;
  }
  else if ((ext = loggerGetFileExt(arg_, 1)))
  {
    int isSource = 0;
    if (strcmp(ext, "java") == 0)
    {
      char path[PATH_MAX];
      if (loggerMakePathAbs(arg_, path, 0))
      {
        loggerVectorAddUnique(&data_->sources,
          loggerStrDup(path), (LoggerCmpFuc) &strcmp);
        isSource = 1;
      }
    }

    if (isSource)
    {
      argToAdd[0] = 0;
    }

    free(ext);
  }

  if (argToAdd[0])
  {
    loggerVectorAdd(&data_->commonArgs, loggerStrDup(argToAdd));
  }

  free(argToAdd);
}