<commit_before>#pragma once

#include <mutex>
#include <thread>

#include <SFML/Config.hpp>
#include <SFML/Graphics.hpp>
#include <yaml-cpp/yaml.h>

#ifdef NDEBUG
#define LOGOG_LEVEL LOGOG_LEVEL_INFO
#else
#define LOGOG_LEVEL LOGOG_LEVEL_ALL
#endif
#include <logog/logog.hpp>

#include <Sprite.hpp>

class Engine {
public:
    const uint32_t JAGE_VERSION_MAJOR = 0;
    const uint32_t JAGE_VERSION_MINOR = 5;
    const uint32_t JAGE_VERSION_REVISION = 2;

    Engine(const int argc, const char** argv);
    ~Engine();

    bool ready();

    // main event loop
    bool run();

private:
    /* methods */

    //event dispatcher
     void processEvents();
    // update the simulation
    void update(const sf::Time& elapsed);
    // render everything, runs in separate thread
    void renderLoop();

    // event handlers
    void handleResize(const sf::Event::SizeEvent& newSize);
    void handleKeyPress(const sf::Event& event);
    void handleKeyRelease(const sf::Event& event);

    // log some build & system info
    void dumpSystemInfo();

    // get the configuration from an INI file
    void readConfig();

    // [re]create the rendering window, possibly fullscreen
    void createWindow(const bool shouldFullscreen = false);
    // change the viewport to maintain 16:9 aspect ratio
    void adjustAspect(const sf::Vector2u& newSize);

    // control the window mutex and active window
    void inline lockWindow();
    void inline releaseWindow();

    /* member data */

    int argc;
    const char** argv;

    logog::LogFile* logFile;
    logog::Cout* logConsole;
    logog::Formatter* formatter;

    std::unique_ptr<std::thread> renderThread;

    bool isReady = false;
    bool running = false;

    std::string game;
    std::string data_dir;

    // render internally to 720p widescreen
    unsigned int renderWidth = 1280;
    unsigned int renderHeight = 720;

    struct {
        std::string name;
        // this size fits in most screens in windowed mode
        unsigned int width = 1200;
        unsigned int height = 675;
        // don't start fullscreen
        bool fullscreen = false;
        // but do use desktop size when going fullscreen
        bool useDesktopSize = true;
        // obvi, use vsync
        bool vsync = true;
        // controller/keyboard settings
        float deadZone = 15.0;
        float keySpeed = 75.0;
    } config;

    // where everything is drawn
    sf::RenderWindow window;
    // controls the 2D camera, used for rendering internally at a set size
    sf::View view;
    // where we render the game before copying it to the window
    sf::RenderTexture screen;

    // mutexes for the window and sprite list
    std::recursive_mutex windowMutex;
    std::recursive_mutex spritesMutex;

    // all normal sprites to draw
    std::vector<std::shared_ptr<Sprite>> sprites;

    // the player's ship sprite
    std::shared_ptr<Sprite> player;
    // computer opponent's ship sprite
    std::shared_ptr<Sprite> enemy;
};
<commit_msg>std::recursive_mutex was not the right choice.<commit_after>#pragma once

#include <mutex>
#include <thread>

#include <SFML/Config.hpp>
#include <SFML/Graphics.hpp>
#include <yaml-cpp/yaml.h>

#ifdef NDEBUG
#define LOGOG_LEVEL LOGOG_LEVEL_INFO
#else
#define LOGOG_LEVEL LOGOG_LEVEL_ALL
#endif
#include <logog/logog.hpp>

#include <Sprite.hpp>

class Engine {
public:
    const uint32_t JAGE_VERSION_MAJOR = 0;
    const uint32_t JAGE_VERSION_MINOR = 5;
    const uint32_t JAGE_VERSION_REVISION = 2;

    Engine(const int argc, const char** argv);
    ~Engine();

    bool ready();

    // main event loop
    bool run();

private:
    /* methods */

    //event dispatcher
     void processEvents();
    // update the simulation
    void update(const sf::Time& elapsed);
    // render everything, runs in separate thread
    void renderLoop();

    // event handlers
    void handleResize(const sf::Event::SizeEvent& newSize);
    void handleKeyPress(const sf::Event& event);
    void handleKeyRelease(const sf::Event& event);

    // log some build & system info
    void dumpSystemInfo();

    // get the configuration from an INI file
    void readConfig();

    // [re]create the rendering window, possibly fullscreen
    void createWindow(const bool shouldFullscreen = false);
    // change the viewport to maintain 16:9 aspect ratio
    void adjustAspect(const sf::Vector2u& newSize);

    // control the window mutex and active window
    void inline lockWindow();
    void inline releaseWindow();

    /* member data */

    int argc;
    const char** argv;

    logog::LogFile* logFile;
    logog::Cout* logConsole;
    logog::Formatter* formatter;

    std::unique_ptr<std::thread> renderThread;

    bool isReady = false;
    bool running = false;

    std::string game;
    std::string data_dir;

    // render internally to 720p widescreen
    unsigned int renderWidth = 1280;
    unsigned int renderHeight = 720;

    struct {
        std::string name;
        // this size fits in most screens in windowed mode
        unsigned int width = 1200;
        unsigned int height = 675;
        // don't start fullscreen
        bool fullscreen = false;
        // but do use desktop size when going fullscreen
        bool useDesktopSize = true;
        // obvi, use vsync
        bool vsync = true;
        // controller/keyboard settings
        float deadZone = 15.0;
        float keySpeed = 75.0;
    } config;

    // where everything is drawn
    sf::RenderWindow window;
    // controls the 2D camera, used for rendering internally at a set size
    sf::View view;
    // where we render the game before copying it to the window
    sf::RenderTexture screen;

    // mutexes for the window and sprite list
    std::mutex windowMutex;
    std::mutex spritesMutex;

    // all normal sprites to draw
    std::vector<std::shared_ptr<Sprite>> sprites;

    // the player's ship sprite
    std::shared_ptr<Sprite> player;
    // computer opponent's ship sprite
    std::shared_ptr<Sprite> enemy;
};
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef TARGET_MACROS_H
#define TARGET_MACROS_H

namespace eddic {

#ifdef __GNUG__
    #ifdef __LP64__
        static bool Target64 = true;
    #else
        static bool Target64 = false;
    #endif
    static bool TargetDetermined = true;
#else
    static bool Target64 = false;
    static bool TargetDetermined = false;
#endif

} //end of eddic

#endif
<commit_msg>Put global variables to const<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef TARGET_MACROS_H
#define TARGET_MACROS_H

namespace eddic {

#ifdef __GNUG__
    #ifdef __LP64__
        static const bool Target64 = true;
    #else
        static const bool Target64 = false;
    #endif
    static const bool TargetDetermined = true;
#else
    static const bool Target64 = false;
    static const bool TargetDetermined = false;
#endif

} //end of eddic

#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.

#ifndef KERNEL_OS_HPP
#define KERNEL_OS_HPP

#include <common>
#include <arch.hpp>
#include <kernel/memmap.hpp>
#include <kernel/rtc.hpp>
#include <hertz>
#include <string>
#include <vector>
#include <boot/multiboot.h>

/**
 *  The entrypoint for OS services
 *
 *  @note For device access, see Dev
 */
class OS {
public:
  using print_func  = delegate<void(const char*, size_t)>;
  using Plugin      = delegate<void()>;
  using Span_mods   = gsl::span<multiboot_module_t>;

  /**
   * Returns the OS version string
   **/
  static const std::string& version() noexcept
  { return version_str_; }

  /**
   * Returns the CPU architecture for which the OS was built
   **/
  static const std::string& arch() noexcept
  { return arch_str_; }

  /**
   *  Returns the commandline arguments provided,
   *  if any, to the VM passed on by multiboot or
   *  other mechanisms. The first argument is always
   *  the binary name.
  **/
  static const char* cmdline_args() noexcept;

  /** Clock cycles since boot. */
  static uint64_t cycles_since_boot() {
    return __arch_cpu_cycles();
  }
  /** micro seconds since boot */
  static int64_t micros_since_boot() noexcept;

  /** Timestamp for when OS was booted */
  static RTC::timestamp_t boot_timestamp();

  /** Uptime in whole seconds. */
  static RTC::timestamp_t uptime();

  /** Time spent sleeping (halt) in cycles */
  static uint64_t cycles_asleep() noexcept;

  /** Time spent sleeping (halt) in micros */
  static uint64_t micros_asleep() noexcept;

  static MHz cpu_freq() noexcept
  { return cpu_mhz_; }

  /**
   * Reboot operating system
   *
   **/
  static void reboot();

  /**
   * Shutdown operating system
   *
   **/
  static void shutdown();

  /**
   *  Halt until next interrupt.
   *
   *  @Warning If there is no regular timer interrupt (i.e. from PIT / APIC)
   *  we'll stay asleep.
   */
  static void halt();

  /**
   *  Returns true when the OS will still be running, and not shutting down.
   */
  static bool is_running() noexcept {
    return power_;
  }

  /**
   *  Returns true when the OS has passed the boot sequence, and
   *  is at least processing plugins and about to call Service::start
   */
  static bool is_booted() noexcept {
    return boot_sequence_passed_;
  }

  static bool block_drivers_ready() noexcept {
    return m_block_drivers_ready;
  }

  /**
   *  Returns true when the OS is currently panicking
   */
  static bool is_panicking() noexcept;

  /**
   * Sometimes the OS just has a bad day and crashes
   * The on_panic handler will be called directly after a panic,
   * or any condition which will deliberately cause the OS to become
   * unresponsive. After the handler is called, the OS goes to sleep.
   * This handler can thus be used to, for example, automatically
   * have the OS restart on any crash.
  **/
  typedef void (*on_panic_func) (const char*);
  static void on_panic(on_panic_func);

  /**
   *  Write data to standard out callbacks
   */
  static void print(const char* ptr, const size_t len);

  /**
   *  Add handler for standard output.
   */
  static void add_stdout(print_func func);

  /**
   *  The default output method preferred by each platform
   *  Directly writes the string to its output mechanism
   **/
  static void default_stdout(const char*, size_t);

  /** Memory page helpers */
  static constexpr uint32_t page_size() noexcept {
    return 4096;
  }
  static constexpr uint32_t addr_to_page(uintptr_t addr) noexcept {
    return addr >> PAGE_SHIFT;
  }
  static constexpr uintptr_t page_to_addr(uint32_t page) noexcept {
    return page << PAGE_SHIFT;
  }

  /** Total used dynamic memory, in bytes */
  static uintptr_t heap_usage() noexcept;

  /** Attempt to trim the heap end, reducing the size */
  static void heap_trim() noexcept;

  /** First address of the heap **/
  static uintptr_t heap_begin() noexcept;

  /** Last used address of the heap **/
  static uintptr_t heap_end() noexcept;

  /** Resize the heap if possible. Return (potentially) new size. **/
  static uintptr_t resize_heap(size_t size);

  /** The maximum last address of the dynamic memory area (heap) */
  static uintptr_t heap_max() noexcept;

  /** The end of usable memory **/
  static uintptr_t memory_end() noexcept {
    return memory_end_;
  }

  /**
   *  Returns true when the current OS comes from a live update,
   *  as opposed to booting from either a rollback or a normal boot
   */
  static bool is_live_updated() noexcept;

  /** Returns the automatic location set aside for storing system and program state **/
  static void* liveupdate_storage_area() noexcept;

  /**
   * A map of memory ranges. The key is the starting address in numeric form.
   * @note : the idea is to avoid raw pointers whenever possible
  **/
  static Memory_map& memory_map() {
    static  Memory_map memmap {};
    return memmap;
  }

  /** Get "kernel modules", provided by multiboot */
  static Span_mods modules();

  /**
   * Register a custom initialization function. The provided delegate is
   * guaranteed to be called after global constructors and device initialization
   * and before Service::start, provided that this funciton was called by a
   * global constructor.
   * @param delg : A delegate to be called
   * @param name : A human readable identifier
  **/
  static void register_plugin(Plugin delg, const char* name);

  /**
   * Block for a while, e.g. until the next round in the event loop
   **/
  static void block();

  /** The main event loop. Check interrupts, timers etc., and do callbacks. */
  static void event_loop();

  /** Initialize platform, devices etc. */
  static void start(uint32_t boot_magic, uint32_t boot_addr);

  static void start(char *cmdline, uintptr_t mem_size);

  /** Initialize common subsystems, call Service::start */
  static void post_start();

private:
  /** Process multiboot info. Called by 'start' if multibooted **/
  static void multiboot(uint32_t boot_addr);

  static multiboot_info_t* bootinfo();

  /** Boot with no multiboot params */
  static void legacy_boot();

  /** Resume stuff from a soft reset **/
  static bool is_softreset_magic(uint32_t value);
  static void resume_softreset(intptr_t boot_addr);

  static constexpr int PAGE_SHIFT = 12;
  static bool power_;
  static bool boot_sequence_passed_;
  static bool m_is_live_updated;
  static bool m_block_drivers_ready;
  static MHz cpu_mhz_;

  static RTC::timestamp_t booted_at_;
  static uintptr_t liveupdate_loc_;
  static std::string version_str_;
  static std::string arch_str_;
  static uintptr_t memory_end_;
  static uintptr_t heap_max_;
  static const uintptr_t elf_binary_size_;
  static const char* cmdline;

  // Prohibit copy and move operations
  OS(OS&)  = delete;
  OS(OS&&) = delete;
  OS& operator=(OS&)  = delete;
  OS& operator=(OS&&)  = delete;
  ~OS() = delete;
  // Prohibit construction
  OS() = delete;

  friend void __platform_init();
}; //< OS

inline OS::Span_mods OS::modules()
{
  auto* bootinfo_ = bootinfo();
  if (bootinfo_ and bootinfo_->flags & MULTIBOOT_INFO_MODS and bootinfo_->mods_count) {

    Expects(bootinfo_->mods_count < std::numeric_limits<int>::max());

    return Span_mods{
      reinterpret_cast<multiboot_module_t*>(bootinfo_->mods_addr),
        static_cast<int>(bootinfo_->mods_count) };
  }
  return nullptr;
}

#endif //< KERNEL_OS_HPP
<commit_msg>os: Implement OS::is_live_updated<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.

#ifndef KERNEL_OS_HPP
#define KERNEL_OS_HPP

#include <common>
#include <arch.hpp>
#include <kernel/memmap.hpp>
#include <kernel/rtc.hpp>
#include <hertz>
#include <string>
#include <vector>
#include <boot/multiboot.h>

/**
 *  The entrypoint for OS services
 *
 *  @note For device access, see Dev
 */
class OS {
public:
  using print_func  = delegate<void(const char*, size_t)>;
  using Plugin      = delegate<void()>;
  using Span_mods   = gsl::span<multiboot_module_t>;

  /**
   * Returns the OS version string
   **/
  static const std::string& version() noexcept
  { return version_str_; }

  /**
   * Returns the CPU architecture for which the OS was built
   **/
  static const std::string& arch() noexcept
  { return arch_str_; }

  /**
   *  Returns the commandline arguments provided,
   *  if any, to the VM passed on by multiboot or
   *  other mechanisms. The first argument is always
   *  the binary name.
  **/
  static const char* cmdline_args() noexcept;

  /** Clock cycles since boot. */
  static uint64_t cycles_since_boot() {
    return __arch_cpu_cycles();
  }
  /** micro seconds since boot */
  static int64_t micros_since_boot() noexcept;

  /** Timestamp for when OS was booted */
  static RTC::timestamp_t boot_timestamp();

  /** Uptime in whole seconds. */
  static RTC::timestamp_t uptime();

  /** Time spent sleeping (halt) in cycles */
  static uint64_t cycles_asleep() noexcept;

  /** Time spent sleeping (halt) in micros */
  static uint64_t micros_asleep() noexcept;

  static MHz cpu_freq() noexcept
  { return cpu_mhz_; }

  /**
   * Reboot operating system
   *
   **/
  static void reboot();

  /**
   * Shutdown operating system
   *
   **/
  static void shutdown();

  /**
   *  Halt until next interrupt.
   *
   *  @Warning If there is no regular timer interrupt (i.e. from PIT / APIC)
   *  we'll stay asleep.
   */
  static void halt();

  /**
   *  Returns true when the OS will still be running, and not shutting down.
   */
  static bool is_running() noexcept {
    return power_;
  }

  /**
   *  Returns true when the OS has passed the boot sequence, and
   *  is at least processing plugins and about to call Service::start
   */
  static bool is_booted() noexcept {
    return boot_sequence_passed_;
  }

  static bool block_drivers_ready() noexcept {
    return m_block_drivers_ready;
  }

  /**
   *  Returns true when the OS is currently panicking
   */
  static bool is_panicking() noexcept;

  /**
   * Sometimes the OS just has a bad day and crashes
   * The on_panic handler will be called directly after a panic,
   * or any condition which will deliberately cause the OS to become
   * unresponsive. After the handler is called, the OS goes to sleep.
   * This handler can thus be used to, for example, automatically
   * have the OS restart on any crash.
  **/
  typedef void (*on_panic_func) (const char*);
  static void on_panic(on_panic_func);

  /**
   *  Write data to standard out callbacks
   */
  static void print(const char* ptr, const size_t len);

  /**
   *  Add handler for standard output.
   */
  static void add_stdout(print_func func);

  /**
   *  The default output method preferred by each platform
   *  Directly writes the string to its output mechanism
   **/
  static void default_stdout(const char*, size_t);

  /** Memory page helpers */
  static constexpr uint32_t page_size() noexcept {
    return 4096;
  }
  static constexpr uint32_t addr_to_page(uintptr_t addr) noexcept {
    return addr >> PAGE_SHIFT;
  }
  static constexpr uintptr_t page_to_addr(uint32_t page) noexcept {
    return page << PAGE_SHIFT;
  }

  /** Total used dynamic memory, in bytes */
  static uintptr_t heap_usage() noexcept;

  /** Attempt to trim the heap end, reducing the size */
  static void heap_trim() noexcept;

  /** First address of the heap **/
  static uintptr_t heap_begin() noexcept;

  /** Last used address of the heap **/
  static uintptr_t heap_end() noexcept;

  /** Resize the heap if possible. Return (potentially) new size. **/
  static uintptr_t resize_heap(size_t size);

  /** The maximum last address of the dynamic memory area (heap) */
  static uintptr_t heap_max() noexcept;

  /** The end of usable memory **/
  static uintptr_t memory_end() noexcept {
    return memory_end_;
  }

  /**
   *  Returns true when the current OS comes from a live update,
   *  as opposed to booting from either a rollback or a normal boot
   */
  static bool is_live_updated() noexcept;

  /** Returns the automatic location set aside for storing system and program state **/
  static void* liveupdate_storage_area() noexcept;

  /**
   * A map of memory ranges. The key is the starting address in numeric form.
   * @note : the idea is to avoid raw pointers whenever possible
  **/
  static Memory_map& memory_map() {
    static  Memory_map memmap {};
    return memmap;
  }

  /** Get "kernel modules", provided by multiboot */
  static Span_mods modules();

  /**
   * Register a custom initialization function. The provided delegate is
   * guaranteed to be called after global constructors and device initialization
   * and before Service::start, provided that this funciton was called by a
   * global constructor.
   * @param delg : A delegate to be called
   * @param name : A human readable identifier
  **/
  static void register_plugin(Plugin delg, const char* name);

  /**
   * Block for a while, e.g. until the next round in the event loop
   **/
  static void block();

  /** The main event loop. Check interrupts, timers etc., and do callbacks. */
  static void event_loop();

  /** Initialize platform, devices etc. */
  static void start(uint32_t boot_magic, uint32_t boot_addr);

  static void start(char *cmdline, uintptr_t mem_size);

  /** Initialize common subsystems, call Service::start */
  static void post_start();

private:
  /** Process multiboot info. Called by 'start' if multibooted **/
  static void multiboot(uint32_t boot_addr);

  static multiboot_info_t* bootinfo();

  /** Boot with no multiboot params */
  static void legacy_boot();

  /** Resume stuff from a soft reset **/
  static bool is_softreset_magic(uint32_t value);
  static void resume_softreset(intptr_t boot_addr);

  static constexpr int PAGE_SHIFT = 12;
  static bool power_;
  static bool boot_sequence_passed_;
  static bool m_is_live_updated;
  static bool m_block_drivers_ready;
  static MHz cpu_mhz_;

  static RTC::timestamp_t booted_at_;
  static uintptr_t liveupdate_loc_;
  static std::string version_str_;
  static std::string arch_str_;
  static uintptr_t memory_end_;
  static uintptr_t heap_max_;
  static const uintptr_t elf_binary_size_;
  static const char* cmdline;

  // Prohibit copy and move operations
  OS(OS&)  = delete;
  OS(OS&&) = delete;
  OS& operator=(OS&)  = delete;
  OS& operator=(OS&&)  = delete;
  ~OS() = delete;
  // Prohibit construction
  OS() = delete;

  friend void __platform_init();
}; //< OS

inline bool OS::is_live_updated() noexcept {
  return OS::m_is_live_updated;
}

inline OS::Span_mods OS::modules()
{
  auto* bootinfo_ = bootinfo();
  if (bootinfo_ and bootinfo_->flags & MULTIBOOT_INFO_MODS and bootinfo_->mods_count) {

    Expects(bootinfo_->mods_count < std::numeric_limits<int>::max());

    return Span_mods{
      reinterpret_cast<multiboot_module_t*>(bootinfo_->mods_addr),
        static_cast<int>(bootinfo_->mods_count) };
  }
  return nullptr;
}

#endif //< KERNEL_OS_HPP
<|endoftext|>


<commit_before>#include <vector>
#include <iostream>

using namespace std;

/* DIS DA COMPILA
   mainly an assortment of tools for the levels (or levels) to use
   has all the capabilities, but none of the drive
   levels take over and make use of it */

class Level{
public:
  vector<char> spec;
  vector<int (*)()> routes;
  Level* parent;

  Level(vector<char> s, vector<int (*)()> r, Level* p){
    if(s.size()==r.size()){
      spec = s;
      routes = r;
      parent = p;
    }
    else
      throw "Special character and routine lists not of equal length!";
  }

  int isSpec(char c){
    //checks if c is a special char
    //returns its index in spec[] if so, -1 otherwise

    int mid, low = 0, high = spec.size()-1;

    int ans;

    while (high > low){
      mid = (high+low)/2;

      if (c <= spec[low])
	return c == spec[low] ? low : -1;

      else if (c >= spec[high])
	return c == spec[high] ? high : -1;

      else {
	char diff = c - spec[mid];
	if (diff < 0) high = mid-1;
	else if (diff > 0) low = mid+1;
	else return mid;
      }
    }
    return -1;
  }

  int checkSpec(char c){
    int x = isSpec(c);
    if (x != -1)
      (*routes[x])();
    return x;
  }
};

#define MAXWL 100 //max word length: 100

Level* clevel;
char wuff[MAXWL]; //word buffer
int wptr = 0; //pointer to current position in word

int add(char c){
  //returns 1 for a sucessful add, 0 if the buffer is full  or some other fail
  if (wptr < MAXWL){
    wuff[wptr++] = c;
    return 1;
  } else return 0;
}

void bead(char c){
  if (! clevel->checkSpec(c))
    add(c);
}

vector<char> cV(const char* c){
  vector<char> cv;

  while (*c != '\0'){
    cv.push_back(*(c++)); //would this work w/o parens?
  }
  return cv;
}

#include "levels.hpp"

int main(int argc, char *argv[]){
  try
    {
      clevel = new Root;
    } catch (const char* s) {
    cout << s << "\n";
    }
  return 0;
}

  //this is it, a fresh start

  //  int bead(char c)

  // sigh, ok major decision here. need to not rush, but come to a final conclusion
  //   so this wont be a constant nagging question
  //   do i want each level to simply have a giant function? so easy to do...
  // 	 might not be as fast, but gets rid of ridiculous libraries of functions
  // 	   is more free in the sense that the levels have no requirements besides have that one function that takes a char

  // 	   or is it better to have the structure of words and special characters?
  // 	   its a great way to have a very simple unobtrusive level of comprehension
  // 	   all code will have variable names which will have no inherent meaning to the compiler
  // 	   this stuff, if nothing else, is the words, and all else special characters [this is the way to do it, winner]

  // so, nothing should have to be done in terms of a 'normal function' (for handling non-special characters)
  //   it should be standard, regardless of level, because it is simply making a word, and finding spec chars should be standardized,
  //   so it is easy to ooptimize (without changing a bunch of code)

  //   so yeah, as we know, a level needs a list of special chars and a list of equal length containing functions defining behavior when a special character is called or hit or whatever. [ok, sidenote: there should be a variable in the compiler that is the current character being dealt with. this way spec char funks can refernce this char and be the same funk while storing character specific info. (whew)]

  //   the end result of this level of parsing is going to be very simple it is words and directions to other levels
  //   pop + soda -> drank (simply a chain of words)
  //   ( po + p ) + soda -> drank   (enter sublevel (words) exit sublevel) words

  //   it can be expressed as a list of objects that are either a word or a direction to another level
  //   the next (separate) level of operation is the compiler starting at root level as current level, switcching whenever it comes upon those pobjects, and feeding th ewords from the other objects into whatever the current level is

  //   it seems like that level will require functors or for each level to be a subclass of level (making them subclasses would be better)
<commit_msg>all the goodies<commit_after><|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef CPM_IO_HPP
#define CPM_IO_HPP

#include <unistd.h>
#include <algorithm>
#include <iomanip>

#include <sys/stat.h>

namespace cpm {

inline std::size_t max_path_length(){
    auto path_max = pathconf(".", _PC_PATH_MAX);
    if (path_max == -1){
        path_max = 1024;
    } else if (path_max > 10240){
        path_max = 10240;
    }
    return path_max;
}

inline std::string get_cwd(){
    auto path_max = max_path_length();

    char* buf = static_cast<char*>(malloc(sizeof(char) * path_max));
    if(!buf){
        return "";
    }

    char* ptr = getcwd(buf, path_max);
    if (!ptr) {
        return "";
    }

    std::string cwd = buf;

    free(buf);

    return cwd;
}

inline std::string make_absolute(const std::string& folder){
    auto path_max = max_path_length();

    char* buf = static_cast<char*>(malloc(sizeof(char) * path_max));
    if(!buf){
        return folder;
    }

    char* res = realpath(folder.c_str(), buf);

    if(!res){
        return folder;
    }

    std::string abs = buf;

    free(buf);

    return abs;
}

inline std::string get_free_file(const std::string& base_folder){
    std::size_t result_name = 0;
    std::string result_folder;

    struct stat buffer;
    do {
        ++result_name;
        result_folder = base_folder + std::to_string(result_name) + ".cpm";
    } while(stat(result_folder.c_str(), &buffer) == 0);

    return std::to_string(result_name);
}

inline bool folder_exists(const std::string& folder){
    struct stat buffer;
    if (stat(folder.c_str(), &buffer) == 0 && S_ISDIR(buffer.st_mode)){
        return true;
    } else {
        return false;
    }
}

inline std::string url_encode(const std::string& value) {
    std::ostringstream escaped;
    escaped.fill('0');
    escaped << std::hex;

    for (auto i = value.begin(), n = value.end(); i != n; ++i) {
        auto c = *i;

        // Keep alphanumeric and other accepted characters intact
        if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
            escaped << c;
            continue;
        }

        // Any other characters are percent-encoded
        escaped << '%' << std::setw(2) << int((unsigned char) c);
    }

    return escaped.str();
}

inline std::string filify(std::string name){
    std::string n{std::move(name)};

    //Replace all spaces
    std::replace(n.begin(), n.end(), ' ', '_');

    //Append extension
    n += ".html";

    return n;
}

inline std::string filify(std::string compiler, std::string configuration){
    std::string n1{std::move(compiler)};
    std::string n2{std::move(configuration)};

    auto n = n1 + "-" + n2;

    return filify(n);
}

inline std::string filify(std::string compiler, std::string configuration, std::string bench){
    std::string n1{std::move(compiler)};
    std::string n2{std::move(configuration)};
    std::string n3{std::move(bench)};

    auto n = n1 + "-" + n2 + "-" + n3;

    return filify(n);
}

} //end of namespace cpm

#endif //CPM_IO_HPP
<commit_msg>Fix slashes<commit_after>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef CPM_IO_HPP
#define CPM_IO_HPP

#include <unistd.h>
#include <algorithm>
#include <iomanip>

#include <sys/stat.h>

namespace cpm {

inline std::size_t max_path_length(){
    auto path_max = pathconf(".", _PC_PATH_MAX);
    if (path_max == -1){
        path_max = 1024;
    } else if (path_max > 10240){
        path_max = 10240;
    }
    return path_max;
}

inline std::string get_cwd(){
    auto path_max = max_path_length();

    char* buf = static_cast<char*>(malloc(sizeof(char) * path_max));
    if(!buf){
        return "";
    }

    char* ptr = getcwd(buf, path_max);
    if (!ptr) {
        return "";
    }

    std::string cwd = buf;

    free(buf);

    return cwd;
}

inline std::string make_absolute(const std::string& folder){
    auto path_max = max_path_length();

    char* buf = static_cast<char*>(malloc(sizeof(char) * path_max));
    if(!buf){
        return folder;
    }

    char* res = realpath(folder.c_str(), buf);

    if(!res){
        return folder;
    }

    std::string abs = buf;

    free(buf);

    return abs;
}

inline std::string get_free_file(const std::string& base_folder){
    std::size_t result_name = 0;
    std::string result_folder;

    struct stat buffer;
    do {
        ++result_name;
        result_folder = base_folder + std::to_string(result_name) + ".cpm";
    } while(stat(result_folder.c_str(), &buffer) == 0);

    return std::to_string(result_name);
}

inline bool folder_exists(const std::string& folder){
    struct stat buffer;
    if (stat(folder.c_str(), &buffer) == 0 && S_ISDIR(buffer.st_mode)){
        return true;
    } else {
        return false;
    }
}

inline std::string url_encode(const std::string& value) {
    std::ostringstream escaped;
    escaped.fill('0');
    escaped << std::hex;

    for (auto i = value.begin(), n = value.end(); i != n; ++i) {
        auto c = *i;

        // Keep alphanumeric and other accepted characters intact
        if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
            escaped << c;
            continue;
        }

        // Any other characters are percent-encoded
        escaped << '%' << std::setw(2) << int((unsigned char) c);
    }

    return escaped.str();
}

inline std::string filify(std::string name){
    std::string n{std::move(name)};

    //Replace all spaces
    std::replace(n.begin(), n.end(), ' ', '_');

    //Replace all forward slashes
    std::replace(n.begin(), n.end(), '/', '|');

    //Append extension
    n += ".html";

    return n;
}

inline std::string filify(std::string compiler, std::string configuration){
    std::string n1{std::move(compiler)};
    std::string n2{std::move(configuration)};

    auto n = n1 + "-" + n2;

    return filify(n);
}

inline std::string filify(std::string compiler, std::string configuration, std::string bench){
    std::string n1{std::move(compiler)};
    std::string n2{std::move(configuration)};
    std::string n3{std::move(bench)};

    auto n = n1 + "-" + n2 + "-" + n3;

    return filify(n);
}

} //end of namespace cpm

#endif //CPM_IO_HPP
<|endoftext|>


<commit_before>#ifndef ERRORS_H_INCLUDED
#define ERRORS_H_INCLUDED

#include <iostream>
#include <SDL.h>

/* Log a SDL error */
static inline void logSDLError(const std::string &msg,
                               std::ostream &os = std::cerr)
{
    os << "[SDL ] " << msg << " error: " << SDL_GetError() << std::endl;
}

/* Log a normal message */
static inline void log(const std::string &msg, std::ostream &os = std::cout)
{
    os << "[    ] " << msg << std::endl;
}

#endif /* ERRORS_H_INCLUDED */
<commit_msg>Error: adding raw error log<commit_after>#ifndef ERRORS_H_INCLUDED
#define ERRORS_H_INCLUDED

#include <iostream>
#include <SDL.h>

/* Log a SDL error */
static inline void logSDLError(const std::string &msg,
                               std::ostream &os = std::cerr)
{
    os << "[SDL ] " << msg << " error: " << SDL_GetError() << std::endl;
}

/* Log a normal message */
static inline void log(const std::string &msg, std::ostream &os = std::cout)
{
    os << "[    ] " << msg << std::endl;
}

/* Log a raw error */
static inline void logError(const std::string &msg,
                            std::ostream &os = std::cerr)
{
    os << "[XXXX] " << msg << std::endl;
}

#endif /* ERRORS_H_INCLUDED */
<|endoftext|>


<commit_before>/* json11
 *
 * json11 is a tiny JSON library for C++11, providing JSON parsing and
 * serialization.
 *
 * The core object provided by the library is json11::Json. A Json object
 * represents any JSON value: null, bool, number (int or double), string
 * (std::string), array (std::vector), or object (std::map).
 *
 * Json objects act like values: they can be assigned, copied, moved, compared
 * for equality or order, etc. There are also helper methods Json::dump, to
 * serialize a Json to a string, and Json::parse (static) to parse a std::string
 * as a Json object.
 *
 * Internally, the various types of Json object are represented by the JsonValue
 * class hierarchy.
 *
 * A note on numbers - JSON specifies the syntax of number formatting but not
 * its semantics, so some JSON implementations distinguish between integers and
 * floating-point numbers, while some don't. In json11, we choose the latter.
 * Because some JSON implementations (namely Javascript itself) treat all
 * numbers as the same type, distinguishing the two leads to JSON that will be
 * *silently* changed by a round-trip through those implementations. Dangerous!
 * To avoid that risk, json11 stores all numbers as double internally, but also
 * provides integer helpers.
 *
 * Fortunately, double-precision IEEE754 ('double') can precisely store any
 * integer in the range +/-2^53, which includes every 'int' on most systems.
 * (Timestamps often use int64 or long long to avoid the Y2038K problem; a
 * double storing microseconds since some epoch will be exact for +/- 275
 * years.)
 */

/* Copyright (c) 2013 Dropbox, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#pragma once

#include <initializer_list>
#include <map>
#include <memory>
#include <string>
#include <vector>

#ifdef _MSC_VER
#if _MSC_VER <= 1800  // VS 2013
#ifndef noexcept
#define noexcept throw()
#endif

#ifndef snprintf
#define snprintf _snprintf_s
#endif
#endif
#endif

namespace json11 {

enum JsonParse { STANDARD, COMMENTS };

class JsonValue;

class Json final {
 public:
  // Types
  enum Type { NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT };

  // Array and object typedefs
  typedef std::vector<Json> array;
  typedef std::map<std::string, Json> object_;

  // Constructors for the various types of JSON value.
  Json() noexcept;                 // NUL
  Json(std::nullptr_t) noexcept;   // NUL
  Json(double value);              // NUMBER
  Json(int value);                 // NUMBER
  Json(bool value);                // BOOL
  Json(const std::string &value);  // STRING
  Json(std::string &&value);       // STRING
  Json(const char *value);         // STRING
  Json(const array &values);       // ARRAY
  Json(array &&values);            // ARRAY
  Json(const object_ &values);     // OBJECT
  Json(object_ &&values);          // OBJECT

  // Implicit constructor: anything with a to_json() function.
  template <class T, class = decltype(&T::to_json)>
  Json(const T &t) : Json(t.to_json()) {}

  // Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
  template <
      class M,
      typename std::enable_if<
          std::is_constructible<std::string, typename M::key_type>::value &&
              std::is_constructible<Json, typename M::mapped_type>::value,
          int>::type = 0>
  Json(const M &m) : Json(object_(m.begin(), m.end())) {}

  // Implicit constructor: vector-like objects (std::list, std::vector,
  // std::set, etc)
  template <class V,
            typename std::enable_if<
                std::is_constructible<Json, typename V::value_type>::value,
                int>::type = 0>
  Json(const V &v) : Json(array(v.begin(), v.end())) {}

  // This prevents Json(some_pointer) from accidentally producing a bool. Use
  // Json(bool(some_pointer)) if that behavior is desired.
  Json(void *) = delete;

  // Accessors
  Type type() const;

  bool is_null() const { return type() == NUL; }
  bool is_number() const { return type() == NUMBER; }
  bool is_bool() const { return type() == BOOL; }
  bool is_string() const { return type() == STRING; }
  bool is_array() const { return type() == ARRAY; }
  bool is_object() const { return type() == OBJECT; }

  // Return the enclosed value if this is a number, 0 otherwise. Note that
  // json11 does not distinguish between integer and non-integer numbers -
  // number_value() and int_value() can both be applied to a NUMBER-typed
  // object.
  double number_value() const;
  int int_value() const;

  // Return the enclosed value if this is a boolean, false otherwise.
  bool bool_value() const;
  // Return the enclosed string if this is a string, "" otherwise.
  const std::string &string_value() const;
  // Return the enclosed std::vector if this is an array, or an empty vector
  // otherwise.
  const array &array_items() const;
  // Return the enclosed std::map if this is an object, or an empty map
  // otherwise.
  const object_ &object_items() const;

  // Return a reference to arr[i] if this is an array, Json() otherwise.
  const Json &operator[](size_t i) const;
  // Return a reference to obj[key] if this is an object, Json() otherwise.
  const Json &operator[](const std::string &key) const;

  // Serialize.
  void dump(std::string &out) const;
  std::string dump() const {
    std::string out;
    dump(out);
    return out;
  }

  // Parse. If parse fails, return Json() and assign an error message to err.
  static Json parse(const std::string &in, std::string &err,
                    JsonParse strategy = JsonParse::STANDARD);
  static Json parse(const char *in, std::string &err,
                    JsonParse strategy = JsonParse::STANDARD) {
    if (in) {
      return parse(std::string(in), err, strategy);
    } else {
      err = "null input";
      return nullptr;
    }
  }
  // Parse multiple objects, concatenated or separated by whitespace
  static std::vector<Json> parse_multi(
      const std::string &in, std::string::size_type &parser_stop_pos,
      std::string &err, JsonParse strategy = JsonParse::STANDARD);

  static inline std::vector<Json> parse_multi(
      const std::string &in, std::string &err,
      JsonParse strategy = JsonParse::STANDARD) {
    std::string::size_type parser_stop_pos;
    return parse_multi(in, parser_stop_pos, err, strategy);
  }

  bool operator==(const Json &rhs) const;
  bool operator<(const Json &rhs) const;
  bool operator!=(const Json &rhs) const { return !(*this == rhs); }
  bool operator<=(const Json &rhs) const { return !(rhs < *this); }
  bool operator>(const Json &rhs) const { return (rhs < *this); }
  bool operator>=(const Json &rhs) const { return !(*this < rhs); }

  /* has_shape(types, err)
   *
   * Return true if this is a JSON object and, for each item in types, has a
   * field of the given type. If not, return false and set err to a descriptive
   * message.
   */
  typedef std::initializer_list<std::pair<std::string, Type>> shape;
  bool has_shape(const shape &types, std::string &err) const;

 private:
  std::shared_ptr<JsonValue> m_ptr;
};

// Internal class hierarchy - JsonValue objects are not exposed to users of this
// API.
class JsonValue {
 protected:
  friend class Json;
  friend class JsonInt;
  friend class JsonDouble;
  virtual Json::Type type() const = 0;
  virtual bool equals(const JsonValue *other) const = 0;
  virtual bool less(const JsonValue *other) const = 0;
  virtual void dump(std::string &out) const = 0;
  virtual double number_value() const;
  virtual int int_value() const;
  virtual bool bool_value() const;
  virtual const std::string &string_value() const;
  virtual const Json::array &array_items() const;
  virtual const Json &operator[](size_t i) const;
  virtual const Json::object_ &object_items() const;
  virtual const Json &operator[](const std::string &key) const;
  virtual ~JsonValue() {}
};

}  // namespace json11
<commit_msg>Change Json map/vector conversions to invoke begin() directly<commit_after>/* json11
 *
 * json11 is a tiny JSON library for C++11, providing JSON parsing and
 * serialization.
 *
 * The core object provided by the library is json11::Json. A Json object
 * represents any JSON value: null, bool, number (int or double), string
 * (std::string), array (std::vector), or object (std::map).
 *
 * Json objects act like values: they can be assigned, copied, moved, compared
 * for equality or order, etc. There are also helper methods Json::dump, to
 * serialize a Json to a string, and Json::parse (static) to parse a std::string
 * as a Json object.
 *
 * Internally, the various types of Json object are represented by the JsonValue
 * class hierarchy.
 *
 * A note on numbers - JSON specifies the syntax of number formatting but not
 * its semantics, so some JSON implementations distinguish between integers and
 * floating-point numbers, while some don't. In json11, we choose the latter.
 * Because some JSON implementations (namely Javascript itself) treat all
 * numbers as the same type, distinguishing the two leads to JSON that will be
 * *silently* changed by a round-trip through those implementations. Dangerous!
 * To avoid that risk, json11 stores all numbers as double internally, but also
 * provides integer helpers.
 *
 * Fortunately, double-precision IEEE754 ('double') can precisely store any
 * integer in the range +/-2^53, which includes every 'int' on most systems.
 * (Timestamps often use int64 or long long to avoid the Y2038K problem; a
 * double storing microseconds since some epoch will be exact for +/- 275
 * years.)
 */

/* Copyright (c) 2013 Dropbox, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#pragma once

#include <initializer_list>
#include <map>
#include <memory>
#include <string>
#include <vector>

#ifdef _MSC_VER
#if _MSC_VER <= 1800  // VS 2013
#ifndef noexcept
#define noexcept throw()
#endif

#ifndef snprintf
#define snprintf _snprintf_s
#endif
#endif
#endif

namespace json11 {

enum JsonParse { STANDARD, COMMENTS };

class JsonValue;

class Json final {
 public:
  // Types
  enum Type { NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT };

  // Array and object typedefs
  typedef std::vector<Json> array;
  typedef std::map<std::string, Json> object_;

  // Constructors for the various types of JSON value.
  Json() noexcept;                 // NUL
  Json(std::nullptr_t) noexcept;   // NUL
  Json(double value);              // NUMBER
  Json(int value);                 // NUMBER
  Json(bool value);                // BOOL
  Json(const std::string &value);  // STRING
  Json(std::string &&value);       // STRING
  Json(const char *value);         // STRING
  Json(const array &values);       // ARRAY
  Json(array &&values);            // ARRAY
  Json(const object_ &values);     // OBJECT
  Json(object_ &&values);          // OBJECT

  // Implicit constructor: anything with a to_json() function.
  template <class T, class = decltype(&T::to_json)>
  Json(const T &t) : Json(t.to_json()) {}

  // Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
  template <
      class M,
      typename std::enable_if<
          std::is_constructible<
              std::string, decltype(std::declval<M>().begin()->first)>::value &&
              std::is_constructible<
                  Json, decltype(std::declval<M>().begin()->second)>::value,
          int>::type = 0>
  Json(const M &m) : Json(object_(m.begin(), m.end())) {}

  // Implicit constructor: vector-like objects (std::list, std::vector,
  // std::set, etc)
  template <class V, typename std::enable_if<
                         std::is_constructible<
                             Json, decltype(*std::declval<V>().begin())>::value,
                         int>::type = 0>
  Json(const V &v) : Json(array(v.begin(), v.end())) {}

  // This prevents Json(some_pointer) from accidentally producing a bool. Use
  // Json(bool(some_pointer)) if that behavior is desired.
  Json(void *) = delete;

  // Accessors
  Type type() const;

  bool is_null() const { return type() == NUL; }
  bool is_number() const { return type() == NUMBER; }
  bool is_bool() const { return type() == BOOL; }
  bool is_string() const { return type() == STRING; }
  bool is_array() const { return type() == ARRAY; }
  bool is_object() const { return type() == OBJECT; }

  // Return the enclosed value if this is a number, 0 otherwise. Note that
  // json11 does not distinguish between integer and non-integer numbers -
  // number_value() and int_value() can both be applied to a NUMBER-typed
  // object.
  double number_value() const;
  int int_value() const;

  // Return the enclosed value if this is a boolean, false otherwise.
  bool bool_value() const;
  // Return the enclosed string if this is a string, "" otherwise.
  const std::string &string_value() const;
  // Return the enclosed std::vector if this is an array, or an empty vector
  // otherwise.
  const array &array_items() const;
  // Return the enclosed std::map if this is an object, or an empty map
  // otherwise.
  const object_ &object_items() const;

  // Return a reference to arr[i] if this is an array, Json() otherwise.
  const Json &operator[](size_t i) const;
  // Return a reference to obj[key] if this is an object, Json() otherwise.
  const Json &operator[](const std::string &key) const;

  // Serialize.
  void dump(std::string &out) const;
  std::string dump() const {
    std::string out;
    dump(out);
    return out;
  }

  // Parse. If parse fails, return Json() and assign an error message to err.
  static Json parse(const std::string &in, std::string &err,
                    JsonParse strategy = JsonParse::STANDARD);
  static Json parse(const char *in, std::string &err,
                    JsonParse strategy = JsonParse::STANDARD) {
    if (in) {
      return parse(std::string(in), err, strategy);
    } else {
      err = "null input";
      return nullptr;
    }
  }
  // Parse multiple objects, concatenated or separated by whitespace
  static std::vector<Json> parse_multi(
      const std::string &in, std::string::size_type &parser_stop_pos,
      std::string &err, JsonParse strategy = JsonParse::STANDARD);

  static inline std::vector<Json> parse_multi(
      const std::string &in, std::string &err,
      JsonParse strategy = JsonParse::STANDARD) {
    std::string::size_type parser_stop_pos;
    return parse_multi(in, parser_stop_pos, err, strategy);
  }

  bool operator==(const Json &rhs) const;
  bool operator<(const Json &rhs) const;
  bool operator!=(const Json &rhs) const { return !(*this == rhs); }
  bool operator<=(const Json &rhs) const { return !(rhs < *this); }
  bool operator>(const Json &rhs) const { return (rhs < *this); }
  bool operator>=(const Json &rhs) const { return !(*this < rhs); }

  /* has_shape(types, err)
   *
   * Return true if this is a JSON object and, for each item in types, has a
   * field of the given type. If not, return false and set err to a descriptive
   * message.
   */
  typedef std::initializer_list<std::pair<std::string, Type>> shape;
  bool has_shape(const shape &types, std::string &err) const;

 private:
  std::shared_ptr<JsonValue> m_ptr;
};

// Internal class hierarchy - JsonValue objects are not exposed to users of this
// API.
class JsonValue {
 protected:
  friend class Json;
  friend class JsonInt;
  friend class JsonDouble;
  virtual Json::Type type() const = 0;
  virtual bool equals(const JsonValue *other) const = 0;
  virtual bool less(const JsonValue *other) const = 0;
  virtual void dump(std::string &out) const = 0;
  virtual double number_value() const;
  virtual int int_value() const;
  virtual bool bool_value() const;
  virtual const std::string &string_value() const;
  virtual const Json::array &array_items() const;
  virtual const Json &operator[](size_t i) const;
  virtual const Json::object_ &object_items() const;
  virtual const Json &operator[](const std::string &key) const;
  virtual ~JsonValue() {}
};

}  // namespace json11
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <fstream>

using namespace std;

class Matrix
{
private:
	int **matr;
	int st, cl;

public:
	Matrix();
	Matrix(int, int);
	Matrix(const Matrix &matrc);
	~Matrix();
	int rows()const;
	int columns()const;
	Matrix operator+ (const Matrix &mat_2) const;
	Matrix operator* (const Matrix &mat_2) const;
	Matrix& operator =(Matrix &);
	bool operator==(const Matrix&)const;
	friend istream& operator >> (istream& ist, Matrix& cmatr);
	friend ostream& operator << (ostream&, const Matrix&);
};
<commit_msg>Update matrix.hpp<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <typename T>
struct Node
{
	Node *left;
	Node *right;
	T data;
};

template <typename T>
class BinaryTree;

template <typename T>
std::ostream& operator<<(std::ostream&, const BinaryTree<T>&);

template <typename T>
class BinaryTree
{
private:
	Node<T>*root;
	int count = 0;
public:
	BinaryTree();
	~BinaryTree();
	Node<T>* root_();
	unsigned int getCount()const;
	Node<T> *findNode(const T&, Node<T>*)const;
	void insertNode(const T&x);
	void deleteNode(Node<T>* temp);
	bool removeElement(Node<T>* parent, Node<T>* current, const T& val);
	bool deleteValue(const T& value);
	void write(const std::string& filename)const;
	friend std::ostream& operator<<<>(std::ostream&, const BinaryTree<T>&);
};

template <typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template <typename T>
unsigned int BinaryTree<T>::getCount()const
{
	return count;
}

template<typename T>
Node<T>* BinaryTree<T>::findNode(const T& data, Node<T>* temp) const
{
	if (temp == 0 || data == temp->data)
		return temp;
	if (data > temp->data)
		return findNode(data, temp->right);
	else
		return findNode(data, temp->left);
}

template<typename T>
void BinaryTree<T>::insertNode(const T&x)
{
	if (findNode(x, root_())) return;
	Node<T>* Tree = new Node<T>;
	MyTree->data = x;
	MyTree->left = Tree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = Tree;
	else
	{
		if (x < buff->data)
			buff->left = Tree;
		else
			buff->right = Tree;
	}
	++count;
}

template<typename T>
void BinaryTree<T>::write(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << count << "\t";
	output(file_1, root);
	file_1.close();
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
		return;
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template <typename T>
std::ostream& output(std::ostream& out, const Node<T>* node, unsigned int level)
{
	if (!node)
		return out;
	output(out, node->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
		out << "\t";
	out << node->data << std::endl;
	output(out, node->left, level + 1);
	return out;
}

template<typename T>
bool BinaryTree<T>::removeElement(Node<T>* parent, Node<T>* current, const T& val)
{
	if (!current) return false;
	if (current->data == val)
	{
		if (current->left == NULL || current->right == NULL) {
			Node<T>* temp = current->left;
			if (current->right) temp = current->right;
			if (parent) {
				if (parent->left == current) {
					parent->left = temp;
				}
				else {
					parent->right = temp;
				}
			}
			else {
				this->root = temp;
			}
		}
		else {
			Node<T>* validSubs = current->right;
			while (validSubs->left) {
				validSubs = validSubs->left;
			}
			T temp = current->data;
			current->data = validSubs->data;
			validSubs->data = temp;
			return removeElement(current, current->right, temp);
		}
		delete current;
		count--;
		return true;
	}
	if (current->data > val)
		return removeElement(current, current->left, val);
	else
		return removeElement(current, current->right, val);
}

template<typename T>
bool BinaryTree<T>::deleteValue(const T& value)
{
	return this->removeElement(NULL, root, value);
}

template <typename T>
std::ostream& operator<<(std::ostream& out, const BinaryTree<T>& temp)
{
	output(out, temp.root, 0);
	return out;
}
<|endoftext|>


<commit_before>/*
** Copyright 1994 by Miron Livny, and Mike Litzkow
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation, and that the names of the University of
** Wisconsin and the copyright holders not be used in advertising or
** publicity pertaining to distribution of the software without specific,
** written prior permission.  The University of Wisconsin and the
** copyright holders make no representations about the suitability of this
** software for any purpose.  It is provided "as is" without express
** or implied warranty.
**
** THE UNIVERSITY OF WISCONSIN AND THE COPYRIGHT HOLDERS DISCLAIM ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF
** WISCONSIN OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT
** OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
** OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
** OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
** OR PERFORMANCE OF THIS SOFTWARE.
**
** Author:  Mike Greger
**
*/

#include "image.h"
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include "condor_debug.h"
#include "condor_syscalls.h"

// Class to hold proc file system stuff
class Proc {
public:
	Proc();
	void read_proc();
	long data_start_addr();
	long data_end_addr();
	long stack_start_addr();
	long stack_end_addr();
private:
	long	proc_pid;
	char	proc_comm[PATH_MAX];
	char	proc_state;
	long	proc_ppid;
	long	proc_pgrp;
	long	proc_session;
	long	proc_tty;
	long	proc_tpgid;
	unsigned long	proc_flags;
	unsigned long	proc_min_flt;
	unsigned long	proc_cmin_flt;
	unsigned long	proc_maj_flt;
	unsigned long	proc_cmaj_flt;
	long	proc_utime;
	long	proc_stime;
	long	proc_cutime;
	long	proc_cstime;
	long	proc_priority;
	long	proc_nice;
	unsigned long	proc_timeout;
	unsigned long	proc_it_real_value;
	long	proc_start_time;
	unsigned long	proc_vsize;
	unsigned long	proc_rss;
	unsigned long	proc_rlim;
	unsigned long	proc_start_code;
	unsigned long	proc_end_code;
	unsigned long	proc_stack_start_addr;
	unsigned long	proc_kstk_esp;
	unsigned long	proc_kstk_eip;
	long	proc_signal;
	long	proc_blocked;
	long	proc_sigignore;
	long	proc_sigcatch;
	unsigned long	proc_wchan;
	long	proc_stack_end_addr;
};

Proc::Proc()
{
}

void Proc::read_proc()
{
	int		scm;
	pid_t		pid;
	FILE		*proc;
	char		fn[PATH_MAX];
	unsigned long	tmp_u;

        scm = SetSyscalls( SYS_LOCAL | SYS_UNMAPPED );
        pid = getpid();

	sprintf(fn ,"/proc/%d/stat", pid);
        proc=fopen(fn, "r");
	if(!proc) {
		printf("Can't open %s for reading\n", fn);
	}

	fscanf(proc, "%d %s %c %d %d %d %d %d",
		&proc_pid, proc_comm, &proc_state, &proc_ppid, &proc_pgrp,
		&proc_session, &proc_tty, &proc_tpgid);
	fscanf(proc, "%u %u %u %u %u",
		&proc_flags, &proc_min_flt, &proc_cmin_flt,
		&proc_maj_flt, &proc_cmaj_flt);
	fscanf(proc, "%d %d %d %d %d %d",
		&proc_utime, &proc_stime, &proc_cutime, &proc_cstime,
		&proc_priority, &proc_nice);
	fscanf(proc, "%u %u %d",
		&proc_timeout, &proc_it_real_value, &proc_start_time);
	fscanf(proc, "%u %u %u %u %u %u %u %u %u",
		&proc_vsize, &proc_rss, &proc_rlim, &proc_start_code,
		&proc_end_code, &tmp_u, &proc_stack_start_addr, &proc_kstk_esp,
		&proc_kstk_eip); /* FIXME - Greger  This works, but why? */
	/*`
	fscanf(proc, "%d %d %d %d %u",
		&proc_signal, &proc_blocked, &proc_sigignore, &proc_sigcatch,
		&proc_wchan);*/

        fclose(proc);
	SetSyscalls(scm);
	proc_stack_end_addr = 0xbfffffff;
}

long Proc::data_start_addr()
{
	read_proc();
	return((long)((proc_end_code+7) & ~7)+4096);  // Odd, isn't it!
}

long Proc::data_end_addr()
{
	return(long)sbrk(0);
}

long Proc::stack_start_addr()
{
	read_proc();
	return((long)proc_stack_start_addr & ~4095);
}

long Proc::stack_end_addr()
{
	read_proc();
	return((long)proc_stack_end_addr);
}

/*
  Return starting address of the data segment
*/
long
data_start_addr()
{
	Proc	p;
	/*printf("Data Start: 0x%x\n", p.data_start_addr());*/
	return(p.data_start_addr());
}

/*
  Return ending address of the data segment
*/
long
data_end_addr()
{
	Proc	p;
	/*printf("Data End  : 0x%x\n", p.data_end_addr());*/
	return(p.data_end_addr());
}

/*
  Return TRUE if the stack grows toward lower addresses, and FALSE
  otherwise.
*/
BOOL StackGrowsDown()
{
	return TRUE;
}

/*
  Return the index into the jmp_buf where the stack pointer is stored.
  Expect that the jmp_buf will be viewed as an array of integers for
  this.
*/
int JmpBufSP_Index()
{
	return 4;
}

/*
  Return starting address of stack segment.
*/
long
stack_start_addr()
{
	Proc	p;
	return(p.stack_start_addr());
}

/*
  Return ending address of stack segment.
*/
long
stack_end_addr()
{
	Proc	p;
	return(p.stack_end_addr());
}

/*
  Patch any registers whose vaules should be different at restart
  time than they were at checkpoint time.
*/
void
patch_registers( void *generic_ptr )
{
	//Any Needed??  Don't think so.
}

// Support for shared library linking
// Written by Michael J. Greger (greger@cae.wisc.edu) August, 1996
// Based on Solaris port by Mike Litzkow

struct map_t {
	long	mem_start;
	long	mem_end;
	long	offset;
	int		prot;
	int		flags;
	int		inode;
	char	r, w, x, p;
};

static map_t	my_map[MAX_SEGS];
static int		map_count=0;
static int		text_loc=-1, stack_loc=-1, heap_loc=-1;

int find_map_for_addr(long addr)
{
	int		i;

	fprintf(stderr, "Finding map for addr:0x%x (map_cnt=%d)\n", addr, map_count);
	for(i=0;i<map_count;i++) {
		fprintf(stderr, "0x%x 0x%x\n", my_map[i].mem_start, my_map[i].mem_end);
		if(addr >= my_map[i].mem_start && addr <= my_map[i].mem_end) {
			fprintf(stderr, "  Found:%d\n", i);
			return i;
		}
	}
	fprintf(stderr, "  NOT Found\n");
	return -1;
}

int num_segments()
{
	FILE	*pfs;
	char	proc[128];
	char	rperm, wperm, xperm, priv;
	int		scm;
	int		num_seg=0;
	int		major, minor, inode;
	long	mem_start, mem_end;
	long	offset;
	char	e, f;

	scm=SetSyscalls(SYS_LOCAL | SYS_UNMAPPED);

	sprintf(proc, "/proc/%d/maps", syscall(SYS_getpid));
	pfs=fopen(proc, "r");
	if(!pfs) {
		SetSyscalls(scm);
		return -1;
	}

	// Count the numer of mmapped files in use by the executable
	while(!feof(pfs)) {
		fscanf(pfs, "%x-%x %c%c%c%c %x %d:%d %d\n",
			&mem_start, &mem_end, &rperm, &wperm,
			&xperm, &priv, &offset, &major, &minor, &inode);
		fprintf(stderr, "0x%x 0x%x %c%c%c%c 0x%x %d:%d %d\n",
			mem_start, mem_end, rperm, wperm, xperm, priv,
			offset, major, minor, inode);
		my_map[num_seg].mem_start=mem_start;
		my_map[num_seg].mem_end=mem_end-1;
		/* FIXME - Greger */
		if(my_map[num_seg].mem_end-my_map[num_seg].mem_start==0x34000-1)
			my_map[num_seg].mem_end=my_map[num_seg].mem_start+0x320ff;
		my_map[num_seg].offset=offset;
		my_map[num_seg].prot=(rperm=='r'?PROT_READ:0) |
							 (wperm=='w'?PROT_WRITE:0) |
							 (xperm=='x'?PROT_EXEC:0);
		my_map[num_seg].flags=(priv=='p'?:0);
		my_map[num_seg].inode=inode;
		my_map[num_seg].r=rperm;
		my_map[num_seg].w=wperm;
		my_map[num_seg].x=xperm;
		my_map[num_seg].p=priv;
		num_seg++;
	}
	fclose(pfs);

	map_count=num_seg;
	text_loc=find_map_for_addr((long)num_segments);
	if(StackGrowsDown())
		stack_loc=find_map_for_addr((long)stack_end_addr());
	else
		stack_loc=find_map_for_addr((long)stack_start_addr());
	heap_loc=find_map_for_addr((long)data_start_addr());

	fprintf(stderr, "%d segments\n", num_seg);
	SetSyscalls(scm);
	return num_seg;
}

int segment_bounds(int seg_num, RAW_ADDR &start, RAW_ADDR &end, int &prot)
{
	start=(long)my_map[seg_num].mem_start;
	end=(long)my_map[seg_num].mem_end;
	prot=my_map[seg_num].prot;
	if(seg_num==text_loc)
		return 1;
	else if(seg_num==stack_loc)
		return 2;
	else if(seg_num==heap_loc ||
		(my_map[seg_num].mem_start >= data_start_addr() &&
		 my_map[seg_num].mem_start <= data_end_addr()))
	 	return 3;
	//else if(!my_map[seg_num].inode)
		//return 1;

	return 0;
}

struct ma_flags {
	int 	flag_val;
	char	*flag_name;
};

void display_prmap()
{
	int		i;

	for(i=0;i<map_count;i++) {
		dprintf(D_ALWAYS, "addr= 0x%p, size= 0x%lx, offset= 0x%x\n",
			my_map[i].mem_start, my_map[i].mem_end-my_map[i].mem_start,
			my_map[i].offset);
		dprintf(D_ALWAYS, "Flags: %c%c%c%c inode %d\n",
			my_map[i].r, my_map[i].w, my_map[i].x, my_map[i].p,
			my_map[i].inode);
	}
}

/*
 * This is a hack!  The values found in /proc/pid/maps do not always seem
 * to be correct.  This function works its way down from the end addr
 * until it finds an addr that we can read from... - Greger
 */
unsigned long find_correct_vm_addr(unsigned long start, unsigned long end,
	int prot)
{

	if((mprotect((char *)start, end-start, PROT_READ))==0) {
		/*
		 * We were allowed to do read access to the chunk.  Change
		 * protection back to what it was before the call.
		 */
		if((mprotect((char *)start, end-start, prot))==0) {
			return end;
		} else {
			dprintf(D_ALWAYS, "Fatal error, Can't restore memory protection\n");
		}
	} else {
		/*
		 * We were not allowed read permission to the whole block.  Find
		 * a smaller block that we do have access to...
		 */
		for(;end>start;end-=4) { /* Most lib stuff is alligned on 4 bytes or less??... */
			if((mprotect((char *)start, end-start, PROT_READ))==0) {
				/*
		 		* We were allowed to do read access to the chunk.  Change
		 		* protection back to what it was before the call.
		 		*/
				if((mprotect((char *)start, end-start, prot))==0) {
					return end;
				} else {
					dprintf(D_ALWAYS, "Fatal error, Can't restore memory protection\n");
				}
			}
		}
		dprintf(D_ALWAYS, "Fatal error, Can't read any of this block\n");
	}
}

<commit_msg>   In find_correct_vm_addr(), since we're calling mprotect(), we need to be in local syscall mode.<commit_after>/*
** Copyright 1994 by Miron Livny, and Mike Litzkow
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation, and that the names of the University of
** Wisconsin and the copyright holders not be used in advertising or
** publicity pertaining to distribution of the software without specific,
** written prior permission.  The University of Wisconsin and the
** copyright holders make no representations about the suitability of this
** software for any purpose.  It is provided "as is" without express
** or implied warranty.
**
** THE UNIVERSITY OF WISCONSIN AND THE COPYRIGHT HOLDERS DISCLAIM ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF
** WISCONSIN OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT
** OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
** OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
** OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
** OR PERFORMANCE OF THIS SOFTWARE.
**
** Author:  Mike Greger
**
*/

#include "image.h"
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include "condor_debug.h"
#include "condor_syscalls.h"

// Class to hold proc file system stuff
class Proc {
public:
	Proc();
	void read_proc();
	long data_start_addr();
	long data_end_addr();
	long stack_start_addr();
	long stack_end_addr();
private:
	long	proc_pid;
	char	proc_comm[PATH_MAX];
	char	proc_state;
	long	proc_ppid;
	long	proc_pgrp;
	long	proc_session;
	long	proc_tty;
	long	proc_tpgid;
	unsigned long	proc_flags;
	unsigned long	proc_min_flt;
	unsigned long	proc_cmin_flt;
	unsigned long	proc_maj_flt;
	unsigned long	proc_cmaj_flt;
	long	proc_utime;
	long	proc_stime;
	long	proc_cutime;
	long	proc_cstime;
	long	proc_priority;
	long	proc_nice;
	unsigned long	proc_timeout;
	unsigned long	proc_it_real_value;
	long	proc_start_time;
	unsigned long	proc_vsize;
	unsigned long	proc_rss;
	unsigned long	proc_rlim;
	unsigned long	proc_start_code;
	unsigned long	proc_end_code;
	unsigned long	proc_stack_start_addr;
	unsigned long	proc_kstk_esp;
	unsigned long	proc_kstk_eip;
	long	proc_signal;
	long	proc_blocked;
	long	proc_sigignore;
	long	proc_sigcatch;
	unsigned long	proc_wchan;
	long	proc_stack_end_addr;
};

Proc::Proc()
{
}

void Proc::read_proc()
{
	int		scm;
	pid_t		pid;
	FILE		*proc;
	char		fn[PATH_MAX];
	unsigned long	tmp_u;

        scm = SetSyscalls( SYS_LOCAL | SYS_UNMAPPED );
        pid = getpid();

	sprintf(fn ,"/proc/%d/stat", pid);
        proc=fopen(fn, "r");
	if(!proc) {
		printf("Can't open %s for reading\n", fn);
	}

	fscanf(proc, "%d %s %c %d %d %d %d %d",
		&proc_pid, proc_comm, &proc_state, &proc_ppid, &proc_pgrp,
		&proc_session, &proc_tty, &proc_tpgid);
	fscanf(proc, "%u %u %u %u %u",
		&proc_flags, &proc_min_flt, &proc_cmin_flt,
		&proc_maj_flt, &proc_cmaj_flt);
	fscanf(proc, "%d %d %d %d %d %d",
		&proc_utime, &proc_stime, &proc_cutime, &proc_cstime,
		&proc_priority, &proc_nice);
	fscanf(proc, "%u %u %d",
		&proc_timeout, &proc_it_real_value, &proc_start_time);
	fscanf(proc, "%u %u %u %u %u %u %u %u %u",
		&proc_vsize, &proc_rss, &proc_rlim, &proc_start_code,
		&proc_end_code, &tmp_u, &proc_stack_start_addr, &proc_kstk_esp,
		&proc_kstk_eip); /* FIXME - Greger  This works, but why? */
	/*`
	fscanf(proc, "%d %d %d %d %u",
		&proc_signal, &proc_blocked, &proc_sigignore, &proc_sigcatch,
		&proc_wchan);*/

        fclose(proc);
	SetSyscalls(scm);
	proc_stack_end_addr = 0xbfffffff;
}

long Proc::data_start_addr()
{
	read_proc();
	return((long)((proc_end_code+7) & ~7)+4096);  // Odd, isn't it!
}

long Proc::data_end_addr()
{
	return(long)sbrk(0);
}

long Proc::stack_start_addr()
{
	read_proc();
	return((long)proc_stack_start_addr & ~4095);
}

long Proc::stack_end_addr()
{
	read_proc();
	return((long)proc_stack_end_addr);
}

/*
  Return starting address of the data segment
*/
long
data_start_addr()
{
	Proc	p;
	/*printf("Data Start: 0x%x\n", p.data_start_addr());*/
	return(p.data_start_addr());
}

/*
  Return ending address of the data segment
*/
long
data_end_addr()
{
	Proc	p;
	/*printf("Data End  : 0x%x\n", p.data_end_addr());*/
	return(p.data_end_addr());
}

/*
  Return TRUE if the stack grows toward lower addresses, and FALSE
  otherwise.
*/
BOOL StackGrowsDown()
{
	return TRUE;
}

/*
  Return the index into the jmp_buf where the stack pointer is stored.
  Expect that the jmp_buf will be viewed as an array of integers for
  this.
*/
int JmpBufSP_Index()
{
	return 4;
}

/*
  Return starting address of stack segment.
*/
long
stack_start_addr()
{
	Proc	p;
	return(p.stack_start_addr());
}

/*
  Return ending address of stack segment.
*/
long
stack_end_addr()
{
	Proc	p;
	return(p.stack_end_addr());
}

/*
  Patch any registers whose vaules should be different at restart
  time than they were at checkpoint time.
*/
void
patch_registers( void *generic_ptr )
{
	//Any Needed??  Don't think so.
}

// Support for shared library linking
// Written by Michael J. Greger (greger@cae.wisc.edu) August, 1996
// Based on Solaris port by Mike Litzkow

struct map_t {
	long	mem_start;
	long	mem_end;
	long	offset;
	int		prot;
	int		flags;
	int		inode;
	char	r, w, x, p;
};

static map_t	my_map[MAX_SEGS];
static int		map_count=0;
static int		text_loc=-1, stack_loc=-1, heap_loc=-1;

int find_map_for_addr(long addr)
{
	int		i;

	fprintf(stderr, "Finding map for addr:0x%x (map_cnt=%d)\n", addr, map_count);
	for(i=0;i<map_count;i++) {
		fprintf(stderr, "0x%x 0x%x\n", my_map[i].mem_start, my_map[i].mem_end);
		if(addr >= my_map[i].mem_start && addr <= my_map[i].mem_end) {
			fprintf(stderr, "  Found:%d\n", i);
			return i;
		}
	}
	fprintf(stderr, "  NOT Found\n");
	return -1;
}

int num_segments()
{
	FILE	*pfs;
	char	proc[128];
	char	rperm, wperm, xperm, priv;
	int		scm;
	int		num_seg=0;
	int		major, minor, inode;
	long	mem_start, mem_end;
	long	offset;
	char	e, f;

	scm=SetSyscalls(SYS_LOCAL | SYS_UNMAPPED);

	sprintf(proc, "/proc/%d/maps", syscall(SYS_getpid));
	pfs=fopen(proc, "r");
	if(!pfs) {
		SetSyscalls(scm);
		return -1;
	}

	// Count the numer of mmapped files in use by the executable
	while(!feof(pfs)) {
		fscanf(pfs, "%x-%x %c%c%c%c %x %d:%d %d\n",
			&mem_start, &mem_end, &rperm, &wperm,
			&xperm, &priv, &offset, &major, &minor, &inode);
		fprintf(stderr, "0x%x 0x%x %c%c%c%c 0x%x %d:%d %d\n",
			mem_start, mem_end, rperm, wperm, xperm, priv,
			offset, major, minor, inode);
		my_map[num_seg].mem_start=mem_start;
		my_map[num_seg].mem_end=mem_end-1;
		/* FIXME - Greger */
		if(my_map[num_seg].mem_end-my_map[num_seg].mem_start==0x34000-1)
			my_map[num_seg].mem_end=my_map[num_seg].mem_start+0x320ff;
		my_map[num_seg].offset=offset;
		my_map[num_seg].prot=(rperm=='r'?PROT_READ:0) |
							 (wperm=='w'?PROT_WRITE:0) |
							 (xperm=='x'?PROT_EXEC:0);
		my_map[num_seg].flags=(priv=='p'?:0);
		my_map[num_seg].inode=inode;
		my_map[num_seg].r=rperm;
		my_map[num_seg].w=wperm;
		my_map[num_seg].x=xperm;
		my_map[num_seg].p=priv;
		num_seg++;
	}
	fclose(pfs);

	map_count=num_seg;
	text_loc=find_map_for_addr((long)num_segments);
	if(StackGrowsDown())
		stack_loc=find_map_for_addr((long)stack_end_addr());
	else
		stack_loc=find_map_for_addr((long)stack_start_addr());
	heap_loc=find_map_for_addr((long)data_start_addr());

	fprintf(stderr, "%d segments\n", num_seg);
	SetSyscalls(scm);
	return num_seg;
}

int segment_bounds(int seg_num, RAW_ADDR &start, RAW_ADDR &end, int &prot)
{
	start=(long)my_map[seg_num].mem_start;
	end=(long)my_map[seg_num].mem_end;
	prot=my_map[seg_num].prot;
	if(seg_num==text_loc)
		return 1;
	else if(seg_num==stack_loc)
		return 2;
	else if(seg_num==heap_loc ||
		(my_map[seg_num].mem_start >= data_start_addr() &&
		 my_map[seg_num].mem_start <= data_end_addr()))
	 	return 3;
	//else if(!my_map[seg_num].inode)
		//return 1;

	return 0;
}

struct ma_flags {
	int 	flag_val;
	char	*flag_name;
};

void display_prmap()
{
	int		i;

	for(i=0;i<map_count;i++) {
		dprintf(D_ALWAYS, "addr= 0x%p, size= 0x%lx, offset= 0x%x\n",
			my_map[i].mem_start, my_map[i].mem_end-my_map[i].mem_start,
			my_map[i].offset);
		dprintf(D_ALWAYS, "Flags: %c%c%c%c inode %d\n",
			my_map[i].r, my_map[i].w, my_map[i].x, my_map[i].p,
			my_map[i].inode);
	}
}

/*
 * This is a hack!  The values found in /proc/pid/maps do not always seem
 * to be correct.  This function works its way down from the end addr
 * until it finds an addr that we can read from... - Greger
 */
unsigned long find_correct_vm_addr(unsigned long start, unsigned long end,
	int prot)
{
	int scm=SetSyscalls(SYS_LOCAL | SYS_UNMAPPED);

	if((mprotect((char *)start, end-start, PROT_READ))==0) {
		/*
		 * We were allowed to do read access to the chunk.  Change
		 * protection back to what it was before the call.
		 */
		if((mprotect((char *)start, end-start, prot))==0) {
			SetSyscalls(scm);
			return end;
		} else {
			dprintf(D_ALWAYS, "Fatal error, Can't restore memory protection\n");
		}
	} else {
		/*
		 * We were not allowed read permission to the whole block.  Find
		 * a smaller block that we do have access to...
		 */
		for(;end>start;end-=4) { /* Most lib stuff is alligned on 4 bytes or less??... */
			if((mprotect((char *)start, end-start, PROT_READ))==0) {
				/*
		 		* We were allowed to do read access to the chunk.  Change
		 		* protection back to what it was before the call.
		 		*/
				if((mprotect((char *)start, end-start, prot))==0) {
					SetSyscalls(scm);
					return end;
				} else {
					dprintf(D_ALWAYS, "Fatal error, Can't restore memory protection\n");
				}
			}
		}
		dprintf(D_ALWAYS, "Fatal error, Can't read any of this block\n");
	}
	SetSyscalls(scm);
}

<|endoftext|>


<commit_before>#include "startd.h"
static char *_FileName_ = __FILE__;

Resource::Resource( Sock* coll_sock, Sock* alt_sock )
{
	char tmp[100];

	r_classad = new ClassAd;
	r_private_classad = new ClassAd;
	r_state = new ResState( this );
	r_starter = new Starter;
	r_cur = new Match;
	r_pre = NULL;
	r_reqexp = new Reqexp( r_classad );
	r_attr = new ResAttributes( this );

	if( gethostname( tmp, 99 ) < 0 ) {
		EXCEPT( "gethostname" );
	}
	r_name = strdup( tmp );

	this->coll_sock = coll_sock;
	this->alt_sock = alt_sock;
	up_tid = -1;
	poll_tid = -1;
}

Resource::~Resource()
{
	daemonCore->Cancel_Timer( up_tid );
	this->cancel_poll_timer();

	delete r_state;
	delete r_classad;
	delete r_private_classad;
	delete r_starter;
	delete r_cur;
	delete r_pre;
	delete r_reqexp;
	delete r_attr;
	free( r_name );
}

int
Resource::init_classad()
{
	char 	tmp[80];
	int 	phys_memory = -1;
#if !defined(WIN32)
	char*	host_cell;
#endif
	char*	ptr;
	int		needs_free = 0;

		// Insert state and activity attributes into public ad
	r_state->init_classad( r_classad );

		// Name of this resource (needs to be in public and private ads)
	sprintf( tmp, "%s=\"%s\"", ATTR_NAME, r_name );
	r_classad->Insert( tmp );
	r_private_classad->Insert( tmp );

		// STARTD_IP_ADDR (needs to be in public and private ads)
	sprintf( tmp, "%s=\"%s\"", ATTR_STARTD_IP_ADDR,
			 daemonCore->InfoCommandSinfulString() );
	r_classad->Insert( tmp );
	r_private_classad->Insert( tmp );

#if !defined(WIN32) /* NEED TO PORT TO WIN32 */
		// AFS cell
	host_cell = get_host_cell();
	if( host_cell ) {
		sprintf( tmp, "%s=\"%s\"", ATTR_AFS_CELL, host_cell );
		r_classad->Insert( tmp );
		dprintf( D_ALWAYS, "AFS_Cell = \"%s\"\n", host_cell );
		delete [] host_cell;
	} else {
		dprintf( D_ALWAYS, "AFS_Cell not set\n" );
	}
#endif

		// If the UID domain is not set, use our hostname as the
		// default.
	if( (ptr = param("UID_DOMAIN")) == NULL ) {
		ptr = get_full_hostname();
	} else {
			// If the UID domain is defined as "*", accept uids from
			// anyone.
		if( ptr[0] == '*' ) {
			free( ptr );
			ptr = "";
		} else {
			needs_free = 1;
		}
	}
	dprintf( D_ALWAYS, "%s = \"%s\"\n", ATTR_UID_DOMAIN, ptr );
	sprintf( tmp, "%s=\"%s\"", ATTR_UID_DOMAIN, ptr );
	r_classad->Insert( tmp );
	if( needs_free ) {
		free( ptr );
		needs_free = 0;
	}

		// If the file system domain is not set, use our hostname as
		// the default.
	if( (ptr = param("FILESYSTEM_DOMAIN")) == NULL ) {
		ptr = get_full_hostname();
	} else {
			// If the file system domain is defined as "*", assume we
			// share files with everyone.
		if( ptr[0] == '*' ) {
			free( ptr );
			ptr = "";
		} else {
			needs_free = 1;
		}
	}
	dprintf( D_ALWAYS, "%s = \"%s\"\n", ATTR_FILE_SYSTEM_DOMAIN, ptr );
	sprintf( tmp, "%s=\"%s\"", ATTR_FILE_SYSTEM_DOMAIN, ptr );
	r_classad->Insert( tmp );
	if( needs_free ) {
		free( ptr );
		needs_free = 0;
	}

		// Number of CPUs.
	sprintf( tmp, "%s=%d", ATTR_CPUS, calc_ncpus() );
	r_classad->Insert( tmp );

		// Physical memory
	phys_memory = calc_phys_memory();
	if( phys_memory > 0 ) {
		sprintf( tmp, "%s=%d", ATTR_MEMORY, phys_memory );
		r_classad->Insert( tmp );
	}

		// Nest
	if( (ptr = param("NEST")) != NULL ) {
		sprintf( tmp, "%s=\"%s\"", ATTR_NEST, ptr );
		r_classad->Insert( tmp );
		free( ptr );
	}

		// Current rank
	sprintf( tmp, "%s=0", ATTR_CURRENT_RANK );
	r_classad->Insert( tmp );

	return TRUE;
}

int
Resource::update_classad()
{
	ClassAd* cp = r_classad;
	char line[80];

		// Recompute update-only statistics
	r_attr->update();

		// Refresh the classad with statistics that are only needed on updates
	sprintf( line, "%s=%lu", ATTR_VIRTUAL_MEMORY, r_attr->virtmem() );
 	cp->Insert( line );

	sprintf( line, "%s=%lu", ATTR_DISK, r_attr->disk() );
	cp->Insert( line );

	// KFLOPS and MIPS are only conditionally computed; thus, only
	// advertise them if we computed them.
	if ( r_attr->kflops() > 0 ) {
		sprintf( line, "%s=%d", ATTR_KFLOPS, r_attr->kflops() );
		cp->Insert( line );
	}
	if ( r_attr->mips() > 0 ) {
		sprintf( line, "%s=%d", ATTR_MIPS, r_attr->mips() );
		cp->Insert( line );
	}

		// Add capability to private classad.  If r_pre exists, we
		// need to advertise it's capability.  Otherwise, we should
		// get the capability from r_cur.
	if( r_pre ) {
		sprintf( line, "%s=\"%s\"", ATTR_CAPABILITY, r_pre->capab() );
	} else {
		sprintf( line, "%s=\"%s\"", ATTR_CAPABILITY, r_cur->capab() );
	}
	r_private_classad->Insert( line );

		// Update current rank expression in classad
	sprintf( line, "%s=%f", ATTR_CURRENT_RANK, r_cur->rank() );
	cp->Insert( line );

	return TRUE;
}

int
Resource::timeout_classad()
{
	ClassAd* cp = r_classad;
	char line[80];

		// Recompute statistics needed at every timeout
	r_attr->timeout();

	sprintf( line, "%s=%f", ATTR_LOAD_AVG, r_attr->load() );
	cp->Insert(line);

	sprintf( line, "%s=%f", ATTR_CONDOR_LOAD_AVG, r_attr->condor_load() );
	cp->Insert(line);

	sprintf(line, "%s=%d", ATTR_KEYBOARD_IDLE, r_attr->idle() );
	cp->Insert(line);

	// ConsoleIdle cannot be determined on all platforms; thus, only
	// advertise if it is not -1.
	if( r_attr->console_idle() != -1 ) {
		sprintf( line, "%s=%d", ATTR_CONSOLE_IDLE,
				 r_attr->console_idle() );
		cp->Insert(line);
	}

	return TRUE;
}

int
Resource::update()
{
	int rval1 = TRUE, rval2 = TRUE;

		// Recompute stats needed only for updates and refresh classad.
	this->update_classad();

		// Send class ad to collector
	rval1 = send_classad_to_sock( coll_sock, TRUE );
	if( rval1 ) {
		dprintf( D_ALWAYS, "Sent update to the collector (%s)\n",
				 collector_host );
	}

		// If we have an alternate collector, send CA there.
	if( alt_sock ) {
		if( (rval2 = send_classad_to_sock( alt_sock, FALSE )) ) {
			dprintf( D_FULLDEBUG,
					 "Sent update to the condor_view host (%s)\n",
					 condor_view_host );
		}
	}

		// Set a flag to indicate that we've done an update.
	did_update = TRUE;

		// Reset our timer so we update again after update_interval.
	daemonCore->Reset_Timer( up_tid, update_interval, 0 );

	return( rval1 && rval2 );
}

int
Resource::eval_and_update()
{
	did_update = FALSE;

		// Evaluate the state of this resource.
	eval_state();

		// If we didn't update b/c of the eval_state, we need to
		// actually do the update now.
	if( ! did_update ) {
		update();
	}
	return TRUE;
}

int
Resource::start_update_timer()
{
	up_tid =
		daemonCore->Register_Timer( update_interval, 0,
									(TimerHandler)timeout_and_update,
									"timeout_and_update" );
	if( up_tid < 0 ) {
		EXCEPT( "Can't register DaemonCore timer" );
	}

	if( ! daemonCore->Register_DataPtr( (void*) this ) ) {
		EXCEPT( "Can't register update timer data pointer" );
	}
	return TRUE;
}

int
Resource::start_poll_timer()
{
	if( poll_tid >= 0 ) {
			// Timer already started.
		return TRUE;
	}

	poll_tid =
		daemonCore->Register_Timer( polling_interval,
									polling_interval,
									(TimerHandler)poll_resource,
									"poll_resource" );
	if( poll_tid < 0 ) {
		EXCEPT( "Can't register DaemonCore timer" );
	}

	if( ! daemonCore->Register_DataPtr( (void*) this ) ) {
		EXCEPT( "Can't register update timer data pointer" );
	}
	return TRUE;
}

void
Resource::cancel_poll_timer()
{
	if( poll_tid != -1 ) {
		daemonCore->Cancel_Timer( poll_tid );
		poll_tid = -1;
		dprintf( D_FULLDEBUG, "Canceled polling timer.\n" );
	}
}

int
Resource::change_state( State newstate )
{
	return r_state->change( newstate );
}

int
Resource::change_state( Activity newact )
{
	return r_state->change( newact );
}

bool
Resource::in_use()
{
	State s = state();
	if( s == owner_state || s == unclaimed_state ) {
		return false;
	} else {
		return true;
	}
}

void
Resource::starter_exited()
{
	dprintf( D_ALWAYS, "Starter pid %d has exited.\n",
			 r_starter->pid() );
	r_starter->exited();
	change_state( idle_act );
}

int
Resource::send_classad_to_sock( Sock* sock, int send_private )
{
	sock->encode();

	r_classad->SetMyTypeName( STARTD_ADTYPE );
	r_classad->SetTargetTypeName( JOB_ADTYPE );

	if( send_private ) {
		r_private_classad->SetMyTypeName( STARTD_ADTYPE );
		r_private_classad->SetTargetTypeName( JOB_ADTYPE );
	}

	if( ! sock->put( UPDATE_STARTD_AD ) ) {
		dprintf( D_ALWAYS, "Can't send command\n");
		sock->end_of_message();
		return FALSE;
	}

	if( ! r_classad->put( *sock ) ) {
		dprintf( D_ALWAYS, "Can't send public classad\n");
		sock->end_of_message();
		return FALSE;
	}

	if( send_private ) {
		if( ! r_private_classad->put( *sock ) ) {
			dprintf( D_ALWAYS, "Can't send private classad\n");
			sock->end_of_message();
			return FALSE;
		}
	}

	if( ! sock->end_of_message() ) {
		dprintf( D_ALWAYS, "Can't send end_of_message\n");
		return FALSE;
	}

	return TRUE;
}

<commit_msg>+ init_classad(), update_classad() and timeout_classad() all return   void. + Use the new ResState::update() and ResAttributes::update()   interface.  Pass a pointer to the classad you want filled in, and   let them do all the work. + Use my_hostname() instead of calling gethostname() directly. + Automatically insert Machine, Arch and OpSys into the startd ad.<commit_after>#include "startd.h"
static char *_FileName_ = __FILE__;

Resource::Resource( Sock* coll_sock, Sock* alt_sock )
{
	r_classad = new ClassAd;
	r_private_classad = new ClassAd;
	r_state = new ResState( this );
	r_starter = new Starter;
	r_cur = new Match;
	r_pre = NULL;
	r_reqexp = new Reqexp( r_classad );
	r_attr = new ResAttributes( this );
	r_name = strdup( my_hostname() );

	this->coll_sock = coll_sock;
	this->alt_sock = alt_sock;
	up_tid = -1;
	poll_tid = -1;
}

Resource::~Resource()
{
	daemonCore->Cancel_Timer( up_tid );
	this->cancel_poll_timer();

	delete r_state;
	delete r_classad;
	delete r_private_classad;
	delete r_starter;
	delete r_cur;
	delete r_pre;
	delete r_reqexp;
	delete r_attr;
	free( r_name );
}

void
Resource::init_classad()
{
	char 	tmp[80];
	int 	phys_memory = -1;
	char*	ptr;
	int		needs_free = 0;

		// Insert state and activity attributes into public ad
	r_state->update( r_classad );

		// Name of this resource (needs to be in public and private ads)
	sprintf( tmp, "%s = \"%s\"", ATTR_NAME, r_name );
	r_classad->Insert( tmp );
	r_private_classad->Insert( tmp );

		// Stick the hostname of this machine into classad.
	sprintf( tmp, "%s = \"%s\"", ATTR_MACHINE, my_hostname() );
	r_classad->Insert( tmp );

		// STARTD_IP_ADDR (needs to be in public and private ads)
	sprintf( tmp, "%s = \"%s\"", ATTR_STARTD_IP_ADDR,
			 daemonCore->InfoCommandSinfulString() );
	r_classad->Insert( tmp );
	r_private_classad->Insert( tmp );

		// Arch and OpSys.  Note: these will always return something,
		// since config() will insert values for these from uname() if
		// we don't have them in the config file.
	ptr = param( "ARCH" );
	sprintf( tmp, "%s = \"%s\"", ATTR_ARCH, ptr );
	r_classad->Insert( tmp );
	free( ptr );

	ptr = param( "OPSYS" );
	sprintf( tmp, "%s = \"%s\"", ATTR_OPSYS, ptr );
	r_classad->Insert( tmp );
	free( ptr );

#if !defined(WIN32) /* NEED TO PORT TO WIN32 */
		// AFS cell
	if( r_attr->afs_cell() ) {
		sprintf( tmp, "%s = \"%s\"", ATTR_AFS_CELL, r_attr->afs_cell() );
		r_classad->Insert( tmp );
		dprintf( D_ALWAYS, "%s\n", tmp );
	} else {
		dprintf( D_ALWAYS, "AFS_Cell not set\n" );
	}
#endif

		// If the UID domain is not set, use our hostname as the
		// default.
	if( (ptr = param("UID_DOMAIN")) == NULL ) {
		ptr = my_full_hostname();
	} else {
			// If the UID domain is defined as "*", accept uids from
			// anyone.
		if( ptr[0] == '*' ) {
			free( ptr );
			ptr = "";
		} else {
			needs_free = 1;
		}
	}
	sprintf( tmp, "%s = \"%s\"", ATTR_UID_DOMAIN, ptr );
	dprintf( D_ALWAYS, "%s\n", tmp );
	r_classad->Insert( tmp );
	if( needs_free ) {
		free( ptr );
		needs_free = 0;
	}

		// If the file system domain is not set, use our hostname as
		// the default.
	if( (ptr = param("FILESYSTEM_DOMAIN")) == NULL ) {
		ptr = my_full_hostname();
	} else {
			// If the file system domain is defined as "*", assume we
			// share files with everyone.
		if( ptr[0] == '*' ) {
			free( ptr );
			ptr = "";
		} else {
			needs_free = 1;
		}
	}
	sprintf( tmp, "%s = \"%s\"", ATTR_FILE_SYSTEM_DOMAIN, ptr );
	dprintf( D_ALWAYS, "%s\n", tmp );
	r_classad->Insert( tmp );
	if( needs_free ) {
		free( ptr );
		needs_free = 0;
	}

		// Number of CPUs.
	sprintf( tmp, "%s = %d", ATTR_CPUS, calc_ncpus() );
	r_classad->Insert( tmp );

		// Physical memory
	phys_memory = calc_phys_memory();
	if( phys_memory > 0 ) {
		sprintf( tmp, "%s = %d", ATTR_MEMORY, phys_memory );
		r_classad->Insert( tmp );
	}

		// Nest
	if( (ptr = param("NEST")) != NULL ) {
		sprintf( tmp, "%s = \"%s\"", ATTR_NEST, ptr );
		r_classad->Insert( tmp );
		free( ptr );
	}

		// Current rank
	sprintf( tmp, "%s = 0", ATTR_CURRENT_RANK );
	r_classad->Insert( tmp );
}

void
Resource::update_classad()
{
	char line[100];

		// Recompute update-only statistics and fill in classad
	r_attr->update( r_classad );

		// Add capability to private classad.  If r_pre exists, we
		// need to advertise it's capability.  Otherwise, we should
		// get the capability from r_cur.
	if( r_pre ) {
		sprintf( line, "%s = \"%s\"", ATTR_CAPABILITY, r_pre->capab() );
	} else {
		sprintf( line, "%s = \"%s\"", ATTR_CAPABILITY, r_cur->capab() );
	}
	r_private_classad->Insert( line );

		// Update current rank expression in classad
	sprintf( line, "%s = %f", ATTR_CURRENT_RANK, r_cur->rank() );
	r_classad->Insert( line );
}

void
Resource::timeout_classad()
{
		// Recompute statistics needed at every timeout and fill in classad
	r_attr->timeout( r_classad );
}

int
Resource::update()
{
	int rval1 = TRUE, rval2 = TRUE;

		// Recompute stats needed only for updates and refresh classad.
	this->update_classad();

		// Send class ad to collector
	if( (rval1 = send_classad_to_sock( coll_sock, TRUE )) ) {
		dprintf( D_ALWAYS, "Sent update to the collector (%s)\n",
				 collector_host );
	}

		// If we have an alternate collector, send CA there.
	if( alt_sock ) {
		if( (rval2 = send_classad_to_sock( alt_sock, FALSE )) ) {
			dprintf( D_FULLDEBUG,
					 "Sent update to the condor_view host (%s)\n",
					 condor_view_host );
		}
	}

		// Set a flag to indicate that we've done an update.
	did_update = TRUE;

		// Reset our timer so we update again after update_interval.
	daemonCore->Reset_Timer( up_tid, update_interval, 0 );

	return( rval1 && rval2 );
}

int
Resource::eval_and_update()
{
	did_update = FALSE;

		// Evaluate the state of this resource.
	eval_state();

		// If we didn't update b/c of the eval_state, we need to
		// actually do the update now.
	if( ! did_update ) {
		update();
	}
	return TRUE;
}

int
Resource::start_update_timer()
{
	up_tid =
		daemonCore->Register_Timer( update_interval, 0,
									(TimerHandler)timeout_and_update,
									"timeout_and_update" );
	if( up_tid < 0 ) {
		EXCEPT( "Can't register DaemonCore timer" );
	}

	if( ! daemonCore->Register_DataPtr( (void*) this ) ) {
		EXCEPT( "Can't register update timer data pointer" );
	}
	return TRUE;
}

int
Resource::start_poll_timer()
{
	if( poll_tid >= 0 ) {
			// Timer already started.
		return TRUE;
	}

	poll_tid =
		daemonCore->Register_Timer( polling_interval,
									polling_interval,
									(TimerHandler)poll_resource,
									"poll_resource" );
	if( poll_tid < 0 ) {
		EXCEPT( "Can't register DaemonCore timer" );
	}

	if( ! daemonCore->Register_DataPtr( (void*) this ) ) {
		EXCEPT( "Can't register update timer data pointer" );
	}
	return TRUE;
}

void
Resource::cancel_poll_timer()
{
	if( poll_tid != -1 ) {
		daemonCore->Cancel_Timer( poll_tid );
		poll_tid = -1;
		dprintf( D_FULLDEBUG, "Canceled polling timer.\n" );
	}
}

int
Resource::change_state( State newstate )
{
	return r_state->change( newstate );
}

int
Resource::change_state( Activity newact )
{
	return r_state->change( newact );
}

bool
Resource::in_use()
{
	State s = state();
	if( s == owner_state || s == unclaimed_state ) {
		return false;
	} else {
		return true;
	}
}

void
Resource::starter_exited()
{
	dprintf( D_ALWAYS, "Starter pid %d has exited.\n",
			 r_starter->pid() );
	r_starter->exited();
	change_state( idle_act );
}

int
Resource::send_classad_to_sock( Sock* sock, int send_private )
{
	sock->encode();

	r_classad->SetMyTypeName( STARTD_ADTYPE );
	r_classad->SetTargetTypeName( JOB_ADTYPE );

	if( send_private ) {
		r_private_classad->SetMyTypeName( STARTD_ADTYPE );
		r_private_classad->SetTargetTypeName( JOB_ADTYPE );
	}

	if( ! sock->put( UPDATE_STARTD_AD ) ) {
		dprintf( D_ALWAYS, "Can't send command\n");
		sock->end_of_message();
		return FALSE;
	}

	if( ! r_classad->put( *sock ) ) {
		dprintf( D_ALWAYS, "Can't send public classad\n");
		sock->end_of_message();
		return FALSE;
	}

	if( send_private ) {
		if( ! r_private_classad->put( *sock ) ) {
			dprintf( D_ALWAYS, "Can't send private classad\n");
			sock->end_of_message();
			return FALSE;
		}
	}

	if( ! sock->end_of_message() ) {
		dprintf( D_ALWAYS, "Can't send end_of_message\n");
		return FALSE;
	}

	return TRUE;
}

<|endoftext|>