コード例 #1
0
int loggerGccParserCollectActions(
  const char* prog_,
  const char* toolName_,
  const char* const argv_[],
  LoggerVector* actions_)
{
  enum Language { C, CPP, OBJC } lang = CPP;

  size_t i;
  /* Position of the last include path + 1 */
  char full_prog_path[PATH_MAX+1];
  char *path_ptr;

  size_t lastIncPos = 1;
  size_t lastSysIncPos = 1;
  GccArgsState state = Normal;
  LoggerAction* action = loggerActionNew(toolName_);

  char* keepLinkVar = getenv("CC_LOGGER_KEEP_LINK");
  int keepLink = keepLinkVar && strcmp(keepLinkVar, "true") == 0;

  /* If prog_ is a relative path we try to
   * convert it to absolute path.
   */
  path_ptr = realpath(prog_, full_prog_path);

  /* If we cannot convert it, we try to find the
   * executable in the PATH.
   */
  if (!path_ptr)
	  path_ptr = findFullPath(toolName_, full_prog_path);
  if (path_ptr) /* Log compiler with full path. */
	  loggerVectorAdd(&action->arguments, loggerStrDup(full_prog_path));
  else  /* Compiler was not found in path, log the binary name only. */
  	  loggerVectorAdd(&action->arguments, loggerStrDup(toolName_));

  /* Determine programming language based on compiler name. */
  for (i = 0; cCompiler[i]; ++i)
    if (strstr(toolName_, cCompiler[i]))
      lang = C;

  for (i = 0; cppCompiler[i]; ++i)
    if (strstr(toolName_, cppCompiler[i]))
      lang = CPP;

  for (i = 1; argv_[i]; ++i)
  {
    const char* current = argv_[i];
    state = processArgument(state, current, action);

    if (current[0] == '-')
    {
      /* Determine the position of the last -I and -isystem flags.
       * Depending on whether the parameter of -I or -isystem is separated
       * from the flag by a space character.
       * 2 == strlen("-I") && 8 == strlen("-isystem")
       */
      if (current[1] == 'I')
        lastIncPos = action->arguments.size + (current[2] ? 0 : 1);
      else if (strstr(current, "-isystem") == current)
        lastSysIncPos = action->arguments.size + (current[8] ? 0 : 1);

      /* Determine the programming language based on -x flag.
       */
      else if (strcmp(current, "-x") == 0)
      {
        /* TODO: The language value after -x can be others too. See the man
         * page of GCC.
         * TODO: According to a GCC warning the -x flag has no effect when it
         * is placed after the last input file to be compiled.
         */
        const char* l = argv_[i + 1];
        if (strcmp(l, "c") == 0 || strcmp(l, "c-header") == 0)
          lang = C;
        else if (strcmp(l, "c++") == 0 || strcmp(l, "c++-header") == 0)
          lang = CPP;
      }
    }
  }

  if (getenv("CC_LOGGER_DEF_DIRS"))
  {
    LoggerVector defIncludes;
    loggerVectorInit(&defIncludes);

    getDefaultArguments(prog_, &defIncludes);
    if (defIncludes.size)
    {
      loggerVectorAddFrom(&action->arguments, &defIncludes,
        &lastIncPos, (LoggerDupFuc) &loggerStrDup);

      if (lastSysIncPos > lastIncPos)
        lastSysIncPos += defIncludes.size;

      lastIncPos += defIncludes.size;
    }

    loggerVectorClear(&defIncludes);
  }

  if (getenv("CPATH"))
  {
    LoggerVector includes;
    loggerVectorInit(&includes);

    getPathsFromEnvVar(&includes, "CPATH", "-I");
    if (includes.size)
    {
      loggerVectorAddFrom(&action->arguments, &includes,
        &lastIncPos, (LoggerDupFuc) &loggerStrDup);

      if (lastSysIncPos > lastIncPos)
        lastSysIncPos += includes.size;

      lastIncPos += includes.size;
    }

    loggerVectorClear(&includes);
  }

  if (lang == CPP && getenv("CPLUS_INCLUDE_PATH"))
  {
    LoggerVector includes;
    loggerVectorInit(&includes);

    getPathsFromEnvVar(&includes, "CPLUS_INCLUDE_PATH", "-isystem");
    if (includes.size)
    {
      loggerVectorAddFrom(&action->arguments, &includes,
        &lastSysIncPos, (LoggerDupFuc) &loggerStrDup);
    }

    loggerVectorClear(&includes);
  }
  else if (lang == C && getenv("C_INCLUDE_PATH"))
  {
    LoggerVector includes;
    loggerVectorInit(&includes);

    getPathsFromEnvVar(&includes, "C_INCLUDE_PATH", "-isystem");
    if (includes.size)
    {
      loggerVectorAddFrom(&action->arguments, &includes,
        &lastSysIncPos, (LoggerDupFuc) &loggerStrDup);
    }

    loggerVectorClear(&includes);
  }

  /*
   * Workaround for -MT and friends: if the source set contains the output,
   * then we have to remove it from the set.
   */
  i = loggerVectorFind(&action->sources, action->output.path,
    (LoggerCmpFuc) &strcmp);
  if (i != SIZE_MAX)
  {
    loggerVectorErase(&action->sources, i);
  }

  if (!keepLink)
    do {
      i = loggerVectorFindIf(&action->sources, (LoggerPredFuc) &isObjectFile);
      loggerVectorErase(&action->sources, i);
    } while (i != SIZE_MAX);

  if (action->sources.size != 0)
    loggerVectorAdd(actions_, action);

  return 1;
}
コード例 #2
0
int loggerGccParserCollectActions(
  const char* prog_,
  const char* toolName_,
  const char* const argv_[],
  LoggerVector* actions_)
{
  size_t i;
  /* Position of the last include path + 1 */
  size_t lastIncPos = 1;
  GccArgsState state = Normal;
  LoggerAction* action = loggerActionNew(toolName_);

  loggerVectorAdd(&action->arguments, loggerStrDup(toolName_));

  for (i = 1; argv_[i]; ++i)
  {
    state = processArgument(state, argv_[i], action);
    if (argv_[i][0] == '-' && argv_[i][1] == 'I')
    {
      if (argv_[i][2])
      {
        /* -I with path argument */
        lastIncPos = action->arguments.size;
      }
      else
      {
        /* The path should be the next argument */
        lastIncPos = action->arguments.size + 1;
      }
    }
  }

  if (!getenv("CC_LOGGER_NO_DEF_DIRS"))
  {
    LoggerVector defIncludes;
    loggerVectorInit(&defIncludes);

    getDefaultArguments(prog_, &defIncludes);
    if (defIncludes.size)
    {
      loggerVectorAddFrom(&action->arguments, &defIncludes,
        &lastIncPos, (LoggerDupFuc) &loggerStrDup);
    }

    loggerVectorClear(&defIncludes);
  }

  /*
   * Workaround for -MT and friends: if the source set contains the output,
   * then we have to remove it from the set.
   */
  i = loggerVectorFind(&action->sources, action->output.path,
    (LoggerCmpFuc) &strcmp);
  if (i != SIZE_MAX)
  {
    loggerVectorErase(&action->sources, i);
  }

  loggerVectorAdd(actions_, action);
  return 1;
}
コード例 #3
0
void runApplicationTest(char *applicationPath, const char *testName, LinkedList testArguments, ReturnCodes expectedResultCode, boolByte anazyleOutput) {
  char** applicationArguments;
  ArgumentsCopyData argumentsCopyData;
  int resultCode = -1;
  LinkedList defaultArguments = getDefaultArguments(testName);
  LinkedList arguments = _appendLinkedLists(defaultArguments, testArguments);
  CharString failedAnalysisFunctionName = newCharString();
  unsigned long failedAnalysisSample;

  // Remove any output files which may have been left from previous tests
  foreachItemInList(defaultArguments, _removeOutputFile, NULL);

#if WINDOWS
#else
  mkdir("out", 0755);
#endif

#if WINDOWS
  logUnsupportedFeature("Application testing");
#else
  int numArgs = numItemsInList(arguments);
  // Add two extra items to the array, one for the application path and another for a NULL object.
  // These are required for the calls to the execv* functions.
  applicationArguments = (char**)malloc(sizeof(char*) * (numArgs + 2));
  applicationArguments[0] = applicationPath;
  applicationArguments[numArgs + 1] = NULL;
  argumentsCopyData.currentIndex = 1;
  argumentsCopyData.outArray = applicationArguments;
  foreachItemInList(arguments, _copyArgumentToArray, &argumentsCopyData);
  printf("  %s: ", testName);

  pid_t forkedPid = fork();
  if(forkedPid == 0) {
    resultCode = execvp(applicationPath, applicationArguments);
    exit(resultCode);
  }
  else {
    int statusLoc;
    waitpid(forkedPid, &statusLoc, 0);
    if(WIFEXITED(statusLoc)) {
      resultCode = WEXITSTATUS(statusLoc);
    }
  }
#endif

  if(resultCode == expectedResultCode) {
    if(anazyleOutput) {
      if(analyzeFile(_getTestOutputFilename(testName, "pcm"), failedAnalysisFunctionName, &failedAnalysisSample)) {
        testsPassed++;
        foreachItemInList(defaultArguments, _removeOutputFile, NULL);
        printTestSuccess();
      }
      else {
        printTestFail();
        printf("    in test '%s', while analyzing output for %s at sample %lu.\n",
          testName, failedAnalysisFunctionName->data, failedAnalysisSample);
        testsFailed++;
      }
    }
    else {
      testsPassed++;
      foreachItemInList(defaultArguments, _removeOutputFile, NULL);
      printTestSuccess();
    }
  }
  else {
    printTestFail();
    printf("    in %s. Expected result code %d, got %d.\n", testName, expectedResultCode, resultCode);
    testsFailed++;
  }

  freeLinkedList(defaultArguments);
  freeLinkedList(testArguments);
  freeLinkedList(arguments);
}