<commit_before>/**
  * Touhou Community Reliant Automatic Patcher
  * Main DLL
  *
  * ----
  *
  * Direct memory patching and Import Address Table detouring.
  */

#include "thcrap.h"

static json_t *detours = NULL;

BOOL VirtualCheckRegion(const void *ptr, const size_t len)
{
	MEMORY_BASIC_INFORMATION mbi;
	if(VirtualQuery(ptr, &mbi, sizeof(MEMORY_BASIC_INFORMATION))) {
		auto page_end = (size_t)mbi.BaseAddress + mbi.RegionSize;
		return
			(~mbi.Protect & PAGE_NOACCESS)
			&& (page_end >= ((size_t)ptr + len));
	}
	return FALSE;
}

BOOL VirtualCheckCode(const void *ptr)
{
	return VirtualCheckRegion(ptr, 1);
}

int PatchRegion(void *ptr, const void *Prev, const void *New, size_t len)
{
	DWORD oldProt;
	int ret = 0;

	if(!VirtualCheckRegion(ptr, len)) {
		return ret;
	}
	VirtualProtect(ptr, len, PAGE_READWRITE, &oldProt);
	if(Prev ? !memcmp(ptr, Prev, len) : 1) {
		memcpy(ptr, New, len);
		ret = 1;
	}
	VirtualProtect(ptr, len, oldProt, &oldProt);
	return ret;
}

int PatchRegionEx(HANDLE hProcess, void *ptr, const void *Prev, const void *New, size_t len)
{
	MEMORY_BASIC_INFORMATION mbi;
	DWORD oldProt;
	VLA(BYTE, old_val, len);
	SIZE_T byte_ret;

	VirtualQueryEx(hProcess, ptr, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
	VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &oldProt);
	ReadProcessMemory(hProcess, ptr, old_val, len, &byte_ret);
	if(Prev ? !memcmp(old_val, Prev, len) : 1) {
		WriteProcessMemory(hProcess, ptr, New, len, &byte_ret);
	}
	VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize, oldProt, &oldProt);
	VLA_FREE(old_val);
	return byte_ret != len;
}

/// Import Address Table detouring
/// ==============================
inline int func_detour(PIMAGE_THUNK_DATA pThunk, const void *new_ptr)
{
	return PatchRegion(&pThunk->u1.Function, NULL, &new_ptr, sizeof(new_ptr));
}

int iat_detour_func(HMODULE hMod, PIMAGE_IMPORT_DESCRIPTOR pImpDesc, const iat_detour_t *detour)
{
	if(!hMod || !pImpDesc || !detour || !detour->new_ptr || !detour->old_func) {
		return -1;
	}
	if(!VirtualCheckCode(detour->new_ptr)) {
		return -2;
	}
	auto pOT = (PIMAGE_THUNK_DATA)((UINT_PTR)hMod + pImpDesc->OriginalFirstThunk);
	auto pIT = (PIMAGE_THUNK_DATA)((UINT_PTR)hMod + pImpDesc->FirstThunk);

	// We generally detour by comparing exported names. This has the advantage
	// that we can override any existing patches, and that it works on Win9x
	// too (as if that matters). However, in case we lack a pointer to the
	// OriginalFirstThunk, or the function is only exported by ordinal, this
	// is not possible, so we have to detour by comparing pointers then.

	if(pImpDesc->OriginalFirstThunk) {
		for(; pOT->u1.Function; pOT++, pIT++) {
			PIMAGE_IMPORT_BY_NAME pByName;
			if(!(pOT->u1.Ordinal & IMAGE_ORDINAL_FLAG)) {
				pByName = (PIMAGE_IMPORT_BY_NAME)((UINT_PTR)hMod + pOT->u1.AddressOfData);
				if(pByName->Name[0] == '\0') {
					return 0;
				}
				if(!stricmp(detour->old_func, (char*)pByName->Name)) {
					return func_detour(pIT, detour->new_ptr);
				}
			} else {
				if((void*)pIT->u1.Function == detour->old_ptr) {
					return func_detour(pIT, detour->new_ptr);
				}
			}
		}
	} else {
		for(; pIT->u1.Function; pIT++) {
			if((void*)pIT->u1.Function == detour->old_ptr) {
				return func_detour(pIT, detour->new_ptr);
			}
		}
	}
	// Function not found
	return 0;
}
/// ----------

/// Detour chaining
/// ---------------
json_t* detour_get_create(const char *dll_name)
{
	json_t *ret = NULL;
	STRLWR_DEC(dll_name);
	STRLWR_CONV(dll_name);
	if(!detours) {
		detours = json_object();
	}
	ret = json_object_get_create(detours, dll_name_lower, JSON_OBJECT);
	STRLWR_FREE(dll_name);

	return ret;
}

int detour_chain(const char *dll_name, int return_old_ptrs, ...)
{
	int ret = 0;
	json_t *dll = detour_get_create(dll_name);
	const char *func_name = NULL;
	va_list va;

	va_start(va, return_old_ptrs);
	while(func_name = va_arg(va, const char*)) {
		FARPROC *old_ptr = NULL;
		FARPROC chain_ptr;
		const void *func_ptr = va_arg(va, const void*);
		if(
			return_old_ptrs
			&& (old_ptr = va_arg(va, FARPROC*))
			&& (chain_ptr = (FARPROC)json_object_get_hex(dll, func_name))
			&& (chain_ptr != func_ptr)
		) {
			*old_ptr = chain_ptr;
		}
		json_object_set_new(dll, func_name, json_integer((size_t)func_ptr));
	}
	va_end(va);
	return ret;
}

int detour_chain_w32u8(const w32u8_dll_t *dll)
{
	const w32u8_pair_t *pair = NULL;
	json_t *detours_dll = NULL;

	if(!dll || !dll->name || !dll->funcs) {
		return -1;
	}
	detours_dll = detour_get_create(dll->name);
	pair = dll->funcs;
	while(pair && pair->ansi_name && pair->utf8_ptr) {
		json_object_set_new(
			detours_dll, pair->ansi_name, json_integer((size_t)pair->utf8_ptr)
		);
		pair++;
	}
	return 0;
}

int iat_detour_apply(HMODULE hMod)
{
	int ret = 0;
	PIMAGE_IMPORT_DESCRIPTOR pImpDesc;

	pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)GetNtDataDirectory(hMod, IMAGE_DIRECTORY_ENTRY_IMPORT);
	if(!pImpDesc) {
		return ret;
	}

	while(pImpDesc->Name) {
		json_t *funcs;
		size_t func_count;
		char *dll_name = (char*)((UINT_PTR)hMod + (UINT_PTR)pImpDesc->Name);
		HMODULE hDll = GetModuleHandleA(dll_name);
		STRLWR_DEC(dll_name);

		STRLWR_CONV(dll_name);
		funcs = json_object_get(detours, dll_name_lower);
		func_count = json_object_size(funcs);

		if(hDll && func_count) {
			const char *func_name;
			json_t *ptr;
			size_t i = 0;

			log_printf("Detouring DLL functions (%s)...\n", dll_name_lower);

			json_object_foreach(funcs, func_name, ptr) {
				iat_detour_t detour;
				int local_ret;

				detour.old_func = func_name;
				detour.old_ptr = GetProcAddress(hDll, detour.old_func);
				detour.new_ptr = (FARPROC)json_integer_value(ptr);

				local_ret = iat_detour_func(hMod, pImpDesc, &detour);

				log_printf(
					"(%2d/%2d) %s... %s\n",
					i + 1, func_count, detour.old_func,
					local_ret ? "OK" : "not found"
				);
				i++;
			}
		}
		STRLWR_FREE(dll_name);
		pImpDesc++;
	}
	return ret;
}

FARPROC detour_top(const char *dll_name, const char *func_name, FARPROC fallback)
{
	json_t *funcs = json_object_get_create(detours, dll_name, JSON_OBJECT);
	FARPROC ret = (FARPROC)json_object_get_hex(funcs, func_name);
	return ret ? ret : fallback;
}

int vtable_detour(void **vtable, const vtable_detour_t *det, size_t det_count)
{
	assert(vtable);
	assert(det);

	if(det_count == 0) {
		return 0;
	}

	DWORD old_prot;
	int replaced = 0;
	size_t i;

	// VirtualProtect() is infamously slow, so...
	size_t lowest = (size_t)-1;
	size_t highest = 0;

	for(i = 0; i < det_count; i++) {
		lowest = MIN(lowest, det[i].index);
		highest = MAX(highest, det[i].index);
	}

	size_t bytes_to_lock = ((highest + 1) - lowest) * sizeof(void*);

	VirtualProtect(vtable + lowest, bytes_to_lock, PAGE_READWRITE, &old_prot);
	for(i = 0; i < det_count; i++) {
		auto& cur = det[i];

		bool replace =
			(cur.old_func == nullptr) || (*cur.old_func == nullptr)
			|| (*cur.old_func == vtable[cur.index]);
		bool set_old = (cur.old_func != nullptr) && (*cur.old_func == nullptr);

		if(set_old) {
			*cur.old_func = vtable[cur.index];
		}
		if(replace) {
			vtable[cur.index] = cur.new_func;
			replaced++;
		}
	}
	VirtualProtect(vtable + lowest, bytes_to_lock, old_prot, &old_prot);
	return replaced;
}

void detour_exit(void)
{
	detours = json_decref_safe(detours);
}
/// ----------

/// =============================
<commit_msg>mempatch: fix crash on invalid memory regions<commit_after>/**
  * Touhou Community Reliant Automatic Patcher
  * Main DLL
  *
  * ----
  *
  * Direct memory patching and Import Address Table detouring.
  */

#include "thcrap.h"

static json_t *detours = NULL;

BOOL VirtualCheckRegion(const void *ptr, const size_t len)
{
	MEMORY_BASIC_INFORMATION mbi;
	if (VirtualQuery(ptr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == 0) {
		return FALSE;
	}

	auto ptr_end = (size_t)ptr + len;
	auto page_end = (size_t)mbi.BaseAddress + mbi.RegionSize;
	if (page_end < (ptr_end)) {
		return FALSE;
	}

	if (mbi.Protect == 0 || (mbi.Protect & PAGE_NOACCESS)) {
		return FALSE;
	}

	return TRUE;
}

BOOL VirtualCheckCode(const void *ptr)
{
	return VirtualCheckRegion(ptr, 1);
}

int PatchRegion(void *ptr, const void *Prev, const void *New, size_t len)
{
	DWORD oldProt;
	int ret = 0;

	if(!VirtualCheckRegion(ptr, len)) {
		return ret;
	}
	VirtualProtect(ptr, len, PAGE_READWRITE, &oldProt);
	if(Prev ? !memcmp(ptr, Prev, len) : 1) {
		memcpy(ptr, New, len);
		ret = 1;
	}
	VirtualProtect(ptr, len, oldProt, &oldProt);
	return ret;
}

int PatchRegionEx(HANDLE hProcess, void *ptr, const void *Prev, const void *New, size_t len)
{
	MEMORY_BASIC_INFORMATION mbi;
	DWORD oldProt;
	VLA(BYTE, old_val, len);
	SIZE_T byte_ret;

	VirtualQueryEx(hProcess, ptr, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
	VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &oldProt);
	ReadProcessMemory(hProcess, ptr, old_val, len, &byte_ret);
	if(Prev ? !memcmp(old_val, Prev, len) : 1) {
		WriteProcessMemory(hProcess, ptr, New, len, &byte_ret);
	}
	VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize, oldProt, &oldProt);
	VLA_FREE(old_val);
	return byte_ret != len;
}

/// Import Address Table detouring
/// ==============================
inline int func_detour(PIMAGE_THUNK_DATA pThunk, const void *new_ptr)
{
	return PatchRegion(&pThunk->u1.Function, NULL, &new_ptr, sizeof(new_ptr));
}

int iat_detour_func(HMODULE hMod, PIMAGE_IMPORT_DESCRIPTOR pImpDesc, const iat_detour_t *detour)
{
	if(!hMod || !pImpDesc || !detour || !detour->new_ptr || !detour->old_func) {
		return -1;
	}
	if(!VirtualCheckCode(detour->new_ptr)) {
		return -2;
	}
	auto pOT = (PIMAGE_THUNK_DATA)((UINT_PTR)hMod + pImpDesc->OriginalFirstThunk);
	auto pIT = (PIMAGE_THUNK_DATA)((UINT_PTR)hMod + pImpDesc->FirstThunk);

	// We generally detour by comparing exported names. This has the advantage
	// that we can override any existing patches, and that it works on Win9x
	// too (as if that matters). However, in case we lack a pointer to the
	// OriginalFirstThunk, or the function is only exported by ordinal, this
	// is not possible, so we have to detour by comparing pointers then.

	if(pImpDesc->OriginalFirstThunk) {
		for(; pOT->u1.Function; pOT++, pIT++) {
			PIMAGE_IMPORT_BY_NAME pByName;
			if(!(pOT->u1.Ordinal & IMAGE_ORDINAL_FLAG)) {
				pByName = (PIMAGE_IMPORT_BY_NAME)((UINT_PTR)hMod + pOT->u1.AddressOfData);
				if(pByName->Name[0] == '\0') {
					return 0;
				}
				if(!stricmp(detour->old_func, (char*)pByName->Name)) {
					return func_detour(pIT, detour->new_ptr);
				}
			} else {
				if((void*)pIT->u1.Function == detour->old_ptr) {
					return func_detour(pIT, detour->new_ptr);
				}
			}
		}
	} else {
		for(; pIT->u1.Function; pIT++) {
			if((void*)pIT->u1.Function == detour->old_ptr) {
				return func_detour(pIT, detour->new_ptr);
			}
		}
	}
	// Function not found
	return 0;
}
/// ----------

/// Detour chaining
/// ---------------
json_t* detour_get_create(const char *dll_name)
{
	json_t *ret = NULL;
	STRLWR_DEC(dll_name);
	STRLWR_CONV(dll_name);
	if(!detours) {
		detours = json_object();
	}
	ret = json_object_get_create(detours, dll_name_lower, JSON_OBJECT);
	STRLWR_FREE(dll_name);

	return ret;
}

int detour_chain(const char *dll_name, int return_old_ptrs, ...)
{
	int ret = 0;
	json_t *dll = detour_get_create(dll_name);
	const char *func_name = NULL;
	va_list va;

	va_start(va, return_old_ptrs);
	while(func_name = va_arg(va, const char*)) {
		FARPROC *old_ptr = NULL;
		FARPROC chain_ptr;
		const void *func_ptr = va_arg(va, const void*);
		if(
			return_old_ptrs
			&& (old_ptr = va_arg(va, FARPROC*))
			&& (chain_ptr = (FARPROC)json_object_get_hex(dll, func_name))
			&& (chain_ptr != func_ptr)
		) {
			*old_ptr = chain_ptr;
		}
		json_object_set_new(dll, func_name, json_integer((size_t)func_ptr));
	}
	va_end(va);
	return ret;
}

int detour_chain_w32u8(const w32u8_dll_t *dll)
{
	const w32u8_pair_t *pair = NULL;
	json_t *detours_dll = NULL;

	if(!dll || !dll->name || !dll->funcs) {
		return -1;
	}
	detours_dll = detour_get_create(dll->name);
	pair = dll->funcs;
	while(pair && pair->ansi_name && pair->utf8_ptr) {
		json_object_set_new(
			detours_dll, pair->ansi_name, json_integer((size_t)pair->utf8_ptr)
		);
		pair++;
	}
	return 0;
}

int iat_detour_apply(HMODULE hMod)
{
	int ret = 0;
	PIMAGE_IMPORT_DESCRIPTOR pImpDesc;

	pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)GetNtDataDirectory(hMod, IMAGE_DIRECTORY_ENTRY_IMPORT);
	if(!pImpDesc) {
		return ret;
	}

	while(pImpDesc->Name) {
		json_t *funcs;
		size_t func_count;
		char *dll_name = (char*)((UINT_PTR)hMod + (UINT_PTR)pImpDesc->Name);
		HMODULE hDll = GetModuleHandleA(dll_name);
		STRLWR_DEC(dll_name);

		STRLWR_CONV(dll_name);
		funcs = json_object_get(detours, dll_name_lower);
		func_count = json_object_size(funcs);

		if(hDll && func_count) {
			const char *func_name;
			json_t *ptr;
			size_t i = 0;

			log_printf("Detouring DLL functions (%s)...\n", dll_name_lower);

			json_object_foreach(funcs, func_name, ptr) {
				iat_detour_t detour;
				int local_ret;

				detour.old_func = func_name;
				detour.old_ptr = GetProcAddress(hDll, detour.old_func);
				detour.new_ptr = (FARPROC)json_integer_value(ptr);

				local_ret = iat_detour_func(hMod, pImpDesc, &detour);

				log_printf(
					"(%2d/%2d) %s... %s\n",
					i + 1, func_count, detour.old_func,
					local_ret ? "OK" : "not found"
				);
				i++;
			}
		}
		STRLWR_FREE(dll_name);
		pImpDesc++;
	}
	return ret;
}

FARPROC detour_top(const char *dll_name, const char *func_name, FARPROC fallback)
{
	json_t *funcs = json_object_get_create(detours, dll_name, JSON_OBJECT);
	FARPROC ret = (FARPROC)json_object_get_hex(funcs, func_name);
	return ret ? ret : fallback;
}

int vtable_detour(void **vtable, const vtable_detour_t *det, size_t det_count)
{
	assert(vtable);
	assert(det);

	if(det_count == 0) {
		return 0;
	}

	DWORD old_prot;
	int replaced = 0;
	size_t i;

	// VirtualProtect() is infamously slow, so...
	size_t lowest = (size_t)-1;
	size_t highest = 0;

	for(i = 0; i < det_count; i++) {
		lowest = MIN(lowest, det[i].index);
		highest = MAX(highest, det[i].index);
	}

	size_t bytes_to_lock = ((highest + 1) - lowest) * sizeof(void*);

	VirtualProtect(vtable + lowest, bytes_to_lock, PAGE_READWRITE, &old_prot);
	for(i = 0; i < det_count; i++) {
		auto& cur = det[i];

		bool replace =
			(cur.old_func == nullptr) || (*cur.old_func == nullptr)
			|| (*cur.old_func == vtable[cur.index]);
		bool set_old = (cur.old_func != nullptr) && (*cur.old_func == nullptr);

		if(set_old) {
			*cur.old_func = vtable[cur.index];
		}
		if(replace) {
			vtable[cur.index] = cur.new_func;
			replaced++;
		}
	}
	VirtualProtect(vtable + lowest, bytes_to_lock, old_prot, &old_prot);
	return replaced;
}

void detour_exit(void)
{
	detours = json_decref_safe(detours);
}
/// ----------

/// =============================
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

// Base class for generators using external MC generators.
// For example AliGenPythia using Pythia.
// Provides basic functionality: setting of kinematic cuts on
// decay products and particle selection.
// andreas.morsch@cern.ch

#include <TClonesArray.h>
#include <TMath.h>
#include <TPDGCode.h>
#include <TParticle.h>

#include "AliGenMC.h"
#include "AliGeometry.h"

ClassImp(AliGenMC)

AliGenMC::AliGenMC()
    :AliGenerator()
{
// Default Constructor
    SetCutOnChild();
    SetChildMomentumRange();
    SetChildPtRange();
    SetChildPhiRange();
    SetChildThetaRange();
    SetChildYRange();
    SetMaximumLifetime();
    SetGeometryAcceptance();
    SetPdgCodeParticleforAcceptanceCut();
    SetNumberOfAcceptedParticles();
    SetTarget();
    SetProjectile();
    fParentSelect.Set(8);
    fChildSelect.Set(8);
    fForceDecay = kAll;
}

AliGenMC::AliGenMC(Int_t npart)
    :AliGenerator(npart)
{
//  Constructor
    SetCutOnChild();
    SetChildMomentumRange();
    SetChildPtRange();
    SetChildPhiRange();
    SetChildThetaRange();
    SetChildYRange();
//
    fParentSelect.Set(8);
    fChildSelect.Set(8);
    for (Int_t i=0; i<8; i++) fParentSelect[i]=fChildSelect[i]=0;
    SetMaximumLifetime();
    SetGeometryAcceptance();
    SetPdgCodeParticleforAcceptanceCut();
    SetNumberOfAcceptedParticles();
    SetTarget();
    SetProjectile();
    fForceDecay = kAll;
}

AliGenMC::AliGenMC(const AliGenMC & mc):
    AliGenerator(mc)
{
// Copy constructor
    mc.Copy(*this);
}

AliGenMC::~AliGenMC()
{
// Destructor
}

void AliGenMC::Init()
{
//
//  Initialization
    switch (fForceDecay) {
    case kSemiElectronic:
    case kDiElectron:
    case kBJpsiDiElectron:
    case kBPsiPrimeDiElectron:
	fChildSelect[0] = kElectron;
	break;
    case kHardMuons:
    case kSemiMuonic:
    case kDiMuon:
    case kBJpsiDiMuon:
    case kBPsiPrimeDiMuon:
    case kPiToMu:
    case kKaToMu:
	fChildSelect[0]=kMuonMinus;
	break;
    case kHadronicD:
	fChildSelect[0]=kPiPlus;
	fChildSelect[1]=kKPlus;
	break;
    case kPhiKK:
	fChildSelect[0]=kKPlus;
	break;
    case kBJpsi:
	fChildSelect[0]=443;
	break;
    case kOmega:
    case kAll:
    case kNoDecay:
    case kNoDecayHeavy:
	break;
    }

    if (fZTarget != 0 && fAProjectile != 0)
    {
	fDyBoost    = - 0.5 * TMath::Log(Double_t(fZProjectile) * Double_t(fATarget) /
					 (Double_t(fZTarget)    * Double_t(fAProjectile)));
    }
}

Bool_t AliGenMC::ParentSelected(Int_t ip) const
{
// True if particle is in list of parent particles to be selected
    for (Int_t i=0; i<8; i++)
    {
	if (fParentSelect.At(i) == ip) return kTRUE;
    }
    return kFALSE;
}

Bool_t AliGenMC::ChildSelected(Int_t ip) const
{
// True if particle is in list of decay products to be selected
    for (Int_t i=0; i<5; i++)
    {
	if (fChildSelect.At(i) == ip) return kTRUE;
    }
    return kFALSE;
}

Bool_t AliGenMC::KinematicSelection(TParticle *particle, Int_t flag) const
{
// Perform kinematic selection
    Float_t pz    = particle->Pz();
    Float_t  e    = particle->Energy();
    Float_t pt    = particle->Pt();
    Float_t p     = particle->P();
    Float_t theta = particle->Theta();
    Float_t mass  = particle->GetCalcMass();
    Float_t mt2   = pt * pt + mass * mass;
    Float_t phi   = particle->Phi();

    Double_t y, y0;

    if (TMath::Abs(pz) <  e) {
	y = 0.5*TMath::Log((e+pz)/(e-pz));
    } else {
	y = 1.e10;
    }

    if (mt2) {
	y0 = 0.5*TMath::Log((e+TMath::Abs(pz))*(e+TMath::Abs(pz))/mt2);
    } else {
	if (TMath::Abs(y) < 1.e10) {
	    y0 = y;
	} else {
	    y0 = 1.e10;
	}
    }

    y = (pz < 0) ? -y0 : y0;

    if (flag == 0) {
//
// Primary particle cuts
//
//  transverse momentum cut
	if (pt > fPtMax || pt < fPtMin) {
//	    printf("\n failed pt cut %f %f %f \n",pt,fPtMin,fPtMax);
	    return kFALSE;
	}
//
// momentum cut
	if (p > fPMax || p < fPMin) {
//	    printf("\n failed p cut %f %f %f \n",p,fPMin,fPMax);
	    return kFALSE;
	}
//
// theta cut
	if (theta > fThetaMax || theta < fThetaMin) {
//	    printf("\n failed theta cut %f %f %f \n",theta,fThetaMin,fThetaMax);
	    return kFALSE;
	}
//
// rapidity cut
	if (y > fYMax || y < fYMin) {
//	    printf("\n failed y cut %f %f %f \n",y,fYMin,fYMax);
	    return kFALSE;
	}
//
// phi cut
	if (phi > fPhiMax || phi < fPhiMin) {
//	    printf("\n failed phi cut %f %f %f \n",phi,fPhiMin,fPhiMax);
	    return kFALSE;
	}
    } else {
//
// Decay product cuts
//
//  transverse momentum cut
	if (pt > fChildPtMax || pt < fChildPtMin) {
//	    printf("\n failed pt cut %f %f %f \n",pt,fChildPtMin,fChildPtMax);
	    return kFALSE;
	}
//
// momentum cut
	if (p > fChildPMax || p < fChildPMin) {
//	    printf("\n failed p cut %f %f %f \n",p,fChildPMin,fChildPMax);
	    return kFALSE;
	}
//
// theta cut
	if (theta > fChildThetaMax || theta < fChildThetaMin) {
//	    printf("\n failed theta cut %f %f %f \n",theta,fChildThetaMin,fChildThetaMax);
	    return kFALSE;
	}
//
// rapidity cut
	if (y > fChildYMax || y < fChildYMin) {
//	    printf("\n failed y cut %f %f %f \n",y,fChildYMin,fChildYMax);
	    return kFALSE;
	}
//
// phi cut
	if (phi > fChildPhiMax || phi < fChildPhiMin) {
//	    printf("\n failed phi cut %f %f %f \n",phi,fChildPhiMin,fChildPhiMax);
	    return kFALSE;
	}
    }

    return kTRUE;
}

Bool_t AliGenMC::CheckAcceptanceGeometry(Int_t np, TClonesArray* particles)
{
// Check the geometrical acceptance for particle.

  Bool_t check ;
  Int_t numberOfPdgCodeParticleforAcceptanceCut = 0;
  Int_t numberOfAcceptedPdgCodeParticleforAcceptanceCut = 0;
  TParticle * particle;
  Int_t i;
  for (i = 0; i < np; i++) {
    particle =  (TParticle *) particles->At(i);
    if( TMath::Abs( particle->GetPdgCode() ) == TMath::Abs( fPdgCodeParticleforAcceptanceCut ) ) {
      numberOfPdgCodeParticleforAcceptanceCut++;
      if (fGeometryAcceptance->Impact(particle)) numberOfAcceptedPdgCodeParticleforAcceptanceCut++;
    }
  }
  if ( numberOfAcceptedPdgCodeParticleforAcceptanceCut > (fNumberOfAcceptedParticles-1) )
    check = kTRUE;
  else
    check = kFALSE;

  return check;
}

Int_t AliGenMC::CheckPDGCode(Int_t pdgcode) const
{
//
//  If the particle is in a diffractive state, then take action accordingly
  switch (pdgcode) {
  case 91:
    return 92;
  case 110:
    //rho_diff0 -- difficult to translate, return rho0
    return 113;
  case 210:
    //pi_diffr+ -- change to pi+
    return 211;
  case 220:
    //omega_di0 -- change to omega0
    return 223;
  case 330:
    //phi_diff0 -- return phi0
    return 333;
  case 440:
    //J/psi_di0 -- return J/psi
    return 443;
  case 2110:
    //n_diffr -- return neutron
    return 2112;
  case 2210:
    //p_diffr+ -- return proton
    return 2212;
  }
  //non diffractive state -- return code unchanged
  return pdgcode;
}

void AliGenMC::Boost()
{
//
// Boost cms into LHC lab frame
//

    Double_t beta  = TMath::TanH(fDyBoost);
    Double_t gamma = 1./TMath::Sqrt(1.-beta*beta);
    Double_t gb    = gamma * beta;

    //    printf("\n Boosting particles to lab frame %f %f %f", fDyBoost, beta, gamma);

    Int_t i;
    Int_t np = fParticles->GetEntriesFast();
    for (i = 0; i < np; i++)
    {
	TParticle* iparticle = (TParticle*) fParticles->At(i);

	Double_t e   = iparticle->Energy();
	Double_t px  = iparticle->Px();
	Double_t py  = iparticle->Py();
	Double_t pz  = iparticle->Pz();

	Double_t eb  = gamma * e -      gb * pz;
	Double_t pzb =   -gb * e +   gamma * pz;

	iparticle->SetMomentum(px, py, pzb, eb);
    }
}

AliGenMC& AliGenMC::operator=(const  AliGenMC& rhs)
{
// Assignment operator
    rhs.Copy(*this);
    return *this;
}

void AliGenMC::Copy(TObject&) const
{
    //
    // Copy
    //
    Fatal("Copy","Not implemented!\n");
}

<commit_msg>Decay options or W added. (Z. Conesa)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

// Base class for generators using external MC generators.
// For example AliGenPythia using Pythia.
// Provides basic functionality: setting of kinematic cuts on
// decay products and particle selection.
// andreas.morsch@cern.ch

#include <TClonesArray.h>
#include <TMath.h>
#include <TPDGCode.h>
#include <TParticle.h>

#include "AliGenMC.h"
#include "AliGeometry.h"

ClassImp(AliGenMC)

AliGenMC::AliGenMC()
    :AliGenerator()
{
// Default Constructor
    SetCutOnChild();
    SetChildMomentumRange();
    SetChildPtRange();
    SetChildPhiRange();
    SetChildThetaRange();
    SetChildYRange();
    SetMaximumLifetime();
    SetGeometryAcceptance();
    SetPdgCodeParticleforAcceptanceCut();
    SetNumberOfAcceptedParticles();
    SetTarget();
    SetProjectile();
    fParentSelect.Set(8);
    fChildSelect.Set(8);
    fForceDecay = kAll;
}

AliGenMC::AliGenMC(Int_t npart)
    :AliGenerator(npart)
{
//  Constructor
    SetCutOnChild();
    SetChildMomentumRange();
    SetChildPtRange();
    SetChildPhiRange();
    SetChildThetaRange();
    SetChildYRange();
//
    fParentSelect.Set(8);
    fChildSelect.Set(8);
    for (Int_t i=0; i<8; i++) fParentSelect[i]=fChildSelect[i]=0;
    SetMaximumLifetime();
    SetGeometryAcceptance();
    SetPdgCodeParticleforAcceptanceCut();
    SetNumberOfAcceptedParticles();
    SetTarget();
    SetProjectile();
    fForceDecay = kAll;
}

AliGenMC::AliGenMC(const AliGenMC & mc):
    AliGenerator(mc)
{
// Copy constructor
    mc.Copy(*this);
}

AliGenMC::~AliGenMC()
{
// Destructor
}

void AliGenMC::Init()
{
//
//  Initialization
    switch (fForceDecay) {
    case kSemiElectronic:
    case kDiElectron:
    case kBJpsiDiElectron:
    case kBPsiPrimeDiElectron:
	fChildSelect[0] = kElectron;
	break;
    case kHardMuons:
    case kSemiMuonic:
    case kDiMuon:
    case kBJpsiDiMuon:
    case kBPsiPrimeDiMuon:
    case kPiToMu:
    case kKaToMu:
    case kWToMuon:
    case kWToCharmToMuon:
	fChildSelect[0]=kMuonMinus;
	break;
    case kWToCharm:
	break;
    case kHadronicD:
	fChildSelect[0]=kPiPlus;
	fChildSelect[1]=kKPlus;
	break;
    case kPhiKK:
	fChildSelect[0]=kKPlus;
	break;
    case kBJpsi:
	fChildSelect[0]=443;
	break;
    case kOmega:
    case kAll:
    case kNoDecay:
    case kNoDecayHeavy:
	break;
    }

    if (fZTarget != 0 && fAProjectile != 0)
    {
	fDyBoost    = - 0.5 * TMath::Log(Double_t(fZProjectile) * Double_t(fATarget) /
					 (Double_t(fZTarget)    * Double_t(fAProjectile)));
    }
}

Bool_t AliGenMC::ParentSelected(Int_t ip) const
{
// True if particle is in list of parent particles to be selected
    for (Int_t i=0; i<8; i++)
    {
	if (fParentSelect.At(i) == ip) return kTRUE;
    }
    return kFALSE;
}

Bool_t AliGenMC::ChildSelected(Int_t ip) const
{
// True if particle is in list of decay products to be selected
    for (Int_t i=0; i<5; i++)
    {
	if (fChildSelect.At(i) == ip) return kTRUE;
    }
    return kFALSE;
}

Bool_t AliGenMC::KinematicSelection(TParticle *particle, Int_t flag) const
{
// Perform kinematic selection
    Float_t pz    = particle->Pz();
    Float_t  e    = particle->Energy();
    Float_t pt    = particle->Pt();
    Float_t p     = particle->P();
    Float_t theta = particle->Theta();
    Float_t mass  = particle->GetCalcMass();
    Float_t mt2   = pt * pt + mass * mass;
    Float_t phi   = particle->Phi();

    Double_t y, y0;

    if (TMath::Abs(pz) <  e) {
	y = 0.5*TMath::Log((e+pz)/(e-pz));
    } else {
	y = 1.e10;
    }

    if (mt2) {
	y0 = 0.5*TMath::Log((e+TMath::Abs(pz))*(e+TMath::Abs(pz))/mt2);
    } else {
	if (TMath::Abs(y) < 1.e10) {
	    y0 = y;
	} else {
	    y0 = 1.e10;
	}
    }

    y = (pz < 0) ? -y0 : y0;

    if (flag == 0) {
//
// Primary particle cuts
//
//  transverse momentum cut
	if (pt > fPtMax || pt < fPtMin) {
//	    printf("\n failed pt cut %f %f %f \n",pt,fPtMin,fPtMax);
	    return kFALSE;
	}
//
// momentum cut
	if (p > fPMax || p < fPMin) {
//	    printf("\n failed p cut %f %f %f \n",p,fPMin,fPMax);
	    return kFALSE;
	}
//
// theta cut
	if (theta > fThetaMax || theta < fThetaMin) {
//	    printf("\n failed theta cut %f %f %f \n",theta,fThetaMin,fThetaMax);
	    return kFALSE;
	}
//
// rapidity cut
	if (y > fYMax || y < fYMin) {
//	    printf("\n failed y cut %f %f %f \n",y,fYMin,fYMax);
	    return kFALSE;
	}
//
// phi cut
	if (phi > fPhiMax || phi < fPhiMin) {
//	    printf("\n failed phi cut %f %f %f \n",phi,fPhiMin,fPhiMax);
	    return kFALSE;
	}
    } else {
//
// Decay product cuts
//
//  transverse momentum cut
	if (pt > fChildPtMax || pt < fChildPtMin) {
//	    printf("\n failed pt cut %f %f %f \n",pt,fChildPtMin,fChildPtMax);
	    return kFALSE;
	}
//
// momentum cut
	if (p > fChildPMax || p < fChildPMin) {
//	    printf("\n failed p cut %f %f %f \n",p,fChildPMin,fChildPMax);
	    return kFALSE;
	}
//
// theta cut
	if (theta > fChildThetaMax || theta < fChildThetaMin) {
//	    printf("\n failed theta cut %f %f %f \n",theta,fChildThetaMin,fChildThetaMax);
	    return kFALSE;
	}
//
// rapidity cut
	if (y > fChildYMax || y < fChildYMin) {
//	    printf("\n failed y cut %f %f %f \n",y,fChildYMin,fChildYMax);
	    return kFALSE;
	}
//
// phi cut
	if (phi > fChildPhiMax || phi < fChildPhiMin) {
//	    printf("\n failed phi cut %f %f %f \n",phi,fChildPhiMin,fChildPhiMax);
	    return kFALSE;
	}
    }

    return kTRUE;
}

Bool_t AliGenMC::CheckAcceptanceGeometry(Int_t np, TClonesArray* particles)
{
// Check the geometrical acceptance for particle.

  Bool_t check ;
  Int_t numberOfPdgCodeParticleforAcceptanceCut = 0;
  Int_t numberOfAcceptedPdgCodeParticleforAcceptanceCut = 0;
  TParticle * particle;
  Int_t i;
  for (i = 0; i < np; i++) {
    particle =  (TParticle *) particles->At(i);
    if( TMath::Abs( particle->GetPdgCode() ) == TMath::Abs( fPdgCodeParticleforAcceptanceCut ) ) {
      numberOfPdgCodeParticleforAcceptanceCut++;
      if (fGeometryAcceptance->Impact(particle)) numberOfAcceptedPdgCodeParticleforAcceptanceCut++;
    }
  }
  if ( numberOfAcceptedPdgCodeParticleforAcceptanceCut > (fNumberOfAcceptedParticles-1) )
    check = kTRUE;
  else
    check = kFALSE;

  return check;
}

Int_t AliGenMC::CheckPDGCode(Int_t pdgcode) const
{
//
//  If the particle is in a diffractive state, then take action accordingly
  switch (pdgcode) {
  case 91:
    return 92;
  case 110:
    //rho_diff0 -- difficult to translate, return rho0
    return 113;
  case 210:
    //pi_diffr+ -- change to pi+
    return 211;
  case 220:
    //omega_di0 -- change to omega0
    return 223;
  case 330:
    //phi_diff0 -- return phi0
    return 333;
  case 440:
    //J/psi_di0 -- return J/psi
    return 443;
  case 2110:
    //n_diffr -- return neutron
    return 2112;
  case 2210:
    //p_diffr+ -- return proton
    return 2212;
  }
  //non diffractive state -- return code unchanged
  return pdgcode;
}

void AliGenMC::Boost()
{
//
// Boost cms into LHC lab frame
//

    Double_t beta  = TMath::TanH(fDyBoost);
    Double_t gamma = 1./TMath::Sqrt(1.-beta*beta);
    Double_t gb    = gamma * beta;

    //    printf("\n Boosting particles to lab frame %f %f %f", fDyBoost, beta, gamma);

    Int_t i;
    Int_t np = fParticles->GetEntriesFast();
    for (i = 0; i < np; i++)
    {
	TParticle* iparticle = (TParticle*) fParticles->At(i);

	Double_t e   = iparticle->Energy();
	Double_t px  = iparticle->Px();
	Double_t py  = iparticle->Py();
	Double_t pz  = iparticle->Pz();

	Double_t eb  = gamma * e -      gb * pz;
	Double_t pzb =   -gb * e +   gamma * pz;

	iparticle->SetMomentum(px, py, pzb, eb);
    }
}

AliGenMC& AliGenMC::operator=(const  AliGenMC& rhs)
{
// Assignment operator
    rhs.Copy(*this);
    return *this;
}

void AliGenMC::Copy(TObject&) const
{
    //
    // Copy
    //
    Fatal("Copy","Not implemented!\n");
}

<|endoftext|>


<commit_before>/*
  Copyright 2007 Albert Strasheim <fullung@gmail.com>

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "pyactivemq.h"

#include <boost/python/class.hpp>
#include <boost/python/object/pointer_holder.hpp>

#include <cms/Message.h>
#include <cms/Topic.h>
#include <cms/Queue.h>
#include <cms/TemporaryTopic.h>
#include <cms/TemporaryQueue.h>

namespace py = boost::python;

using cms::Message;
using cms::Destination;
using cms::Topic;
using cms::Queue;
using cms::TemporaryTopic;
using cms::TemporaryQueue;

static const char* Message_docstring =
    "Root of all messages.\n\nAs in JMS, a message is comprised of 3 parts: "
    "CMS-specific headers, user-defined properties, and the body.";
static const char* Message_acknowledge_docstring =
    "Acknowledges all consumed messages of the session of this consumed message.\n\n"
    "All consumed CMS messages support the acknowledge method for use when a client "
    "has specified that its CMS session's consumed messages are to be explicitly "
    "acknowledged. By invoking acknowledge on a consumed message, a client "
    "acknowledges all messages consumed by the session that the message was delivered"
    " to.\n\nCalls to acknowledge are ignored for both transacted sessions and "
    "sessions specified to use implicit acknowledgement modes.\n\nA client may "
    "individually acknowledge each message as it is consumed, or it may choose to "
    "acknowledge messages as an application-defined group (which is done by calling "
    "acknowledge on the last received message of the group, thereby acknowledging "
    "all messages consumed by the session.)\n\nMessages that have been received but "
    "not acknowledged may be redelivered.";
static const char* Message_clearBody_docstring =
    "Clears out the body of the message.\n\nThis does not clear the headers or properties.";
static const char* Message_clearProperties_docstring =
    "Clears out the message body.\n\nClearing a message's body does not clear its "
    "header values or property entries.\n\nIf this message body was read-only, "
    "calling this method leaves the message body in the same state as an empty body "
    "in a newly created message.";
static const char* Message_propertyNames_docstring = "Retrieves the complete set of property names currently in this message.";
static const char* Message_propertyExists_docstring = "Indicates whether or not a given property exists.";
static const char* Message_getBooleanProperty_docstring = "Gets a boolean property.";
static const char* Message_getByteProperty_docstring = "Gets a byte property.";
static const char* Message_getDoubleProperty_docstring = "Gets a double property.";
static const char* Message_getFloatProperty_docstring = "Gets a float property.";
static const char* Message_getIntProperty_docstring = "Gets a int property.";
static const char* Message_getLongProperty_docstring = "Gets a long property.";
static const char* Message_getShortProperty_docstring = "Gets a short property.";
static const char* Message_getStringProperty_docstring = "Gets a string property.";
static const char* Message_setBooleanProperty_docstring = "Sets a boolean property.";
static const char* Message_setByteProperty_docstring = "Sets a byte property.";
static const char* Message_setDoubleProperty_docstring = "Sets a double property.";
static const char* Message_setFloatProperty_docstring = "Sets a float property.";
static const char* Message_setIntProperty_docstring = "Sets a int property.";
static const char* Message_setLongProperty_docstring = "Sets a long property.";
static const char* Message_setShortProperty_docstring = "Sets a short property.";
static const char* Message_setStringProperty_docstring = "Sets a string property.";
static const char* Message_deliveryMode_docstring = "Gets the L{DeliveryMode} for this message.";
static const char* Message_expiration_docstring =
    "Gets the message's expiration value.\n\nWhen a message is sent, the expiration "
    "header field is left unassigned. After completion of the send or publish method, "
    "it holds the expiration time of the message. This is the sum of the time-to-live "
    "value specified by the client and the GMT at the time of the send or publish.\n\n"
    "If the time-to-live is specified as zero, expiration is set to zero to indicate "
    "that the message does not expire.\n\nWhen a message's expiration time is reached,"
    " a provider should discard it.";
static const char* Message_messageID_docstring =
    "The C{messageID} header field contains a value that uniquely identifies each message"
    " sent by a provider.\n\nWhen a message is sent, messageID can be ignored. When the "
    "send or publish method returns, it contains a provider-assigned value.\n\nA "
    "messageID is a C{String} value that should function as a unique key for "
    "identifying messages in a historical repository. The exact scope of uniqueness is "
    "provider-defined. It should at least cover all messages for a specific "
    "installation of a provider, where an installation is some connected set of "
    "message routers.\n\nAll C{messageID} values must start with the prefix 'C{ID:}'. "
    "Uniqueness of message ID values across different providers is not required.\n\n"
    "Since message IDs take some effort to create and increase a message's size, some "
    "CMS providers may be able to optimize message overhead if they are given a hint "
    "that the message ID is not used by an application. By setting the "
    "L{MessageProducer.disableMessageID} method, a CMS client enables this potential "
    "optimization for all messages sent by that message producer. If the CMS provider "
    "accepts this hint, these messages must have the message ID set to null; if the "
    "provider ignores the hint, the message ID must be set to its normal unique value.";
static const char* Message_priority_docstring =
    "Gets the message priority level.\n\nThe CMS API defines ten levels of priority "
    "value, with 0 as the lowest priority and 9 as the highest. In addition, clients "
    "should consider priorities 0-4 as gradations of normal priority and priorities 5-9 "
    "as gradations of expedited priority.\n\nThe CMS API does not require that a "
    "provider strictly implements priority ordering of messages; however, it should do "
    "its best to deliver expedited messages ahead of normal messages.";
static const char* Message_redelivered_docstring =
    "Gets an indication of whether this message is being redelivered.\n\nIf a client "
    "receives a message with the redelivered field set, it is likely, but not "
    "guaranteed, that this message was delivered earlier but that its receipt was not "
    "acknowledged at that time.";
static const char* Message_timestamp_docstring =
    "Gets the message timestamp.\n\nThe C{timestamp} header field contains the time a "
    "message was handed off to a provider to be sent. It is not the time the message was"
    " actually transmitted, because the actual send may occur later due to transactions "
    "or other client-side queueing of messages.\n\nWhen a message is sent, C{timestamp} "
    "is ignored. When the send or publish method returns, it contains a time value "
    "somewhere in the interval between the call and the return. The value is in the "
    "format of a normal millis time value in the Java programming language.\n\nSince "
    "timestamps take some effort to create and increase a message's size, some CMS "
    "providers may be able to optimize message overhead if they are given a hint that "
    "the timestamp is not used by an application. By setting "
    "L{MessageProducer.disableMessageTimeStamp}, a CMS client enables this potential "
    "optimization for all messages sent by that message producer. If the CMS provider "
    "accepts this hint, these messages must have the timestamp set to zero; if the "
    "provider ignores the hint, the timestamp must be set to its normal value.";
static const char* Message_replyTo_docstring =
    "The L{Destination} object to which a reply to this message should be sent."
    "\n\nThe C{replyTo} header field contains the destination where a reply to "
    "the current message should be sent. If it is null, no reply is expected. "
    "The destination may be either a L{Queue} object or a L{Topic} object.\n\n"
    "Messages sent with a null C{replyTo} value may be a notification of some "
    "event, or they may just be some data the sender thinks is of interest.\n\n"
    "Messages with a C{replyTo} value typically expect a response. A response "
    "is optional; it is up to the client to decide. These messages are called "
    "requests. A message sent in response to a request is called a reply.\n\n"
    "In some cases a client may wish to match a request it sent earlier with "
    "a reply it has just received. The client can use the L{correlationID} "
    "header field for this purpose.";
static const char* Message_destination_docstring =
    "Returns the L{Destination} object for this message.\n\nThe destination header "
    "field contains the destination to which the message is being sent.\n\nWhen a "
    "message is sent, this field is ignored. After completion of the send or "
    "publish method, the field holds the destination specified by the method.\n\n"
    "When a message is received, its C{destination} value must be equivalent to "
    "the value assigned when it was sent.";
static const char* Message_correlationID_docstring =
    "The correlation ID for the message.\n\nA client can use the C{correlationID} "
    "header field to link one message with another. A typical use is to link a "
    "response message with its request message.\n\nC{correlationID} can hold one "
    "of the following:\n\n"
    " - A provider-specific message ID\n\n"
    " - An application-specific string\n\n"
    " - A provider-native byte value\n\n"
    "Since each message sent by a CMS provider is assigned a message ID value, "
    "it is convenient to link messages via message ID. All message ID values "
    "must start with the 'C{ID:}' prefix.\n\nIn some cases, an application "
    "(made up of several clients) needs to use an application-specific value "
    "for linking messages. For instance, an application may use "
    "C{correlationID} to hold a value referencing some external information. "
    "Application-specified values must not start with the 'C{ID:}' prefix; this "
    "is reserved for provider-generated message ID values.\n\nIf a provider "
    "supports the native concept of correlation ID, a CMS client may need to "
    "assign specific C{correlationID} values to match those expected by clients "
    "that do not use the CMS API. A byte value is used for this purpose. CMS "
    "providers without native correlation ID values are not required to "
    "support byte values. The use of a byte value for correlationID is "
    "non-portable.";
static const char* Message_type_docstring =
    "Sets the message type.\n\nSome CMS providers use a message repository that "
    "contains the definitions of messages sent by applications. The C{type} header "
    "field may reference a message's definition in the provider's repository.\n\n"
    "The CMS API does not define a standard message definition repository, nor "
    "does it define a naming policy for the definitions it contains.\n\nSome "
    "messaging systems require that a message type definition for each application "
    "message be created and that each message specify its type. In order to work "
    "with such CMS providers, CMS clients should assign a value to C{type}, "
    "whether the application makes use of it or not. This ensures that the field "
    "is properly set for those providers that require it.\n\nTo ensure portability, "
    "CMS clients should use symbolic values for C{type} that can be configured at "
    "installation time to the values defined in the current provider's message "
    "repository. If string literals are used, they may not be valid type names "
    "for some CMS providers.";

void export_Message()
{
    py::class_<Message, boost::noncopyable>("Message", Message_docstring, py::no_init)
        .def("acknowledge", &Message::acknowledge, Message_acknowledge_docstring)
        .def("clearBody", &Message::clearBody, Message_clearBody_docstring)
        .def("clearProperties", &Message::clearProperties, Message_clearProperties_docstring)
        .add_property("propertyNames", &Message::getPropertyNames, Message_propertyNames_docstring)
        .def("propertyExists", &Message::propertyExists, Message_propertyExists_docstring)
        .def("getBooleanProperty", &Message::getBooleanProperty, Message_getBooleanProperty_docstring)
        .def("getByteProperty", &Message::getByteProperty, Message_getByteProperty_docstring)
        .def("getDoubleProperty", &Message::getDoubleProperty, Message_getDoubleProperty_docstring)
        .def("getFloatProperty", &Message::getFloatProperty, Message_getFloatProperty_docstring)
        .def("getIntProperty", &Message::getIntProperty, Message_getIntProperty_docstring)
        .def("getLongProperty", &Message::getLongProperty, Message_getLongProperty_docstring)
        .def("getShortProperty", &Message::getShortProperty, Message_getShortProperty_docstring)
        .def("getStringProperty", &Message::getStringProperty, Message_getStringProperty_docstring)
        .def("setBooleanProperty", &Message::setBooleanProperty, Message_setBooleanProperty_docstring)
        .def("setByteProperty", &Message::setByteProperty, Message_setByteProperty_docstring)
        .def("setDoubleProperty", &Message::setDoubleProperty, Message_setDoubleProperty_docstring)
        .def("setFloatProperty", &Message::setFloatProperty, Message_setFloatProperty_docstring)
        .def("setIntProperty", &Message::setIntProperty, Message_setIntProperty_docstring)
        .def("setLongProperty", &Message::setLongProperty, Message_setLongProperty_docstring)
        .def("setShortProperty", &Message::setShortProperty, Message_setShortProperty_docstring)
        .def("setStringProperty", &Message::setStringProperty, Message_setStringProperty_docstring)
        // read-only properties
        .add_property("deliveryMode", &Message::getCMSDeliveryMode, Message_deliveryMode_docstring)
        .add_property("expiration", &Message::getCMSExpiration, Message_expiration_docstring)
        .add_property("messageID", &Message::getCMSMessageID, Message_messageID_docstring)
        .add_property("priority", &Message::getCMSPriority, Message_priority_docstring)
        .add_property("redelivered", &Message::getCMSRedelivered, Message_redelivered_docstring)
        .add_property("timestamp", &Message::getCMSTimestamp, Message_timestamp_docstring)
        // read-write properties
        .add_property("replyTo",
                      make_function(&Message::getCMSReplyTo, py::return_internal_reference<>()),
                      make_function(&Message::setCMSReplyTo, py::with_custodian_and_ward<1, 2>()),
                      Message_replyTo_docstring)
        .add_property("destination",
                      make_function(&Message::getCMSDestination, py::return_internal_reference<>()),
                      make_function(&Message::setCMSDestination, py::with_custodian_and_ward<1, 2>()),
                      Message_destination_docstring)
        .add_property("correlationID", &Message::getCMSCorrelationID, &Message::setCMSCorrelationID,
                      Message_correlationID_docstring)
        .add_property("type", &Message::getCMSType, &Message::setCMSType, Message_type_docstring)
        ;
}
<commit_msg>Wrapped Message::clone.<commit_after>/*
  Copyright 2007 Albert Strasheim <fullung@gmail.com>

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "pyactivemq.h"

#include <boost/python/class.hpp>
#include <boost/python/object/pointer_holder.hpp>
#include <boost/python/manage_new_object.hpp>

#include <cms/Message.h>
#include <cms/Topic.h>
#include <cms/Queue.h>
#include <cms/TemporaryTopic.h>
#include <cms/TemporaryQueue.h>

namespace py = boost::python;

using cms::Message;
using cms::Destination;
using cms::Topic;
using cms::Queue;
using cms::TemporaryTopic;
using cms::TemporaryQueue;

static const char* Message_docstring =
    "Root of all messages.\n\nAs in JMS, a message is comprised of 3 parts: "
    "CMS-specific headers, user-defined properties, and the body.";
static const char* Message_acknowledge_docstring =
    "Acknowledges all consumed messages of the session of this consumed message.\n\n"
    "All consumed CMS messages support the acknowledge method for use when a client "
    "has specified that its CMS session's consumed messages are to be explicitly "
    "acknowledged. By invoking acknowledge on a consumed message, a client "
    "acknowledges all messages consumed by the session that the message was delivered"
    " to.\n\nCalls to acknowledge are ignored for both transacted sessions and "
    "sessions specified to use implicit acknowledgement modes.\n\nA client may "
    "individually acknowledge each message as it is consumed, or it may choose to "
    "acknowledge messages as an application-defined group (which is done by calling "
    "acknowledge on the last received message of the group, thereby acknowledging "
    "all messages consumed by the session.)\n\nMessages that have been received but "
    "not acknowledged may be redelivered.";
static const char* Message_clearBody_docstring =
    "Clears out the body of the message.\n\nThis does not clear the headers or properties.";
static const char* Message_clearProperties_docstring =
    "Clears out the message body.\n\nClearing a message's body does not clear its "
    "header values or property entries.\n\nIf this message body was read-only, "
    "calling this method leaves the message body in the same state as an empty body "
    "in a newly created message.";
static const char* Message_propertyNames_docstring = "Retrieves the complete set of property names currently in this message.";
static const char* Message_propertyExists_docstring = "Indicates whether or not a given property exists.";
static const char* Message_getBooleanProperty_docstring = "Gets a boolean property.";
static const char* Message_getByteProperty_docstring = "Gets a byte property.";
static const char* Message_getDoubleProperty_docstring = "Gets a double property.";
static const char* Message_getFloatProperty_docstring = "Gets a float property.";
static const char* Message_getIntProperty_docstring = "Gets a int property.";
static const char* Message_getLongProperty_docstring = "Gets a long property.";
static const char* Message_getShortProperty_docstring = "Gets a short property.";
static const char* Message_getStringProperty_docstring = "Gets a string property.";
static const char* Message_setBooleanProperty_docstring = "Sets a boolean property.";
static const char* Message_setByteProperty_docstring = "Sets a byte property.";
static const char* Message_setDoubleProperty_docstring = "Sets a double property.";
static const char* Message_setFloatProperty_docstring = "Sets a float property.";
static const char* Message_setIntProperty_docstring = "Sets a int property.";
static const char* Message_setLongProperty_docstring = "Sets a long property.";
static const char* Message_setShortProperty_docstring = "Sets a short property.";
static const char* Message_setStringProperty_docstring = "Sets a string property.";
static const char* Message_deliveryMode_docstring = "Gets the L{DeliveryMode} for this message.";
static const char* Message_expiration_docstring =
    "Gets the message's expiration value.\n\nWhen a message is sent, the expiration "
    "header field is left unassigned. After completion of the send or publish method, "
    "it holds the expiration time of the message. This is the sum of the time-to-live "
    "value specified by the client and the GMT at the time of the send or publish.\n\n"
    "If the time-to-live is specified as zero, expiration is set to zero to indicate "
    "that the message does not expire.\n\nWhen a message's expiration time is reached,"
    " a provider should discard it.";
static const char* Message_messageID_docstring =
    "The C{messageID} header field contains a value that uniquely identifies each message"
    " sent by a provider.\n\nWhen a message is sent, messageID can be ignored. When the "
    "send or publish method returns, it contains a provider-assigned value.\n\nA "
    "messageID is a C{String} value that should function as a unique key for "
    "identifying messages in a historical repository. The exact scope of uniqueness is "
    "provider-defined. It should at least cover all messages for a specific "
    "installation of a provider, where an installation is some connected set of "
    "message routers.\n\nAll C{messageID} values must start with the prefix 'C{ID:}'. "
    "Uniqueness of message ID values across different providers is not required.\n\n"
    "Since message IDs take some effort to create and increase a message's size, some "
    "CMS providers may be able to optimize message overhead if they are given a hint "
    "that the message ID is not used by an application. By setting the "
    "L{MessageProducer.disableMessageID} method, a CMS client enables this potential "
    "optimization for all messages sent by that message producer. If the CMS provider "
    "accepts this hint, these messages must have the message ID set to null; if the "
    "provider ignores the hint, the message ID must be set to its normal unique value.";
static const char* Message_priority_docstring =
    "Gets the message priority level.\n\nThe CMS API defines ten levels of priority "
    "value, with 0 as the lowest priority and 9 as the highest. In addition, clients "
    "should consider priorities 0-4 as gradations of normal priority and priorities 5-9 "
    "as gradations of expedited priority.\n\nThe CMS API does not require that a "
    "provider strictly implements priority ordering of messages; however, it should do "
    "its best to deliver expedited messages ahead of normal messages.";
static const char* Message_redelivered_docstring =
    "Gets an indication of whether this message is being redelivered.\n\nIf a client "
    "receives a message with the redelivered field set, it is likely, but not "
    "guaranteed, that this message was delivered earlier but that its receipt was not "
    "acknowledged at that time.";
static const char* Message_timestamp_docstring =
    "Gets the message timestamp.\n\nThe C{timestamp} header field contains the time a "
    "message was handed off to a provider to be sent. It is not the time the message was"
    " actually transmitted, because the actual send may occur later due to transactions "
    "or other client-side queueing of messages.\n\nWhen a message is sent, C{timestamp} "
    "is ignored. When the send or publish method returns, it contains a time value "
    "somewhere in the interval between the call and the return. The value is in the "
    "format of a normal millis time value in the Java programming language.\n\nSince "
    "timestamps take some effort to create and increase a message's size, some CMS "
    "providers may be able to optimize message overhead if they are given a hint that "
    "the timestamp is not used by an application. By setting "
    "L{MessageProducer.disableMessageTimeStamp}, a CMS client enables this potential "
    "optimization for all messages sent by that message producer. If the CMS provider "
    "accepts this hint, these messages must have the timestamp set to zero; if the "
    "provider ignores the hint, the timestamp must be set to its normal value.";
static const char* Message_replyTo_docstring =
    "The L{Destination} object to which a reply to this message should be sent."
    "\n\nThe C{replyTo} header field contains the destination where a reply to "
    "the current message should be sent. If it is null, no reply is expected. "
    "The destination may be either a L{Queue} object or a L{Topic} object.\n\n"
    "Messages sent with a null C{replyTo} value may be a notification of some "
    "event, or they may just be some data the sender thinks is of interest.\n\n"
    "Messages with a C{replyTo} value typically expect a response. A response "
    "is optional; it is up to the client to decide. These messages are called "
    "requests. A message sent in response to a request is called a reply.\n\n"
    "In some cases a client may wish to match a request it sent earlier with "
    "a reply it has just received. The client can use the L{correlationID} "
    "header field for this purpose.";
static const char* Message_destination_docstring =
    "Returns the L{Destination} object for this message.\n\nThe destination header "
    "field contains the destination to which the message is being sent.\n\nWhen a "
    "message is sent, this field is ignored. After completion of the send or "
    "publish method, the field holds the destination specified by the method.\n\n"
    "When a message is received, its C{destination} value must be equivalent to "
    "the value assigned when it was sent.";
static const char* Message_correlationID_docstring =
    "The correlation ID for the message.\n\nA client can use the C{correlationID} "
    "header field to link one message with another. A typical use is to link a "
    "response message with its request message.\n\nC{correlationID} can hold one "
    "of the following:\n\n"
    " - A provider-specific message ID\n\n"
    " - An application-specific string\n\n"
    " - A provider-native byte value\n\n"
    "Since each message sent by a CMS provider is assigned a message ID value, "
    "it is convenient to link messages via message ID. All message ID values "
    "must start with the 'C{ID:}' prefix.\n\nIn some cases, an application "
    "(made up of several clients) needs to use an application-specific value "
    "for linking messages. For instance, an application may use "
    "C{correlationID} to hold a value referencing some external information. "
    "Application-specified values must not start with the 'C{ID:}' prefix; this "
    "is reserved for provider-generated message ID values.\n\nIf a provider "
    "supports the native concept of correlation ID, a CMS client may need to "
    "assign specific C{correlationID} values to match those expected by clients "
    "that do not use the CMS API. A byte value is used for this purpose. CMS "
    "providers without native correlation ID values are not required to "
    "support byte values. The use of a byte value for correlationID is "
    "non-portable.";
static const char* Message_type_docstring =
    "Sets the message type.\n\nSome CMS providers use a message repository that "
    "contains the definitions of messages sent by applications. The C{type} header "
    "field may reference a message's definition in the provider's repository.\n\n"
    "The CMS API does not define a standard message definition repository, nor "
    "does it define a naming policy for the definitions it contains.\n\nSome "
    "messaging systems require that a message type definition for each application "
    "message be created and that each message specify its type. In order to work "
    "with such CMS providers, CMS clients should assign a value to C{type}, "
    "whether the application makes use of it or not. This ensures that the field "
    "is properly set for those providers that require it.\n\nTo ensure portability, "
    "CMS clients should use symbolic values for C{type} that can be configured at "
    "installation time to the values defined in the current provider's message "
    "repository. If string literals are used, they may not be valid type names "
    "for some CMS providers.";

void export_Message()
{
    py::class_<Message, boost::noncopyable>("Message", Message_docstring, py::no_init)
        .def("acknowledge", &Message::acknowledge, Message_acknowledge_docstring)
        .def("clearBody", &Message::clearBody, Message_clearBody_docstring)
        .def("clearProperties", &Message::clearProperties, Message_clearProperties_docstring)
        .def("clone", &Message::clone, py::return_value_policy<py::manage_new_object>())
        .add_property("propertyNames", &Message::getPropertyNames, Message_propertyNames_docstring)
        .def("propertyExists", &Message::propertyExists, Message_propertyExists_docstring)
        .def("getBooleanProperty", &Message::getBooleanProperty, Message_getBooleanProperty_docstring)
        .def("getByteProperty", &Message::getByteProperty, Message_getByteProperty_docstring)
        .def("getDoubleProperty", &Message::getDoubleProperty, Message_getDoubleProperty_docstring)
        .def("getFloatProperty", &Message::getFloatProperty, Message_getFloatProperty_docstring)
        .def("getIntProperty", &Message::getIntProperty, Message_getIntProperty_docstring)
        .def("getLongProperty", &Message::getLongProperty, Message_getLongProperty_docstring)
        .def("getShortProperty", &Message::getShortProperty, Message_getShortProperty_docstring)
        .def("getStringProperty", &Message::getStringProperty, Message_getStringProperty_docstring)
        .def("setBooleanProperty", &Message::setBooleanProperty, Message_setBooleanProperty_docstring)
        .def("setByteProperty", &Message::setByteProperty, Message_setByteProperty_docstring)
        .def("setDoubleProperty", &Message::setDoubleProperty, Message_setDoubleProperty_docstring)
        .def("setFloatProperty", &Message::setFloatProperty, Message_setFloatProperty_docstring)
        .def("setIntProperty", &Message::setIntProperty, Message_setIntProperty_docstring)
        .def("setLongProperty", &Message::setLongProperty, Message_setLongProperty_docstring)
        .def("setShortProperty", &Message::setShortProperty, Message_setShortProperty_docstring)
        .def("setStringProperty", &Message::setStringProperty, Message_setStringProperty_docstring)
        // read-only properties
        .add_property("deliveryMode", &Message::getCMSDeliveryMode, Message_deliveryMode_docstring)
        .add_property("expiration", &Message::getCMSExpiration, Message_expiration_docstring)
        .add_property("messageID", &Message::getCMSMessageID, Message_messageID_docstring)
        .add_property("priority", &Message::getCMSPriority, Message_priority_docstring)
        .add_property("redelivered", &Message::getCMSRedelivered, Message_redelivered_docstring)
        .add_property("timestamp", &Message::getCMSTimestamp, Message_timestamp_docstring)
        // read-write properties
        .add_property("replyTo",
                      make_function(&Message::getCMSReplyTo, py::return_internal_reference<>()),
                      make_function(&Message::setCMSReplyTo, py::with_custodian_and_ward<1, 2>()),
                      Message_replyTo_docstring)
        .add_property("destination",
                      make_function(&Message::getCMSDestination, py::return_internal_reference<>()),
                      make_function(&Message::setCMSDestination, py::with_custodian_and_ward<1, 2>()),
                      Message_destination_docstring)
        .add_property("correlationID", &Message::getCMSCorrelationID, &Message::setCMSCorrelationID,
                      Message_correlationID_docstring)
        .add_property("type", &Message::getCMSType, &Message::setCMSType, Message_type_docstring)
        ;
}
<|endoftext|>


<commit_before>class Solution {
  public:
    int calculate(string s) {
        stack<long long> nums;
        stack<char> ops;

        auto calculate = [&]() {
            long long curr_num = nums.top();
            nums.pop();
            while (!ops.empty() && ops.top() != '(') {
                if (ops.top() == '*')
                    nums.top() *= curr_num;
                else if (ops.top() == '/')
                    nums.top() /= curr_num;
                else if (ops.top() == '+')
                    nums.top() += curr_num;
                else if (ops.top() == '-')
                    nums.top() -= curr_num;

                curr_num = nums.top();
                nums.pop();
                ops.pop();
            }
            nums.push(curr_num);
        };

        istringstream expin(s); // expression in
        char curr_char;
        long long curr_num;

        while (expin >> ws && !expin.eof()) {
            if (isdigit(expin.peek())) {
                expin >> curr_num;
                nums.push(curr_num);

                if (!ops.empty() && (ops.top() == '*' || ops.top() == '/'))
                    calculate();
            } else {
                expin >> curr_char;
                if (curr_char == ')') {
                    calculate();
                    ops.pop();
                } else {
                    if (curr_char == '+' || curr_char == '-')
                        calculate();
                    ops.push(curr_char);
                }
            }
        }

        calculate();

        return nums.empty() ? 0 : nums.top();
    }
};<commit_msg>772 update description<commit_after>// Implement a basic calculator to evaluate a simple expression string.

// The expression string may contain open ( and closing parentheses ), the plus
// + or minus sign -, non-negative integers and empty spaces .

// The expression string contains only non-negative integers, +, -, *, /
// operators , open ( and closing parentheses ) and empty spaces . The integer
// division should truncate toward zero.

// You may assume that the given expression is always valid. All intermediate
// results will be in the range of [-2147483648, 2147483647].

// Some examples:

// "1 + 1" = 2
// " 6-4 / 2 " = 4
// "2*(5+5*2)/3+(6/2+8)" = 21
// "(2+6* 3+5- (3*14/7+2)*5)+3"=-12

// Note: Do not use the eval built-in library function.

class Solution {
  public:
    int calculate(string s) {
        stack<long long> nums;
        stack<char> ops;

        auto calculate = [&]() {
            long long curr_num = nums.top();
            nums.pop();
            while (!ops.empty() && ops.top() != '(') {
                if (ops.top() == '*')
                    nums.top() *= curr_num;
                else if (ops.top() == '/')
                    nums.top() /= curr_num;
                else if (ops.top() == '+')
                    nums.top() += curr_num;
                else if (ops.top() == '-')
                    nums.top() -= curr_num;

                curr_num = nums.top();
                nums.pop();
                ops.pop();
            }
            nums.push(curr_num);
        };

        istringstream expin(s); // expression in
        char curr_char;
        long long curr_num;

        while (expin >> ws && !expin.eof()) {
            if (isdigit(expin.peek())) {
                expin >> curr_num;
                nums.push(curr_num);

                if (!ops.empty() && (ops.top() == '*' || ops.top() == '/'))
                    calculate();
            } else {
                expin >> curr_char;
                if (curr_char == ')') {
                    calculate();
                    ops.pop();
                } else {
                    if (curr_char == '+' || curr_char == '-')
                        calculate();
                    ops.push(curr_char);
                }
            }
        }

        calculate();

        return nums.empty() ? 0 : nums.top();
    }
};<|endoftext|>


<commit_before>#include "server_functions.h"
#include <string.h>

#include <iostream>
#include <sstream>

#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <netdb.h>
#include <stdlib.h>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"

#include "rpc.h"
#include "constants.h"
#include "helper_function.h"
#include "message_types.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *> * > proc_loc_dict;
//static map<rpcFunctionKey, list<service_info *> * > servicesDictionary;

static list<server_info *> roundRobinList;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/
void registration_request_handler(RegisterRequestMessage * message, int sock){
	const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  procedure_signature key(name, argTypes);

  int status = 0;

  //if no key dosnt exist in map
	if (proc_loc_dict.find(key) == proc_loc_dict.end()) {
    //Adding to the map

    //int *memArgTypes = copyArgTypes(argTypes);
    //key = procedure_signature(name, memArgTypes);

    proc_loc_dict[key] = new list<server_info *>();
    server_info * entry = new server_info(server_identifier, port, sock);

    //Adding to roundRobinList
    roundRobinList.push_back(entry);

  }else{

    bool sameLoc = false;
    list<server_info *> *hostList = proc_loc_dict[key];
    //list<server_info *> *hostList = proc_loc_dict.find(key);

    for (list<server_info *>::iterator it = hostList->begin(); it != hostList->end(); it++) {
      // IF THEY ARE AT THE SAME PLACE, THEY SHOULD HAVE TEH SAME SOCKET
      if((*it)->socket == sock){
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something
        sameLoc = true;
      }

    }
    //Same procedure signature, different location
  	if(!sameLoc){
       server_info * new_msg_loc = new server_info(server_identifier, port, sock);
       hostList->push_back(new_msg_loc);
    }
  }

  RegisterSuccessMessage * success_message = new RegisterSuccessMessage(status);
  success_message->send(sock);
}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
int location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
	for (list<server_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){

    //If the name are the same
    if((*it)->name == message->getName() && compareArr((*it)->argTypes, message->getArgTypes() )){

      exist = true;

      LocSuccessMessage * success_message = new LocSuccessMessage((*it)->si->server_identifier, (*it)->si->port);

      success_message->send(sock);

      //When we have identified the correct procedure_signature use round robin and move that service to the end
      roundRobinList.splice(roundRobinList.end(), roundRobinList, it);

      break;
 		}
	}

  if(!exist){
    int reasoncode = 0;
    LocFailureMessage * failure_message = new LocFailureMessage(reasoncode);
    failure_message->send(sock);
  }

	return 0; //LOC_FAILURE
}

int request_handler(Segment * segment, int sock){
  int retval = 0;
  if(segment->getType() == MSG_TYPE_REGISTER_REQUEST){ //'LOC_REQUEST'
    Message * cast1 = segment->getMessage();
    RegisterRequestMessage * rrm = dynamic_cast<RegisterRequestMessage*>(cast1);
    registration_request_handler(rrm, sock);

  }else if (segment->getType() == MSG_TYPE_LOC_REQUEST){ //'REGISTER'
    Message * cast2 = segment->getMessage();
    LocRequestMessage * lqm = dynamic_cast<LocRequestMessage*>(cast2);
    retval = location_request_handler(lqm, sock);
  }

	return retval;
}

// Returns the binder address
string getBinderAddress() {
   char hostname[MAXHOSTNAMELEN + 1] = {'\0'};
   gethostname(hostname, sizeof(hostname));
   return string(hostname);
}

// Returns the binder port
int getBinderPort(int welcomeSocket) {
   struct sockaddr_in binderAddress;
   socklen_t binderAddressLength = sizeof(binderAddress);

   int result = getsockname(welcomeSocket, (struct sockaddr*) &binderAddress,
      &binderAddressLength);
   if (result < 0) {
      exit(-1);
   } // if

   return ntohs(binderAddress.sin_port);
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main(){

  vector<int> myConnections;
  vector<int> myToRemove;

  int status;
  struct addrinfo hints;
  struct addrinfo* servinfo;
  struct addrinfo* p;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  status = getaddrinfo(NULL, "0", &hints, &servinfo);

  if (status != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    return 0;
  }

  p = servinfo;
  int sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);

  status = bind(sock, servinfo->ai_addr, servinfo->ai_addrlen);
  status = listen(sock, 5);

  cout << "BINDER_ADDRESS " << getBinderAddress() << endl;
  cout << "BINDER_PORT " << getBinderPort(sock) << endl;

  fd_set readfds;
  int n;
  struct sockaddr_storage their_addr;

  while(true){
    //CONNECTIONS VECTOR
    FD_ZERO(&readfds);
    FD_SET(sock, &readfds);

    n = sock;

    for (vector<int>::iterator it = myConnections.begin();it != myConnections.end(); ++it) {
      int connection = *it;
      FD_SET(connection, &readfds);
       if (connection > n){
        n = connection;
      }
    }

    n = n+1;

    status = select(n, &readfds, NULL, NULL, NULL);

    if (status == -1) {
      cerr << "ERROR: select failed." << endl;
    } else {

      if (FD_ISSET(sock, &readfds)) {
        socklen_t addr_size = sizeof their_addr;
        int new_sock = accept(sock, (struct sockaddr*)&their_addr, &addr_size);

        if (new_sock < 0) {
          cerr << "ERROR: while accepting connection" << endl;
          close(new_sock);
          continue;
        }

        myConnections.push_back(new_sock);

      } else {

        for (vector<int>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
          int tempConnection = *it;
          if (FD_ISSET(tempConnection, &readfds)) {

            Segment * segment = 0;
            status = Segment::receive(sock, segment);

            if (status < 0) {
                RegisterFailureMessage * failure_message = new RegisterFailureMessage(status);
                failure_message->send(sock);
                return status;
            }

            if (status == 0) {
              // client has closed the connection
              myToRemove.push_back(sock);
              return status;
            }

            request_handler(segment, sock);
          }
        }
      }

      for (vector<int>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
        myConnections.erase(remove(myConnections.begin(), myConnections.end(), *it), myConnections.end());
        close(*it);
      }
      myToRemove.clear();
    }
  }

  freeaddrinfo(servinfo);
}
<commit_msg>changes<commit_after>#include "server_functions.h"
#include <string.h>

#include <iostream>
#include <sstream>

#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <netdb.h>
#include <stdlib.h>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"

#include "rpc.h"
#include "constants.h"
#include "helper_function.h"
#include "message_types.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *> * > proc_loc_dict;
//static map<rpcFunctionKey, list<service_info *> * > servicesDictionary;

static list<server_function_info *> roundRobinList;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/
void registration_request_handler(RegisterRequestMessage * message, int sock){
	const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  procedure_signature key(name, argTypes);

  int status = 0;

  //if no key dosnt exist in map
	if (proc_loc_dict.find(key) == proc_loc_dict.end()) {
    //Adding to the map

    //int *memArgTypes = copyArgTypes(argTypes);
    //key = procedure_signature(name, memArgTypes);

    proc_loc_dict[key] = new list<server_info *>();
    server_info * entry = new server_info(server_identifier, port, sock);

    //Adding to roundRobinList
    server_function_info * info = new server_function_info(entry, key);
    roundRobinList.push_back(info);

  }else{

    bool sameLoc = false;
    list<server_info *> *hostList = proc_loc_dict[key];
    //list<server_info *> *hostList = proc_loc_dict.find(key);

    for (list<server_info *>::iterator it = hostList->begin(); it != hostList->end(); it++) {
      // IF THEY ARE AT THE SAME PLACE, THEY SHOULD HAVE TEH SAME SOCKET
      if((*it)->socket == sock){
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something
        sameLoc = true;
      }

    }
    //Same procedure signature, different location
  	if(!sameLoc){
       server_info * new_msg_loc = new server_info(server_identifier, port, sock);
       hostList->push_back(new_msg_loc);
    }
  }

  RegisterSuccessMessage * success_message = new RegisterSuccessMessage(status);
  success_message->send(sock);
}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
int location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
	for (list<server_function_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){

    //If the name are the same
    if((*it)->ps->name == message->getName() && compareArr((*it)->ps->argTypes, message->getArgTypes() )){

      exist = true;

      LocSuccessMessage * success_message = new LocSuccessMessage((*it)->si->server_identifier, (*it)->si->port);

      success_message->send(sock);

      //When we have identified the correct procedure_signature use round robin and move that service to the end
      roundRobinList.splice(roundRobinList.end(), roundRobinList, it);

      break;
 		}
	}

  if(!exist){
    int reasoncode = 0;
    LocFailureMessage * failure_message = new LocFailureMessage(reasoncode);
    failure_message->send(sock);
  }

	return 0; //LOC_FAILURE
}

int request_handler(Segment * segment, int sock){
  int retval = 0;
  if(segment->getType() == MSG_TYPE_REGISTER_REQUEST){ //'LOC_REQUEST'
    Message * cast1 = segment->getMessage();
    RegisterRequestMessage * rrm = dynamic_cast<RegisterRequestMessage*>(cast1);
    registration_request_handler(rrm, sock);

  }else if (segment->getType() == MSG_TYPE_LOC_REQUEST){ //'REGISTER'
    Message * cast2 = segment->getMessage();
    LocRequestMessage * lqm = dynamic_cast<LocRequestMessage*>(cast2);
    retval = location_request_handler(lqm, sock);
  }

	return retval;
}

// Returns the binder address
string getBinderAddress() {
   char hostname[MAXHOSTNAMELEN + 1] = {'\0'};
   gethostname(hostname, sizeof(hostname));
   return string(hostname);
}

// Returns the binder port
int getBinderPort(int welcomeSocket) {
   struct sockaddr_in binderAddress;
   socklen_t binderAddressLength = sizeof(binderAddress);

   int result = getsockname(welcomeSocket, (struct sockaddr*) &binderAddress,
      &binderAddressLength);
   if (result < 0) {
      exit(-1);
   } // if

   return ntohs(binderAddress.sin_port);
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main(){

  vector<int> myConnections;
  vector<int> myToRemove;

  int status;
  struct addrinfo hints;
  struct addrinfo* servinfo;
  struct addrinfo* p;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  status = getaddrinfo(NULL, "0", &hints, &servinfo);

  if (status != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    return 0;
  }

  p = servinfo;
  int sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);

  status = bind(sock, servinfo->ai_addr, servinfo->ai_addrlen);
  status = listen(sock, 5);

  cout << "BINDER_ADDRESS " << getBinderAddress() << endl;
  cout << "BINDER_PORT " << getBinderPort(sock) << endl;

  fd_set readfds;
  int n;
  struct sockaddr_storage their_addr;

  while(true){
    //CONNECTIONS VECTOR
    FD_ZERO(&readfds);
    FD_SET(sock, &readfds);

    n = sock;

    for (vector<int>::iterator it = myConnections.begin();it != myConnections.end(); ++it) {
      int connection = *it;
      FD_SET(connection, &readfds);
       if (connection > n){
        n = connection;
      }
    }

    n = n+1;

    status = select(n, &readfds, NULL, NULL, NULL);

    if (status == -1) {
      cerr << "ERROR: select failed." << endl;
    } else {

      if (FD_ISSET(sock, &readfds)) {
        socklen_t addr_size = sizeof their_addr;
        int new_sock = accept(sock, (struct sockaddr*)&their_addr, &addr_size);

        if (new_sock < 0) {
          cerr << "ERROR: while accepting connection" << endl;
          close(new_sock);
          continue;
        }

        myConnections.push_back(new_sock);

      } else {

        for (vector<int>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
          int tempConnection = *it;
          if (FD_ISSET(tempConnection, &readfds)) {

            Segment * segment = 0;
            status = Segment::receive(sock, segment);

            if (status < 0) {
                RegisterFailureMessage * failure_message = new RegisterFailureMessage(status);
                failure_message->send(sock);
                return status;
            }

            if (status == 0) {
              // client has closed the connection
              myToRemove.push_back(sock);
              return status;
            }

            request_handler(segment, sock);
          }
        }
      }

      for (vector<int>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
        myConnections.erase(remove(myConnections.begin(), myConnections.end(), *it), myConnections.end());
        close(*it);
      }
      myToRemove.clear();
    }
  }

  freeaddrinfo(servinfo);
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All rights reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build ignore

#include "command.h"

#include <unordered_map>
#include <unordered_set>

#include "dep.h"
#include "eval.h"
#include "flags.h"
#include "log.h"
#include "strutil.h"
#include "var.h"

namespace {

class AutoVar : public Var {
 public:
  virtual const char* Flavor() const override {
    return "undefined";
  }
  virtual VarOrigin Origin() const override {
    return VarOrigin::AUTOMATIC;
  }

  virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }

  virtual StringPiece String() const override {
    ERROR("$(value %s) is not implemented yet", sym_);
    return "";
  }

  virtual string DebugString() const override {
    return string("AutoVar(") + sym_ + ")";
  }

 protected:
  AutoVar(CommandEvaluator* ce, const char* sym) : ce_(ce), sym_(sym) {}
  virtual ~AutoVar() = default;

  CommandEvaluator* ce_;
  const char* sym_;
};

#define DECLARE_AUTO_VAR_CLASS(name)                                    \
  class name : public AutoVar {                                         \
   public:                                                              \
   name(CommandEvaluator* ce, const char* sym)                          \
       : AutoVar(ce, sym) {}                                            \
   virtual ~name() = default;                                           \
   virtual void Eval(Evaluator* ev, string* s) const override;          \
  }

DECLARE_AUTO_VAR_CLASS(AutoAtVar);
DECLARE_AUTO_VAR_CLASS(AutoLessVar);
DECLARE_AUTO_VAR_CLASS(AutoHatVar);
DECLARE_AUTO_VAR_CLASS(AutoPlusVar);
DECLARE_AUTO_VAR_CLASS(AutoStarVar);
DECLARE_AUTO_VAR_CLASS(AutoNotImplementedVar);

class AutoSuffixDVar : public AutoVar {
 public:
  AutoSuffixDVar(CommandEvaluator* ce, const char* sym, Var* wrapped)
      : AutoVar(ce, sym), wrapped_(wrapped) {
  }
  virtual ~AutoSuffixDVar() = default;
  virtual void Eval(Evaluator* ev, string* s) const override;

 private:
  Var* wrapped_;
};

class AutoSuffixFVar : public AutoVar {
 public:
  AutoSuffixFVar(CommandEvaluator* ce, const char* sym, Var* wrapped)
      : AutoVar(ce, sym), wrapped_(wrapped) {}
  virtual ~AutoSuffixFVar() = default;
  virtual void Eval(Evaluator* ev, string* s) const override;

 private:
  Var* wrapped_;
};

void AutoAtVar::Eval(Evaluator*, string* s) const {
  *s += ce_->current_dep_node()->output.str();
}

void AutoLessVar::Eval(Evaluator*, string* s) const {
  auto& ai = ce_->current_dep_node()->actual_inputs;
  if (!ai.empty())
    *s += ai[0].str();
}

void AutoHatVar::Eval(Evaluator*, string* s) const {
  unordered_set<StringPiece> seen;
  WordWriter ww(s);
  for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
    if (seen.insert(ai.str()).second)
      ww.Write(ai.str());
  }
}

void AutoPlusVar::Eval(Evaluator*, string* s) const {
  WordWriter ww(s);
  for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
    ww.Write(ai.str());
  }
}

void AutoStarVar::Eval(Evaluator*, string* s) const {
  const DepNode* n = ce_->current_dep_node();
  if (!n->output_pattern.IsValid())
    return;
  Pattern pat(n->output_pattern.str());
  pat.Stem(n->output.str()).AppendToString(s);
}

void AutoNotImplementedVar::Eval(Evaluator* ev, string*) const {
  ev->Error(StringPrintf(
      "Automatic variable `$%s' isn't supported yet", sym_));
}

void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const {
  string buf;
  wrapped_->Eval(ev, &buf);
  WordWriter ww(s);
  for (StringPiece tok : WordScanner(buf)) {
    ww.Write(Dirname(tok));
  }
}

void AutoSuffixFVar::Eval(Evaluator* ev, string* s) const {
  string buf;
  wrapped_->Eval(ev, &buf);
  WordWriter ww(s);
  for (StringPiece tok : WordScanner(buf)) {
    ww.Write(Basename(tok));
  }
}

void ParseCommandPrefixes(StringPiece* s, bool* echo, bool* ignore_error) {
  *s = TrimLeftSpace(*s);
  while (true) {
    char c = s->get(0);
    if (c == '@') {
      *echo = false;
    } else if (c == '-') {
      *ignore_error = true;
    } else {
      break;
    }
    *s = TrimLeftSpace(s->substr(1));
  }
}

}  // namespace

CommandEvaluator::CommandEvaluator(Evaluator* ev)
    : ev_(ev) {
#define INSERT_AUTO_VAR(name, sym) do {                                 \
    Var* v = new name(this, sym);                                       \
    Intern(sym).SetGlobalVar(v);                                        \
    Intern(sym"D").SetGlobalVar(new AutoSuffixDVar(this, sym"D", v));   \
    Intern(sym"F").SetGlobalVar(new AutoSuffixFVar(this, sym"F", v));   \
  } while (0)
  INSERT_AUTO_VAR(AutoAtVar, "@");
  INSERT_AUTO_VAR(AutoLessVar, "<");
  INSERT_AUTO_VAR(AutoHatVar, "^");
  INSERT_AUTO_VAR(AutoPlusVar, "+");
  INSERT_AUTO_VAR(AutoStarVar, "*");
  // TODO: Implement them.
  INSERT_AUTO_VAR(AutoNotImplementedVar, "%");
  INSERT_AUTO_VAR(AutoNotImplementedVar, "?");
  INSERT_AUTO_VAR(AutoNotImplementedVar, "|");
}

void CommandEvaluator::Eval(DepNode* n, vector<Command*>* commands) {
  ev_->set_loc(n->loc);
  ev_->set_current_scope(n->rule_vars);
  current_dep_node_ = n;
  for (Value* v : n->cmds) {
    const string&& cmds_buf = v->Eval(ev_);
    StringPiece cmds = cmds_buf;
    bool global_echo = !g_flags.is_silent_mode;
    bool global_ignore_error = false;
    ParseCommandPrefixes(&cmds, &global_echo, &global_ignore_error);
    if (cmds == "")
      continue;
    while (true) {
      size_t lf_cnt;
      size_t index = FindEndOfLine(cmds, 0, &lf_cnt);
      if (index == cmds.size())
        index = string::npos;
      StringPiece cmd = TrimLeftSpace(cmds.substr(0, index));
      cmds = cmds.substr(index + 1);

      bool echo = global_echo;
      bool ignore_error = global_ignore_error;
      ParseCommandPrefixes(&cmd, &echo, &ignore_error);

      if (!cmd.empty()) {
        Command* command = new Command(n->output);
        command->cmd = cmd.as_string();
        command->echo = echo;
        command->ignore_error = ignore_error;
        commands->push_back(command);
      }
      if (index == string::npos)
        break;
    }
    continue;
  }

  if (!ev_->delayed_output_commands().empty()) {
    vector<Command*> output_commands;
    for (const string& cmd : ev_->delayed_output_commands()) {
      Command* c = new Command(n->output);
      c->cmd = cmd;
      c->echo = false;
      c->ignore_error = false;
      output_commands.push_back(c);
    }
    // Prepend |output_commands|.
    commands->swap(output_commands);
    copy(output_commands.begin(), output_commands.end(),
         back_inserter(*commands));
    ev_->clear_delayed_output_commands();
  }

  ev_->set_current_scope(NULL);
}
<commit_msg>[C++] Ignore recursive marker in recipes<commit_after>// Copyright 2015 Google Inc. All rights reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build ignore

#include "command.h"

#include <unordered_map>
#include <unordered_set>

#include "dep.h"
#include "eval.h"
#include "flags.h"
#include "log.h"
#include "strutil.h"
#include "var.h"

namespace {

class AutoVar : public Var {
 public:
  virtual const char* Flavor() const override {
    return "undefined";
  }
  virtual VarOrigin Origin() const override {
    return VarOrigin::AUTOMATIC;
  }

  virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }

  virtual StringPiece String() const override {
    ERROR("$(value %s) is not implemented yet", sym_);
    return "";
  }

  virtual string DebugString() const override {
    return string("AutoVar(") + sym_ + ")";
  }

 protected:
  AutoVar(CommandEvaluator* ce, const char* sym) : ce_(ce), sym_(sym) {}
  virtual ~AutoVar() = default;

  CommandEvaluator* ce_;
  const char* sym_;
};

#define DECLARE_AUTO_VAR_CLASS(name)                                    \
  class name : public AutoVar {                                         \
   public:                                                              \
   name(CommandEvaluator* ce, const char* sym)                          \
       : AutoVar(ce, sym) {}                                            \
   virtual ~name() = default;                                           \
   virtual void Eval(Evaluator* ev, string* s) const override;          \
  }

DECLARE_AUTO_VAR_CLASS(AutoAtVar);
DECLARE_AUTO_VAR_CLASS(AutoLessVar);
DECLARE_AUTO_VAR_CLASS(AutoHatVar);
DECLARE_AUTO_VAR_CLASS(AutoPlusVar);
DECLARE_AUTO_VAR_CLASS(AutoStarVar);
DECLARE_AUTO_VAR_CLASS(AutoNotImplementedVar);

class AutoSuffixDVar : public AutoVar {
 public:
  AutoSuffixDVar(CommandEvaluator* ce, const char* sym, Var* wrapped)
      : AutoVar(ce, sym), wrapped_(wrapped) {
  }
  virtual ~AutoSuffixDVar() = default;
  virtual void Eval(Evaluator* ev, string* s) const override;

 private:
  Var* wrapped_;
};

class AutoSuffixFVar : public AutoVar {
 public:
  AutoSuffixFVar(CommandEvaluator* ce, const char* sym, Var* wrapped)
      : AutoVar(ce, sym), wrapped_(wrapped) {}
  virtual ~AutoSuffixFVar() = default;
  virtual void Eval(Evaluator* ev, string* s) const override;

 private:
  Var* wrapped_;
};

void AutoAtVar::Eval(Evaluator*, string* s) const {
  *s += ce_->current_dep_node()->output.str();
}

void AutoLessVar::Eval(Evaluator*, string* s) const {
  auto& ai = ce_->current_dep_node()->actual_inputs;
  if (!ai.empty())
    *s += ai[0].str();
}

void AutoHatVar::Eval(Evaluator*, string* s) const {
  unordered_set<StringPiece> seen;
  WordWriter ww(s);
  for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
    if (seen.insert(ai.str()).second)
      ww.Write(ai.str());
  }
}

void AutoPlusVar::Eval(Evaluator*, string* s) const {
  WordWriter ww(s);
  for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
    ww.Write(ai.str());
  }
}

void AutoStarVar::Eval(Evaluator*, string* s) const {
  const DepNode* n = ce_->current_dep_node();
  if (!n->output_pattern.IsValid())
    return;
  Pattern pat(n->output_pattern.str());
  pat.Stem(n->output.str()).AppendToString(s);
}

void AutoNotImplementedVar::Eval(Evaluator* ev, string*) const {
  ev->Error(StringPrintf(
      "Automatic variable `$%s' isn't supported yet", sym_));
}

void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const {
  string buf;
  wrapped_->Eval(ev, &buf);
  WordWriter ww(s);
  for (StringPiece tok : WordScanner(buf)) {
    ww.Write(Dirname(tok));
  }
}

void AutoSuffixFVar::Eval(Evaluator* ev, string* s) const {
  string buf;
  wrapped_->Eval(ev, &buf);
  WordWriter ww(s);
  for (StringPiece tok : WordScanner(buf)) {
    ww.Write(Basename(tok));
  }
}

void ParseCommandPrefixes(StringPiece* s, bool* echo, bool* ignore_error) {
  *s = TrimLeftSpace(*s);
  while (true) {
    char c = s->get(0);
    if (c == '@') {
      *echo = false;
    } else if (c == '-') {
      *ignore_error = true;
    } else if (c == '+') {
      // ignore recursion marker
    } else {
      break;
    }
    *s = TrimLeftSpace(s->substr(1));
  }
}

}  // namespace

CommandEvaluator::CommandEvaluator(Evaluator* ev)
    : ev_(ev) {
#define INSERT_AUTO_VAR(name, sym) do {                                 \
    Var* v = new name(this, sym);                                       \
    Intern(sym).SetGlobalVar(v);                                        \
    Intern(sym"D").SetGlobalVar(new AutoSuffixDVar(this, sym"D", v));   \
    Intern(sym"F").SetGlobalVar(new AutoSuffixFVar(this, sym"F", v));   \
  } while (0)
  INSERT_AUTO_VAR(AutoAtVar, "@");
  INSERT_AUTO_VAR(AutoLessVar, "<");
  INSERT_AUTO_VAR(AutoHatVar, "^");
  INSERT_AUTO_VAR(AutoPlusVar, "+");
  INSERT_AUTO_VAR(AutoStarVar, "*");
  // TODO: Implement them.
  INSERT_AUTO_VAR(AutoNotImplementedVar, "%");
  INSERT_AUTO_VAR(AutoNotImplementedVar, "?");
  INSERT_AUTO_VAR(AutoNotImplementedVar, "|");
}

void CommandEvaluator::Eval(DepNode* n, vector<Command*>* commands) {
  ev_->set_loc(n->loc);
  ev_->set_current_scope(n->rule_vars);
  current_dep_node_ = n;
  for (Value* v : n->cmds) {
    const string&& cmds_buf = v->Eval(ev_);
    StringPiece cmds = cmds_buf;
    bool global_echo = !g_flags.is_silent_mode;
    bool global_ignore_error = false;
    ParseCommandPrefixes(&cmds, &global_echo, &global_ignore_error);
    if (cmds == "")
      continue;
    while (true) {
      size_t lf_cnt;
      size_t index = FindEndOfLine(cmds, 0, &lf_cnt);
      if (index == cmds.size())
        index = string::npos;
      StringPiece cmd = TrimLeftSpace(cmds.substr(0, index));
      cmds = cmds.substr(index + 1);

      bool echo = global_echo;
      bool ignore_error = global_ignore_error;
      ParseCommandPrefixes(&cmd, &echo, &ignore_error);

      if (!cmd.empty()) {
        Command* command = new Command(n->output);
        command->cmd = cmd.as_string();
        command->echo = echo;
        command->ignore_error = ignore_error;
        commands->push_back(command);
      }
      if (index == string::npos)
        break;
    }
    continue;
  }

  if (!ev_->delayed_output_commands().empty()) {
    vector<Command*> output_commands;
    for (const string& cmd : ev_->delayed_output_commands()) {
      Command* c = new Command(n->output);
      c->cmd = cmd;
      c->echo = false;
      c->ignore_error = false;
      output_commands.push_back(c);
    }
    // Prepend |output_commands|.
    commands->swap(output_commands);
    copy(output_commands.begin(), output_commands.end(),
         back_inserter(*commands));
    ev_->clear_delayed_output_commands();
  }

  ev_->set_current_scope(NULL);
}
<|endoftext|>


<commit_before>#pragma once

#define BRYNET_VERSION 1011002
<commit_msg>Update Version.hpp<commit_after>#pragma once

#define BRYNET_VERSION 1012000
<|endoftext|>