<commit_before>// Copyright (c) 2014-2022 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_DEMANGLE_HPP
#define TAO_PEGTL_DEMANGLE_HPP

#include <ciso646>
#include <string_view>

#include "config.hpp"

// ensure a consistent interface
namespace TAO_PEGTL_NAMESPACE
{
#if !defined( __clang__ ) && defined( __GNUC__ ) && ( __GNUC__ == 7 )

   template< typename T >
   [[nodiscard]] std::string_view demangle() noexcept;

#else

   template< typename T >
   [[nodiscard]] constexpr std::string_view demangle() noexcept;

#endif

}  // namespace TAO_PEGTL_NAMESPACE

#if defined( __clang__ )

#if defined( _LIBCPP_VERSION )

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   constexpr std::string_view sv = __PRETTY_FUNCTION__;
   constexpr auto begin = sv.find( '=' );
   static_assert( begin != std::string_view::npos );
   return sv.substr( begin + 2, sv.size() - begin - 3 );
}

#else

namespace TAO_PEGTL_NAMESPACE::internal
{
   // When using libstdc++ with clang, std::string_view::find is not constexpr :(
   template< char C >
   constexpr const char* string_view_find( const char* p, std::size_t n ) noexcept
   {
      while( n ) {
         if( *p == C ) {
            return p;
         }
         ++p;
         --n;
      }
      return nullptr;
   }

}  // namespace TAO_PEGTL_NAMESPACE::internal

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   constexpr std::string_view sv = __PRETTY_FUNCTION__;
   constexpr auto begin = internal::string_view_find< '=' >( sv.data(), sv.size() );
   static_assert( begin != nullptr );
   return { begin + 2, sv.data() + sv.size() - begin - 3 };
}

#endif

#elif defined( __GNUC__ )

#if( __GNUC__ == 7 )

// GCC 7 wrongly sometimes disallows __PRETTY_FUNCTION__ in constexpr functions,
// therefore we drop the 'constexpr' and hope for the best.
template< typename T >
[[nodiscard]] std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   const std::string_view sv = __PRETTY_FUNCTION__;
   const auto begin = sv.find( '=' );
   const auto tmp = sv.substr( begin + 2 );
   const auto end = tmp.rfind( ';' );
   return tmp.substr( 0, end );
}

#elif( __GNUC__ == 9 ) && ( __GNUC_MINOR__ < 3 )

#if !defined( __cpp_rtti )
#error "RTTI support required for GCC 9.1/9.2"
#else

#include <typeinfo>

// GCC 9.1 and 9.2 have a bug that leads to truncated __PRETTY_FUNCTION__ names,
// see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91155
template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   // fallback: requires RTTI, no demangling
   return typeid( T ).name();
}

#endif

#else

namespace TAO_PEGTL_NAMESPACE::special
{
   template< typename T >
   [[nodiscard]] constexpr std::string_view demangle() noexcept
   {
      constexpr std::string_view sv = __PRETTY_FUNCTION__;
      constexpr auto begin = sv.find( '=' );
      static_assert( begin != std::string_view::npos );
      constexpr auto tmp = sv.substr( begin + 2 );
      constexpr auto end = tmp.rfind( ';' );
      static_assert( end != std::string_view::npos );
      return tmp.substr( 0, end );
   }

}  // namespace TAO_PEGTL_NAMESPACE::special

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   return TAO_PEGTL_NAMESPACE::special::demangle< T >();
}

#endif

#elif defined( _MSC_VER )

#if( _MSC_VER < 1920 )

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   const std::string_view sv = __FUNCSIG__;
   const auto begin = sv.find( "demangle<" );
   const auto tmp = sv.substr( begin + 9 );
   const auto end = tmp.rfind( '>' );
   return tmp.substr( 0, end );
}

#else

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   // we can not add static_assert for additional safety,
   // see issues #296, #301 and #308
   constexpr std::string_view sv = __FUNCSIG__;
   constexpr auto begin = sv.find( "demangle<" );
   constexpr auto tmp = sv.substr( begin + 9 );
   constexpr auto end = tmp.rfind( '>' );
   return tmp.substr( 0, end );
}

#endif

#else

#if !defined( __cpp_rtti )
#error "RTTI support required for unknown compilers"
#else

#include <typeinfo>

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   // fallback: requires RTTI, no demangling
   return typeid( T ).name();
}

#endif

#endif

#endif
<commit_msg>Simplify<commit_after>// Copyright (c) 2014-2022 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_DEMANGLE_HPP
#define TAO_PEGTL_DEMANGLE_HPP

#include <ciso646>
#include <string_view>

#include "config.hpp"

// ensure a consistent interface
namespace TAO_PEGTL_NAMESPACE
{
#if !defined( __clang__ ) && defined( __GNUC__ ) && ( __GNUC__ == 7 )

   template< typename T >
   [[nodiscard]] std::string_view demangle() noexcept;

#else

   template< typename T >
   [[nodiscard]] constexpr std::string_view demangle() noexcept;

#endif

}  // namespace TAO_PEGTL_NAMESPACE

#if defined( __clang__ )

#if defined( _LIBCPP_VERSION )

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   constexpr std::string_view sv = __PRETTY_FUNCTION__;
   constexpr auto begin = sv.find( '=' );
   static_assert( begin != std::string_view::npos );
   return sv.substr( begin + 2, sv.size() - begin - 3 );
}

#else

namespace TAO_PEGTL_NAMESPACE::internal
{
   // When using libstdc++ with clang, std::string_view::find is not constexpr :(
   template< char C >
   constexpr const char* string_view_find( const char* p, std::size_t n ) noexcept
   {
      while( n ) {
         if( *p == C ) {
            return p;
         }
         ++p;
         --n;
      }
      return nullptr;
   }

}  // namespace TAO_PEGTL_NAMESPACE::internal

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   constexpr std::string_view sv = __PRETTY_FUNCTION__;
   constexpr auto begin = internal::string_view_find< '=' >( sv.data(), sv.size() );
   static_assert( begin != nullptr );
   return { begin + 2, sv.data() + sv.size() - begin - 3 };
}

#endif

#elif defined( __GNUC__ )

#if( __GNUC__ == 7 )

// GCC 7 wrongly sometimes disallows __PRETTY_FUNCTION__ in constexpr functions,
// therefore we drop the 'constexpr' and hope for the best.
template< typename T >
[[nodiscard]] std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   const std::string_view sv = __PRETTY_FUNCTION__;
   const auto begin = sv.find( '=' );
   const auto tmp = sv.substr( begin + 2 );
   const auto end = tmp.rfind( ';' );
   return tmp.substr( 0, end );
}

#elif( __GNUC__ == 9 ) && ( __GNUC_MINOR__ < 3 )

#if !defined( __cpp_rtti )
#error "RTTI support required for GCC 9.1/9.2"
#else

#include <typeinfo>

// GCC 9.1 and 9.2 have a bug that leads to truncated __PRETTY_FUNCTION__ names,
// see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91155
template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   // fallback: requires RTTI, no demangling
   return typeid( T ).name();
}

#endif

#else

namespace TAO_PEGTL_NAMESPACE::special
{
   template< typename T >
   [[nodiscard]] constexpr std::string_view demangle() noexcept
   {
      constexpr std::string_view sv = __PRETTY_FUNCTION__;
      constexpr auto begin = sv.find( '=' );
      static_assert( begin != std::string_view::npos );
      constexpr auto tmp = sv.substr( begin + 2 );
      constexpr auto end = tmp.rfind( ';' );
      static_assert( end != std::string_view::npos );
      return tmp.substr( 0, end );
   }

}  // namespace TAO_PEGTL_NAMESPACE::special

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   return special::demangle< T >();
}

#endif

#elif defined( _MSC_VER )

#if( _MSC_VER < 1920 )

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   const std::string_view sv = __FUNCSIG__;
   const auto begin = sv.find( "demangle<" );
   const auto tmp = sv.substr( begin + 9 );
   const auto end = tmp.rfind( '>' );
   return tmp.substr( 0, end );
}

#else

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   // we can not add static_assert for additional safety,
   // see issues #296, #301 and #308
   constexpr std::string_view sv = __FUNCSIG__;
   constexpr auto begin = sv.find( "demangle<" );
   constexpr auto tmp = sv.substr( begin + 9 );
   constexpr auto end = tmp.rfind( '>' );
   return tmp.substr( 0, end );
}

#endif

#else

#if !defined( __cpp_rtti )
#error "RTTI support required for unknown compilers"
#else

#include <typeinfo>

template< typename T >
[[nodiscard]] constexpr std::string_view TAO_PEGTL_NAMESPACE::demangle() noexcept
{
   // fallback: requires RTTI, no demangling
   return typeid( T ).name();
}

#endif

#endif

#endif
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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 <os>
#include <net/inet4>
#include <net/dhcp/dh4client.hpp>
#include <math.h> // rand()
#include <sstream>

// An IP-stack object
std::unique_ptr<net::Inet4<VirtioNet> > inet;

using namespace std::chrono;

std::string HTML_RESPONSE() {
  int color = rand();
  std::stringstream stream;

  /* HTML Fonts */
  std::string ubuntu_medium  = "font-family: \'Ubuntu\', sans-serif; font-weight: 500; ";
  std::string ubuntu_normal  = "font-family: \'Ubuntu\', sans-serif; font-weight: 400; ";
  std::string ubuntu_light  = "font-family: \'Ubuntu\', sans-serif; font-weight: 300; ";

  /* HTML */
  stream << ""
         << "<link href='https://fonts.googleapis.com/css?family=Ubuntu:500,300' rel='stylesheet' type='text/css'>"
         << ""
         << "<h1 style= \"color: " << "#" << std::hex << (color >> 8) << "\">"
         <<  "IncludeOS
"
         <<  "
Now speaks TCP!
"
    // .... generate more dynamic content
         << "
  ...and can improvise http. With limitations of course, but it's been easier than expected so far
"
         << "
 © 2015, Oslo and Akershus University College of Applied Sciences "
         << "\n";

  std::string html = stream.str();

  std::string header="HTTP/1.1 200 OK \n "        \
    "Date: Mon, 01 Jan 1970 00:00:01 GMT \n"      \
    "Server: IncludeOS prototype 4.0 \n"        \
    "Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT \n"   \
    "Content-Type: text/html; charset=UTF-8 \n"     \
    "Content-Length: "+std::to_string(html.size())+"\n"   \
    "Accept-Ranges: bytes\n"          \
    "Connection: close\n\n";
  return header + html;
}

void Service::start() {
  // Assign a driver (VirtioNet) to a network interface (eth0)
  // @note: We could determine the appropirate driver dynamically, but then we'd
  // have to include all the drivers into the image, which  we want to avoid.
  hw::Nic<VirtioNet>& eth0 = hw::Dev::eth<0,VirtioNet>();

  // Bring up a network stack, attached to the nic
  // @note : No parameters after 'nic' means we'll use DHCP for IP config.
  inet = std::make_unique<net::Inet4<VirtioNet> >(eth0);

  // Static IP configuration, until we (possibly) get DHCP
  // @note : Mostly to get a robust demo service that it works with and without DHCP
  inet->network_config( { 10,0,0,42 },      // IP
                        { 255,255,255,0 },  // Netmask
                        { 10,0,0,1 },       // Gateway
                        { 8,8,8,8 } );      // DNS

  srand(OS::cycles_since_boot());

  // Set up a TCP server on port 80
  auto& server = inet->tcp().bind(80);

  hw::PIT::instance().onRepeatedTimeout(30s, []{
      printf("<Service> TCP STATUS:\n%s \n", inet->tcp().status().c_str());
    });

  // Add a TCP connection handler - here a hardcoded HTTP-service
  server.onAccept([](auto conn) -> bool {
      printf("<Service> @onAccept - Connection attempt from: %s \n",
             conn->to_string().c_str());
      return true; // allow all connections

    }).onConnect([](auto conn) {
        printf("<Service> @onConnect - Connection successfully established.\n");
        // read async with a buffer size of 1024 bytes
        // define what to do when data is read
        conn->read(1024, [conn](net::TCP::buffer_t buf, size_t n) {
            // create string from buffer
            std::string data { (char*)buf.get(), n };
            printf("<Service> @read:\n%s\n", data.c_str());

            // create response
            std::string response = HTML_RESPONSE();
            // write the data from the string with the strings size
            conn->write(response.data(), response.size(), [](size_t n) {
                printf("<Service> @write: %u bytes written\n", n);
              });
          });

      }).onDisconnect([](auto, auto reason) {
          printf("<Service> @onDisconnect - Reason: %s \n", reason.to_string().c_str());
        });

  printf("*** TEST SERVICE STARTED *** \n");
}
<commit_msg>example: made the demo a tiny bit smarter<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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 <os>
#include <net/inet4>
#include <net/dhcp/dh4client.hpp>
#include <math.h> // rand()
#include <sstream>

// An IP-stack object
std::unique_ptr<net::Inet4<VirtioNet> > inet;

using namespace std::chrono;

std::string HTML_RESPONSE() {
  int color = rand();
  std::stringstream stream;

  /* HTML Fonts */
  std::string ubuntu_medium  = "font-family: \'Ubuntu\', sans-serif; font-weight: 500; ";
  std::string ubuntu_normal  = "font-family: \'Ubuntu\', sans-serif; font-weight: 400; ";
  std::string ubuntu_light  = "font-family: \'Ubuntu\', sans-serif; font-weight: 300; ";

  /* HTML */
  stream << ""
         << "<link href='https://fonts.googleapis.com/css?family=Ubuntu:500,300' rel='stylesheet' type='text/css'>"
         << ""
         << "<h1 style= \"color: " << "#" << std::hex << (color >> 8) << "\">"
         <<  "IncludeOS
"
         <<  "
Now speaks TCP!
"
    // .... generate more dynamic content
         << "
  ...and can improvise http. With limitations of course, but it's been easier than expected so far
"
         << "
 © 2015, Oslo and Akershus University College of Applied Sciences "
         << "\n";

  std::string html = stream.str();

  std::string header="HTTP/1.1 200 OK \n "        \
    "Date: Mon, 01 Jan 1970 00:00:01 GMT \n"      \
    "Server: IncludeOS prototype 4.0 \n"        \
    "Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT \n"   \
    "Content-Type: text/html; charset=UTF-8 \n"     \
    "Content-Length: "+std::to_string(html.size())+"\n"   \
    "Accept-Ranges: bytes\n"          \
    "Connection: close\n\n";
  return header + html;
}

const std::string NOT_FOUND = "HTTP/1.1 404 Not Found \n Connection: close\n\n";

void Service::start() {
  // Assign a driver (VirtioNet) to a network interface (eth0)
  // @note: We could determine the appropirate driver dynamically, but then we'd
  // have to include all the drivers into the image, which  we want to avoid.
  hw::Nic<VirtioNet>& eth0 = hw::Dev::eth<0,VirtioNet>();

  // Bring up a network stack, attached to the nic
  // @note : No parameters after 'nic' means we'll use DHCP for IP config.
  inet = std::make_unique<net::Inet4<VirtioNet> >(eth0);

  // Static IP configuration, until we (possibly) get DHCP
  // @note : Mostly to get a robust demo service that it works with and without DHCP
  inet->network_config( { 10,0,0,42 },      // IP
                        { 255,255,255,0 },  // Netmask
                        { 10,0,0,1 },       // Gateway
                        { 8,8,8,8 } );      // DNS

  srand(OS::cycles_since_boot());

  // Set up a TCP server on port 80
  auto& server = inet->tcp().bind(80);

  hw::PIT::instance().onRepeatedTimeout(30s, []{
      printf("<Service> TCP STATUS:\n%s \n", inet->tcp().status().c_str());
    });

  // Add a TCP connection handler - here a hardcoded HTTP-service
  server.onAccept([](auto conn) -> bool {
    printf("<Service> @onAccept - Connection attempt from: %s \n",
           conn->to_string().c_str());
    return true; // allow all connections

  }).onConnect([](auto conn) {
    printf("<Service> @onConnect - Connection successfully established.\n");
    // read async with a buffer size of 1024 bytes
    // define what to do when data is read
    conn->read(1024, [conn](net::TCP::buffer_t buf, size_t n) {
      // create string from buffer
      std::string data { (char*)buf.get(), n };
      printf("<Service> @read:\n%s\n", data.c_str());
      if(data.find("GET / ") != std::string::npos) {
        // create response
        std::string response = HTML_RESPONSE();
        // write the data from the string with the strings size
        conn->write(response.data(), response.size(), [](size_t n) {
          printf("<Service> @write: %u bytes written\n", n);
        });
      }
      else {
        conn->write(NOT_FOUND.data(), NOT_FOUND.size());
      }

    });

  }).onDisconnect([](auto conn, auto reason) {
    printf("<Service> @onDisconnect - Reason: %s \n", reason.to_string().c_str());
    conn->close();
  }).onPacketReceived([](auto, auto packet) {
    printf("@Packet: %s\n", packet->to_string().c_str());
  });

  printf("*** TEST SERVICE STARTED *** \n");
}
<|endoftext|>


<commit_before>#ifndef ORIGEN_HPP_INCLUDED
#define ORIGEN_HPP_INCLUDED

#define ORIGEN_VERSION "0.11.0"

#ifndef debugger
#define debugger __asm__("int $3");
#endif

#include "origen/helpers.hpp"
#include "origen/site.hpp"
#include "origen/utils.hpp"

namespace Origen {

extern vector<Site> Sites;
Utils::Version version();
Site& site();
Site& site(int site);
extern bool invertFunctionalResults;
}
#endif
<commit_msg>Wrote new version in C++ code<commit_after>#ifndef ORIGEN_HPP_INCLUDED
#define ORIGEN_HPP_INCLUDED

#define ORIGEN_VERSION "0.12.0"

#ifndef debugger
#define debugger __asm__("int $3");
#endif

#include "origen/helpers.hpp"
#include "origen/site.hpp"
#include "origen/utils.hpp"

namespace Origen {

extern vector<Site> Sites;
Utils::Version version();
Site& site();
Site& site(int site);
extern bool invertFunctionalResults;
}
#endif
<|endoftext|>


<commit_before>// Copyright 2011 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 "lexer.h"

#include "eval_env.h"

bool Lexer::Error(const string& message, string* err) {
  // Compute line/column.
  int line = 1;
  const char* context = input_.str_;
  for (const char* p = input_.str_; p < last_token_; ++p) {
    if (*p == '\n') {
      ++line;
      context = p + 1;
    }
  }
  int col = last_token_ ? last_token_ - context : 0;

  char buf[1024];
  snprintf(buf, sizeof(buf), "%s:%d: ", filename_.AsString().c_str(), line);
  *err = buf;
  *err += message + "\n";

  // Add some context to the message.
  const int kTruncateColumn = 72;
  if (col > 0 && col < kTruncateColumn) {
    int len;
    bool truncated = true;
    for (len = 0; len < kTruncateColumn; ++len) {
      if (context[len] == 0 || context[len] == '\n') {
        truncated = false;
        break;
      }
    }
    *err += string(context, len);
    if (truncated)
      *err += "...";
    *err += "\n";
    *err += string(col, ' ');
    *err += "^ near here\n";
  }

  return false;
}

Lexer::Lexer(const char* input) {
  Start("input", input);
}

void Lexer::Start(StringPiece filename, StringPiece input) {
  filename_ = filename;
  input_ = input;
  ofs_ = input_.str_;
  last_token_ = NULL;
}

const char* Lexer::TokenName(Token t) {
  switch (t) {
  case ERROR:    return "lexing error";
  case BUILD:    return "'build'";
  case COLON:    return "':'";
  case DEFAULT:  return "'default'";
  case EQUALS:   return "'='";
  case IDENT:    return "identifier";
  case INCLUDE:  return "'include'";
  case INDENT:   return "indent";
  case NEWLINE:  return "newline";
  case PIPE2:    return "'||'";
  case PIPE:     return "'|'";
  case RULE:     return "'rule'";
  case SUBNINJA: return "'subninja'";
  case TEOF:     return "eof";
  }
  return NULL;  // not reached
}

void Lexer::UnreadToken() {
  ofs_ = last_token_;
}

Lexer::Token Lexer::ReadToken() {
  const char* p = ofs_;
  const char* q;
  const char* start;
  Lexer::Token token;
  for (;;) {
    start = p;
    /*!re2c
    re2c:define:YYCTYPE = "char";
    re2c:define:YYCURSOR = p;
    re2c:define:YYMARKER = q;
    re2c:yyfill:enable = 0;

    nul = "\000";
    simple_varname = [a-zA-Z0-9_]+;
    varname = [a-zA-Z0-9_.]+;

    "#"[^\000\n]*"\n" { continue; }
    [\n]       { token = NEWLINE;  break; }
    [ ]+       { token = INDENT;   break; }
    "build"    { token = BUILD;    break; }
    "rule"     { token = RULE;     break; }
    "default"  { token = DEFAULT;  break; }
    "="        { token = EQUALS;   break; }
    ":"        { token = COLON;    break; }
    "||"       { token = PIPE2;    break; }
    "|"        { token = PIPE;     break; }
    "include"  { token = INCLUDE;  break; }
    "subninja" { token = SUBNINJA; break; }
    varname    { token = IDENT;    break; }
    nul        { token = TEOF;     break; }
    [^]        { token = ERROR;    break; }
    */
  }

  last_token_ = start;
  ofs_ = p;
  if (token != NEWLINE && token != TEOF)
    EatWhitespace();
  return token;
}

bool Lexer::PeekToken(Token token) {
  Token t = ReadToken();
  if (t == token)
    return true;
  UnreadToken();
  return false;
}

void Lexer::EatWhitespace() {
  const char* p = ofs_;
  for (;;) {
    ofs_ = p;
    /*!re2c
    [ ]+  { continue; }
    "$\n" { continue; }
    nul   { break; }
    [^]   { break; }
    */
  }
}

bool Lexer::ReadIdent(string* out) {
  const char* p = ofs_;
  for (;;) {
    const char* start = p;
    /*!re2c
    varname {
      out->assign(start, p - start);
      break;
    }
    [^] { return false; }
    */
  }
  ofs_ = p;
  EatWhitespace();
  return true;
}

bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) {
  const char* p = ofs_;
  const char* q;
  const char* start;
  for (;;) {
    start = p;
    /*!re2c
    [^$ :\n|\000]+ {
      eval->Add(EvalString::RAW, StringPiece(start, p - start));
      continue;
    }
    [ :|\n] {
      if (path) {
        p = start;
        break;
      } else {
        if (*start == '\n')
          break;
        eval->Add(EvalString::RAW, StringPiece(start, 1));
        continue;
      }
    }
    "$$" {
      eval->Add(EvalString::RAW, StringPiece("$", 1));
      continue;
    }
    "$ " {
      eval->Add(EvalString::RAW, StringPiece(" ", 1));
      continue;
    }
    "$\n"[ ]* {
      continue;
    }
    "${"varname"}" {
      eval->Add(EvalString::SPECIAL, StringPiece(start + 2, p - start - 3));
      continue;
    }
    "$"simple_varname {
      eval->Add(EvalString::SPECIAL, StringPiece(start + 1, p - start - 1));
      continue;
    }
    "$". {
      last_token_ = start;
      return Error("bad $-escape (literal $ must be written as $$)", err);
    }
    nul {
      last_token_ = start;
      return Error("unexpected EOF", err);
    }
    [^] {
      last_token_ = start;
      return Error("lexing error", err);
    }
    */
  }
  last_token_ = start;
  ofs_ = p;
  if (path)
    EatWhitespace();
  // Non-path strings end in newlines, so there's no whitespace to eat.
  return true;
}
<commit_msg>build fix<commit_after>// Copyright 2011 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 "lexer.h"

#include <stdio.h>

#include "eval_env.h"

bool Lexer::Error(const string& message, string* err) {
  // Compute line/column.
  int line = 1;
  const char* context = input_.str_;
  for (const char* p = input_.str_; p < last_token_; ++p) {
    if (*p == '\n') {
      ++line;
      context = p + 1;
    }
  }
  int col = last_token_ ? last_token_ - context : 0;

  char buf[1024];
  snprintf(buf, sizeof(buf), "%s:%d: ", filename_.AsString().c_str(), line);
  *err = buf;
  *err += message + "\n";

  // Add some context to the message.
  const int kTruncateColumn = 72;
  if (col > 0 && col < kTruncateColumn) {
    int len;
    bool truncated = true;
    for (len = 0; len < kTruncateColumn; ++len) {
      if (context[len] == 0 || context[len] == '\n') {
        truncated = false;
        break;
      }
    }
    *err += string(context, len);
    if (truncated)
      *err += "...";
    *err += "\n";
    *err += string(col, ' ');
    *err += "^ near here\n";
  }

  return false;
}

Lexer::Lexer(const char* input) {
  Start("input", input);
}

void Lexer::Start(StringPiece filename, StringPiece input) {
  filename_ = filename;
  input_ = input;
  ofs_ = input_.str_;
  last_token_ = NULL;
}

const char* Lexer::TokenName(Token t) {
  switch (t) {
  case ERROR:    return "lexing error";
  case BUILD:    return "'build'";
  case COLON:    return "':'";
  case DEFAULT:  return "'default'";
  case EQUALS:   return "'='";
  case IDENT:    return "identifier";
  case INCLUDE:  return "'include'";
  case INDENT:   return "indent";
  case NEWLINE:  return "newline";
  case PIPE2:    return "'||'";
  case PIPE:     return "'|'";
  case RULE:     return "'rule'";
  case SUBNINJA: return "'subninja'";
  case TEOF:     return "eof";
  }
  return NULL;  // not reached
}

void Lexer::UnreadToken() {
  ofs_ = last_token_;
}

Lexer::Token Lexer::ReadToken() {
  const char* p = ofs_;
  const char* q;
  const char* start;
  Lexer::Token token;
  for (;;) {
    start = p;
    /*!re2c
    re2c:define:YYCTYPE = "char";
    re2c:define:YYCURSOR = p;
    re2c:define:YYMARKER = q;
    re2c:yyfill:enable = 0;

    nul = "\000";
    simple_varname = [a-zA-Z0-9_]+;
    varname = [a-zA-Z0-9_.]+;

    "#"[^\000\n]*"\n" { continue; }
    [\n]       { token = NEWLINE;  break; }
    [ ]+       { token = INDENT;   break; }
    "build"    { token = BUILD;    break; }
    "rule"     { token = RULE;     break; }
    "default"  { token = DEFAULT;  break; }
    "="        { token = EQUALS;   break; }
    ":"        { token = COLON;    break; }
    "||"       { token = PIPE2;    break; }
    "|"        { token = PIPE;     break; }
    "include"  { token = INCLUDE;  break; }
    "subninja" { token = SUBNINJA; break; }
    varname    { token = IDENT;    break; }
    nul        { token = TEOF;     break; }
    [^]        { token = ERROR;    break; }
    */
  }

  last_token_ = start;
  ofs_ = p;
  if (token != NEWLINE && token != TEOF)
    EatWhitespace();
  return token;
}

bool Lexer::PeekToken(Token token) {
  Token t = ReadToken();
  if (t == token)
    return true;
  UnreadToken();
  return false;
}

void Lexer::EatWhitespace() {
  const char* p = ofs_;
  for (;;) {
    ofs_ = p;
    /*!re2c
    [ ]+  { continue; }
    "$\n" { continue; }
    nul   { break; }
    [^]   { break; }
    */
  }
}

bool Lexer::ReadIdent(string* out) {
  const char* p = ofs_;
  for (;;) {
    const char* start = p;
    /*!re2c
    varname {
      out->assign(start, p - start);
      break;
    }
    [^] { return false; }
    */
  }
  ofs_ = p;
  EatWhitespace();
  return true;
}

bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) {
  const char* p = ofs_;
  const char* q;
  const char* start;
  for (;;) {
    start = p;
    /*!re2c
    [^$ :\n|\000]+ {
      eval->Add(EvalString::RAW, StringPiece(start, p - start));
      continue;
    }
    [ :|\n] {
      if (path) {
        p = start;
        break;
      } else {
        if (*start == '\n')
          break;
        eval->Add(EvalString::RAW, StringPiece(start, 1));
        continue;
      }
    }
    "$$" {
      eval->Add(EvalString::RAW, StringPiece("$", 1));
      continue;
    }
    "$ " {
      eval->Add(EvalString::RAW, StringPiece(" ", 1));
      continue;
    }
    "$\n"[ ]* {
      continue;
    }
    "${"varname"}" {
      eval->Add(EvalString::SPECIAL, StringPiece(start + 2, p - start - 3));
      continue;
    }
    "$"simple_varname {
      eval->Add(EvalString::SPECIAL, StringPiece(start + 1, p - start - 1));
      continue;
    }
    "$". {
      last_token_ = start;
      return Error("bad $-escape (literal $ must be written as $$)", err);
    }
    nul {
      last_token_ = start;
      return Error("unexpected EOF", err);
    }
    [^] {
      last_token_ = start;
      return Error("lexing error", err);
    }
    */
  }
  last_token_ = start;
  ofs_ = p;
  if (path)
    EatWhitespace();
  // Non-path strings end in newlines, so there's no whitespace to eat.
  return true;
}
<|endoftext|>


<commit_before>#ifndef V_SMC_CORE_PARTICLE_HPP
#define V_SMC_CORE_PARTICLE_HPP

#include <vector>
#include <cmath>
#include <cstddef>
#include <boost/function.hpp>
#include <boost/random/binomial_distribution.hpp>
#include <boost/random/uniform_01.hpp>
#include <Eigen/Dense>
#include <vSMC/internal/rng.hpp>
#include <vSMC/internal/version.hpp>

namespace vSMC {

/// Resample scheme
enum ResampleScheme {
    MULTINOMIAL, RESIDUAL, STRATIFIED, SYSTEMATIC, RESIDUAL_STRATIFIED};

/// \brief Particle class
///
/// Particle class store the particle set and arrays of weights and log
/// weights. It provides access to particle values as well as weights. It
/// computes and manages resources for ESS, resampling, etc, tasks unique to
/// each iteration.
template <typename T>
class Particle
{
    public :

    typedef V_SMC_RNG_TYPE rng_type;

    /// \brief Construct a Particle object with given number of particles
    ///
    /// \param N The number of particles
    /// \param seed The seed to the parallel RNG system
    Particle (std::size_t N, rng_type::seed_type seed = V_SMC_RNG_SEED) :
        size_(N), value_(N),
        weight_(N), log_weight_(N), inc_weight_(N), replication_(N),
        ess_(0), resampled_(false), zconst_(0), prng_(N)
    {
        rng_type rng(seed);
        rng.step_size(size_);
        for (std::size_t i = 0; i != size_; ++i) {
            rng.advance_ctr(i);
            prng_[i] = rng;
        }

        weight_.setConstant(1.0 / size_);
        log_weight_.setConstant(0);
    }

    /// \brief Size of the particle set
    ///
    /// \return The number of particles
    std::size_t size () const
    {
        return size_;
    }

    /// \brief Read and write access to particle values
    ///
    /// \return A reference to the particle values, type (T &)
    ///
    /// \note The Particle class guarantee that during the life type of the
    /// object, the reference returned by this member will no be a dangle
    /// handler.
    T &value ()
    {
        return value_;
    }

    /// \brief Read only access to particle values
    ///
    /// \return A const reference to the particle values
    const T &value () const
    {
        return value_;
    }

    /// \brief Read only access to the weights
    ///
    /// \return A const pointer to the weights
    ///
    /// \note The Particle class guarantee that during the life type of the
    /// object, the pointer returned by this always valid and point to the
    /// same address
    const double *weight_ptr () const
    {
        return weight_.data();
    }

    /// \brief Read only access to the log weights
    ///
    /// \return A const pointer to the log weights
    const double *log_weight_ptr () const
    {
        return log_weight_.data();
    }

    const Eigen::VectorXd &weight () const
    {
        return weight_;
    }

    const Eigen::VectorXd &log_weight () const
    {
        return log_weight_;
    }

    /// \brief Set the log weights
    ///
    /// \param new_weight New log weights
    /// \param delta A multiplier appiled to new_weight
    void set_log_weight (const double *new_weight, double delta = 1)
    {
        Eigen::Map<const Eigen::VectorXd> w(new_weight, size_);
        log_weight_ = delta * w;
        set_weight();
    }

    /// \brief Add to the log weights
    ///
    /// \param inc_weight Incremental log weights
    /// \param delta A multiplier applied to inc_weight
    /// \param add_zconst Whether this incremental weights should contribute
    /// the esitmates of normalizing constants
    void add_log_weight (const double *inc_weight, double delta = 1,
            bool add_zconst = true)
    {
        Eigen::Map<const Eigen::VectorXd> w(inc_weight, size_);
        if (add_zconst) {
            inc_weight_ = (delta * w).array().exp();
            zconst_ += std::log(weight_.dot(inc_weight_));
        }
        log_weight_ += delta * w;
        set_weight();
    }

    /// \brief The ESS (Effective Sample Size)
    ///
    /// \return The value of ESS for current particle set
    double ess () const
    {
        return ess_;
    }

    /// \brief Get indicator of resampling
    ///
    /// \return A bool value, \b true if the current iteration was resampled
    bool resampled () const
    {
        return resampled_;
    }

    /// \brief Set indicator of resampling
    ///
    /// \param resampled \b true if the current iteration was resampled
    void resampled (bool resampled)
    {
        resampled_ = resampled;
    }

    /// \brief Get the value of SMC normalizing constant
    ///
    /// \return SMC normalizng constant estimate
    double zconst () const
    {
        return zconst_;
    }

    /// \brief Reset the value of SMC normalizing constant
    void reset_zconst ()
    {
        zconst_ = 0;
    }

    /// \brief Perform resampling
    ///
    /// \param scheme The resampling scheme, see ResamplingScheme
    void resample (ResampleScheme scheme)
    {
        switch (scheme) {
            case MULTINOMIAL :
                resample_multinomial();
                break;
            case RESIDUAL :
                resample_residual();
                break;
            case STRATIFIED :
                resample_stratified();
                break;
            case SYSTEMATIC :
                resample_systematic();
                break;
            case RESIDUAL_STRATIFIED :
                resample_residual_stratified ();
                break;
            default :
                throw std::runtime_error(
                        "ERROR: vSMC::Particle::resample: "
                        "Unknown Resample Scheme");
        }
    }

    rng_type &prng (std::size_t id)
    {
        return prng_[id];
    }

    private :

    std::size_t size_;
    T value_;

    Eigen::VectorXd weight_;
    Eigen::VectorXd log_weight_;
    Eigen::VectorXd inc_weight_;
    Eigen::VectorXi replication_;

    double ess_;
    bool resampled_;
    double zconst_;

    std::vector<rng_type> prng_;
    typedef boost::random::binomial_distribution<> binom_type;
    binom_type binom_;

    void set_weight ()
    {
        double max_weight = log_weight_.maxCoeff();
        log_weight_ = log_weight_.array() - max_weight;
        weight_ = log_weight_.array().exp();
        double sum = weight_.sum();
        weight_ *= 1 / sum;
        ess_ = 1 / weight_.squaredNorm();
    }

    void resample_multinomial ()
    {
        weight2replication(size_);
        resample_do();
    }

    void resample_residual ()
    {
        // Reuse weight and log_weight. weight: act as the fractional part of
        // N * weight. log_weight: act as the integral part of N * weight.
        // They all will be reset to equal weights after resampling.  So it is
        // safe to modify them here.
        for (std::size_t i = 0; i != size_; ++i)
            weight_[i] = std::modf(size_ * weight_[i], log_weight_.data() + i);
        std::size_t size = size_ - log_weight_.sum();
        weight2replication(size);
        for (std::size_t i = 0; i != size_; ++i)
            replication_[i] += log_weight_[i];
        resample_do();
    }

    void resample_stratified ()
    {
        replication_.setConstant(0);
        std::size_t j = 0;
        std::size_t k = 0;
        boost::random::uniform_01<> unif;
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size_) {
            while (j < cw * size_ - u && j != size_) {
                ++replication_[k];
                u = unif(prng_[j++]);
            }
            cw += weight_[++k];
        }
        resample_do();
    }

    void resample_systematic ()
    {
        replication_.setConstant(0);
        std::size_t j = 0;
        std::size_t k = 0;
        boost::random::uniform_01<> unif;
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size_) {
            while (j < cw * size_ - u && j != size_) {
                ++replication_[k];
		++j;
            }
            cw += weight_[++k];
        }
        resample_do();
    }

    void resample_residual_stratified ()
    {
        for (std::size_t i = 0; i != size_; ++i)
            weight_[i] = std::modf(size_ * weight_[i], log_weight_.data() + i);
        resample_stratified();
        for (std::size_t i = 0; i != size_; ++i)
            replication_[i] += log_weight_[i];
        resample_do();
    }

    void weight2replication (std::size_t size)
    {
        double tp = weight_.sum();
        double sum_p = 0;
        std::size_t sum_n = 0;
        replication_.setConstant(0);
        for (std::size_t i = 0; i != size_; ++i) {
            if (sum_n < size && weight_[i] > 0) {
                binom_type::param_type
                    param(size - sum_n, weight_[i] / (tp - sum_p));
                replication_[i] = binom_(prng_[i], param);
            }
            sum_p += weight_[i];
            sum_n += replication_[i];
        }
    }

    void resample_do ()
    {
	// Some times the nuemrical round error can cause the total childs
	// differ from number of particles
	std::size_t sum = replication_.sum();
	if (sum != size_) {
            Eigen::VectorXd::Index id_max;
            replication_.maxCoeff(&id_max);
            replication_[id_max] += size_ - sum;
	}

        std::size_t from = 0;
        std::size_t time = 0;
        for (std::size_t to = 0; to != size_; ++to) {
            if (!replication_[to]) {
                // replication_[to] has zero child, copy from elsewhere
                if (replication_[from] - time <= 1) {
                    // only 1 child left on replication_[from]
                    time = 0;
                    do // move from to some position with at least 2 children
                        ++from;
                    while (replication_[from] < 2);
                }
                value_.copy(from, to);
                ++time;
            }
        }

        ess_ = size_;
        weight_.setConstant(1.0 / size_);
        log_weight_.setConstant(0);
    }
}; // class Particle

} // namespace vSMC

#endif // V_SMC_CORE_PARTICLE_HPP
<commit_msg>implement residual stratified resampling<commit_after>#ifndef V_SMC_CORE_PARTICLE_HPP
#define V_SMC_CORE_PARTICLE_HPP

#include <vector>
#include <cmath>
#include <cstddef>
#include <boost/function.hpp>
#include <boost/random/binomial_distribution.hpp>
#include <boost/random/uniform_01.hpp>
#include <Eigen/Dense>
#include <vSMC/internal/rng.hpp>
#include <vSMC/internal/version.hpp>

namespace vSMC {

/// Resample scheme
enum ResampleScheme {
    MULTINOMIAL, RESIDUAL, STRATIFIED, SYSTEMATIC, RESIDUAL_STRATIFIED};

/// \brief Particle class
///
/// Particle class store the particle set and arrays of weights and log
/// weights. It provides access to particle values as well as weights. It
/// computes and manages resources for ESS, resampling, etc, tasks unique to
/// each iteration.
template <typename T>
class Particle
{
    public :

    typedef V_SMC_RNG_TYPE rng_type;

    /// \brief Construct a Particle object with given number of particles
    ///
    /// \param N The number of particles
    /// \param seed The seed to the parallel RNG system
    Particle (std::size_t N, rng_type::seed_type seed = V_SMC_RNG_SEED) :
        size_(N), value_(N),
        weight_(N), log_weight_(N), inc_weight_(N), replication_(N),
        ess_(0), resampled_(false), zconst_(0), prng_(N)
    {
        rng_type rng(seed);
        rng.step_size(size_);
        for (std::size_t i = 0; i != size_; ++i) {
            rng.advance_ctr(i);
            prng_[i] = rng;
        }

        weight_.setConstant(1.0 / size_);
        log_weight_.setConstant(0);
    }

    /// \brief Size of the particle set
    ///
    /// \return The number of particles
    std::size_t size () const
    {
        return size_;
    }

    /// \brief Read and write access to particle values
    ///
    /// \return A reference to the particle values, type (T &)
    ///
    /// \note The Particle class guarantee that during the life type of the
    /// object, the reference returned by this member will no be a dangle
    /// handler.
    T &value ()
    {
        return value_;
    }

    /// \brief Read only access to particle values
    ///
    /// \return A const reference to the particle values
    const T &value () const
    {
        return value_;
    }

    /// \brief Read only access to the weights
    ///
    /// \return A const pointer to the weights
    ///
    /// \note The Particle class guarantee that during the life type of the
    /// object, the pointer returned by this always valid and point to the
    /// same address
    const double *weight_ptr () const
    {
        return weight_.data();
    }

    /// \brief Read only access to the log weights
    ///
    /// \return A const pointer to the log weights
    const double *log_weight_ptr () const
    {
        return log_weight_.data();
    }

    const Eigen::VectorXd &weight () const
    {
        return weight_;
    }

    const Eigen::VectorXd &log_weight () const
    {
        return log_weight_;
    }

    /// \brief Set the log weights
    ///
    /// \param new_weight New log weights
    /// \param delta A multiplier appiled to new_weight
    void set_log_weight (const double *new_weight, double delta = 1)
    {
        Eigen::Map<const Eigen::VectorXd> w(new_weight, size_);
        log_weight_ = delta * w;
        set_weight();
    }

    /// \brief Add to the log weights
    ///
    /// \param inc_weight Incremental log weights
    /// \param delta A multiplier applied to inc_weight
    /// \param add_zconst Whether this incremental weights should contribute
    /// the esitmates of normalizing constants
    void add_log_weight (const double *inc_weight, double delta = 1,
            bool add_zconst = true)
    {
        Eigen::Map<const Eigen::VectorXd> w(inc_weight, size_);
        if (add_zconst) {
            inc_weight_ = (delta * w).array().exp();
            zconst_ += std::log(weight_.dot(inc_weight_));
        }
        log_weight_ += delta * w;
        set_weight();
    }

    /// \brief The ESS (Effective Sample Size)
    ///
    /// \return The value of ESS for current particle set
    double ess () const
    {
        return ess_;
    }

    /// \brief Get indicator of resampling
    ///
    /// \return A bool value, \b true if the current iteration was resampled
    bool resampled () const
    {
        return resampled_;
    }

    /// \brief Set indicator of resampling
    ///
    /// \param resampled \b true if the current iteration was resampled
    void resampled (bool resampled)
    {
        resampled_ = resampled;
    }

    /// \brief Get the value of SMC normalizing constant
    ///
    /// \return SMC normalizng constant estimate
    double zconst () const
    {
        return zconst_;
    }

    /// \brief Reset the value of SMC normalizing constant
    void reset_zconst ()
    {
        zconst_ = 0;
    }

    /// \brief Perform resampling
    ///
    /// \param scheme The resampling scheme, see ResamplingScheme
    void resample (ResampleScheme scheme)
    {
        switch (scheme) {
            case MULTINOMIAL :
                resample_multinomial();
                break;
            case RESIDUAL :
                resample_residual();
                break;
            case STRATIFIED :
                resample_stratified();
                break;
            case SYSTEMATIC :
                resample_systematic();
                break;
            case RESIDUAL_STRATIFIED :
                resample_residual_stratified ();
                break;
            default :
                throw std::runtime_error(
                        "ERROR: vSMC::Particle::resample: "
                        "Unknown Resample Scheme");
        }
    }

    rng_type &prng (std::size_t id)
    {
        return prng_[id];
    }

    private :

    std::size_t size_;
    T value_;

    Eigen::VectorXd weight_;
    Eigen::VectorXd log_weight_;
    Eigen::VectorXd inc_weight_;
    Eigen::VectorXi replication_;

    double ess_;
    bool resampled_;
    double zconst_;

    std::vector<rng_type> prng_;
    typedef boost::random::binomial_distribution<> binom_type;
    binom_type binom_;

    void set_weight ()
    {
        double max_weight = log_weight_.maxCoeff();
        log_weight_ = log_weight_.array() - max_weight;
        weight_ = log_weight_.array().exp();
        double sum = weight_.sum();
        weight_ *= 1 / sum;
        ess_ = 1 / weight_.squaredNorm();
    }

    void resample_multinomial ()
    {
        weight2replication(size_);
        resample_do();
    }

    void resample_residual ()
    {
        // Reuse weight and log_weight. weight: act as the fractional part of
        // N * weight. log_weight: act as the integral part of N * weight.
        // They all will be reset to equal weights after resampling.  So it is
        // safe to modify them here.
        for (std::size_t i = 0; i != size_; ++i)
            weight_[i] = std::modf(size_ * weight_[i], log_weight_.data() + i);
        weight2replication(weight_.sum());
        for (std::size_t i = 0; i != size_; ++i)
            replication_[i] += log_weight_[i];
        resample_do();
    }

    void resample_stratified ()
    {
        replication_.setConstant(0);
        std::size_t j = 0;
        std::size_t k = 0;
        boost::random::uniform_01<> unif;
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size_) {
            while (j < cw * size_ - u && j != size_) {
                ++replication_[k];
                u = unif(prng_[j++]);
            }
            cw += weight_[++k];
        }
        resample_do();
    }

    void resample_systematic ()
    {
        replication_.setConstant(0);
        std::size_t j = 0;
        std::size_t k = 0;
        boost::random::uniform_01<> unif;
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size_) {
            while (j < cw * size_ - u && j != size_) {
                ++replication_[k];
		++j;
            }
            cw += weight_[++k];
        }
        resample_do();
    }

    void resample_residual_stratified ()
    {
        replication_.setConstant(0);
        for (std::size_t i = 0; i != size_; ++i)
            weight_[i] = std::modf(size_ * weight_[i], log_weight_.data() + i);
        std::size_t size = weight_.sum();
        weight_ /= size;
        std::size_t j = 0;
        std::size_t k = 0;
        boost::random::uniform_01<> unif;
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size) {
            while (j < cw * size_ - u && j != size) {
                ++replication_[k];
		++j;
            }
            cw += weight_[++k];
        }
        for (std::size_t i = 0; i != size_; ++i)
            replication_[i] += log_weight_[i];
        resample_do();
    }

    void weight2replication (std::size_t size)
    {
        double tp = weight_.sum();
        double sum_p = 0;
        std::size_t sum_n = 0;
        replication_.setConstant(0);
        for (std::size_t i = 0; i != size_; ++i) {
            if (sum_n < size && weight_[i] > 0) {
                binom_type::param_type
                    param(size - sum_n, weight_[i] / (tp - sum_p));
                replication_[i] = binom_(prng_[i], param);
            }
            sum_p += weight_[i];
            sum_n += replication_[i];
        }
    }

    void resample_do ()
    {
	// Some times the nuemrical round error can cause the total childs
	// differ from number of particles
	std::size_t sum = replication_.sum();
	if (sum != size_) {
            Eigen::VectorXd::Index id_max;
            replication_.maxCoeff(&id_max);
            replication_[id_max] += size_ - sum;
	}

        std::size_t from = 0;
        std::size_t time = 0;
        for (std::size_t to = 0; to != size_; ++to) {
            if (!replication_[to]) {
                // replication_[to] has zero child, copy from elsewhere
                if (replication_[from] - time <= 1) {
                    // only 1 child left on replication_[from]
                    time = 0;
                    do // move from to some position with at least 2 children
                        ++from;
                    while (replication_[from] < 2);
                }
                value_.copy(from, to);
                ++time;
            }
        }

        ess_ = size_;
        weight_.setConstant(1.0 / size_);
        log_weight_.setConstant(0);
    }
}; // class Particle

} // namespace vSMC

#endif // V_SMC_CORE_PARTICLE_HPP
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
// Copyright 2018-present Open Networking Foundation
// SPDX-License-Identifier: Apache-2.0

#include "stratum/hal/lib/common/hal.h"

#include <chrono>  // NOLINT
#include <utility>

#include "absl/base/macros.h"
#include "absl/memory/memory.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include "absl/synchronization/mutex.h"
#include "gflags/gflags.h"
#include "stratum/glue/logging.h"
#include "stratum/lib/constants.h"
#include "stratum/lib/macros.h"
#include "stratum/lib/utils.h"
#include "stratum/procmon/procmon.grpc.pb.h"

// TODO(unknown): Use FLAG_DEFINE for all flags.
DEFINE_string(external_stratum_urls, stratum::kExternalStratumUrls,
              "Comma-separated list of URLs for server to listen to for "
              "external calls from SDN controller, etc.");
DEFINE_string(local_stratum_url, stratum::kLocalStratumUrl,
              "URL for listening to local calls from stratum stub.");
DEFINE_bool(warmboot, false, "Determines whether HAL is in warmboot stage.");
DEFINE_string(procmon_service_addr, ::stratum::kProcmonServiceUrl,
              "URL of the procmon service to connect to.");
DEFINE_string(persistent_config_dir, "/etc/stratum/",
              "The persistent dir where all the config files will be stored.");
DEFINE_int32(grpc_keepalive_time_ms, 600000, "grpc keep alive time");
DEFINE_int32(grpc_keepalive_timeout_ms, 20000,
             "grpc keep alive timeout period");
DEFINE_int32(grpc_keepalive_min_ping_interval, 10000,
             "grpc keep alive minimum ping interval");
DEFINE_int32(grpc_keepalive_permit, 1, "grpc keep alive permit");
DEFINE_uint32(grpc_max_recv_msg_size, 256 * 1024 * 1024,
              "grpc server max receive message size (0 = gRPC default).");
DEFINE_uint32(grpc_max_send_msg_size, 0,
              "grpc server max send message size (0 = gRPC default).");

namespace stratum {
namespace hal {

namespace {

// Signal received callback which is registered as the handler for SIGINT and
// SIGTERM signals using signal() system call.
void SignalRcvCallback(int value) {
  Hal* hal = Hal::GetSingleton();
  if (hal == nullptr) return;
  hal->HandleSignal(value);
}

// Set the channel arguments to match the defualt keep-alive parameters set by
// the google3 side net/grpc clients.
void SetGrpcServerKeepAliveArgs(::grpc::ServerBuilder* builder) {
  builder->AddChannelArgument(GRPC_ARG_KEEPALIVE_TIME_MS,
                              FLAGS_grpc_keepalive_time_ms);
  builder->AddChannelArgument(GRPC_ARG_KEEPALIVE_TIMEOUT_MS,
                              FLAGS_grpc_keepalive_timeout_ms);
  builder->AddChannelArgument(
      GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS,
      FLAGS_grpc_keepalive_min_ping_interval);
  builder->AddChannelArgument(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS,
                              FLAGS_grpc_keepalive_permit);
}

}  // namespace

Hal* Hal::singleton_ = nullptr;
ABSL_CONST_INIT absl::Mutex Hal::init_lock_(absl::kConstInit);

Hal::Hal(OperationMode mode, SwitchInterface* switch_interface,
         AuthPolicyChecker* auth_policy_checker,
         CredentialsManager* credentials_manager)
    : mode_(mode),
      switch_interface_(ABSL_DIE_IF_NULL(switch_interface)),
      auth_policy_checker_(ABSL_DIE_IF_NULL(auth_policy_checker)),
      credentials_manager_(ABSL_DIE_IF_NULL(credentials_manager)),
      error_buffer_(ABSL_DIE_IF_NULL(new ErrorBuffer())),
      config_monitoring_service_(),
      p4_service_(nullptr),
      admin_service_(nullptr),
      certificate_management_service_(nullptr),
      diag_service_(nullptr),
      file_service_(nullptr),
      external_server_(nullptr),
      old_signal_handlers_() {}

Hal::~Hal() {
  // TODO(unknown): Handle this error?
  UnregisterSignalHandlers().IgnoreError();
}

::util::Status Hal::SanityCheck() {
  const std::vector<std::string> external_stratum_urls =
      absl::StrSplit(FLAGS_external_stratum_urls, ',', absl::SkipEmpty());
  CHECK_RETURN_IF_FALSE(!external_stratum_urls.empty())
      << "No external URL was given. This is invalid.";

  auto it =
      std::find_if(external_stratum_urls.begin(), external_stratum_urls.end(),
                   [](const std::string& url) {
                     return (url == FLAGS_local_stratum_url ||
                             // FIXME(boc) google only url ==
                             // FLAGS_cmal_service_url ||
                             url == FLAGS_procmon_service_addr);
                   });
  CHECK_RETURN_IF_FALSE(it == external_stratum_urls.end())
      << "You used one of these reserved local URLs as your external URLs: "
      << FLAGS_local_stratum_url
      << ", "
      /*FIXME(boc) google only << FLAGS_cmal_service_url */
      << ", " << FLAGS_procmon_service_addr << ".";

  CHECK_RETURN_IF_FALSE(!FLAGS_persistent_config_dir.empty())
      << "persistent_config_dir flag needs to be explicitly given.";

  LOG(INFO) << "HAL sanity checks all passed.";

  return ::util::OkStatus();
}

::util::Status Hal::Setup() {
  LOG(INFO) << "Setting up HAL in "
            << (FLAGS_warmboot ? "WARMBOOT" : "COLDBOOT") << " mode...";

  RETURN_IF_ERROR(RecursivelyCreateDir(FLAGS_persistent_config_dir));

  // Setup all the services. In case of coldboot setup, we push the saved
  // configs to the switch as part of setup. In case of warmboot, we only
  // recover the internal state of the class.
  RETURN_IF_ERROR(config_monitoring_service_->Setup(FLAGS_warmboot));
  RETURN_IF_ERROR(p4_service_->Setup(FLAGS_warmboot));
  RETURN_IF_ERROR(admin_service_->Setup(FLAGS_warmboot));
  RETURN_IF_ERROR(certificate_management_service_->Setup(FLAGS_warmboot));
  RETURN_IF_ERROR(diag_service_->Setup(FLAGS_warmboot));
  RETURN_IF_ERROR(file_service_->Setup(FLAGS_warmboot));
  if (FLAGS_warmboot) {
    // In case of warmboot, we also call unfreeze the switch interface after
    // services are setup. Note that finding the saved configs in case of
    // warmboot is critical. We will not perform unfreeze if we dont find those
    // files.
    LOG(INFO) << "Unfreezing HAL...";
    ::util::Status status = switch_interface_->Unfreeze();
    if (!status.ok()) {
      error_buffer_->AddError(status, "Failed to unfreeze HAL: ", GTL_LOC);
      return status;
    }
  }

  // Successful warmboot or coldboot will clear out the blocking errors.
  error_buffer_->ClearErrors();

  return ::util::OkStatus();
}

::util::Status Hal::Teardown() {
  // Teardown is called as part of both warmboot and coldboot shutdown. In case
  // of warmboot shutdown, the stack is first freezed by calling an RPC in
  // AdminService, which itself calls Freeze() method in SwitchInterface class.
  LOG(INFO) << "Shutting down HAL...";
  ::util::Status status = ::util::OkStatus();
  APPEND_STATUS_IF_ERROR(status, config_monitoring_service_->Teardown());
  APPEND_STATUS_IF_ERROR(status, p4_service_->Teardown());
  APPEND_STATUS_IF_ERROR(status, certificate_management_service_->Teardown());
  APPEND_STATUS_IF_ERROR(status, diag_service_->Teardown());
  APPEND_STATUS_IF_ERROR(status, file_service_->Teardown());
  APPEND_STATUS_IF_ERROR(status, switch_interface_->Shutdown());
  APPEND_STATUS_IF_ERROR(status, auth_policy_checker_->Shutdown());
  APPEND_STATUS_IF_ERROR(status, admin_service_->Teardown());
  if (!status.ok()) {
    error_buffer_->AddError(status, "Failed to shutdown HAL: ", GTL_LOC);
    return status;
  }

  return ::util::OkStatus();
}

::util::Status Hal::Run() {
  // All HAL external facing services listen to a list of secure external URLs
  // given by external_stratum_urls flag, as well as a local insecure URLs for
  // given by local_stratum_url flag. The insecure URLs is used by any local
  // stratum_stub binary running on the switch, since local connections cannot
  // support auth.
  const std::vector<std::string> external_stratum_urls =
      absl::StrSplit(FLAGS_external_stratum_urls, ',');
  {
    std::shared_ptr<::grpc::ServerCredentials> server_credentials =
        credentials_manager_->GenerateExternalFacingServerCredentials();
    ::grpc::ServerBuilder builder;
    SetGrpcServerKeepAliveArgs(&builder);
    builder.AddListeningPort(FLAGS_local_stratum_url,
                             ::grpc::InsecureServerCredentials());
    for (const auto& url : external_stratum_urls) {
      builder.AddListeningPort(url, server_credentials);
    }
    if (FLAGS_grpc_max_recv_msg_size > 0) {
      builder.SetMaxReceiveMessageSize(FLAGS_grpc_max_recv_msg_size);
      builder.AddChannelArgument<int>(GRPC_ARG_MAX_METADATA_SIZE,
                                      FLAGS_grpc_max_recv_msg_size);
    }
    if (FLAGS_grpc_max_send_msg_size > 0) {
      builder.SetMaxSendMessageSize(FLAGS_grpc_max_send_msg_size);
    }
    builder.RegisterService(config_monitoring_service_.get());
    builder.RegisterService(p4_service_.get());
    builder.RegisterService(admin_service_.get());
    builder.RegisterService(certificate_management_service_.get());
    builder.RegisterService(diag_service_.get());
    builder.RegisterService(file_service_.get());
    external_server_ = builder.BuildAndStart();
    if (external_server_ == nullptr) {
      return MAKE_ERROR(ERR_INTERNAL)
             << "Failed to start Stratum external facing services. This is an "
             << "internal error.";
    }
    LOG(ERROR) << "Stratum external facing services are listening to "
               << absl::StrJoin(external_stratum_urls, ", ") << ", "
               << FLAGS_local_stratum_url << "...";
  }

  if (mode_ != OPERATION_MODE_SIM) {
    // Try checking in with Procmon if we are not running in sim mode. Continue
    // if checkin fails.
    ::util::Status status = ProcmonCheckin();
    if (!status.ok()) {
      LOG(ERROR) << "Error when checking in with procmon: "
                 << status.error_message() << ".";
    }
  }

  external_server_->Wait();  // blocking until external_server_->Shutdown()
                             // is called. We dont wait on internal_service.
  return Teardown();
}

void Hal::HandleSignal(int value) {
  LOG(INFO) << "Received signal: " << strsignal(value);
  // Calling Shutdown() so the blocking call to Wait() returns.
  // NOTE: Seems like if there is an active stream Read(), calling Shutdown()
  // with no deadline will block forever, as it waits for all the active RPCs
  // to finish. To fix this, we give a deadline set to "now" so the call returns
  // immediately.
  external_server_->Shutdown(std::chrono::system_clock::now());
}

Hal* Hal::CreateSingleton(OperationMode mode, SwitchInterface* switch_interface,
                          AuthPolicyChecker* auth_policy_checker,
                          CredentialsManager* credentials_manager) {
  absl::WriterMutexLock l(&init_lock_);
  if (!singleton_) {
    singleton_ = new Hal(mode, switch_interface, auth_policy_checker,
                         credentials_manager);
    ::util::Status status = singleton_->RegisterSignalHandlers();
    if (!status.ok()) {
      LOG(ERROR) << "RegisterSignalHandlers() failed: " << status;
      delete singleton_;
      singleton_ = nullptr;
    }
    status = singleton_->InitializeServer();
    if (!status.ok()) {
      LOG(ERROR) << "InitializeServer() failed: " << status;
      delete singleton_;
      singleton_ = nullptr;
    }
  }

  return singleton_;
}

Hal* Hal::GetSingleton() {
  absl::ReaderMutexLock l(&init_lock_);
  return singleton_;
}

#define CHECK_IS_NULL(ptr)                                                    \
  if (ptr != nullptr) {                                                       \
    return MAKE_ERROR(ERR_INTERNAL)                                           \
           << #ptr << " is not nullptr. InitializeServer() cannot be called " \
           << "multiple times.";                                              \
  }

::util::Status Hal::InitializeServer() {
  CHECK_IS_NULL(config_monitoring_service_);
  CHECK_IS_NULL(p4_service_);
  CHECK_IS_NULL(admin_service_);
  CHECK_IS_NULL(certificate_management_service_);
  CHECK_IS_NULL(diag_service_);
  CHECK_IS_NULL(file_service_);
  CHECK_IS_NULL(external_server_);
  // FIXME(boc) google only
  // CHECK_IS_NULL(internal_server_);

  // Reset error_buffer_.
  error_buffer_->ClearErrors();

  // Build the HAL services.
  config_monitoring_service_ = absl::make_unique<ConfigMonitoringService>(
      mode_, switch_interface_, auth_policy_checker_, error_buffer_.get());
  p4_service_ = absl::make_unique<P4Service>(
      mode_, switch_interface_, auth_policy_checker_, error_buffer_.get());
  admin_service_ = absl::make_unique<AdminService>(
      mode_, switch_interface_, auth_policy_checker_, error_buffer_.get(),
      SignalRcvCallback);
  certificate_management_service_ =
      absl::make_unique<CertificateManagementService>(
          mode_, switch_interface_, auth_policy_checker_, error_buffer_.get());
  diag_service_ = absl::make_unique<DiagService>(
      mode_, switch_interface_, auth_policy_checker_, error_buffer_.get());
  file_service_ = absl::make_unique<FileService>(
      mode_, switch_interface_, auth_policy_checker_, error_buffer_.get());

  return ::util::OkStatus();
}

#undef CHECK_IS_NULL  // should not be used in any other method.

::util::Status Hal::RegisterSignalHandlers() {
  // Register the signal handlers and save the old handlers as well.
  std::vector<int> sig = {SIGINT, SIGTERM, SIGUSR2};
  for (const int s : sig) {
    sighandler_t h = signal(s, SignalRcvCallback);
    if (h == SIG_ERR) {
      return MAKE_ERROR(ERR_INTERNAL)
             << "Failed to register signal " << strsignal(s);
    }
    old_signal_handlers_[s] = h;
  }

  return ::util::OkStatus();
}

::util::Status Hal::UnregisterSignalHandlers() {
  // Register the old handlers for all the signals.
  for (const auto& e : old_signal_handlers_) {
    signal(e.first, e.second);
  }
  old_signal_handlers_.clear();

  return ::util::OkStatus();
}

::util::Status Hal::ProcmonCheckin() {
  // FIXME replace Procmon with gNOI
  std::unique_ptr<procmon::ProcmonService::Stub> stub =
      procmon::ProcmonService::NewStub(::grpc::CreateChannel(
          FLAGS_procmon_service_addr, ::grpc::InsecureChannelCredentials()));
  if (stub == nullptr) {
    return MAKE_ERROR(ERR_INTERNAL)
           << "Could not create stub for procmon gRPC service.";
  }

  procmon::CheckinRequest req;
  procmon::CheckinResponse resp;
  ::grpc::ClientContext context;
  req.set_checkin_key(getpid());
  ::grpc::Status status = stub->Checkin(&context, req, &resp);
  if (!status.ok()) {
    return MAKE_ERROR(ERR_INTERNAL)
           << "Failed to check in with procmon: " << status.error_message();
  }

  return ::util::OkStatus();
}

}  // namespace hal
}  // namespace stratum
<commit_msg>Replace `<chrono>` with absl time in hal.c (#647)<commit_after>// Copyright 2018 Google LLC
// Copyright 2018-present Open Networking Foundation
// SPDX-License-Identifier: Apache-2.0

#include "stratum/hal/lib/common/hal.h"

#include <utility>

#include "absl/base/macros.h"
#include "absl/memory/memory.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include "absl/synchronization/mutex.h"
#include "gflags/gflags.h"
#include "stratum/glue/logging.h"
#include "stratum/lib/constants.h"
#include "stratum/lib/macros.h"
#include "stratum/lib/utils.h"
#include "stratum/procmon/procmon.grpc.pb.h"

// TODO(unknown): Use FLAG_DEFINE for all flags.
DEFINE_string(external_stratum_urls, stratum::kExternalStratumUrls,
              "Comma-separated list of URLs for server to listen to for "
              "external calls from SDN controller, etc.");
DEFINE_string(local_stratum_url, stratum::kLocalStratumUrl,
              "URL for listening to local calls from stratum stub.");
DEFINE_bool(warmboot, false, "Determines whether HAL is in warmboot stage.");
DEFINE_string(procmon_service_addr, ::stratum::kProcmonServiceUrl,
              "URL of the procmon service to connect to.");
DEFINE_string(persistent_config_dir, "/etc/stratum/",
              "The persistent dir where all the config files will be stored.");
DEFINE_int32(grpc_keepalive_time_ms, 600000, "grpc keep alive time");
DEFINE_int32(grpc_keepalive_timeout_ms, 20000,
             "grpc keep alive timeout period");
DEFINE_int32(grpc_keepalive_min_ping_interval, 10000,
             "grpc keep alive minimum ping interval");
DEFINE_int32(grpc_keepalive_permit, 1, "grpc keep alive permit");
DEFINE_uint32(grpc_max_recv_msg_size, 256 * 1024 * 1024,
              "grpc server max receive message size (0 = gRPC default).");
DEFINE_uint32(grpc_max_send_msg_size, 0,
              "grpc server max send message size (0 = gRPC default).");

namespace stratum {
namespace hal {

namespace {

// Signal received callback which is registered as the handler for SIGINT and
// SIGTERM signals using signal() system call.
void SignalRcvCallback(int value) {
  Hal* hal = Hal::GetSingleton();
  if (hal == nullptr) return;
  hal->HandleSignal(value);
}

// Set the channel arguments to match the defualt keep-alive parameters set by
// the google3 side net/grpc clients.
void SetGrpcServerKeepAliveArgs(::grpc::ServerBuilder* builder) {
  builder->AddChannelArgument(GRPC_ARG_KEEPALIVE_TIME_MS,
                              FLAGS_grpc_keepalive_time_ms);
  builder->AddChannelArgument(GRPC_ARG_KEEPALIVE_TIMEOUT_MS,
                              FLAGS_grpc_keepalive_timeout_ms);
  builder->AddChannelArgument(
      GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS,
      FLAGS_grpc_keepalive_min_ping_interval);
  builder->AddChannelArgument(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS,
                              FLAGS_grpc_keepalive_permit);
}

}  // namespace

Hal* Hal::singleton_ = nullptr;
ABSL_CONST_INIT absl::Mutex Hal::init_lock_(absl::kConstInit);

Hal::Hal(OperationMode mode, SwitchInterface* switch_interface,
         AuthPolicyChecker* auth_policy_checker,
         CredentialsManager* credentials_manager)
    : mode_(mode),
      switch_interface_(ABSL_DIE_IF_NULL(switch_interface)),
      auth_policy_checker_(ABSL_DIE_IF_NULL(auth_policy_checker)),
      credentials_manager_(ABSL_DIE_IF_NULL(credentials_manager)),
      error_buffer_(ABSL_DIE_IF_NULL(new ErrorBuffer())),
      config_monitoring_service_(),
      p4_service_(nullptr),
      admin_service_(nullptr),
      certificate_management_service_(nullptr),
      diag_service_(nullptr),
      file_service_(nullptr),
      external_server_(nullptr),
      old_signal_handlers_() {}

Hal::~Hal() {
  // TODO(unknown): Handle this error?
  UnregisterSignalHandlers().IgnoreError();
}

::util::Status Hal::SanityCheck() {
  const std::vector<std::string> external_stratum_urls =
      absl::StrSplit(FLAGS_external_stratum_urls, ',', absl::SkipEmpty());
  CHECK_RETURN_IF_FALSE(!external_stratum_urls.empty())
      << "No external URL was given. This is invalid.";

  auto it =
      std::find_if(external_stratum_urls.begin(), external_stratum_urls.end(),
                   [](const std::string& url) {
                     return (url == FLAGS_local_stratum_url ||
                             // FIXME(boc) google only url ==
                             // FLAGS_cmal_service_url ||
                             url == FLAGS_procmon_service_addr);
                   });
  CHECK_RETURN_IF_FALSE(it == external_stratum_urls.end())
      << "You used one of these reserved local URLs as your external URLs: "
      << FLAGS_local_stratum_url
      << ", "
      /*FIXME(boc) google only << FLAGS_cmal_service_url */
      << ", " << FLAGS_procmon_service_addr << ".";

  CHECK_RETURN_IF_FALSE(!FLAGS_persistent_config_dir.empty())
      << "persistent_config_dir flag needs to be explicitly given.";

  LOG(INFO) << "HAL sanity checks all passed.";

  return ::util::OkStatus();
}

::util::Status Hal::Setup() {
  LOG(INFO) << "Setting up HAL in "
            << (FLAGS_warmboot ? "WARMBOOT" : "COLDBOOT") << " mode...";

  RETURN_IF_ERROR(RecursivelyCreateDir(FLAGS_persistent_config_dir));

  // Setup all the services. In case of coldboot setup, we push the saved
  // configs to the switch as part of setup. In case of warmboot, we only
  // recover the internal state of the class.
  RETURN_IF_ERROR(config_monitoring_service_->Setup(FLAGS_warmboot));
  RETURN_IF_ERROR(p4_service_->Setup(FLAGS_warmboot));
  RETURN_IF_ERROR(admin_service_->Setup(FLAGS_warmboot));
  RETURN_IF_ERROR(certificate_management_service_->Setup(FLAGS_warmboot));
  RETURN_IF_ERROR(diag_service_->Setup(FLAGS_warmboot));
  RETURN_IF_ERROR(file_service_->Setup(FLAGS_warmboot));
  if (FLAGS_warmboot) {
    // In case of warmboot, we also call unfreeze the switch interface after
    // services are setup. Note that finding the saved configs in case of
    // warmboot is critical. We will not perform unfreeze if we dont find those
    // files.
    LOG(INFO) << "Unfreezing HAL...";
    ::util::Status status = switch_interface_->Unfreeze();
    if (!status.ok()) {
      error_buffer_->AddError(status, "Failed to unfreeze HAL: ", GTL_LOC);
      return status;
    }
  }

  // Successful warmboot or coldboot will clear out the blocking errors.
  error_buffer_->ClearErrors();

  return ::util::OkStatus();
}

::util::Status Hal::Teardown() {
  // Teardown is called as part of both warmboot and coldboot shutdown. In case
  // of warmboot shutdown, the stack is first freezed by calling an RPC in
  // AdminService, which itself calls Freeze() method in SwitchInterface class.
  LOG(INFO) << "Shutting down HAL...";
  ::util::Status status = ::util::OkStatus();
  APPEND_STATUS_IF_ERROR(status, config_monitoring_service_->Teardown());
  APPEND_STATUS_IF_ERROR(status, p4_service_->Teardown());
  APPEND_STATUS_IF_ERROR(status, certificate_management_service_->Teardown());
  APPEND_STATUS_IF_ERROR(status, diag_service_->Teardown());
  APPEND_STATUS_IF_ERROR(status, file_service_->Teardown());
  APPEND_STATUS_IF_ERROR(status, switch_interface_->Shutdown());
  APPEND_STATUS_IF_ERROR(status, auth_policy_checker_->Shutdown());
  APPEND_STATUS_IF_ERROR(status, admin_service_->Teardown());
  if (!status.ok()) {
    error_buffer_->AddError(status, "Failed to shutdown HAL: ", GTL_LOC);
    return status;
  }

  return ::util::OkStatus();
}

::util::Status Hal::Run() {
  // All HAL external facing services listen to a list of secure external URLs
  // given by external_stratum_urls flag, as well as a local insecure URLs for
  // given by local_stratum_url flag. The insecure URLs is used by any local
  // stratum_stub binary running on the switch, since local connections cannot
  // support auth.
  const std::vector<std::string> external_stratum_urls =
      absl::StrSplit(FLAGS_external_stratum_urls, ',');
  {
    std::shared_ptr<::grpc::ServerCredentials> server_credentials =
        credentials_manager_->GenerateExternalFacingServerCredentials();
    ::grpc::ServerBuilder builder;
    SetGrpcServerKeepAliveArgs(&builder);
    builder.AddListeningPort(FLAGS_local_stratum_url,
                             ::grpc::InsecureServerCredentials());
    for (const auto& url : external_stratum_urls) {
      builder.AddListeningPort(url, server_credentials);
    }
    if (FLAGS_grpc_max_recv_msg_size > 0) {
      builder.SetMaxReceiveMessageSize(FLAGS_grpc_max_recv_msg_size);
      builder.AddChannelArgument<int>(GRPC_ARG_MAX_METADATA_SIZE,
                                      FLAGS_grpc_max_recv_msg_size);
    }
    if (FLAGS_grpc_max_send_msg_size > 0) {
      builder.SetMaxSendMessageSize(FLAGS_grpc_max_send_msg_size);
    }
    builder.RegisterService(config_monitoring_service_.get());
    builder.RegisterService(p4_service_.get());
    builder.RegisterService(admin_service_.get());
    builder.RegisterService(certificate_management_service_.get());
    builder.RegisterService(diag_service_.get());
    builder.RegisterService(file_service_.get());
    external_server_ = builder.BuildAndStart();
    if (external_server_ == nullptr) {
      return MAKE_ERROR(ERR_INTERNAL)
             << "Failed to start Stratum external facing services. This is an "
             << "internal error.";
    }
    LOG(ERROR) << "Stratum external facing services are listening to "
               << absl::StrJoin(external_stratum_urls, ", ") << ", "
               << FLAGS_local_stratum_url << "...";
  }

  if (mode_ != OPERATION_MODE_SIM) {
    // Try checking in with Procmon if we are not running in sim mode. Continue
    // if checkin fails.
    ::util::Status status = ProcmonCheckin();
    if (!status.ok()) {
      LOG(ERROR) << "Error when checking in with procmon: "
                 << status.error_message() << ".";
    }
  }

  external_server_->Wait();  // blocking until external_server_->Shutdown()
                             // is called. We dont wait on internal_service.
  return Teardown();
}

void Hal::HandleSignal(int value) {
  LOG(INFO) << "Received signal: " << strsignal(value);
  // Calling Shutdown() so the blocking call to Wait() returns.
  // NOTE: Seems like if there is an active stream Read(), calling Shutdown()
  // with no deadline will block forever, as it waits for all the active RPCs
  // to finish. To fix this, we give a deadline set to "now" so the call returns
  // immediately.
  external_server_->Shutdown(absl::ToChronoTime(absl::Now()));
}

Hal* Hal::CreateSingleton(OperationMode mode, SwitchInterface* switch_interface,
                          AuthPolicyChecker* auth_policy_checker,
                          CredentialsManager* credentials_manager) {
  absl::WriterMutexLock l(&init_lock_);
  if (!singleton_) {
    singleton_ = new Hal(mode, switch_interface, auth_policy_checker,
                         credentials_manager);
    ::util::Status status = singleton_->RegisterSignalHandlers();
    if (!status.ok()) {
      LOG(ERROR) << "RegisterSignalHandlers() failed: " << status;
      delete singleton_;
      singleton_ = nullptr;
    }
    status = singleton_->InitializeServer();
    if (!status.ok()) {
      LOG(ERROR) << "InitializeServer() failed: " << status;
      delete singleton_;
      singleton_ = nullptr;
    }
  }

  return singleton_;
}

Hal* Hal::GetSingleton() {
  absl::ReaderMutexLock l(&init_lock_);
  return singleton_;
}

#define CHECK_IS_NULL(ptr)                                                    \
  if (ptr != nullptr) {                                                       \
    return MAKE_ERROR(ERR_INTERNAL)                                           \
           << #ptr << " is not nullptr. InitializeServer() cannot be called " \
           << "multiple times.";                                              \
  }

::util::Status Hal::InitializeServer() {
  CHECK_IS_NULL(config_monitoring_service_);
  CHECK_IS_NULL(p4_service_);
  CHECK_IS_NULL(admin_service_);
  CHECK_IS_NULL(certificate_management_service_);
  CHECK_IS_NULL(diag_service_);
  CHECK_IS_NULL(file_service_);
  CHECK_IS_NULL(external_server_);
  // FIXME(boc) google only
  // CHECK_IS_NULL(internal_server_);

  // Reset error_buffer_.
  error_buffer_->ClearErrors();

  // Build the HAL services.
  config_monitoring_service_ = absl::make_unique<ConfigMonitoringService>(
      mode_, switch_interface_, auth_policy_checker_, error_buffer_.get());
  p4_service_ = absl::make_unique<P4Service>(
      mode_, switch_interface_, auth_policy_checker_, error_buffer_.get());
  admin_service_ = absl::make_unique<AdminService>(
      mode_, switch_interface_, auth_policy_checker_, error_buffer_.get(),
      SignalRcvCallback);
  certificate_management_service_ =
      absl::make_unique<CertificateManagementService>(
          mode_, switch_interface_, auth_policy_checker_, error_buffer_.get());
  diag_service_ = absl::make_unique<DiagService>(
      mode_, switch_interface_, auth_policy_checker_, error_buffer_.get());
  file_service_ = absl::make_unique<FileService>(
      mode_, switch_interface_, auth_policy_checker_, error_buffer_.get());

  return ::util::OkStatus();
}

#undef CHECK_IS_NULL  // should not be used in any other method.

::util::Status Hal::RegisterSignalHandlers() {
  // Register the signal handlers and save the old handlers as well.
  std::vector<int> sig = {SIGINT, SIGTERM, SIGUSR2};
  for (const int s : sig) {
    sighandler_t h = signal(s, SignalRcvCallback);
    if (h == SIG_ERR) {
      return MAKE_ERROR(ERR_INTERNAL)
             << "Failed to register signal " << strsignal(s);
    }
    old_signal_handlers_[s] = h;
  }

  return ::util::OkStatus();
}

::util::Status Hal::UnregisterSignalHandlers() {
  // Register the old handlers for all the signals.
  for (const auto& e : old_signal_handlers_) {
    signal(e.first, e.second);
  }
  old_signal_handlers_.clear();

  return ::util::OkStatus();
}

::util::Status Hal::ProcmonCheckin() {
  // FIXME replace Procmon with gNOI
  std::unique_ptr<procmon::ProcmonService::Stub> stub =
      procmon::ProcmonService::NewStub(::grpc::CreateChannel(
          FLAGS_procmon_service_addr, ::grpc::InsecureChannelCredentials()));
  if (stub == nullptr) {
    return MAKE_ERROR(ERR_INTERNAL)
           << "Could not create stub for procmon gRPC service.";
  }

  procmon::CheckinRequest req;
  procmon::CheckinResponse resp;
  ::grpc::ClientContext context;
  req.set_checkin_key(getpid());
  ::grpc::Status status = stub->Checkin(&context, req, &resp);
  if (!status.ok()) {
    return MAKE_ERROR(ERR_INTERNAL)
           << "Failed to check in with procmon: " << status.error_message();
  }

  return ::util::OkStatus();
}

}  // namespace hal
}  // namespace stratum
<|endoftext|>


<commit_before>/**
 * Description: BigInt (Big Integer library)
 * Usage:  See constructors, operators like +, -, *, /, >, >=, <, <=, ==, toString
 * Note: Remove references '&' in overloaded operators for chaining operations.
 * Source: https://github.com/dragonslayerx
 */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

class Bigint {

    const static int MAX = 100005;
    char x[MAX];
    int length;

    void align(char *X, int numDigits) {
        int length = strlen(X);
        for (int i = length; i < numDigits; i++) X[i]='0';
        X[numDigits]='\0';
    }

    int add(char *X, int lenX, char *Y, int lenY, int carry, char *Z) {
        int maxLen = max(lenX, lenY);
        align(X, maxLen); align(Y, maxLen);
        for (int i = 0; i < maxLen; i++) {
            int num = (X[i]-'0') + (Y[i]-'0') + carry;
            Z[i] = num%10 + '0';
            carry = num / 10;
        }
        if (carry) Z[maxLen++] = carry+'0';
        Z[maxLen] = '\0';

        //Put everything back to original state
        X[lenX]='\0'; Y[lenY]='\0';

        return maxLen;
    }

    int substract(char *X, int lenX, char *Y, int lenY, char *Z){
        int maxLen = max(lenX, lenY);
        align(X, maxLen); align(Y, maxLen);
        for (int i = 0; i < maxLen; i++) Y[i]=('9'-Y[i])+'0';
        int len = add(X, lenX, Y, maxLen, 1, Z);
        Z[len--] = '\0';

        //Put everything back to original state
        for (int i = 0; i < maxLen; i++) Y[i]=('9'-Y[i])+'0';
		X[lenX]='\0'; Y[lenY]='\0';

        return len;
    }

    int multiply(char *X, int lenX, char *Y, int lenY, char *Z) {
        if (lenX < lenY) {
            swap(X, Y); swap(lenX, lenY);
        }
        char result[MAX];
        int lenZ = 0;
        for (int i = 0; Y[i]; i++) {
            int digit = Y[i]-'0';
            int carry = 0, size = 0;
            for (int j = 0; X[j]; j++) {
                int val = ((X[j]-'0')*digit) + carry;
                carry = val/10;
                val %= 10;
                result[size++] = val+'0';
            }
            if (carry) result[size++] = carry + '0';
            result[size]='\0';

            for (int j = size; j >= 0; j--) result[j+i] = result[j];
            for (int j = 0; j < i; j++) result[j]='0';

            char finalResult[MAX];
            lenZ = add(result, size+i, Z, lenZ, 0, finalResult);
            strcpy(Z, finalResult);
        }
        return lenZ;
    }

    template<class T>
    int divideNmodulo(char *X, int lenX, T divisor, char *Z, T &modulo) {
        int remainder = 0;
   		int size = 0;
   		for(int i = lenX-1; i >= 0; i--){
    		remainder *= 10;
      		remainder += X[i]- '0';
      		Z[size++] = remainder/divisor + '0';
      		remainder %= divisor;
    	}
    	Z[size]='\0';
    	reverse(Z, Z+size);
    	modulo = remainder;
    	return size;
    }

    //Logical Operations
    bool equals(char *X, int lenX, char *Y, int lenY) {
        int maxLen = max(lenX, lenY);
        align(X, maxLen); align(Y, maxLen);
        for (int i = maxLen; i >= 0; i--) {
            if (X[i] != Y[i]) return false;
        }

        //Put everything back to original state
        X[lenX] = '\0'; Y[lenY] = '\0';

        return true;
    }

    bool greater(char *X, int lenX, char *Y, int lenY) {
        int maxLen = max(lenX, lenY);
        align(X, maxLen); align(Y, maxLen);
        for (int i = maxLen; i >= 0; i--) {
            if (X[i] > Y[i]) return true;
        }

        //Put everything back to original state
        X[lenX] = '\0'; Y[lenY] = '\0';

        return false;
    }

public:
    //Constructors
    Bigint() {
        x[0]='0'; x[1]='\0';
        length=1;
    }

    Bigint(string s) {
        length = s.size();
        for (int i=0, j=length-1; i < s.size(); i++, j--) x[j]=s[i];
        x[length]='\0';
    }

    Bigint(int v) {
        int size = 0;
        while (v) {
            x[size++] = v % 10 + '0';
            v /= 10;
        }
        x[size]='\0';
        length = size;
    }

    //Arithmetic Operations
    Bigint operator +(Bigint &b) {
        Bigint r;
        r.length = add(this->x, this->length, b.x, b.length, 0, r.x);
        return r;
    }

    Bigint operator *(Bigint &b) {
        Bigint r;
        r.length = multiply(this->x, this->length, b.x, b.length, r.x);
        return r;
    }

    Bigint operator -(Bigint &b) {
        Bigint r;
        r.length = substract(this->x, this->length, b.x, b.length, r.x);
        return r;
    }

    Bigint operator /(int divisor) {
        Bigint r;
        int modulo = 0;
        r.length = divideNmodulo(this->x, this->length, divisor, r.x, modulo);
        return r;
    }

    int operator %(int divisor) {
        Bigint r;
        int modulo = 0;
        r.length = divideNmodulo(this->x, this->length, divisor, r.x, modulo);
        return modulo;
    }

    //Logical Operators
    bool operator ==(Bigint &b) {
        return equals(this->x, this->length, b.x, b.length);
    }

    bool operator >(Bigint &b) {
        return !greater(b.x, b.length, this->x, this->length);
    }

    bool operator >=(Bigint &b) {
        return (((*this)>b) || ((*this)==b));
    }

    bool operator <(Bigint &b) {
        return !((*this)>=b);
    }

    bool operator <=(Bigint &b) {
        return !((*this)>b);
    }

    string trimZeros(string &s) {
        int start = 0;
        while (s[start]=='0') start++;
        return s.substr(start);
    }

    string toString() {
        string s(x, x+length);
        reverse(s.begin(), s.end());
        return trimZeros(s);
    }

    friend std::ostream& operator<<(ostream &o, Bigint v) {
        o << v.toString();
        return o;
    }
};

int main() {
    Bigint A("123456789"); // Construct Bigint using string representation
    Bigint B(987654321); // Construct Bigint using integer representation
    Bigint C("456789");
    cout << A * B << endl; // Overridden ostream
    cout << A * B + C << endl; // Chaining operations
    cout << (A > B) << endl;
    // logical operations
    if (A > B) cout << "A is greater than B" << endl;
    else cout << "B is greater than A" << endl;
}
<commit_msg>bigint: fix: toString with value 0<commit_after>/*
 * Description: BigInt (Big Integer library)
 * Usage:  See constructors, operators like +, -, *, /, >, >=, <, <=, ==, toString
 * Note: Remove references '&' in overloaded operators for chaining operations.
 * Source: https://github.com/dragonslayerx
 */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

class Bigint {

    const static int MAX = 100005;
    char x[MAX];
    int length;

    void align(char *X, int numDigits) {
        int length = strlen(X);
        for (int i = length; i < numDigits; i++) X[i]='0';
        X[numDigits]='\0';
    }

    int add(char *X, int lenX, char *Y, int lenY, int carry, char *Z) {
        int maxLen = max(lenX, lenY);
        align(X, maxLen); align(Y, maxLen);
        for (int i = 0; i < maxLen; i++) {
            int num = (X[i]-'0') + (Y[i]-'0') + carry;
            Z[i] = num%10 + '0';
            carry = num / 10;
        }
        if (carry) Z[maxLen++] = carry+'0';
        Z[maxLen] = '\0';

        //Put everything back to original state
        X[lenX]='\0'; Y[lenY]='\0';

        return maxLen;
    }

    int substract(char *X, int lenX, char *Y, int lenY, char *Z){
        int maxLen = max(lenX, lenY);
        align(X, maxLen); align(Y, maxLen);
        for (int i = 0; i < maxLen; i++) Y[i]=('9'-Y[i])+'0';
        int len = add(X, lenX, Y, maxLen, 1, Z);
        Z[len--] = '\0';

        //Put everything back to original state
        for (int i = 0; i < maxLen; i++) Y[i]=('9'-Y[i])+'0';
        X[lenX]='\0'; Y[lenY]='\0';

        return len;
    }

    int multiply(char *X, int lenX, char *Y, int lenY, char *Z) {
        if (lenX < lenY) {
            swap(X, Y); swap(lenX, lenY);
        }
        char result[MAX];
        int lenZ = 0;
        for (int i = 0; Y[i]; i++) {
            int digit = Y[i]-'0';
            int carry = 0, size = 0;
            for (int j = 0; X[j]; j++) {
                int val = ((X[j]-'0')*digit) + carry;
                carry = val/10;
                val %= 10;
                result[size++] = val+'0';
            }
            if (carry) result[size++] = carry + '0';
            result[size]='\0';

            for (int j = size; j >= 0; j--) result[j+i] = result[j];
            for (int j = 0; j < i; j++) result[j]='0';

            char finalResult[MAX];
            lenZ = add(result, size+i, Z, lenZ, 0, finalResult);
            strcpy(Z, finalResult);
        }
        return lenZ;
    }

    template<class T>
        int divideNmodulo(char *X, int lenX, T divisor, char *Z, T &modulo) {
            int remainder = 0;
            int size = 0;
            for(int i = lenX-1; i >= 0; i--){
                remainder *= 10;
                remainder += X[i]- '0';
                Z[size++] = remainder/divisor + '0';
                remainder %= divisor;
            }
            Z[size]='\0';
            reverse(Z, Z+size);
            modulo = remainder;
            return size;
        }

    //Logical Operations
    bool equals(char *X, int lenX, char *Y, int lenY) {
        int maxLen = max(lenX, lenY);
        align(X, maxLen); align(Y, maxLen);
        for (int i = maxLen; i >= 0; i--) {
            if (X[i] != Y[i]) return false;
        }

        //Put everything back to original state
        X[lenX] = '\0'; Y[lenY] = '\0';

        return true;
    }

    bool greater(char *X, int lenX, char *Y, int lenY) {
        int maxLen = max(lenX, lenY);
        align(X, maxLen); align(Y, maxLen);
        for (int i = maxLen; i >= 0; i--) {
            if (X[i] > Y[i]) return true;
        }

        //Put everything back to original state
        X[lenX] = '\0'; Y[lenY] = '\0';

        return false;
    }

public:
    //Constructors
    Bigint() {
        x[0]='0'; x[1]='\0';
        length=1;
    }

    Bigint(string s) {
        length = s.size();
        for (int i=0, j=length-1; i < s.size(); i++, j--) x[j]=s[i];
        x[length]='\0';
    }

    Bigint(int v) {
        int size = 0;
        while (v) {
            x[size++] = v % 10 + '0';
            v /= 10;
        }
        x[size]='\0';
        length = size;
    }

    //Arithmetic Operations
    Bigint operator +(Bigint &b) {
        Bigint r;
        r.length = add(this->x, this->length, b.x, b.length, 0, r.x);
        return r;
    }

    Bigint operator *(Bigint &b) {
        Bigint r;
        r.length = multiply(this->x, this->length, b.x, b.length, r.x);
        return r;
    }

    Bigint operator -(Bigint &b) {
        Bigint r;
        r.length = substract(this->x, this->length, b.x, b.length, r.x);
        return r;
    }

    Bigint operator /(int divisor) {
        Bigint r;
        int modulo = 0;
        r.length = divideNmodulo(this->x, this->length, divisor, r.x, modulo);
        return r;
    }

    int operator %(int divisor) {
        Bigint r;
        int modulo = 0;
        r.length = divideNmodulo(this->x, this->length, divisor, r.x, modulo);
        return modulo;
    }

    //Logical Operators
    bool operator ==(Bigint &b) {
        return equals(this->x, this->length, b.x, b.length);
    }

    bool operator >(Bigint &b) {
        return !greater(b.x, b.length, this->x, this->length);
    }

    bool operator >=(Bigint &b) {
        return (((*this)>b) || ((*this)==b));
    }

    bool operator <(Bigint &b) {
        return !((*this)>=b);
    }

    bool operator <=(Bigint &b) {
        return !((*this)>b);
    }

    string trimZeros(string &s) {
        int start = 0;
        while (s[start]=='0') start++;
        return s.substr(start);
    }

    string toString() {
        string s(x, x+length);
        reverse(s.begin(), s.end());
        s = trimZeros(s);
        if(s.length() == 0)
            return "0";
        return s;
    }

    friend std::ostream& operator<<(ostream &o, Bigint v) {
        o << v.toString();
        return o;
    }
};

int main() {
    Bigint A("123456789"); // Construct Bigint using string representation
    Bigint B(987654321); // Construct Bigint using integer representation
    Bigint C("456789");
    Bigint D("0");
    cout << "A * B: " << A * B << endl; // Overridden ostream
    cout << "A * B + C: " << A * B + C << endl; // Chaining operations
    cout << "(A > B): " << (A > B) << endl;
    cout << "D: " << D << endl;
    // logical operations
    if (A > B) cout << "A is greater than B" << endl;
    if (B > A) cout << "B is greater than A" << endl;
    if (A == B) cout << "A is equal to B" << endl;
}
<|endoftext|>


<commit_before>// RUN: cat %s | %cling -Xclang -verify | FileCheck %s
//This file checks a call instruction. The called function has arguments with nonnull attribute.
#include <string.h>
// XFAIL: darwin
// XFAIL: i686-pc-linux-gnu

char *p = 0;
strcmp("a", p); // expected-warning {{warning: null passed to a callee which requires a non-null argument}}

strcmp(p, "a"); // expected-warning {{warning: null passed to a callee which requires a non-null argument}}

extern "C" int printf(const char* fmt, ...);
.rawInput 1
extern "C" int cannotCallWithNull(int* p = 0);
extern "C" int cannotCallWithNull(int* p) __attribute__((nonnull(1)));
extern "C" int cannotCallWithNull(int* p);
extern "C" int cannotCallWithNull(int* p);
.rawInput 0

extern "C" int cannotCallWithNull(int* p) {
  if (!p)
    printf("Must not be called with p=0.\n");
  return 1;
}
int *q = 0;
cannotCallWithNull(q); // expected-warning {{warning: null passed to a callee which requires a non-null argument}}
//CHECK-NOT: Must not be called with p=0.
cannotCallWithNull(new int(4))
//CHECK: (int) 1

.q
<commit_msg>Adapt to new diag format.<commit_after>// RUN: cat %s | %cling -Xclang -verify | FileCheck %s
//This file checks a call instruction. The called function has arguments with nonnull attribute.
#include <string.h>
// XFAIL: darwin
// XFAIL: i686-pc-linux-gnu

char *p = 0;
strcmp("a", p); // expected-warning {{null passed to a callee which requires a non-null argument}}

strcmp(p, "a"); // expected-warning {{null passed to a callee which requires a non-null argument}}

extern "C" int printf(const char* fmt, ...);
.rawInput 1
extern "C" int cannotCallWithNull(int* p = 0);
extern "C" int cannotCallWithNull(int* p) __attribute__((nonnull(1)));
extern "C" int cannotCallWithNull(int* p);
extern "C" int cannotCallWithNull(int* p);
.rawInput 0

extern "C" int cannotCallWithNull(int* p) {
  if (!p)
    printf("Must not be called with p=0.\n");
  return 1;
}
int *q = 0;
cannotCallWithNull(q); // expected-warning {{null passed to a callee which requires a non-null argument}}
//CHECK-NOT: Must not be called with p=0.
cannotCallWithNull(new int(4))
//CHECK: (int) 1

.q
<|endoftext|>