<commit_before>// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "default-platform.h"

#include <queue>

// TODO(jochen): We should have our own version of checks.h.
#include "../checks.h"
// TODO(jochen): Why is cpu.h not in platform/?
#include "../cpu.h"
#include "worker-thread.h"

namespace v8 {
namespace internal {

DefaultPlatform::DefaultPlatform()
    : initialized_(false), thread_pool_size_(0) {}

DefaultPlatform::~DefaultPlatform() {
  LockGuard<Mutex> guard(&lock_);
  if (initialized_) {
    queue_.Terminate();
    for (std::vector<WorkerThread*>::iterator i = thread_pool_.begin();
         i != thread_pool_.end(); ++i) {
      delete *i;
    }
  }
}

void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
  LockGuard<Mutex> guard(&lock_);
  ASSERT(thread_pool_size >= 0);
  if (thread_pool_size < 1)
    thread_pool_size = CPU::NumberOfProcessorsOnline();
  thread_pool_size_ = Max(Min(thread_pool_size, kMaxThreadPoolSize), 1);
}

void DefaultPlatform::EnsureInitialized() {
  LockGuard<Mutex> guard(&lock_);
  if (initialized_) return;
  initialized_ = true;

  for (int i = 0; i < thread_pool_size_; ++i)
    thread_pool_.push_back(new WorkerThread(&queue_));
}

void DefaultPlatform::CallOnBackgroundThread(Task *task,
                                             ExpectedRuntime expected_runtime) {
  EnsureInitialized();
  queue_.Append(task);
}

void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
  // TODO(jochen): implement.
  task->Run();
  delete task;
}

} }  // namespace v8::internal
<commit_msg>Always terminate the task queue<commit_after>// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "default-platform.h"

#include <queue>

// TODO(jochen): We should have our own version of checks.h.
#include "../checks.h"
// TODO(jochen): Why is cpu.h not in platform/?
#include "../cpu.h"
#include "worker-thread.h"

namespace v8 {
namespace internal {

DefaultPlatform::DefaultPlatform()
    : initialized_(false), thread_pool_size_(0) {}

DefaultPlatform::~DefaultPlatform() {
  LockGuard<Mutex> guard(&lock_);
  queue_.Terminate();
  if (initialized_) {
    for (std::vector<WorkerThread*>::iterator i = thread_pool_.begin();
         i != thread_pool_.end(); ++i) {
      delete *i;
    }
  }
}

void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
  LockGuard<Mutex> guard(&lock_);
  ASSERT(thread_pool_size >= 0);
  if (thread_pool_size < 1)
    thread_pool_size = CPU::NumberOfProcessorsOnline();
  thread_pool_size_ = Max(Min(thread_pool_size, kMaxThreadPoolSize), 1);
}

void DefaultPlatform::EnsureInitialized() {
  LockGuard<Mutex> guard(&lock_);
  if (initialized_) return;
  initialized_ = true;

  for (int i = 0; i < thread_pool_size_; ++i)
    thread_pool_.push_back(new WorkerThread(&queue_));
}

void DefaultPlatform::CallOnBackgroundThread(Task *task,
                                             ExpectedRuntime expected_runtime) {
  EnsureInitialized();
  queue_.Append(task);
}

void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
  // TODO(jochen): implement.
  task->Run();
  delete task;
}

} }  // namespace v8::internal
<|endoftext|>


<commit_before>#include <Dice.h>
#include <Arduino.h>

Dice::Dice(int led4, int led2, int led1) {
  _led4 = led4; // LED that represents MSBit
  _led2 = led2; // LED that represents medium Bit
  _led1 = led1; // LED that represents LSBit
  pinMode(_led4, OUTPUT); // all pins are OUTPUT pins
  pinMode(_led2, OUTPUT);
  pinMode(_led1, OUTPUT);
  randomSeed(analogRead(A0)); // read random value from analog A0 for initial seed
}

void Dice::roll() {
   int result = random(1,7); // get a random number from 1..6
#ifdef DEBUG
   Serial.print(“result = “);
   Serial.println(result);
#endif

   controlLED(_led4, (1 == result / 4 )); // simple arithmetic

#ifdef DEBUG
   Serial.print(“led4 = “);
   Serial.println(1 == result / 4);
#endif

   result = result % 4;
   controlLED(_led2, (1 == result /  2));

#ifdef DEBUG
   Serial.print(“led2 = “);
   Serial.println(1 == result / 2);
#endif

   result = result % 2;
   controlLED(_led1, 1 ==  result);

#ifdef DEBUG
   Serial.print(“led1 = “);
   Serial.println(1 == result);
#endif
}

void Dice::controlLED(int led, bool on) {
  if (on)
    digitalWrite(led, HIGH);
  else
    digitalWrite(led, LOW);
}
<commit_msg>Eliminated some stray characters<commit_after>#include <Dice.h>
#include <Arduino.h>

#define DEBUG
Dice::Dice(int led4, int led2, int led1) {
  _led4 = led4; // LED that represents MSBit
  _led2 = led2; // LED that represents medium Bit
  _led1 = led1; // LED that represents LSBit
  pinMode(_led4, OUTPUT); // all pins are OUTPUT pins
  pinMode(_led2, OUTPUT);
  pinMode(_led1, OUTPUT);
  randomSeed(analogRead(A0)); // read random value from analog A0 for initial seed
}

void Dice::roll() {
   int result = random(1,7); // get a random number from 1..6

#ifdef DEBUG
   Serial.print("dice value = ");
   Serial.println(result);
#endif

   controlLED(_led4, (1 == result / 4 )); // simple arithmetic

#ifdef DEBUG
   Serial.print("LED4 = ");
   Serial.println(1 == result / 4);
#endif

   result = result % 4;
   controlLED(_led2, (1 == result /  2));

#ifdef DEBUG
   Serial.print("LED2 = ");
   Serial.println(1 == result / 2);
#endif

   result = result % 2;
   controlLED(_led1, 1 ==  result);

#ifdef DEBUG
   Serial.print("LED1 = ");
   Serial.println(1 == result);
#endif
}

void Dice::controlLED(int led, bool on) {
  if (on)
    digitalWrite(led, HIGH);
  else
    digitalWrite(led, LOW);
}
<|endoftext|>


<commit_before>/*

*/

#include "lineFollowing.h"

using namespace std;
using namespace cv;

ControlMovements lineFollowingControl() {

  line_main();

  return ControlMovements();
}

void line_main() {
//  printf("Hello, this is Caleb\n");

  VideoCapture cap("../../tests/videos/top_down_4.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;

  namedWindow("edges", CV_WINDOW_NORMAL);
//  Mat edges;
  for (; ;) {
    Mat mask, hsv_mask;
    Mat frame, hsv;
    cap >> frame; // get a new frame from camera

    cvtColor(frame, hsv, CV_BGR2HSV);

    double minH = 0;
    double minS = 0;
    double minV = 0;
    double maxH = 255;
    double maxS = 255;
    double maxV = 255;

    cv::Scalar lower(minH, minS, minV);
    cv::Scalar upper(maxH, maxS, maxV);
    cv::inRange(hsv, lower, upper, mask);

    //    low = Scalar(30, 0, 240);
//    high = Scalar(80, 70, 255);

//    inRange(hsv, Scalar(100, 0, 0), Scalar(255, 255, 255), mask);

    bitwise_and(frame, frame, frame, mask);

//    cvtColor(mask, hsv_mask, CV_HS);

    vector <Vec4i> lines;
//    HoughLinesP(mask, lines, 1, CV_PI / 180, 100, 100, 10);

    printf("Adding in %d lines\n", (int) lines.size());
    for (size_t i = 0; i < lines.size(); i++) {
      Vec4i l = lines[i];
      line(hsv_mask, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, CV_AA);
    }

    imshow("edges", frame);
    if (waitKey(30) >= 0) break;
  }
  // the camera will be deinitialized automatically in VideoCapture destructor
  return;
}
<commit_msg>correct hsv threshold<commit_after>/*

*/

#include "lineFollowing.h"

using namespace std;
using namespace cv;

ControlMovements lineFollowingControl() {

  line_main();

  return ControlMovements();
}

void line_main() {
//  printf("Hello, this is Caleb\n");

  VideoCapture cap("../../tests/videos/top_down_4.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;

  namedWindow("edges", CV_WINDOW_NORMAL);
//  Mat edges;
  for (; ;) {
    Mat mask, hsv_mask;
    Mat frame, hsv;
    cap >> frame; // get a new frame from camera

    cvtColor(frame, hsv, CV_BGR2HSV);

    double minH = 30;
    double minS = 0;
    double minV = 240;
    double maxH = 80;
    double maxS = 70;
    double maxV = 255;

    cv::Scalar lower(minH, minS, minV);
    cv::Scalar upper(maxH, maxS, maxV);
    cv::inRange(hsv, lower, upper, mask);

    //    low = Scalar(30, 0, 240);
//    high = Scalar(80, 70, 255);

//    inRange(hsv, Scalar(100, 0, 0), Scalar(255, 255, 255), mask);

    bitwise_and(frame, frame, frame, mask);

//    cvtColor(mask, hsv_mask, CV_HS);

    vector <Vec4i> lines;
//    HoughLinesP(mask, lines, 1, CV_PI / 180, 100, 100, 10);

    printf("Adding in %d lines\n", (int) lines.size());
    for (size_t i = 0; i < lines.size(); i++) {
      Vec4i l = lines[i];
      line(hsv_mask, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, CV_AA);
    }

    imshow("edges", mask);
    if (waitKey(30) >= 0) break;
  }
  // the camera will be deinitialized automatically in VideoCapture destructor
  return;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 BrewPi/Elco Jacobs.
 *
 * This file is part of BrewPi.
 *
 * BrewPi is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * BrewPi is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with BrewPi.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "Brewpi.h"
#include "BrewpiStrings.h"

#if BREWPI_MENU

#include "Menu.h"

#include <limits.h>
#include "Pins.h"
#include "Display.h"
#include "TempControl.h"
#include "TemperatureFormats.h"
#include "RotaryEncoder.h"
#include "PiLink.h"
#include "Ticks.h"

Menu menu;

#define MENU_OPTIMIZE 0

#define MENU_TIMEOUT 10u

void Menu::pickSettingToChange(){
	// ensure beer temp is displayed
	uint8_t flags = display.getDisplayFlags();
	display.setDisplayFlags(flags &= ~(LCD_FLAG_ALTERNATE_ROOM|LCD_FLAG_DISPLAY_ROOM));
	pickSettingToChangeLoop();
	display.setDisplayFlags(flags);
}

#if MENU_OPTIMIZE
void blinkLoop()
{
	uint16_t timer = ticks.seconds();
	uint8_t blinkTimer = 0;
	while(ticks.timeSince(timer) < MENU_TIMEOUT_SECS){ // time out at 10 seconds
		if(rotaryEncoder.changed()){
			timer=ticks.seconds();
			blinkTimer = 0;
		}

}

#endif

void Menu::pickSettingToChangeLoop(void){

	rotaryEncoder.setRange(0, 0, 2); // mode setting, beer temp, fridge temp
	uint16_t lastChangeTime = ticks.seconds();
	uint8_t blinkTimer = 0;
	while(ticks.timeSince(lastChangeTime) < MENU_TIMEOUT){ // time out at 10 seconds
		if(rotaryEncoder.changed()){
			lastChangeTime = ticks.seconds();
			blinkTimer = 0;
		}
		if(blinkTimer == 0){
			// print all text again for blinking
			display.printStationaryText();
		}
		if(blinkTimer == 128){ // blink one of the options by overwriting it with spaces
			display.printAt_P(0, rotaryEncoder.read(), STR_SPACES_END-6);
		}
		if( rotaryEncoder.pushed() ){
			rotaryEncoder.resetPushed();
			switch(rotaryEncoder.read()){
				case 0:
					pickMode();
					return;
				case 1:
					// switch to beer constant, because beer setting will be set through display
					tempControl.setMode(MODE_BEER_CONSTANT);
					display.printMode();
					pickBeerSetting();
					return;
				case 2:
					// switch to fridge constant, because fridge setting will be set through display
					tempControl.setMode(MODE_FRIDGE_CONSTANT);
					display.printMode();
					pickFridgeSetting();
					return;
			}
		}

		blinkTimer++;
		wait.millis(3); // delay for blinking
	}
}

void Menu::initRotaryWithTemp(fixed7_9 oldSetting){
	fixed7_9 startVal;
	if(oldSetting == INT_MIN){ // previous temperature was not defined, start at 20C
		startVal = 20*512;
	}
	else{
		startVal = oldSetting;
	}
	rotaryEncoder.setRange(fixedToTenths(startVal), fixedToTenths(tempControl.cc.tempSettingMin), fixedToTenths(tempControl.cc.tempSettingMax));
}

const char* LOOKUP = "bfpo";

void Menu::pickMode(void){
	display.printStationaryText(); // restore original text after blinking 'Mode'
	char oldSetting = tempControl.getMode();
	uint8_t startValue=0;
	startValue = indexOf(LOOKUP, oldSetting);
	rotaryEncoder.setRange(startValue, 0, 3); // toggle between beer constant, beer profile, fridge constant
	const char lookup[] = {'b', 'f', 'p', 'o'};
	uint8_t blinkTimer = 0;
	uint16_t lastChangeTime = ticks.seconds();
	while(ticks.timeSince(lastChangeTime) < MENU_TIMEOUT){ // time out at 10 seconds
		if(rotaryEncoder.changed()){
			lastChangeTime = ticks.seconds();
			blinkTimer = 0;

			tempControl.setMode(lookup[rotaryEncoder.read()]);
			display.printMode();

			if( rotaryEncoder.pushed() ){
				rotaryEncoder.resetPushed();
				char mode = tempControl.getMode();
				if(mode ==  MODE_BEER_CONSTANT){
					menu.pickBeerSetting();
				}
				else if(mode == MODE_FRIDGE_CONSTANT){
					menu.pickFridgeSetting();
				}
				else if(mode == MODE_BEER_PROFILE){
					piLink.printBeerAnnotation(PSTR("Changed to profile mode in menu."));
				}
				else if(mode == MODE_OFF){
					piLink.printBeerAnnotation(PSTR("Temp control turned off in menu."));
				}
				return;
			}
		}
		else{
			if(blinkTimer == 0){
				display.printMode();
			}
			if(blinkTimer == 128){
				display.printAt_P(7, 0, STR_SPACES_END-13);
			}
			blinkTimer++;
			wait.millis(3); // delay for blinking
		}
	}
	// Time Out. Restore original setting
	tempControl.setMode(oldSetting);
}

typedef void (* PrintAnnotation)(const char * annotation, ...);
typedef void (* DisplayUpdate)(void);
typedef fixed7_9 (* ReadTemp)();
typedef void (* WriteTemp)(fixed7_9);

void pickTempSetting(ReadTemp readTemp, WriteTemp writeTemp, const char* tempName, DisplayUpdate update, PrintAnnotation printAnnoation, int row) {
	display.printStationaryText(); // restore original text after blinking
	fixed7_9 oldSetting = readTemp();
	menu.initRotaryWithTemp(oldSetting);

	uint8_t blinkTimer = 0;
	uint8_t lastChangeTime = ticks.seconds();
	while(ticks.timeSince(lastChangeTime) < MENU_TIMEOUT){ // time out at 10 seconds
		if(rotaryEncoder.changed()){
			lastChangeTime = ticks.seconds();
			blinkTimer = 0;

			writeTemp(tenthsToFixed(rotaryEncoder.read()));
			update();

			if( rotaryEncoder.pushed() ){
				rotaryEncoder.resetPushed();
				char tempString[9];
				printAnnoation(PSTR("%S temp set to %s in Menu."), tempName, tempToString(tempString,readTemp(),1,9));
				return;
			}
		}
		else{
			if(blinkTimer == 0){
				update();
			}
			if(blinkTimer == 128){
				display.printAt_P(12, row, STR_SPACES_END-5);
			}
			blinkTimer++;
			wait.millis(3); // delay for blinking
		}
	}
	// Time Out. Restore original setting
	writeTemp(oldSetting);

}

void Menu::pickFridgeSetting(void){
	pickTempSetting(tempControl.getFridgeSetting, tempControl.setFridgeTemp, PSTR("Fridge"), display.printFridgeSet, piLink.printFridgeAnnotation, 2);
}

void Menu::pickBeerSetting(void){
	pickTempSetting(tempControl.getBeerSetting, tempControl.setBeerTemp, PSTR("Beer"), display.printBeerSet, piLink.printBeerAnnotation, 1);
}

#endif<commit_msg>menu optimizations saves 50 bytes<commit_after>/*
 * Copyright 2012 BrewPi/Elco Jacobs.
 *
 * This file is part of BrewPi.
 *
 * BrewPi is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * BrewPi is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with BrewPi.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "Brewpi.h"
#include "BrewpiStrings.h"

#if BREWPI_MENU

#include "Menu.h"

#include <limits.h>
#include "Pins.h"
#include "Display.h"
#include "TempControl.h"
#include "TemperatureFormats.h"
#include "RotaryEncoder.h"
#include "PiLink.h"
#include "Ticks.h"

Menu menu;

#define MENU_OPTIMIZE 1

#define MENU_TIMEOUT 10u

void Menu::pickSettingToChange(){
	// ensure beer temp is displayed
	uint8_t flags = display.getDisplayFlags();
	display.setDisplayFlags(flags &= ~(LCD_FLAG_ALTERNATE_ROOM|LCD_FLAG_DISPLAY_ROOM));
	pickSettingToChangeLoop();
	display.setDisplayFlags(flags);
}

#if MENU_OPTIMIZE
/**
 * @return {@code true} if a value was selected. {@code false} on timeout.
 */
bool blinkLoop(
	void (*changed)(),	// called to update the value
	void (*show)(),		// called to show the current value
	void (*blink)(),	// called to blank out the current value
	void (*pushed)())	// handle selection
{
	uint16_t lastChangeTime = ticks.seconds();
	uint8_t blinkTimer = 0;

	while(ticks.timeSince(lastChangeTime) < MENU_TIMEOUT){ // time out at 10 seconds
		if(rotaryEncoder.changed()){
			lastChangeTime = ticks.seconds();
			blinkTimer = 0;
			changed();
		}
		if (blinkTimer==0)
			show();
		else if (blinkTimer==128)
			blink();

		if (rotaryEncoder.pushed()) {
			rotaryEncoder.resetPushed();
			show();
			pushed();
			return true;
		}

		blinkTimer++;
		wait.millis(3); // delay for blinking
	}
	return false;
}

void clearSettingText() {
	display.printAt_P(0, rotaryEncoder.read(), STR_SPACES_END-6);
}

void settingChanged() {} // no -op - the only change is to update the display which happens already

void settingSelected() {
	switch(rotaryEncoder.read()){
		case 0:
			menu.pickMode();
			return;
		case 1:
			// switch to beer constant, because beer setting will be set through display
			tempControl.setMode(MODE_BEER_CONSTANT);
			display.printMode();
			menu.pickBeerSetting();
			return;
		case 2:
			// switch to fridge constant, because fridge setting will be set through display
			tempControl.setMode(MODE_FRIDGE_CONSTANT);
			display.printMode();
			menu.pickFridgeSetting();
			return;
	}
}

void Menu::pickSettingToChangeLoop(void) {
	rotaryEncoder.setRange(0, 0, 2); // mode setting, beer temp, fridge temp
	blinkLoop(
		settingChanged,
		display.printStationaryText,
		clearSettingText,
		settingSelected
	);
}

void changedMode() {
	const char lookup[] = {'b', 'f', 'p', 'o'};
	tempControl.setMode(lookup[rotaryEncoder.read()]);
}

void clearMode() {
	display.printAt_P(7, 0, STR_SPACES_END-13);
}

void selectMode() {
	char mode = tempControl.getMode();
	if(mode ==  MODE_BEER_CONSTANT){
		menu.pickBeerSetting();
	}
	else if(mode == MODE_FRIDGE_CONSTANT){
		menu.pickFridgeSetting();
	}
	else if(mode == MODE_BEER_PROFILE){
		piLink.printBeerAnnotation(PSTR("Changed to profile mode in menu."));
	}
	else if(mode == MODE_OFF){
		piLink.printBeerAnnotation(PSTR("Temp control turned off in menu."));
	}
}

void Menu::pickMode(void) {
	char oldSetting = tempControl.getMode();
	uint8_t startValue=0;
	const char* LOOKUP = "bfpo";
	startValue = indexOf(LOOKUP, oldSetting);
	rotaryEncoder.setRange(startValue, 0, 3); // toggle between beer constant, beer profile, fridge constant

	if (!blinkLoop(changedMode, display.printMode, clearMode, selectMode))
		tempControl.setMode(oldSetting);
}

#else
void Menu::pickSettingToChangeLoop(void){

	rotaryEncoder.setRange(0, 0, 2); // mode setting, beer temp, fridge temp
	uint16_t lastChangeTime = ticks.seconds();
	uint8_t blinkTimer = 0;
	while(ticks.timeSince(lastChangeTime) < MENU_TIMEOUT){ // time out at 10 seconds
		if(rotaryEncoder.changed()){
			lastChangeTime = ticks.seconds();
			blinkTimer = 0;
		}
		if(blinkTimer == 0){
			// print all text again for blinking
			display.printStationaryText();
		}
		if(blinkTimer == 128){ // blink one of the options by overwriting it with spaces
			display.printAt_P(0, rotaryEncoder.read(), STR_SPACES_END-6);
		}
		if( rotaryEncoder.pushed() ){
			rotaryEncoder.resetPushed();
			switch(rotaryEncoder.read()){
				case 0:
					pickMode();
					return;
				case 1:
					// switch to beer constant, because beer setting will be set through display
					tempControl.setMode(MODE_BEER_CONSTANT);
					display.printMode();
					pickBeerSetting();
					return;
				case 2:
					// switch to fridge constant, because fridge setting will be set through display
					tempControl.setMode(MODE_FRIDGE_CONSTANT);
					display.printMode();
					pickFridgeSetting();
					return;
			}
		}

		blinkTimer++;
		wait.millis(3); // delay for blinking
	}
}

const char* LOOKUP = "bfpo";

void Menu::pickMode(void){
	display.printStationaryText(); // restore original text after blinking 'Mode'
	char oldSetting = tempControl.getMode();
	uint8_t startValue=0;
	startValue = indexOf(LOOKUP, oldSetting);
	rotaryEncoder.setRange(startValue, 0, 3); // toggle between beer constant, beer profile, fridge constant
	const char lookup[] = {'b', 'f', 'p', 'o'};
	uint8_t blinkTimer = 0;
	uint16_t lastChangeTime = ticks.seconds();
	while(ticks.timeSince(lastChangeTime) < MENU_TIMEOUT){ // time out at 10 seconds
		if(rotaryEncoder.changed()){
			lastChangeTime = ticks.seconds();
			blinkTimer = 0;

			tempControl.setMode(lookup[rotaryEncoder.read()]);
			display.printMode();

			if( rotaryEncoder.pushed() ){
				rotaryEncoder.resetPushed();
				char mode = tempControl.getMode();
				if(mode ==  MODE_BEER_CONSTANT){
					menu.pickBeerSetting();
				}
				else if(mode == MODE_FRIDGE_CONSTANT){
					menu.pickFridgeSetting();
				}
				else if(mode == MODE_BEER_PROFILE){
					piLink.printBeerAnnotation(PSTR("Changed to profile mode in menu."));
				}
				else if(mode == MODE_OFF){
					piLink.printBeerAnnotation(PSTR("Temp control turned off in menu."));
				}
				return;
			}
		}
		else{
			if(blinkTimer == 0){
				display.printMode();
			}
			if(blinkTimer == 128){
				display.printAt_P(7, 0, STR_SPACES_END-13);
			}
			blinkTimer++;
			wait.millis(3); // delay for blinking
		}
	}
	// Time Out. Restore original setting
	tempControl.setMode(oldSetting);
}
#endif

typedef void (* PrintAnnotation)(const char * annotation, ...);
typedef void (* DisplayUpdate)(void);
typedef fixed7_9 (* ReadTemp)();
typedef void (* WriteTemp)(fixed7_9);

void pickTempSetting(ReadTemp readTemp, WriteTemp writeTemp, const char* tempName, DisplayUpdate update, PrintAnnotation printAnnoation, int row) {
	display.printStationaryText(); // restore original text after blinking
	fixed7_9 oldSetting = readTemp();
	fixed7_9 startVal = oldSetting;
	if(oldSetting == INT_MIN)	 // previous temperature was not defined, start at 20C
		startVal = 20*512;

	rotaryEncoder.setRange(fixedToTenths(startVal), fixedToTenths(tempControl.cc.tempSettingMin), fixedToTenths(tempControl.cc.tempSettingMax));

	uint8_t blinkTimer = 0;
	uint8_t lastChangeTime = ticks.seconds();
	while(ticks.timeSince(lastChangeTime) < MENU_TIMEOUT){ // time out at 10 seconds
		if(rotaryEncoder.changed()){
			lastChangeTime = ticks.seconds();
			blinkTimer = 0;

			writeTemp(tenthsToFixed(rotaryEncoder.read()));
			update();

			if( rotaryEncoder.pushed() ){
				rotaryEncoder.resetPushed();
				char tempString[9];
				printAnnoation(PSTR("%S temp set to %s in Menu."), tempName, tempToString(tempString,readTemp(),1,9));
				return;
			}
	}
		else{
			if(blinkTimer == 0){
				update();
			}
			if(blinkTimer == 128){
				display.printAt_P(12, row, STR_SPACES_END-5);
			}
			blinkTimer++;
			wait.millis(3); // delay for blinking
		}
	}
	// Time Out. Restore original setting
	writeTemp(oldSetting);
}

void Menu::pickFridgeSetting(void){
	pickTempSetting(tempControl.getFridgeSetting, tempControl.setFridgeTemp, PSTR("Fridge"), display.printFridgeSet, piLink.printFridgeAnnotation, 2);
}

void Menu::pickBeerSetting(void){
	pickTempSetting(tempControl.getBeerSetting, tempControl.setBeerTemp, PSTR("Beer"), display.printBeerSet, piLink.printBeerAnnotation, 1);
}

#endif<|endoftext|>


<commit_before>//! \file **************************************************************
//! \brief Source notification.
//!
//! - Compilateur : GCC,MinGW
//!
//! \author Antoine Maleyrie
//! \version 0.3
//! \date 12.04.2013
//!
//! ********************************************************************

/*
*	Copyright © 2013 - Antoine Maleyrie.
*/

#include "notification.hpp"

#include <wx/log.h>
#include <wx/intl.h>

#ifndef USE_EMULATE_NOTIFICATION
	//Sous unix on utilise la libnotify
	#if defined(__UNIX__)
		#include <libnotify/notify.h>
	//Pour les autres os on utilise les notifications de wxWidgets
	#else
		#include <wx/notifmsg.h>
	#endif
#endif

//TEST
#include <iostream>

// *********************************************************************
// Class FrameNotification
// *********************************************************************

#if defined(USE_EMULATE_NOTIFICATION) || defined(__DOXYGEN__)

DialogNotification::DialogNotification(	wxString const& title,
										wxString const& message)
: GuiDialogNotification(nullptr, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxFRAME_NO_TASKBAR|wxDIALOG_NO_PARENT|wxSTAY_ON_TOP|wxNO_BORDER),
_timeout(this)
{
	//Affiche le titre et le message.
	_staticTextTitle->SetLabelMarkup(""+title+"");
	_staticTextMessage->SetLabel(message);

	//Recalcule de la tille de la fenêtre.
	this->Layout();
	GetSizer()->Fit(this);

	//Pour ne pas redimensionner la fenêtre.
	this->SetSizeHints(GetSize(), GetSize());

	//Bind du timer pour le timeout
	Bind(wxEVT_TIMER, &DialogNotification::OnTimeout, this);
}

DialogNotification::~DialogNotification()
{
	//Unbind du timer pour le timeout
	Unbind(wxEVT_TIMER, &DialogNotification::OnTimeout, this);
}

void DialogNotification::show(int timeout)
{
	ShowWithoutActivating();
	_timeout.Start(timeout*1000, wxTIMER_ONE_SHOT);
}

void DialogNotification::OnClose(wxCloseEvent&)
{
	//Qui la notification
	exit();
}

void DialogNotification::OnLeftDown(wxMouseEvent&)
{
	//Qui la notification
	exit();
}

void DialogNotification::OnTimeout(wxTimerEvent&)
{
	//Qui la notification
	exit();
}

void DialogNotification::exit()
{
	//Envoi de l'événement.
	wxCommandEvent event(EVT_EXIT_DIALG_NOTIFICATION, GetId());
    event.SetEventObject(this);
    ProcessWindowEvent(event);
}

wxDEFINE_EVENT(EVT_EXIT_DIALG_NOTIFICATION, wxCommandEvent);

#endif

// *********************************************************************
// Class Notification
// *********************************************************************
//! \todo a instenser/supprimer dans main.cpp
Notification::Notification()
{
	#ifndef USE_EMULATE_NOTIFICATION
		//Sous unix on utilise la libnotify
		#if defined(__UNIX__)
			if(!notify_init(PROJECT_NAME))
			{
				wxLogError(_("Libnotify could not be initialized."));
			}
		#endif
	#endif
}

Notification::~Notification()
{
	#ifndef USE_EMULATE_NOTIFICATION
		//Sous unix on utilise la libnotify
		#if defined(__UNIX__)
			notify_uninit();
		#endif
	#else
		//On détruis les dialogues
		for(auto it : _dialogs)
		{
			it->Destroy();
			delete it;
		}
	#endif
}

void Notification::notify(	wxString const& title,
							wxString const& message)
{
	//3s par défaut + 1s de plus tout les 10 caractères.
	int timeout = 3+message.Length()/10;

	#ifndef USE_EMULATE_NOTIFICATION
		#if define(__UNIX__)
			//Préparation de la notification.
			NotifyNotification * notify = notify_notification_new(title.mb_str(wxConvUTF8), message.fn_str(), "dialog-information");
			notify_notification_set_timeout(notify, timeout*1000);

			//Affichage de la notification
			if(!notify_notification_show(notify, nullptr))
			{
				//Si problème
				wxLogError(_("The notify could not be show."));
			}
		#else
			//Préparation de la notification.
			wxNotificationMessage notify(title, message);
			//Affichage de la notification
			notify.Show(timeout);
		#endif
	#else
		DialogNotification *dialog = new DialogNotification(title, message);

		if(_dialogs.size() != 0)
		{
			int positionY = 0;
			int sizeY = 0;
			DialogNotification *lastDialog = _dialogs.back();

			lastDialog->GetPosition(nullptr, &positionY);
			lastDialog->GetSize(nullptr, &sizeY);

			dialog->SetPosition(wxPoint(0, positionY+sizeY));
		}
		else
		{
			dialog->SetPosition(wxPoint(0, 0));
		}

		_dialogs.push_back(dialog);
		dialog->Bind(EVT_EXIT_DIALG_NOTIFICATION, &Notification::OnExitDialogNotification, this);
		dialog->show(timeout);
	#endif
}

#ifdef USE_EMULATE_NOTIFICATION

void Notification::OnExitDialogNotification(wxCommandEvent& event)
{
	//Obtenir le dialogue qui provoquer l'événement.
	DialogNotification* dialog = static_cast<DialogNotification*>(event.GetEventObject());

	//Unbind le dialogue
	dialog->Unbind(EVT_EXIT_DIALG_NOTIFICATION, &Notification::OnExitDialogNotification, this);

	int iDialog = -1;
	int sizeY = 0;

	//On sauvegarde le décalage que l'on doit affecter au dialogue qui doive être décaler.
	dialog->GetSize(nullptr, &sizeY);

	//Parcoure tout les dialogues actifs
	for(unsigned int i = 0; i<_dialogs.size(); i++)
	{
		//Si le dialogue a été trouver
		if(iDialog != -1)
		{
			//On décale les dialogue qui doive changer de position
			wxPoint pos = _dialogs[i]->GetPosition();
			pos.y -= sizeY;
			_dialogs[i]->SetPosition(pos);
		}
		//c'est le dialogue que l'on cherche ?
		else if(_dialogs[i] == dialog)
		{
			//On retiens sont index dans le vector
			iDialog = i;
		}
	}

	//On détruis le dialogue
	_dialogs[iDialog]->Destroy();
	delete _dialogs[iDialog];
	//Et on l'enlève du vector
	_dialogs.erase(_dialogs.begin()+iDialog);
}

#endif
<commit_msg>limited a number notification<commit_after>//! \file **************************************************************
//! \brief Source notification.
//!
//! - Compilateur : GCC,MinGW
//!
//! \author Antoine Maleyrie
//! \version 0.3
//! \date 12.04.2013
//!
//! ********************************************************************

/*
*	Copyright © 2013 - Antoine Maleyrie.
*/

#include "notification.hpp"

#include <wx/log.h>
#include <wx/intl.h>

#ifndef USE_EMULATE_NOTIFICATION
	//Sous unix on utilise la libnotify
	#if defined(__UNIX__)
		#include <libnotify/notify.h>
	//Pour les autres os on utilise les notifications de wxWidgets
	#else
		#include <wx/notifmsg.h>
	#endif
#else
	#include <wx/gdicmn.h>
#endif

//TEST
#include <iostream>

// *********************************************************************
// Class FrameNotification
// *********************************************************************

#if defined(USE_EMULATE_NOTIFICATION) || defined(__DOXYGEN__)

DialogNotification::DialogNotification(	wxString const& title,
										wxString const& message)
: GuiDialogNotification(nullptr, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxFRAME_NO_TASKBAR|wxDIALOG_NO_PARENT|wxSTAY_ON_TOP|wxNO_BORDER),
_timeout(this)
{
	//Affiche le titre et le message.
	_staticTextTitle->SetLabelMarkup(""+title+"");
	_staticTextMessage->SetLabel(message);

	//Recalcule de la tille de la fenêtre.
	this->Layout();
	GetSizer()->Fit(this);

	//Pour ne pas redimensionner la fenêtre.
	this->SetSizeHints(GetSize(), GetSize());

	//Bind du timer pour le timeout
	Bind(wxEVT_TIMER, &DialogNotification::OnTimeout, this);
}

DialogNotification::~DialogNotification()
{
	//Unbind du timer pour le timeout
	Unbind(wxEVT_TIMER, &DialogNotification::OnTimeout, this);
}

void DialogNotification::show(int timeout)
{
	ShowWithoutActivating();
	_timeout.Start(timeout*1000, wxTIMER_ONE_SHOT);
}

void DialogNotification::OnClose(wxCloseEvent&)
{
	//Qui la notification
	exit();
}

void DialogNotification::OnLeftDown(wxMouseEvent&)
{
	//Qui la notification
	exit();
}

void DialogNotification::OnTimeout(wxTimerEvent&)
{
	//Qui la notification
	exit();
}

void DialogNotification::exit()
{
	//Envoi de l'événement.
	wxCommandEvent event(EVT_EXIT_DIALG_NOTIFICATION, GetId());
    event.SetEventObject(this);
    ProcessWindowEvent(event);
}

wxDEFINE_EVENT(EVT_EXIT_DIALG_NOTIFICATION, wxCommandEvent);

#endif

// *********************************************************************
// Class Notification
// *********************************************************************
//! \todo a instenser/supprimer dans main.cpp
Notification::Notification()
{
	#ifndef USE_EMULATE_NOTIFICATION
		//Sous unix on utilise la libnotify
		#if defined(__UNIX__)
			if(!notify_init(PROJECT_NAME))
			{
				wxLogError(_("Libnotify could not be initialized."));
			}
		#endif
	#endif
}

Notification::~Notification()
{
	#ifndef USE_EMULATE_NOTIFICATION
		//Sous unix on utilise la libnotify
		#if defined(__UNIX__)
			notify_uninit();
		#endif
	#else
		//On détruis les dialogues
		for(auto it : _dialogs)
		{
			it->Destroy();
			delete it;
		}
	#endif
}

void Notification::notify(	wxString const& title,
							wxString const& message)
{
	//3s par défaut + 1s de plus tout les 10 caractères.
	int timeout = 3+message.Length()/10;

	#ifndef USE_EMULATE_NOTIFICATION
		#if define(__UNIX__)
			//Préparation de la notification.
			NotifyNotification * notify = notify_notification_new(title.mb_str(wxConvUTF8), message.fn_str(), "dialog-information");
			notify_notification_set_timeout(notify, timeout*1000);

			//Affichage de la notification
			if(!notify_notification_show(notify, nullptr))
			{
				//Si problème
				wxLogError(_("The notify could not be show."));
			}
		#else
			//Préparation de la notification.
			wxNotificationMessage notify(title, message);
			//Affichage de la notification
			notify.Show(timeout);
		#endif
	#else
		DialogNotification *dialog = new DialogNotification(title, message);

		if(_dialogs.size() != 0)
		{
			int positionY = 0;
			int sizeY = 0;
			DialogNotification *lastDialog = _dialogs.back();

			lastDialog->GetPosition(nullptr, &positionY);
			lastDialog->GetSize(nullptr, &sizeY);

			dialog->SetPosition(wxPoint(0, positionY+sizeY));
		}
		else
		{
			dialog->SetPosition(wxPoint(0, 0));
		}

		_dialogs.push_back(dialog);
		dialog->Bind(EVT_EXIT_DIALG_NOTIFICATION, &Notification::OnExitDialogNotification, this);
		dialog->show(timeout);

		if(_dialogs.size() != 0)
		{
			int positionY = 0;
			int sizeY = 0;
			int displayY = 0;

			wxDisplaySize(nullptr, &displayY);
			dialog->GetPosition(nullptr, &positionY);
			dialog->GetSize(nullptr, &sizeY);

			if(positionY+sizeY > displayY)
			{
				_dialogs[0]->exit();
			}
		}
	#endif
}

#ifdef USE_EMULATE_NOTIFICATION

void Notification::OnExitDialogNotification(wxCommandEvent& event)
{
	//Obtenir le dialogue qui provoquer l'événement.
	DialogNotification* dialog = static_cast<DialogNotification*>(event.GetEventObject());

	//Unbind le dialogue
	dialog->Unbind(EVT_EXIT_DIALG_NOTIFICATION, &Notification::OnExitDialogNotification, this);

	int iDialog = -1;
	int sizeY = 0;

	//On sauvegarde le décalage que l'on doit affecter au dialogue qui doive être décaler.
	dialog->GetSize(nullptr, &sizeY);

	//Parcoure tout les dialogues actifs
	for(unsigned int i = 0; i<_dialogs.size(); i++)
	{
		//Si le dialogue a été trouver
		if(iDialog != -1)
		{
			//On décale les dialogue qui doive changer de position
			wxPoint pos = _dialogs[i]->GetPosition();
			pos.y -= sizeY;
			_dialogs[i]->SetPosition(pos);
		}
		//c'est le dialogue que l'on cherche ?
		else if(_dialogs[i] == dialog)
		{
			//On retiens sont index dans le vector
			iDialog = i;
		}
	}

	//On détruis le dialogue
	_dialogs[iDialog]->Destroy();
	delete _dialogs[iDialog];
	//Et on l'enlève du vector
	_dialogs.erase(_dialogs.begin()+iDialog);
}

#endif
<|endoftext|>


<commit_before>/**
 ** \file object/system-class.cc
 ** \brief Creation of the URBI object system.
 */

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include <memory>
#include <sstream>

#include <kernel/userver.hh>
#include <kernel/uconnection.hh>

#include <object/code.hh>
#include <object/dictionary.hh>
#include <object/float.hh>
#include <object/list.hh>
#include <object/system.hh>
#include <object/tag.hh>
#include <object/task.hh>

#include <parser/transform.hh>

#include <runner/at-handler.hh>
#include <runner/runner.hh>
#include <runner/interpreter.hh>

#include <ast/nary.hh>
#include <ast/routine.hh>

namespace object
{

  rObject
  execute_parsed(runner::Runner& r,
                 parser::parse_result_type p,
                 libport::Symbol fun, UrbiException e)
  {
    runner::Interpreter& run = dynamic_cast<runner::Interpreter&>(r);

    // Report potential errors
    {
      ast::rNary errs = new ast::Nary();
      p->process_errors(*errs);
      run(errs.get());
    }

    ast::rConstAst ast = parser::transform(p->ast_get());
    if (!ast)
      throw e;

    runner::Interpreter* sub = new runner::Interpreter(run, ast, fun);
    // So that it will resist to the call to yield_until_terminated,
    // and will be reclaimed at the end of the scope.
    scheduler::rJob job = sub;
    run.link(job);
    sub->start_job();
    run.yield_until_terminated(*job);
    return sub->result_get();
  }

  rObject system_class;

  /*--------------------.
  | System primitives.  |
  `--------------------*/

#define SERVER_FUNCTION(Function)					\
  static rObject							\
  system_class_ ## Function (runner::Runner&, objects_type args)	\
  {									\
    CHECK_ARG_COUNT (1);						\
    ::urbiserver->Function();						\
    return void_class;							\
  }

  SERVER_FUNCTION(reboot)
  SERVER_FUNCTION(shutdown)

#undef SERVER_FUNCTION

  static rObject
  system_class_sleep (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (2);
    type_check<Float>(args[1], SYMBOL(sleep));
    rFloat arg1 = args[1]->as<Float>();
    libport::utime_t deadline;
    if (arg1->value_get() == std::numeric_limits<ufloat>::infinity())
      deadline = std::numeric_limits<libport::utime_t>::max();
    else
      deadline = r.scheduler_get().get_time() +
	static_cast<libport::utime_t>(arg1->value_get() * 1000.0);
    r.yield_until (deadline);
    return void_class;
  }

  static rObject
  system_class_time(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return new Float(r.scheduler_get().get_time() / 1000.0);
  }

  static rObject
  system_class_shiftedTime(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return new Float((r.scheduler_get().get_time() -
			  r.time_shift_get()) / 1000.0);
  }

  static rObject
  system_class_assert_(runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT(3);
    type_check<String>(args[2], SYMBOL(assert_UL));
    rString arg2 = args[2]->as<String>();
    if (!is_true(args[1], SYMBOL(assert_UL)))
      throw PrimitiveError
	(SYMBOL(assert_UL),
	 "assertion `" + arg2->value_get() + "' failed");
    return void_class;
  }

  static rObject
  system_class_eval(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(2);
    type_check<String>(args[1], SYMBOL(eval));
    rString arg1 = args[1]->as<String>();
    return
      execute_parsed(r, parser::parse(arg1->value_get()),
                     SYMBOL(eval),
                     PrimitiveError(SYMBOL(eval),
                                    "error executing command: "
                                    + arg1->value_get()));
  }

  static rObject
  system_class_registerAtJob (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(4);
    runner::register_at_job(dynamic_cast<runner::Interpreter&>(r),
			    args[1], args[2], args[3]);
    return object::void_class;
  }

  static rObject
  system_class_scopeTag(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(1);
    const scheduler::rTag& scope_tag =
      dynamic_cast<runner::Interpreter&>(r).scope_tag();
    return new Tag(scope_tag);
  }

  static rObject
  system_class_searchFile (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (2);
    type_check<String>(args[1], SYMBOL(assert));
    const rString& arg1 = args[1]->as<String>();

    UServer& s = r.lobby_get()->value_get().connection.server_get();
    try
    {
      return new String(s.find_file(arg1->value_get()));
    }
    catch (libport::file_library::Not_found&)
    {
      throw
	PrimitiveError(SYMBOL(searchFile),
		       "Unable to find file: "
		       + arg1->value_get());
      // Never reached
      assertion(false);
      return 0;
    }
  }

  static rObject
  system_class_loadFile(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(2);
    type_check<String>(args[1], SYMBOL(assert));
    const rString& arg1 = args[1]->as<String>();

    const std::string& filename = arg1->value_get();

    if (!libport::path(filename).exists())
      throw PrimitiveError(SYMBOL(loadFile),
			   "No such file: " + filename);
    return
      execute_parsed(r, parser::parse_file(filename),
                     SYMBOL(loadFile),
                     PrimitiveError(SYMBOL(loadFile),
                                    "error loading file: " + filename));
  }

  static rObject
  system_class_currentRunner (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return new Task(&r);
  }

  static rObject
  system_class_cycle (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return new Float(r.scheduler_get ().cycle_get ());
  }

  static rObject
  system_class_fresh (runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return new String(libport::Symbol::fresh());
  }

  static rObject
  system_class_lobby (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return r.lobby_get();
  }

  static rObject
  system_class_nonInterruptible (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    r.non_interruptible_set (true);
    return void_class;
  }

  static rObject
  system_class_quit (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    r.lobby_get()->value_get().connection.close();
    return void_class;
  }

  static rObject
  system_class_spawn(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT_RANGE (2, 3, SYMBOL(spawn));
    rObject arg1 = args[1]->as<Code>();
    assert(arg1);

    runner::Interpreter* new_runner =
      new runner::Interpreter (dynamic_cast<runner::Interpreter&>(r),
			       rObject(arg1));
    new_runner->copy_tags (r);
    new_runner->time_shift_set (r.time_shift_get ());

    if (args.size () == 3)
    {
      if (is_true (args[2], SYMBOL(spawn)))
	r.link (new_runner);
    }

    new_runner->start_job ();

    return object::void_class;
  }

  static rObject
  system_class_stats(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(1);
    Dictionary::value_type res;
    const scheduler::scheduler_stats_type& stats =
      r.scheduler_get().stats_get();
    // The space after "Symbol(" is mandatory to avoid triggering an error in
    // symbol generation code
#define ADDSTAT(Suffix, Function, Divisor)				\
    res[libport::Symbol( "cycles" # Suffix)] = new Float(stats.Function() / Divisor)
    ADDSTAT(, samples, 1);
    ADDSTAT(Max, max, 1000.0);
    ADDSTAT(Mean, mean, 1000.0);
    ADDSTAT(Min, min, 1000.0);
    ADDSTAT(StdDev, standard_deviation, 1000.0);
    ADDSTAT(Variance, variance, 1000.0);
#undef ADDSTAT
    return new Dictionary(res);
  }

  // This should give a backtrace as an urbi object.
  static rObject
  system_class_backtrace(runner::Runner& r, objects_type args)
  {
    // FIXME: This method sucks a bit, because show_backtrace sucks a
    // bit, because our channeling/message-sending system sucks a lot.
    CHECK_ARG_COUNT (1);
    runner::Runner::backtrace_type bt = r.backtrace_get();
    bt.pop_back();
    foreach (const runner::Runner::frame_type& elt,
	     boost::make_iterator_range(boost::rbegin(bt),
					boost::rend(bt)))
      r.send_message("backtrace", elt.first + " (" + elt.second + ")");
    return void_class;
  }

  static rObject
  system_class_jobs(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(1);
    List::value_type res;
    foreach(scheduler::rJob job, r.scheduler_get().jobs_get())
      res.push_back(new Task(job));
    return new List(res);
  }

  static rObject
  system_class_breakpoint(runner::Runner&, objects_type)
  {
    return void_class;
  }

#define SERVER_SET_VAR(Function, Variable, Value)			\
  static rObject							\
  system_class_ ## Function (runner::Runner&, objects_type args)	\
  {									\
    CHECK_ARG_COUNT (1);						\
    ::urbiserver->Variable = Value;					\
    return void_class;							\
  }

  SERVER_SET_VAR(debugoff, debugOutput, false)
  SERVER_SET_VAR(debugon, debugOutput, true)
  SERVER_SET_VAR(stopall, stopall, true)

#undef SERVER_SET_VAR

  void
  system_class_initialize ()
  {
    /// \a Call gives the name of the C++ function, and \a Name that in Urbi.
#define DECLARE(Name)				\
    DECLARE_PRIMITIVE(system, Name)

    DECLARE(assert_);
    DECLARE(backtrace);
    DECLARE(breakpoint);
    DECLARE(currentRunner);
    DECLARE(cycle);
    DECLARE(debugoff);
    DECLARE(debugon);
    DECLARE(eval);
    DECLARE(fresh);
    DECLARE(jobs);
    DECLARE(loadFile);
    DECLARE(lobby);
    DECLARE(nonInterruptible);
    DECLARE(quit);
    DECLARE(reboot);
    DECLARE(registerAtJob);
    DECLARE(scopeTag);
    DECLARE(searchFile);
    DECLARE(shiftedTime);
    DECLARE(stats);
    DECLARE(shutdown);
    DECLARE(sleep);
    DECLARE(spawn);
    DECLARE(stopall);
    DECLARE(time);
#undef DECLARE
  }

}; // namespace object
<commit_msg>Add environment access functions.<commit_after>/**
 ** \file object/system-class.cc
 ** \brief Creation of the URBI object system.
 */

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include <memory>
#include <sstream>

#include <kernel/userver.hh>
#include <kernel/uconnection.hh>

#include <object/code.hh>
#include <object/cxx-primitive.hh>
#include <object/dictionary.hh>
#include <object/float.hh>
#include <object/list.hh>
#include <object/system.hh>
#include <object/tag.hh>
#include <object/task.hh>

#include <parser/transform.hh>

#include <runner/at-handler.hh>
#include <runner/call.hh>
#include <runner/interpreter.hh>
#include <runner/runner.hh>

#include <ast/nary.hh>
#include <ast/routine.hh>

namespace object
{

  rObject
  execute_parsed(runner::Runner& r,
                 parser::parse_result_type p,
                 libport::Symbol fun, UrbiException e)
  {
    runner::Interpreter& run = dynamic_cast<runner::Interpreter&>(r);

    // Report potential errors
    {
      ast::rNary errs = new ast::Nary();
      p->process_errors(*errs);
      run(errs.get());
    }

    ast::rConstAst ast = parser::transform(p->ast_get());
    if (!ast)
      throw e;

    runner::Interpreter* sub = new runner::Interpreter(run, ast, fun);
    // So that it will resist to the call to yield_until_terminated,
    // and will be reclaimed at the end of the scope.
    scheduler::rJob job = sub;
    run.link(job);
    sub->start_job();
    run.yield_until_terminated(*job);
    return sub->result_get();
  }

  rObject system_class;

  /*--------------------.
  | System primitives.  |
  `--------------------*/

#define SERVER_FUNCTION(Function)					\
  static rObject							\
  system_class_ ## Function (runner::Runner&, objects_type args)	\
  {									\
    CHECK_ARG_COUNT (1);						\
    ::urbiserver->Function();						\
    return void_class;							\
  }

  SERVER_FUNCTION(reboot)
  SERVER_FUNCTION(shutdown)

#undef SERVER_FUNCTION

  static rObject
  system_class_sleep (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (2);
    type_check<Float>(args[1], SYMBOL(sleep));
    rFloat arg1 = args[1]->as<Float>();
    libport::utime_t deadline;
    if (arg1->value_get() == std::numeric_limits<ufloat>::infinity())
      deadline = std::numeric_limits<libport::utime_t>::max();
    else
      deadline = r.scheduler_get().get_time() +
	static_cast<libport::utime_t>(arg1->value_get() * 1000.0);
    r.yield_until (deadline);
    return void_class;
  }

  static rObject
  system_class_time(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return new Float(r.scheduler_get().get_time() / 1000.0);
  }

  static rObject
  system_class_shiftedTime(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return new Float((r.scheduler_get().get_time() -
			  r.time_shift_get()) / 1000.0);
  }

  static rObject
  system_class_assert_(runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT(3);
    type_check<String>(args[2], SYMBOL(assert_UL));
    rString arg2 = args[2]->as<String>();
    if (!is_true(args[1], SYMBOL(assert_UL)))
      throw PrimitiveError
	(SYMBOL(assert_UL),
	 "assertion `" + arg2->value_get() + "' failed");
    return void_class;
  }

  static rObject
  system_class_eval(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(2);
    type_check<String>(args[1], SYMBOL(eval));
    rString arg1 = args[1]->as<String>();
    return
      execute_parsed(r, parser::parse(arg1->value_get()),
                     SYMBOL(eval),
                     PrimitiveError(SYMBOL(eval),
                                    "error executing command: "
                                    + arg1->value_get()));
  }

  static rObject
  system_class_registerAtJob (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(4);
    runner::register_at_job(dynamic_cast<runner::Interpreter&>(r),
			    args[1], args[2], args[3]);
    return object::void_class;
  }

  static rObject
  system_class_scopeTag(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(1);
    const scheduler::rTag& scope_tag =
      dynamic_cast<runner::Interpreter&>(r).scope_tag();
    return new Tag(scope_tag);
  }

  static rObject
  system_class_searchFile (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (2);
    type_check<String>(args[1], SYMBOL(assert));
    const rString& arg1 = args[1]->as<String>();

    UServer& s = r.lobby_get()->value_get().connection.server_get();
    try
    {
      return new String(s.find_file(arg1->value_get()));
    }
    catch (libport::file_library::Not_found&)
    {
      throw
	PrimitiveError(SYMBOL(searchFile),
		       "Unable to find file: "
		       + arg1->value_get());
      // Never reached
      assertion(false);
      return 0;
    }
  }

  static rObject
  system_class_loadFile(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(2);
    type_check<String>(args[1], SYMBOL(assert));
    const rString& arg1 = args[1]->as<String>();

    const std::string& filename = arg1->value_get();

    if (!libport::path(filename).exists())
      throw PrimitiveError(SYMBOL(loadFile),
			   "No such file: " + filename);
    return
      execute_parsed(r, parser::parse_file(filename),
                     SYMBOL(loadFile),
                     PrimitiveError(SYMBOL(loadFile),
                                    "error loading file: " + filename));
  }

  static rObject
  system_class_currentRunner (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return new Task(&r);
  }

  static rObject
  system_class_cycle (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return new Float(r.scheduler_get ().cycle_get ());
  }

  static rObject
  system_class_fresh (runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return new String(libport::Symbol::fresh());
  }

  static rObject
  system_class_lobby (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return r.lobby_get();
  }

  static rObject
  system_class_nonInterruptible (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    r.non_interruptible_set (true);
    return void_class;
  }

  static rObject
  system_class_quit (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    r.lobby_get()->value_get().connection.close();
    return void_class;
  }

  static rObject
  system_class_spawn(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT_RANGE (2, 3, SYMBOL(spawn));
    rObject arg1 = args[1]->as<Code>();
    assert(arg1);

    runner::Interpreter* new_runner =
      new runner::Interpreter (dynamic_cast<runner::Interpreter&>(r),
			       rObject(arg1));
    new_runner->copy_tags (r);
    new_runner->time_shift_set (r.time_shift_get ());

    if (args.size () == 3)
    {
      if (is_true (args[2], SYMBOL(spawn)))
	r.link (new_runner);
    }

    new_runner->start_job ();

    return object::void_class;
  }

  static rObject
  system_class_stats(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(1);
    Dictionary::value_type res;
    const scheduler::scheduler_stats_type& stats =
      r.scheduler_get().stats_get();
    // The space after "Symbol(" is mandatory to avoid triggering an error in
    // symbol generation code
#define ADDSTAT(Suffix, Function, Divisor)				\
    res[libport::Symbol( "cycles" # Suffix)] = new Float(stats.Function() / Divisor)
    ADDSTAT(, samples, 1);
    ADDSTAT(Max, max, 1000.0);
    ADDSTAT(Mean, mean, 1000.0);
    ADDSTAT(Min, min, 1000.0);
    ADDSTAT(StdDev, standard_deviation, 1000.0);
    ADDSTAT(Variance, variance, 1000.0);
#undef ADDSTAT
    return new Dictionary(res);
  }

  // This should give a backtrace as an urbi object.
  static rObject
  system_class_backtrace(runner::Runner& r, objects_type args)
  {
    // FIXME: This method sucks a bit, because show_backtrace sucks a
    // bit, because our channeling/message-sending system sucks a lot.
    CHECK_ARG_COUNT (1);
    runner::Runner::backtrace_type bt = r.backtrace_get();
    bt.pop_back();
    foreach (const runner::Runner::frame_type& elt,
	     boost::make_iterator_range(boost::rbegin(bt),
					boost::rend(bt)))
      r.send_message("backtrace", elt.first + " (" + elt.second + ")");
    return void_class;
  }

  static rObject
  system_class_jobs(runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT(1);
    List::value_type res;
    foreach(scheduler::rJob job, r.scheduler_get().jobs_get())
      res.push_back(new Task(job));
    return new List(res);
  }

  static rObject
  system_class_breakpoint(runner::Runner&, objects_type)
  {
    return void_class;
  }

#define SERVER_SET_VAR(Function, Variable, Value)			\
  static rObject							\
  system_class_ ## Function (runner::Runner&, objects_type args)	\
  {									\
    CHECK_ARG_COUNT (1);						\
    ::urbiserver->Variable = Value;					\
    return void_class;							\
  }

  SERVER_SET_VAR(debugoff, debugOutput, false)
  SERVER_SET_VAR(debugon, debugOutput, true)
  SERVER_SET_VAR(stopall, stopall, true)

#undef SERVER_SET_VAR

  static rObject system_getenv(rObject, const std::string& name)
  {
    char* res = getenv(name.c_str());
    return res ? new String(res) : 0;
  }

  static rObject system_setenv(rObject, runner::Runner& r,
                               const std::string& name, rObject value)
  {
    rString v = urbi_call(r, value, SYMBOL(asString))->as<String>();
    setenv(name.c_str(), v->value_get().c_str(), 1);
    return v;
  }

  static rObject system_unsetenv(rObject, const std::string& name)
  {
    rObject res = system_getenv(0, name);
    unsetenv(name.c_str());
    return res;
  }

  void
  system_class_initialize ()
  {
#define DECLARE(Name)                                                   \
    system_class->slot_set                                              \
      (SYMBOL(Name),                                                    \
       make_primitive(&system_##Name, SYMBOL(Name)))                    \

    DECLARE(getenv);
    DECLARE(setenv);
    DECLARE(unsetenv);

#undef DECLARE

    /// \a Call gives the name of the C++ function, and \a Name that in Urbi.
#define DECLARE(Name)				\
    DECLARE_PRIMITIVE(system, Name)

    DECLARE(assert_);
    DECLARE(backtrace);
    DECLARE(breakpoint);
    DECLARE(currentRunner);
    DECLARE(cycle);
    DECLARE(debugoff);
    DECLARE(debugon);
    DECLARE(eval);
    DECLARE(fresh);
    DECLARE(jobs);
    DECLARE(loadFile);
    DECLARE(lobby);
    DECLARE(nonInterruptible);
    DECLARE(quit);
    DECLARE(reboot);
    DECLARE(registerAtJob);
    DECLARE(scopeTag);
    DECLARE(searchFile);
    DECLARE(shiftedTime);
    DECLARE(stats);
    DECLARE(shutdown);
    DECLARE(sleep);
    DECLARE(spawn);
    DECLARE(stopall);
    DECLARE(time);
#undef DECLARE
  }

}; // namespace object
<|endoftext|>


<commit_before>/**
 ** \file object/system-class.cc
 ** \brief Creation of the URBI object system.
 */

#include <ltdl.h>

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>
#include <libport/cstdlib>
#include <libport/program-name.hh>

#include <memory>
#include <sstream>

#include <kernel/uconnection.hh>
#include <kernel/uobject.hh>
#include <kernel/userver.hh>

#include <object/code.hh>
#include <object/cxx-primitive.hh>
#include <object/dictionary.hh>
#include <object/float.hh>
#include <object/global.hh>
#include <object/lobby.hh>
#include <object/list.hh>
#include <object/path.hh>
#include <object/primitives.hh>
#include <object/system.hh>
#include <object/tag.hh>
#include <object/task.hh>
#include <parser/transform.hh>
#include <runner/at-handler.hh>
#include <runner/interpreter.hh>
#include <runner/raise.hh>
#include <runner/runner.hh>

#include <ast/nary.hh>
#include <ast/routine.hh>

namespace object
{
  using kernel::urbiserver;

  static inline
  runner::Runner&
  runner()
  {
    return ::kernel::urbiserver->getCurrentRunner();
  }

  static inline
  runner::Interpreter&
  interpreter()
  {
    return dynamic_cast<runner::Interpreter&>(runner());
  }

  // Extract a filename from a String or a Path object
  static std::string
  filename_get(const rObject& o)
  {
    if (o.is_a<Path>())
      return o->as<Path>()->as_string();
    type_check<String>(o);
    return o->as<String>()->value_get();
  }

  rObject
  execute_parsed(parser::parse_result_type p,
                 libport::Symbol fun, std::string e)
  {
    runner::Interpreter& run = interpreter();

    // Report potential errors
    {
      ast::rNary errs = new ast::Nary();
      p->process_errors(*errs);
      run(errs.get());
    }

    ast::rConstAst ast = parser::transform(p->ast_get());
    if (!ast)
      runner::raise_primitive_error(e);

    runner::Interpreter* sub = new runner::Interpreter(run, ast, fun);
    // So that it will resist to the call to yield_until_terminated,
    // and will be reclaimed at the end of the scope.
    sched::rJob job = sub;
    libport::Finally finally;
    runner().register_child(sub, finally);
    sub->start_job();
    try
    {
      run.yield_until_terminated(*job);
    }
    catch (const sched::ChildException& ce)
    {
      // Kill the sub-job and propagate.
      ce.rethrow_child_exception();
    }
    return sub->result_get();
  }

  rObject system_class;

  /*--------------------.
  | System primitives.  |
  `--------------------*/

#define SERVER_FUNCTION(Function)               \
  static void                                   \
  system_ ## Function ()                        \
  {                                             \
    urbiserver->Function();                     \
  }

  SERVER_FUNCTION(reboot)
  SERVER_FUNCTION(shutdown)

#undef SERVER_FUNCTION

  static void
  system_sleep(const rObject&, libport::ufloat seconds)
  {
    runner::Runner& r = runner();
    if (seconds == std::numeric_limits<ufloat>::infinity())
      r.yield_until_terminated(r);
    else
      r.yield_until(r.scheduler_get().get_time()
                    + static_cast<libport::utime_t>(seconds * 1000000.0));
  }

  static float
  system_time()
  {
    return runner().scheduler_get().get_time() / 1000000.0;
  }

  static float
  system_shiftedTime()
  {
    runner::Runner& r = runner();
    return (r.scheduler_get().get_time() - r.time_shift_get()) / 1000000.0;
  }

  static void
  system_assert_(const rObject&,
                 const rObject& value, const std::string& assertion)
  {
    if (!is_true(value))
      runner::raise_primitive_error("failed assertion: " + assertion);
  }

  static rObject
  system_eval(const rObject&, const std::string& code)
  {
    return execute_parsed(parser::parse(code, ast::loc()),
                          SYMBOL(eval),
                          "error executing command: " + code);
  }

  static rObject
  system_class_registerAtJob (objects_type args)
  {
    check_arg_count(args.size() - 1, 3);
    runner::register_at_job(interpreter(),
			    args[1], args[2], args[3]);
    return object::void_class;
  }

  static rObject
  system_scopeTag()
  {
    return new Tag(interpreter().scope_tag());
  }

  static rObject
  system_class_searchFile(objects_type args)
  {
    check_arg_count(args.size() - 1, 1);
    const std::string filename = filename_get(args[1]);

    try
    {
      return new Path(urbiserver->find_file(filename));
    }
    catch (libport::file_library::Not_found&)
    {
      runner::raise_urbi(SYMBOL(FileNotFound), to_urbi(filename));
      // Never reached
      assertion(false);
      return 0;
    }
  }

  static List::value_type
  system_searchPath()
  {
    List::value_type res;
    foreach (const libport::path& p, urbiserver->search_path.search_path_get())
      res.push_back(new Path(p));
    return res;
  }

  static rObject
  system_class_loadFile(objects_type args)
  {
    check_arg_count(args.size() - 1, 1);
    const std::string filename = filename_get(args[1]);

    if (!libport::path(filename).exists())
      runner::raise_urbi(SYMBOL(FileNotFound), to_urbi(filename));
    return
      execute_parsed(parser::parse_file(filename),
                     SYMBOL(loadFile),
		     "error loading file: " + filename);
  }

  static rObject
  system_currentRunner()
  {
    return runner().as_task();
  }

  static float
  system_cycle()
  {
    return runner().scheduler_get().cycle_get();
  }

  static libport::Symbol
  system_fresh()
  {
    return libport::Symbol::fresh();
  }

  static rObject
  system_lobby()
  {
    return runner().lobby_get();
  }

  static void
  system_nonInterruptible()
  {
    runner().non_interruptible_set(true);
  }

  static void
  system_quit()
  {
    runner().lobby_get()->connection_get().close();
  }

  static void
  system_spawn(const rObject&,
	       const rCode& code,
               const rObject& clear_tags)
  {
    runner::Runner& r = runner();
    runner::Interpreter* new_runner =
      new runner::Interpreter(interpreter(),
                              rObject(code),
                              libport::Symbol::fresh(r.name_get()));

    if (is_true(clear_tags))
      new_runner->tag_stack_clear();

    new_runner->time_shift_set(r.time_shift_get());
    new_runner->start_job();
  }

  static rObject
  system_stats()
  {
    Dictionary::value_type res;
    const sched::scheduler_stats_type& stats =
      runner().scheduler_get().stats_get();

    // If statistics have just been reset, return "nil" since we cannot
    // return anything significant.
    if (stats.empty())
      return nil_class;

    // The space after "Symbol(" is mandatory to avoid triggering an error in
    // symbol generation code
#define ADDSTAT(Suffix, Function, Divisor)      \
    res[libport::Symbol("cycles" # Suffix)] =   \
      new Float(stats.Function() / Divisor)
    ADDSTAT(, size, 1);
    ADDSTAT(Max, max, 1e6);
    ADDSTAT(Mean, mean, 1e6);
    ADDSTAT(Min, min, 1e6);
    ADDSTAT(StdDev, standard_deviation, 1e6);
    ADDSTAT(Variance, variance, 1e3);
#undef ADDSTAT
    return new Dictionary(res);
  }

  static void
  system_resetStats()
  {
    runner().scheduler_get().stats_reset();
  }

  // This should give a backtrace as an urbi object.
  static void
  system_backtrace()
  {
    // FIXME: This method sucks a bit, because show_backtrace sucks a
    // bit, because our channeling/message-sending system sucks a lot.
    runner::Runner::backtrace_type bt = runner().backtrace_get();
    bt.pop_back();
    foreach (const runner::Runner::frame_type& elt,
	     boost::make_iterator_range(boost::rbegin(bt),
					boost::rend(bt)))
      runner().send_message("backtrace", elt.first + " (" + elt.second + ")");
  }

  static List::value_type
  system_jobs()
  {
    List::value_type res;
    foreach(sched::rJob job, runner().scheduler_get().jobs_get())
      res.push_back(dynamic_cast<runner::Runner*>(job.get())->as_task());
    return res;
  }

  static int
  system_aliveJobs()
  {
    return sched::Job::alive_jobs();
  }

  static void
  system_breakpoint()
  {
    return;
  }

#define SERVER_SET_VAR(Function, Variable, Value)       \
  static void                                           \
  system_ ## Function ()                                \
  {                                                     \
    urbiserver->Variable = Value;                       \
  }

  SERVER_SET_VAR(stopall, stopall, true)

#undef SERVER_SET_VAR

  static rObject system_getenv(const rObject&, const std::string& name)
  {
    char* res = getenv(name.c_str());
    return res ? new String(res) : nil_class;
  }

  static rObject system_setenv(const rObject&, const std::string& name, rObject value)
  {
    rString v = value->call(SYMBOL(asString))->as<String>();
    setenv(name.c_str(), v->value_get().c_str(), 1);
    return v;
  }

  static rObject system_unsetenv(const rObject&, const std::string& name)
  {
    rObject res = system_getenv(0, name);
    unsetenv(name.c_str());
    return res;
  }

  static libport::InstanceTracker<Lobby>::set_type system_lobbies()
  {
    return Lobby::instances_get();
  }

  static void system_loadModule(const rObject&, const std::string& name)
  {
    static bool initialized = false;

    if (!initialized)
    {
      initialized = true;
      lt_dlinit();
    }
    lt_dlhandle handle = lt_dlopenext(name.c_str());
    if (!handle)
      runner::raise_primitive_error
        ("Failed to open `" + name + "': " + lt_dlerror());

    // Reload uobjects
    uobjects_reload();

    // Reload CxxObjects
    CxxObject::create();
    CxxObject::initialize(global_class);
    CxxObject::cleanup();
  }

  static libport::cli_args_type urbi_arguments_;
  static boost::optional<std::string> urbi_program_name_;

  void system_push_argument(const std::string& arg)
  {
    urbi_arguments_.push_back(arg);
  }

  void system_set_program_name(const std::string& name)
  {
    urbi_program_name_ = name;
  }

  static const libport::cli_args_type& system_arguments()
  {
    return urbi_arguments_;
  }

  static boost::optional<std::string> system_programName()
  {
    return urbi_program_name_;
  }

  static void system__exit(const rObject&, int status)
  {
    exit(status);
  }

  void
  system_class_initialize ()
  {
#define DECLARE(Name)                                                   \
    system_class->slot_set(SYMBOL(Name),                                \
                           make_primitive(&system_##Name))              \

    DECLARE(_exit);
    DECLARE(aliveJobs);
    DECLARE(arguments);
    DECLARE(assert_);
    DECLARE(backtrace);
    DECLARE(breakpoint);
    DECLARE(currentRunner);
    DECLARE(cycle);
    DECLARE(eval);
    DECLARE(fresh);
    DECLARE(getenv);
    DECLARE(jobs);
    DECLARE(loadModule);
    DECLARE(lobbies);
    DECLARE(lobby);
    DECLARE(nonInterruptible);
    DECLARE(programName);
    DECLARE(quit);
    DECLARE(reboot);
    DECLARE(resetStats);
    DECLARE(scopeTag);
    DECLARE(searchPath);
    DECLARE(setenv);
    DECLARE(shiftedTime);
    DECLARE(shutdown);
    DECLARE(sleep);
    DECLARE(spawn);
    DECLARE(stats);
    DECLARE(stopall);
    DECLARE(time);
    DECLARE(unsetenv);

#undef DECLARE

    /// \a Call gives the name of the C++ function, and \a Name that in Urbi.
#define DECLARE(Name)				\
    DECLARE_PRIMITIVE(system, Name)

    DECLARE(loadFile);
    DECLARE(registerAtJob);
    DECLARE(searchFile);
#undef DECLARE
  }

}; // namespace object
<commit_msg>system: finish migration.<commit_after>/**
 ** \file object/system-class.cc
 ** \brief Creation of the URBI object system.
 */

#include <ltdl.h>

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>
#include <libport/cstdlib>
#include <libport/program-name.hh>

#include <memory>
#include <sstream>

#include <kernel/uconnection.hh>
#include <kernel/uobject.hh>
#include <kernel/userver.hh>

#include <object/code.hh>
#include <object/cxx-primitive.hh>
#include <object/dictionary.hh>
#include <object/float.hh>
#include <object/global.hh>
#include <object/lobby.hh>
#include <object/list.hh>
#include <object/path.hh>
#include <object/primitives.hh>
#include <object/system.hh>
#include <object/tag.hh>
#include <object/task.hh>
#include <parser/transform.hh>
#include <runner/at-handler.hh>
#include <runner/interpreter.hh>
#include <runner/raise.hh>
#include <runner/runner.hh>

#include <ast/nary.hh>
#include <ast/routine.hh>

namespace object
{
  using kernel::urbiserver;

  static inline
  runner::Runner&
  runner()
  {
    return ::kernel::urbiserver->getCurrentRunner();
  }

  static inline
  runner::Interpreter&
  interpreter()
  {
    return dynamic_cast<runner::Interpreter&>(runner());
  }

  // Extract a filename from a String or a Path object
  static std::string
  filename_get(const rObject& o)
  {
    if (o.is_a<Path>())
      return o->as<Path>()->as_string();
    type_check<String>(o);
    return o->as<String>()->value_get();
  }

  rObject
  execute_parsed(parser::parse_result_type p,
                 libport::Symbol fun, std::string e)
  {
    runner::Interpreter& run = interpreter();

    // Report potential errors
    {
      ast::rNary errs = new ast::Nary();
      p->process_errors(*errs);
      run(errs.get());
    }

    ast::rConstAst ast = parser::transform(p->ast_get());
    if (!ast)
      runner::raise_primitive_error(e);

    runner::Interpreter* sub = new runner::Interpreter(run, ast, fun);
    // So that it will resist to the call to yield_until_terminated,
    // and will be reclaimed at the end of the scope.
    sched::rJob job = sub;
    libport::Finally finally;
    runner().register_child(sub, finally);
    sub->start_job();
    try
    {
      run.yield_until_terminated(*job);
    }
    catch (const sched::ChildException& ce)
    {
      // Kill the sub-job and propagate.
      ce.rethrow_child_exception();
    }
    return sub->result_get();
  }

  rObject system_class;

  /*--------------------.
  | System primitives.  |
  `--------------------*/

#define SERVER_FUNCTION(Function)               \
  static void                                   \
  system_ ## Function ()                        \
  {                                             \
    urbiserver->Function();                     \
  }

  SERVER_FUNCTION(reboot)
  SERVER_FUNCTION(shutdown)

#undef SERVER_FUNCTION

  static void
  system_sleep(const rObject&, libport::ufloat seconds)
  {
    runner::Runner& r = runner();
    if (seconds == std::numeric_limits<ufloat>::infinity())
      r.yield_until_terminated(r);
    else
      r.yield_until(r.scheduler_get().get_time()
                    + static_cast<libport::utime_t>(seconds * 1000000.0));
  }

  static float
  system_time()
  {
    return runner().scheduler_get().get_time() / 1000000.0;
  }

  static float
  system_shiftedTime()
  {
    runner::Runner& r = runner();
    return (r.scheduler_get().get_time() - r.time_shift_get()) / 1000000.0;
  }

  static void
  system_assert_(const rObject&,
                 const rObject& value, const std::string& assertion)
  {
    if (!is_true(value))
      runner::raise_primitive_error("failed assertion: " + assertion);
  }

  static rObject
  system_eval(const rObject&, const std::string& code)
  {
    return execute_parsed(parser::parse(code, ast::loc()),
                          SYMBOL(eval),
                          "error executing command: " + code);
  }

  static void
  system_registerAtJob(const rObject&,
                       const rObject& condition,
                       const rObject& clause,
                       const rObject& on_leave)
  {
    runner::register_at_job(interpreter(),
			    condition, clause, on_leave);
  }

  static rObject
  system_scopeTag()
  {
    return new Tag(interpreter().scope_tag());
  }

  static rObject
  system_searchFile(const rObject&, const rObject& f)
  {
    const std::string& filename = filename_get(f);
    try
    {
      return new Path(urbiserver->find_file(filename));
    }
    catch (libport::file_library::Not_found&)
    {
      runner::raise_urbi(SYMBOL(FileNotFound), to_urbi(filename));
      // Never reached
      assertion(false);
      return 0;
    }
  }

  static List::value_type
  system_searchPath()
  {
    List::value_type res;
    foreach (const libport::path& p, urbiserver->search_path.search_path_get())
      res.push_back(new Path(p));
    return res;
  }

  static rObject
  system_loadFile(const rObject&, const rObject& f)
  {
    const std::string& filename = filename_get(f);
    if (!libport::path(filename).exists())
      runner::raise_urbi(SYMBOL(FileNotFound), to_urbi(filename));
    return
      execute_parsed(parser::parse_file(filename),
                     SYMBOL(loadFile),
		     "error loading file: " + filename);
  }

  static rObject
  system_currentRunner()
  {
    return runner().as_task();
  }

  static float
  system_cycle()
  {
    return runner().scheduler_get().cycle_get();
  }

  static libport::Symbol
  system_fresh()
  {
    return libport::Symbol::fresh();
  }

  static rObject
  system_lobby()
  {
    return runner().lobby_get();
  }

  static void
  system_nonInterruptible()
  {
    runner().non_interruptible_set(true);
  }

  static void
  system_quit()
  {
    runner().lobby_get()->connection_get().close();
  }

  static void
  system_spawn(const rObject&,
	       const rCode& code,
               const rObject& clear_tags)
  {
    runner::Runner& r = runner();
    runner::Interpreter* new_runner =
      new runner::Interpreter(interpreter(),
                              rObject(code),
                              libport::Symbol::fresh(r.name_get()));

    if (is_true(clear_tags))
      new_runner->tag_stack_clear();

    new_runner->time_shift_set(r.time_shift_get());
    new_runner->start_job();
  }

  static rObject
  system_stats()
  {
    Dictionary::value_type res;
    const sched::scheduler_stats_type& stats =
      runner().scheduler_get().stats_get();

    // If statistics have just been reset, return "nil" since we cannot
    // return anything significant.
    if (stats.empty())
      return nil_class;

    // The space after "Symbol(" is mandatory to avoid triggering an error in
    // symbol generation code
#define ADDSTAT(Suffix, Function, Divisor)      \
    res[libport::Symbol("cycles" # Suffix)] =   \
      new Float(stats.Function() / Divisor)
    ADDSTAT(, size, 1);
    ADDSTAT(Max, max, 1e6);
    ADDSTAT(Mean, mean, 1e6);
    ADDSTAT(Min, min, 1e6);
    ADDSTAT(StdDev, standard_deviation, 1e6);
    ADDSTAT(Variance, variance, 1e3);
#undef ADDSTAT
    return new Dictionary(res);
  }

  static void
  system_resetStats()
  {
    runner().scheduler_get().stats_reset();
  }

  // This should give a backtrace as an urbi object.
  static void
  system_backtrace()
  {
    // FIXME: This method sucks a bit, because show_backtrace sucks a
    // bit, because our channeling/message-sending system sucks a lot.
    runner::Runner::backtrace_type bt = runner().backtrace_get();
    bt.pop_back();
    foreach (const runner::Runner::frame_type& elt,
	     boost::make_iterator_range(boost::rbegin(bt),
					boost::rend(bt)))
      runner().send_message("backtrace", elt.first + " (" + elt.second + ")");
  }

  static List::value_type
  system_jobs()
  {
    List::value_type res;
    foreach(sched::rJob job, runner().scheduler_get().jobs_get())
      res.push_back(dynamic_cast<runner::Runner*>(job.get())->as_task());
    return res;
  }

  static int
  system_aliveJobs()
  {
    return sched::Job::alive_jobs();
  }

  static void
  system_breakpoint()
  {
    return;
  }

#define SERVER_SET_VAR(Function, Variable, Value)       \
  static void                                           \
  system_ ## Function ()                                \
  {                                                     \
    urbiserver->Variable = Value;                       \
  }

  SERVER_SET_VAR(stopall, stopall, true)

#undef SERVER_SET_VAR

  static rObject system_getenv(const rObject&, const std::string& name)
  {
    char* res = getenv(name.c_str());
    return res ? new String(res) : nil_class;
  }

  static rObject system_setenv(const rObject&, const std::string& name, rObject value)
  {
    rString v = value->call(SYMBOL(asString))->as<String>();
    setenv(name.c_str(), v->value_get().c_str(), 1);
    return v;
  }

  static rObject system_unsetenv(const rObject&, const std::string& name)
  {
    rObject res = system_getenv(0, name);
    unsetenv(name.c_str());
    return res;
  }

  static libport::InstanceTracker<Lobby>::set_type system_lobbies()
  {
    return Lobby::instances_get();
  }

  static void system_loadModule(const rObject&, const std::string& name)
  {
    static bool initialized = false;

    if (!initialized)
    {
      initialized = true;
      lt_dlinit();
    }
    lt_dlhandle handle = lt_dlopenext(name.c_str());
    if (!handle)
      runner::raise_primitive_error
        ("Failed to open `" + name + "': " + lt_dlerror());

    // Reload uobjects
    uobjects_reload();

    // Reload CxxObjects
    CxxObject::create();
    CxxObject::initialize(global_class);
    CxxObject::cleanup();
  }

  static libport::cli_args_type urbi_arguments_;
  static boost::optional<std::string> urbi_program_name_;

  void system_push_argument(const std::string& arg)
  {
    urbi_arguments_.push_back(arg);
  }

  void system_set_program_name(const std::string& name)
  {
    urbi_program_name_ = name;
  }

  static const libport::cli_args_type& system_arguments()
  {
    return urbi_arguments_;
  }

  static boost::optional<std::string> system_programName()
  {
    return urbi_program_name_;
  }

  static void system__exit(const rObject&, int status)
  {
    exit(status);
  }

  void
  system_class_initialize ()
  {
#define DECLARE(Name)                                                   \
    system_class->slot_set(SYMBOL(Name),                                \
                           make_primitive(&system_##Name))              \

    DECLARE(_exit);
    DECLARE(aliveJobs);
    DECLARE(arguments);
    DECLARE(assert_);
    DECLARE(backtrace);
    DECLARE(breakpoint);
    DECLARE(currentRunner);
    DECLARE(cycle);
    DECLARE(eval);
    DECLARE(fresh);
    DECLARE(getenv);
    DECLARE(jobs);
    DECLARE(loadFile);
    DECLARE(loadModule);
    DECLARE(lobbies);
    DECLARE(lobby);
    DECLARE(nonInterruptible);
    DECLARE(programName);
    DECLARE(quit);
    DECLARE(reboot);
    DECLARE(registerAtJob);
    DECLARE(resetStats);
    DECLARE(scopeTag);
    DECLARE(searchFile);
    DECLARE(searchPath);
    DECLARE(setenv);
    DECLARE(shiftedTime);
    DECLARE(shutdown);
    DECLARE(sleep);
    DECLARE(spawn);
    DECLARE(stats);
    DECLARE(stopall);
    DECLARE(time);
    DECLARE(unsetenv);

#undef DECLARE
  }

} // namespace object
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */
/**
 ** \file object/system-class.hh
 ** \brief Definition of the URBI object system.
 */

#ifndef OBJECT_SYSTEM_CLASS_HH
# define OBJECT_SYSTEM_CLASS_HH

# include <urbi/object/fwd.hh>
# include <parser/parse.hh>
# include <parser/parse-result.hh>

namespace urbi
{
  namespace object
  {
    extern rObject system_class;

    /// Parse, bind etc. and execute code.
    ///
    /// Used internally and from the debugging routines.
    ///
    /// \param r   runner that must be an Interpreter.
    /// \param p   the parser result.
    /// \param fun name of the caller.
    /// \param e   exception to raise on error.
    /// \returns the result of the evaluation.
    rObject execute_parsed(parser::parse_result_type p,
                           libport::Symbol fun, std::string e);
    /// Set the current script name
    void system_set_program_name(const std::string& name);
    /// Register a new user-argument for the script
    void system_push_argument(const std::string& arg);

    /// Initialize the System class.
    void system_class_initialize();

  /// Return true if location is from a system file.
  bool is_system_location(const ast::loc& l);

  typedef std::set<libport::Symbol> system_files_type;
  /// Return the list of loaded system files.
  system_files_type& system_files_get();
  }; // namespace object
}

#endif // !OBJECT_SYSTEM_CLASS_HH
<commit_msg>Formatting changes.<commit_after>/*
 * Copyright (C) 2009, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */
/**
 ** \file object/system-class.hh
 ** \brief Definition of the URBI object system.
 */

#ifndef OBJECT_SYSTEM_CLASS_HH
# define OBJECT_SYSTEM_CLASS_HH

# include <urbi/object/fwd.hh>
# include <parser/parse.hh>
# include <parser/parse-result.hh>

namespace urbi
{
  namespace object
  {
    extern rObject system_class;

    /// Parse, bind etc. and execute code.
    ///
    /// Used internally and from the debugging routines.
    ///
    /// \param r   runner that must be an Interpreter.
    /// \param p   the parser result.
    /// \param fun name of the caller.
    /// \param e   exception to raise on error.
    /// \returns the result of the evaluation.
    rObject execute_parsed(parser::parse_result_type p,
                           libport::Symbol fun, std::string e);
    /// Set the current script name
    void system_set_program_name(const std::string& name);
    /// Register a new user-argument for the script
    void system_push_argument(const std::string& arg);

    /// Initialize the System class.
    void system_class_initialize();

    /// Return true if location is from a system file.
    bool is_system_location(const ast::loc& l);

    typedef std::set<libport::Symbol> system_files_type;
    /// Return the list of loaded system files.
    system_files_type& system_files_get();
  }; // namespace object
}

#endif // !OBJECT_SYSTEM_CLASS_HH
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2009 SpringSource, Inc.
 * Copyright (c) 2009 VMware, Inc.
 *
 * 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.
 */

#define UNICODE
#define _UNICODE
#define _WIN32_DCOM

#include <winsock2.h>
#include <windows.h>
#include <unistd.h>
#include <stdio.h>
#include <ole2.h>
#include <initguid.h>
#include <wbemcli.h>
#include <shobjidl.h>
#include <tchar.h>
#include "sigar.h"
#include "sigar_private.h"
#include "sigar_pdh.h"
#include "sigar_os.h"
#include "sigar_util.h"
#include "sigar_format.h"

#pragma comment(lib, "wbemuuid.lib")

#ifndef SIGAR_CMDLINE_MAX
#define SIGAR_CMDLINE_MAX 4096<<2
#endif

#ifndef _MSC_VER

DEFINE_GUID(CLSID_WbemLocator, 0x4590f811, 0x1d3a, 0x11d0, 0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24);
template <> const GUID & __mingw_uuidof < IWbemLocator > () {
	return IID_IWbemLocator;
}

template <> const GUID & __mingw_uuidof < IWbemLocator * >() {
	return __mingw_uuidof < IWbemLocator > ();
}
#endif
extern "C" {

int wmi_map_sigar_error(HRESULT hres)
{
	switch (hres) {
	case S_OK:
		return ERROR_SUCCESS;
	case WBEM_E_NOT_FOUND:
		return ERROR_NOT_FOUND;
	case WBEM_E_ACCESS_DENIED:
		return ERROR_ACCESS_DENIED;
	case WBEM_E_NOT_SUPPORTED:
		return SIGAR_ENOTIMPL;
	default:
		return ERROR_INVALID_FUNCTION;
	}
}

void wmi_handle_close(sigar_wmi_handle_t *wmi_handle)
{
	if(wmi_handle == NULL)
		return;

	if (wmi_handle->services) {
		wmi_handle->services->Release();
		wmi_handle->services = NULL;
	}

	if (wmi_handle->locator) {
		wmi_handle->locator->Release();
		wmi_handle->services = NULL;
	}
}

sigar_wmi_handle_t * wmi_handle_open(int *error)
{
	*error = SIGAR_OK;

	sigar_wmi_handle_t *handle;

	handle = (sigar_wmi_handle_t *)calloc(1, sizeof (*handle));

	HRESULT hres;
	wchar_t root[] = L"root\\CIMV2";

	hres = CoInitializeEx(NULL, COINIT_MULTITHREADED);
	if (FAILED(hres)) {
		goto err;
	}

	hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT,
                                    RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0);

	/*
	* If RPC_E_TOO_LATE then we have already been called.  This happens in the case of
	* multiple sigar instances since this should only be called once per application.
	*/

	if (FAILED(hres) && hres != RPC_E_TOO_LATE) {
		goto err;
	}

	hres = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&handle->locator));
	if (FAILED(hres)) {
		goto err;
	}

	hres = handle->locator->ConnectServer(root, NULL, NULL, NULL,
                                              WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &handle->services);
	if (FAILED(hres)) {
		goto err;
	}

	return handle;
err:
	wmi_handle_close(handle);
	*error = wmi_map_sigar_error(hres);
	return NULL;
}

HRESULT wmi_get_proc_string_property(sigar_t *sigar, DWORD pid, TCHAR * name, TCHAR * value, DWORD len)
{
	IWbemClassObject *obj;
	VARIANT var;
	HRESULT result;

	if(sigar->wmi_handle == NULL)
            return (E_INVALIDARG);

	wchar_t query[56];
	wsprintf(query, L"Win32_Process.Handle=%d", pid);

	result = sigar->wmi_handle->services->GetObject(query, 0, 0, &obj, 0);

	if (FAILED(result)) {
		return result;
	}

	result = obj->Get(name, 0, &var, 0, 0);

	if (SUCCEEDED(result)) {
		if (var.vt == VT_NULL) {
			result = E_INVALIDARG;
		} else {
			lstrcpyn(value, var.bstrVal, len);
		}
		VariantClear(&var);
	}

	obj->Release();

	return result;
}

HRESULT wmi_get_proc_executable_path(sigar_t *sigar, DWORD pid, TCHAR * value)
{
	wchar_t prop[] = L"ExecutablePath";
	return wmi_get_proc_string_property(sigar, pid, prop, value, MAX_PATH);
}

HRESULT wmi_get_proc_command_line(sigar_t *sigar, DWORD pid, TCHAR * value)
{
	wchar_t prop[] = L"CommandLine";
	return wmi_get_proc_string_property(sigar, pid, prop, value, MAX_PATH);
}

IEnumWbemClassObject *wmi_query(sigar_t *sigar, const wchar_t * query)
{
	IEnumWbemClassObject *wmi_enum = NULL;
	if (sigar->wmi_handle) {
		wchar_t lang[] = L"WQL";
		wchar_t *query_cpy = wcsdup(query);

		HRESULT hres =
			sigar->wmi_handle->services->ExecQuery(lang, query_cpy, WBEM_FLAG_FORWARD_ONLY, NULL, &wmi_enum);

		free(query_cpy);
	}
	return wmi_enum;
}

int wmi_query_sum_u64(sigar_t  *sigar, const wchar_t * query, const wchar_t * attrib,
					  sigar_uint64_t * sum, unsigned long *num_elems)
{
	*sum = 0;
	*num_elems = 0;

	IEnumWbemClassObject *wmi_enum = wmi_query(sigar, query);
	if (!wmi_enum) {
		return -1;
	}

	wchar_t *attrib_cpy = wcsdup(attrib);

	IWbemClassObject *wmi_obj = NULL;
	HRESULT hres;
	unsigned long curr_elem = 0;
	while (((hres = wmi_enum->Next(WBEM_INFINITE, 1, &wmi_obj, &curr_elem)) != WBEM_S_FALSE)
		   && !FAILED(hres)) {
		(*num_elems)++;
		VARIANT val;
		VariantInit(&val);
		if (SUCCEEDED(wmi_obj->Get(attrib_cpy, 0, &val, NULL, NULL))) {
			if (val.vt == VT_BSTR) {
				*sum += _wtoi(val.bstrVal);
			} else {
				*sum += val.intVal;
			}
		}
		wmi_obj->Release();
	}

	free(attrib_cpy);
	wmi_enum->Release();

	return 0;
}

int wmi_query_sum_u32(sigar_t *sigar, const wchar_t * query,
		const wchar_t * attrib, sigar_uint32_t * sum, unsigned long *num_elems)
{
	sigar_uint64_t sum64 = 0;
	int rc = wmi_query_sum_u64(sigar, query, attrib, &sum64, num_elems);
	*sum = sum64;
	return rc;
}

int wmi_query_avg(sigar_t *sigar, const wchar_t * query,
		const wchar_t * attrib, float *avg)
{
	sigar_uint64_t sum = 0;
	unsigned long num_elems = 0;
	int rc = wmi_query_sum_u64(sigar, query, attrib, &sum, &num_elems);
	if (!rc && num_elems) {
		*avg = sum / (double)(num_elems);
	}
	return rc;
}

/* in peb.c */
int sigar_parse_proc_args(sigar_t * sigar, WCHAR * buf, sigar_proc_args_t * procargs);

int sigar_proc_args_wmi_get(sigar_t * sigar, sigar_pid_t pid, sigar_proc_args_t * procargs)
{
	TCHAR buf[SIGAR_CMDLINE_MAX];
	int status;

	if ((status = wmi_get_proc_command_line(sigar, pid, buf))) {
		goto out;
	} else {
		status = sigar_parse_proc_args(sigar, buf, procargs);
	}

out:
	return status;
}

int sigar_proc_exe_wmi_get(sigar_t * sigar, sigar_pid_t pid, sigar_proc_exe_t * procexe)
{
	TCHAR buf[MAX_PATH + 1];
	int status;

	procexe->name[0] = '\0';

	if ((status = wmi_get_proc_executable_path(sigar, pid, buf))) {
		goto out;
	} else {
		status = SIGAR_OK;
		/* SIGAR_W2A(buf, procexe->name, sizeof(procexe->name)); */
		WideCharToMultiByte(CP_ACP, 0, buf, -1,
			(LPSTR) procexe->name, sizeof(procexe->name), NULL, NULL);
	}

out:
	return status;
}
}								//extern "C"
<commit_msg>conditionally define WbemLocator<commit_after>/*
 * Copyright (c) 2009 SpringSource, Inc.
 * Copyright (c) 2009 VMware, Inc.
 *
 * 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.
 */

#define UNICODE
#define _UNICODE
#define _WIN32_DCOM

#include <winsock2.h>
#include <windows.h>
#include <unistd.h>
#include <stdio.h>
#include <ole2.h>
#include <initguid.h>
#include <wbemcli.h>
#include <shobjidl.h>
#include <tchar.h>
#include "sigar.h"
#include "sigar_private.h"
#include "sigar_pdh.h"
#include "sigar_os.h"
#include "sigar_util.h"
#include "sigar_format.h"

#pragma comment(lib, "wbemuuid.lib")

#ifndef SIGAR_CMDLINE_MAX
#define SIGAR_CMDLINE_MAX 4096<<2
#endif

#if !defined(_MSC_VER) && !defined(__WbemLocator_FWD_DEFINED__)

DEFINE_GUID(CLSID_WbemLocator, 0x4590f811, 0x1d3a, 0x11d0, 0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24);
template <> const GUID & __mingw_uuidof < IWbemLocator > () {
	return IID_IWbemLocator;
}

template <> const GUID & __mingw_uuidof < IWbemLocator * >() {
	return __mingw_uuidof < IWbemLocator > ();
}

#endif
extern "C" {

int wmi_map_sigar_error(HRESULT hres)
{
	switch (hres) {
	case S_OK:
		return ERROR_SUCCESS;
	case WBEM_E_NOT_FOUND:
		return ERROR_NOT_FOUND;
	case WBEM_E_ACCESS_DENIED:
		return ERROR_ACCESS_DENIED;
	case WBEM_E_NOT_SUPPORTED:
		return SIGAR_ENOTIMPL;
	default:
		return ERROR_INVALID_FUNCTION;
	}
}

void wmi_handle_close(sigar_wmi_handle_t *wmi_handle)
{
	if(wmi_handle == NULL)
		return;

	if (wmi_handle->services) {
		wmi_handle->services->Release();
		wmi_handle->services = NULL;
	}

	if (wmi_handle->locator) {
		wmi_handle->locator->Release();
		wmi_handle->services = NULL;
	}
}

sigar_wmi_handle_t * wmi_handle_open(int *error)
{
	*error = SIGAR_OK;

	sigar_wmi_handle_t *handle;

	handle = (sigar_wmi_handle_t *)calloc(1, sizeof (*handle));

	HRESULT hres;
	wchar_t root[] = L"root\\CIMV2";

	hres = CoInitializeEx(NULL, COINIT_MULTITHREADED);
	if (FAILED(hres)) {
		goto err;
	}

	hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT,
                                    RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0);

	/*
	* If RPC_E_TOO_LATE then we have already been called.  This happens in the case of
	* multiple sigar instances since this should only be called once per application.
	*/

	if (FAILED(hres) && hres != RPC_E_TOO_LATE) {
		goto err;
	}

	hres = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&handle->locator));
	if (FAILED(hres)) {
		goto err;
	}

	hres = handle->locator->ConnectServer(root, NULL, NULL, NULL,
                                              WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &handle->services);
	if (FAILED(hres)) {
		goto err;
	}

	return handle;
err:
	wmi_handle_close(handle);
	*error = wmi_map_sigar_error(hres);
	return NULL;
}

HRESULT wmi_get_proc_string_property(sigar_t *sigar, DWORD pid, TCHAR * name, TCHAR * value, DWORD len)
{
	IWbemClassObject *obj;
	VARIANT var;
	HRESULT result;

	if(sigar->wmi_handle == NULL)
            return (E_INVALIDARG);

	wchar_t query[56];
	wsprintf(query, L"Win32_Process.Handle=%d", pid);

	result = sigar->wmi_handle->services->GetObject(query, 0, 0, &obj, 0);

	if (FAILED(result)) {
		return result;
	}

	result = obj->Get(name, 0, &var, 0, 0);

	if (SUCCEEDED(result)) {
		if (var.vt == VT_NULL) {
			result = E_INVALIDARG;
		} else {
			lstrcpyn(value, var.bstrVal, len);
		}
		VariantClear(&var);
	}

	obj->Release();

	return result;
}

HRESULT wmi_get_proc_executable_path(sigar_t *sigar, DWORD pid, TCHAR * value)
{
	wchar_t prop[] = L"ExecutablePath";
	return wmi_get_proc_string_property(sigar, pid, prop, value, MAX_PATH);
}

HRESULT wmi_get_proc_command_line(sigar_t *sigar, DWORD pid, TCHAR * value)
{
	wchar_t prop[] = L"CommandLine";
	return wmi_get_proc_string_property(sigar, pid, prop, value, MAX_PATH);
}

IEnumWbemClassObject *wmi_query(sigar_t *sigar, const wchar_t * query)
{
	IEnumWbemClassObject *wmi_enum = NULL;
	if (sigar->wmi_handle) {
		wchar_t lang[] = L"WQL";
		wchar_t *query_cpy = wcsdup(query);

		HRESULT hres =
			sigar->wmi_handle->services->ExecQuery(lang, query_cpy, WBEM_FLAG_FORWARD_ONLY, NULL, &wmi_enum);

		free(query_cpy);
	}
	return wmi_enum;
}

int wmi_query_sum_u64(sigar_t  *sigar, const wchar_t * query, const wchar_t * attrib,
					  sigar_uint64_t * sum, unsigned long *num_elems)
{
	*sum = 0;
	*num_elems = 0;

	IEnumWbemClassObject *wmi_enum = wmi_query(sigar, query);
	if (!wmi_enum) {
		return -1;
	}

	wchar_t *attrib_cpy = wcsdup(attrib);

	IWbemClassObject *wmi_obj = NULL;
	HRESULT hres;
	unsigned long curr_elem = 0;
	while (((hres = wmi_enum->Next(WBEM_INFINITE, 1, &wmi_obj, &curr_elem)) != WBEM_S_FALSE)
		   && !FAILED(hres)) {
		(*num_elems)++;
		VARIANT val;
		VariantInit(&val);
		if (SUCCEEDED(wmi_obj->Get(attrib_cpy, 0, &val, NULL, NULL))) {
			if (val.vt == VT_BSTR) {
				*sum += _wtoi(val.bstrVal);
			} else {
				*sum += val.intVal;
			}
		}
		wmi_obj->Release();
	}

	free(attrib_cpy);
	wmi_enum->Release();

	return 0;
}

int wmi_query_sum_u32(sigar_t *sigar, const wchar_t * query,
		const wchar_t * attrib, sigar_uint32_t * sum, unsigned long *num_elems)
{
	sigar_uint64_t sum64 = 0;
	int rc = wmi_query_sum_u64(sigar, query, attrib, &sum64, num_elems);
	*sum = sum64;
	return rc;
}

int wmi_query_avg(sigar_t *sigar, const wchar_t * query,
		const wchar_t * attrib, float *avg)
{
	sigar_uint64_t sum = 0;
	unsigned long num_elems = 0;
	int rc = wmi_query_sum_u64(sigar, query, attrib, &sum, &num_elems);
	if (!rc && num_elems) {
		*avg = sum / (double)(num_elems);
	}
	return rc;
}

/* in peb.c */
int sigar_parse_proc_args(sigar_t * sigar, WCHAR * buf, sigar_proc_args_t * procargs);

int sigar_proc_args_wmi_get(sigar_t * sigar, sigar_pid_t pid, sigar_proc_args_t * procargs)
{
	TCHAR buf[SIGAR_CMDLINE_MAX];
	int status;

	if ((status = wmi_get_proc_command_line(sigar, pid, buf))) {
		goto out;
	} else {
		status = sigar_parse_proc_args(sigar, buf, procargs);
	}

out:
	return status;
}

int sigar_proc_exe_wmi_get(sigar_t * sigar, sigar_pid_t pid, sigar_proc_exe_t * procexe)
{
	TCHAR buf[MAX_PATH + 1];
	int status;

	procexe->name[0] = '\0';

	if ((status = wmi_get_proc_executable_path(sigar, pid, buf))) {
		goto out;
	} else {
		status = SIGAR_OK;
		/* SIGAR_W2A(buf, procexe->name, sizeof(procexe->name)); */
		WideCharToMultiByte(CP_ACP, 0, buf, -1,
			(LPSTR) procexe->name, sizeof(procexe->name), NULL, NULL);
	}

out:
	return status;
}
}								//extern "C"
<|endoftext|>


<commit_before><commit_msg>code update<commit_after><|endoftext|>