<commit_before>//===-- Intercept.cpp - System function interception routines -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// If a function call occurs to an external function, the JIT is designed to use
// the dynamic loader interface to find a function to call.  This is useful for
// calling system calls and library functions that are not available in LLVM.
// Some system calls, however, need to be handled specially.  For this reason,
// we intercept some of them here and use our own stubs to handle them.
//
//===----------------------------------------------------------------------===//

#include "JIT.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/Config/config.h"
using namespace llvm;

// AtExitHandlers - List of functions to call when the program exits,
// registered with the atexit() library function.
static std::vector<void (*)()> AtExitHandlers;

/// runAtExitHandlers - Run any functions registered by the program's
/// calls to atexit(3), which we intercept and store in
/// AtExitHandlers.
///
static void runAtExitHandlers() {
  while (!AtExitHandlers.empty()) {
    void (*Fn)() = AtExitHandlers.back();
    AtExitHandlers.pop_back();
    Fn();
  }
}

//===----------------------------------------------------------------------===//
// Function stubs that are invoked instead of certain library calls
//===----------------------------------------------------------------------===//

// Force the following functions to be linked in to anything that uses the
// JIT. This is a hack designed to work around the all-too-clever Glibc
// strategy of making these functions work differently when inlined vs. when
// not inlined, and hiding their real definitions in a separate archive file
// that the dynamic linker can't see. For more info, search for
// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
#if defined(__linux__)
#if defined(HAVE_SYS_STAT_H)
#include <sys/stat.h>
#endif
void *FunctionPointers[] = {
  (void *)(intptr_t) stat,
  (void *)(intptr_t) fstat,
  (void *)(intptr_t) lstat,
  (void *)(intptr_t) stat64,
  (void *)(intptr_t) fstat64,
  (void *)(intptr_t) lstat64,
  (void *)(intptr_t) atexit,
  (void *)(intptr_t) mknod
};
#endif // __linux__

// jit_exit - Used to intercept the "exit" library call.
static void jit_exit(int Status) {
  runAtExitHandlers();   // Run atexit handlers...
  exit(Status);
}

// jit_atexit - Used to intercept the "atexit" library call.
static int jit_atexit(void (*Fn)(void)) {
  AtExitHandlers.push_back(Fn);    // Take note of atexit handler...
  return 0;  // Always successful
}

//===----------------------------------------------------------------------===//
//
/// getPointerToNamedFunction - This method returns the address of the specified
/// function by using the dynamic loader interface.  As such it is only useful
/// for resolving library symbols, not code generated symbols.
///
void *JIT::getPointerToNamedFunction(const std::string &Name) {
  // Check to see if this is one of the functions we want to intercept.  Note,
  // we cast to intptr_t here to silence a -pedantic warning that complains
  // about casting a function pointer to a normal pointer.
  if (Name == "exit") return (void*)(intptr_t)&jit_exit;
  if (Name == "atexit") return (void*)(intptr_t)&jit_atexit;

  const char *NameStr = Name.c_str();
  // If this is an asm specifier, skip the sentinal.
  if (NameStr[0] == 1) ++NameStr;

  // If it's an external function, look it up in the process image...
  void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
  if (Ptr) return Ptr;

  // If it wasn't found and if it starts with an underscore ('_') character, and
  // has an asm specifier, try again without the underscore.
  if (Name[0] == 1 && NameStr[0] == '_') {
    Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
    if (Ptr) return Ptr;
  }

  // darwin/ppc adds $LDBLStub suffixes to various symbols like printf.  These
  // are references to hidden visibility symbols that dlsym cannot resolve.  If
  // we have one of these, strip off $LDBLStub and try again.
#if defined(__APPLE__) && defined(__ppc__)
  if (Name.size() > 9 && Name[Name.size()-9] == '$' &&
      memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0) {
    // First try turning $LDBLStub into $LDBL128.  If that fails, strip it off.
    // This mirrors logic in libSystemStubs.a.
    std::string Prefix = std::string(Name.begin(), Name.end()-9);
    if (void *Ptr = getPointerToNamedFunction(Prefix+"$LDBL128"))
      return Ptr;
    if (void *Ptr = getPointerToNamedFunction(Prefix))
      return Ptr;
  }
#endif

  /// If a LazyFunctionCreator is installed, use it to get/create the function.
  if (LazyFunctionCreator)
    if (void *RP = LazyFunctionCreator(Name))
      return RP;

  cerr << "ERROR: Program used external function '" << Name
       << "' which could not be resolved!\n";
  abort();
  return 0;
}
<commit_msg>Fix PR1873, a problem finding stat-related symbols on linux, due to "libc_nonshared.a". Patch by Edwin Török!<commit_after>//===-- Intercept.cpp - System function interception routines -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// If a function call occurs to an external function, the JIT is designed to use
// the dynamic loader interface to find a function to call.  This is useful for
// calling system calls and library functions that are not available in LLVM.
// Some system calls, however, need to be handled specially.  For this reason,
// we intercept some of them here and use our own stubs to handle them.
//
//===----------------------------------------------------------------------===//

#include "JIT.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/Config/config.h"
using namespace llvm;

// AtExitHandlers - List of functions to call when the program exits,
// registered with the atexit() library function.
static std::vector<void (*)()> AtExitHandlers;

/// runAtExitHandlers - Run any functions registered by the program's
/// calls to atexit(3), which we intercept and store in
/// AtExitHandlers.
///
static void runAtExitHandlers() {
  while (!AtExitHandlers.empty()) {
    void (*Fn)() = AtExitHandlers.back();
    AtExitHandlers.pop_back();
    Fn();
  }
}

//===----------------------------------------------------------------------===//
// Function stubs that are invoked instead of certain library calls
//===----------------------------------------------------------------------===//

// Force the following functions to be linked in to anything that uses the
// JIT. This is a hack designed to work around the all-too-clever Glibc
// strategy of making these functions work differently when inlined vs. when
// not inlined, and hiding their real definitions in a separate archive file
// that the dynamic linker can't see. For more info, search for
// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
#if defined(__linux__)
#if defined(HAVE_SYS_STAT_H)
#include <sys/stat.h>
#endif

/* stat functions are redirecting to __xstat with a version number.
 * On x86-64 linking with libc_nonshared.a and -Wl,--export-dynamic
 * doesn't make 'stat' available as an exported symbol, so we have to add it explicitely.*/
class StatSymbols {
	public:
	StatSymbols() {
		sys::DynamicLibrary::AddSymbol("stat", (void*)(intptr_t)stat);
		sys::DynamicLibrary::AddSymbol("fstat", (void*)(intptr_t)fstat);
		sys::DynamicLibrary::AddSymbol("fstatat", (void*)(intptr_t)fstatat);
		sys::DynamicLibrary::AddSymbol("lstat", (void*)(intptr_t)lstat);
		sys::DynamicLibrary::AddSymbol("stat64", (void*)(intptr_t)stat64);
		sys::DynamicLibrary::AddSymbol("fstat64", (void*)(intptr_t)fstat64);
		sys::DynamicLibrary::AddSymbol("fstatat64", (void*)(intptr_t)fstatat64);
		sys::DynamicLibrary::AddSymbol("lstat64", (void*)(intptr_t)lstat64);
		sys::DynamicLibrary::AddSymbol("atexit", (void*)(intptr_t)atexit);
		sys::DynamicLibrary::AddSymbol("mknod", (void*)(intptr_t)mknod);
		sys::DynamicLibrary::AddSymbol("mknodat", (void*)(intptr_t)mknodat);
	}
};
static StatSymbols initStatSymbols;
#endif // __linux__

// jit_exit - Used to intercept the "exit" library call.
static void jit_exit(int Status) {
  runAtExitHandlers();   // Run atexit handlers...
  exit(Status);
}

// jit_atexit - Used to intercept the "atexit" library call.
static int jit_atexit(void (*Fn)(void)) {
  AtExitHandlers.push_back(Fn);    // Take note of atexit handler...
  return 0;  // Always successful
}

//===----------------------------------------------------------------------===//
//
/// getPointerToNamedFunction - This method returns the address of the specified
/// function by using the dynamic loader interface.  As such it is only useful
/// for resolving library symbols, not code generated symbols.
///
void *JIT::getPointerToNamedFunction(const std::string &Name) {
  // Check to see if this is one of the functions we want to intercept.  Note,
  // we cast to intptr_t here to silence a -pedantic warning that complains
  // about casting a function pointer to a normal pointer.
  if (Name == "exit") return (void*)(intptr_t)&jit_exit;
  if (Name == "atexit") return (void*)(intptr_t)&jit_atexit;

  const char *NameStr = Name.c_str();
  // If this is an asm specifier, skip the sentinal.
  if (NameStr[0] == 1) ++NameStr;

  // If it's an external function, look it up in the process image...
  void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
  if (Ptr) return Ptr;

  // If it wasn't found and if it starts with an underscore ('_') character, and
  // has an asm specifier, try again without the underscore.
  if (Name[0] == 1 && NameStr[0] == '_') {
    Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
    if (Ptr) return Ptr;
  }

  // darwin/ppc adds $LDBLStub suffixes to various symbols like printf.  These
  // are references to hidden visibility symbols that dlsym cannot resolve.  If
  // we have one of these, strip off $LDBLStub and try again.
#if defined(__APPLE__) && defined(__ppc__)
  if (Name.size() > 9 && Name[Name.size()-9] == '$' &&
      memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0) {
    // First try turning $LDBLStub into $LDBL128.  If that fails, strip it off.
    // This mirrors logic in libSystemStubs.a.
    std::string Prefix = std::string(Name.begin(), Name.end()-9);
    if (void *Ptr = getPointerToNamedFunction(Prefix+"$LDBL128"))
      return Ptr;
    if (void *Ptr = getPointerToNamedFunction(Prefix))
      return Ptr;
  }
#endif

  /// If a LazyFunctionCreator is installed, use it to get/create the function.
  if (LazyFunctionCreator)
    if (void *RP = LazyFunctionCreator(Name))
      return RP;

  cerr << "ERROR: Program used external function '" << Name
       << "' which could not be resolved!\n";
  abort();
  return 0;
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 1998 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "sysdef.h"
#include "cscom/com.h"
#include "cs3d/glide2/g3dglide.h"

#ifdef OS_WIN32
#define DLL_NAME "Glide2xRender.dll"
#elif OS_LINUX
#define DLL_NAME "Glide2xRender.so"
#define IS_DEFAULT
#elif OS_MACOS
#define DLL_NAME "Glide2xRender.shlb"
#endif

extern const CLSID CLSID_Glide2xGraphics3D;

static int gb_cRef = 0;

static DllRegisterData gb_regData=
{
  &CLSID_Glide2xGraphics3D,
  "crystalspace.graphics3d.glide.2x",
  "csGraphics3D Glide2x Driver",
  DLL_NAME,
};

static DllRegisterData gb_regDataDefault=
{
  &CLSID_Glide2xGraphics3D,
  "crystalspace.graphics3d.glide",
  "csGraphics3D Glide2x Driver",
  DLL_NAME,
};

void STDAPICALLTYPE ModuleAddRef()
{
  gb_cRef++;
}

void STDAPICALLTYPE ModuleRelease()
{
  gb_cRef--;
}

#ifdef OS_WIN32

HINSTANCE DllHandle;

// our main entry point...should be called when we're loaded.
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD /*fdwReason*/, LPVOID /*lpvReserved*/)
{
  DllHandle = hinstDLL;

  return TRUE;
}

#endif

#if OS_LINUX || OS_MACOS
  STDAPI DllInitialize ()
  {
       csCoInitialize (0);

       return TRUE;
  }
#endif

// return S_OK if it's ok to unload us now.
STDAPI DllCanUnloadNow()
{
  return gb_cRef ? S_FALSE : S_OK;
}

// used to get a COM class object from us.
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv)
{
  static csGraphics3DGlide2xFactory factory;

  if (rclsid == CLSID_Glide2xGraphics3D)
    return factory.QueryInterface(riid, ppv);

  // if we get here, rclsid is a class we don't implement
  *ppv = NULL;
  return CLASS_E_CLASSNOTAVAILABLE;
}

// Called by RegSvr32.exe
STDAPI DllRegisterServer()
{
#ifdef IS_DEFAULT
  HRESULT hRes;

  hRes = csRegisterServer(&gb_regDataDefault);
  if (FAILED(hRes))
    return hRes;
#endif
  return csRegisterServer(&gb_regData);
}

// Called by RegSvr32.exe
STDAPI DllUnregisterServer()
{
#ifdef IS_DEFAULT
  HRESULT hRes;

  hRes = csRegisterServer(&gb_regDataDefault);
  if (FAILED(hRes))
    return hRes;
#endif
  return csUnregisterServer(&gb_regData);
}

// Implementation of the csGraphics2DGlide2x factory... ///////////

IMPLEMENT_UNKNOWN_NODELETE( csGraphics3DGlide2xFactory )

BEGIN_INTERFACE_TABLE( csGraphics3DGlide2xFactory )
IMPLEMENTS_INTERFACE( IGraphicsContextFactory )
END_INTERFACE_TABLE()

STDMETHODIMP csGraphics3DGlide2xFactory::CreateInstance(REFIID riid, ISystem* piSystem, void**ppv)
{
  if (!piSystem)
  {
    *ppv = 0;
    return E_INVALIDARG;
  }

  csGraphics3DGlide2x* pNew = new csGraphics3DGlide2x(piSystem);
  if (!pNew)
    {
      *ppv = 0;
      return E_OUTOFMEMORY;
    }

  return pNew->QueryInterface(riid, ppv);
}

STDMETHODIMP csGraphics3DGlide2xFactory::LockServer(BOOL bLock)
{
  if (bLock)
    gb_cRef++;
  else
    gb_cRef--;

  return S_OK;
}
<commit_msg>Support for Glide and BeOS.<commit_after>/*
    Copyright (C) 1998 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "sysdef.h"
#include "cscom/com.h"
#include "cs3d/glide2/g3dglide.h"

#ifdef OS_WIN32
#define DLL_NAME "Glide2xRender.dll"
#elif OS_BE
#define DLL_NAME "Glide2xRender.so"
#elif OS_LINUX
#define DLL_NAME "Glide2xRender.so"
#define IS_DEFAULT
#elif OS_MACOS
#define DLL_NAME "Glide2xRender.shlb"
#endif

extern const CLSID CLSID_Glide2xGraphics3D;

static int gb_cRef = 0;

static DllRegisterData gb_regData=
{
  &CLSID_Glide2xGraphics3D,
  "crystalspace.graphics3d.glide.2x",
  "csGraphics3D Glide2x Driver",
  DLL_NAME,
};

static DllRegisterData gb_regDataDefault=
{
  &CLSID_Glide2xGraphics3D,
  "crystalspace.graphics3d.glide",
  "csGraphics3D Glide2x Driver",
  DLL_NAME,
};

void STDAPICALLTYPE ModuleAddRef()
{
  gb_cRef++;
}

void STDAPICALLTYPE ModuleRelease()
{
  gb_cRef--;
}

#ifdef OS_WIN32

HINSTANCE DllHandle;

// our main entry point...should be called when we're loaded.
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD /*fdwReason*/, LPVOID /*lpvReserved*/)
{
  DllHandle = hinstDLL;

  return TRUE;
}

#endif

#if OS_LINUX || OS_MACOS  || OS_BE
  STDAPI DllInitialize ()
  {
       csCoInitialize (0);

       return TRUE;
  }
#endif

// return S_OK if it's ok to unload us now.
STDAPI DllCanUnloadNow()
{
  return gb_cRef ? S_FALSE : S_OK;
}

// used to get a COM class object from us.
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv)
{
  static csGraphics3DGlide2xFactory factory;

  if (rclsid == CLSID_Glide2xGraphics3D)
    return factory.QueryInterface(riid, ppv);

  // if we get here, rclsid is a class we don't implement
  *ppv = NULL;
  return CLASS_E_CLASSNOTAVAILABLE;
}

// Called by RegSvr32.exe
STDAPI DllRegisterServer()
{
#ifdef IS_DEFAULT
  HRESULT hRes;

  hRes = csRegisterServer(&gb_regDataDefault);
  if (FAILED(hRes))
    return hRes;
#endif
  return csRegisterServer(&gb_regData);
}

// Called by RegSvr32.exe
STDAPI DllUnregisterServer()
{
#ifdef IS_DEFAULT
  HRESULT hRes;

  hRes = csRegisterServer(&gb_regDataDefault);
  if (FAILED(hRes))
    return hRes;
#endif
  return csUnregisterServer(&gb_regData);
}

// Implementation of the csGraphics2DGlide2x factory... ///////////

IMPLEMENT_UNKNOWN_NODELETE( csGraphics3DGlide2xFactory )

BEGIN_INTERFACE_TABLE( csGraphics3DGlide2xFactory )
IMPLEMENTS_INTERFACE( IGraphicsContextFactory )
END_INTERFACE_TABLE()

STDMETHODIMP csGraphics3DGlide2xFactory::CreateInstance(REFIID riid, ISystem* piSystem, void**ppv)
{
  if (!piSystem)
  {
    *ppv = 0;
    return E_INVALIDARG;
  }

  csGraphics3DGlide2x* pNew = new csGraphics3DGlide2x(piSystem);
  if (!pNew)
    {
      *ppv = 0;
      return E_OUTOFMEMORY;
    }

  return pNew->QueryInterface(riid, ppv);
}

STDMETHODIMP csGraphics3DGlide2xFactory::LockServer(BOOL bLock)
{
  if (bLock)
    gb_cRef++;
  else
    gb_cRef--;

  return S_OK;
}
<|endoftext|>


<commit_before>#include "ExpertSystem/CLIPSEnvironment.h"

extern "C" {
#include "clips.h"
}

CLIPSEnvironment::CLIPSEnvironment() {
   environment = CreateEnvironment();
}
CLIPSEnvironment::~CLIPSEnvironment() {
   DestroyEnvironment(environment);
}

bool CLIPSEnvironment::environmentCreated() { return (environment != 0); }
void* CLIPSEnvironment::getEnvironment() { return environment; }
void CLIPSEnvironment::reset() {
   EnvReset(environment);
}
void CLIPSEnvironment::clear() {
   EnvClear(environment);
}
void CLIPSEnvironment::run(ExecutionDuration count) {
   if(count <= 0L) {
      EnvRun(environment, -1L);
   } else {
      EnvRun(environment, count);
   }
}
void CLIPSEnvironment::saveInstances(char* fileName) {
   EnvSaveInstances(environment, fileName, VISIBLE_SAVE, NULL, TRUE);
}
void CLIPSEnvironment::assertFact(char* str) {
   EnvAssertString(environment, str);
}
bool CLIPSEnvironment::makeInstances(char* str) {
   return EnvLoadInstancesFromString(environment, str, -1) != -1;
}
bool CLIPSEnvironment::makeInstance(char* str) {
   return (EnvMakeInstance(environment, str) != NULL);
}
void CLIPSEnvironment::batchStar(char* str) {
   EnvBatchStar(environment, str);
}
<commit_msg>Added the eval and build commands to CLIPSEnvironment.cpp<commit_after>#include "ExpertSystem/CLIPSEnvironment.h"

extern "C" {
#include "clips.h"
}

CLIPSEnvironment::CLIPSEnvironment() {
   environment = CreateEnvironment();
}
CLIPSEnvironment::~CLIPSEnvironment() {
   DestroyEnvironment(environment);
}

bool CLIPSEnvironment::environmentCreated() { return (environment != 0); }
void* CLIPSEnvironment::getEnvironment() { return environment; }
void CLIPSEnvironment::reset() {
   EnvReset(environment);
}
void CLIPSEnvironment::clear() {
   EnvClear(environment);
}
void CLIPSEnvironment::run(ExecutionDuration count) {
   if(count <= 0L) {
      EnvRun(environment, -1L);
   } else {
      EnvRun(environment, count);
   }
}
void CLIPSEnvironment::saveInstances(char* fileName) {
   EnvSaveInstances(environment, fileName, VISIBLE_SAVE, NULL, TRUE);
}
void CLIPSEnvironment::assertFact(char* str) {
   EnvAssertString(environment, str);
}
bool CLIPSEnvironment::makeInstances(char* str) {
   return EnvLoadInstancesFromString(environment, str, -1) != -1;
}
bool CLIPSEnvironment::makeInstance(char* str) {
   return (EnvMakeInstance(environment, str) != NULL);
}
void CLIPSEnvironment::batchStar(char* str) {
   EnvBatchStar(environment, str);
}

void CLIPSEnvironment::eval(char* stmt) {
   DATA_OBJECT tmp;
   EnvEval(environment, stmt, &tmp);
}

void CLIPSEnvironment::build(char* stmt) {
   EnvBuild(environment, stmt);
}
<|endoftext|>


<commit_before>//===--- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a concrete diagnostic client, which buffers the diagnostic messages.
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;

/// HandleDiagnostic - Store the errors, warnings, and notes that are
/// reported.
///
void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic::Level Level,
                                            const DiagnosticInfo &Info) {
  llvm::SmallString<100> StrC;
  Info.FormatDiagnostic(StrC);
  std::string Str(StrC.begin(), StrC.end());
  switch (Level) {
  default: assert(0 && "Diagnostic not handled during diagnostic buffering!");
  case Diagnostic::Note:
    Notes.push_back(std::make_pair(Info.getLocation(), Str));
    break;
  case Diagnostic::Warning:
    Warnings.push_back(std::make_pair(Info.getLocation(), Str));
    break;
  case Diagnostic::Error:
  case Diagnostic::Fatal:
    Errors.push_back(std::make_pair(Info.getLocation(), Str));
    break;
  }
}
<commit_msg>Simplify.<commit_after>//===--- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a concrete diagnostic client, which buffers the diagnostic messages.
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;

/// HandleDiagnostic - Store the errors, warnings, and notes that are
/// reported.
///
void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic::Level Level,
                                            const DiagnosticInfo &Info) {
  llvm::SmallString<100> Buf;
  Info.FormatDiagnostic(Buf);
  switch (Level) {
  default: assert(0 && "Diagnostic not handled during diagnostic buffering!");
  case Diagnostic::Note:
    Notes.push_back(std::make_pair(Info.getLocation(), Buf.str()));
    break;
  case Diagnostic::Warning:
    Warnings.push_back(std::make_pair(Info.getLocation(), Buf.str()));
    break;
  case Diagnostic::Error:
  case Diagnostic::Fatal:
    Errors.push_back(std::make_pair(Info.getLocation(), Buf.str()));
    break;
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * 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 "tango_data.h"

// Temp hack.
static const int kMaxVertCount = 61440;

TangoData::TangoData() : config_(nullptr) , pointcloud_timestamp_(0.0f) {
  depth_data_buffer_ = new float[kMaxVertCount * 3];
  depth_buffer_size_ = kMaxVertCount * 3;
  lib_version_ = new char[26];
}

/// Callback function when new XYZij data available, caller is responsible
/// for allocating the memory, and the memory will be released after the
/// callback function is over.
/// XYZij data updates in 5Hz.
static void onXYZijAvailable(const TangoXYZij* XYZ_ij) {
  memcpy(TangoData::GetInstance().GetDepthBuffer(), XYZ_ij->xyz,
         XYZ_ij->xyz_count * 3 * sizeof(float));
  TangoData::GetInstance().SetDepthBufferSize(XYZ_ij->xyz_count * 3);
}

bool TangoData::Initialize() {
  // Initialize Tango Service.
  if (TangoService_initialize() != TANGO_SUCCESS) {
    LOGE("TangoService_initialize(): Failed");
    return false;
  }
  return true;
}

bool TangoData::SetConfig() {
  // Allocate a TangoConfig object.
  if ((config_ = TangoConfig_alloc()) == NULL) {
    LOGE("TangoService_allocConfig(): Failed");
    return false;
  }

  // Get the default TangoConfig.
  if (TangoService_getConfig(TANGO_CONFIG_DEFAULT, config_) != TANGO_SUCCESS) {
    LOGE("TangoService_getConfig(): Failed");
    return false;
  }

  // Enable depth.
  if (TangoConfig_setBool(config_, "config_enable_depth", true) != TANGO_SUCCESS) {
    LOGI("config_enable_depth Failed");
    return false;
  }

  // Attach the onXYZijAvailable callback.
  if (TangoService_connectOnXYZijAvailable(onXYZijAvailable) != TANGO_SUCCESS) {
    LOGI("TangoService_connectOnXYZijAvailable(): Failed");
    return false;
  }

  return true;
}

bool TangoData::LockConfig() {
  // Lock in this configuration.
  if (TangoService_lockConfig(config_) != TANGO_SUCCESS) {
    LOGE("TangoService_lockConfig(): Failed");
    return false;
  }
  return true;
}

bool TangoData::UnlockConfig() {
  // Unlock current configuration.
  if (TangoService_unlockConfig() != TANGO_SUCCESS) {
    LOGE("TangoService_unlockConfig(): Failed");
    return false;
  }
  return true;
}

/// Connect to the Tango Service.
/// Note: connecting Tango service will start the motion
/// tracking automatically.
bool TangoData::Connect() {
  if (TangoService_connect() != TANGO_SUCCESS) {
    LOGE("TangoService_connect(): Failed");
    return false;
  }
  return true;
}

void TangoData::Disconnect() {
  // Disconnect application from Tango Service.
  TangoService_disconnect();
}

float* TangoData::GetDepthBuffer() {
  return depth_data_buffer_;
}

void TangoData::SetDepthBuffer(float* buffer) {
  depth_data_buffer_ = buffer;
}

int TangoData::GetDepthBufferSize() {
  return depth_buffer_size_;
}

void TangoData::SetDepthBufferSize(int size) {
  depth_buffer_size_ = size;
}

char* TangoData::GetVersonString() {
  TangoConfig_getString(config_, "tango_service_library_version", lib_version_, 26);
  return lib_version_;
}

TangoData::~TangoData() {
  delete[] depth_data_buffer_;
  delete[] lib_version_;
}
<commit_msg>change to 0828 API<commit_after>/*
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * 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 "tango_data.h"

// Temp hack.
static const int kMaxVertCount = 61440;

TangoData::TangoData() : config_(nullptr) , pointcloud_timestamp_(0.0f) {
  depth_data_buffer_ = new float[kMaxVertCount * 3];
  depth_buffer_size_ = kMaxVertCount * 3;
  lib_version_ = new char[26];
}

/// Callback function when new XYZij data available, caller is responsible
/// for allocating the memory, and the memory will be released after the
/// callback function is over.
/// XYZij data updates in 5Hz.
static void onXYZijAvailable(void* context, const TangoXYZij* XYZ_ij) {
  memcpy(TangoData::GetInstance().GetDepthBuffer(), XYZ_ij->xyz,
         XYZ_ij->xyz_count * 3 * sizeof(float));
  TangoData::GetInstance().SetDepthBufferSize(XYZ_ij->xyz_count * 3);
}

bool TangoData::Initialize() {
  // Initialize Tango Service.
  if (TangoService_initialize() != TANGO_SUCCESS) {
    LOGE("TangoService_initialize(): Failed");
    return false;
  }
  return true;
}

bool TangoData::SetConfig() {
  // Allocate a TangoConfig object.
  if ((config_ = TangoConfig_alloc()) == NULL) {
    LOGE("TangoService_allocConfig(): Failed");
    return false;
  }

  // Get the default TangoConfig.
  if (TangoService_getConfig(TANGO_CONFIG_DEFAULT, config_) != TANGO_SUCCESS) {
    LOGE("TangoService_getConfig(): Failed");
    return false;
  }

  // Enable depth.
  if (TangoConfig_setBool(config_, "config_enable_depth", true) != TANGO_SUCCESS) {
    LOGI("config_enable_depth Failed");
    return false;
  }

  // Attach the onXYZijAvailable callback.
  if (TangoService_connectOnXYZijAvailable(onXYZijAvailable) != TANGO_SUCCESS) {
    LOGI("TangoService_connectOnXYZijAvailable(): Failed");
    return false;
  }

  return true;
}

bool TangoData::LockConfig() {
  // Lock in this configuration.
  if (TangoService_lockConfig(config_) != TANGO_SUCCESS) {
    LOGE("TangoService_lockConfig(): Failed");
    return false;
  }
  return true;
}

bool TangoData::UnlockConfig() {
  // Unlock current configuration.
  if (TangoService_unlockConfig() != TANGO_SUCCESS) {
    LOGE("TangoService_unlockConfig(): Failed");
    return false;
  }
  return true;
}

/// Connect to the Tango Service.
/// Note: connecting Tango service will start the motion
/// tracking automatically.
bool TangoData::Connect() {
  if (TangoService_connect(nullptr) != TANGO_SUCCESS) {
    LOGE("TangoService_connect(): Failed");
    return false;
  }
  return true;
}

void TangoData::Disconnect() {
  // Disconnect application from Tango Service.
  TangoService_disconnect();
}

float* TangoData::GetDepthBuffer() {
  return depth_data_buffer_;
}

void TangoData::SetDepthBuffer(float* buffer) {
  depth_data_buffer_ = buffer;
}

int TangoData::GetDepthBufferSize() {
  return depth_buffer_size_;
}

void TangoData::SetDepthBufferSize(int size) {
  depth_buffer_size_ = size;
}

char* TangoData::GetVersonString() {
  TangoConfig_getString(config_, "tango_service_library_version", lib_version_, 26);
  return lib_version_;
}

TangoData::~TangoData() {
  delete[] depth_data_buffer_;
  delete[] lib_version_;
}
<|endoftext|>


<commit_before>/*
===========================================================================

Daemon GPL Source Code
Copyright (C) 2013 Unvanquished Developers

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Daemon Source Code 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

===========================================================================
*/

#include "Command.h"
#include "Log.h"

#include "../engine/qcommon/qcommon.h"
#include "../engine/framework/CommandSystem.h"
#include "../engine/framework/CvarSystem.h"

namespace Cmd {

    std::string Escape(Str::StringRef text) {
        std::string res = "\"";

        for (char c: text) {
            if (c == '\\') {
                res.append("\\\\");
            } else if (c == '\"') {
                res.append("\\\"");
            } else if (c == '$') {
                res.append("\\$");
            } else {
                res.push_back(c);
            }
        }

        res += "\"";
        return res;
    }

    static bool SkipSpaces(const char*& in, const char* end)
    {
        bool foundSpace = false;
        while (in != end) {
            // Handle spaces
            if ((in[0] & 0xff) <= ' ') {
                foundSpace = true;
                in++;
            } else if (in + 1 != end) {
                // Handle // comments
                if (in[0] == '/' && in[1] == '/') {
                    in = end;
                    return true;
                }
                // Handle /* */ comments
                if (in[0] == '/' && in[1] == '*') {
                    foundSpace = true;
                    in += 2;
                    while (in != end) {
                        if (in + 1 != end && in[0] == '*' && in[1] == '/') {
                            in += 2;
                            break;
                        } else {
                            in++;
                        }
                    }
                } else {
                    // Non-space character
                    return foundSpace;
                }
            } else {
                // Non-space character
                return foundSpace;
            }
        }
        return true;
    }

    const char* SplitCommand(const char* start, const char* end) {
        bool inQuote = false;
        bool inComment = false;
        bool inInlineComment = false;

        while (start != end) {
            //End of comment
            if (inInlineComment && start + 1 != end && start[0] == '*' && start[1] == '/') {
                inInlineComment = false;
                start += 2;
                continue;
            }

            //Ignore everything else in an inline comment
            if (inInlineComment) {
                start++;
                continue;
            }

            //Start of comment
            if (not inQuote && not inComment && start + 1 != end && start[0] == '/' && start[1] == '*') {
                inInlineComment = true;
                start += 2;
                continue;
            }
            if (not inQuote && start + 1 != end && start[0] == '/' && start[1] == '/') {
                inComment = true;
                start += 2;
                continue;
            }

            //Escaped character
            if (start + 1 != end && start[0] == '\\') {
                start += 2;
                continue;
            }

            //Quote
            if (start[0] == '"') {
                inQuote = !inQuote;
                start++;
                continue;
            }

            //Semicolon
            if (start[0] == ';' && !inQuote && !inComment) {
                return start + 1;
            }

            //Newline
            if (start[0] == '\n') {
                return start + 1;
            }

            //Normal character
            start++;
        }

        return end;
    }

    // Special escape function for cvar values
    static void EscapeCvarValue(std::string& text, bool inQuote) {
        for (auto it = text.begin(); it != text.end(); ++it) {
            if (*it == '\\')
                it = text.insert(it, '\\') + 1;
            else if (*it == '\"')
                it = text.insert(it, '\\') + 1;
            else if (*it == '$')
                it = text.insert(it, '\\') + 1;
            else if (!inQuote && *it == '/')
                it = text.insert(it, '\\') + 1;
            else if (!inQuote && *it == ';')
                it = text.insert(it, '\\') + 1;
        }
    }

    std::string SubstituteCvars(Str::StringRef text) {
        std::string out = text;
        auto in = out.begin();
        auto end = out.end();
        bool inQuote = false;
        bool inInlineComment = false;

        while (in != end) {
            //End of comment
            if (inInlineComment && in + 1 != end && in[0] == '*' && in[1] == '/') {
                inInlineComment = false;
                in += 2;
                continue;
            }

            //Ignore everything else in an inline comment
            if (inInlineComment) {
                in++;
                continue;
            }

            //Start of comment
            if (not inQuote && in + 1 != end && in[0] == '/' && in[1] == '*') {
                inInlineComment = true;
                in += 2;
                continue;
            }

            //Escaped character
            if (in + 1 != end && in[0] == '\\') {
                in += 2;
                continue;
            }

            //Quote
            if (in[0] == '"') {
                inQuote = !inQuote;
                in++;
                continue;
            }

            // Start of cvar substitution block
            if (in[0] == '$') {
                // Find the end of the block, only allow valid cvar name characters
                auto cvarStart = ++in;
                while (in[0] == '_' || in[0] == '.' ||
                       (in[0] >= 'a' && in[0] <= 'z') ||
                       (in[0] >= 'A' && in[0] <= 'Z') ||
                       (in[0] >= '0' && in[0] <= '9')) {
                    in++;
                }

                // If the block is not terminated properly, ignore it
                if (in[0] == '$') {
                    std::string cvarName(cvarStart, in);
                    std::string cvarValue = Cvar::GetValue(cvarName);
                    EscapeCvarValue(cvarValue, inQuote);

                    // Iterators get invalidated by replace
                    size_t stringPos = cvarStart - 1 - out.begin() + cvarValue.size();
                    out.replace(cvarStart - 1, in + 1, cvarValue);
                    in = out.begin() + stringPos;
                    end = out.end();
                }
                continue;
            }

            //Normal character
            in++;
        }

        return out;
    }

    bool IsValidCvarName(Str::StringRef text)
    {
        for (char c: text) {
            if (c >= 'a' && c <= 'z')
                continue;
            if (c >= 'A' && c <= 'Z')
                continue;
            if (c >= '0' && c <= '9')
                continue;
            if (c == '_' || c == '.')
                continue;
            return false;
        }
        return true;
    }

    bool IsValidCmdName(Str::StringRef text)
    {
        bool firstChar = true;
        for (char c: text) {
            // Allow command names starting with +/-
            if (firstChar && (c == '+' || c == '-')) {
                firstChar = false;
                continue;
            }
            firstChar = false;
            if (c >= 'a' && c <= 'z')
                continue;
            if (c >= 'A' && c <= 'Z')
                continue;
            if (c >= '0' && c <= '9')
                continue;
            if (c == '_' || c == '.')
                continue;
            return false;
        }
        return true;
    }

    /*
    ===============================================================================

    Cmd::CmdArgs

    ===============================================================================
    */

    Args::Args() {
    }

    Args::Args(std::vector<std::string> args_) {
        args = std::move(args_);
    }

    Args::Args(Str::StringRef cmd) {
        const char* in = cmd.begin();

        //Skip leading whitespace
        SkipSpaces(in, cmd.end());

        //Return if the cmd is empty
        if (in == cmd.end())
            return;

        //Build arg tokens
        std::string currentToken;
        while (true) {
            //Check for end of current token
            if (SkipSpaces(in, cmd.end())) {
                 args.push_back(std::move(currentToken));
                 if (in == cmd.end())
                    return;
                 currentToken.clear();
            }

            //Handle quoted strings
            if (in[0] == '\"') {
                in++;
                //Read all characters until quote end
                while (in != cmd.end()) {
                    if (in[0] == '\"') {
                        in++;
                        break;
                    } else if (in + 1 !=  cmd.end() && in[0] == '\\') {
                        currentToken.push_back(in[1]);
                        in += 2;
                    } else {
                        currentToken.push_back(in[0]);
                        in++;
                    }
                }
            } else {
                if (in + 1 !=  cmd.end() && in[0] == '\\') {
                    currentToken.push_back(in[1]);
                    in += 2;
                } else {
                    currentToken.push_back(in[0]);
                    in++;
                }
            }
        }
    }

    int Args::Argc() const {
        return args.size();
    }

    const std::string& Args::Argv(int argNum) const {
        return args[argNum];
    }

    std::string Args::EscapedArgs(int start, int end) const {
        std::string res;

        if (end < 0) {
            end = args.size() - 1;
        }

        for (int i = start; i < end + 1; i++) {
            if (i != start) {
                res += " ";
            }
            res += Escape(args[i]);
        }

        return res;
    }

    std::string Args::ConcatArgs(int start, int end) const {
        std::string res;

        if (end < 0) {
            end = args.size() - 1;
        }

        for (int i = start; i < end + 1; i++) {
            if (i != start) {
                res += " ";
            }
            res += args[i];
        }

        return res;
    }

    const std::vector<std::string>& Args::ArgVector() const {
        return args;
    }

    int Args::size() const {
        return Argc();
    }

    const std::string& Args::operator[] (int argNum) const {
        return Argv(argNum);
    }

    /*
    ===============================================================================

    Cmd::CmdBase

    ===============================================================================
    */

    CmdBase::CmdBase(const int flags): flags(flags) {
    }

    CompletionResult CmdBase::Complete(int argNum, const Args& args, Str::StringRef prefix) const {
        Q_UNUSED(argNum);
        Q_UNUSED(args);
        Q_UNUSED(prefix);
        return {};
    }

    void CmdBase::PrintUsage(const Args& args, Str::StringRef syntax, Str::StringRef description) const {
        if(description.empty()) {
            Print("%s: %s %s", _("usage"), args.Argv(0).c_str(), syntax.c_str());
        } else {
            Print("%s: %s %s — %s", _("usage"), args.Argv(0).c_str(), syntax.c_str(), description.c_str());
        }
    }

    int CmdBase::GetFlags() const {
        return flags;
    }

    void CmdBase::ExecuteAfter(Str::StringRef text, bool parseCvars) const {
        GetEnv().ExecuteAfter(text, parseCvars);
    }

    Environment& CmdBase::GetEnv() const {
        return *Cmd::GetEnv();
    }

    StaticCmd::StaticCmd(std::string name, const int flags, std::string description)
    :CmdBase(flags){
        //Register this command statically
        AddCommand(std::move(name), *this, std::move(description));
    }

}
<commit_msg>Don't unnecessarily quote escaped strings.<commit_after>/*
===========================================================================

Daemon GPL Source Code
Copyright (C) 2013 Unvanquished Developers

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Daemon Source Code 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

===========================================================================
*/

#include "Command.h"
#include "Log.h"

#include "../engine/qcommon/qcommon.h"
#include "../engine/framework/CommandSystem.h"
#include "../engine/framework/CvarSystem.h"

namespace Cmd {

    std::string Escape(Str::StringRef text) {
        bool escaped = false;
        std::string res = "\"";

        for (char c: text) {
            if (c == '\\') {
                res.append("\\\\");
            } else if (c == '\"') {
                res.append("\\\"");
            } else if (c == '$') {
                res.append("\\$");
            } else {
                if (c == ' ' || c == ';') {
                    escaped = true;
                }
                res.push_back(c);
            }
        }

        if (escaped || res.length() == 0) {
            res += "\"";
        } else {
            res.erase(0, 1);
        }

        return res;
    }

    static bool SkipSpaces(const char*& in, const char* end)
    {
        bool foundSpace = false;
        while (in != end) {
            // Handle spaces
            if ((in[0] & 0xff) <= ' ') {
                foundSpace = true;
                in++;
            } else if (in + 1 != end) {
                // Handle // comments
                if (in[0] == '/' && in[1] == '/') {
                    in = end;
                    return true;
                }
                // Handle /* */ comments
                if (in[0] == '/' && in[1] == '*') {
                    foundSpace = true;
                    in += 2;
                    while (in != end) {
                        if (in + 1 != end && in[0] == '*' && in[1] == '/') {
                            in += 2;
                            break;
                        } else {
                            in++;
                        }
                    }
                } else {
                    // Non-space character
                    return foundSpace;
                }
            } else {
                // Non-space character
                return foundSpace;
            }
        }
        return true;
    }

    const char* SplitCommand(const char* start, const char* end) {
        bool inQuote = false;
        bool inComment = false;
        bool inInlineComment = false;

        while (start != end) {
            //End of comment
            if (inInlineComment && start + 1 != end && start[0] == '*' && start[1] == '/') {
                inInlineComment = false;
                start += 2;
                continue;
            }

            //Ignore everything else in an inline comment
            if (inInlineComment) {
                start++;
                continue;
            }

            //Start of comment
            if (not inQuote && not inComment && start + 1 != end && start[0] == '/' && start[1] == '*') {
                inInlineComment = true;
                start += 2;
                continue;
            }
            if (not inQuote && start + 1 != end && start[0] == '/' && start[1] == '/') {
                inComment = true;
                start += 2;
                continue;
            }

            //Escaped character
            if (start + 1 != end && start[0] == '\\') {
                start += 2;
                continue;
            }

            //Quote
            if (start[0] == '"') {
                inQuote = !inQuote;
                start++;
                continue;
            }

            //Semicolon
            if (start[0] == ';' && !inQuote && !inComment) {
                return start + 1;
            }

            //Newline
            if (start[0] == '\n') {
                return start + 1;
            }

            //Normal character
            start++;
        }

        return end;
    }

    // Special escape function for cvar values
    static void EscapeCvarValue(std::string& text, bool inQuote) {
        for (auto it = text.begin(); it != text.end(); ++it) {
            if (*it == '\\')
                it = text.insert(it, '\\') + 1;
            else if (*it == '\"')
                it = text.insert(it, '\\') + 1;
            else if (*it == '$')
                it = text.insert(it, '\\') + 1;
            else if (!inQuote && *it == '/')
                it = text.insert(it, '\\') + 1;
            else if (!inQuote && *it == ';')
                it = text.insert(it, '\\') + 1;
        }
    }

    std::string SubstituteCvars(Str::StringRef text) {
        std::string out = text;
        auto in = out.begin();
        auto end = out.end();
        bool inQuote = false;
        bool inInlineComment = false;

        while (in != end) {
            //End of comment
            if (inInlineComment && in + 1 != end && in[0] == '*' && in[1] == '/') {
                inInlineComment = false;
                in += 2;
                continue;
            }

            //Ignore everything else in an inline comment
            if (inInlineComment) {
                in++;
                continue;
            }

            //Start of comment
            if (not inQuote && in + 1 != end && in[0] == '/' && in[1] == '*') {
                inInlineComment = true;
                in += 2;
                continue;
            }

            //Escaped character
            if (in + 1 != end && in[0] == '\\') {
                in += 2;
                continue;
            }

            //Quote
            if (in[0] == '"') {
                inQuote = !inQuote;
                in++;
                continue;
            }

            // Start of cvar substitution block
            if (in[0] == '$') {
                // Find the end of the block, only allow valid cvar name characters
                auto cvarStart = ++in;
                while (in[0] == '_' || in[0] == '.' ||
                       (in[0] >= 'a' && in[0] <= 'z') ||
                       (in[0] >= 'A' && in[0] <= 'Z') ||
                       (in[0] >= '0' && in[0] <= '9')) {
                    in++;
                }

                // If the block is not terminated properly, ignore it
                if (in[0] == '$') {
                    std::string cvarName(cvarStart, in);
                    std::string cvarValue = Cvar::GetValue(cvarName);
                    EscapeCvarValue(cvarValue, inQuote);

                    // Iterators get invalidated by replace
                    size_t stringPos = cvarStart - 1 - out.begin() + cvarValue.size();
                    out.replace(cvarStart - 1, in + 1, cvarValue);
                    in = out.begin() + stringPos;
                    end = out.end();
                }
                continue;
            }

            //Normal character
            in++;
        }

        return out;
    }

    bool IsValidCvarName(Str::StringRef text)
    {
        for (char c: text) {
            if (c >= 'a' && c <= 'z')
                continue;
            if (c >= 'A' && c <= 'Z')
                continue;
            if (c >= '0' && c <= '9')
                continue;
            if (c == '_' || c == '.')
                continue;
            return false;
        }
        return true;
    }

    bool IsValidCmdName(Str::StringRef text)
    {
        bool firstChar = true;
        for (char c: text) {
            // Allow command names starting with +/-
            if (firstChar && (c == '+' || c == '-')) {
                firstChar = false;
                continue;
            }
            firstChar = false;
            if (c >= 'a' && c <= 'z')
                continue;
            if (c >= 'A' && c <= 'Z')
                continue;
            if (c >= '0' && c <= '9')
                continue;
            if (c == '_' || c == '.')
                continue;
            return false;
        }
        return true;
    }

    /*
    ===============================================================================

    Cmd::CmdArgs

    ===============================================================================
    */

    Args::Args() {
    }

    Args::Args(std::vector<std::string> args_) {
        args = std::move(args_);
    }

    Args::Args(Str::StringRef cmd) {
        const char* in = cmd.begin();

        //Skip leading whitespace
        SkipSpaces(in, cmd.end());

        //Return if the cmd is empty
        if (in == cmd.end())
            return;

        //Build arg tokens
        std::string currentToken;
        while (true) {
            //Check for end of current token
            if (SkipSpaces(in, cmd.end())) {
                 args.push_back(std::move(currentToken));
                 if (in == cmd.end())
                    return;
                 currentToken.clear();
            }

            //Handle quoted strings
            if (in[0] == '\"') {
                in++;
                //Read all characters until quote end
                while (in != cmd.end()) {
                    if (in[0] == '\"') {
                        in++;
                        break;
                    } else if (in + 1 !=  cmd.end() && in[0] == '\\') {
                        currentToken.push_back(in[1]);
                        in += 2;
                    } else {
                        currentToken.push_back(in[0]);
                        in++;
                    }
                }
            } else {
                if (in + 1 !=  cmd.end() && in[0] == '\\') {
                    currentToken.push_back(in[1]);
                    in += 2;
                } else {
                    currentToken.push_back(in[0]);
                    in++;
                }
            }
        }
    }

    int Args::Argc() const {
        return args.size();
    }

    const std::string& Args::Argv(int argNum) const {
        return args[argNum];
    }

    std::string Args::EscapedArgs(int start, int end) const {
        std::string res;

        if (end < 0) {
            end = args.size() - 1;
        }

        for (int i = start; i < end + 1; i++) {
            if (i != start) {
                res += " ";
            }
            res += Escape(args[i]);
        }

        return res;
    }

    std::string Args::ConcatArgs(int start, int end) const {
        std::string res;

        if (end < 0) {
            end = args.size() - 1;
        }

        for (int i = start; i < end + 1; i++) {
            if (i != start) {
                res += " ";
            }
            res += args[i];
        }

        return res;
    }

    const std::vector<std::string>& Args::ArgVector() const {
        return args;
    }

    int Args::size() const {
        return Argc();
    }

    const std::string& Args::operator[] (int argNum) const {
        return Argv(argNum);
    }

    /*
    ===============================================================================

    Cmd::CmdBase

    ===============================================================================
    */

    CmdBase::CmdBase(const int flags): flags(flags) {
    }

    CompletionResult CmdBase::Complete(int argNum, const Args& args, Str::StringRef prefix) const {
        Q_UNUSED(argNum);
        Q_UNUSED(args);
        Q_UNUSED(prefix);
        return {};
    }

    void CmdBase::PrintUsage(const Args& args, Str::StringRef syntax, Str::StringRef description) const {
        if(description.empty()) {
            Print("%s: %s %s", _("usage"), args.Argv(0).c_str(), syntax.c_str());
        } else {
            Print("%s: %s %s — %s", _("usage"), args.Argv(0).c_str(), syntax.c_str(), description.c_str());
        }
    }

    int CmdBase::GetFlags() const {
        return flags;
    }

    void CmdBase::ExecuteAfter(Str::StringRef text, bool parseCvars) const {
        GetEnv().ExecuteAfter(text, parseCvars);
    }

    Environment& CmdBase::GetEnv() const {
        return *Cmd::GetEnv();
    }

    StaticCmd::StaticCmd(std::string name, const int flags, std::string description)
    :CmdBase(flags){
        //Register this command statically
        AddCommand(std::move(name), *this, std::move(description));
    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// 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.

namespace iox
{
namespace concurrent
{
template <class ValueType, uint32_t CapacityValue>
SoFi<ValueType, CapacityValue>::SoFi() noexcept
{
}

template <class ValueType, uint32_t CapacityValue>
uint64_t SoFi<ValueType, CapacityValue>::capacity() const noexcept
{
    return m_size - INTERNAL_SIZE_ADD_ON;
}

template <class ValueType, uint32_t CapacityValue>
uint64_t SoFi<ValueType, CapacityValue>::size() const noexcept
{
    uint64_t readPosition;
    uint64_t writePosition;
    do
    {
        readPosition = m_readPosition.load(std::memory_order_relaxed);
        writePosition = m_writePosition.load(std::memory_order_relaxed);
    } while (m_writePosition.load(std::memory_order_relaxed) != writePosition
             || m_readPosition.load(std::memory_order_relaxed) != readPosition);

    return writePosition - readPosition;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::resize(const uint32_t newSize) noexcept
{
    uint64_t newInternalSize = newSize + INTERNAL_SIZE_ADD_ON;
    if (empty() && (newInternalSize <= INTERNAL_SOFI_SIZE))
    {
        m_size = newInternalSize;

        m_readPosition.store(0u, std::memory_order_release);
        m_writePosition.store(0u, std::memory_order_release);

        return true;
    }

    return false;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::empty() const noexcept
{
    uint64_t currentReadPosition;
    bool isEmpty;

    do
    {
        /// @todo read before write since the writer increments the aba counter!!!
        /// @todo write doc with example!!!
        currentReadPosition = m_readPosition.load(std::memory_order_acquire);
        uint64_t currentWritePosition = m_writePosition.load(std::memory_order_acquire);

        isEmpty = (currentWritePosition == currentReadPosition);
        // we need compare without exchange
    } while (!(currentReadPosition == m_readPosition.load(std::memory_order_acquire)));

    return isEmpty;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::pop(ValueType& valueOut) noexcept
{
    return popIf(valueOut, [](ValueType) { return true; });
}

template <class ValueType, uint32_t CapacityValue>
template <typename Verificator_T>
inline bool SoFi<ValueType, CapacityValue>::popIf(ValueType& valueOut, const Verificator_T& verificator) noexcept
{
    uint64_t currentReadPosition = m_readPosition.load(std::memory_order_acquire);
    uint64_t nextReadPosition;

    bool popWasSuccessful{true};
    do
    {
        if (currentReadPosition == m_writePosition.load(std::memory_order_acquire))
        {
            nextReadPosition = currentReadPosition;
            popWasSuccessful = false;
        }
        else
        {
            // we use memcpy here, since the copy assignment is not thread safe in general (we might have an overflow in
            // the push thread and invalidates the object while the copy is running and therefore works on an
            // invalid object); memcpy is also not thread safe, but we discard the object anyway and read it
            // again if its overwritten in between; this is only relevant for types larger than pointer size
            // assign the user data
            std::memcpy(&valueOut, &m_data[static_cast<int32_t>(currentReadPosition) % m_size], sizeof(ValueType));

            /// @brief first we need to peak valueOut if it is fitting the condition and then we have to verify
            ///        if valueOut is not am invalid object, this could be the case if the read position has
            ///        changed
            if (m_readPosition.load(std::memory_order_relaxed) == currentReadPosition && verificator(valueOut) == false)
            {
                popWasSuccessful = false;
            }
            else
            {
                nextReadPosition = currentReadPosition + 1U;
                popWasSuccessful = true;
            }
        }

        // compare and swap
        // if(m_readPosition == currentReadPosition)
        //     m_readPosition = l_next_aba_read_pos
        // else
        //     currentReadPosition = m_readPosition
        // Assign m_aba_read_p to next readable location
    } while (!m_readPosition.compare_exchange_weak(
        currentReadPosition, nextReadPosition, std::memory_order_acq_rel, std::memory_order_acquire));

    return popWasSuccessful;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::push(const ValueType& valueOut, ValueType& f_paramOut_r) noexcept
{
    constexpr bool OVERFLOW{false};

    uint64_t currentWritePosition = m_writePosition.load(std::memory_order_relaxed);
    uint64_t nextWritePosition = currentWritePosition + 1U;

    m_data[static_cast<int32_t>(currentWritePosition) % m_size] = valueOut;
    m_writePosition.store(nextWritePosition, std::memory_order_release);

    uint64_t currentReadPosition = m_readPosition.load(std::memory_order_acquire);

    // check if there is a free position for the next push
    if (nextWritePosition < currentReadPosition + m_size)
    {
        return !OVERFLOW;
    }

    // this is an overflow situation, which means that the next push has no free position, therefore the oldest value
    // needs to be passed back to the caller

    uint64_t nextReadPosition = currentReadPosition + 1U;

    // we need to update the read position
    // a) it works, then we need to pass the overflow value back
    // b) it doesn't work, which means that the pop thread already took the value in the meantime an no further action
    // is required
    // memory order success is memory_order_acq_rel
    //   - this is to prevent the reordering of m_writePosition.store(...) after the increment of the m_readPosition
    //     - in case of an overflow, this might result in the pop thread getting one element less than the capacity of
    //       the SoFi if the push thread is suspended in between this two statements
    //     - it's still possible to get more elements than the capacity, but this is an inherent issue with concurrent
    //       queues and cannot be prevented since there can always be a push during a pop operation
    //   - another issue might be that two consecutive pushes (not concurrent) happen on different CPU cores without
    //     synchronization, then the memory also needs to be synchronized for the overflow case
    // memory order failure is memory_order_relaxed since there is no further synchronization needed if there is no
    // overflow
    if (m_readPosition.compare_exchange_strong(
            currentReadPosition, nextReadPosition, std::memory_order_acq_rel, std::memory_order_relaxed))
    {
        std::memcpy(&f_paramOut_r, &m_data[static_cast<int32_t>(currentReadPosition) % m_size], sizeof(ValueType));
        return OVERFLOW;
    }

    return !OVERFLOW;
}

} // namespace concurrent
} // namespace iox
<commit_msg>iox-#32 fix compiler error in sofi.inl:142<commit_after>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// 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.

namespace iox
{
namespace concurrent
{
template <class ValueType, uint32_t CapacityValue>
SoFi<ValueType, CapacityValue>::SoFi() noexcept
{
}

template <class ValueType, uint32_t CapacityValue>
uint64_t SoFi<ValueType, CapacityValue>::capacity() const noexcept
{
    return m_size - INTERNAL_SIZE_ADD_ON;
}

template <class ValueType, uint32_t CapacityValue>
uint64_t SoFi<ValueType, CapacityValue>::size() const noexcept
{
    uint64_t readPosition;
    uint64_t writePosition;
    do
    {
        readPosition = m_readPosition.load(std::memory_order_relaxed);
        writePosition = m_writePosition.load(std::memory_order_relaxed);
    } while (m_writePosition.load(std::memory_order_relaxed) != writePosition
             || m_readPosition.load(std::memory_order_relaxed) != readPosition);

    return writePosition - readPosition;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::resize(const uint32_t newSize) noexcept
{
    uint64_t newInternalSize = newSize + INTERNAL_SIZE_ADD_ON;
    if (empty() && (newInternalSize <= INTERNAL_SOFI_SIZE))
    {
        m_size = newInternalSize;

        m_readPosition.store(0u, std::memory_order_release);
        m_writePosition.store(0u, std::memory_order_release);

        return true;
    }

    return false;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::empty() const noexcept
{
    uint64_t currentReadPosition;
    bool isEmpty;

    do
    {
        /// @todo read before write since the writer increments the aba counter!!!
        /// @todo write doc with example!!!
        currentReadPosition = m_readPosition.load(std::memory_order_acquire);
        uint64_t currentWritePosition = m_writePosition.load(std::memory_order_acquire);

        isEmpty = (currentWritePosition == currentReadPosition);
        // we need compare without exchange
    } while (!(currentReadPosition == m_readPosition.load(std::memory_order_acquire)));

    return isEmpty;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::pop(ValueType& valueOut) noexcept
{
    return popIf(valueOut, [](ValueType) { return true; });
}

template <class ValueType, uint32_t CapacityValue>
template <typename Verificator_T>
inline bool SoFi<ValueType, CapacityValue>::popIf(ValueType& valueOut, const Verificator_T& verificator) noexcept
{
    uint64_t currentReadPosition = m_readPosition.load(std::memory_order_acquire);
    uint64_t nextReadPosition;

    bool popWasSuccessful{true};
    do
    {
        if (currentReadPosition == m_writePosition.load(std::memory_order_acquire))
        {
            nextReadPosition = currentReadPosition;
            popWasSuccessful = false;
        }
        else
        {
            // we use memcpy here, since the copy assignment is not thread safe in general (we might have an overflow in
            // the push thread and invalidates the object while the copy is running and therefore works on an
            // invalid object); memcpy is also not thread safe, but we discard the object anyway and read it
            // again if its overwritten in between; this is only relevant for types larger than pointer size
            // assign the user data
            std::memcpy(&valueOut, &m_data[static_cast<int32_t>(currentReadPosition) % m_size], sizeof(ValueType));

            /// @brief first we need to peak valueOut if it is fitting the condition and then we have to verify
            ///        if valueOut is not am invalid object, this could be the case if the read position has
            ///        changed
            if (m_readPosition.load(std::memory_order_relaxed) == currentReadPosition && verificator(valueOut) == false)
            {
                popWasSuccessful = false;
            }
            else
            {
                nextReadPosition = currentReadPosition + 1U;
                popWasSuccessful = true;
            }
        }

        // compare and swap
        // if(m_readPosition == currentReadPosition)
        //     m_readPosition = l_next_aba_read_pos
        // else
        //     currentReadPosition = m_readPosition
        // Assign m_aba_read_p to next readable location
    } while (!m_readPosition.compare_exchange_weak(
        currentReadPosition, nextReadPosition, std::memory_order_acq_rel, std::memory_order_acquire));

    return popWasSuccessful;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::push(const ValueType& valueOut, ValueType& f_paramOut_r) noexcept
{
    constexpr bool SOFI_OVERFLOW{false};

    uint64_t currentWritePosition = m_writePosition.load(std::memory_order_relaxed);
    uint64_t nextWritePosition = currentWritePosition + 1U;

    m_data[static_cast<int32_t>(currentWritePosition) % m_size] = valueOut;
    m_writePosition.store(nextWritePosition, std::memory_order_release);

    uint64_t currentReadPosition = m_readPosition.load(std::memory_order_acquire);

    // check if there is a free position for the next push
    if (nextWritePosition < currentReadPosition + m_size)
    {
        return !SOFI_OVERFLOW;
    }

    // this is an overflow situation, which means that the next push has no free position, therefore the oldest value
    // needs to be passed back to the caller

    uint64_t nextReadPosition = currentReadPosition + 1U;

    // we need to update the read position
    // a) it works, then we need to pass the overflow value back
    // b) it doesn't work, which means that the pop thread already took the value in the meantime an no further action
    // is required
    // memory order success is memory_order_acq_rel
    //   - this is to prevent the reordering of m_writePosition.store(...) after the increment of the m_readPosition
    //     - in case of an overflow, this might result in the pop thread getting one element less than the capacity of
    //       the SoFi if the push thread is suspended in between this two statements
    //     - it's still possible to get more elements than the capacity, but this is an inherent issue with concurrent
    //       queues and cannot be prevented since there can always be a push during a pop operation
    //   - another issue might be that two consecutive pushes (not concurrent) happen on different CPU cores without
    //     synchronization, then the memory also needs to be synchronized for the overflow case
    // memory order failure is memory_order_relaxed since there is no further synchronization needed if there is no
    // overflow
    if (m_readPosition.compare_exchange_strong(
            currentReadPosition, nextReadPosition, std::memory_order_acq_rel, std::memory_order_relaxed))
    {
        std::memcpy(&f_paramOut_r, &m_data[static_cast<int32_t>(currentReadPosition) % m_size], sizeof(ValueType));
        return SOFI_OVERFLOW;
    }

    return !SOFI_OVERFLOW;
}

} // namespace concurrent
} // namespace iox
<|endoftext|>


<commit_before>//===---------- IssueHash.cpp - Generate identification hashes --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"

#include <functional>
#include <sstream>
#include <string>

using namespace clang;

// Get a string representation of the parts of the signature that can be
// overloaded on.
static std::string GetSignature(const FunctionDecl *Target) {
  if (!Target)
    return "";
  std::string Signature;

  if (!isa<CXXConstructorDecl>(Target) && !isa<CXXDestructorDecl>(Target) &&
      !isa<CXXConversionDecl>(Target))
    Signature.append(Target->getReturnType().getAsString()).append(" ");
  Signature.append(Target->getQualifiedNameAsString()).append("(");

  for (int i = 0, paramsCount = Target->getNumParams(); i < paramsCount; ++i) {
    if (i)
      Signature.append(", ");
    Signature.append(Target->getParamDecl(i)->getType().getAsString());
  }

  if (Target->isVariadic())
    Signature.append(", ...");
  Signature.append(")");

  const auto *TargetT =
      llvm::dyn_cast_or_null<FunctionType>(Target->getType().getTypePtr());

  if (!TargetT || !isa<CXXMethodDecl>(Target))
    return Signature;

  if (TargetT->isConst())
    Signature.append(" const");
  if (TargetT->isVolatile())
    Signature.append(" volatile");
  if (TargetT->isRestrict())
    Signature.append(" restrict");

  if (const auto *TargetPT =
          dyn_cast_or_null<FunctionProtoType>(Target->getType().getTypePtr())) {
    switch (TargetPT->getRefQualifier()) {
    case RQ_LValue:
      Signature.append(" &");
      break;
    case RQ_RValue:
      Signature.append(" &&");
      break;
    default:
      break;
    }
  }

  return Signature;
}

static std::string GetEnclosingDeclContextSignature(const Decl *D) {
  if (!D)
    return "";

  if (const auto *ND = dyn_cast<NamedDecl>(D)) {
    std::string DeclName;

    switch (ND->getKind()) {
    case Decl::Namespace:
    case Decl::Record:
    case Decl::CXXRecord:
    case Decl::Enum:
      DeclName = ND->getQualifiedNameAsString();
      break;
    case Decl::CXXConstructor:
    case Decl::CXXDestructor:
    case Decl::CXXConversion:
    case Decl::CXXMethod:
    case Decl::Function:
      DeclName = GetSignature(dyn_cast_or_null<FunctionDecl>(ND));
      break;
    case Decl::ObjCMethod:
      // ObjC Methods can not be overloaded, qualified name uniquely identifies
      // the method.
      DeclName = ND->getQualifiedNameAsString();
      break;
    default:
      break;
    }

    return DeclName;
  }

  return "";
}

static StringRef GetNthLineOfFile(llvm::MemoryBuffer *Buffer, int Line) {
  if (!Buffer)
    return "";

  llvm::line_iterator LI(*Buffer, false);
  for (; !LI.is_at_eof() && LI.line_number() != Line; ++LI)
    ;

  return *LI;
}

static std::string NormalizeLine(const SourceManager &SM, FullSourceLoc &L,
                                 const LangOptions &LangOpts) {
  static StringRef Whitespaces = " \t\n";

  StringRef Str = GetNthLineOfFile(SM.getBuffer(L.getFileID(), L),
                                   L.getExpansionLineNumber());
  unsigned col = Str.find_first_not_of(Whitespaces);
  col++;
  SourceLocation StartOfLine =
      SM.translateLineCol(SM.getFileID(L), L.getExpansionLineNumber(), col);
  llvm::MemoryBuffer *Buffer =
      SM.getBuffer(SM.getFileID(StartOfLine), StartOfLine);
  if (!Buffer)
    return {};

  const char *BufferPos = SM.getCharacterData(StartOfLine);

  Token Token;
  Lexer Lexer(SM.getLocForStartOfFile(SM.getFileID(StartOfLine)), LangOpts,
              Buffer->getBufferStart(), BufferPos, Buffer->getBufferEnd());

  size_t NextStart = 0;
  std::ostringstream LineBuff;
  while (!Lexer.LexFromRawLexer(Token) && NextStart < 2) {
    if (Token.isAtStartOfLine() && NextStart++ > 0)
      continue;
    LineBuff << std::string(SM.getCharacterData(Token.getLocation()),
                            Token.getLength());
  }

  return LineBuff.str();
}

static llvm::SmallString<32> GetHashOfContent(StringRef Content) {
  llvm::MD5 Hash;
  llvm::MD5::MD5Result MD5Res;
  SmallString<32> Res;

  Hash.update(Content);
  Hash.final(MD5Res);
  llvm::MD5::stringifyResult(MD5Res, Res);

  return Res;
}

std::string clang::GetIssueString(const SourceManager &SM,
                                  FullSourceLoc &IssueLoc,
                                  StringRef CheckerName, StringRef BugType,
                                  const Decl *D,
                                  const LangOptions &LangOpts) {
  static StringRef Delimiter = "$";

  return (llvm::Twine(CheckerName) + Delimiter +
          GetEnclosingDeclContextSignature(D) + Delimiter +
          Twine(IssueLoc.getExpansionColumnNumber()) + Delimiter +
          NormalizeLine(SM, IssueLoc, LangOpts) + Delimiter + BugType)
      .str();
}

SmallString<32> clang::GetIssueHash(const SourceManager &SM,
                                    FullSourceLoc &IssueLoc,
                                    StringRef CheckerName, StringRef BugType,
                                    const Decl *D,
                                    const LangOptions &LangOpts) {

  return GetHashOfContent(
      GetIssueString(SM, IssueLoc, CheckerName, BugType, D, LangOpts));
}
<commit_msg>Propagating prior merge from 'llvm.org/master'.<commit_after>//===---------- IssueHash.cpp - Generate identification hashes --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"

#include <functional>
#include <sstream>
#include <string>

using namespace clang;

// Get a string representation of the parts of the signature that can be
// overloaded on.
static std::string GetSignature(const FunctionDecl *Target) {
  if (!Target)
    return "";
  std::string Signature;

  if (!isa<CXXConstructorDecl>(Target) && !isa<CXXDestructorDecl>(Target) &&
      !isa<CXXConversionDecl>(Target))
    Signature.append(Target->getReturnType().getAsString()).append(" ");
  Signature.append(Target->getQualifiedNameAsString()).append("(");

  for (int i = 0, paramsCount = Target->getNumParams(); i < paramsCount; ++i) {
    if (i)
      Signature.append(", ");
    Signature.append(Target->getParamDecl(i)->getType().getAsString());
  }

  if (Target->isVariadic())
    Signature.append(", ...");
  Signature.append(")");

  const auto *TargetT =
      llvm::dyn_cast_or_null<FunctionType>(Target->getType().getTypePtr());

  if (!TargetT || !isa<CXXMethodDecl>(Target))
    return Signature;

  if (TargetT->isConst())
    Signature.append(" const");
  if (TargetT->isVolatile())
    Signature.append(" volatile");
  if (TargetT->isRestrict())
    Signature.append(" restrict");

  if (const auto *TargetPT =
          dyn_cast_or_null<FunctionProtoType>(Target->getType().getTypePtr())) {
    switch (TargetPT->getRefQualifier()) {
    case RQ_LValue:
      Signature.append(" &");
      break;
    case RQ_RValue:
      Signature.append(" &&");
      break;
    default:
      break;
    }
  }

  return Signature;
}

static std::string GetEnclosingDeclContextSignature(const Decl *D) {
  if (!D)
    return "";

  if (const auto *ND = dyn_cast<NamedDecl>(D)) {
    std::string DeclName;

    switch (ND->getKind()) {
    case Decl::Namespace:
    case Decl::Record:
    case Decl::CXXRecord:
    case Decl::Enum:
      DeclName = ND->getQualifiedNameAsString();
      break;
    case Decl::CXXConstructor:
    case Decl::CXXDestructor:
    case Decl::CXXConversion:
    case Decl::CXXMethod:
    case Decl::Function:
      DeclName = GetSignature(dyn_cast_or_null<FunctionDecl>(ND));
      break;
    case Decl::ObjCMethod:
      // ObjC Methods can not be overloaded, qualified name uniquely identifies
      // the method.
      DeclName = ND->getQualifiedNameAsString();
      break;
    default:
      break;
    }

    return DeclName;
  }

  return "";
}

static StringRef GetNthLineOfFile(llvm::MemoryBuffer *Buffer, int Line) {
  if (!Buffer)
    return "";

  llvm::line_iterator LI(*Buffer, false);
  for (; !LI.is_at_eof() && LI.line_number() != Line; ++LI)
    ;

  return *LI;
}

static std::string NormalizeLine(const SourceManager &SM, FullSourceLoc &L,
                                 const LangOptions &LangOpts) {
  static StringRef Whitespaces = " \t\n";

  StringRef Str = GetNthLineOfFile(SM.getBuffer(L.getFileID(), L),
                                   L.getExpansionLineNumber());
  StringRef::size_type col = Str.find_first_not_of(Whitespaces);
  if (col == StringRef::npos)
    col = 1; // The line only contains whitespace.
  else
    col++;
  SourceLocation StartOfLine =
      SM.translateLineCol(SM.getFileID(L), L.getExpansionLineNumber(), col);
  llvm::MemoryBuffer *Buffer =
      SM.getBuffer(SM.getFileID(StartOfLine), StartOfLine);
  if (!Buffer)
    return {};

  const char *BufferPos = SM.getCharacterData(StartOfLine);

  Token Token;
  Lexer Lexer(SM.getLocForStartOfFile(SM.getFileID(StartOfLine)), LangOpts,
              Buffer->getBufferStart(), BufferPos, Buffer->getBufferEnd());

  size_t NextStart = 0;
  std::ostringstream LineBuff;
  while (!Lexer.LexFromRawLexer(Token) && NextStart < 2) {
    if (Token.isAtStartOfLine() && NextStart++ > 0)
      continue;
    LineBuff << std::string(SM.getCharacterData(Token.getLocation()),
                            Token.getLength());
  }

  return LineBuff.str();
}

static llvm::SmallString<32> GetHashOfContent(StringRef Content) {
  llvm::MD5 Hash;
  llvm::MD5::MD5Result MD5Res;
  SmallString<32> Res;

  Hash.update(Content);
  Hash.final(MD5Res);
  llvm::MD5::stringifyResult(MD5Res, Res);

  return Res;
}

std::string clang::GetIssueString(const SourceManager &SM,
                                  FullSourceLoc &IssueLoc,
                                  StringRef CheckerName, StringRef BugType,
                                  const Decl *D,
                                  const LangOptions &LangOpts) {
  static StringRef Delimiter = "$";

  return (llvm::Twine(CheckerName) + Delimiter +
          GetEnclosingDeclContextSignature(D) + Delimiter +
          Twine(IssueLoc.getExpansionColumnNumber()) + Delimiter +
          NormalizeLine(SM, IssueLoc, LangOpts) + Delimiter + BugType)
      .str();
}

SmallString<32> clang::GetIssueHash(const SourceManager &SM,
                                    FullSourceLoc &IssueLoc,
                                    StringRef CheckerName, StringRef BugType,
                                    const Decl *D,
                                    const LangOptions &LangOpts) {

  return GetHashOfContent(
      GetIssueString(SM, IssueLoc, CheckerName, BugType, D, LangOpts));
}
<|endoftext|>


<commit_before>//===---------- IssueHash.cpp - Generate identification hashes --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"

#include <functional>
#include <sstream>
#include <string>

using namespace clang;

// Get a string representation of the parts of the signature that can be
// overloaded on.
static std::string GetSignature(const FunctionDecl *Target) {
  if (!Target)
    return "";
  std::string Signature;

  if (!isa<CXXConstructorDecl>(Target) && !isa<CXXDestructorDecl>(Target) &&
      !isa<CXXConversionDecl>(Target))
    Signature.append(Target->getReturnType().getAsString()).append(" ");
  Signature.append(Target->getQualifiedNameAsString()).append("(");

  for (int i = 0, paramsCount = Target->getNumParams(); i < paramsCount; ++i) {
    if (i)
      Signature.append(", ");
    Signature.append(Target->getParamDecl(i)->getType().getAsString());
  }

  if (Target->isVariadic())
    Signature.append(", ...");
  Signature.append(")");

  const auto *TargetT =
      llvm::dyn_cast_or_null<FunctionType>(Target->getType().getTypePtr());

  if (!TargetT || !isa<CXXMethodDecl>(Target))
    return Signature;

  if (TargetT->isConst())
    Signature.append(" const");
  if (TargetT->isVolatile())
    Signature.append(" volatile");
  if (TargetT->isRestrict())
    Signature.append(" restrict");

  if (const auto *TargetPT =
          dyn_cast_or_null<FunctionProtoType>(Target->getType().getTypePtr())) {
    switch (TargetPT->getRefQualifier()) {
    case RQ_LValue:
      Signature.append(" &");
      break;
    case RQ_RValue:
      Signature.append(" &&");
      break;
    default:
      break;
    }
  }

  return Signature;
}

static std::string GetEnclosingDeclContextSignature(const Decl *D) {
  if (!D)
    return "";

  if (const auto *ND = dyn_cast<NamedDecl>(D)) {
    std::string DeclName;

    switch (ND->getKind()) {
    case Decl::Namespace:
    case Decl::Record:
    case Decl::CXXRecord:
    case Decl::Enum:
      DeclName = ND->getQualifiedNameAsString();
      break;
    case Decl::CXXConstructor:
    case Decl::CXXDestructor:
    case Decl::CXXConversion:
    case Decl::CXXMethod:
    case Decl::Function:
      DeclName = GetSignature(dyn_cast_or_null<FunctionDecl>(ND));
      break;
    case Decl::ObjCMethod:
      // ObjC Methods can not be overloaded, qualified name uniquely identifies
      // the method.
      DeclName = ND->getQualifiedNameAsString();
      break;
    default:
      break;
    }

    return DeclName;
  }

  return "";
}

static StringRef GetNthLineOfFile(llvm::MemoryBuffer *Buffer, int Line) {
  if (!Buffer)
    return "";

  llvm::line_iterator LI(*Buffer, false);
  for (; !LI.is_at_eof() && LI.line_number() != Line; ++LI)
    ;

  return *LI;
}

static std::string NormalizeLine(const SourceManager &SM, FullSourceLoc &L,
                                 const LangOptions &LangOpts) {
  static StringRef Whitespaces = " \t\n";

  StringRef Str = GetNthLineOfFile(SM.getBuffer(L.getFileID(), L),
                                   L.getExpansionLineNumber());
  unsigned col = Str.find_first_not_of(Whitespaces);
  col++;
  SourceLocation StartOfLine =
      SM.translateLineCol(SM.getFileID(L), L.getExpansionLineNumber(), col);
  llvm::MemoryBuffer *Buffer =
      SM.getBuffer(SM.getFileID(StartOfLine), StartOfLine);
  if (!Buffer)
    return {};

  const char *BufferPos = SM.getCharacterData(StartOfLine);

  Token Token;
  Lexer Lexer(SM.getLocForStartOfFile(SM.getFileID(StartOfLine)), LangOpts,
              Buffer->getBufferStart(), BufferPos, Buffer->getBufferEnd());

  size_t NextStart = 0;
  std::ostringstream LineBuff;
  while (!Lexer.LexFromRawLexer(Token) && NextStart < 2) {
    if (Token.isAtStartOfLine() && NextStart++ > 0)
      continue;
    LineBuff << std::string(SM.getCharacterData(Token.getLocation()),
                            Token.getLength());
  }

  return LineBuff.str();
}

static llvm::SmallString<32> GetHashOfContent(StringRef Content) {
  llvm::MD5 Hash;
  llvm::MD5::MD5Result MD5Res;
  SmallString<32> Res;

  Hash.update(Content);
  Hash.final(MD5Res);
  llvm::MD5::stringifyResult(MD5Res, Res);

  return Res;
}

std::string clang::GetIssueString(const SourceManager &SM,
                                  FullSourceLoc &IssueLoc,
                                  StringRef CheckerName, StringRef BugType,
                                  const Decl *D,
                                  const LangOptions &LangOpts) {
  static StringRef Delimiter = "$";

  return (llvm::Twine(CheckerName) + Delimiter +
          GetEnclosingDeclContextSignature(D) + Delimiter +
          llvm::utostr(IssueLoc.getExpansionColumnNumber()) + Delimiter +
          NormalizeLine(SM, IssueLoc, LangOpts) + Delimiter + BugType)
      .str();
}

SmallString<32> clang::GetIssueHash(const SourceManager &SM,
                                    FullSourceLoc &IssueLoc,
                                    StringRef CheckerName, StringRef BugType,
                                    const Decl *D,
                                    const LangOptions &LangOpts) {

  return GetHashOfContent(
      GetIssueString(SM, IssueLoc, CheckerName, BugType, D, LangOpts));
}
<commit_msg>Convert an unsigned to Twine instead of using utostr since we're already building a Twine. NFC<commit_after>//===---------- IssueHash.cpp - Generate identification hashes --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"

#include <functional>
#include <sstream>
#include <string>

using namespace clang;

// Get a string representation of the parts of the signature that can be
// overloaded on.
static std::string GetSignature(const FunctionDecl *Target) {
  if (!Target)
    return "";
  std::string Signature;

  if (!isa<CXXConstructorDecl>(Target) && !isa<CXXDestructorDecl>(Target) &&
      !isa<CXXConversionDecl>(Target))
    Signature.append(Target->getReturnType().getAsString()).append(" ");
  Signature.append(Target->getQualifiedNameAsString()).append("(");

  for (int i = 0, paramsCount = Target->getNumParams(); i < paramsCount; ++i) {
    if (i)
      Signature.append(", ");
    Signature.append(Target->getParamDecl(i)->getType().getAsString());
  }

  if (Target->isVariadic())
    Signature.append(", ...");
  Signature.append(")");

  const auto *TargetT =
      llvm::dyn_cast_or_null<FunctionType>(Target->getType().getTypePtr());

  if (!TargetT || !isa<CXXMethodDecl>(Target))
    return Signature;

  if (TargetT->isConst())
    Signature.append(" const");
  if (TargetT->isVolatile())
    Signature.append(" volatile");
  if (TargetT->isRestrict())
    Signature.append(" restrict");

  if (const auto *TargetPT =
          dyn_cast_or_null<FunctionProtoType>(Target->getType().getTypePtr())) {
    switch (TargetPT->getRefQualifier()) {
    case RQ_LValue:
      Signature.append(" &");
      break;
    case RQ_RValue:
      Signature.append(" &&");
      break;
    default:
      break;
    }
  }

  return Signature;
}

static std::string GetEnclosingDeclContextSignature(const Decl *D) {
  if (!D)
    return "";

  if (const auto *ND = dyn_cast<NamedDecl>(D)) {
    std::string DeclName;

    switch (ND->getKind()) {
    case Decl::Namespace:
    case Decl::Record:
    case Decl::CXXRecord:
    case Decl::Enum:
      DeclName = ND->getQualifiedNameAsString();
      break;
    case Decl::CXXConstructor:
    case Decl::CXXDestructor:
    case Decl::CXXConversion:
    case Decl::CXXMethod:
    case Decl::Function:
      DeclName = GetSignature(dyn_cast_or_null<FunctionDecl>(ND));
      break;
    case Decl::ObjCMethod:
      // ObjC Methods can not be overloaded, qualified name uniquely identifies
      // the method.
      DeclName = ND->getQualifiedNameAsString();
      break;
    default:
      break;
    }

    return DeclName;
  }

  return "";
}

static StringRef GetNthLineOfFile(llvm::MemoryBuffer *Buffer, int Line) {
  if (!Buffer)
    return "";

  llvm::line_iterator LI(*Buffer, false);
  for (; !LI.is_at_eof() && LI.line_number() != Line; ++LI)
    ;

  return *LI;
}

static std::string NormalizeLine(const SourceManager &SM, FullSourceLoc &L,
                                 const LangOptions &LangOpts) {
  static StringRef Whitespaces = " \t\n";

  StringRef Str = GetNthLineOfFile(SM.getBuffer(L.getFileID(), L),
                                   L.getExpansionLineNumber());
  unsigned col = Str.find_first_not_of(Whitespaces);
  col++;
  SourceLocation StartOfLine =
      SM.translateLineCol(SM.getFileID(L), L.getExpansionLineNumber(), col);
  llvm::MemoryBuffer *Buffer =
      SM.getBuffer(SM.getFileID(StartOfLine), StartOfLine);
  if (!Buffer)
    return {};

  const char *BufferPos = SM.getCharacterData(StartOfLine);

  Token Token;
  Lexer Lexer(SM.getLocForStartOfFile(SM.getFileID(StartOfLine)), LangOpts,
              Buffer->getBufferStart(), BufferPos, Buffer->getBufferEnd());

  size_t NextStart = 0;
  std::ostringstream LineBuff;
  while (!Lexer.LexFromRawLexer(Token) && NextStart < 2) {
    if (Token.isAtStartOfLine() && NextStart++ > 0)
      continue;
    LineBuff << std::string(SM.getCharacterData(Token.getLocation()),
                            Token.getLength());
  }

  return LineBuff.str();
}

static llvm::SmallString<32> GetHashOfContent(StringRef Content) {
  llvm::MD5 Hash;
  llvm::MD5::MD5Result MD5Res;
  SmallString<32> Res;

  Hash.update(Content);
  Hash.final(MD5Res);
  llvm::MD5::stringifyResult(MD5Res, Res);

  return Res;
}

std::string clang::GetIssueString(const SourceManager &SM,
                                  FullSourceLoc &IssueLoc,
                                  StringRef CheckerName, StringRef BugType,
                                  const Decl *D,
                                  const LangOptions &LangOpts) {
  static StringRef Delimiter = "$";

  return (llvm::Twine(CheckerName) + Delimiter +
          GetEnclosingDeclContextSignature(D) + Delimiter +
          Twine(IssueLoc.getExpansionColumnNumber()) + Delimiter +
          NormalizeLine(SM, IssueLoc, LangOpts) + Delimiter + BugType)
      .str();
}

SmallString<32> clang::GetIssueHash(const SourceManager &SM,
                                    FullSourceLoc &IssueLoc,
                                    StringRef CheckerName, StringRef BugType,
                                    const Decl *D,
                                    const LangOptions &LangOpts) {

  return GetHashOfContent(
      GetIssueString(SM, IssueLoc, CheckerName, BugType, D, LangOpts));
}
<|endoftext|>