/* Copyright 2008-2013 Broadcom Corporation
 * Copyright (c) 2014 QLogic Corporation
 * All rights reserved
 *
 * Unless you and QLogic execute a separate written software license
 * agreement governing use of this software, this software is licensed to you
 * under the terms of the GNU General Public License version 2, available
 * at http://www.gnu.org/licenses/gpl-2.0.html (the "GPL").
 *
 * Notwithstanding the above, under no circumstances may you combine this
 * software in any way with any other Qlogic software provided under a
 * license other than the GPL, without Qlogic's express prior written
 * consent.
 *
 * Written by Yaniv Rosner
 *
 */

#ifndef BNX2X_LINK_H
#define BNX2X_LINK_H

/***********************************************************/
/*                         Defines                         */
/***********************************************************/
#define DEFAULT_PHY_DEV_ADDR	3
#define E2_DEFAULT_PHY_DEV_ADDR	5

#define BNX2X_FLOW_CTRL_AUTO		PORT_FEATURE_FLOW_CONTROL_AUTO
#define BNX2X_FLOW_CTRL_TX		PORT_FEATURE_FLOW_CONTROL_TX
#define BNX2X_FLOW_CTRL_RX		PORT_FEATURE_FLOW_CONTROL_RX
#define BNX2X_FLOW_CTRL_BOTH		PORT_FEATURE_FLOW_CONTROL_BOTH
#define BNX2X_FLOW_CTRL_NONE		PORT_FEATURE_FLOW_CONTROL_NONE

#define NET_SERDES_IF_XFI		1
#define NET_SERDES_IF_SFI		2
#define NET_SERDES_IF_KR		3
#define NET_SERDES_IF_DXGXS	4

#define SPEED_AUTO_NEG		0
#define SPEED_20000		20000

#define I2C_DEV_ADDR_A0			0xa0
#define I2C_DEV_ADDR_A2			0xa2

#define SFP_EEPROM_PAGE_SIZE			16
#define SFP_EEPROM_VENDOR_NAME_ADDR		0x14
#define SFP_EEPROM_VENDOR_NAME_SIZE		16
#define SFP_EEPROM_VENDOR_OUI_ADDR		0x25
#define SFP_EEPROM_VENDOR_OUI_SIZE		3
#define SFP_EEPROM_PART_NO_ADDR			0x28
#define SFP_EEPROM_PART_NO_SIZE			16
#define SFP_EEPROM_REVISION_ADDR		0x38
#define SFP_EEPROM_REVISION_SIZE		4
#define SFP_EEPROM_SERIAL_ADDR			0x44
#define SFP_EEPROM_SERIAL_SIZE			16
#define SFP_EEPROM_DATE_ADDR			0x54 /* ASCII YYMMDD */
#define SFP_EEPROM_DATE_SIZE			6
#define SFP_EEPROM_DIAG_TYPE_ADDR		0x5c
#define SFP_EEPROM_DIAG_TYPE_SIZE		1
#define SFP_EEPROM_DIAG_ADDR_CHANGE_REQ		(1<<2)
#define SFP_EEPROM_SFF_8472_COMP_ADDR		0x5e
#define SFP_EEPROM_SFF_8472_COMP_SIZE		1

#define SFP_EEPROM_A2_CHECKSUM_RANGE		0x5e
#define SFP_EEPROM_A2_CC_DMI_ADDR		0x5f

#define PWR_FLT_ERR_MSG_LEN			250

#define XGXS_EXT_PHY_TYPE(ext_phy_config) \
		((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK)
#define XGXS_EXT_PHY_ADDR(ext_phy_config) \
		(((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> \
		 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT)
#define SERDES_EXT_PHY_TYPE(ext_phy_config) \
		((ext_phy_config) & PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK)

/* Single Media Direct board is the plain 577xx board with CX4/RJ45 jacks */
#define SINGLE_MEDIA_DIRECT(params)	(params->num_phys == 1)
/* Single Media board contains single external phy */
#define SINGLE_MEDIA(params)		(params->num_phys == 2)
/* Dual Media board contains two external phy with different media */
#define DUAL_MEDIA(params)		(params->num_phys == 3)

#define FW_PARAM_PHY_ADDR_MASK		0x000000FF
#define FW_PARAM_PHY_TYPE_MASK		0x0000FF00
#define FW_PARAM_MDIO_CTRL_MASK		0xFFFF0000
#define FW_PARAM_MDIO_CTRL_OFFSET		16
#define FW_PARAM_PHY_ADDR(fw_param) (fw_param & \
					   FW_PARAM_PHY_ADDR_MASK)
#define FW_PARAM_PHY_TYPE(fw_param) (fw_param & \
					   FW_PARAM_PHY_TYPE_MASK)
#define FW_PARAM_MDIO_CTRL(fw_param) ((fw_param & \
					    FW_PARAM_MDIO_CTRL_MASK) >> \
					    FW_PARAM_MDIO_CTRL_OFFSET)
#define FW_PARAM_SET(phy_addr, phy_type, mdio_access) \
	(phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET)

#define PFC_BRB_FULL_LB_XOFF_THRESHOLD				170
#define PFC_BRB_FULL_LB_XON_THRESHOLD				250

#define MAXVAL(a, b) (((a) > (b)) ? (a) : (b))

#define BMAC_CONTROL_RX_ENABLE		2
/***********************************************************/
/*                         Structs                         */
/***********************************************************/
#define INT_PHY		0
#define EXT_PHY1	1
#define EXT_PHY2	2
#define MAX_PHYS	3

/* Same configuration is shared between the XGXS and the first external phy */
#define LINK_CONFIG_SIZE (MAX_PHYS - 1)
#define LINK_CONFIG_IDX(_phy_idx) ((_phy_idx == INT_PHY) ? \
					 0 : (_phy_idx - 1))
/***********************************************************/
/*                      bnx2x_phy struct                     */
/*  Defines the required arguments and function per phy    */
/***********************************************************/
struct link_vars;
struct link_params;
struct bnx2x_phy;

typedef u8 (*config_init_t)(struct bnx2x_phy *phy, struct link_params *params,
			    struct link_vars *vars);
typedef u8 (*read_status_t)(struct bnx2x_phy *phy, struct link_params *params,
			    struct link_vars *vars);
typedef void (*link_reset_t)(struct bnx2x_phy *phy,
			     struct link_params *params);
typedef void (*config_loopback_t)(struct bnx2x_phy *phy,
				  struct link_params *params);
typedef u8 (*format_fw_ver_t)(u32 raw, u8 *str, u16 *len);
typedef void (*hw_reset_t)(struct bnx2x_phy *phy, struct link_params *params);
typedef void (*set_link_led_t)(struct bnx2x_phy *phy,
			       struct link_params *params, u8 mode);
typedef void (*phy_specific_func_t)(struct bnx2x_phy *phy,
				    struct link_params *params, u32 action);
struct bnx2x_reg_set {
	u8  devad;
	u16 reg;
	u16 val;
};

struct bnx2x_phy {
	u32 type;

	/* Loaded during init */
	u8 addr;
	u8 def_md_devad;
	u16 flags;
	/* No Over-Current detection */
#define FLAGS_NOC			(1<<1)
	/* Fan failure detection required */
#define FLAGS_FAN_FAILURE_DET_REQ	(1<<2)
	/* Initialize first the XGXS and only then the phy itself */
#define FLAGS_INIT_XGXS_FIRST		(1<<3)
#define FLAGS_WC_DUAL_MODE		(1<<4)
#define FLAGS_4_PORT_MODE		(1<<5)
#define FLAGS_REARM_LATCH_SIGNAL	(1<<6)
#define FLAGS_SFP_NOT_APPROVED		(1<<7)
#define FLAGS_MDC_MDIO_WA		(1<<8)
#define FLAGS_DUMMY_READ		(1<<9)
#define FLAGS_MDC_MDIO_WA_B0		(1<<10)
#define FLAGS_TX_ERROR_CHECK		(1<<12)
#define FLAGS_EEE			(1<<13)
#define FLAGS_MDC_MDIO_WA_G		(1<<15)

	/* preemphasis values for the rx side */
	u16 rx_preemphasis[4];

	/* preemphasis values for the tx side */
	u16 tx_preemphasis[4];

	/* EMAC address for access MDIO */
	u32 mdio_ctrl;

	u32 supported;

	u32 media_type;
#define	ETH_PHY_UNSPECIFIED	0x0
#define	ETH_PHY_SFPP_10G_FIBER	0x1
#define	ETH_PHY_XFP_FIBER		0x2
#define	ETH_PHY_DA_TWINAX		0x3
#define	ETH_PHY_BASE_T		0x4
#define	ETH_PHY_SFP_1G_FIBER	0x5
#define	ETH_PHY_KR		0xf0
#define	ETH_PHY_CX4		0xf1
#define	ETH_PHY_NOT_PRESENT	0xff

	/* The address in which version is located*/
	u32 ver_addr;

	u16 req_flow_ctrl;

	u16 req_line_speed;

	u32 speed_cap_mask;

	u16 req_duplex;
	u16 rsrv;
	/* Called per phy/port init, and it configures LASI, speed, autoneg,
	 duplex, flow control negotiation, etc. */
	config_init_t config_init;

	/* Called due to interrupt. It determines the link, speed */
	read_status_t read_status;

	/* Called when driver is unloading. Should reset the phy */
	link_reset_t link_reset;

	/* Set the loopback configuration for the phy */
	config_loopback_t config_loopback;

	/* Format the given raw number into str up to len */
	format_fw_ver_t format_fw_ver;

	/* Reset the phy (both ports) */
	hw_reset_t hw_reset;

	/* Set link led mode (on/off/oper)*/
	set_link_led_t set_link_led;

	/* PHY Specific tasks */
	phy_specific_func_t phy_specific_func;
#define DISABLE_TX	1
#define ENABLE_TX	2
#define PHY_INIT	3
};

/* Inputs parameters to the CLC */
struct link_params {

	u8 port;

	/* Default / User Configuration */
	u8 loopback_mode;
#define LOOPBACK_NONE		0
#define LOOPBACK_EMAC		1
#define LOOPBACK_BMAC		2
#define LOOPBACK_XGXS		3
#define LOOPBACK_EXT_PHY	4
#define LOOPBACK_EXT		5
#define LOOPBACK_UMAC		6
#define LOOPBACK_XMAC		7

	/* Device parameters */
	u8 mac_addr[6];

	u16 req_duplex[LINK_CONFIG_SIZE];
	u16 req_flow_ctrl[LINK_CONFIG_SIZE];

	u16 req_line_speed[LINK_CONFIG_SIZE]; /* Also determine AutoNeg */

	/* shmem parameters */
	u32 shmem_base;
	u32 shmem2_base;
	u32 speed_cap_mask[LINK_CONFIG_SIZE];
	u32 switch_cfg;
#define SWITCH_CFG_1G		PORT_FEATURE_CON_SWITCH_1G_SWITCH
#define SWITCH_CFG_10G		PORT_FEATURE_CON_SWITCH_10G_SWITCH
#define SWITCH_CFG_AUTO_DETECT	PORT_FEATURE_CON_SWITCH_AUTO_DETECT

	u32 lane_config;

	/* Phy register parameter */
	u32 chip_id;

	/* features */
	u32 feature_config_flags;
#define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED	(1<<0)
#define FEATURE_CONFIG_PFC_ENABLED			(1<<1)
#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY		(1<<2)
#define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY	(1<<3)
#define FEATURE_CONFIG_BC_SUPPORTS_AFEX			(1<<8)
#define FEATURE_CONFIG_AUTOGREEEN_ENABLED			(1<<9)
#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED		(1<<10)
#define FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET		(1<<11)
#define FEATURE_CONFIG_MT_SUPPORT			(1<<13)
#define FEATURE_CONFIG_BOOT_FROM_SAN			(1<<14)

	/* Will be populated during common init */
	struct bnx2x_phy phy[MAX_PHYS];

	/* Will be populated during common init */
	u8 num_phys;

	u8 rsrv;

	/* Used to configure the EEE Tx LPI timer, has several modes of
	 * operation, according to bits 29:28 -
	 * 2'b00: Timer will be configured by nvram, output will be the value
	 *        from nvram.
	 * 2'b01: Timer will be configured by nvram, output will be in
	 *        microseconds.
	 * 2'b10: bits 1:0 contain an nvram value which will be used instead
	 *        of the one located in the nvram. Output will be that value.
	 * 2'b11: bits 19:0 contain the idle timer in microseconds; output
	 *        will be in microseconds.
	 * Bits 31:30 should be 2'b11 in order for EEE to be enabled.
	 */
	u32 eee_mode;
#define EEE_MODE_NVRAM_BALANCED_TIME		(0xa00)
#define EEE_MODE_NVRAM_AGGRESSIVE_TIME		(0x100)
#define EEE_MODE_NVRAM_LATENCY_TIME		(0x6000)
#define EEE_MODE_NVRAM_MASK		(0x3)
#define EEE_MODE_TIMER_MASK		(0xfffff)
#define EEE_MODE_OUTPUT_TIME		(1<<28)
#define EEE_MODE_OVERRIDE_NVRAM		(1<<29)
#define EEE_MODE_ENABLE_LPI		(1<<30)
#define EEE_MODE_ADV_LPI			(1<<31)

	u16 hw_led_mode; /* part of the hw_config read from the shmem */
	u32 multi_phy_config;

	/* Device pointer passed to all callback functions */
	struct bnx2x *bp;
	u16 req_fc_auto_adv; /* Should be set to TX / BOTH when
				req_flow_ctrl is set to AUTO */
	u16 link_flags;
#define LINK_FLAGS_INT_DISABLED		(1<<0)
#define PHY_INITIALIZED		(1<<1)
	u32 lfa_base;

	/* The same definitions as the shmem2 parameter */
	u32 link_attr_sync;
};

/* Output parameters */
struct link_vars {
	u8 phy_flags;
#define PHY_XGXS_FLAG			(1<<0)
#define PHY_SGMII_FLAG			(1<<1)
#define PHY_PHYSICAL_LINK_FLAG		(1<<2)
#define PHY_HALF_OPEN_CONN_FLAG		(1<<3)
#define PHY_OVER_CURRENT_FLAG		(1<<4)
#define PHY_SFP_TX_FAULT_FLAG		(1<<5)

	u8 mac_type;
#define MAC_TYPE_NONE		0
#define MAC_TYPE_EMAC		1
#define MAC_TYPE_BMAC		2
#define MAC_TYPE_UMAC		3
#define MAC_TYPE_XMAC		4

	u8 phy_link_up; /* internal phy link indication */
	u8 link_up;

	u16 line_speed;
	u16 duplex;

	u16 flow_ctrl;
	u16 ieee_fc;

	/* The same definitions as the shmem parameter */
	u32 link_status;
	u32 eee_status;
	u8 fault_detected;
	u8 check_kr2_recovery_cnt;
#define CHECK_KR2_RECOVERY_CNT	5
	u16 periodic_flags;
#define PERIODIC_FLAGS_LINK_EVENT	0x0001

	u32 aeu_int_mask;
	u8 rx_tx_asic_rst;
	u8 turn_to_run_wc_rt;
	u16 rsrv2;
};

/***********************************************************/
/*                         Functions                       */
/***********************************************************/
int bnx2x_phy_init(struct link_params *params, struct link_vars *vars);

/* Reset the link. Should be called when driver or interface goes down
   Before calling phy firmware upgrade, the reset_ext_phy should be set
   to 0 */
int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
		     u8 reset_ext_phy);
int bnx2x_lfa_reset(struct link_params *params, struct link_vars *vars);
/* bnx2x_link_update should be called upon link interrupt */
int bnx2x_link_update(struct link_params *params, struct link_vars *vars);

/* use the following phy functions to read/write from external_phy
  In order to use it to read/write internal phy registers, use
  DEFAULT_PHY_DEV_ADDR as devad, and (_bank + (_addr & 0xf)) as
  the register */
int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
		   u8 devad, u16 reg, u16 *ret_val);

int bnx2x_phy_write(struct link_params *params, u8 phy_addr,
		    u8 devad, u16 reg, u16 val);

/* Reads the link_status from the shmem,
   and update the link vars accordingly */
void bnx2x_link_status_update(struct link_params *input,
			    struct link_vars *output);
/* returns string representing the fw_version of the external phy */
int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 *version,
				 u16 len);

/* Set/Unset the led
   Basically, the CLC takes care of the led for the link, but in case one needs
   to set/unset the led unnaturally, set the "mode" to LED_MODE_OPER to
   blink the led, and LED_MODE_OFF to set the led off.*/
int bnx2x_set_led(struct link_params *params,
		  struct link_vars *vars, u8 mode, u32 speed);
#define LED_MODE_OFF			0
#define LED_MODE_ON			1
#define LED_MODE_OPER			2
#define LED_MODE_FRONT_PANEL_OFF	3

/* bnx2x_handle_module_detect_int should be called upon module detection
   interrupt */
void bnx2x_handle_module_detect_int(struct link_params *params);

/* Get the actual link status. In case it returns 0, link is up,
	otherwise link is down*/
int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
		    u8 is_serdes);

/* One-time initialization for external phy after power up */
int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
			  u32 shmem2_base_path[], u32 chip_id);

/* Reset the external PHY using GPIO */
void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);

/* Reset the external of SFX7101 */
void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy);

/* Read "byte_cnt" bytes from address "addr" from the SFP+ EEPROM */
int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
				 struct link_params *params, u8 dev_addr,
				 u16 addr, u16 byte_cnt, u8 *o_buf);

void bnx2x_hw_reset_phy(struct link_params *params);

/* Check swap bit and adjust PHY order */
u32 bnx2x_phy_selection(struct link_params *params);

/* Probe the phys on board, and populate them in "params" */
int bnx2x_phy_probe(struct link_params *params);

/* Checks if fan failure detection is required on one of the phys on board */
u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
			     u32 shmem2_base, u8 port);

/* Open / close the gate between the NIG and the BRB */
void bnx2x_set_rx_filter(struct link_params *params, u8 en);

/* DCBX structs */

/* Number of maximum COS per chip */
#define DCBX_E2E3_MAX_NUM_COS		(2)
#define DCBX_E3B0_MAX_NUM_COS_PORT0	(6)
#define DCBX_E3B0_MAX_NUM_COS_PORT1	(3)
#define DCBX_E3B0_MAX_NUM_COS		( \
			MAXVAL(DCBX_E3B0_MAX_NUM_COS_PORT0, \
			    DCBX_E3B0_MAX_NUM_COS_PORT1))

#define DCBX_MAX_NUM_COS			( \
			MAXVAL(DCBX_E3B0_MAX_NUM_COS, \
			    DCBX_E2E3_MAX_NUM_COS))

/* PFC port configuration params */
struct bnx2x_nig_brb_pfc_port_params {
	/* NIG */
	u32 pause_enable;
	u32 llfc_out_en;
	u32 llfc_enable;
	u32 pkt_priority_to_cos;
	u8 num_of_rx_cos_priority_mask;
	u32 rx_cos_priority_mask[DCBX_MAX_NUM_COS];
	u32 llfc_high_priority_classes;
	u32 llfc_low_priority_classes;
};

/* ETS port configuration params */
struct bnx2x_ets_bw_params {
	u8 bw;
};

struct bnx2x_ets_sp_params {
	/**
	 * valid values are 0 - 5. 0 is highest strict priority.
	 * There can't be two COS's with the same pri.
	 */
	u8 pri;
};

enum bnx2x_cos_state {
	bnx2x_cos_state_strict = 0,
	bnx2x_cos_state_bw = 1,
};

struct bnx2x_ets_cos_params {
	enum bnx2x_cos_state state ;
	union {
		struct bnx2x_ets_bw_params bw_params;
		struct bnx2x_ets_sp_params sp_params;
	} params;
};

struct bnx2x_ets_params {
	u8 num_of_cos; /* Number of valid COS entries*/
	struct bnx2x_ets_cos_params cos[DCBX_MAX_NUM_COS];
};

/* Used to update the PFC attributes in EMAC, BMAC, NIG and BRB
 * when link is already up
 */
int bnx2x_update_pfc(struct link_params *params,
		      struct link_vars *vars,
		      struct bnx2x_nig_brb_pfc_port_params *pfc_params);

/* Used to configure the ETS to disable */
int bnx2x_ets_disabled(struct link_params *params,
		       struct link_vars *vars);

/* Used to configure the ETS to BW limited */
void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
			const u32 cos1_bw);

/* Used to configure the ETS to strict */
int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);

/*  Configure the COS to ETS according to BW and SP settings.*/
int bnx2x_ets_e3b0_config(const struct link_params *params,
			 const struct link_vars *vars,
			 struct bnx2x_ets_params *ets_params);

void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
			    u32 chip_id, u32 shmem_base, u32 shmem2_base,
			    u8 port);

void bnx2x_period_func(struct link_params *params, struct link_vars *vars);

#endif /* BNX2X_LINK_H */


/////////////////////////////////////////////////////////////////////////////
// HippoPlugInApp.cpp

#include "StdAfx.h"
#include "SampleSkinHandlerPlugIn.h"
#include "../SampleSkin/Resource.h"

void CSampleSkinHandlerPlugIn::OnInitPlugInMenuPopups(WPARAM wParam, LPARAM lParam)
{
  UNREFERENCED_PARAMETER(wParam);
  UNREFERENCED_PARAMETER(lParam);
  // TODO
}

BOOL CSampleSkinHandlerPlugIn::OnPlugInMenuCommand(WPARAM wParam)
{
  switch (wParam)
  {
  case ID_FILE_NEW:
    RhinoApp().RunMenuScript(L"! _New");
    break;
  case ID_FILE_OPEN:
    RhinoApp().RunMenuScript(L"! _Open");
    break;
  case ID_FILE_SAVE:
    RhinoApp().RunMenuScript(L"! _Save");
    break;
  case ID_FILE_SAVEAS:
    RhinoApp().RunMenuScript(L"! _SaveAs");
    break;
  case ID_FILE_EXIT:
    RhinoApp().RunMenuScript(L"! _Exit");
    break;
  }

  return TRUE;
}


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netstandard2.1;netstandard2.0</TargetFrameworks>
    <LangVersion>8.0</LangVersion>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
    <OutputPath>.\bin\$(Configuration)</OutputPath>
    <DocumentationFile>$(OutputPath)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
    <RootDir>$(MSBuildProjectDirectory)\..\..\..</RootDir>
  </PropertyGroup>

  <!-- delay sign the assembly for Release build -->
  <PropertyGroup Condition=" '$(Configuration)' == 'Release' AND '$(AZURE_IOT_DONOTSIGN.ToUpper())' != 'TRUE' ">
    <AssemblyOriginatorKeyFile>$(RootDir)\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
    <DelaySign>true</DelaySign>
    <SignAssembly>true</SignAssembly>
  </PropertyGroup>

  <PropertyGroup>
    <Version>1.7.0</Version>
    <Title>Microsoft Azure IoT Provisioning Service Client SDK</Title>
    <IncludeSource>True</IncludeSource>
    <IncludeSymbols>True</IncludeSymbols>
    <SymbolPackageFormat>snupkg</SymbolPackageFormat>
    <Authors>Microsoft</Authors>
    <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
    <PackageLicenseFile>LICENSE</PackageLicenseFile>
    <Description>Provisioning Service Client SDK for Azure IoT</Description>
    <PackageIcon>nugetIcon.png</PackageIcon>
    <PackageProjectUrl>https://github.com/Azure/azure-iot-sdk-csharp</PackageProjectUrl>
    <Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
    <PackageTags>Microsoft Azure IoT Provisioning Service Client .NET HTTP</PackageTags>
  </PropertyGroup>

  <ItemGroup>
    <None Include="$(RootDir)\LICENSE" Pack="true" PackagePath="" />
    <None Include="$(RootDir)\shared\icons\nugetIcon.png" Pack="true" PackagePath="" />
  </ItemGroup>

  <PropertyGroup>
    <common>$(RootDir)\common\src</common>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="$(common)\service\CommonResources.cs" Link="Common\CommonResources.cs" />
    <Compile Include="$(common)\service\EventTraceActivity.cs" Link="Common\EventTraceActivity.cs" />
    <Compile Include="$(common)\service\Resources.Designer.cs" Link="Common\Resources.Designer.cs" />
    <Compile Include="$(common)\service\StringValidationHelper.cs" Link="Common\StringValidationHelper.cs" />
    <Compile Include="$(common)\service\Utils.cs" Link="Common\Utils.cs" />
    <Compile Include="$(Common)\DefaultWebProxySettings.cs" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
    <PackageReference Condition=" '$(Configuration)' == 'Debug' " Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="$(RootDir)\shared\src\Microsoft.Azure.Devices.Shared.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Compile Update="Properties\ApiResources.Designer.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>ApiResources.resx</DependentUpon>
    </Compile>
  </ItemGroup>

  <ItemGroup>
    <EmbeddedResource Update="Properties\ApiResources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>ApiResources.Designer.cs</LastGenOutput>
      <CustomToolNamespace>Microsoft.Azure.Devices</CustomToolNamespace>
    </EmbeddedResource>
  </ItemGroup>
</Project>


// The MIT License (MIT)
//
// Copyright (c) 2019 Henk-Jan Lebbink
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

namespace AsmSim
{
    // The above copyright notice and this permission notice shall be included in all
    // copies or substantial portions of the Software.

    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    // SOFTWARE.

    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Text;
    using AsmTools;
    using Microsoft.Z3;

    public class StateUpdate : IDisposable
    {
        #region Fields
        private readonly Tools tools_;
        private readonly Context ctx_;
        private string nextKey_;
        private readonly string prevKey_Regular_;
        private readonly string prevKey_Branch_;
        private readonly BoolExpr branch_Condition_;

        public bool Empty { get; private set; }

        /// Gets or sets a value indicating whether gets if this stateUpdate is an update in which the state is reset.
        public bool Reset { get; set; }

        private BranchInfo branchInfo_;

        private readonly object ctxLock_ = new object();

        #endregion

        #region Flags
        private BoolExpr cf_ = null;
        private BoolExpr pf_ = null;
        private BoolExpr af_ = null;
        private BoolExpr zf_ = null;
        private BoolExpr sf_ = null;
        private BoolExpr of_ = null;
        private BoolExpr df_ = null;

        private BoolExpr cf_U_ = null;
        private BoolExpr pf_U_ = null;
        private BoolExpr af_U_ = null;
        private BoolExpr zf_U_ = null;
        private BoolExpr sf_U_ = null;
        private BoolExpr of_U_ = null;
        private BoolExpr df_U_ = null;
        #endregion

        #region Registers
        private BoolExpr rax_ = null;
        private BoolExpr rbx_ = null;
        private BoolExpr rcx_ = null;
        private BoolExpr rdx_ = null;

        private BoolExpr rsi_ = null;
        private BoolExpr rdi_ = null;
        private BoolExpr rbp_ = null;
        private BoolExpr rsp_ = null;

        private BoolExpr r8_ = null;
        private BoolExpr r9_ = null;
        private BoolExpr r10_ = null;
        private BoolExpr r11_ = null;

        private BoolExpr r12_ = null;
        private BoolExpr r13_ = null;
        private BoolExpr r14_ = null;
        private BoolExpr r15_ = null;

        private BoolExpr simd_ = null;

        private BoolExpr rax_U_ = null;
        private BoolExpr rbx_U_ = null;
        private BoolExpr rcx_U_ = null;
        private BoolExpr rdx_U_ = null;

        private BoolExpr rsi_U_ = null;
        private BoolExpr rdi_U_ = null;
        private BoolExpr rbp_U_ = null;
        private BoolExpr rsp_U_ = null;

        private BoolExpr r8_U_ = null;
        private BoolExpr r9_U_ = null;
        private BoolExpr r10_U_ = null;
        private BoolExpr r11_U_ = null;

        private BoolExpr r12_U_ = null;
        private BoolExpr r13_U_ = null;
        private BoolExpr r14_U_ = null;
        private BoolExpr r15_U_ = null;

        private BoolExpr simd_U_ = null;
        #endregion

        #region Memory
        private BoolExpr mem_Update_ = null;
        private BoolExpr mem_Update_U_ = null;
        private ArrayExpr mem_Full_ = null;
        #endregion

        #region Constructor

        ///  Constructor
        public StateUpdate(string prevKey, string nextKey, Tools tools)
        {
            Contract.Requires(tools != null);

            this.branch_Condition_ = null;
            this.prevKey_Regular_ = prevKey;
            this.prevKey_Branch_ = null;
            this.nextKey_ = nextKey;
            this.tools_ = tools;
            this.ctx_ = new Context(tools.ContextSettings); // housekeeping in Dispose();
            this.Empty = true;
        }

        //TODO consider creating a special StateUpdateMerge class

        /// Constructor for merging. prevKey_Regular is the key for the regular continue for the provided branchCondition
        public StateUpdate(BoolExpr branchCondition, string prevKey_Regular, string prevKey_Branch, string nextKey, Tools tools)
        {
            Contract.Requires(tools != null);
            Contract.Requires(branchCondition != null);

            this.ctx_ = new Context(tools.ContextSettings); // housekeeping in Dispose();
            this.branch_Condition_ = branchCondition.Translate(this.ctx_) as BoolExpr;
            this.prevKey_Regular_ = prevKey_Regular;
            this.prevKey_Branch_ = prevKey_Branch;
            this.nextKey_ = nextKey;
            this.tools_ = tools;
            this.Empty = false;
        }
        #endregion

        /// Update the provided state with this stateUpdate
        public void Update(State state)
        {
            Contract.Requires(state != null);

            lock (this.ctxLock_)
            {
                if (!this.Reset)
                {
                    state.Assert(this.Value, false, true);
                    state.Assert(this.simd_, false, true);
                }
                state.Assert(this.Undef, true, true);
                state.Assert(this.simd_U_, true, true);

                state.Add(this.BranchInfo);
            }
        }

        //TODO
        public BitVecExpr NextLineNumberExpr { get; set; }

        #region Getters
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
        private IEnumerable<BoolExpr> Value
        {
            get
            {
                Context ctx = this.ctx_;

                foreach (Flags flag in this.tools_.StateConfig.GetFlagOn())
                {
                    yield return this.Get_Private(flag, false);
                }
                foreach (Rn reg in this.tools_.StateConfig.GetRegOn())
                {
                    yield return this.Get_Private(reg, false);
                }
                if (this.tools_.StateConfig.Mem)
                {
                    if (this.mem_Full_ != null)
                    {
                        yield return this.mem_Update_ ?? ctx.MkEq(Tools.Create_Mem_Key(this.NextKey, ctx), this.mem_Full_);
                    }
                    else
                    {
                        if (this.branch_Condition_ == null)
                        {
                            yield return this.mem_Update_ ?? ctx.MkEq(Tools.Create_Mem_Key(this.NextKey, ctx), Tools.Create_Mem_Key(this.prevKey_Regular_, ctx));
                        }
                        else
                        {
                            yield return ctx.MkEq(Tools.Create_Mem_Key(this.NextKey, ctx), ctx.MkITE(this.branch_Condition_, Tools.Create_Mem_Key(this.prevKey_Regular_, ctx), Tools.Create_Mem_Key(this.prevKey_Branch_, ctx)));
                        }
                    }
                }
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
        private IEnumerable<BoolExpr> Undef
        {
            get
            {
                Context ctx = this.ctx_;

                foreach (Flags flag in this.tools_.StateConfig.GetFlagOn())
                {
                    yield return this.Get_Private(flag, true);
                }
                foreach (Rn reg in this.tools_.StateConfig.GetRegOn())
                {
                    yield return this.Get_Private(reg, true);
                }
                if (this.tools_.StateConfig.Mem)
                {
                    if (this.mem_Full_ != null)
                    {
                        yield return this.mem_Update_U_ ?? ctx.MkEq(Tools.Create_Mem_Key(this.NextKey, ctx), this.mem_Full_);
                    }
                    else
                    {
                        if (this.branch_Condition_ == null)
                        {
                            yield return this.mem_Update_U_ ?? ctx.MkEq(Tools.Create_Mem_Key(this.NextKey, ctx), Tools.Create_Mem_Key(this.prevKey_Regular_, ctx));
                        }
                        else
                        {
                            yield return ctx.MkEq(Tools.Create_Mem_Key(this.NextKey, ctx), ctx.MkITE(this.branch_Condition_, Tools.Create_Mem_Key(this.prevKey_Regular_, ctx), Tools.Create_Mem_Key(this.prevKey_Branch_, ctx)));
                        }
                    }
                }
            }
        }

        public BranchInfo BranchInfo
        {
            get { return this.branchInfo_; }

            set
            {
                if (value != null)
                {
                    this.Empty = false;
                }

                if (this.branchInfo_ != null)
                {
                    Console.WriteLine("WARNING: StatusUpdate:BranchInfo.Set: branchInfo is already set.");
                }

                this.branchInfo_ = value;
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
        private BoolExpr Get_Private(Rn reg, bool undef)
        {
            lock (this.ctxLock_)
            {
                Context ctx = this.ctx_;
                if (this.branch_Condition_ == null)
                {
                    return this.Get_Raw_Private(reg, undef) ?? ctx.MkEq(Tools.Create_Key(reg, this.NextKey, ctx), Tools.Create_Key(reg, this.prevKey_Regular_, ctx));
                }
                else
                {
                    return ctx.MkEq(
                        Tools.Create_Key(reg, this.NextKey, ctx),
                        ctx.MkITE(this.branch_Condition_, Tools.Create_Key(reg, this.prevKey_Regular_, ctx), Tools.Create_Key(reg, this.prevKey_Branch_, ctx)));
                }
            }
        }

        private BoolExpr Get_Raw_Private(Rn reg, bool undef)
        {
            switch (reg)
            {
                case Rn.RAX: return undef ? this.rax_U_ : this.rax_;
                case Rn.RBX: return undef ? this.rbx_U_ : this.rbx_;
                case Rn.RCX: return undef ? this.rcx_U_ : this.rcx_;
                case Rn.RDX: return undef ? this.rdx_U_ : this.rdx_;

                case Rn.RSI: return undef ? this.rsi_U_ : this.rsi_;
                case Rn.RDI: return undef ? this.rdi_U_ : this.rdi_;
                case Rn.RBP: return undef ? this.rbp_U_ : this.rbp_;
                case Rn.RSP: return undef ? this.rsp_U_ : this.rsp_;

                case Rn.R8: return undef ? this.r8_U_ : this.r8_;
                case Rn.R9: return undef ? this.r9_U_ : this.r9_;
                case Rn.R10: return undef ? this.r10_U_ : this.r10_;
                case Rn.R11: return undef ? this.r11_U_ : this.r11_;

                case Rn.R12: return undef ? this.r12_U_ : this.r12_;
                case Rn.R13: return undef ? this.r13_U_ : this.r13_;
                case Rn.R14: return undef ? this.r14_U_ : this.r14_;
                case Rn.R15: return undef ? this.r15_U_ : this.r15_;

                default: throw new Exception();
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
        private BoolExpr Get_Private(Flags flag, bool undef)
        {
            lock (this.ctxLock_)
            {
                Context ctx = this.ctx_;
                if (this.branch_Condition_ == null)
                {
                    BoolExpr f1 = Tools.Create_Key(flag, this.NextKey, ctx);
                    BoolExpr f2 = Tools.Create_Key(flag, this.prevKey_Regular_, ctx);
                    return this.Get_Raw_Private(flag, undef) ?? ctx.MkEq(f1, f2);
                }
                else
                {
                    BoolExpr f1 = Tools.Create_Key(flag, this.NextKey, ctx);
                    BoolExpr f2 = Tools.Create_Key(flag, this.prevKey_Regular_, ctx);
                    BoolExpr f3 = Tools.Create_Key(flag, this.prevKey_Branch_, ctx);
                    return ctx.MkEq(f1, ctx.MkITE(this.branch_Condition_, f2, f3));
                }
            }
        }

        private BoolExpr Get_Raw_Private(Flags flag, bool undef)
        {
            switch (flag)
            {
                case Flags.CF: return undef ? this.cf_U_ : this.cf_;
                case Flags.PF: return undef ? this.pf_U_ : this.pf_;
                case Flags.AF: return undef ? this.af_U_ : this.af_;
                case Flags.ZF: return undef ? this.zf_U_ : this.zf_;
                case Flags.SF: return undef ? this.sf_U_ : this.sf_;
                case Flags.OF: return undef ? this.of_U_ : this.of_;
                case Flags.DF: return undef ? this.df_U_ : this.df_;
                default: throw new Exception();
            }
        }
        #endregion

        #region Setters

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
        public string NextKey
        {
            get { return this.nextKey_; }

            set
            {
                if (this.nextKey_ == null)
                {
                    this.nextKey_ = value;
                }
                else if (this.nextKey_ != value)
                {
                    Context ctx = this.ctx_;

                    foreach (Flags flag in this.tools_.StateConfig.GetFlagOn())
                    {
                        {
                            BoolExpr expr = this.Get_Raw_Private(flag, false);
                            if (expr != null)
                            {
                                this.Set_Private(flag, expr.Substitute(Tools.Create_Key(flag, this.nextKey_, ctx), Tools.Create_Key(flag, value, ctx)) as BoolExpr, false);
                            }
                        }
                        {
                            BoolExpr expr = this.Get_Raw_Private(flag, true);
                            if (expr != null)
                            {
                                this.Set_Private(flag, expr.Substitute(Tools.Create_Key(flag, this.nextKey_, ctx), Tools.Create_Key(flag, value, ctx)) as BoolExpr, true);
                            }
                        }
                    }
                    foreach (Rn reg in this.tools_.StateConfig.GetRegOn())
                    {
                        {
                            BoolExpr expr = this.Get_Raw_Private(reg, false);
                            if (expr != null)
                            {
                                this.Set_Private(reg, expr.Substitute(Tools.Create_Key(reg, this.nextKey_, ctx), Tools.Create_Key(reg, value, ctx)) as BoolExpr, false);
                            }
                        }
                        {
                            BoolExpr expr = this.Get_Raw_Private(reg, true);
                            if (expr != null)
                            {
                                this.Set_Private(reg, expr.Substitute(Tools.Create_Key(reg, this.nextKey_, ctx), Tools.Create_Key(reg, value, ctx)) as BoolExpr, true);
                            }
                        }
                    }
                    if (this.tools_.StateConfig.Mem)
                    {
                        if (this.mem_Update_ != null)
                        {
                            this.mem_Update_ = this.mem_Update_.Substitute(Tools.Create_Mem_Key(this.nextKey_, ctx), Tools.Create_Mem_Key(value, ctx)) as BoolExpr;
                        }
                        if (this.mem_Update_U_ != null)
                        {
                            this.mem_Update_U_ = this.mem_Update_U_.Substitute(Tools.Create_Mem_Key(this.nextKey_, ctx), Tools.Create_Mem_Key(value, ctx)) as BoolExpr;
                        }
                    }
                    this.nextKey_ = value;
                }
            }
        }

        #region Set Flag
        public void Set(Flags flag, bool value)
        {
            this.Set(flag, value ? Tv.ONE : Tv.ZERO);
        }

        public void Set(Flags flag, Tv value)
        {
            lock (this.ctxLock_)
            {
                switch (value)
                {
                    case Tv.ZERO: this.Set(flag, this.ctx_.MkFalse()); break;
                    case Tv.ONE: this.Set(flag, this.ctx_.MkTrue()); break;
                    case Tv.UNKNOWN: this.Set(flag, null, this.ctx_.MkTrue()); break;
                    case Tv.UNDEFINED: this.Set(flag, null, null); break;
                    default: throw new Exception();
                }
            }
        }

        public void Set(Flags flag, BoolExpr value)
        {
            this.Set(flag, value, value);
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
        public void Set(Flags flag, BoolExpr value, BoolExpr undef)
        {
            this.Empty = false;

            lock (this.ctxLock_)
            {
                Context ctx = this.ctx_;

                value = value?.Translate(ctx) as BoolExpr;
                undef = undef?.Translate(ctx) as BoolExpr;

                BoolExpr key = Tools.Create_Key(flag, this.NextKey, ctx);
                BoolExpr value_Constraint;
                {
                    if (value == null)
                    {
                        value_Constraint = ctx.MkEq(key, Tools.Create_Flag_Key_Fresh(flag, this.tools_.Rand, ctx));
                    }
                    else if (value.IsTrue)
                    {
                        value_Constraint = key;
                    }
                    else if (value.IsFalse)
                    {
                        value_Constraint = ctx.MkNot(key);
                    }
                    else
                    {
                        value_Constraint = ctx.MkEq(key, value);
                    }
                }
                BoolExpr undef_Constraint;
                {
                    if (undef == null)
                    {
                        undef_Constraint = ctx.MkEq(key, Tools.Create_Flag_Key_Fresh(flag, this.tools_.Rand, ctx));
                    }
                    else if (undef.IsTrue)
                    {
                        undef_Constraint = key;
                    }
                    else if (undef.IsFalse)
                    {
                        undef_Constraint = ctx.MkNot(key);
                    }
                    else
                    {
                        undef_Constraint = ctx.MkEq(key, undef);
                    }
                }

                this.Set_Private(flag, value_Constraint, false);
                this.Set_Private(flag, undef_Constraint, true);
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
        public void Set_SF_ZF_PF(BitVecExpr value)
        {
            Contract.Requires(value != null);
            this.Empty = false;

            lock (this.ctxLock_)
            {
                Context ctx = this.ctx_;
                value = value.Translate(ctx) as BitVecExpr;
                this.Set(Flags.SF, ToolsFlags.Create_SF(value, value.SortSize, ctx));
                this.Set(Flags.ZF, ToolsFlags.Create_ZF(value, ctx));
                this.Set(Flags.PF, ToolsFlags.Create_PF(value, ctx));
            }
        }

        private void Set_Private(Flags flag, BoolExpr value, bool undef)
        {
            switch (flag)
            {
                case Flags.CF:
                    if (undef)
                    {
                        this.cf_U_ = value;
                    }
                    else
                    {
                        this.cf_ = value;
                    }
                    break;
                case Flags.PF:
                    if (undef)
                    {
                        this.pf_U_ = value;
                    }
                    else
                    {
                        this.pf_ = value;
                    }
                    break;
                case Flags.AF:
                    if (undef)
                    {
                        this.af_U_ = value;
                    }
                    else
                    {
                        this.af_ = value;
                    }
                    break;
                case Flags.ZF:
                    if (undef)
                    {
                        this.zf_U_ = value;
                    }
                    else
                    {
                        this.zf_ = value;
                    }
                    break;
                case Flags.SF:
                    if (undef)
                    {
                        this.sf_U_ = value;
                    }
                    else
                    {
                        this.sf_ = value;
                    }
                    break;
                case Flags.OF:
                    if (undef)
                    {
                        this.of_U_ = value;
                    }
                    else
                    {
                        this.of_ = value;
                    }
                    break;
                case Flags.DF:
                    if (undef)
                    {
                        this.df_U_ = value;
                    }
                    else
                    {
                        this.df_ = value;
                    }
                    break;
                default: throw new Exception();
            }
        }

        #endregion

        #region Set Register
        public void Set(Rn reg, ulong value)
        {
            BitVecExpr valueExpr = this.ctx_.MkBV(value, (uint)RegisterTools.NBits(reg));
            this.Set(reg, valueExpr, valueExpr);
        }

        public void Set(Rn reg, string value)
        {
            this.Set(reg, ToolsZ3.GetTvArray(value));
        }

        public void Set(Rn reg, Tv[] value)
        {
            (BitVecExpr value, BitVecExpr undef) tup = ToolsZ3.MakeVecExpr(value, this.ctx_);
            this.Set(reg, tup.value, tup.undef);
        }

        ///  Fill all bits of the provided register with the provided truth-value
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
        public void Set(Rn reg, Tv value)
        {
            switch (value)
            {
                case Tv.ZERO: this.Set(reg, 0UL); break;
                case Tv.UNKNOWN:
                    BitVecExpr unknown = Tools.Create_Reg_Key_Fresh(reg, this.tools_.Rand, this.ctx_);
                    this.Set(reg, unknown, this.ctx_.MkBV(0, (uint)RegisterTools.NBits(reg)));
                    break;
                case Tv.INCONSISTENT:
                case Tv.UNDEFINED:
                case Tv.ONE:
                    throw new Exception("Not implemented yet");
                    break;
                default: break;
            }
        }

        public void Set(Rn reg, BitVecExpr value)
        {
            this.Set(reg, value, value);
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
        public void Set(Rn reg, BitVecExpr value, BitVecExpr undef)
        {
            Contract.Requires(value != null);
            Contract.Requires(undef != null);

            this.Empty = false;

            lock (this.ctxLock_)
            {
                Context ctx = this.ctx_;

                value = value.Translate(ctx) as BitVecExpr;
                undef = undef.Translate(ctx) as BitVecExpr;

                if (RegisterTools.IsGeneralPurposeRegister(reg))
                {
                    Rn reg64 = RegisterTools.Get64BitsRegister(reg);
                    uint nBits = value.SortSize;
                    switch (nBits)
                    {
                        case 64: break;
                        case 32:
                            {
                                value = ctx.MkZeroExt(32, value);
                                undef = ctx.MkZeroExt(32, undef);
                                break;
                            }
                        case 16:
                            {
                                BitVecExpr reg64Expr = Tools.Create_Key(reg64, this.prevKey_Regular_, ctx);
                                BitVecExpr prefix = ctx.MkExtract(63, 16, reg64Expr);
                                value = ctx.MkConcat(prefix, value);
                                undef = ctx.MkConcat(prefix, undef);
                                break;
                            }
                        case 8:
                            {
                                BitVecExpr reg64Expr = Tools.Create_Key(reg64, this.prevKey_Regular_, ctx);
                                if (RegisterTools.Is8BitHigh(reg))
                                {
                                    BitVecExpr postFix = ctx.MkExtract(7, 0, reg64Expr);
                                    BitVecExpr prefix = ctx.MkExtract(63, 16, reg64Expr);
                                    value = ctx.MkConcat(ctx.MkConcat(prefix, value), postFix);
                                    undef = ctx.MkConcat(ctx.MkConcat(prefix, undef), postFix);
                                }
                                else
                                {
                                    BitVecExpr prefix = ctx.MkExtract(63, 8, reg64Expr);
                                    value = ctx.MkConcat(prefix, value);
                                    undef = ctx.MkConcat(prefix, undef);
                                }
                                break;
                            }
                        default:
                            {
                                Console.WriteLine("ERROR: Set: bits=" + nBits + "; value=" + value + "; undef=" + undef);
                                throw new Exception();
                            }
                    }
                    {
                        BitVecExpr key = Tools.Create_Key(reg64, this.NextKey, ctx);
                        BoolExpr value_Constraint = ctx.MkEq(key, value) as BoolExpr;
                        BoolExpr undef_Constraint = ctx.MkEq(key, undef) as BoolExpr;

                        if (this.Get_Raw_Private(reg64, false) != null)
                        {
                            throw new Exception("Multiple assignments to register " + reg64);
                        }

                        this.Set_Private(reg64, value_Constraint, false);
                        this.Set_Private(reg64, undef_Constraint, true);
                    }
                }
                else if (RegisterTools.Is_SIMD_Register(reg))
                {
                    uint max = 512 * 32;

                    BitVecExpr prevKey = ctx.MkBVConst(Tools.Reg_Name(reg, this.prevKey_Regular_), max);
                    (uint high, uint low) = Tools.SIMD_Extract_Range(reg);

                    BitVecExpr top = null;
                    BitVecExpr bottom = null;
                    if (high < (max - 1))
                    {
                        top = ctx.MkExtract(max - 1, high + 1, prevKey);
                    }

                    if (low > 0)
                    {
                        bottom = ctx.MkExtract(low - 1, 0, prevKey);
                    }

                    Console.WriteLine(top.SortSize + "+" + value.SortSize + "+" + bottom.SortSize + "=" + prevKey.SortSize);

                    BitVecExpr newValue = (top == null) ? value : ctx.MkConcat(top, value) as BitVecExpr;
                    newValue = (bottom == null) ? newValue : ctx.MkConcat(newValue, bottom);
                    BitVecExpr newUndef = (top == null) ? value : ctx.MkConcat(top, value) as BitVecExpr;
                    newUndef = (bottom == null) ? newUndef : ctx.MkConcat(newUndef, bottom);

                    BitVecExpr nextKey = ctx.MkBVConst(Tools.Reg_Name(reg, this.NextKey), 512 * 32);
                    //Debug.Assert(newValue.SortSize == nextKey.SortSize);

                    this.simd_ = ctx.MkEq(nextKey, newValue);
                    this.simd_U_ = ctx.MkEq(nextKey, newUndef);
                }
                else
                {
                    // do nothing;
                }
            }
        }

        private void Set_Private(Rn reg, BoolExpr value, bool undef)
        {
            switch (reg)
            {
                case Rn.RAX:
                    if (undef)
                    {
                        this.rax_U_ = value;
                    }
                    else
                    {
                        this.rax_ = value;
                    }
                    break;
                case Rn.RBX:
                    if (undef)
                    {
                        this.rbx_U_ = value;
                    }
                    else
                    {
                        this.rbx_ = value;
                    }
                    break;
                case Rn.RCX:
                    if (undef)
                    {
                        this.rcx_U_ = value;
                    }
                    else
                    {
                        this.rcx_ = value;
                    }
                    break;
                case Rn.RDX:
                    if (undef)
                    {
                        this.rdx_U_ = value;
                    }
                    else
                    {
                        this.rdx_ = value;
                    }
                    break;

                case Rn.RSI:
                    if (undef)
                    {
                        this.rsi_U_ = value;
                    }
                    else
                    {
                        this.rsi_ = value;
                    }
                    break;
                case Rn.RDI:
                    if (undef)
                    {
                        this.rdi_U_ = value;
                    }
                    else
                    {
                        this.rdi_ = value;
                    }
                    break;
                case Rn.RBP:
                    if (undef)
                    {
                        this.rbp_U_ = value;
                    }
                    else
                    {
                        this.rbp_ = value;
                    }
                    break;
                case Rn.RSP:
                    if (undef)
                    {
                        this.rsp_U_ = value;
                    }
                    else
                    {
                        this.rsp_ = value;
                    }
                    break;

                case Rn.R8:
                    if (undef)
                    {
                        this.r8_U_ = value;
                    }
                    else
                    {
                        this.r8_ = value;
                    }
                    break;
                case Rn.R9:
                    if (undef)
                    {
                        this.r9_U_ = value;
                    }
                    else
                    {
                        this.r9_ = value;
                    }
                    break;
                case Rn.R10:
                    if (undef)
                    {
                        this.r10_U_ = value;
                    }
                    else
                    {
                        this.r10_ = value;
                    }
                    break;
                case Rn.R11:
                    if (undef)
                    {
                        this.r11_U_ = value;
                    }
                    else
                    {
                        this.r11_ = value;
                    }
                    break;

                case Rn.R12:
                    if (undef)
                    {
                        this.r12_U_ = value;
                    }
                    else
                    {
                        this.r12_ = value;
                    }
                    break;
                case Rn.R13:
                    if (undef)
                    {
                        this.r13_U_ = value;
                    }
                    else
                    {
                        this.r13_ = value;
                    }
                    break;
                case Rn.R14:
                    if (undef)
                    {
                        this.r14_U_ = value;
                    }
                    else
                    {
                        this.r14_ = value;
                    }
                    break;
                case Rn.R15:
                    if (undef)
                    {
                        this.r15_U_ = value;
                    }
                    else
                    {
                        this.r15_ = value;
                    }
                    break;

                default: throw new Exception();
            }
        }
        #endregion

        #region Set Memory
        public void Set_Mem(BitVecExpr address, ulong value, int nBytes)
        {
            BitVecExpr valueExpr = this.ctx_.MkBV(value, (uint)nBytes << 3);
            this.Set_Mem(address, valueExpr);
        }

        public void Set_Mem(BitVecExpr address, string value)
        {
            this.Set_Mem(address, ToolsZ3.GetTvArray(value));
        }

        public void Set_Mem(BitVecExpr address, Tv[] value)
        {
            (BitVecExpr value, BitVecExpr undef) tup = ToolsZ3.MakeVecExpr(value, this.ctx_);
            this.Set_Mem(address, tup.value, tup.undef);
        }

        public void Set_Mem(BitVecExpr address, BitVecExpr value)
        {
            this.Set_Mem(address, value, value);
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
        public void Set_Mem(BitVecExpr address, BitVecExpr value, BitVecExpr undef)
        {
            Contract.Requires(address != null);
            Contract.Requires(value != null);
            Contract.Requires(undef != null);

            this.Empty = false;

            lock (this.ctxLock_)
            {
                Context ctx = this.ctx_;
                address = address.Translate(ctx) as BitVecExpr;
                value = value.Translate(ctx) as BitVecExpr;
                undef = undef.Translate(ctx) as BitVecExpr;

                ArrayExpr newMemContent = Tools.Set_Value_To_Mem(value, address, this.prevKey_Regular_, ctx);
                ArrayExpr newMemContent_U = Tools.Set_Value_To_Mem(undef, address, this.prevKey_Regular_, ctx);
                ArrayExpr memKey = Tools.Create_Mem_Key(this.NextKey, ctx);

                //Console.WriteLine("SetMem: memKey=" + memKey + "; new Value=" + newMemContent);
                if (this.mem_Update_ != null)
                {
                    Console.WriteLine("WARNING: StateUpdate:SetMem: multiple memory updates are not allowed");
                    //throw new Exception("Multiple memory updates are not allowed");
                }
                this.mem_Update_ = ctx.MkEq(memKey, newMemContent);
                this.mem_Update_U_ = ctx.MkEq(memKey, newMemContent_U);
            }
        }

        public void Set_Mem(ArrayExpr memContent)
        {
            Contract.Requires(memContent != null);

            this.Empty = false;

            if (this.mem_Full_ != null)
            {
                Console.WriteLine("WARNING: StateUpdate:SetMem: multiple memory updates are not allowed");
                //throw new Exception("Multiple memory updates are not allowed");
            }
            this.mem_Full_ = memContent.Translate(this.ctx_) as ArrayExpr;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
        public void Set_Mem_Unknown()
        {
            this.Set_Mem(Tools.Create_Mem_Key_Fresh(this.tools_.Rand, this.ctx_));
        }

        #endregion

        #region Set Operand
        public void Set(Operand operand, BitVecExpr value)
        {
            this.Set(operand, value, value);
        }

        public void Set(Operand operand, BitVecExpr value, BitVecExpr undef)
        {
            Contract.Requires(operand != null);

            if (operand.IsReg)
            {
                this.Set(operand.Rn, value, undef);
            }
            else if (operand.IsMem)
            {
                BitVecExpr address = Tools.Calc_Effective_Address(operand, this.prevKey_Regular_, this.ctx_);
                this.Set_Mem(address, value, undef);
            }
            else
            {
                throw new Exception();
            }
        }
        #endregion

        #endregion Setters

        #region ToString

        public string ToString2()
        {
            StringBuilder sb = new StringBuilder();
            foreach (Flags flag in this.tools_.StateConfig.GetFlagOn())
            {
                BoolExpr b = this.Get_Raw_Private(flag, true);
                if (b != null)
                {
                    sb.AppendLine(flag + ": " + ToolsZ3.ToString(b));
                }
            }
            foreach (Rn reg in this.tools_.StateConfig.GetRegOn())
            {
                BoolExpr b = this.Get_Raw_Private(reg, true);
                if (b != null)
                {
                    sb.AppendLine(reg + ": " + ToolsZ3.ToString(b));
                }
            }
            if (this.branchInfo_ != null)
            {
                sb.AppendLine(this.branchInfo_.ToString());
            }
            return sb.ToString();
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder("StateUpdate: PrevKey=" + this.prevKey_Regular_ + "; NextKey=" + this.NextKey + " ");
            if (this.Empty)
            {
                sb.AppendLine("Empty UpdateState");
            }

            if (this.Reset)
            {
                sb.AppendLine("Reset UpdateState");
            }

            foreach (Flags flag in this.tools_.StateConfig.GetFlagOn())
            {
                BoolExpr b = this.Get_Raw_Private(flag, true);
                if (b != null)
                {
                    sb.AppendLine(flag + ": " + ToolsZ3.ToString(b));
                }
            }
            foreach (Rn reg in this.tools_.StateConfig.GetRegOn())
            {
                BoolExpr b = this.Get_Raw_Private(reg, true);
                if (b != null)
                {
                    sb.AppendLine(reg + ": " + ToolsZ3.ToString(b));
                }
            }
            if (this.branchInfo_ != null)
            {
                sb.AppendLine(this.branchInfo_.ToString());
            }
            return sb.ToString();
        }

        #endregion

        #region IDisposable Support

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        ~StateUpdate()
        {
            this.Dispose(false);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // free managed resources
                lock (this.ctxLock_)
                {
                    this.cf_?.Dispose();
                    this.pf_?.Dispose();
                    this.af_?.Dispose();
                    this.zf_?.Dispose();
                    this.sf_?.Dispose();
                    this.of_?.Dispose();
                    this.df_?.Dispose();

                    this.cf_U_?.Dispose();
                    this.pf_U_?.Dispose();
                    this.af_U_?.Dispose();
                    this.zf_U_?.Dispose();
                    this.sf_U_?.Dispose();
                    this.of_U_?.Dispose();
                    this.df_U_?.Dispose();

                    this.rax_?.Dispose();
                    this.rbx_?.Dispose();
                    this.rcx_?.Dispose();
                    this.rdx_?.Dispose();

                    this.rsi_?.Dispose();
                    this.rdi_?.Dispose();
                    this.rbp_?.Dispose();
                    this.rsp_?.Dispose();

                    this.r8_?.Dispose();
                    this.r9_?.Dispose();
                    this.r10_?.Dispose();
                    this.r11_?.Dispose();

                    this.r12_?.Dispose();
                    this.r13_?.Dispose();
                    this.r14_?.Dispose();
                    this.r15_?.Dispose();

                    this.simd_?.Dispose();

                    this.rax_U_?.Dispose();
                    this.rbx_U_?.Dispose();
                    this.rcx_U_?.Dispose();
                    this.rdx_U_?.Dispose();

                    this.rsi_U_?.Dispose();
                    this.rdi_U_?.Dispose();
                    this.rbp_U_?.Dispose();
                    this.rsp_U_?.Dispose();

                    this.r8_U_?.Dispose();
                    this.r9_U_?.Dispose();
                    this.r10_U_?.Dispose();
                    this.r11_U_?.Dispose();

                    this.r12_U_?.Dispose();
                    this.r13_U_?.Dispose();
                    this.r14_U_?.Dispose();
                    this.r15_U_?.Dispose();

                    this.simd_U_?.Dispose();
                    this.mem_Update_?.Dispose();
                    this.mem_Update_U_?.Dispose();
                    this.mem_Full_?.Dispose();

                    //TODO HJ 26-10-2019 why when when branch_Condition_ is disposed Get_Private will throw
                    //this.branch_Condition_?.Dispose();

                    this.ctx_.Dispose();
                }
            }
            // free native resources if there are any.
        }
        #endregion
    }
}


all: toy-mcjit toy-jit

toy-mcjit : toy.cpp
	clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core mcjit native` -o toy-mcjit

toy-jit : toy-jit.cpp
	clang++ toy-jit.cpp -g -O3 -rdynamic `llvm-config --cppflags --ldflags --libs core jit native` -o toy-jit


//===------------------------- string.cpp ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "string"
#include "cstdlib"
#include "cwchar"
#include "cerrno"
#include "limits"
#include "stdexcept"
#ifdef _LIBCPP_MSVCRT
#include "support/win32/support.h"
#endif // _LIBCPP_MSVCRT
#include <stdio.h>

_LIBCPP_BEGIN_NAMESPACE_STD

template class __basic_string_common<true>;

template class basic_string<char>;
template class basic_string<wchar_t>;

template
    string
    operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);

namespace
{

template<typename T>
inline
void throw_helper( const string& msg )
{
#ifndef _LIBCPP_NO_EXCEPTIONS
    throw T( msg );
#else
    fprintf(stderr, "%s\n", msg.c_str());
    abort();
#endif
}

inline
void throw_from_string_out_of_range( const string& func )
{
    throw_helper<out_of_range>(func + ": out of range");
}

inline
void throw_from_string_invalid_arg( const string& func )
{
    throw_helper<invalid_argument>(func + ": no conversion");
}

// as_integer

template<typename V, typename S, typename F>
inline
V
as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f)
{
    typename S::value_type* ptr = nullptr;
    const typename S::value_type* const p = str.c_str();
    typename remove_reference<decltype(errno)>::type errno_save = errno;
    errno = 0;
    V r = f(p, &ptr, base);
    swap(errno, errno_save);
    if (errno_save == ERANGE)
        throw_from_string_out_of_range(func);
    if (ptr == p)
        throw_from_string_invalid_arg(func);
    if (idx)
        *idx = static_cast<size_t>(ptr - p);
    return r;
}

template<typename V, typename S>
inline
V
as_integer(const string& func, const S& s, size_t* idx, int base);

// string
template<>
inline
int
as_integer(const string& func, const string& s, size_t* idx, int base )
{
    // Use long as no Standard string to integer exists.
    long r = as_integer_helper<long>( func, s, idx, base, strtol );
    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
        throw_from_string_out_of_range(func);
    return static_cast<int>(r);
}

template<>
inline
long
as_integer(const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<long>( func, s, idx, base, strtol );
}

template<>
inline
unsigned long
as_integer( const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long>( func, s, idx, base, strtoul );
}

template<>
inline
long long
as_integer( const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<long long>( func, s, idx, base, strtoll );
}

template<>
inline
unsigned long long
as_integer( const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
}

// wstring
template<>
inline
int
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    // Use long as no Stantard string to integer exists.
    long r = as_integer_helper<long>( func, s, idx, base, wcstol );
    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
        throw_from_string_out_of_range(func);
    return static_cast<int>(r);
}

template<>
inline
long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<long>( func, s, idx, base, wcstol );
}

template<>
inline
unsigned long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul );
}

template<>
inline
long long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<long long>( func, s, idx, base, wcstoll );
}

template<>
inline
unsigned long long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull );
}

// as_float

template<typename V, typename S, typename F>
inline
V
as_float_helper(const string& func, const S& str, size_t* idx, F f )
{
    typename S::value_type* ptr = nullptr;
    const typename S::value_type* const p = str.c_str();
    typename remove_reference<decltype(errno)>::type errno_save = errno;
    errno = 0;
    V r = f(p, &ptr);
    swap(errno, errno_save);
    if (errno_save == ERANGE)
        throw_from_string_out_of_range(func);
    if (ptr == p)
        throw_from_string_invalid_arg(func);
    if (idx)
        *idx = static_cast<size_t>(ptr - p);
    return r;
}

template<typename V, typename S>
inline
V as_float( const string& func, const S& s, size_t* idx = nullptr );

template<>
inline
float
as_float( const string& func, const string& s, size_t* idx )
{
    return as_float_helper<float>( func, s, idx, strtof );
}

template<>
inline
double
as_float(const string& func, const string& s, size_t* idx )
{
    return as_float_helper<double>( func, s, idx, strtod );
}

template<>
inline
long double
as_float( const string& func, const string& s, size_t* idx )
{
    return as_float_helper<long double>( func, s, idx, strtold );
}

template<>
inline
float
as_float( const string& func, const wstring& s, size_t* idx )
{
    return as_float_helper<float>( func, s, idx, wcstof );
}

template<>
inline
double
as_float( const string& func, const wstring& s, size_t* idx )
{
    return as_float_helper<double>( func, s, idx, wcstod );
}

template<>
inline
long double
as_float( const string& func, const wstring& s, size_t* idx )
{
    return as_float_helper<long double>( func, s, idx, wcstold );
}

}  // unnamed namespace

int
stoi(const string& str, size_t* idx, int base)
{
    return as_integer<int>( "stoi", str, idx, base );
}

int
stoi(const wstring& str, size_t* idx, int base)
{
    return as_integer<int>( "stoi", str, idx, base );
}

long
stol(const string& str, size_t* idx, int base)
{
    return as_integer<long>( "stol", str, idx, base );
}

long
stol(const wstring& str, size_t* idx, int base)
{
    return as_integer<long>( "stol", str, idx, base );
}

unsigned long
stoul(const string& str, size_t* idx, int base)
{
    return as_integer<unsigned long>( "stoul", str, idx, base );
}

unsigned long
stoul(const wstring& str, size_t* idx, int base)
{
    return as_integer<unsigned long>( "stoul", str, idx, base );
}

long long
stoll(const string& str, size_t* idx, int base)
{
    return as_integer<long long>( "stoll", str, idx, base );
}

long long
stoll(const wstring& str, size_t* idx, int base)
{
    return as_integer<long long>( "stoll", str, idx, base );
}

unsigned long long
stoull(const string& str, size_t* idx, int base)
{
    return as_integer<unsigned long long>( "stoull", str, idx, base );
}

unsigned long long
stoull(const wstring& str, size_t* idx, int base)
{
    return as_integer<unsigned long long>( "stoull", str, idx, base );
}

float
stof(const string& str, size_t* idx)
{
    return as_float<float>( "stof", str, idx );
}

float
stof(const wstring& str, size_t* idx)
{
    return as_float<float>( "stof", str, idx );
}

double
stod(const string& str, size_t* idx)
{
    return as_float<double>( "stod", str, idx );
}

double
stod(const wstring& str, size_t* idx)
{
    return as_float<double>( "stod", str, idx );
}

long double
stold(const string& str, size_t* idx)
{
    return as_float<long double>( "stold", str, idx );
}

long double
stold(const wstring& str, size_t* idx)
{
    return as_float<long double>( "stold", str, idx );
}

// to_string

namespace
{

// as_string

template<typename S, typename P, typename V >
inline
S
as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
{
    typedef typename S::size_type size_type;
    size_type available = s.size();
    while (true)
    {
        int status = sprintf_like(&s[0], available + 1, fmt, a);
        if ( status >= 0 )
        {
            size_type used = static_cast<size_type>(status);
            if ( used <= available )
            {
                s.resize( used );
                break;
            }
            available = used; // Assume this is advice of how much space we need.
        }
        else
            available = available * 2 + 1;
        s.resize(available);
    }
    return s;
}

template <class S, class V, bool = is_floating_point<V>::value>
struct initial_string;

template <class V, bool b>
struct initial_string<string, V, b>
{
    string
    operator()() const
    {
        string s;
        s.resize(s.capacity());
        return s;
    }
};

template <class V>
struct initial_string<wstring, V, false>
{
    wstring
    operator()() const
    {
        const size_t n = (numeric_limits<unsigned long long>::digits / 3)
          + ((numeric_limits<unsigned long long>::digits % 3) != 0)
          + 1;
        wstring s(n, wchar_t());
        s.resize(s.capacity());
        return s;
    }
};

template <class V>
struct initial_string<wstring, V, true>
{
    wstring
    operator()() const
    {
        wstring s(20, wchar_t());
        s.resize(s.capacity());
        return s;
    }
};

typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);

inline
wide_printf
get_swprintf()
{
#ifndef _LIBCPP_MSVCRT
    return swprintf;
#else
    return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(swprintf);
#endif
}

}  // unnamed namespace

string to_string(int val)
{
    return as_string(snprintf, initial_string<string, int>()(), "%d", val);
}

string to_string(unsigned val)
{
    return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val);
}

string to_string(long val)
{
    return as_string(snprintf, initial_string<string, long>()(), "%ld", val);
}

string to_string(unsigned long val)
{
    return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val);
}

string to_string(long long val)
{
    return as_string(snprintf, initial_string<string, long long>()(), "%lld", val);
}

string to_string(unsigned long long val)
{
    return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val);
}

string to_string(float val)
{
    return as_string(snprintf, initial_string<string, float>()(), "%f", val);
}

string to_string(double val)
{
    return as_string(snprintf, initial_string<string, double>()(), "%f", val);
}

string to_string(long double val)
{
    return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val);
}

wstring to_wstring(int val)
{
    return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val);
}

wstring to_wstring(unsigned val)
{
    return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val);
}

wstring to_wstring(long val)
{
    return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val);
}

wstring to_wstring(unsigned long val)
{
    return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val);
}

wstring to_wstring(long long val)
{
    return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val);
}

wstring to_wstring(unsigned long long val)
{
    return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val);
}

wstring to_wstring(float val)
{
    return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val);
}

wstring to_wstring(double val)
{
    return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val);
}

wstring to_wstring(long double val)
{
    return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val);
}
_LIBCPP_END_NAMESPACE_STD


####################################################################
# Microwindows and Nano-X configuration file
#
# This package can be configured to run on Linux (MIPS, ARM, POWERPC or x86)
# UNIX, ELKS, DJGPP, or RTEMS.
# On Linux, we've got drivers for Linux 2.x framebuffers, X11, or,
# svgalib for VGA hardware.
# In addition, a gpm or direct serial mouse driver can be configured.
# On ELKS, the bios screen driver and serial mouse driver are always used.
#
# Either Microwindows and/or Nano-X can be built.
# Microwindows and Nano-X have several demos.
#
# For MSDOS makes, see mcmwin.mak and mcnanox.mak
####################################################################

####################################################################
#
# build target platform
#
# Valid ARCH values are:
#
# LINUX-NATIVE
# LINUX-ARM
# LINUX-MIPS
# LINUX-POWERPC
# LINUX-SH
# FREEBSD-X86
# SOLARIS
# RTEMS
# DJGPP
# ELKS
#
# note: ELKS can't build client/server nano-X, nor widget lib
#
####################################################################
ARCH                     = LINUX-NATIVE
ARMTOOLSPREFIX           = arm-linux-
MIPSTOOLSPREFIX          = mipsel-linux-
POWERPCTOOLSPREFIX       = powerpc-linux-
SHTOOLSPREFIX            = sh-linux-gnu
RTEMSTOOLSPREFIX         = i386-rtemself-

####################################################################
#
# Compiling options
#
####################################################################
OPTIMIZE                 = Y
DEBUG                    = N
VERBOSE                  = N

####################################################################
#
# Libraries to build: microwin, nano-X, nanowidget, object frameworks
#
####################################################################
MICROWIN                 = Y
NANOX                    = Y
SHAREDLIBS               = N
OBJFRAMEWORK             = N

####################################################################
#
# Demos to build
#
####################################################################
MICROWINDEMO             = Y
NANOXDEMO                = Y

####################################################################
#
# Applications to build
#
####################################################################
NANOWM                   = Y

####################################################################
#
# The pixeltype of the native hardware or underlying graphics library.
# This definition defines the PIXELVAL to be 32, 16 or 8 bits wide.
# If using Linux framebuffer, set to MWPF_TRUECOLOR0888, and use fbset.
# It also enables GdArea/GrArea for this particular pixel packing format.
#
# define MWPF_PALETTE       /* pixel is packed 8 bits 1, 4 or 8 pal index*/
# define MWPF_TRUECOLOR0888 /* pixel is packed 32 bits 8/8/8 truecolor*/
# define MWPF_TRUECOLOR888  /* pixel is packed 24 bits 8/8/8 truecolor*/
# define MWPF_TRUECOLOR565  /* pixel is packed 16 bits 5/6/5 truecolor*/
# define MWPF_TRUECOLOR555  /* pixel is packed 16 bits 5/5/5 truecolor*/
# define MWPF_TRUECOLOR332  /* pixel is packed 8 bits 3/3/2 truecolor*/
#
####################################################################
SCREEN_PIXTYPE           = MWPF_TRUECOLOR0888

####################################################################
#
# NanoX: Put Y to the following line to link the nano-X application
# with the server.  This is required for ELKS, if no network is present,
# or for speed or debugging.  This affects the nano-X server only.
#
####################################################################
LINK_APP_INTO_SERVER     = N

####################################################################
#
# File I/O support
# Supporting either below drags in libc stdio, which may not be wanted
#
####################################################################
HAVE_FILEIO              = Y

####################################################################
# BMP, GIF reading support
####################################################################
HAVE_BMP_SUPPORT         = Y
HAVE_GIF_SUPPORT         = Y
HAVE_PNM_SUPPORT         = Y
HAVE_XPM_SUPPORT         = Y

####################################################################
# JPEG support through libjpeg, see README.txt in contrib/jpeg
####################################################################
HAVE_JPEG_SUPPORT        = N
INCJPEG                  = .
LIBJPEG                  = /usr/lib/libjpeg.a

####################################################################
# PNG support via libpng and libz
####################################################################
HAVE_PNG_SUPPORT         = N
INCPNG                   = /usr/include
LIBPNG                   = /usr/lib/libpng.a
LIBZ                     = /usr/lib/libz.a

####################################################################
# T1 adobe type1 font support thru t1lib
####################################################################
HAVE_T1LIB_SUPPORT       = N
INCT1LIB                 = /usr/include
LIBT1LIB                 = /usr/lib/libt1.a

####################################################################
# TrueType font support thru FreeType
####################################################################
HAVE_FREETYPE_SUPPORT    = N
INCFTLIB                 = /usr/include
LIBFTLIB                 = /usr/lib/libttf.so
FREETYPE_FONT_DIR        = "/usr/local/microwin/fonts"

####################################################################
# PCF font support
# Selecting HAVE_PCFGZ_SUPPORT will allow you to directly read
# .pcf.gz files, but it will add libz to the size of the server
####################################################################
HAVE_PCF_SUPPORT         = N
HAVE_PCFGZ_SUPPORT       = N

####################################################################
# Shared memory support for Nano-X client/server protocol speedup
####################################################################
HAVE_SHAREDMEM_SUPPORT   = N

####################################################################
# Chinese Han Zi Ku font support
####################################################################
HAVE_HZK_SUPPORT         = N
HZK_FONT_DIR             = "fonts/chinese"

####################################################################
# Chinese BIG5 compiled in font support (big5font.c)
####################################################################
HAVE_BIG5_SUPPORT        = N

####################################################################
# Chinese GB2312 compiled in font support (gb2312font.c)
####################################################################
HAVE_GB2312_SUPPORT      = N

####################################################################
# Korean HANGUL font support (jo16x16.c)
####################################################################
HAVE_KSC5601_SUPPORT     = N

####################################################################
# Generate screen driver interface only with no fonts or clipping
####################################################################
NOFONTSORCLIPPING        = N

####################################################################
#
# Window move algorithms for Microwindows
# Change for tradeoff between cpu speed and looks
# ERASEMOVE repaints only backgrounds while window dragging, quicker.
# Otherwise an XOR redraw is used for window moves only after button up,
# quickest (should set for ELKS)
# UPDATEREGIONS paints in update clipping region only for better look and feel
#
####################################################################
ERASEMOVE                = Y
UPDATEREGIONS            = Y

####################################################################
#
# Use MS fonts (default no)
#
####################################################################
HAVEMSFONTS              = N

####################################################################
#
# Link with Gray Palette (valid only for 4bpp modes)
#
####################################################################
GRAYPALETTE              = N

####################################################################
#
# If the platform is running UNIX, Linux or RTEMS...
#
####################################################################
ifneq ($(ARCH), ELKS)

# X Window screen, mouse and kbd drivers
X11                      = N

ifeq ($(X11), Y)
# predefined model or select screen width, height, depth(palette mode only)
SCREEN_E15               = N
SCREEN_WIDTH             = 640
SCREEN_HEIGHT            = 480
SCREEN_DEPTH             = 4

# You may want to turn this on for XFree86 4.x or if your backing store
# isn't functioning properly
USE_EXPOSURE		 = Y

else

# framebuffer screen driver (linear and/or vga 4 planes)
# set VTSWITCH to include virtual terminal switch code
# set FBREVERSE to reverse bit orders in 1,2,4 bpp
# set FBVGA=N for all systems without VGA hardware (for MIPS must=N)
FRAMEBUFFER              = N
FBVGA                    = N
VTSWITCH                 = N
FBREVERSE                = N

# EM8400 screen driver
EM8400			 = Y
EM8400_DIR		 = /usr/realmagic

# svgalib screen driver
VGALIB                   = N

# direct VGA hardware access screen driver
HWVGA                    = N

####################################################################
# Mouse or touch screen driver
# TPMOUSE for Linux-VR and Embedded Planet
# TPHELIO for VTech Helio
# ADSMOUSE for ADS Graphics Client
# IPAQMOUSE for Compaq iPAQ,Intel Assabet, ARM ucb1200 (/dev/h3600_ts 11,0)
# HARRIERMOUSE for NEC Harrier
# PSIONMOUSE for the Psion 5
# MTMOUSE for Microtouch touchpanel controller at RS232 port
####################################################################
GPMMOUSE                 = Y
SUNMOUSE                 = N
SERMOUSE                 = N
TPMOUSE                  = N
TPHELIO                  = N
ADSMOUSE                 = N
IPAQMOUSE                = N
HARRIERMOUSE             = N
PSIONMOUSE               = N
MTMOUSE                  = N
NOMOUSE                  = N

# keyboard or null kbd driver
TTYKBD                   = N
SCANKBD                  = Y
PIPEKBD                  = N
NOKBD                    = N

endif

####################################################################
# Screen driver specific configuration
# SA1100_LCD_LTLEND 4bpp driver with arm SA1100 LCD controller
# INVERT4BPP 4bpp inverted pixel driver for VTech Helio
####################################################################
SA1100_LCD_LTLEND        = N
INVERT4BPP               = N

####################################################################
#
# If the platform is a RTEMS box ....
#
####################################################################
ifeq ($(ARCH), RTEMS)

# Location & BSP information of the RTEMS build
RTEMS_BUILD              = /tools/build-i386-elf-rtems
RTEMS_BSP                = pc386
LINK_APP_INTO_SERVER     = Y

endif

endif

####################################################################
#
# If the platform is an ELKS box ...
#
####################################################################
ifeq ($(ARCH), ELKS)

# Higher speed asm driver, c driver of hercules screen driver
ASMVGADRIVER             = Y
CVGADRIVER               = N
HERCDRIVER               = N
DBGDRIVER                = N

# Mouse support
SERMOUSE                 = Y

endif