Erick / Mbed 2 deprecated ICE-F412

Dependencies:   mbed-rtos mbed

Files at this revision

API Documentation at this revision

Comitter:
davidjhoward
Date:
Tue Jan 24 21:12:26 2017 +0000
Parent:
1:b2e90cda7a5a
Commit message:
Delete ICE-Application

Changed in this revision

ICE-Application/inc/global.h Show diff for this revision Revisions of this file
ICE-Application/inc/version.h Show diff for this revision Revisions of this file
ICE-Application/main.cpp Show diff for this revision Revisions of this file
ICE-Application/src/AnalyticsLogger/AnalyticsLogger.cpp Show diff for this revision Revisions of this file
ICE-Application/src/AnalyticsLogger/AnalyticsLogger.h Show diff for this revision Revisions of this file
ICE-Application/src/BLEDataHandler/BLEDataHandler.cpp Show diff for this revision Revisions of this file
ICE-Application/src/BLEDataHandler/BLEDataHandler.h Show diff for this revision Revisions of this file
ICE-Application/src/CloudDataHandler/CloudDataHandler.cpp Show diff for this revision Revisions of this file
ICE-Application/src/CloudDataHandler/CloudDataHandler.h Show diff for this revision Revisions of this file
ICE-Application/src/CloudDataHandler/CloudFileReceiver.cpp Show diff for this revision Revisions of this file
ICE-Application/src/CloudDataHandler/CloudFileReceiver.h Show diff for this revision Revisions of this file
ICE-Application/src/CommandParser/cmd.cpp Show diff for this revision Revisions of this file
ICE-Application/src/CommandParser/cmd.h Show diff for this revision Revisions of this file
ICE-Application/src/CommandParser/cmd_utils.cpp Show diff for this revision Revisions of this file
ICE-Application/src/CommandParser/cmd_utils.h Show diff for this revision Revisions of this file
ICE-Application/src/CommandParser/sequence.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Algorithms/CompositeAlgorithm.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Algorithms/CompositeAlgorithm.h Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/ConfigurationHandler.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/ConfigurationHandler.h Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/CompositeControl.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/CompositeControl.h Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/FailsafeControl.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/FailsafeControl.h Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/ManualControl.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/ManualControl.h Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/PIDControl.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/PIDControl.h Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/SensorErrorControl.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/SensorErrorControl.h Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/SequenceControl.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/SequenceControl.h Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/SetpointControl.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/SetpointControl.h Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/TimerControl.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ConfigurationHandler/Controls/TimerControl.h Show diff for this revision Revisions of this file
ICE-Application/src/ControlTask/ControlTask.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ControlTask/ControlTask.h Show diff for this revision Revisions of this file
ICE-Application/src/DataHandler/DataHandler.cpp Show diff for this revision Revisions of this file
ICE-Application/src/DataHandler/DataHandler.h Show diff for this revision Revisions of this file
ICE-Application/src/DataHandler/LogHandler.cpp Show diff for this revision Revisions of this file
ICE-Application/src/DataHandler/LogHandler.h Show diff for this revision Revisions of this file
ICE-Application/src/DataHandler/LoggerApi.cpp Show diff for this revision Revisions of this file
ICE-Application/src/DataHandler/LoggerApi.h Show diff for this revision Revisions of this file
ICE-Application/src/Drivers/LogLocalApi.cpp Show diff for this revision Revisions of this file
ICE-Application/src/Drivers/LogLocalApi.h Show diff for this revision Revisions of this file
ICE-Application/src/Drivers/i2c_eeprom.cpp Show diff for this revision Revisions of this file
ICE-Application/src/Drivers/i2c_eeprom.h Show diff for this revision Revisions of this file
ICE-Application/src/Drivers/mod.cpp Show diff for this revision Revisions of this file
ICE-Application/src/Drivers/mod.h Show diff for this revision Revisions of this file
ICE-Application/src/Drivers/rtc.cpp Show diff for this revision Revisions of this file
ICE-Application/src/Drivers/rtc.h Show diff for this revision Revisions of this file
ICE-Application/src/ModbusMaster/ModbusMaster.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ModbusMaster/ModbusMaster.h Show diff for this revision Revisions of this file
ICE-Application/src/ModbusMaster/ModbusMasterApi.cpp Show diff for this revision Revisions of this file
ICE-Application/src/ModbusMaster/ModbusMasterApi.h Show diff for this revision Revisions of this file
ICE-Application/src/OutputTask/ControlClass/Control.cpp Show diff for this revision Revisions of this file
ICE-Application/src/OutputTask/ControlClass/Control.h Show diff for this revision Revisions of this file
ICE-Application/src/OutputTask/OutputTask.cpp Show diff for this revision Revisions of this file
ICE-Application/src/OutputTask/OutputTask.h Show diff for this revision Revisions of this file
ICE-Application/src/Utilities/timerUtils.cpp Show diff for this revision Revisions of this file
ICE-Application/src/Utilities/timerUtils.h Show diff for this revision Revisions of this file
ICE-Application/src/Utilities/utilities.cpp Show diff for this revision Revisions of this file
ICE-Application/src/Utilities/utilities.h Show diff for this revision Revisions of this file
ICE-Application/src/Utilities/v7_c_calls.cpp Show diff for this revision Revisions of this file
ICE-Application/src/Utilities/v7_c_calls.h Show diff for this revision Revisions of this file
ICE-Application/src/Utilities/v7_execute.cpp Show diff for this revision Revisions of this file
ICE-Application/src/Utilities/v7_execute.h Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/BLE/inc/ble_init.h Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/BLE/inc/ble_main.h Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/BLE/inc/ble_msg_handler.h Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/BLE/inc/ble_spi.h Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/BLE/src/ble_init.cpp Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/BLE/src/ble_main.cpp Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/BLE/src/ble_msg_handler.cpp Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/BLE/src/ble_spi.cpp Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/ConfigFS/ConfigFs.cpp Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/ConfigFS/ConfigFs.h Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/ConfigFS/mfs.cpp Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/ConfigFS/mfs.h Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/ICELog/ICELog.cpp Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/ICELog/ICELog.h Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/NaturalTinyShell.lib Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/cJSON/cJSON.c Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/cJSON/cJSON.h Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/crc32/crc.cpp Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/crc32/crc.h Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/v7/v7.c Show diff for this revision Revisions of this file
ICE-Application/src/add-ons/v7/v7.h Show diff for this revision Revisions of this file
--- a/ICE-Application/inc/global.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,258 +0,0 @@
-#ifndef GLOBAL_H
-#define GLOBAL_H
-
-#include <map>
-
-#define LOAD_PERSISTENT_CONFIGURATIONS
-#include "mbed.h"
-#include "ntshell.h"
-#include "rtos.h"
-#include "ConfigFs.h"
-
-extern int sig_output_continue;
-extern int sig_config_continue;
-extern int sig_control_continue;
-
-extern osThreadId mainThreadId;
-
-extern Thread *GLOBAL_analyticsLogger_thread;
-extern Thread *GLOBAL_modbusMaster_thread;
-extern Thread *GLOBAL_BLE_thread;
-extern Thread *GLOBAL_CDH_thread;
-extern Thread *GLOBAL_configHandler_thread;
-extern Thread *GLOBAL_controlTask_thread;
-extern Thread *GLOBAL_outputTask_thread;
-extern Thread *GLOBAL_dataHandler_thread;
-
-extern ConfigFs *GLOBAL_mdot;
-extern I2C i2c_instance;
-extern I2C* i2c;
-
-#define EXECUTE_SCRIPT
-
-// declare stack sizes
-#ifdef EXECUTE_SCRIPT
-#define MODBUS_MASTER_STACK_SIZE        (1024 * 8)
-#else
-#define MODBUS_MASTER_STACK_SIZE        (1024 * 4)
-#endif
-#define OUTPUT_TASK_STACK_SIZE          ((1024 * 2) + 512)
-#define CONFIG_HANDLER_STACK_SIZE       (1024 * 3)
-#define CONTROL_TASK_STACK_SIZE         (1024 * 2)
-#ifdef MDOT_ICE
-#define BLE_DATA_HANDLER_STACK_SIZE     (1024 * 3)
-#define CLOUD_DATA_HANDLER_STACK_SIZE   (1024 * 4)  
-#else
-#define DATA_HANDLER_STACK_SIZE         (1024 * 4)
-#endif
-#define ANALYTICS_LOGGER_STACK_SIZE     (1024 * 2)
-
-/* tiny shell specifics */
-extern ntshell_t ntshell;
-
-extern int  func_read(char *buf, int cnt);
-extern int  func_write(const char *buf, int cnt);
-extern int  func_cb_ntshell(const char *text);
-extern void func_cb_ntopt(int argc, char **argv);
-
-#define MAX_FILE_SIZE       350  
-
-/**************************************************************************** 
- * Mailbox messaging data structures
- ****************************************************************************/
-
-#define CONTROL_FILE_SIZE               (64) 
-#define MODBUS_MSG_SIZE                 (256)
-
-// Messages sent to the configuration handler -------------------------------
-
-typedef enum action_tag {
-    ACTION_CREATE,
-    ACTION_MODIFY,
-    ACTION_DESTROY,
-    ACTION_READ_FILE,
-    ACTION_EXEC_CMD
-} Action_t;
-
-typedef enum control_tag {
-    CONTROL_TIMER           = 0,
-    CONTROL_PID             = 1,
-    CONTROL_SETPOINT        = 2,
-    CONTROL_COMPOSITE       = 3,
-    CONTROL_MANUAL          = 4,
-    CONTROL_FAILSAFE        = 5,
-    CONTROL_SEQUENCE        = 6,
-    CONTROL_SENSOR_ERROR    = 7,
-    CONTROL_ALGORITHM       = 8
-} Control_t;
-
-typedef struct message_tag {
-    Action_t        action;
-    Control_t       control;
-    char            controlFile[CONTROL_FILE_SIZE];
-} ConfigMessage_t;
-
-// Messages sent to the Modbus Master ---------------------------------------
-
-typedef enum thread_name_tag {
-    ANALYTICS_LOGGER        = 0,
-    BLE_HANDLER             = 1,
-    CLOUD_DATA_HANDLER      = 2,
-    CONFIG_HANDLER          = 3,
-    CONTROL_TASK            = 4,
-    OUTPUT_TASK             = 5,
-} ThreadName_t;
-
-typedef struct modbus_master_tag {
-    Action_t        action;
-    Control_t       control;
-    ThreadName_t    replyThread;
-    char            msg[MODBUS_MSG_SIZE];
-} ModbusMasterReq_t;
-
-// Messages sent to the Output Task ------------------------------------------
-
-typedef enum output_action {
-    ACTION_NEW,
-    ACTION_CONTROL_ON,
-    ACTION_CONTROL_OFF,
-    ACTION_CONTROL_REGISTER,
-    ACTION_CONTROL_UNREGISTER
-} OutputAction;
-
-typedef struct output_control_req_t {
-    OutputAction    action;
-    Control_t       controlType;
-    char            controlFile[CONTROL_FILE_SIZE];
-    char            input_tag[32];
-    char            output_tag[32];
-    char            id[32];
-    unsigned int    priority;
-} OutputControlMsg_t;
-
-
-// Messages sent to the Analytics Logger ------------------------------------
-
-typedef struct analytics_logger_req_t {
-    char            timestamp[32];
-    char            log_entry[96];
-} AnalyticsLoggerReq_t;
-
-// BLE request message
-typedef struct ble_handler_req_t {
-    char            reply[500];
-} BLEHandlerReq_t;
-
-extern Mail<ConfigMessage_t, 16>            ConfigHandlerMailBox;
-extern Mail<ModbusMasterReq_t, 2>           ModbusMasterMailBox;
-extern Mail<OutputControlMsg_t, 16>         OutputMasterMailBox;
-extern Mail<BLEHandlerReq_t, 1>             BLEHandlerMailBox;
-
-/****************************************************************************
- * MODBUS
- * TODO! Move this to the proper location
- ****************************************************************************/
-
-#define NUM_SCRIPT_ARGS 4
-
-typedef enum register_type_tag {
-    REG_TYPE_NONE,
-    REG_TYPE_INPUT,
-    REG_TYPE_OUTPUT,
-    REG_TYPE_VINPUT,
-    REG_TYPE_VOUTPUT,
-} RegisterType_t;
-
-#define MODBUS_READ_COIL                1
-#define MODBUS_READ_DISCRETE_INPUT      2
-#define MODBUS_READ_HOLDING             3
-#define MODBUS_READ_INPUT               4
-#define MODBUS_WRITE_SINGLE_COIL        5
-#define MODBUS_WRITE_SINGLE_HOLDING     6
-#define MODBUS_WRITE_MULTIPLE_COIL      15
-#define MODBUS_WRITE_MULTIPLE_HOLDING   16
-
-#define ARGT_INT    0
-#define ARGT_FLOAT  1
-#define ARGT_DOUBLE 2
-#define ARGT_STRING 3
-
-struct ModbusRegister {
-    float min;
-    float max;
-    unsigned char node;
-    unsigned char rtype;
-    unsigned char type;
-    unsigned char size;
-    unsigned char order;
-    unsigned char rfreq;
-    unsigned char argc;
-    uint32_t reg;
-    RegisterType_t regType;
-    std::string cmd;
-    std::string argv[NUM_SCRIPT_ARGS];
-    bool simulated;
-};
-
-struct ExecuteJavaScript {
-    std::string script;
-    std::string argv[NUM_SCRIPT_ARGS];
-};
-
-struct RegisterValue {
-    double float_value;
-    uint32_t errflag;
-};
-
-struct VirtualCommand {
-    float Constant;
-    std::string Operand;
-    std::string Operator;
-};
-
-struct HoldingRegister {
-    unsigned char node;
-    unsigned char sreg;
-    unsigned char nreg;
-    unsigned char order;
-};
-
-struct SimulateInput {
-    float start_value;
-    float min;
-    float max;
-    float up_step;
-    float down_step;
-    bool moving_up;
-    uint32_t errflag;
-};
-
-typedef enum byte_order {
-    BigEndian                   = 0,
-    LittleEndian                = 1,
-    BigEndianReverseWord        = 2,
-    LittleEndianReversWord      = 3,
-} Byte_Order;
-
-typedef enum event_reason_tag {
-    EVENT_REASON_AUTO,
-    EVENT_REASON_MANUAL,
-    EVENT_REASON_TIMER,
-    EVENT_REASON_FLOW,
-    EVENT_REASON_FAILSAFE,
-    EVENT_REASON_NO_CONTROL
-} EventReason_t;
-
-typedef struct event_reason_struct_t {
-    EventReason_t   eventReason;
-    char            inputTag[32];
-    char            outputTag[32];
-    float           inputValue;
-    float           outputValue;
-} EventReasonStruct_t;
-
-extern std::map<std::string, ModbusRegister>    ModbusRegisterMap;
-extern std::map<std::string, RegisterValue>     RegisterValueMap;
-extern std::map<std::string, SimulateInput>     SimulateInputMap;
-
-#endif 
--- a/ICE-Application/inc/version.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/******************************************************************************
- * version.h
- *****************************************************************************/
-#ifndef VERSION_H
-#define VERSION_H
-
-#define MAJOR_VERSION_NUMBER        0
-#define MINOR_VERSION_NUMBER        1
-#define PATCH_VERSION_NUMBER        0
-
-#define PROJECT_CODE_NAME           "foobar"
-
-#endif
--- a/ICE-Application/main.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/******************************************************************************
- *
- * File:                main.cpp
- * Desciption:          Ground Zero
- *
- *****************************************************************************/
-#include <time.h>
-#include <iostream>
-
-#include "global.h"
-#include "mbed.h"
-#include "rtos.h"
-#include "ntshell.h"
-#include "version.h"
-#include "AnalyticsLogger.h"
-#include "ConfigurationHandler.h"
-#include "ControlTask.h"
-#include "DataHandler.h"
-#include "ModbusMaster.h"
-#include "OutputTask.h"
-#include "ConfigFs.h"
-#include "rtc.h"
-#include "mfs.h"
-
-// threading data
-osThreadId mainThreadId = NULL;
-
-Thread *GLOBAL_analyticsLogger_thread = NULL;
-Thread *GLOBAL_modbusMaster_thread = NULL;
-Thread *GLOBAL_BLE_thread = NULL;
-Thread *GLOBAL_CDH_thread = NULL;
-Thread *GLOBAL_configHandler_thread = NULL;
-Thread *GLOBAL_controlTask_thread = NULL;
-Thread *GLOBAL_outputTask_thread = NULL;
-Thread *GLOBAL_dataHandler_thread = NULL;
-
-// mailboxes
-Mail<ConfigMessage_t, 16>       ConfigHandlerMailBox;   
-Mail<ModbusMasterReq_t, 2>      ModbusMasterMailBox;
-Mail<OutputControlMsg_t, 16>    OutputMasterMailBox;
-Mail<AnalyticsLoggerReq_t, 16>  AnalyticsLoggerMailBox;
-Mail<BLEHandlerReq_t, 1>        BLEHandlerMailBox;
-
-// bootup sequence signals
-int sig_output_continue     = 0x1;      // allow the output handler to start 
-int sig_config_continue     = 0x2;      // allow the config handler to start
-int sig_control_continue    = 0x3;      // allow the control task to start
-
-// some digitals...for fun, whilst developing 
-DigitalOut led1(LED1);
-DigitalOut led2(LED2);
-DigitalOut led3(LED3);
-
-DigitalIn rClk(D7);
-
-// console communication settings 
-Serial console(USBTX, USBRX, 115200);
-
-I2C* i2c;
-
-ConfigFs EEP_FileSystem;
-ConfigFs *GLOBAL_mdot = &EEP_FileSystem;
-
-//MTSLog *GLOBAL_logger;
-
-#undef TODO_ICE // move this, doesn't belong here...
-// store modbus register information
-std::map<std::string,ModbusRegister>    ModbusRegisterMap;
-std::map<std::string,RegisterValue>     RegisterValueMap;
-std::map<std::string,SimulateInput>     SimulateInputMap;
-
-// local prototypes
-static void banner(void);
-
-/*****************************************************************************
- * Function:            timestamp_boot_record()
- * Description:         timestamp the boot record with current time
- *
- * @param               none
- * @return              none
- *****************************************************************************/
-static void timestamp_boot_record(void)
-{
-    char time_string[80];
-    time_t curr_sec;
-    struct tm *ts;
-
-    curr_sec = time(0);
-    ts = localtime(&curr_sec);
-    strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ts);
-
-    GLOBAL_mdot->saveUserFile("boot.time", time_string, sizeof(time_string));
-    return;
-}
-
-
-/**
- * @brief           the main software entry point
- *
- * @param           none
- * @return          0
- */
-
-
-
-int main(void)
-{    
-    // light 'em up! -- remove this once we go to a real board!
-    led1 = led2 = led3 = 1;
-
-    struct tm   rtc_time;
-    time_t      curr_sec;
-    int         year = 0;
-
-    mainThreadId = osThreadGetId();
-
-    i2c = &i2c_instance;
-    
-    // intialize the real-time clock
-    rtc_init();
-
-    rtc_get_time(&year, &rtc_time.tm_mon, &rtc_time.tm_mday, &rtc_time.tm_hour, &rtc_time.tm_min, &rtc_time.tm_sec);
-    rtc_time.tm_mon = rtc_time.tm_mon - 1;
-    rtc_time.tm_year = year - 1900;
-    curr_sec =  mktime( &rtc_time );
-
-    set_time(curr_sec);
-
-    timestamp_boot_record();
-    
-    mainThreadId = osThreadGetId();
-     
-    // display the startup banner 
-    banner();
-    
-    // the Modbus master task
-    Thread modbusMaster_thread(ModbusMaster, NULL, osPriorityHigh, MODBUS_MASTER_STACK_SIZE, NULL);
-    osSignalWait(sig_output_continue, osWaitForever);
-    
-    // the Output task
-    Thread outputTask_thread(OutputTask, NULL, osPriorityNormal, OUTPUT_TASK_STACK_SIZE, NULL);
-    osSignalWait(sig_config_continue, osWaitForever);
-   
-    // the Configuration Handler task
-    Thread configHandler_thread(ConfigurationHandler, NULL, osPriorityNormal, CONFIG_HANDLER_STACK_SIZE,  NULL);
-    osSignalWait(sig_control_continue, osWaitForever);
-
-    // the Control task
-    Thread controlTask_thread(ControlTask, NULL, osPriorityNormal, CONTROL_TASK_STACK_SIZE,  NULL);
-    
-    // the Data Handler
-    Thread dataHandler_thread(DataHandler, NULL, osPriorityNormal, DATA_HANDLER_STACK_SIZE, NULL);
-    
-    // the Analytics Logger task
-    Thread analyticsLoggerThread(AnalyticsLogger, NULL, osPriorityHigh, ANALYTICS_LOGGER_STACK_SIZE, NULL);
-    
-    GLOBAL_analyticsLogger_thread = &analyticsLoggerThread;
-    GLOBAL_modbusMaster_thread    = &modbusMaster_thread;
-    GLOBAL_configHandler_thread   = &configHandler_thread;
-    GLOBAL_controlTask_thread     = &controlTask_thread;
-    GLOBAL_outputTask_thread      = &outputTask_thread;
-    GLOBAL_dataHandler_thread     = &dataHandler_thread;
-
-    Thread::wait(2500);
-    
-    // start the command shell -- this will loop forever
-    console.printf("\r\nInvoking the command shell\n\r\n");
-    ntshell_execute(&ntshell, func_read, func_write, func_cb_ntshell);
-}
-
-/**
- * @brief           the bootup banner
- * 
- * @param           none
- * @return          none
- */
-static void banner(void)
-{
-    struct tm       *ts;
-    time_t          curr_sec;
-    char            time_string[80];
-
-    curr_sec = time(0);
-    ts       = localtime(&curr_sec);
-    
-    strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ts);
-
-    printf("\n\n\r\nProject: ICE v%d.%d.%d (%s)\n", 
-        MAJOR_VERSION_NUMBER, 
-        MINOR_VERSION_NUMBER, 
-        PATCH_VERSION_NUMBER, 
-        PROJECT_CODE_NAME);
-    
-    printf("\rThe Intelligent Connected Experience\n");
-    printf("\rCopyright 2017 Nalco Water, an Ecolab Company\n");
-    
-#ifdef __ICCARM__
-    printf("\rToolchain: IAR\n");
-#else 
-    printf("\rToolchain: MBED\n");
-#endif 
-
-    printf("\r _________ _______  _______ \n");
-    printf("\r \\__   __/(  ____ \\(  ____ \\ \n");
-    printf("\r    ) (   | (    \\/| (    \\/ \n");
-    printf("\r    | |   | |      | (__     \n");
-    printf("\r    | |   | |      |  __)   \n");
-    printf("\r    | |   | |      | (      \n");
-    printf("\r ___) (___| (____/\\| (____/\\ \n");
-    printf("\r \\_______/(_______/(_______/  \n");
-
-    printf("\r\nCurrent time is: %s\r\n", time_string);
-}
--- a/ICE-Application/src/AnalyticsLogger/AnalyticsLogger.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/******************************************************************************
- *
- * File:                AnalyticsLogger.cpp
- * Desciption:          source for the ICE Analytics Logger
- *
- *****************************************************************************/
-#include "global.h"
-#include <stdio.h>
-#include <string>
-#include <sstream>
-#include <iostream>
-#include <vector>
-#include <time.h>
-#include "AnalyticsLogger.h"
-#include "LoggerApi.h"
-//#include "rtc.h"
-
-static void checkStackUsage(void);
-
-/*****************************************************************************
- * Function:             AnalyticsLogger
- * Description:          entry point for the Analytics Logger
- *
- * @param                (IN) args (user-defined arguments)
- * @return               none
- *****************************************************************************/
-void AnalyticsLogger(void const *args)
-{
-    struct tm       *ts;
-    time_t curr_sec;
-    int last_min=8;
-    bool log_sent=false;
-    
-    printf("\rAnalyticsLogger has started...\n");
-
-    while ( true ) {
-
-        std::ostringstream log_event;
-
-        curr_sec = time(0);
-        ts = localtime(&curr_sec);
-//        printf("curr_sec=%ld, min=%d (last=%d)\r\n", curr_sec, ts->tm_min, last_min );
-        if( ((ts->tm_min%5) == 0) && (ts->tm_min != last_min) ) {
-            last_min = ts->tm_min;
-
-            int map_count = ModbusRegisterMap.size();
-            int collected_count = 0;
-
-            log_event << "\"lr\":[";
-            std::map<std::string, ModbusRegister>::iterator iter;
-            for (iter = ModbusRegisterMap.begin(); iter != ModbusRegisterMap.end(); ++iter) {
-
-                collected_count = collected_count + 1;
-
-                log_event << "{\"t\":"<< "\"" << iter->first.c_str() << "\"," << "\"v\":"<< "\"" << RegisterValueMap[iter->first].float_value<< "\"},";
-                log_sent = false;
-                if( log_event.str().size() >= 150 ) {
-                    std::string str = log_event.str();
-                    str.erase( str.size() - 1 );
-                    if( collected_count == map_count ) {
-                        str.append("],\"seq\":\"0\"");
-                    } else {
-                        str.append("],\"seq\":\"1\"");
-                    }
-//                    printf("%s:%d: Logging %s : len=%d\r\n", __func__, __LINE__, str.c_str(), str.length() );
-                    LiveDataLoggerApi( str.c_str() );
-                    log_event.str("");
-                    log_event.clear();
-                    log_event << "\"lr\":[";
-                    log_sent = true;
-                }
-            }
-            if( log_sent == false ) {
-                std::string str = log_event.str();
-                str.erase( str.size() - 1 );
-                str.append("],\"seq\":\"0\"");
-                if( str.length() > 20 ) {
-//                    printf("%s:%d: Logging %s : len=%d\r\n", __func__, __LINE__, str.c_str(), str.length() );
-                    LiveDataLoggerApi( str.c_str() );
-                }
-            }
-        }
-
-        Thread::wait(5000);
-        checkStackUsage();
-    }
-}
-
-//
-// For optimizing/debugging purposes only!
-//
-static void checkStackUsage(void)
-{
-    const float threshold = .85;
-
-    std::vector<std::pair<std::string, Thread*> > taskList;
-    taskList.push_back(make_pair((std::string)"AnalyticsLogger",  GLOBAL_analyticsLogger_thread));
-    taskList.push_back(make_pair((std::string)"DataHandler",      GLOBAL_dataHandler_thread));
-    taskList.push_back(make_pair((std::string)"ConfigHandler",    GLOBAL_configHandler_thread));
-    taskList.push_back(make_pair((std::string)"ControlTask",      GLOBAL_controlTask_thread));
-    taskList.push_back(make_pair((std::string)"ModbusMaster",     GLOBAL_modbusMaster_thread));
-    taskList.push_back(make_pair((std::string)"OutputTask",       GLOBAL_outputTask_thread));
-    for ( std::vector<std::pair<std::string, Thread*> >::iterator pos = taskList.begin(); pos != taskList.end(); ++ pos) {
-        // do something
-        if ( (float) pos->second->max_stack() / (float) pos->second->stack_size() >= threshold ) {
-            printf("\rWARNING: %s has used %.2f%% of its stack!\n", pos->first.c_str(),
-                   (double)((float)pos->second->max_stack() / (float)pos->second->stack_size()) * 100.0);
-        }
-    }
-}
\ No newline at end of file
--- a/ICE-Application/src/AnalyticsLogger/AnalyticsLogger.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-/******************************************************************************
- * 
- * File:                AnalyticsLogger.h
- * Desciption:          interface for the ICE Analytics Logger
- *
- *****************************************************************************/
-#ifndef ANALYTICS_LOGGER_H
-#define ANALYTICS_LOGGER_H
-
-#ifdef __cplusplus
-#define EXTERNC extern "C"
-#else
-#define EXTERNC
-#endif
-
-EXTERNC void AnalyticsLogger   ( void const *args );
-EXTERNC bool AnalyticsLoggerApi( std::string *log_string );
-
-#undef EXTERNC
-
-#endif
\ No newline at end of file
--- a/ICE-Application/src/BLEDataHandler/BLEDataHandler.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,303 +0,0 @@
-/******************************************************************************
- *
- * File:                BLEDataHandler.cpp
- * Desciption:          source for the ICE Bluetooth Low Energy Data Handler
- *
- *****************************************************************************/
-#include "global.h"
-#include <stdio.h>
-#include <sstream>
-#include <iostream>
-#include "BLEDataHandler.h"
-#include "CloudDataHandler.h"
-#include "LogLocalApi.h"
-#include "LoggerApi.h"
-#include "ble_main.h"
-#include "ble_init.h"
-#include "ble_msg_handler.h"
-#include "ble_spi.h"
-#include "cJSON.h"
-
-/*****************************************************************************
- * Function:             BLEDataHandler
- * Description:          entry point for the Analytics Logger
- *
- * @param                (IN) args (user-defined arguments)
- * @return               none
- *****************************************************************************/
-
-BLE_FILE BLE;
-BLE_INIT ble_init;
-
-#define BLE_GAP_DEVNAME_MAX_LEN 31 //max length is 31including null
-#define BLE_RECEIVE_BUFFER_SIZE 500
-#define BLE_TRANSMIT_BUFFER_SIZE 500
-//const static char BLE_DEVICE_NAME[BLE_GAP_DEVNAME_MAX_LEN] = {"ICE-Ecolab"};
-
-bool BLE_StringReceived = false;
-char BLE_ReceiveString[BLE_RECEIVE_BUFFER_SIZE];
-
-void BLE_ReplyToHandler( std::string &id, int status, float value )
-{
-    std::ostringstream mb_reply;
-
-    BLEHandlerReq_t *mail = BLEHandlerMailBox.alloc();
-    mb_reply << "{  \"mtype\":" << BT_MODBUS_COMMAND_REPLY_MTYPE << ", \"mbreply\":{ \"id\":\"" << id.c_str() << "\"," "\"status\":\"" << status << "\"," "\"value\":\"" << value << "\"} }";
-    std::string string_reply = mb_reply.str();
-    strncpy( mail->reply, string_reply.c_str(), (sizeof(mail->reply)-1));
-    printf("%s:%d: Reply is: %s\r\n",__func__,__LINE__, mail->reply);
-    BLEHandlerMailBox.put(mail);
-}
-
-/*****************************************************************************
-* Function:            BLE data receive callback
-* Description:         Process BLE data
-*
-* @param               spi_rcv_array
-* @param               *rx_data
-* @param               length
-* @return              none
-*****************************************************************************/
-//char * fake_string = "{  \"mtype\":1200, \"getreadings\":[ { \"tag\":\"i_tra01\" } ] }"; // use this to fake a message out requesting i_tra01 readings
-//char * fake_string = "{  \"mtype\":1200, \"getreadings\":[ { \"tag\":\"i_tra01\" }, { \"tag\":\"i_bdcond01\" }, { \"tag\":\"i_cond_temp01\" } ] }"; // use this to fake a message out requesting i_tra01 readings
-//char * fake_string = "{  \"mtype\":1000, \"mbcommand\":{ \"id\":\"READ_TRASAR\"," "\"node\":\"1\"," "\"func\":\"4\"," "\"sreg\":\"9\"," "\"nreg\":\"2\"," "\"dtype\":\"0\"," "\"order\":\"2\"," "\"value\":\"0\" } }"; // use this to fake a message out requesting i_tra01 readings
-//char * fake_string = "{  \"mtype\":1000, \"mbcommand\":{ \"id\":\"WRITE_MULTIPLE\"," "\"node\":\"21\"," "\"func\":\"16\"," "\"sreg\":\"0\"," "\"nreg\":\"3\"," "\"dtype\":\"5\"," "\"order\":\"2\"," "\"value\":\"0\", \"data\":[ { \"v\":\"20\" }, { \"v\":\"16\" }, { \"v\":\"0\" } ] } }"; // use this to fake a message out requesting i_tra01 readings
-//char * fake_string = "{  \"mtype\":103, \"mncontrol\": { \"id\":\"o_rly01\", \"output\":\"o_rly01\", \"type\":\"1\", \"priority\":\"100\", \"duration\":\"0\", \"setpoint\":\"0\", \"state\":\"1\", \"percent\":\"100\" } }";
-//char * fake_string = "{  \"mtype\":100,  \"spcontrol\": { \"id\": \"INH_TRA_01\", \"priority\": \"800\", \"input\": \"i_tra01\", \"output\": \"o_rly02\", \"setpoint\": \"130\", \"prodfact\": \"100\", \"actingDir\": \"0\", \"halert\": \"190\", \"lalert\": \"92\", \"hfs\": \"200\", \"lfs\": \"70\", \"tol\": \"4\" } }";
-static void BleRxDataCallback(uint8_t *rx_data, uint8_t len)
-{
-    memset( BLE_ReceiveString, 0, BLE_RECEIVE_BUFFER_SIZE );
-    if( len >= BLE_RECEIVE_BUFFER_SIZE ) {
-        printf("Received file larger than buffer (len=%d)\r\n", len );
-        return;
-    }
-#if 0
-    std::string fake_string;
-    switch( rx_data[0] ) {
-        case 'a':
-            fake_string.assign("{ \"mtype\":200,  \"input\": { \"id\": \"i_tra01\", \"name\": \"Trasar\", \"units\": \"PPM\", \"min\": \"0\", \"max\": \"300\", \"node\": \"1\", \"reg\": \"9\", \"rtype\": \"4\", \"type\": \"0\", \"size\": \"2\", \"order\": \"2\", \"fmt\": \"%.2f\", \"rfreq\": \"5\", \"cmd\":\"\" } }");
-            break;
-        case 'b':
-            fake_string.assign("{ \"mtype\":201,  \"output\": { \"id\": \"o_rly02\", \"name\": \"3DTS86\", \"units\": \"\", \"min\": \"0\", \"max\": \"300\", \"node\": \"0\", \"reg\": \"2\", \"rtype\": \"1\", \"type\": \"0\", \"size\": \"2\", \"order\": \"2\", \"fmt\": \"%.2f\", \"rfreq\": \"5\", \"toperiod\":\"0\", \"scalelo\":\"0\", \"scalehi\":\"100\", \"cmd\":\"\" } }");
-            break;
-        case 'c':
-            fake_string.assign("{ \"mtype\":100,  \"spcontrol\": { \"id\": \"INH_TRA_01\", \"priority\": \"800\", \"input\": \"i_tra01\", \"output\": \"o_rly02\", \"setpoint\": \"130\", \"prodfact\": \"100\", \"actingDir\": \"0\", \"halert\": \"190\", \"lalert\": \"92\", \"hfs\": \"200\", \"lfs\": \"70\", \"tol\": \"4\" } }");
-            break;
-        case 'd':
-            fake_string.assign("{ \"mtype\":200,  \"input\": { \"id\": \"i_bdcond01\", \"name\": \"Tower Conductivity\", \"units\": \"uS\", \"min\": \"0\", \"max\": \"600\", \"node\": \"21\", \"reg\": \"18\", \"rtype\": \"4\", \"type\": \"1\", \"size\": \"2\", \"order\": \"2\", \"fmt\": \"%.2f\", \"rfreq\": \"5\", \"cmd\":\"\" } }");
-            break;
-        case 'e':
-            fake_string.assign("{ \"mtype\":201,  \"output\": { \"id\": \"o_rly01\", \"name\": \"Blowdown\", \"units\": \"\", \"min\": \"0\", \"max\": \"300\", \"node\": \"0\", \"reg\": \"1\", \"rtype\": \"1\", \"type\": \"0\", \"size\": \"2\", \"order\": \"2\", \"fmt\": \"%.2f\", \"rfreq\": \"5\", \"toperiod\":\"0\", \"scalelo\":\"0\", \"scalehi\":\"100\", \"cmd\":\"\" } }");
-            break;
-        case 'f':
-            fake_string.assign("{ \"mtype\":100,  \"spcontrol\": { \"id\": \"BLOWDOWN_01\", \"priority\": \"800\", \"input\": \"i_bdcond01\", \"output\": \"o_rly01\", \"setpoint\": \"1800\", \"prodfact\": \"\", \"actingDir\": \"1\", \"halert\": \"2400\", \"lalert\": \"800\", \"hfs\": \"2700\", \"lfs\": \"700\", \"tol\": \"30\" } }");
-            break;
-        case 'g':
-            // relay-1: manual control off
-            fake_string.assign("{ \"mtype\":103, \"mncontrol\": { \"id\":\"o_rly01\", \"output\":\"o_rly01\", \"type\":\"1\", \"priority\":\"100\", \"duration\":\"0\", \"setpoint\":\"0\", \"state\":\"0\", \"percent\":\"100\" } }");
-            break;
-        case 'h':
-            // relay-1: manual control on
-            fake_string.assign("{ \"mtype\":103, \"mncontrol\": { \"id\":\"o_rly01\", \"output\":\"o_rly01\", \"type\":\"1\", \"priority\":\"100\", \"duration\":\"0\", \"setpoint\":\"0\", \"state\":\"1\", \"percent\":\"100\" } }");
-            break;
-        case 'i':
-            // relay-1: manual control destroy
-            fake_string.assign("{ \"mtype\":303, \"mncontrol\": { \"id\":\"o_rly01\" } }");
-            break;
-        case 'j':
-            // relay-2: manual control off
-            fake_string.assign("{ \"mtype\":103, \"mncontrol\": { \"id\":\"o_rly02\", \"output\":\"o_rly02\", \"type\":\"1\", \"priority\":\"100\", \"duration\":\"0\", \"setpoint\":\"0\", \"state\":\"0\", \"percent\":\"100\" } }");
-            break;
-        case 'k':
-            // relay-2: manual control on
-            fake_string.assign("{ \"mtype\":103, \"mncontrol\": { \"id\":\"o_rly02\", \"output\":\"o_rly02\", \"type\":\"1\", \"priority\":\"100\", \"duration\":\"0\", \"setpoint\":\"0\", \"state\":\"1\", \"percent\":\"100\" } }");
-            break;
-        case 'l':
-            // relay-2: manual control destroy
-            fake_string.assign("{ \"mtype\":303, \"mncontrol\": { \"id\":\"o_rly02\" } }");
-            break;
-    }
-#endif
-    memcpy( BLE_ReceiveString, rx_data, len ); // comment out and use line below until we receive JSON from APP
-    // temporary until we receive actual string from APP
-//    memcpy( BLE_ReceiveString, fake_string.c_str(), fake_string.size() );
-    BLE_StringReceived = true;
-//    printf("Data Received:  %s\r\n", BLE_ReceiveString);
-}
-
-void BLEDataHandler(void const *args)
-{
-//    uint8_t tx_array[BLE_TRANSMIT_BUFFER_SIZE];
-//    uint8_t event_status;
-
-    printf("\rBLEDataHandler has started...\n");
-
-    std::string id = "Ecolab";
-    
-    std::vector<std::string>::iterator file;
-    std::vector<std::string> file_list;
-    file_list = GLOBAL_mdot->listUserFiles();
-    for(file = file_list.begin(); file != file_list.end(); ++file) {
-        if( (strncmp( file->c_str(), "ble_device_name", (strlen("ble_device_name")-1)) == 0) ) {
-            bool status = GLOBAL_mdot->readUserFile(file->c_str(), BLE_ReceiveString, MAX_FILE_SIZE);
-            if( status != true ) {
-                printf("%s:%d: read file failed, file=%s, status=%d\r\n", __func__, __LINE__, file->c_str(), status);
-                continue;
-            }
-
-            cJSON * root = cJSON_Parse(BLE_ReceiveString);
-            id.erase (id.begin(), id.end()); 
-            id.append(cJSON_GetObjectItem(root,"id")->valuestring);
-            printf("Loaded BLE_DEVICE_NAME=%s\r\n", id.c_str());
-            cJSON_Delete(root);
-            break;
-        }
-    }
-
-
-    /*TODO
-        Getting the init status from Nano BLE register and
-        Proceed based on the status.
-    */
-    printf("\r\nSetting BLE_DEVICE_NAME=%s\r\n\r\n", id.c_str() );
-//    event_status = BLE.ConfigureBLEDevice(id.c_str());
-//    BleDataRxCbRegister(BleRxDataCallback);
-    while(1) {
-#if 0
-        event_status = PollBLEEvents();
-        if(event_status == true && BLE_StringReceived == true) {
-
-            cJSON * root = cJSON_Parse( BLE_ReceiveString );
-            int mType = cJSON_GetObjectItem(root,"mtype")->valueint;
-
-            printf("mType=%d, str=%s\r\n",mType, BLE_ReceiveString);
-            switch( mType ) {
-                case BT_GETLIVE_COMMAND_MTYPE: {
-                    std::vector<std::string>  RequestedTags;
-                    cJSON *getreadings    = cJSON_GetObjectItem(root, "getreadings");
-                    for ( int i = 0; i < cJSON_GetArraySize(getreadings); ++i ) {
-                        cJSON *item = cJSON_GetArrayItem(getreadings, i);
-                        std::string tag      = cJSON_GetObjectItem(item, "tag")->valuestring;
-                        RequestedTags.push_back(tag);
-                    }
-                    GetTagReadings( RequestedTags, (char *)tx_array, sizeof(tx_array) );
-                    printf("%s:%d: Sending Reply to APP: %s\r\n",__func__,__LINE__,tx_array);
-                    BLE.SendFile(tx_array,strlen((char *)tx_array));
-                    break;
-                }
-                case BT_MODBUS_HOLD_COMMAND_MTYPE:
-                case BT_MODBUS_RAW_COMMAND_MTYPE: {
-                    printf("%s:%d: GOT MODBUS COMMAND\r\n",__func__,__LINE__);
-
-                    cJSON *mbcommand    = cJSON_GetObjectItem(root, "mbcommand");
-                    std::string payload_string = cJSON_PrintUnformatted(mbcommand);
-
-                    printf("%s:%d: Sending Command Request to ModbusMaster: %s\r\n",__func__,__LINE__,payload_string.c_str());
-
-                    ModbusMasterReq_t *mail = ModbusMasterMailBox.alloc();
-                    mail->action = ACTION_EXEC_CMD;
-                    mail->replyThread = BLE_HANDLER;
-                    strncpy( mail->msg, payload_string.c_str(), (sizeof(mail->msg)-1));
-                    ModbusMasterMailBox.put(mail);
-                    break;
-                }
-                case BT_GETLOG_COMMAND_MTYPE: {
-                    bool log_in_eeprom;
-                    log_in_eeprom = LogLocalApi_PopEntry( (char *)tx_array );
-                    if( log_in_eeprom == true ) {
-                        printf("%s:%d: Sending Reply to APP: %s\r\n",__func__,__LINE__,tx_array);
-                        BLE.SendFile(tx_array,strlen((char *)tx_array));
-                    } else {
-                        std::ostringstream reply_oss;
-                        reply_oss << "{  \"mtype\":" << BT_GETLOG_COMMAND_REPLY_MTYPE << ", \"log_empty\":\"true\" }";
-                        std::string string_reply = reply_oss.str();
-                        strncpy( (char *)tx_array, string_reply.c_str(), (sizeof(tx_array)-1));
-                        printf("%s:%d: Sending Reply to APP: %s\r\n",__func__,__LINE__, tx_array);
-                        BLE.SendFile(tx_array,strlen((char *)tx_array));
-                    }
-                    break;
-                }
-                case MANUAL_CONTROL_MTYPE:
-                case DESTROY_MANUAL_MTYPE: {
-
-                    printf("%s:%d: Invoke Manual Control COMMAND VIA BLE\r\n", __func__,__LINE__);
-                    std::string json_string = BLE_ReceiveString;
-                    bool status = !StoreReceivedFile( json_string );
-
-                    std::ostringstream reply_oss;
-                    cJSON *mncontrol    = cJSON_GetObjectItem(root, "mncontrol");
-                    std::string id      = cJSON_GetObjectItem(mncontrol, "id")->valuestring;
-                    reply_oss << "{  \"mtype\":" << MANUAL_CONTROL_REPLY_MTYPE << ", \"mncontrol\":{ \"id\":\"" << id.c_str() << "\"," "\"status\":\"" << status << "\"} }";
-                    std::string string_reply = reply_oss.str();
-                    strncpy( (char *)tx_array, string_reply.c_str(), (sizeof(tx_array)-1));
-                    printf("%s:%d: Sending Reply to APP: %s\r\n",__func__,__LINE__, tx_array);
-                    BLE.SendFile(tx_array,strlen((char *)tx_array));
-                    break;
-                }
-                case SETPOINT_CONTROL_MTYPE:
-                case DESTROY_SETPOINT_MTYPE: {
-
-                    printf("%s:%d: Invoke Setpoint Control COMMAND VIA BLE\r\n", __func__,__LINE__);
-                    std::string json_string = BLE_ReceiveString;
-                    bool status = !StoreReceivedFile( json_string );
-
-                    std::ostringstream reply_oss;
-                    cJSON *spcontrol    = cJSON_GetObjectItem(root, "spcontrol");
-                    std::string id      = cJSON_GetObjectItem(spcontrol, "id")->valuestring;
-                    reply_oss << "{  \"mtype\":" << SETPOINT_CONTROL_REPLY_MTYPE << ", \"spcontrol\":{ \"id\":\"" << id.c_str() << "\"," "\"status\":\"" << status << "\"} }";
-                    std::string string_reply = reply_oss.str();
-                    strncpy( (char *)tx_array, string_reply.c_str(), (sizeof(tx_array)-1));
-                    printf("%s:%d: Sending Reply to APP: %s\r\n",__func__,__LINE__, tx_array);
-                    BLE.SendFile(tx_array,strlen((char *)tx_array));
-                    break;
-                }
-                case INPUT_CONFIG_MTYPE: {
-
-                    printf("%s:%d: Invoke Configure Input COMMAND VIA BLE\r\n", __func__,__LINE__);
-                    std::string json_string = BLE_ReceiveString;
-                    bool status = !StoreReceivedFile( json_string );
-                    printf("%s:%d: Store file finished\r\n",__func__,__LINE__);
-                    std::ostringstream reply_oss;
-                    cJSON *input    = cJSON_GetObjectItem(root, "input");
-                    std::string id      = cJSON_GetObjectItem(input, "id")->valuestring;
-                    reply_oss << "{  \"mtype\":" << INPUT_CONFIG_REPLY_MTYPE << ", \"input\":{ \"id\":\"" << id.c_str() << "\"," "\"status\":\"" << status << "\"} }";
-                    std::string string_reply = reply_oss.str();
-                    strncpy( (char *)tx_array, string_reply.c_str(), (sizeof(tx_array)-1));
-                    printf("%s:%d: Sending Reply to APP: %s\r\n",__func__,__LINE__, tx_array);
-                    BLE.SendFile(tx_array,strlen((char *)tx_array));
-                    break;
-                }
-                case OUTPUT_CONFIG_MTYPE: {
-
-                    printf("%s:%d: Invoke Configure Output COMMAND VIA BLE\r\n", __func__,__LINE__);
-                    std::string json_string = BLE_ReceiveString;
-                    bool status = !StoreReceivedFile( json_string );
-
-                    std::ostringstream reply_oss;
-                    cJSON *output    = cJSON_GetObjectItem(root, "output");
-                    std::string id      = cJSON_GetObjectItem(output, "id")->valuestring;
-                    reply_oss << "{  \"mtype\":" << OUTPUT_CONFIG_REPLY_MTYPE << ", \"output\":{ \"id\":\"" << id.c_str() << "\"," "\"status\":\"" << status << "\"} }";
-                    std::string string_reply = reply_oss.str();
-                    strncpy( (char *)tx_array, string_reply.c_str(), (sizeof(tx_array)-1));
-                    printf("%s:%d: Sending Reply to APP: %s\r\n",__func__,__LINE__, tx_array);
-                    BLE.SendFile(tx_array,strlen((char *)tx_array));
-                    break;
-                }
-                default:
-                    printf("%s:%d: unknown mtype received: %d\r\n", __func__,__LINE__,mType);
-                    break;
-            }
-            BLE_StringReceived = false;
-            cJSON_Delete(root);
-        }
-#endif
-        // This will wait 100ms for a message
-        osEvent evt = BLEHandlerMailBox.get(100);
-        if (evt.status == osEventMail) {
-            BLEHandlerReq_t *mail = (BLEHandlerReq_t*)evt.value.p;
-            printf("%s:%d: Sending Reply to APP: %s\r\n",__func__,__LINE__,mail->reply);
-            BLE.SendFile((uint8_t *)mail->reply,strlen((char *)mail->reply));
-            BLEHandlerMailBox.free(mail);
-        }
-    }
-}
\ No newline at end of file
--- a/ICE-Application/src/BLEDataHandler/BLEDataHandler.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/******************************************************************************
- * 
- * File:                BLEDDataHandler.h
- * Desciption:          interface for the ICE BLE Data Handler 
- *
- *****************************************************************************/
-#ifndef BLEDATAHANDLER_H
-#define BLEDATAHANDLER_H
-
-void BLEDataHandler(void const *args);
-void BLE_ReplyToHandler( std::string &id, int status, float value );
-
-#endif
--- a/ICE-Application/src/CloudDataHandler/CloudDataHandler.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/******************************************************************************
- *
- * File:            CloudDataHandler.cpp
- * Description: 
- *
- *****************************************************************************/
-#include "CloudDataHandler.h"
-#include "CloudFileReceiver.h"
-#include "LogHandler.h"
-#include <stdio.h>
-#include <vector>
-#include "rtos.h"
-#include "global.h"
-
-// 
-// The Cloud Data Handler task
-//
-void CloudDataHandler(void const *args)
-{
-#if 0
-    int32_t ret;
-    bool joined;
-    bool sent;
-#endif
-
-    printf("\r%s has started...\n", __func__);
-
-    while ( true ) {
-
-        std::string tmp_buffer;
-#if 0
-        if (!GLOBAL_mdot->getNetworkJoinStatus()) {
-            logInfo("network not joined, joining network");
-            if ((ret = GLOBAL_mdot->joinNetwork()) != mDot::MDOT_OK) {
-                printf("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
-                joined = false;
-            }
-        } else {
-            joined = true;
-        }
-
-        sent = LogHandler( joined );
-        if( sent == true ) {
-            // sent a packet, try to receive back.
-            printf("Sent to gateway: %s", tmp_buffer.c_str());
-            std::vector<uint8_t> rcvData(256);
-            rcvData.clear();
-            if ((ret = GLOBAL_mdot->recv(rcvData)) == mDot::MDOT_OK) {
-                if (!rcvData.empty()) {
-                    std::string rcv_string(rcvData.begin(), rcvData.end());
-                    printf("Received Data: %s", rcv_string.c_str());
-                    CloudFileReceiver( &rcv_string, GLOBAL_mdot );
-                }
-            }
-        }
-#endif
-        Thread::wait(1000);
-    }
-}
\ No newline at end of file
--- a/ICE-Application/src/CloudDataHandler/CloudDataHandler.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-#ifndef CLOUDDATAHANDLER_H
-#define CLOUDDATAHANDLER_H
-
-#include <string>
-
-#define HEARTBEAT_MSG_MTYPE         20          // heartbeat (out)
-
-#define SETPOINT_CONTROL_MTYPE      100         // create a setpoint control (in)
-#define TIMER_CONTROL_MTYPE         101         // create a timer control (in)
-#define PID_CONTROL_MTYPE           102         // create a PID control (in)
-#define MANUAL_CONTROL_MTYPE        103         // create a manual control (in)
-#define COMPOSITE_CONTROL_MTYPE     104         // create a composite control (in)
-#define FAILSAFE_CONTROL_MTYPE      105         // create a failsafe control (in)
-#define SENSOR_ERR_CONTROL_MTYPE    106         // create a sensor error control (in)
-#define SEQUENCE_CONTROL_MTYPE      107         // create a sequence control (in)
-
-#define INPUT_CONFIG_MTYPE          200         // create an nput (in)
-#define OUTPUT_CONFIG_MTYPE         201         // create an output (in)
-#define VINPUT_CONFIG_MTYPE         203         // create a virtual input (in)
-#define VOUTPUT_CONFIG_MTYPE        204         // create a virtual output (in)
-#define HOLDING_CONFIG_MTYPE        205         // create a holding config (in)
-
-#define VIRTUAL_COMMAND_MTYPE       250         // virtual command (in)
-#define EQUATION_COMMAND_MTYPE      251         // equation command (in)
-
-#define DESTROY_SETPOINT_MTYPE      300         // destroys a setpoint control (in)
-#define DESTROY_TIMER_MTYPE         301         // destroys a timer control (in)
-#define DESTROY_PID_MTYPE           302         // destroys a PID control (in)
-#define DESTROY_MANUAL_MTYPE        303         // destroys a manual control (in)
-#define DESTROY_COMPOSITE_MTYPE     304         // destroys a composite control (in)
-#define DESTROY_FAILSAFE_MTYPE      305         // destroys a failsafe control (in)
-#define DESTROY_SENSOR_ERR_MTYPE    306         // destroys a sensor error control (in)
-#define DESTROY_SEQUENCE_MTYPE      307         // destroys a sequence control (in)
-
-
-#define EVENT_LOG_MTYPE             300         // event log, pump actuation, etc. (out)
-#define DEVICE_CONN_MTYPE           301         // device connected (out)
-#define LIVE_DATA_MTYPE             400         // live data (out)
-
-// BLE requests 
-#define BT_MODBUS_HOLD_COMMAND_MTYPE   1000 
-#define BT_MODBUS_RAW_COMMAND_MTYPE    1002
-#define BT_MODBUS_COMMAND_REPLY_MTYPE  1001
-
-#define BT_GETLOG_COMMAND_MTYPE        1100
-#define BT_GETLOG_COMMAND_REPLY_MTYPE  1101
-#define BT_GETLIVE_COMMAND_MTYPE       1200
-
-#define BT_START_CAL_COMMAND_MTYPE     1300
-#define BT_1PT_CAL_COMMAND_MTYPE       1301
-
-#define SETPOINT_CONTROL_REPLY_MTYPE   500
-#define TIMER_CONTROL_REPLY_MTYPE      501
-#define MANUAL_CONTROL_REPLY_MTYPE     503
-#define COMPOSITE_CONTROL_REPLY_MTYPE  504
-
-#define INPUT_CONFIG_REPLY_MTYPE        550
-#define OUTPUT_CONFIG_REPLY_MTYPE       551
-
-#define OPERATION_SUCCESS   0
-#define ORDER_NOT_SUPPORTED 500
-#define DATA_ARRAY_MISSING  501
-#define UNKNOWN_OPERATION   502
-
-void CloudDataHandler(void const *args);
-bool StoreReceivedFile( std::string &payload_string );
-
-#endif 
\ No newline at end of file
--- a/ICE-Application/src/CloudDataHandler/CloudFileReceiver.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,356 +0,0 @@
-#include "CloudFileReceiver.h"
-#include "CloudDataHandler.h"
-#include "mbed.h"
-#include "global.h"
-#include "cJSON.h"
-#include <algorithm>
-#include <string>
-#include "stdio.h"
-
-char CloudFileReceiverWriteBuf[MAX_FILE_SIZE];
-char CloudFileReceiverReadBuf[MAX_FILE_SIZE];
-
-bool StoreReceivedFile( std::string &payload_string )
-{
-    FILENAME_STRING filename;
-
-    memset( filename, '\0', sizeof(FILENAME_STRING) );
-
-    cJSON * root = cJSON_Parse(payload_string.c_str());
-    int mType = cJSON_GetObjectItem(root,"mtype")->valueint;
-//    printf("%s:%d: mtype=%d\r\n", __func__,__LINE__,mType);
-    switch( mType ) {
-        case SETPOINT_CONTROL_MTYPE:
-        case MANUAL_CONTROL_MTYPE:
-        case TIMER_CONTROL_MTYPE: {
-
-            std::string control_json;
-            ConfigMessage_t *mail  = ConfigHandlerMailBox.alloc();
-            memset(mail, 0, sizeof(ConfigMessage_t));
-            mail->action  = ACTION_CREATE;
-
-            switch( mType ) {
-                case SETPOINT_CONTROL_MTYPE: {
-                    cJSON * spcontrol = cJSON_GetObjectItem(root,"spcontrol");
-                    snprintf( filename, sizeof(FILENAME_STRING), "control_sp_%s.json", cJSON_GetObjectItem(spcontrol,"id")->valuestring );
-                    control_json = cJSON_PrintUnformatted(spcontrol);
-                    mail->control = CONTROL_SETPOINT;
-                    break;
-                }
-                case MANUAL_CONTROL_MTYPE: {
-                    cJSON * mncontrol = cJSON_GetObjectItem(root,"mncontrol");
-                    snprintf( filename, sizeof(FILENAME_STRING), "control_mn_%s.json", cJSON_GetObjectItem(mncontrol,"id")->valuestring );
-                    control_json = cJSON_PrintUnformatted(mncontrol);
-                    mail->control = CONTROL_MANUAL;
-                    break;
-                }
-                case TIMER_CONTROL_MTYPE: {
-                    cJSON * tmcontrol = cJSON_GetObjectItem(root,"tmcontrol");
-                    snprintf( filename, sizeof(FILENAME_STRING), "control_tm_%s.json", cJSON_GetObjectItem(tmcontrol,"id")->valuestring );
-                    std::string control_str = cJSON_PrintUnformatted(tmcontrol);
-                    mail->control = CONTROL_TIMER;
-                    break;
-                }
-                default: {
-                    printf("%s:%d: Unknown message type: %d\r\n",__func__,__LINE__,mType);
-                    cJSON_Delete(root);
-                    return false;
-                }
-            }
-
-            bool status = GLOBAL_mdot->saveUserFile(filename, (void *)control_json.c_str(), MAX_FILE_SIZE);
-            if( status != true ) {
-                printf("(%d)save file failed, status=%d\r\n", __LINE__, status);
-                break;
-            }
-
-            strncpy(mail->controlFile, filename, sizeof(mail->controlFile)-1);
-            ConfigHandlerMailBox.put(mail);
-
-            printf("%s:%d: Control JSON: %s\r\n", __func__,__LINE__, control_json.c_str() );
-            printf("%s:%d: Sending a create request for control %s type = %u\r\n", __func__,__LINE__, mail->controlFile, mail->control);
-            break;
-        }
-        case INPUT_CONFIG_MTYPE:
-        case VINPUT_CONFIG_MTYPE: {
-
-            cJSON * input = cJSON_GetObjectItem(root,"input");
-            if( mType == INPUT_CONFIG_MTYPE ) {
-                snprintf( filename, sizeof(FILENAME_STRING), "input_%s%s", cJSON_GetObjectItem(input,"id")->valuestring, ".json" );
-            } else {
-                snprintf( filename, sizeof(FILENAME_STRING), "vinput_%s%s", cJSON_GetObjectItem(input,"id")->valuestring, ".json" );
-            }
-            std::string input_str = cJSON_PrintUnformatted(input);
-
-
-            bool status = GLOBAL_mdot->saveUserFile(filename, (void *)input_str.c_str(), MAX_FILE_SIZE);
-            if( status != true ) {
-                printf("(%d)save file failed, status=%d", __LINE__, status);
-                break;
-            }
-
-            ModbusMasterReq_t *mail = ModbusMasterMailBox.alloc();
-            mail->action = ACTION_READ_FILE;
-            strncpy( mail->msg, filename, (sizeof(mail->msg)-1));
-            ModbusMasterMailBox.put(mail);
-
-            printf("%s:%d: INPUT JSON: %s\r\n", __func__,__LINE__, input_str.c_str() );
-            printf("%s:%d: Sending New INPUT to ModbusMasterMailBox, filename=%s\r\n", __func__,__LINE__, filename);
-            break;
-        }
-        case OUTPUT_CONFIG_MTYPE:
-        case VOUTPUT_CONFIG_MTYPE: {
-
-            cJSON * output = cJSON_GetObjectItem(root,"output");
-            if( mType == OUTPUT_CONFIG_MTYPE ) {
-                snprintf( filename, sizeof(FILENAME_STRING), "output_%s%s", cJSON_GetObjectItem(output,"id")->valuestring, ".json" );
-            } else {
-                snprintf( filename, sizeof(FILENAME_STRING), "voutput_%s%s", cJSON_GetObjectItem(output,"id")->valuestring, ".json" );
-            }
-            std::string output_str = cJSON_PrintUnformatted(output);
-
-            bool status = GLOBAL_mdot->saveUserFile(filename, (void *)output_str.c_str(), MAX_FILE_SIZE);
-            if( status != true ) {
-                printf("(%d)save file failed, status=%d\r\n", __LINE__, status);
-                break;
-            }
-
-            // send a message to the modbus master
-            ModbusMasterReq_t *mail = ModbusMasterMailBox.alloc();
-            mail->action = ACTION_READ_FILE;
-            strncpy( mail->msg, filename, (sizeof(mail->msg)-1));
-            ModbusMasterMailBox.put(mail);
-
-            // send a message to the output master
-            OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-            output_mail->action = ACTION_NEW;
-            strncpy(output_mail->controlFile, filename, sizeof(output_mail->controlFile)-1);
-            OutputMasterMailBox.put(output_mail);
-
-            printf("%s:%d: OUTPUT JSON: %s\r\n", __func__,__LINE__, output_str.c_str() );
-            printf("%s:%d: Sending New OUTPUT to ModbusMaster and OutputMaster, filename=%s\r\n", __func__,__LINE__, filename);
-
-            break;
-        }
-        case HOLDING_CONFIG_MTYPE: {
-
-            cJSON * holding = cJSON_GetObjectItem(root,"holding");
-            snprintf( filename, sizeof(FILENAME_STRING), "hold_%s%s", cJSON_GetObjectItem(holding,"id")->valuestring, ".json" );
-            std::string holding_str = cJSON_PrintUnformatted(holding);
-
-            bool status = GLOBAL_mdot->saveUserFile(filename, (void *)holding_str.c_str(), MAX_FILE_SIZE);
-            if( status != true ) {
-                printf("(%d)save file failed, status=%d", __LINE__, status);
-                break;
-            }
-
-            ModbusMasterReq_t *mail = ModbusMasterMailBox.alloc();
-            mail->action = ACTION_READ_FILE;
-            strncpy( mail->msg, filename, (sizeof(mail->msg)-1));
-            ModbusMasterMailBox.put(mail);
-
-            printf("%s:%d: HOLDING JSON: %s\r\n", __func__,__LINE__, holding_str.c_str() );
-            printf("%s:%d: Sending New HOLDING REGISTER to ModbusMasterMailBox, filename=%s\r\n", __func__,__LINE__, filename);
-            break;
-        }
-        case DESTROY_SETPOINT_MTYPE: {
-
-            cJSON * spcontrol = cJSON_GetObjectItem(root,"spcontrol");
-            snprintf( filename, sizeof(FILENAME_STRING), "control_sp_%s.json", cJSON_GetObjectItem(spcontrol,"id")->valuestring );
-
-            // send a message to the configuration handler to create the control
-            ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-            memset(msg, 0, sizeof(ConfigMessage_t));
-            msg->action  = ACTION_DESTROY;
-            msg->control = CONTROL_SETPOINT;
-            strncpy(msg->controlFile, filename, sizeof(msg->controlFile)-1);
-
-            printf("%s:%d: Sending a destroy request for setpoint control %s type = %u\r\n", __func__,__LINE__, msg->controlFile, msg->control);
-
-            ConfigHandlerMailBox.put(msg);
-            break;
-        }
-        case DESTROY_MANUAL_MTYPE: {
-
-            cJSON * mncontrol = cJSON_GetObjectItem(root,"mncontrol");
-            snprintf( filename, sizeof(FILENAME_STRING), "control_mn_%s.json", cJSON_GetObjectItem(mncontrol,"id")->valuestring );
-
-            // send a message to the configuration handler to create the control
-            ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-            memset(msg, 0, sizeof(ConfigMessage_t));
-            msg->action  = ACTION_DESTROY;
-            msg->control = CONTROL_MANUAL;
-            strncpy(msg->controlFile, filename, sizeof(msg->controlFile)-1);
-
-            printf("%s:%d: Sending a destroy request for manual control %s type = %u\r\n", __func__,__LINE__, msg->controlFile, msg->control);
-
-            ConfigHandlerMailBox.put(msg);
-            break;
-        }
-        case DESTROY_TIMER_MTYPE: {
-
-            cJSON * tmcontrol = cJSON_GetObjectItem(root,"tmcontrol");
-            snprintf( filename, sizeof(FILENAME_STRING), "control_tm_%s.json", cJSON_GetObjectItem(tmcontrol,"id")->valuestring );
-
-            ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-            memset(msg, 0, sizeof(ConfigMessage_t));
-            msg->action  = ACTION_DESTROY;
-            msg->control = CONTROL_TIMER;
-            strncpy(msg->controlFile, filename, sizeof(msg->controlFile)-1);
-
-            printf("%s:%d: Sending a destroy request for timer control %s type = %u\r\n", __func__,__LINE__, msg->controlFile, msg->control);
-
-            ConfigHandlerMailBox.put(msg);
-            break;
-        }
-        case VIRTUAL_COMMAND_MTYPE: {
-
-            cJSON * command = cJSON_GetObjectItem(root,"command");
-            snprintf( filename, sizeof(FILENAME_STRING), "cmd_%s.json", cJSON_GetObjectItem(command,"id")->valuestring );
-            std::string command_json = cJSON_PrintUnformatted(command);
-
-            bool status = GLOBAL_mdot->saveUserFile(filename, (void *)command_json.c_str(), MAX_FILE_SIZE);
-            if( status != true ) {
-                printf("(%d)save file failed, status=%d\r\n", __LINE__, status);
-                break;
-            }
-
-            ModbusMasterReq_t *mail = ModbusMasterMailBox.alloc();
-            mail->action = ACTION_READ_FILE;
-            strncpy( mail->msg, filename, (sizeof(mail->msg)-1));
-            ModbusMasterMailBox.put(mail);
-
-            printf("%s:%d: COMMAND: %s\r\n", __func__,__LINE__, command_json.c_str() );
-            printf("%s:%d: Sending a create command requst to ModbusMaster %s type = %u\r\n", __func__,__LINE__, mail->msg, mail->control);
-
-            break;
-        }
-        case BT_MODBUS_HOLD_COMMAND_MTYPE: {
-
-            cJSON * mbcommand = cJSON_GetObjectItem(root,"mbcommand");
-            std::string mbcommand_json = cJSON_PrintUnformatted(mbcommand);
-            ModbusMasterReq_t *mail = ModbusMasterMailBox.alloc();
-            mail->action = ACTION_EXEC_CMD;
-            mail->replyThread = CLOUD_DATA_HANDLER;
-            strncpy( mail->msg, mbcommand_json.c_str(), (sizeof(mail->msg)-1));
-            ModbusMasterMailBox.put(mail);
-
-            printf("%s:%d: MODBUS Command: %s\r\n", __func__,__LINE__, mbcommand_json.c_str());
-
-            break;
-        }
-        default:
-//            printf("%s:%d: DEFAULT\r\n", __func__,__LINE__);
-            break;
-    }
-    cJSON_Delete(root);
-    return true;
-}
-
-bool CloudDataHandler_RcvFile = false;
-bool CloudFileReceiver( std::string *recv_string )
-{
-    bool status;
-    CloudDataHandler_RcvFile = false;
-    int sequence;
-    std::string seq_str = recv_string->c_str();
-    std::string remove_seq = "{\"seq\":";
-    std::string::size_type i = seq_str.find(remove_seq);
-    if (i != std::string::npos) {
-        seq_str.erase(i, remove_seq.length());
-        std::string remove_comma = ",";
-        i = seq_str.find(remove_comma);
-        if (i != std::string::npos) {
-            seq_str.erase(i, (seq_str.length()-i));
-            sequence = atoi(seq_str.c_str());
-        }
-    }
-    std::string payload_string = recv_string->c_str();
-    std::string extract_pay = "\"pay\":";
-    i = payload_string.find(extract_pay);
-    if (i != std::string::npos) {
-        i = i + extract_pay.length();
-        payload_string.erase(0, i);
-        payload_string.erase((payload_string.length()-1), 1);
-        if( sequence != -1 ) {
-            payload_string = payload_string.substr(1, payload_string.size() - 2);
-        }
-    }
-
-    printf("sequence=%d, payload_string:%s", sequence, payload_string.c_str() );
-
-    CloudDataHandler_RcvFile = false;
-    if( sequence == -1 ) {
-
-        // sequence of -1 means string sent in 1 chunk.
-//        printf("%s:%d: payload=%s\r\n",__func__,__LINE__, payload_string.c_str() );
-        status = StoreReceivedFile( payload_string );
-
-    } else if( sequence == 0 ) {
-
-        memset(CloudFileReceiverWriteBuf,0,sizeof(CloudFileReceiverWriteBuf));
-        snprintf(CloudFileReceiverWriteBuf, sizeof(CloudFileReceiverWriteBuf), "%s", payload_string.c_str() );
-
-        printf("(%d)Writing String Length=%d, %s", __LINE__, MAX_FILE_SIZE, CloudFileReceiverWriteBuf );
-
-        status = GLOBAL_mdot->saveUserFile("scratch.json", (void *)CloudFileReceiverWriteBuf, MAX_FILE_SIZE);
-        if( status != true ) {
-            printf("(%d)save file failed, status=%d", __LINE__, status);
-        } else {
-            CloudDataHandler_RcvFile = true;
-            printf("(%d)UPDATED scratch.json FILE, status:%d, strlen=%d", __LINE__, status, strlen(CloudFileReceiverWriteBuf));
-        }
-
-    } else if( sequence == -2 ) {
-
-        printf("(%d)READING BACK scratch.json FILE FOR LAST PACKET", __LINE__);
-
-        // read the file back
-        status = GLOBAL_mdot->readUserFile("scratch.json", (void *)CloudFileReceiverReadBuf, MAX_FILE_SIZE);
-        if( status != true ) {
-            printf("(%d)read file failed, status=%d", __LINE__, status);
-            return false;
-        }
-
-        snprintf(CloudFileReceiverWriteBuf, sizeof(CloudFileReceiverWriteBuf), "%s%s", CloudFileReceiverReadBuf, payload_string.c_str() );
-        printf("(%d)Final String Length=%d, %s", __LINE__, strlen(CloudFileReceiverWriteBuf), CloudFileReceiverWriteBuf );
-
-        std::string final_json = CloudFileReceiverWriteBuf;
-        printf("%s:%d: finished parse: %s\r\n", __func__,__LINE__,final_json.c_str() );
-
-        status = StoreReceivedFile( final_json );
-        if( status != true ) {
-            printf("(%d)save file failed, status=%d", __LINE__, status);
-        }
-
-        status = GLOBAL_mdot->deleteUserFile("scratch.json");
-        if( status != true ) {
-            printf("(%d)delete file failed, status=%d", __LINE__, status);
-        }
-
-        printf("(%d)DELETED scratch.json FILE, status:%d", __LINE__, status );
-
-    } else {
-
-        printf("(%d)READING BACK scratch.json FILE", __LINE__);
-
-        // read the file back
-        status = GLOBAL_mdot->readUserFile("scratch.json", (void *)CloudFileReceiverReadBuf, MAX_FILE_SIZE);
-        if( status != true ) {
-            printf("(%d)read file failed, status=%d", __LINE__, status);
-            return false;
-        }
-
-        snprintf(CloudFileReceiverWriteBuf, sizeof(CloudFileReceiverWriteBuf), "%s%s", CloudFileReceiverReadBuf, payload_string.c_str() );
-        printf("(%d)Writing String Length=%d, %s", __LINE__, strlen(CloudFileReceiverWriteBuf), CloudFileReceiverWriteBuf );
-
-        status = GLOBAL_mdot->saveUserFile("scratch.json", (void *)CloudFileReceiverWriteBuf, MAX_FILE_SIZE);
-        if( status != true ) {
-            printf("(%d)save file failed, status=%d", __LINE__, status);
-        } else {
-            CloudDataHandler_RcvFile = true;
-            printf("(%d)UPDATED scratch.json FILE, status:%d, strlen=%d", __LINE__, status, strlen(CloudFileReceiverWriteBuf));
-        }
-    }
-    return true;
-}
\ No newline at end of file
--- a/ICE-Application/src/CloudDataHandler/CloudFileReceiver.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-#ifndef CLOUDFILERECEIVER_H
-#define CLOUDFILERECEIVER_H
-
-#include <string>
-
-typedef char TASKNAME_STRING[64];
-typedef char FILENAME_STRING[64];
-
-extern bool CloudDataHandler_RcvFile;
-
-bool CloudFileReceiver( std::string *recv_string );
-
-#endif 
-
--- a/ICE-Application/src/CommandParser/cmd.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2725 +0,0 @@
-/*
- * ===============================================================
- *  Natural Tiny Shell (NT-Shell) Application example.
- *  Version 0.0.6
- * ===============================================================
- * Copyright (c) 2010-2011 Shinichiro Nakamura
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- * ===============================================================
- */
-
-#include <mbed.h>
-#include <mbed_stats.h>
-#include <stdlib.h>
-#include <vector>
-#include <rtos.h>
-#include "cmd.h"
-#include "ntshell.h"
-#include "ntopt.h"
-#include "cJSON.h"
-#include "v7.h"
-#include "global.h"
-#include "OutputTask.h"
-#include "ModbusMasterApi.h"
-#include "ConfigurationHandler.h"
-#include "mfs.h"
-#include "rtc.h"
-#include "ConfigFs.h"
-#include "version.h"
-#include "ICELog.h"
-#include "utilities.h"
-
-ntshell_t ntshell;
-extern Serial console;
-
-// the readers and writers
-int func_read(char *buf, int cnt);
-int func_write(const char *buf, int cnt);
-int func_cb_ntshell(const char *text);
-void func_cb_ntopt(int argc, char **argv);
-
-// the command table element
-typedef struct {
-    char *command;                              // command (from shell)
-    char *description;                          // descrption
-    void (*func)(int argc, char **argv);        // callback function
-} command_table_t;
-
-const command_table_t cmdlist[] = {
-    {"?",                   "help command",                                     cmd_help            },
-    {"cif",                 "create an input file",                             cmd_cif             },
-    {"cof",                 "create an output file",                            cmd_cof             },
-    {"create-ca",           "create a control algorithm file",                  cmd_createCAlg      },
-    {"create-fs",           "create a failsafe control",                        cmd_createFailsafe  },
-    {"create-mn",           "create a manual control",                          cmd_createManual    },
-    {"create-se",           "create a sensor error control",                    cmd_createSError    },
-    {"create-seq",          "create a sequence control",                        cmd_createSequence  },
-    {"create-sp",           "create a setpoint control",                        cmd_createSetpoint  },
-    {"create-tm",           "create a timer control",                           cmd_createTimer     },
-    {"create-vreg",         "create a virtual register",                        cmd_createVreg      },
-    {"debug-fs",            "debug failsafe controls",                          cmd_debug_fs        },
-    {"debug-mn",            "debug manual controls",                            cmd_debug_mn        },
-    {"debug-se",            "debug sensor error controls",                      cmd_debug_se        },
-    {"debug-seq",           "debug sequence controls",                          cmd_debug_seq       },
-    {"debug-sp",            "debug setpoint controls",                          cmd_debug_sp        },
-    {"debug-tm",            "debug timer controls",                             cmd_debug_tm        },
-    {"delete-file",         "delete a file from EEPROM",                        cmd_deleteFile      },
-    {"destroy-control",     "destroy a control",                                cmd_destroy         },
-    {"format-fs",           "format EEPROM file system",                        cmd_formatFS        },
-    {"heap-stats",          "dump heap data",                                   cmd_heap_stats      },
-    {"help",                "help command",                                     cmd_help            },
-    {"json-test",           "JSON parser test",                                 cmd_json            },
-    {"log-level",           "set debug log-level",                              cmd_logLevel        },
-    {"ls",                  "list files in EEPROM",                             cmd_lsFile          },
-    {"modmap",              "dump modbus register map",                         cmd_modmap          },
-    {"preload",             "pre-load phase-1 demo files",                      cmd_preload         },
-    {"read-file",           "read file from EEPROM",                            cmd_readFile        },
-    {"reset",               "software reset",                                   cmd_reset           },
-    {"simall",              "simulate multiple inputs",                         cmd_simall          },
-    {"simerr",              "simulate input error",                             cmd_simerr          },
-    {"simin",               "simulate input",                                   cmd_simin           },
-    {"show-ca",             "show control algorithms",                          cmd_ShowAlgorithms  },
-    {"show-controls",       "show active controls",                             cmd_ShowControls    },
-    {"show-tm-controls",    "display active timer controls",                    cmd_ShowTimers      },
-    {"show-mn-controls",    "display active manual controls",                   cmd_ShowManuals     },
-    {"show-co-controls",    "display active composite controls",                cmd_ShowComposites  },
-    {"show-fs-controls",    "display active failsafe controls",                 cmd_ShowFailsafes   },
-    {"show-se-controls",    "display active sensor error controls",             cmd_ShowSensorErrors},
-    {"show-seq-controls",   "display active sequential controls",               cmd_ShowSequences   },
-    {"show-sp-controls",    "display active setpoint controls",                 cmd_ShowSetpoints   },
-    {"show-outputs",        "display the output hierarchy",                     cmd_outputs         },
-    //{"spi-test",            "test SPI FLASH interface",                         cmd_spiTest         },
-    {"stack-stats",         "dump stack stats",                                 cmd_stack           },
-    {"test-log-level",      "tests the log functions",                          cmd_testLog         },
-    {"test-prebleed",       "test the pre-bleed scripts",                       cmd_testPreBleed    },
-    {"v7-test",             "V7 test",                                          cmd_v7,             },
-    {"version",             "display version info",                             cmd_version         },
-    {"vregmap",             "display the virtual register map",                 cmd_vregmap         },
-    {"write-file",          "write a file to EEPROM",                           cmd_writeFile       },
-    {"get-time",            "get time from RTC",                                cmd_getTime         },
-    {"set-time",            "set time from RTC",                                cmd_setTime         },
-    {NULL, NULL, NULL}
-};
-
-
-void cmd_testLog(int argc, char **argv)
-{
-    logFatal    ("Testing");
-    logError    ("Testing");
-    logWarning  ("Testing");
-    logInfo     ("Testing");
-    logDebug    ("Testing");
-    logTrace    ("Testing");
-
-}
-
-//
-// function:            cmd_debug_fs
-// decription:          debug failsafe controls (ON|OFF)
-//
-void cmd_debug_fs(int argc, char **argv)
-{
-    extern bool debugFailsafeControl;
-
-    if ( argc == 1 ) {
-        printf("\rCurrent level is %d\r\n", debugFailsafeControl);
-        return;
-    }
-
-    if ( argc != 2 ) {
-usage:
-        printf("\rusage: debug-fs <1|0>\n");
-        printf("\rexample: debug-fs 1\n");
-        return;
-    }
-
-    if ( (atoi(argv[1])) == 1 ) {
-        debugFailsafeControl = true;
-    } else if ( (atoi(argv[1])) == 0  ) {
-        debugFailsafeControl = false;
-    } else {
-        goto usage;
-    }
-}
-
-//
-// function:            cmd__debug_man
-// description:         debug manual controls (ON|OFF)
-//
-void cmd_debug_mn(int argc, char **argv)
-{
-    extern bool debugManualControl;
-
-    if ( argc == 1 ) {
-        printf("\rCurrent level is %d\r\n", debugManualControl);
-        return;
-    }
-
-    if ( argc != 2 ) {
-usage:
-        printf("\rusage:    debug-man <1|0>\n");
-        printf("\rexample:  debug-man 1\n");
-        return;
-    }
-
-    if ( (atoi(argv[1])) == 1 ) {
-        debugManualControl = true;
-    } else if ( (atoi(argv[1])) == 0  ) {
-        debugManualControl = false;
-    } else {
-        goto usage;
-    }
-}
-
-//
-// function:            cmd_debug_se
-// description:         debug sensor error controls (ON|OFF)
-//
-void cmd_debug_se(int argc, char **argv)
-{
-    extern bool debugSensorError;
-
-    if ( argc == 1 ) {
-        printf("\rCurrent level is %d\r\n", debugSensorError);
-        return;
-    }
-
-    if ( argc != 2 ) {
-usage:
-        printf("\rusage:   debug-se <1|0>\n");
-        printf("\rexample: debug-se 1\n");
-        return;
-    }
-
-    if ( (atoi(argv[1])) == 1 ) {
-        debugSensorError = true;
-    } else if ( (atoi(argv[1])) == 0  ) {
-        debugSensorError = false;
-    } else {
-        goto usage;
-    }
-}
-
-//
-// function:            cmd_debug_seq
-// description:         debug sequence controls (ON|OFF
-//
-void cmd_debug_seq(int argc, char **argv)
-{
-    extern bool debugSequenceControl;
-
-    if ( argc == 1 ) {
-        printf("\rCurrent level is %d\r\n", debugSequenceControl);
-        return;
-    }
-
-    if ( argc != 2 ) {
-usage:
-        printf("\rusage:   debug-seq <1|0>\n");
-        printf("\rexample: debug-seq 1\n");
-        return;
-    }
-
-    if ( (atoi(argv[1])) == 1 ) {
-        debugSequenceControl = true;
-    } else if ( (atoi(argv[1])) == 0  ) {
-        debugSequenceControl = false;
-    } else {
-        goto usage;
-    }
-}
-
-//
-// function:            cmd_debug_sp
-// description:         debug setpoint controls
-//
-void cmd_debug_sp(int argc, char **argv)
-{
-    extern bool debugSetpointControl;
-
-    if ( argc == 1 ) {
-        printf("\rCurrent level is %d\r\n", debugSetpointControl);
-        return;
-    }
-
-    if ( argc != 2 ) {
-usage:
-        printf("\rusage:   debug-sp <1|0>\n");
-        printf("\rexample: debug-sp 1\n");
-        return;
-    }
-
-    if ( (atoi(argv[1])) == 1 ) {
-        debugSetpointControl = true;
-    } else if ( (atoi(argv[1])) == 0  ) {
-        debugSetpointControl = false;
-    } else {
-        goto usage;
-    }
-}
-
-//
-// function:            cmd_debug_tm
-// description:         debug timer controls (ON|OFF)
-//
-void cmd_debug_tm(int argc, char **argv)
-{
-    extern bool debugTimerControl;
-
-    if ( argc == 1 ) {
-        printf("\rCurrent level is %d\r\n", debugTimerControl);
-        return;
-    }
-
-    if ( argc != 2 ) {
-usage:
-        printf("\rusage:   debug-tm <1|0>\n");
-        printf("\rexample: debug-tm 1\n");
-        return;
-    }
-
-    if ( (atoi(argv[1])) == 1 ) {
-        debugTimerControl = true;
-    } else if ( (atoi(argv[1])) == 0  ) {
-        debugTimerControl = false;
-    } else {
-        goto usage;
-    }
-}
-
-
-void cmd_heap_stats(int argc, char **argv)
-{
-#ifndef __ICCARM__
-    UNUSED(argc), UNUSED(argv);
-    printf("\r%s\r\n", Util_getHeapData().c_str());
-#if 0
-    UNUSED(argc);
-    UNUSED(argv);
-
-    mbed_stats_heap_t s;
-    mbed_stats_heap_get(&s);
-
-    printf("\rHeap statistics:\n");
-    printf("\r    bytes allocated......%u\n", s.current_size/1024);
-    printf("\r    max bytes allocated..%u\n", s.max_size/1024);
-    printf("\r    cumulative sum.......%u\n", s.total_size);
-    printf("\r    reserved size........%u\n", s.reserved_size);
-    printf("\r    allocations..........%u\n", s.alloc_cnt);
-    printf("\r    failed allocations...%u\n", s.alloc_fail_cnt);
-
-    return;
-#endif
-#endif
-}
-
-void cmd_ShowAlgorithms(int argc, char **argv)
-{
-    UNUSED(argc);
-    UNUSED(argv);
-    ConfigurationHandler_showAlgorithms();
-    printf("\r\n");
-}
-
-void cmd_ShowControls(int argc, char **argv)
-{
-    UNUSED(argc);
-    UNUSED(argv);
-    ConfigurationHandler_showControls();
-    printf("\r\n");
-
-}
-
-void cmd_reset(int argc, char **argv)
-{
-    NVIC_SystemReset();
-}
-
-void cmd_ShowTimers(int argc, char **argv)
-{
-    UNUSED(argc), UNUSED(argv);
-    ConfigurationHandler_showTimerControls();
-    printf("\r\n");
-}
-
-void cmd_ShowManuals(int argc, char **argv)
-{
-    UNUSED(argc), UNUSED(argv);
-    ConfigurationHandler_showManualControls();
-    printf("\r\n");
-}
-
-void cmd_ShowFailsafes(int argc, char **argv)
-{
-    UNUSED(argc), UNUSED(argv);
-    ConfigurationHandler_showFailsafeControls();
-    printf("\r\n");
-}
-
-void cmd_ShowSequences(int argc, char **argv)
-{
-    UNUSED(argc), UNUSED(argv);
-    ConfigurationHandler_showSequenceControls();
-}
-
-void cmd_ShowComposites(int argc, char **argv)
-{
-    UNUSED(argc), UNUSED(argv);
-    ConfigurationHandler_showCompositeControls();
-    printf("\r\n");
-}
-
-void cmd_ShowSetpoints(int argc, char **argv)
-{
-    UNUSED(argc), UNUSED(argv);
-    ConfigurationHandler_showSetpointControls();
-    printf("\r\n");
-}
-
-void cmd_ShowSensorErrors(int argc, char **argv)
-{
-    UNUSED(argc), UNUSED(argv);
-    ConfigurationHandler_showSensorErrorControls();
-    printf("\r\n");
-}
-
-
-/*****************************************************************************
- * Function:        cmd_simerr
- * Description:     simulate an input error
- *
- * @return          none
- *****************************************************************************/
-void cmd_simerr(int argc, char **argv)
-{
-    if ( argc < 3 ) {
-        printf("\rusage:   simerr <input> <errflag_value>\n");
-        printf("\rexample: simerr i_bdcond01 9\n");
-        return;
-    }
-
-    ModbusRegisterMap[argv[1]].simulated = true;
-    SimulateInputMap[argv[1]].errflag = (uint32_t)(atoi(argv[2]));
-}
-
-/*****************************************************************************
- * Function:        cmd_simin
- * Description:     simulat input
- *
- * @param           argc-> number of args
- * @param           argv-> input
- * @return          none
- *****************************************************************************/
-void cmd_simin(int argc, char **argv)
-{
-    if ( argc != 3 && argc != 7 ) {
-        printf("\rusage: simin <input> <value> <<low> <hi> <up_step> <down_step>>\r\n");
-        printf("\rexample: simin i_tra01 100 94 106 1 .25\r\n");
-        printf("\rexample: simin i_bdcond01 2000 1990 2006 .25 1\r\n");
-        printf("\rexample: simin i_bdcond01 1800\n");
-        return;
-    }
-
-    //float value = atof( argv[2] );
-    SimulateInputMap[argv[1]].start_value = atof(argv[2]);
-
-    ModbusRegisterMap[argv[1]].simulated = true;
-
-    if ( argc == 3 ) {
-        SimulateInputMap[argv[1]].min = 0;
-        SimulateInputMap[argv[1]].max = 0;
-        SimulateInputMap[argv[1]].moving_up = false;
-        return;
-    }
-    SimulateInputMap[argv[1]].min = atof(argv[3]);
-    SimulateInputMap[argv[1]].max = atof(argv[4]);
-    SimulateInputMap[argv[1]].up_step = atof(argv[5]);
-    SimulateInputMap[argv[1]].down_step = atof(argv[6]);
-    SimulateInputMap[argv[1]].moving_up = true;
-
-}
-
-/*****************************************************************************
- * Function:        cmd_simall
- * Description:     simulat multiple inputs
- *
- * @return          none
- *****************************************************************************/
-void cmd_simall(int argc, char **argv)
-{
-
-    if ( argc > 1 ) {
-
-        printf("\r  setting: simin i_tra01 100\n");
-        ModbusRegisterMap["i_tra01"].simulated = true;
-        SimulateInputMap["i_tra01"].start_value = 130;
-        SimulateInputMap["i_tra01"].min = 0;
-        SimulateInputMap["i_tra01"].max = 0;
-        SimulateInputMap["i_tra01"].up_step = 0;
-        SimulateInputMap["i_tra01"].down_step = 0;
-        SimulateInputMap["i_tra01"].moving_up = true;
-
-        printf("\r  setting: i_tag01 100\n");
-        ModbusRegisterMap["i_tag01"].simulated = true;
-        SimulateInputMap["i_tag01"].start_value = 100;
-        SimulateInputMap["i_tag01"].min = 0;
-        SimulateInputMap["i_tag01"].max = 0;
-        SimulateInputMap["i_tag01"].up_step = 0;
-        SimulateInputMap["i_tag01"].down_step = 0;
-        SimulateInputMap["i_tag01"].moving_up = true;
-
-        printf("\r  setting: i_bdcond01 1800\n");
-        ModbusRegisterMap["i_bdcond01"].simulated = true;
-        SimulateInputMap["i_bdcond01"].start_value = 1800;
-        SimulateInputMap["i_bdcond01"].min = 0;
-        SimulateInputMap["i_bdcond01"].max = 0;
-        SimulateInputMap["i_bdcond01"].up_step = 0;
-        SimulateInputMap["i_bdcond01"].down_step = 0;
-        SimulateInputMap["i_bdcond01"].moving_up = true;
-
-        printf("\r  setting: i_cond_temp01 25\n");
-        ModbusRegisterMap["i_cond_temp01"].simulated = true;
-        SimulateInputMap["i_cond_temp01"].start_value = 25000.0;
-        SimulateInputMap["i_cond_temp01"].min = 0;
-        SimulateInputMap["i_cond_temp01"].max = 0;
-        SimulateInputMap["i_cond_temp01"].up_step = 0;
-        SimulateInputMap["i_cond_temp01"].down_step = 0;
-        SimulateInputMap["i_cond_temp01"].moving_up = true;
-
-        printf("\r  setting: i_ph01 8\n");
-        ModbusRegisterMap["i_ph01"].simulated = true;
-        SimulateInputMap["i_ph01"].start_value = 8000;
-        SimulateInputMap["i_ph01"].min = 0;
-        SimulateInputMap["i_ph01"].max = 0;
-        SimulateInputMap["i_ph01"].up_step = 0;
-        SimulateInputMap["i_ph01"].down_step = 0;
-        SimulateInputMap["i_ph01"].moving_up = true;
-
-        printf("\r  setting: i_ph_temp01 25\n");
-        ModbusRegisterMap["i_ph_temp01"].simulated = true;
-        SimulateInputMap["i_ph_temp01"].start_value = 25000.0;
-        SimulateInputMap["i_ph_temp01"].min = 0;
-        SimulateInputMap["i_ph_temp01"].max = 0;
-        SimulateInputMap["i_ph_temp01"].up_step = 0;
-        SimulateInputMap["i_ph_temp01"].down_step = 0;
-        SimulateInputMap["i_ph_temp01"].moving_up = true;
-
-        printf("\r  setting: i_orp01 350\n");
-        ModbusRegisterMap["i_orp01"].simulated = true;
-        SimulateInputMap["i_orp01"].start_value = 350;
-        SimulateInputMap["i_orp01"].min = 0;
-        SimulateInputMap["i_orp01"].max = 0;
-        SimulateInputMap["i_orp01"].up_step = 0;
-        SimulateInputMap["i_orp01"].down_step = 0;
-        SimulateInputMap["i_orp01"].moving_up = true;
-
-
-        printf("\r  setting: i_flowsw01 1\n");
-        ModbusRegisterMap["i_flowsw01"].simulated = true;
-        SimulateInputMap["i_flowsw01"].start_value = 1;
-        SimulateInputMap["i_flowsw01"].min = 0;
-        SimulateInputMap["i_flowsw01"].max = 0;
-        SimulateInputMap["i_flowsw01"].up_step = 0;
-        SimulateInputMap["i_flowsw01"].down_step = 0;
-        SimulateInputMap["i_flowsw01"].moving_up = true;
-
-        return;
-    }
-
-    printf("\rsetting: simin i_tra01 130 120 140 1 .25\r\n");
-    printf("\rsetting: simin i_tag01 100 90 110 1 .25\r\n");
-    printf("\rsetting: simin i_bdcond01 1800 1725 1875 1 5\r\n");
-    printf("\rsetting: simin i_ph01 8.0 7.25 8.75 .0. .1\r\n");
-    printf("\rsetting: simin i_orp01 350 300 400 5 1\r\n");
-
-    ModbusRegisterMap["i_tra01"].simulated = true;
-    SimulateInputMap["i_tra01"].start_value = 130;
-    SimulateInputMap["i_tra01"].min = 120;
-    SimulateInputMap["i_tra01"].max = 140;
-    SimulateInputMap["i_tra01"].up_step = 1;
-    SimulateInputMap["i_tra01"].down_step = .25;
-
-    ModbusRegisterMap["i_tag01"].simulated = true;
-    SimulateInputMap["i_tag01"].start_value = 100;
-    SimulateInputMap["i_tag01"].min = 90;
-    SimulateInputMap["i_tag01"].max = 110;
-    SimulateInputMap["i_tag01"].up_step = 1;
-    SimulateInputMap["i_tag01"].down_step = .25;
-
-    ModbusRegisterMap["i_bdcond01"].simulated = true;
-    SimulateInputMap["i_bdcond01"].start_value = 1800;
-    SimulateInputMap["i_bdcond01"].min = 1725;
-    SimulateInputMap["i_bdcond01"].max = 1875;
-    SimulateInputMap["i_bdcond01"].up_step = 1;
-    SimulateInputMap["i_bdcond01"].down_step = 5;
-
-    ModbusRegisterMap["i_ph01"].simulated = true;
-    SimulateInputMap["i_ph01"].start_value = 8000;
-    SimulateInputMap["i_ph01"].min = 7250;
-    SimulateInputMap["i_ph01"].max = 8750;
-    SimulateInputMap["i_ph01"].up_step = 5;
-    SimulateInputMap["i_ph01"].down_step = 10;
-
-    ModbusRegisterMap["i_orp01"].simulated = true;
-    SimulateInputMap["i_orp01"].start_value = 350;
-    SimulateInputMap["i_orp01"].min = 300;
-    SimulateInputMap["i_orp01"].max = 400;
-    SimulateInputMap["i_orp01"].up_step = 5;
-    SimulateInputMap["i_orp01"].down_step = 1;
-
-}
-
-void cmd_stack(int argc, char **argv)
-{
-    vector<pair<string, Thread*> > taskList;
-
-    const char *mapper[] = { "Inactive",
-                             "Ready",
-                             "Running",
-                             "WaitingDelay",
-                             "WaitingInterval",
-                             "WaitingOr",
-                             "WaitingAnd",
-                             "WaitingSempahore",
-                             "WaitingMailbox",
-                             "WaitingMutex"
-                           };
-
-    //simply add your task to the list...
-    taskList.push_back(make_pair((string)"AnalyticsLogger",  GLOBAL_analyticsLogger_thread));
-    taskList.push_back(make_pair((string)"ConfigHandler",    GLOBAL_configHandler_thread));
-    taskList.push_back(make_pair((string)"ControlTask",      GLOBAL_controlTask_thread));
-    taskList.push_back(make_pair((string)"ModbusMaster",     GLOBAL_modbusMaster_thread));
-    taskList.push_back(make_pair((string)"OutputTask",       GLOBAL_outputTask_thread));
-
-    for ( vector<pair<string, Thread*> >::iterator pos = taskList.begin();
-            pos != taskList.end(); ++ pos) {
-        printf("\r %-32s size/free/used/max = %5u/%5u/%5u/%5u\tpri=%u state=%-20s\n",
-               pos->first.c_str(),
-               pos->second->stack_size(),
-               pos->second->free_stack(),
-               pos->second->used_stack(),
-               pos->second->max_stack(),
-               pos->second->get_priority(),
-               mapper[pos->second->get_state()]);
-    }
-
-    printf("\r\n");
-}
-
-void cmd_version(int argc, char **argv)
-{
-    printf("\rversion: %u.%u.%u (%s)\n\r\n",    MAJOR_VERSION_NUMBER,
-           MINOR_VERSION_NUMBER,
-           PATCH_VERSION_NUMBER,
-           PROJECT_CODE_NAME);
-}
-
-void cmd_help(int argc, char **argv)
-{
-    UNUSED(argc);
-    UNUSED(argv);
-
-    const command_table_t *tblPtr = cmdlist;
-
-    while (tblPtr->command) {
-        printf("\r%-32s:\t%s\n", tblPtr->command, tblPtr->description);
-        tblPtr++;
-    }
-    printf("\r\n");
-}
-
-void cmd_v7(int argc, char **argv)
-{
-    struct v7 *v7 = v7_create();
-    v7_val_t exec_rc;
-    const char *js_code = "print(\"Hello World!\")";
-
-    v7_exec(v7, js_code, &exec_rc);
-    printf("\r->exec_rc = %d\r\n", (int)exec_rc);
-    v7_destroy(v7);
-}
-
-void cmd_json(int argc, char **argv)
-{
-    const char buf[] = {
-        "{"
-        "\"tag1\":\"value1\" ,"
-        "\"tag2\":\"value2\" "
-        "}"
-    };
-
-    cJSON *root = cJSON_Parse(buf);
-    printf("\rtag1 = %s\n", cJSON_GetObjectItem(root, "tag1")->valuestring);
-    printf("\rtag2 = %s\n", cJSON_GetObjectItem(root, "tag2")->valuestring);
-    cJSON_Delete(root);
-}
-
-/*****************************************************************************
- * Function:        cmd_outputs
- * Description:     display outputs
- ****************************************************************************/
-void cmd_outputs(int argc, char **argv)
-{
-    UNUSED(argc);
-    UNUSED(argv);
-
-    DisplayOutputs();
-}
-
-void cmd_formatFS(int argc, char **argv)
-{
-    mfs fs0(0xA0);
-    console.printf("\n\r\n\r[mFS] Formatting EEPROM.....................");
-    int bad_blocks = fs0.mkfs(true);
-    console.printf(" found %d bad blocks\r\n", bad_blocks);
-}
-
-void cmd_writeFile(int argc, char **argv)
-{
-    mfs fs0(0xA0);
-
-    char filename[FILENAME_LENGTH];
-    memset( filename, '\0', FILENAME_LENGTH );
-    strncpy( filename, argv[1], FILENAME_LENGTH-1 );
-
-    char *file_buf = (char*) malloc(MAX_FILE_SIZE);
-    memset( file_buf, '\0', MAX_FILE_SIZE);
-    snprintf(file_buf, MAX_FILE_SIZE, "1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890");
-    printf("%s\r\n", file_buf);
-    if( GLOBAL_mdot->saveUserFile( filename, (void *)file_buf, MAX_FILE_SIZE ) != true ) {
-        printf("Failed saveUserFile\r\n");
-    }
-    free(file_buf);
-
-    return;
-}
-
-void cmd_readFile(int argc, char **argv)
-{
-    char filename[FILENAME_LENGTH];
-    memset( filename, '\0', FILENAME_LENGTH );
-    strncpy( filename, argv[1], FILENAME_LENGTH-1 );
-    int file_size = (atoi(argv[2]));
-
-    char *file_buf = (char*) malloc(MAX_FILE_SIZE*2);
-    memset( file_buf, '\0', MAX_FILE_SIZE*2);
-    if( GLOBAL_mdot->readUserFile( filename, (void *)file_buf, file_size ) != true ) {
-        printf("Failed readUserFile\r\n");
-    }
-    printf("%s\r\n", file_buf);
-    free(file_buf);
-
-    return;
-}
-
-void cmd_deleteFile(int argc, char **argv)
-{
-    char filename[FILENAME_LENGTH];
-    memset( filename, '\0', FILENAME_LENGTH );
-    strncpy( filename, argv[1], FILENAME_LENGTH-1 );
-
-    if( GLOBAL_mdot->deleteUserFile( filename ) != true ) {
-        printf("Failed readUserFile\r\n");
-    }
-
-    return;
-}
-
-void cmd_lsFile( int argc, char ** argv )
-{
-
-    std::vector<std::string>::iterator file;
-    std::vector<std::string> file_list;
-    file_list = GLOBAL_mdot->listUserFiles();
-    for(file = file_list.begin(); file != file_list.end(); ++file) {
-        printf("%s\r\n", file->c_str() );
-    }
-
-    mfs fs0(0xA0);
-    // Get number of free blocks
-    char iFreeBlocks = fs0.free();
-    // Calculate amount of space used
-    unsigned int iSpaceUsed = VOL_SIZE - (iFreeBlocks*BS);
-    // Summary
-    printf("\n\r%u/%u kB space used, %u blocks free\n\r\n\r", iSpaceUsed/1024, VOL_SIZE/1024, iFreeBlocks);
-}
-
-/**
- * Serial read function.
- */
-int func_read(char *buf, int cnt)
-{
-    for (int i = 0; i < cnt; i++) {
-        buf[i] = console.getc();
-    }
-
-    return 0;
-}
-
-/**
- * Serial write function.
- */
-int func_write(const char *buf, int cnt)
-{
-    for (int i = 0; i < cnt; i++) {
-        console.putc(buf[i]);
-    }
-    return 0;
-}
-
-/**
- * Callback function for ntshell module.
- */
-int func_cb_ntshell(const char *text)
-{
-    return ntopt_parse(text, func_cb_ntopt);
-}
-
-/**
- * Callback function for ntopt module.
- */
-void func_cb_ntopt(int argc, char **argv)
-{
-    if (argc == 0) {
-        return;
-    }
-    int execnt = 0;
-    const command_table_t *p = &cmdlist[0];
-    while (p->command != NULL) {
-        if (strcmp(argv[0], p->command) == 0) {
-            p->func(argc, argv);
-            execnt++;
-        }
-        p++;
-    }
-    if (execnt == 0) {
-        printf("Command not found.\r\n");
-    }
-    wait_ms(250);
-}
-
-#if 0
-/*****************************************************************************
- * Function:        cmd_createSequence
- * Description:     create an administrative control
- *
- * @param           argc-> number of args
- * @param           argv-> control name, control type
- * @return          none
- *****************************************************************************/
-void cmd_createSequence(int argc, char **argv)
-{
-    char buf[MAX_FILE_SIZE*2];
-
-    // let's crreate the sequence control file
-    std::string filename = "control_seq_SLUG-DOSE.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"SLUG-DOSE\", "
-             "\"startTrigger\": \"v_slugSchedule\", "
-             "\"sequence\": "
-             "["
-             // START PRE-BLEED elements
-             "{ \"startTrigger\":\"v_alwaysTrue\", "
-             "\"actions\": "
-             "["
-             "{ \"action\": \"create\", \"id\": \"PRE-BLEED-SP\" }, "
-             "{ \"action\": \"create\", \"id\": \"GUARD-TM\" }"
-             "]," // end actions array
-             "\"stopTrigger\": \"v_PreBleedDone\" },"
-
-             // DELETE PRE-BLEED elements
-             "{ \"startTrigger\":\"v_alwaysTrue\", "
-             "\"actions\": "
-             "["
-             "{ \"action\": \"delete\", \"id\": \"PRE-BLEED-SP\" }, "
-             "{ \"action\": \"delete\", \"id\": \"GUARD-TM\" }"
-             "],"
-             "\"stopTrigger\": \"v_alwaysTrue\" },"
-
-             // SLUG-FEED elements
-             "{ \"startTrigger\":\"v_alwaysTrue\", "
-             "\"actions\": "
-             "["
-             "{ \"action\": \"create\", \"id\": \"SLUG-FEED-SP\" } "
-             "],"
-             "\"stopTrigger\": \"v_SlugFeedDone\" },"
-
-             // DELETE SLUG-FEED elements
-             "{ \"startTrigger\":\"v_alwaysTrue\", "
-             "\"actions\": "
-             "["
-             "{ \"action\": \"delete\", \"id\": \"SLUG-FEED-SP\" } "
-             "],"
-             "\"stopTrigger\": \"v_alwaysTrue\" }"
-             "] " // end sequence array
-             "} ");
-
-    printf("String Length=%d\r\n", strlen(buf) );
-    bool rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, sizeof(buf));
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-    // the pre-bleed setpoint control
-    snprintf(buf, sizeof(buf),
-             "{"
-             "\"id\": \"PRE-BLEED-SP\","
-             "\"priority\": \"750\", "
-             "\"input\": \"i_bdcond\" ,"
-             "\"output\": \"o_rly01\" ,"
-             "\"setpoint\": \"1750\", "
-             "\"prodfact\": \"\", "
-             "\"actingDir\": \"1\", "
-             "\"tol\": \"5\" "
-             "}");
-    filename = "seq_SLUG-DOSE_PRE-BLEED-SP.json";
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void*)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    // OUTPUT: Virtual Output - this is the START TRIGGER fro the control
-    filename = "vregister_slugSchedule.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"v_slugSchedule\", "
-             "\"value\": \"0\" "
-             "}");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    // VIRTUAL REGISTER: always True
-    filename = "vregister_alwaysTrue.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"v_alwaysTrue\", "
-             "\"value\": \"1\" "
-             "}");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    // VIRTUAL REGISTER: v_GuardTimer
-    filename = "vregister_GuardTimer.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"v_GuardTimer\", "
-             "\"value\": \"0\" "
-             "}");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    // VIRTUAL REGISTER: v_PreBleedDone
-    filename = "vreg_PreBleedDone.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"v_PreBleedDone\", "
-             "\"value\": \"0\" "
-             "}");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    // VIRTUAL REGISTER: v_SlugFeedDone
-    filename = "vreg_SlugFeedDone.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"v_SlugFeedDone\", "
-             "\"value\": \"0\" "
-             "}");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-
-    // CONTROL: GUARD-TIMER
-    filename = "seq_SLUG-DOSE_GUARD-TM.json";
-    snprintf(buf, sizeof(buf),
-             "{"
-             "\"id\":\"GUARD-TM\","
-             "\"output\":\"v_GuardTimer\","
-             "\"priority\":\"750\","
-             "\"day\":\"\","
-             "\"startHour\":\"\","
-             "\"startMin\":\"\","
-             "\"startSec\":\"\","
-             "\"week\":\"\","
-             "\"duration\":\"60\" "
-             "}");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void*)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("failed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    // the pre-bleed setpoint control
-    snprintf(buf, sizeof(buf),
-             "{"
-             "\"id\": \"SLUG-FEED-SP\","
-             "\"priority\": \"750\", "
-             "\"input\": \"i_orp01\" ,"
-             "\"output\": \"o_rly02\" ,"
-             "\"setpoint\": \"400\", "
-             "\"prodfact\": \"\", "
-             "\"actingDir\": \"1\", "
-             "\"tol\": \"5\" "
-             "}");
-    filename = "seq_SLUG-DOSE_SLUG-FEED-SP.json";
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void*)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-}
-#endif
-
-// PRELOAD command, used to create all the pertinent inputs, outputs, and
-// controls needed to achieve a basic cooling water application
-void cmd_preload(int argc, char **argv)
-{
-    UNUSED(argc);
-    UNUSED(argv);
-
-    char buf[MAX_FILE_SIZE];
-    bool rc;
-
-    // PRELOADER:
-    // JavaScripts:
-    //      js_noFlowDelay.js           // implement 10 minute on delay for flow switch
-    //      js_sum.js                   // sum two registers and store in register
-    //      js_diff.js                  // diff two registers and store in register
-    //      js_mul.js                   // mul two registers and store in register
-    //      js_div.js                   // div two registers and store in register
-    //      js_equ.js                   // equ set one register equal to another register
-    //
-    // Inputs:
-    //      input_i_bdcond.json         // conductivity probe
-    //      input_i_bdcond_temp.json    // conductivity probe : temperature
-    //      input_i_flowsw01.json       // flow switch
-    //      input_i_orp01.json          // ORP probe
-    //      input_i_ph01.json           // pH probe
-    //      input_i_ph01_temp.json      // pH probe : temperature
-    //      input_i_tag01.json          // tag (flu)
-    //      input_i_tra01.json          // Trasar
-    //
-    // Outputs:
-    //      output_o_rly01.json         // relay-1
-    //      output_o_rly02.json         // relay-2
-    //
-    // Standard Controls:
-    //      control_sp_i_bd01.json        // blowdown
-    //      control_sp_i_tra01.json       // Trasar
-    //
-    // Control Algorithms:
-    //      control_ca_eq1.json         // == 1
-    //      control_ca_eq129.json       // == 129
-    //
-    // Composite Controls:
-    //      control_comp_flow.json      // flow override
-    //      control_comp_lockout.json   // lockout blowdown
-
-    std::string filename = "ble_device_name.json";
-
-    snprintf(buf, sizeof(buf), "{\"id\":\"ICE-Ecolab\"}");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    filename = "vreg_const_1000.json";
-
-    // Constant: 1000.0
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":        \"v_Const_1000\", "
-             "\"value\":     \"1000.0\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-#ifdef EXECUTE_SCRIPT
-
-    filename = "vreg_noFlowDelaySig.json";
-
-    // Virtual Register: v_noFlowDelaySig
-    // Used to generate on delay timing for flow override.
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":        \"v_noFlowDelaySig\", "
-             "\"value\":     \"1\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    filename = "vreg_noFlowTimeStamp.json";
-
-    // Virtual Register: v_noFlowTimeStamp
-    // Used to generate on delay timing for flow override.
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":        \"v_noFlowTimeStamp\", "
-             "\"value\":     \"0\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    filename = "js_noFlowDelay.js";
-
-    // JavaScript: sum(a, b, c)
-    // a = Flow Input Signal - this is the signal we are doing the on delay timing for
-    // b = v_noFlowDelaySig - signal generated after No Flow condition exsits for 10 minutes
-    // c = v_noFlowTimeStamp - mark of when the no flow signal first started
-    //
-    // "\"args\":[{\"arg\":\"i_flowsw01\"},{\"arg\":\"v_noFlowDelaySig\"},{\"arg\":\"v_noFlowTimeStamp\"}],"
-    //
-    snprintf(buf, sizeof(buf),
-             "var noFlowDelay=function(a,b,c){"
-             "f_state=getRegister(a);"
-             "if(f_state==1){"
-             // we have flow on the skid, reset timestamp to 0
-             // and reset the "delayed" signal to indicate we have flow
-             "setRegister(c,0);"
-             "setRegister(b,f_state);"
-             "}else{"
-             // we don't have flow on the skid
-             "curr_time=getTime();"
-             "st_tstamp=getRegister(c);"
-             "if(st_tstamp==0) {"
-             // this is the 1st read of no-flow
-             // mark the start of the delay timing
-             "setRegister(c,curr_time);"
-             "}else{"
-             // determine how long we have been doing the delay timing.
-             "diff_time=curr_time-st_tstamp;"
-             //"print(' Delay='+diff_time+'\r');"
-             "if(diff_time>=600){"
-             // been doing the delay timing for at least 10 minutes
-             // set the delayed signal to equal the actual flow switch
-             "setRegister(b,f_state);"
-             "}"
-             "}"
-             "}"
-             "return 1;"
-             "};" );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    filename = "js_sum.js";
-
-    // JavaScript: sum(a, b, c)
-    snprintf(buf, sizeof(buf),
-             "var sum = function(a, b, c) {"
-             "res = (getRegister(a) + getRegister(b));"
-             "setRegister(c,res);"
-             "return res;"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    filename = "js_diff.js";
-
-    // JavaScript: diff(a, b, c)
-    snprintf(buf, sizeof(buf),
-             "var diff = function(a, b, c) {"
-             "res = (getRegister(a) - getRegister(b));"
-             "setRegister(c,res);"
-             "return res;"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    filename = "js_div.js";
-
-    // JavaScript: div(a, b, c)
-    snprintf(buf, sizeof(buf),
-             "var div = function(a, b, c) {"
-             "res = (getRegister(a) / getRegister(b));"
-             "setRegister(c,res);"
-             "return res;"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    filename = "js_mul.js";
-
-    // JavaScript: mul(a, b, c)
-    snprintf(buf, sizeof(buf),
-             "var mul = function(a, b, c) {"
-             "res = (getRegister(a) * getRegister(b));"
-             "setRegister(c,res);"
-             "return res;"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    filename = "js_equ.js";
-
-    // JavaScript: equ(a, b)
-    snprintf(buf, sizeof(buf),
-             "var equ = function(a, b) {"
-             "res = getRegister(a);"
-             "setRegister(b,res);"
-             "return res;"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    filename = "exe_js_div_cond_temp01.js";
-
-    // Execute JavaScript: DIV_COND_TEMP01
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":\"DIV_COND_TEMP01\","
-             "\"script\":\"div\","
-             "\"args\":[{\"arg\":\"i_cond_temp01\"},{\"arg\":\"v_Const_1000\"},{\"arg\":\"i_cond_temp01\"}]"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    filename = "exe_js_div_ph01.js";
-
-    // Execute JavaScript: DIV_PH01
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":\"DIV_PH01\","
-             "\"script\":\"div\","
-             "\"args\":[{\"arg\":\"i_ph01\"},{\"arg\":\"v_Const_1000\"},{\"arg\":\"i_ph01\"}]"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    filename = "exe_js_prebleed.js";
-    // Execute JavaScript: PREBLEED_DONE.json
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":\"PREBLEED_DONE\","
-             "\"script\":\"prebleed_done\","
-             // in: o_rly01
-             // in: v_pbTimer
-             // out" v_preBleedDone
-             "\"args\":[{\"arg\":\"o_rly01\"},{\"arg\":\"v_pbTimer\"},{\"arg\":\"v_preBleedDone\"}]"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    /*
-        filename = "exe_js_div_ph_temp01.js";
-
-        // Execute JavaScript: DIV_PH_TEMP01
-        snprintf(buf, sizeof(buf),
-                 "{ "
-                 "\"id\":\"DIV_PH_TEMP01\","
-                 "\"script\":\"div\","
-                 "\"args\":[{\"arg\":\"i_ph_temp01\"},{\"arg\":\"v_Const_1000\"},{\"arg\":\"i_ph_temp01\"}]"
-                 "};"
-                );
-        rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-        if ( rc != true ) {
-            printf("\rFailed to save %s\n", filename.c_str());
-            return;
-        } else {
-            printf("\r...generated %s\n", filename.c_str());
-        }
-
-        Thread::wait(1000);
-
-        filename = "exe_js_no_flow_delay.js";
-
-        // Execute JavaScript: NO_FLOW_DELAY
-        snprintf(buf, sizeof(buf),
-                 "{ "
-                 "\"id\":\"NO_FLOW_DELAY\","
-                 "\"script\":\"noFlowDelay\","
-                 "\"args\":[{\"arg\":\"i_flowsw01\"},{\"arg\":\"v_noFlowDelaySig\"},{\"arg\":\"v_noFlowTimeStamp\"}]"
-                 "};"
-                );
-        rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-        if ( rc != true ) {
-            printf("\rFailed to save %s\n", filename.c_str());
-            return;
-        } else {
-            printf("\r...generated %s\n", filename.c_str());
-        }
-
-        Thread::wait(1000);
-    */
-#endif
-
-    filename = "input_i_bdcond01.json";
-
-    // INPUT: Conductivity
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":        \"i_bdcond01\","
-             "\"name\":      \"Tower Conductivity\", "
-             "\"units\":     \"uS\","
-             "\"min\":       \"0\","
-             "\"max\":       \"6000\","
-             "\"node\":      \"21\","
-             "\"reg\":       \"18\","
-             "\"rtype\":     \"4\","
-             "\"type\":      \"1\","
-             "\"size\":      \"2\","
-             "\"order\":     \"2\","
-             "\"fmt\":       \"%%.2f\","
-             "\"cmd\":       \"\","
-             "\"args\":      [],"
-             "\"rfreq\":     \"5\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // INPUT: Conductivity Temperature
-    filename = "input_i_cond_temp01.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":\"i_cond_temp01\","
-             "\"name\":\"Temp Conductivity\","
-             "\"units\":\"C\","
-             "\"min\":\"0\","
-             "\"max\":\"80\","
-             "\"node\":\"21\","
-             "\"reg\":\"10\","
-             "\"rtype\":\"4\","
-             "\"type\":\"1\","
-             "\"size\":\"2\","
-             "\"order\":\"2\","
-             "\"fmt\":\"%%.2f\","
-             "\"cmd\":\"div\","
-             "\"args\":[{\"arg\":\"i_cond_temp01\"},{\"arg\":\"v_Const_1000\"},{\"arg\":\"i_cond_temp01\"}],"
-             "\"rfreq\":\"5\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // INPUT: Flow Switch
-    filename = "input_i_flowsw01.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":        \"i_flowsw01\","
-             "\"name\":      \"Flow\","
-             "\"units\":     \"\","
-             "\"min\":       \"0\","
-             "\"max\":       \"1\","
-             "\"node\":      \"0\","
-             "\"reg\":       \"1\","
-             "\"rtype\":     \"0\","
-             "\"type\":      \"3\","
-             "\"size\":      \"2\","
-             "\"order\":     \"0\","
-             "\"fmt\":       \"%%d\","
-             "\"cmd\":       \"\","
-             "\"args\":      [],"
-             "\"rfreq\":     \"5\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // INPUT: ORP
-    filename = "input_i_orp01.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":        \"i_orp01\","
-             "\"name\":      \"ORP\","
-             "\"units\":     \"mV\","
-             "\"min\":       \"0\","
-             "\"max\":       \"10\","
-             "\"node\":      \"23\","
-             "\"reg\":       \"14\","
-             "\"rtype\":     \"4\","
-             "\"type\":      \"1\","
-             "\"size\":      \"2\","
-             "\"order\":     \"2\","
-             "\"fmt\":       \"%%.2f\","
-             "\"cmd\":       \"\","
-             "\"args\":      [],"
-             "\"rfreq\":     \"5\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // INPUT: pH
-    filename = "input_i_ph01.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":\"i_ph01\","
-             "\"name\":\"pH\","
-             "\"units\":\"pH\","
-             "\"min\":\"0\","
-             "\"max\":\"10\","
-             "\"node\":\"22\","
-             "\"reg\":\"18\","
-             "\"rtype\":\"4\","
-             "\"type\":\"1\","
-             "\"size\":\"2\","
-             "\"order\":\"2\","
-             "\"fmt\":\"%%.2f\","
-             "\"cmd\":\"div\","
-             "\"args\":[{\"arg\":\"i_ph01\"},{\"arg\":\"v_Const_1000\"},{\"arg\":\"i_ph01\"}],"
-             "\"rfreq\":\"5\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // INPUT: pH Temperature
-    filename = "input_i_ph01_temp.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":\"i_ph_temp01\","
-             "\"name\":\"Temp pH\","
-             "\"units\":\"C\","
-             "\"min\":\"0\","
-             "\"max\":\"10\","
-             "\"node\":\"22\","
-             "\"reg\":\"10\","
-             "\"rtype\":\"4\","
-             "\"type\":\"1\","
-             "\"size\":\"2\","
-             "\"order\":\"2\","
-             "\"fmt\":\"%%.2f\","
-             "\"cmd\":\"div\","
-             "\"args\":[{\"arg\":\"i_ph_temp01\"},{\"arg\":\"v_Const_1000\"},{\"arg\":\"i_ph_temp01\"}],"
-             "\"rfreq\":\"5\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // INPUT: Tag
-    filename = "input_i_tag01.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":        \"i_tag01\","
-             "\"name\":      \"Tag\", "
-             "\"units\":     \"PPM\",    "
-             "\"min\":       \"0\",      "
-             "\"max\":       \"300\",    "
-             "\"node\":      \"1\",      "
-             "\"reg\":       \"11\",      "
-             "\"rtype\":     \"4\",      "
-             "\"type\":      \"0\",      "
-             "\"size\":      \"2\",      "
-             "\"order\":     \"2\",      "
-             "\"fmt\":       \"%%.2f\",   "
-             "\"cmd\":       \"\",       "
-             "\"args\":      [],"
-             "\"rfreq\":     \"5\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // INPUT: Trasar
-    filename = "input_i_tra01.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":        \"i_tra01\","
-             "\"name\":      \"Trasar\", "
-             "\"units\":     \"PPM\",    "
-             "\"min\":       \"0\",      "
-             "\"max\":       \"300\",    "
-             "\"node\":      \"1\",      "
-             "\"reg\":       \"9\",      "
-             "\"rtype\":     \"4\",      "
-             "\"type\":      \"0\",      "
-             "\"size\":      \"2\",      "
-             "\"order\":     \"2\",      "
-             "\"fmt\":       \"%%.2f\",   "
-             "\"cmd\":       \"\",       "
-             "\"args\":      [],"
-             "\"rfreq\":     \"5\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // COMMAND: Divide by 1000
-    filename = "cmd_div.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":\"%s\", "
-             "\"Operand\":\"%s\", "
-             "\"Operator\":\"%s\", "
-             "\"Constant\":\"%s\" } ", "div", "", "/", "1000.0");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // OUTPUT: Relay 01
-    filename = "output_o_rly01.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"o_rly01\", "
-             "\"name\": \"Blowdown\", "
-             "\"units\": \"\", "
-             "\"min\":  \"0\", "
-             "\"max\": \"300\", "
-             "\"node\": \"0\", "
-             "\"reg\": \"1\", "
-             "\"rtype\": \"1\", "
-             "\"type\": \"0\", "
-             "\"size\": \"2\", "
-             "\"order\": \"2\", "
-             "\"fmt\": \"%%.2f\", "
-             "\"cmd\": \"\", "
-             "\"args\": [], "
-             "\"rfreq\": \"5\", "
-             "\"toperiod\": \"0\", "
-             "\"scalelo\": \"0\", "
-             "\"scalehi\": \"100\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // OUTPUT: Relay 02
-    filename = "output_o_rly02.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"o_rly02\", "
-             "\"name\": \"3DTS86\", "
-             "\"units\": \"\", "
-             "\"min\":  \"0\", "
-             "\"max\": \"300\", "
-             "\"node\": \"0\", "
-             "\"reg\": \"2\", "
-             "\"rtype\": \"1\", "
-             "\"type\": \"0\", "
-             "\"size\": \"2\", "
-             "\"order\": \"2\", "
-             "\"fmt\": \"%%.2f\", "
-             "\"cmd\": \"\", "
-             "\"args\": [], "
-             "\"rfreq\": \"5\", "
-             "\"toperiod\": \"0\", "
-             "\"scalelo\": \"0\", "
-             "\"scalehi\": \"100\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // SETPOINT: Blowdown
-    filename = "control_sp_BLOWDOWN_01.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"BLOWDOWN_01\", "
-             "\"priority\": \"800\", "
-             "\"input\": \"i_bdcond01\", "
-             "\"output\": \"o_rly01\", "
-             "\"setpoint\": \"1800\", "
-             "\"prodfact\": \"\", "
-             "\"actingDir\": \"1\", "
-             "\"tol\": \"30\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // SETPOINT: Trasar
-    filename = "control_sp_INH_TRA_01.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"INH_TRA_01\", "
-             "\"priority\": \"800\", "
-             "\"input\": \"i_tra01\", "
-             "\"output\": \"o_rly02\", "
-             "\"setpoint\": \"130\", "
-             "\"prodfact\": \"100\", "
-             "\"actingDir\": \"0\", "
-             "\"tol\": \"4\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // ALGORITHM == 0
-    filename = "control_ca_EQUAL_TO_0.json";
-    snprintf(buf, sizeof(buf),
-             "{"
-             "\"id\":    \"EQUAL_TO_0\", "
-             "\"opr\":   \"0\", "
-             "\"op\":    \"==\", "
-             "\"true\":   \"responseA\", "
-             "\"false\":  \"nothing\" "
-             "}");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save user file %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // ALGORITHM == 129
-    filename = "control_ca_RELAY_ON.json";
-    snprintf(buf, sizeof(buf),
-             "{"
-             "\"id\":    \"RELAY_ON\", "
-             "\"opr\":   \"1\", "
-             "\"op\":    \"&\", "
-             "\"true\":   \"responseA\", "
-             "\"false\":  \"nothing\" "
-             "}");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save user file %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // FLOW
-    filename = "control_comp_FLOW.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":  \"FLOW\",  "
-             "\"tag\": \"i_flowsw01\",  "
-             "\"ca\":  \"EQUAL_TO_0\",   "
-             "\"priority\": \"300\", "
-             "\"entries\":  \"2\", "
-             "\"outputs\": [ "
-             "{"
-             "\"tag\": \"o_rly01\", "
-             "\"responseA\": \"fixed off\" "
-             "},"
-             "{"
-             "\"tag\": \"o_rly02\", "
-             "\"responseA\": \"fixed off\" "
-             "}"
-             "]"
-             "}"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save user file %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // LOCKOUT
-    filename = "control_comp_LOCKOUT_BD.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":  \"LOCKOUT_BD\",  "
-             "\"tag\": \"o_rly01\",  "
-             "\"ca\":  \"RELAY_ON\",   "
-             "\"priority\": \"400\", "
-             "\"entries\":  \"1\", "
-             "\"outputs\": [ "
-             "{"
-             "\"tag\": \"o_rly02\", "
-             "\"responseA\": \"fixed off\" "
-             "}"
-             "]"
-             "}"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save user file %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    filename = "control_fs_BLOWDOWN_FS.json";
-    snprintf(buf, sizeof(buf),
-             "{"
-             "\"id\":    \"BLOWDOWN_FS\", "
-             "\"input\":   \"i_bdcond01\", "
-             "\"output\":  \"o_rly01\", "
-             "\"priority\":\"600\", "
-             "\"lfsValue\":\"700\", "
-             "\"lfsDutyCycle\":\"0\", "
-             "\"lfsInterval\":\"1\", "
-             "\"hfsValue\":\"2700\", "
-             "\"hfsDutyCycle\":\"50\", "
-             "\"hfsInterval\":\"1\" "
-             "}");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to create %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-
-    Thread::wait(1000);
-
-    filename = "control_fs_TRASAR_FS.json";
-    snprintf(buf, sizeof(buf),
-             " {"
-             "\"id\":    \"TRASAR_FS\", "
-             "\"input\":   \"i_tra01\", "
-             "\"output\":  \"o_rly02\", "
-             "\"priority\":\"600\", "
-             "\"lfsValue\":\"70\", "
-             "\"lfsDutyCycle\":\"50\", "    // ON a minute, OFF a minute...
-             "\"lfsInterval\":\"2\", "
-             "\"hfsValue\":\"200\", "
-             "\"hfsDutyCycle\":\"0\", "
-             "\"hfsInterval\":\"2\" "
-             "}");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to create %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    // HOLDING REGISTER: Conductivity Calibration
-    filename = "hold_h_CondCmd_21.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":\"%s\", "
-             "\"node\":\"%s\", "
-             "\"sreg\":\"%s\", "
-             "\"nreg\":\"%s\", "
-             "\"order\":\"%s\" } ", "h_CondCmd_21", "21", "0", "3", "2");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // HOLDING REGISTER: pH Calibration
-    filename = "hold_h_phCmd_22.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":\"%s\", "
-             "\"node\":\"%s\", "
-             "\"sreg\":\"%s\", "
-             "\"nreg\":\"%s\", "
-             "\"order\":\"%s\" } ", "h_phCmd_22", "22", "0", "3", "2");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-
-    printf("\r\nIssue \"reset\" command to invoke changes\r\n\r\n\r\n");
-
-}
-
-/*****************************************************************************
- * Function:        cmd_cif
- * Description:     create input file
- *
- * @param           argc-> number of args
- * @param           argv-> filename
- * @return          none
- *****************************************************************************/
-void cmd_cif(int argc, char **argv)
-{
-    if ( argc != 6 ) {
-        printf("\rusage:   cif <fname> <input> <name> <node> <reg>\n");
-        printf("\rexample: cif input_i_tra01.json i_tra01 Trasar 5 2\n");
-        return;
-    }
-
-    char data_buf[MAX_FILE_SIZE];
-    snprintf(data_buf, sizeof(data_buf),
-             "{ "
-             "\"id\":       \"%s\", "
-             "\"name\":     \"%s\", "
-             "\"units\":    \"PPM\", "
-             "\"min\":      \"0\", "
-             "\"max\":      \"300\", "
-             "\"node\":     \"%s\", "
-             "\"reg\":      \"%s\", "
-             "\"rtype\":    \"1\", "
-             "\"type\":     \"0\", "
-             "\"size\":     \"2\", "
-             "\"order\":    \"2\", "
-             "\"rfreq\":    \"5\", "
-             "\"cmd\":       \"\","
-             "\"args\":      [],"
-             "\"fmt\":      \"%%.2f\" } ", argv[2], argv[3], argv[4], argv[5]);
-
-    bool status = GLOBAL_mdot->saveUserFile(argv[1], (void *)data_buf, MAX_FILE_SIZE);
-    if( status != true ) {
-        printf("(%d)save file failed, status=%d", __LINE__, status);
-    }
-
-    printf("Sending Mail To ModbusMasterMailBox, filename=%s", argv[1]);
-    ModbusMasterReq_t *mail = ModbusMasterMailBox.alloc();
-    mail->action = ACTION_READ_FILE;
-    strncpy( mail->msg, argv[1], (sizeof(mail->msg)-1));
-    ModbusMasterMailBox.put(mail);
-}
-
-/*****************************************************************************
- * Function:        cmd_destroy
- * Description:     destroy a control
- *
- * @param           argc-> number of arguments
- * @param           argv-> control name, control type
- * @return          none
- *****************************************************************************/
-void cmd_destroy(int argc, char **argv)
-{
-    if ( argc != 3 ) {
-        printf("\r\nusage: destroy-control [controlName] [controlType]\n");
-        printf("\rcontrolType-> 0=timer, 1=PID, 2=setpoint, 3=composite, 4=manual, 5=sequence, 6=failsafe, 7=sensor error\r\n");
-        return;
-    }
-
-    // send a message to the configuration handler to destroy the control
-    ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = ACTION_DESTROY;
-    msg->control = (Control_t) atoi(argv[2]);
-    strncpy(msg->controlFile, argv[1], sizeof(msg->controlFile)-1);
-
-    printf("%s: Sending a destroy request for control %s\r\n",
-           __func__, msg->controlFile);
-
-    ConfigHandlerMailBox.put(msg);
-    printf("\r\n");
-    return;
-}
-
-/*****************************************************************************
- * Function:        cmd_cof
- * Description:     create output file
- *
- * @param           argc-> number of args
- * @param           argv-> filename
- * @return          none
- *****************************************************************************/
-void cmd_cof(int argc, char **argv)
-{
-    // OUTPUT: Relay 01
-    char buf[MAX_FILE_SIZE];
-    std::string filename = "output_o_rly01.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"o_rly01\", "
-             "\"name\": \"Blowdown\", "
-             "\"units\": \"\", "
-             "\"min\":  \"0\", "
-             "\"max\": \"300\", "
-             "\"node\": \"0\", "
-             "\"reg\": \"1\", "
-             "\"rtype\": \"1\", "
-             "\"type\": \"0\", "
-             "\"size\": \"2\", "
-             "\"order\": \"2\", "
-             "\"fmt\": \"%%.2f\", "
-             "\"cmd\": \"\", "
-             "\"rfreq\": \"5\", "
-             "\"toperiod\": \"0\", "
-             "\"scalelo\": \"0\", "
-             "\"scalehi\": \"100\" }");
-    bool rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    Thread::wait(1000);
-
-    // OUTPUT: Relay 02
-    filename = "output_o_rly02.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"o_rly02\", "
-             "\"name\": \"3DTS86\", "
-             "\"units\": \"\", "
-             "\"min\":  \"0\", "
-             "\"max\": \"300\", "
-             "\"node\": \"0\", "
-             "\"reg\": \"2\", "
-             "\"rtype\": \"1\", "
-             "\"type\": \"0\", "
-             "\"size\": \"2\", "
-             "\"order\": \"2\", "
-             "\"fmt\": \"%%.2f\", "
-             "\"cmd\": \"\", "
-             "\"rfreq\": \"5\", "
-             "\"toperiod\": \"0\", "
-             "\"scalelo\": \"0\", "
-             "\"scalehi\": \"100\" }");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-}
-
-/*****************************************************************************
- * Function:        cmd_modmap
- * Description:     dump modbus register map
- *****************************************************************************/
-void cmd_modmap(int argc, char **argv)
-{
-
-    UNUSED(argc);
-    UNUSED(argv);
-    ModbusValue value;
-
-    std::map<std::string, ModbusRegister>::iterator iter;
-    for (iter = ModbusRegisterMap.begin(); iter != ModbusRegisterMap.end(); ++iter) {
-        ModbusMasterReadRegister( iter->first, &value );
-        printf("tag=%-24s node=%-4d reg=%-4d rtype=%-2d size=%-2d order=%-2d value=%-12.2f errflag=%-2d argc=%-2d arg[0]=%-24s\r\n",
-               iter->first.c_str(), iter->second.node, iter->second.reg,
-               iter->second.rtype, iter->second.size, iter->second.order,
-               value.value, value.errflag, iter->second.argc, iter->second.argv[0].c_str() );
-    }
-}
-
-void cmd_createVreg(int argc, char **argv)
-{
-    if ( argc != 4 ) {
-        printf("\rusage: create-vreg <filename> <vregId> <value>\n");
-        printf("\rusage: create-vreg vreg_alwaysTrue.json v_alwaysTrue 1\n");
-        return;
-    }
-
-    char buf[MAX_FILE_SIZE];
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":        \"%s\", "
-             "\"value\":     \"%s\" }", argv[2], argv[3]);
-    bool rc = GLOBAL_mdot->saveUserFile(argv[1], (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", argv[1]);
-        return;
-    } else {
-        printf("\r...generated %s\n", argv[1]);
-    }
-}
-
-//
-void cmd_createCAlg(int argc, char **argv)
-{
-    if ( argc != 1 ) {
-        printf("\rusage: create-ca control_ca_equal.json");
-        return;
-    }
-
-    char buf[MAX_FILE_SIZE];
-    std::string filename = "control_ca_eq1.json";
-    snprintf(buf, sizeof(buf),
-             " {"
-             "\"id\":    \"EQUAL_TO_1\", "
-             "\"opr\":   \"1\", "
-             "\"op\":    \"==\", "
-             "\"true\":   \"responseA\", "
-             "\"false\":  \"nothing\" "
-             "}");
-
-    bool rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save user file %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-// send a message to the configuration handler to create the control
-    ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = ACTION_CREATE;
-    msg->control = CONTROL_ALGORITHM;
-    strncpy(msg->controlFile, filename.c_str(), sizeof(msg->controlFile)-1);
-
-    ConfigHandlerMailBox.put(msg);
-
-    Thread::wait(2000);
-
-// == 129
-    filename = "control_ca_eq129.json";
-    snprintf(buf, sizeof(buf),
-             "{"
-             "\"id\":    \"EQUAL_TO_1\", "
-             "\"opr\":   \"1\", "
-             "\"op\":    \"==\", "
-             "\"true\":   \"responseA\", "
-             "\"false\":  \"nothing\" "
-             "}");
-
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save user file %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    // send a message to the configuration handler to create the control
-    msg  = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = ACTION_CREATE;
-    msg->control = CONTROL_ALGORITHM;
-    strncpy(msg->controlFile, "control_ca_greq1.json", sizeof(msg->controlFile)-1);
-
-    ConfigHandlerMailBox.put(msg);
-}
-
-/*****************************************************************************
- * Function:        cmd_createManual
- * Description:     create a manual control
- *
- * @param           argc-> number of args
- * @param           argv-> filename
- * @return          none
- *****************************************************************************/
-void cmd_createManual(int argc, char **argv)
-{
-    std::string relayState;
-    if ( argc != 6 ) {
-        printf("\rusage:   create-mn <filename> <id> <output> <state> <duration>\n");
-        printf("\rexample: create-mn control_mn_rly01.json man-1 o_rly1 on 30\r\n");
-        printf("\r<duration> specified in seconds, 0 for contiuous\n");
-        return;
-    }
-
-    string state(argv[4]);
-
-    if ( state == "on" ) {
-        relayState = "1";
-    } else if ( state == "off" ) {
-        relayState = "0";
-    } else {
-        printf("\r<state> must be on or off\r\n");
-        return;
-    }
-
-    unsigned int duration = atoi(argv[5]);
-    unsigned int type;
-    if ( duration == 0 ) {
-        type = MANUAL_CONTROL_TYPE_CONTINUOUS;
-    } else {
-        type = MANUAL_CONTROL_TYPE_TIMED;
-    }
-
-    char data_buf[MAX_FILE_SIZE];
-    snprintf(data_buf, sizeof(data_buf),
-             "{ "
-             "\"id\":           \"%s\",  "
-             "\"output\":       \"%s\",  "
-             "\"type\":         \"%d\",   "
-             "\"priority\":     \"100\", "
-             "\"duration\":     \"%d\",   "
-             "\"setpoint\":     \"0\",   "
-             "\"state\":        \"%s\",  "
-             "\"percent\":      \"100\"  }", argv[2], argv[3], type, duration, relayState.c_str()
-            );
-
-    bool status = GLOBAL_mdot->saveUserFile(argv[1], (void *)data_buf, MAX_FILE_SIZE);
-    if( status != true ) {
-        printf("(%d)save file failed, status=%d", __LINE__, status);
-        return;
-    }
-
-    // send a message to the configuration handler to create the control
-    ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = ACTION_CREATE;
-    msg->control = CONTROL_MANUAL;
-    strncpy(msg->controlFile, argv[1], sizeof(msg->controlFile)-1);
-
-    printf("%s: Sending a create request for control %s type = %u\r\n",
-           __func__, msg->controlFile, msg->control);
-
-    ConfigHandlerMailBox.put(msg);
-    printf("\r\n");
-    return;
-}
-
-/*****************************************************************************
- * Function:        cmd_createSError
- * Description:     create a sensoe error control
- *
- * @param           argc-> number of args
- * @param           argv-> filename
- * @return          none
- *****************************************************************************/
-void cmd_createSError(int argc, char **argv)
-{
-    if ( argc != 7 ) {
-        printf("\rusage:   create-se <filename> <id> <input> <output> <duty> <interval>\n");
-        printf("\rexample: create-se control_se_bdcond.json se-1 i_bdcond o_rly01 50 10\n");
-        return;
-    }
-
-    char data_buf[MAX_FILE_SIZE];
-    snprintf(data_buf, sizeof(data_buf),
-             "{ "
-             "\"id\":        \"%s\",  "
-             "\"input\":     \"%s\",  "
-             "\"output\":    \"%s\",  "
-             "\"priority\":  \"459\", "
-             "\"dutyCycle\": \"%d\",  "
-             "\"interval\":  \"%d\"  }",
-             argv[2], argv[3], argv[4], atoi(argv[5]), atoi(argv[6])
-            );
-
-    bool status = GLOBAL_mdot->saveUserFile(argv[1], (void *)data_buf, MAX_FILE_SIZE);
-    if( status != true ) {
-        printf("(%d)save file failed, status=%d", __LINE__, status);
-        return;
-    }
-
-    // send a message to the configuration handler to create the control
-    ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = ACTION_CREATE;
-    msg->control = CONTROL_SENSOR_ERROR;
-    strncpy(msg->controlFile, argv[1], sizeof(msg->controlFile)-1);
-
-    printf("%s: Sending a create request for sensor error control %s type = %u\r\n",
-           __func__, msg->controlFile, msg->control);
-
-    ConfigHandlerMailBox.put(msg);
-    printf("\r\n");
-    return;
-}
-
-/*****************************************************************************
- * Function:        cmd_createSetpoint
- * Description:     create control file
- *
- * @param           argc-> number of args
- * @param           argv-> filename
- * @return          none
- *****************************************************************************/
-void cmd_createSetpoint(int argc, char **argv)
-{
-    if ( argc != 8 ) {
-        printf("\rusage:   create-sp <filename> <id> <input> <output> <sp> <dir> <tol>\n");
-        printf("\rexample: create-sp control_sp_1.json bd i_cond o_rly1 2000 1 15\n");
-        return;
-    }
-
-    if ( strncmp(argv[1], CONTROL_SP_STR, strlen(CONTROL_SP_STR)) != 0 ) {
-        printf("\rFilename must be prefixed with control_sp_*\n");
-        return;
-    }
-
-    char data_buf[MAX_FILE_SIZE];
-    snprintf(data_buf, sizeof(data_buf),
-             "{ "
-             "\"id\":           \"%s\", "
-             "\"priority\":     \"800\","
-             "\"input\":        \"%s\", "
-             "\"output\":       \"%s\", "
-             "\"setpoint\":     \"%s\","
-             "\"prodfact\":     \"100\","
-             "\"actingDir\":    \"%s\", "
-             "\"halert\":       \"115\","
-             "\"lalert\":       \"85\", "
-             "\"hfs\":          \"130\","
-             "\"lfs\":          \"70\", "
-             "\"tol\":          \"%s\"  }", argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
-
-    bool status = GLOBAL_mdot->saveUserFile(argv[1], (void *)data_buf, MAX_FILE_SIZE);
-    if( status != true ) {
-        printf("(%d)save file failed, status=%d", __LINE__, status);
-        return;
-    }
-
-    // send a message to the configuration handler to create the control
-    ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = ACTION_CREATE;
-    msg->control = CONTROL_SETPOINT;
-    strncpy(msg->controlFile, argv[1], sizeof(msg->controlFile)-1);
-
-    printf("%s: Sending a create request for control %s type = %u\r\n",
-           __func__, msg->controlFile, msg->control);
-
-    ConfigHandlerMailBox.put(msg);
-    printf("\r\n");
-    return;
-}
-
-/*****************************************************************************
- * Function:        cmd_createTimer
- * Description:     create control file
- *
- * @param           argc-> number of args
- * @param           argv-> filename
- * @return          none
- *****************************************************************************/
-void cmd_createTimer(int argc, char **argv)
-{
-    if ( argc != 10 ) {
-        printf("\rusage:   create-tm <filename> <id> <output> <day> <hh> <mm> <ss> <duration> <week>\n");
-        printf("\rexample: create-tm control_tm_rly01.json o_rly01 wed 12 00 00 60\n");
-        printf("\r      <day> is sun, mon, tue, wed, thu, fri, sat\n");
-        printf("\r      <duration> is in seconds\n");
-        printf("\r      <week> is every, first, second, third, fourth, last, everyother\n\r\n");
-        return;
-    }
-
-    if ( strncmp(argv[1], CONTROL_TM_STR, strlen(CONTROL_TM_STR)) != 0 ) {
-        printf("\rFilename must be prefixed with control_tm_*\n");
-        return;
-    }
-
-    char data_buf[MAX_FILE_SIZE];
-    snprintf(data_buf, sizeof(data_buf),
-             "{ "
-             "\"id\":        \"%s\", "
-             "\"output\":    \"%s\", "
-             "\"priority\":  \"750\", "
-             "\"day\":       \"%s\", "
-             "\"startHour\": \"%s\", "
-             "\"startMin\":  \"%s\", "
-             "\"startSec\":  \"%s\", "
-             "\"duration\":  \"%s\", "
-             "\"week\":      \"%s\" } ",
-             argv[2], argv[3], argv[4], argv[5], argv[6],
-             argv[7], argv[8], argv[9]);
-
-
-    bool status = GLOBAL_mdot->saveUserFile(argv[1], (void *)data_buf, MAX_FILE_SIZE);
-    if( status != true ) {
-        printf("(%d)save file failed, status=%d", __LINE__, status);
-        return;
-    }
-
-    // send a message to the configuration handler to create the control
-    ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = ACTION_CREATE;
-    msg->control = CONTROL_TIMER;
-    strncpy(msg->controlFile, argv[1], sizeof(msg->controlFile)-1);
-
-    printf("%s: Sending a create request for control %s type = %u\r\n",
-           __func__, msg->controlFile, msg->control);
-
-    ConfigHandlerMailBox.put(msg);
-    printf("\r\n");
-    return;
-}
-
-void cmd_createFailsafe(int argc, char **argv)
-{
-    char buf[MAX_FILE_SIZE];
-    bool status;
-
-    std::string filename = "control_fs_rly01.json";
-    snprintf(buf, sizeof(buf),
-             "{"
-             "\"id\":    \"BLOWDOWN-FS\", "
-             "\"input\":   \"i_bdcond01\", "
-             "\"output\":  \"o_rly01\", "
-             "\"priority\":\"700\", "
-             "\"lfsValue\":\"700\", "
-             "\"lfsDutyCycle\":\"0\", "
-             "\"lfsInterval\":\"1\", "
-             "\"hfsValue\":\"2700\", "
-             "\"hfsDutyCycle\":\"50\", "
-             "\"hfsInterval\":\"1\" "
-             "}");
-
-    status = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( status != true ) {
-        printf("\rFailed to create %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r   created %s\n", filename.c_str());
-    }
-
-    ConfigMessage_t *msg = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = ACTION_CREATE;
-    msg->control = CONTROL_FAILSAFE;
-    strncpy(msg->controlFile, filename.c_str(), sizeof(msg->controlFile)-1);
-
-    printf("%s: Sending a create request for control %s type = %u\r\n",
-           __func__, msg->controlFile, msg->control);
-
-    ConfigHandlerMailBox.put(msg);
-    Thread::wait(1000);
-
-    filename = "control_fs_rly02.json";
-    snprintf(buf, sizeof(buf),
-             " {"
-             "\"id\":    \"TRASAR-FS\", "
-             "\"input\":   \"i_tra01\", "
-             "\"output\":  \"o_rly02\", "
-             "\"priority\":\"700\", "
-             "\"lfsValue\":\"70\", "
-             "\"lfsDutyCycle\":\"20\", "
-             "\"lfsInterval\":\"15\", "
-             "\"hfsValue\":\"200\", "
-             "\"hfsDutyCycle\":\"0\", "
-             "\"hfsInterval\":\"15\" "
-             "}");
-
-    status = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( status != true ) {
-        printf("\rFailed to create %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r   created %s\n", filename.c_str());
-    }
-
-    msg = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = ACTION_CREATE;
-    msg->control = CONTROL_FAILSAFE;
-    strncpy(msg->controlFile, filename.c_str(), sizeof(msg->controlFile)-1);
-
-    printf("%s: Sending a create request for control %s type = %u\r\n",
-           __func__, msg->controlFile, msg->control);
-
-    ConfigHandlerMailBox.put(msg);
-}
-
-/*****************************************************************************
- * Function:        cmd_logLevel
- * Description:     get or set the current log-level
- *
- * @param           argc (not used)
- * @param           argv (not used)
- * @return          none
- *****************************************************************************/
-void cmd_logLevel(int argc, char **argv)
-{
-    uint8_t logLevel = 0;
-
-    const char *mapper[] = { "NONE",
-                             "FATAL",
-                             "ERROR",
-                             "WARNING",
-                             "INFO",
-                             "DEBUG",
-                             "TRACE"
-                           };
-
-    if ( argc == 1 ) {
-        printf("\r  current log-level set to %s\r\n",
-               mapper[ICELog::getLogLevel()]);
-        goto usage;
-    }
-
-    if ( argc != 2 ) {
-usage:
-        printf("\rusage: log-level [0-6]\n");
-        printf("\r   0 = NONE\n");
-        printf("\r   1 = FATAL\n");
-        printf("\r   2 = ERROR\n");
-        printf("\r   3 = WARNING\n");
-        printf("\r   4 = INFO\n");
-        printf("\r   5 = DEBUG\n");
-        printf("\r   6 = TRACE\r\n");
-        return;
-    }
-
-    logLevel = atoi(argv[1]);
-    if ( logLevel > 6 )
-        goto usage;
-
-    // reassign the log level
-    printf("...setting log-level to %s\r\n", mapper[logLevel]);
-    ICELog::setLogLevel(logLevel);
-    printf("\r\n");
-}
-
-
-/*****************************************************************************
- * Function:        cmd_vregmap
- * Description:     show virtual register map
- *
- * @param           argc-> number of args
- * @param           argv-> filename
- * @return          none
- *****************************************************************************/
-extern std::map<std::string,RegisterValue> RegisterValueMap;
-
-void cmd_vregmap(int argc, char **argv)
-{
-    UNUSED(argc);
-    UNUSED(argv);
-
-    std::map<std::string, RegisterValue>::iterator iter;
-    for (iter = RegisterValueMap.begin(); iter != RegisterValueMap.end(); ++iter) {
-        printf("id=%s, value=%.4f\r\n", iter->first.c_str(), iter->second.float_value );
-    }
-}
-
-void cmd_testPreBleed(int argc, char **argv)
-{
-    char buf[MAX_FILE_SIZE];
-
-    // OUTPUT (virtual): variable set to TRUE when pre-bleed is done
-    std::string filename = "vreg_preBleedDone.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"v_preBleedDone\", "
-             "\"value\": \"0\" "
-             "}");
-    bool rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    // OUTPUT (virtual): variable is set to TRUE while pre-bleed time is running via timer control
-    filename = "vreg_pbTimer.json";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"v_pbTimer\", "
-             "\"value\": \"0\" "
-             "}");
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    // JavaScript Executor:
-    //   IN: o_rly01
-    //   IN: v_pbTimer
-    //   OUT: v_preBleedDone
-    //
-    // Description: execute the js_nor_regs() script with arguments o_rly01
-    //              and v_pbTimer; stores the result in v_preBleedDone
-    //
-    filename = "exe_js_prebleed_done.js";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":\"PREBLEED_DONE\","
-             "\"script\":\"nor_regs\","
-             "\"args\":[{\"arg\":\"o_rly01\"},{\"arg\":\"v_pbTimer\"},{\"arg\":\"v_preBleedDone\"}]"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-
-    // JavaScript: nor_regs(a, b) => c
-    filename = "js_nor_regs.js";
-    snprintf(buf, sizeof(buf),
-             "var nor_regs = function(a, b, c) {"
-             "res1 = getRegister(a);"
-             "res2 = getRegister(b);"
-             "if ( res1 == 0 || res2 == 0 ) { setRegister(c, 1); }"
-             "return 1;"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-}
-
-/*****************************************************************************
- * Function:        cmd_setTime
- * Description:     set real-time clock
- *
- * @param           argc-> number of args
- * @param           argv-> input
- * @return          none
- *****************************************************************************/
-
-
-void cmd_setTime(int argc, char **argv)
-{
-    if ( argc != 7 ) {
-        printf("\rusage:   set-time <yyyy> <mm> <dd> <hh> <mm> <ss>\n");
-        printf("\rexample: set-time 2017 1 24 9 0 0\r\n");
-        return;
-    }
-
-    int isc = atoi( argv[6] );                              // sec
-    int imn = atoi( argv[5] );                              // min
-    int ihr = atoi( argv[4] );                              // hour
-    int idy = atoi( argv[3] );                              // idy
-    int imo = atoi( argv[2] );                              // imo
-    int iyr = atoi( argv[1] );                              // year
-
-//    printf( "\r\n%s:%d: sec(0x%x) min(0x%x) hour(0x%x) day(0x%x) mon(0x%x) year(0x%x)\r\n", __func__, __LINE__, isc, imn, ihr, idy, imo, iyr );
-
-    rtc_set_time(iyr, imo, idy, ihr, imn, isc);
-}
-void getTime()
-{
-    char time_string[80];
-    struct tm   rtc_time;
-    struct tm * ts;
-    time_t      curr_sec;
-    int         year = 0;
-
-    rtc_get_time(&year, &rtc_time.tm_mon, &rtc_time.tm_mday, &rtc_time.tm_hour, &rtc_time.tm_min, &rtc_time.tm_sec);
-//    printf( "\r\n%s:%d:sec(0x%x) min(0x%x) hour(0x%x) day(0x%x) mon(0x%x) year(0x%x)\r\n", __func__, __LINE__, rtc_time.tm_sec, rtc_time.tm_min, rtc_time.tm_hour, rtc_time.tm_mday, rtc_time.tm_mon, year );
-
-    rtc_time.tm_mon = rtc_time.tm_mon - 1;
-    rtc_time.tm_year = year - 1900;
-    curr_sec =  mktime( &rtc_time );
-
-    ts = localtime(&curr_sec);
-    strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ts);
-
-    printf("%s\r\n", time_string);
-}
-
-void cmd_getTime(int argc, char **argv)
-{
-    getTime();
-}
-
--- a/ICE-Application/src/CommandParser/cmd.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * ===============================================================
- *  Natural Tiny Shell (NT-Shell) Application example.
- *  Version 0.0.6
- * ===============================================================
- * Copyright (c) 2010-2011 Shinichiro Nakamura
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- * ===============================================================
- */
-
-#ifndef CMD_H
-#define CMD_H
-
-// debug commands 
-void cmd_debug_fs       (int argc, char **argv);
-void cmd_debug_mn       (int argc, char **argv);
-void cmd_debug_se       (int argc, char **argv);
-void cmd_debug_seq      (int argc, char **argv);
-void cmd_debug_sp       (int argc, char **argv);
-void cmd_debug_tm       (int argc, char **argv);
-//
-
-void cmd_cif            (int argc, char **argv);
-void cmd_cof            (int argc, char **argv);
-void cmd_destroy        (int argc, char **argv);
-
-void cmd_createCAlg     (int argc, char **argv); 
-void cmd_createManual   (int argc, char **artv);
-void cmd_createSError   (int argc, char **argv);
-void cmd_createSetpoint (int argc, char **argv);
-void cmd_createTimer    (int argc, char **argv); 
-void cmd_createFailsafe (int argc, char **argv);
-void cmd_createVreg     (int argc, char **argv);
-void cmd_createSeq      (int argc, char **argv);
-
-void cmd_version        (int argc, char **argv);
-void cmd_help           (int argc, char **argv);
-void cmd_json           (int argc, char **argv);
-void cmd_v7             (int argc, char **argv);
-void cmd_heap_stats     (int argc, char **argv);
-void cmd_outputs        (int argc, char **argv);
-void cmd_stack          (int argc, char **argv);
-void cmd_readFile       (int argc, char **argv);
-void cmd_writeFile      (int argc, char **argv);
-void cmd_deleteFile     (int argc, char **argv);
-void cmd_lsFile         (int argc, char **argv);
-void cmd_formatFS       (int argc, char **argv);
-void cmd_createSequence (int argc, char **argv);
-void cmd_preload        (int argc, char **argv);
-void cmd_reset          (int argc, char **argv);
-void cmd_modmap         (int argc, char **argv);
-void cmd_ShowControls   (int argc, char **argv);
-void cmd_ShowTimers     (int argc, char **argv);
-void cmd_ShowManuals    (int argc, char **argv);
-void cmd_ShowFailsafes  (int argc, char **argv);
-void cmd_ShowComposites (int argc, char **argv);
-void cmd_ShowSensorErrors(int argc, char **argv);
-void cmd_ShowSetpoints  (int argc, char **argv);
-void cmd_ShowSequences  (int argc, char **argv);
-void cmd_ShowAlgorithms (int argc, char **argv);
-void cmd_simerr         (int argc, char **argv);
-void cmd_simin          (int argc, char **argv);
-void cmd_simall         (int argc, char **argv);
-void cmd_logLevel       (int argc, char **argv);
-void cmd_testLog        (int argc, char **argv);
-void cmd_spiTest        (int argc, char **argv);
-void cmd_vregmap        (int argc, char **argv);
-void cmd_testPreBleed   (int argc, char **argv);
-void cmd_getTime        (int argc, char **argv);
-void cmd_setTime        (int argc, char **argv);
-
-#endif
--- a/ICE-Application/src/CommandParser/cmd_utils.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-#include "cmd_utils.h"
-#include "global.h"
-
-
-// create a virtual register
-void createVregFile(VregFile_t &vreg_f)
-{
-    char buf[MAX_FILE_SIZE];
-    snprintf(buf, sizeof(buf),
-        "{" 
-        "\"id\":\"%s\", "
-        "\"value\":\"%f\" }", vreg_f.id.c_str(), vreg_f.value);
-    bool rc = GLOBAL_mdot->saveUserFile(vreg_f.fname.c_str(), 
-                                       (void*)buf,
-                                       MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", vreg_f.fname.c_str());
-    } else { 
-        printf("\r...generated %s\n", vreg_f.fname.c_str());
-    }
-}
-
-// create an input/output file
-void createIOFile(IOFile_t &io_file)
-{
-    char buf[MAX_FILE_SIZE];
-    snprintf(buf, sizeof(buf),
-           "{ "
-             "\"id\":       \"%s\", "
-             "\"name\":     \"%s\", "
-             "\"units\":    \"PPM\", "
-             "\"min\":      \"%f\", "
-             "\"max\":      \"%f\", "
-             "\"node\":     \"%u\", "
-             "\"reg\":      \"%u\", "
-             "\"rtype\":    \"%u\", "
-             "\"type\":     \"%u\", "
-             "\"size\":     \"%u\", "
-             "\"order\":    \"%u\", "
-             "\"rfreq\":    \"%u\", "
-             "\"cmd\":       \"\","
-             "\"args\":      [],"
-             "\"fmt\":      \"%%.2f\" } ",  io_file.id.c_str(),
-                                            io_file.name.c_str(),
-                                            io_file.min,
-                                            io_file.max,
-                                            io_file.node,
-                                            io_file.reg,
-                                            io_file.rtype,
-                                            io_file.type,
-                                            io_file.size,
-                                            io_file.order,
-                                            io_file.rfreq);
-    bool rc = GLOBAL_mdot->saveUserFile(io_file.fname.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if( rc != true ) {
-        printf("(%d)save file failed, status=%d", __LINE__, rc);
-    } else {
-        printf("\r...generated %s\n", io_file.fname.c_str());
-    }
-}
-
-// create a setpoint control file
-void createSetpointControlFile(SetpointControlFile_t &sp_f)
-{
-    char buf[MAX_FILE_SIZE];
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":           \"%s\", "
-             "\"priority\":     \"%u\","
-             "\"input\":        \"%s\", "
-             "\"output\":       \"%s\", "
-             "\"setpoint\":     \"%f\","
-             "\"prodfact\":     \"%f\","
-             "\"actingDir\":    \"%u\", "
-             "\"tol\":          \"%f\"  }", sp_f.id.c_str(), 
-                                            sp_f.priority,
-                                            sp_f.input.c_str(),
-                                            sp_f.output.c_str(),
-                                            sp_f.setpoint,
-                                            sp_f.productFactor,
-                                            sp_f.actingDir,
-                                            sp_f.tolerance);
-    bool rc = GLOBAL_mdot->saveUserFile(sp_f.controlFile.c_str(), 
-                                            (void *)buf, MAX_FILE_SIZE);
-    if( rc != true ) {
-        printf("(%d)save file failed, status=%d", __LINE__, rc);
-        return;
-    } else {
-        printf("\r...generated %s\n", sp_f.controlFile.c_str());
-    }
-}
-
-// create a timer control file 
-void createTimerControlFile(TimerControlFile_t &timer_f)
-{
-    char buf[MAX_FILE_SIZE];
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":        \"%s\", "
-             "\"output\":    \"%s\", "
-             "\"priority\":  \"%u\", "
-             "\"day\":       \"%u\", "
-             "\"startHour\": \"%u\", "
-             "\"startMin\":  \"%u\", "
-             "\"startSec\":  \"%u\", "
-             "\"duration\":  \"%u\", "
-             "\"week\":      \"%u\" } ",
-                timer_f.id.c_str(),
-                timer_f.output.c_str(),
-                timer_f.priority,
-                timer_f.day,
-                timer_f.startHour,
-                timer_f.startMin,
-                timer_f.startSec,
-                timer_f.duration,
-                timer_f.week);
-    bool rc = GLOBAL_mdot->saveUserFile(timer_f.controlFile.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if( rc != true ) {
-        printf("(%d)save file failed, status=%d", __LINE__, rc);
-        return;
-    } else {
-        printf("\r...generated %s\n", timer_f.controlFile.c_str());
-    }
-}
-
--- a/ICE-Application/src/CommandParser/cmd_utils.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-#ifndef CMDUTILS_H
-#define CMDUTILS_H
-
-#include "global.h"
-#include <string>
-#include <stdio.h>
-#include <stdint.h>
-
-typedef struct vregFile_tag {
-    std::string     fname;
-    std::string     id;
-    float           value;
-} VregFile_t;
-
-typedef struct ioFile_tag {
-    std::string     fname;
-    std::string     id;
-    std::string     name;
-    float           min;
-    float           max;
-    unsigned char   node;
-    unsigned char   rtype;
-    unsigned char   type;
-    unsigned char   size;
-    unsigned char   order;
-    unsigned char   rfreq;
-    unsigned char   argc;
-    uint32_t        reg;
-    RegisterType_t  regType;
-} IOFile_t;
-
-typedef struct setpointControlFile_tag {
-    std::string     controlFile;
-    std::string     id;                 // control identifier
-    int             priority;           // control priority
-    std::string     input;              // control input
-    std::string     output;             // control output
-    double          setpoint;           // setpoint value
-    double          productFactor;      // unused
-    bool            actingDir;          // acting direction
-    double          tolerance;  
-
-} SetpointControlFile_t;
-
-typedef struct timerControlFile_tag {
-    std::string     controlFile;        // file containing control data
-    std::string     id;                 // timer identifier
-    std::string     output;             // output to control
-    unsigned int    priority;           // control priority
-    unsigned int    day;
-    unsigned int    startHour;          // start hour (0-23)
-    unsigned int    startMin;           // start minute (0-59)
-    unsigned int    startSec;           // start second (0-59)
-    unsigned int    duration;           // duration in seconds
-    unsigned int    week;               // every week, first week, ...
-} TimerControlFile_t;    
-
-void createVregFile(VregFile_t&);
-void createIOFile(IOFile_t&);
-void createSetpointControlFile(SetpointControlFile_t&);
-void createTimerControlFile(TimerControlFile_t&);
-#endif
--- a/ICE-Application/src/CommandParser/sequence.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-#include "cmd_utils.h"
-#include "cmd.h"
-
-void cmd_createSequence(int argc, char **argv)
-{
-    // 
-    // This command will test the basic functionality of a sequence control
-    // 
-    // virtual registers:
-    //      v_slugSchedule      -> start trigger for the slug dose
-    //      v_alwaysTrue        -> always set to 1
-    //      v_preBleedDone      -> set to 1 when prebleed is done
-    //      v_slugFeedDone      -> set to 1 when the slug-feed is done
-    //      v_pbTimer           -> prebleed timer control output, set to 0 when finished
-    //      
-    // physical outputs:
-    //      o_rly01             -> blowdown controlled (higher pri setpoint)
-    //      o_rly02             -> slug dose relay
-    //
-    // scripts:
-    //      js_nor_regs.js      -> performs nor operation of args a, b
-    //      
-    // timer controls:
-    //      pb-guard-timer      -> prebleed guard timer
-    //      
-    // setpoint controls:
-    //      pre-bleed-sp        -> pre-bleed setpoint control
-    //      slug-dose-sp        -> slug dose setpoint control
-  
-    // vreg: slug-schedule
-    VregFile_t vreg;
-    vreg.fname  = "vreg_slugScheduleOn.json";
-    vreg.id     = "v_slugScheduleOn";
-    vreg.value  = 0;                            
-    createVregFile(vreg);
-   
-    // vreg: always true
-    vreg.fname  = "vreg_alwaysTrue.json";
-    vreg.id     = "v_alwaysTrue";
-    vreg.value  = 1;
-    createVregFile(vreg);
-    
-    // vreg: pre-bleed done
-    vreg.fname  = "vreg_preBleedDone.json";
-    vreg.id     = "v_preBleedDone";
-    vreg.value  = 0;
-    createVregFile(vreg);
-    
-    // vreg: slug-feed done
-    vreg.fname = "vreg_slugFeedDone.json";
-    vreg.id    = "v_slugFeedDone";
-    vreg.value = 0;
-    createVregFile(vreg);
-    
-    // vreg: prebleed timer
-    vreg.fname = "vreg_pbTimer.json";
-    vreg.id    = "v_preBleedTimer";
-    vreg.value = 0;
-    createVregFile(vreg);
-    
-    // Blowdown Control ---------------------------------------------------
-    // input
-    IOFile_t io_file;
-    memset(&io_file, 0, sizeof(IOFile_t));
-    io_file.fname     = "input_i_bdcond01.json";
-    io_file.id        = "i_bdcond01";
-    io_file.name      = "Tower Conductivity";
-    io_file.min       = 0;
-    io_file.max       = 6000;
-    io_file.node      = 21;
-    io_file.reg       = 5;
-    io_file.type      = 0;
-    io_file.regType   = REG_TYPE_INPUT;
-    io_file.size      = 2;
-    io_file.order     = 2;
-    io_file.rfreq     = 5;
-    createIOFile(io_file);
-    
-    // output
-    memset(&io_file, 0, sizeof(io_file));
-    io_file.fname       = "output_o_rly01.json";
-    io_file.id          = "o_rly01";
-    io_file.name        = "Blowdown-Relay";
-    io_file.min         = 0;
-    io_file.max         = 100;
-    io_file.node        = 0;
-    io_file.reg         = 1;
-    io_file.type        = 0;
-    io_file.regType     = REG_TYPE_OUTPUT;
-    io_file.size        = 2;
-    io_file.order       = 2;
-    io_file.rfreq       = 5;
-    createIOFile(io_file);
-    
-    // blowdown control
-    SetpointControlFile_t sp;
-    memset(&sp, 0, sizeof(sp));
-    sp.controlFile  = "seq_slug_dose_control_sp_prebleed.json";
-    sp.actingDir    = 1;
-    sp.id           = "blowdown";
-    sp.setpoint     = 1750;
-    sp.input        = "i_bdcond01";
-    sp.output       = "o_rly01";
-    sp.priority     = 750;              // this is higher pri than a regular sp control
-    sp.tolerance    = 30;
-    createSetpointControlFile(sp);
-    
-    // timer 
-    TimerControlFile_t timer;
-    memset(&timer, 0, sizeof(timer));
-    timer.controlFile   = "seq_slug_dose_control_tm_prebleed.json";
-    timer.priority      = 750;
-    timer.output        = "v_preBleedTimer";
-    timer.id            = "prebleed";
-    timer.duration      = 30;
-    timer.day           = 0;
-    createTimerControlFile(timer);
-    
-    // sequence control
-    std::string filename = "control_seq_slug_dose.json";
-    char buf[MAX_FILE_SIZE * 3];
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\": \"slug_dose\", "
-             "\"startTrigger\": \"v_slugScheduleOn\", "
-             "\"sequence\": "
-             "["
-             // START PRE-BLEED elements
-             "{ \"startTrigger\":\"v_alwaysTrue\", "
-             "\"actions\": "
-             "["
-                "{ \"action\": \"assign\",   \"id\": \"v_preBleedTimer\", \"val\":\"1.0\" },"
-                "{ \"action\": \"assign\",   \"id\": \"v_preBleedDone\",  \"val\":\"0.0\" },"
-                "{ \"action\": \"createsp\", \"id\": \"prebleed\" },"
-                "{ \"action\": \"createtm\", \"id\": \"prebleed\" }"
-             "]," // end actions array
-             "\"stopTrigger\": \"v_preBleedDone\" },"
-
-             // DELETE PRE-BLEED elements
-             "{ \"startTrigger\":\"v_alwaysTrue\", "
-             "\"actions\": "
-             "["
-                "{ \"action\": \"deletesp\", \"id\": \"prebleed\" }, "
-                "{ \"action\": \"deletetm\", \"id\": \"prebleed\" }"
-             "],"
-             "\"stopTrigger\": \"v_alwaysTrue\" }"
-#if 0 
-             // SLUG-FEED elements
-             "{ \"startTrigger\":\"v_alwaysTrue\", "
-             "\"actions\": "
-             "["
-                "{ \"action\": \"createsp\", \"id\": \"SLUG-FEED-SP\" } "
-             "],"
-             "\"stopTrigger\": \"v_slugFeedDone\" },"
-
-             // DELETE SLUG-FEED elements
-             "{ \"startTrigger\":\"v_alwaysTrue\", "
-             "\"actions\": "
-             "["
-                "{ \"action\": \"deletesp\", \"id\": \"SLUG-FEED-SP\" } "
-             "],"
-             "\"stopTrigger\": \"v_alwaysTrue\" }"
-#endif
-             "] " // end sequence array
-             "} ");
-    printf("\r[DEBUG: bytes = %u\n", (size_t)strlen(buf));
-    bool rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, sizeof(buf));
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-    
-    // JavaScript Executor: 
-    //   IN: o_rly01
-    //   IN: v_preBleedTimer
-    //   OUT: v_preBleedDone
-    // 
-    // Description: execute the js_nor_regs() script with arguments o_rly01 
-    //              and v_pbTimer; stores the result in v_preBleedDone
-    //
-    filename = "exe_js_prebleed_done.js";
-    snprintf(buf, sizeof(buf),
-             "{ "
-             "\"id\":\"PREBLEED_DONE\","
-             "\"script\":\"nor_regs\","
-             "\"args\":[{\"arg\":\"o_rly01\"},{\"arg\":\"v_preBleedTimer\"},{\"arg\":\"v_preBleedDone\"}]"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-    
-    // JavaScript: nor_regs(a, b) => c
-    filename = "js_nor_regs.js";
-    snprintf(buf, sizeof(buf),
-             "var nor_regs = function(a, b, c) {"
-             "res1 = getRegister(a);"
-             "res2 = getRegister(b);"
-             "if ( res1 == 0 || res2 == 0 ) { setRegister(c, 1); }"
-             "return 1;"
-             "};"
-            );
-    rc = GLOBAL_mdot->saveUserFile(filename.c_str(), (void *)buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("\rFailed to save %s\n", filename.c_str());
-        return;
-    } else {
-        printf("\r...generated %s\n", filename.c_str());
-    }
-}
--- a/ICE-Application/src/ConfigurationHandler/Algorithms/CompositeAlgorithm.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/******************************************************************************
- *
- * File:                CompositeAlgorithm.cpp
- * Desciption:          source for the ICE Composite Algorithm
- *
- *****************************************************************************/
-#include "global.h"
-#include "cJSON.h"
-#include "ICELog.h"
-#include "CompositeAlgorithm.h"
-//#include "../add-ons/MTSLog/MTSLog.h"
-
-//
-// method:          load
-// description:     load the pertinents from the control file
-//
-// @param[in]       _controlFile : name of the control file
-// @param[out]      none
-// @return          none
-//
-bool CompositeAlgorithm::load(const std::string _controlFile)
-{
-    controlFile = _controlFile;
-
-    // read the data into a buffer
-    char dataBuf[MAX_FILE_SIZE];
-    bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
-    if ( rc != true ) {
-        logError("%s: failed to read %s", __func__, controlFile.c_str());
-        // caller should destroy the object
-        return false;
-    }
-
-    // parse the JSON data
-    cJSON * root = cJSON_Parse(dataBuf);
-
-    if ( !cJSON_HasObjectItem(root, "id") ||
-            !cJSON_HasObjectItem(root, "opr") ||
-            !cJSON_HasObjectItem(root, "op")  ||
-            !cJSON_HasObjectItem(root, "true") ||
-            !cJSON_HasObjectItem(root, "false") ) {
-        logError("%s: control file is missing expected tags", __func__);
-        cJSON_Delete(root);
-        return false;
-    }
-
-    id          = cJSON_GetObjectItem(root, "id")->valuestring;
-    opr         = cJSON_GetObjectItem(root, "opr")->valuestring;
-    op          = cJSON_GetObjectItem(root, "op")->valuestring;
-    resultTrue  = cJSON_GetObjectItem(root, "true")->valuestring;
-    resultFalse = cJSON_GetObjectItem(root, "false")->valuestring;
-
-    cJSON_Delete(root);
-    return true;
-}
-
-//
-// method:              validateControlData
-// description:         validate the JSON formatted string
-//
-// @param[in]           buf -> JSON formatted string
-// @param[out]          none
-// @return              true if valid; false otherwise
-//
-bool CompositeAlgorithm::validateControlData(const char *buf)
-{
-    bool rc = true;
-    cJSON * root = cJSON_Parse(buf);
-
-    if ( !cJSON_HasObjectItem(root, "id") ||
-            !cJSON_HasObjectItem(root, "opr") ||
-            !cJSON_HasObjectItem(root, "op")  ||
-            !cJSON_HasObjectItem(root, "true") ||
-            !cJSON_HasObjectItem(root, "false") ) {
-        logError("%s: control file is missing expected tags", __func__);
-        rc = false;
-    }
-    cJSON_Delete(root);
-    return rc;
-}
-
-//
-// method:              copyControlData
-// description:         copy JSON data to control data
-//
-// @param[in]           buf -> JSON formatted string
-// @param[out]          none
-// @return              
-void CompositeAlgorithm::copyControlData(const char *buf)
-{
-    cJSON * root = cJSON_Parse(buf);
-    
-    id          = cJSON_GetObjectItem(root, "id")->valuestring;
-    opr         = cJSON_GetObjectItem(root, "opr")->valuestring;
-    op          = cJSON_GetObjectItem(root, "op")->valuestring;
-    resultTrue  = cJSON_GetObjectItem(root, "true")->valuestring;
-    resultFalse = cJSON_GetObjectItem(root, "false")->valuestring;
-
-    cJSON_Delete(root);
-}
-
-//
-// method:          display
-// description:     display the pertinents
-//
-// @param[in]       none
-// @param[out]      none
-// @return          none
-//
-void CompositeAlgorithm::display(void)
-{
-    printf("\r          id : %s\n", id.c_str());
-    printf("\r         opr : %s\n", opr.c_str());
-    printf("\r          op : %s\n", op.c_str());
-    printf("\r        true : %s\n", resultTrue.c_str());
-    printf("\r       false : %s\n", resultFalse.c_str());
-    printf("\r\n");
-}
\ No newline at end of file
--- a/ICE-Application/src/ConfigurationHandler/Algorithms/CompositeAlgorithm.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/******************************************************************************
- * 
- * File:                CompositeAlgorithm.h
- * Desciption:          interface file for the ICE Composite Algorithm
- *
- *****************************************************************************/
-#ifndef COMPOSITEALGORITHM_H
-#define COMPOSITEALGORITHM_H
-
-#include <stdio.h>
-#include <string>
-
-class CompositeAlgorithm
-{
-private:
-    std::string     controlFile;        // the control file
-    std::string     id;                 // algorithm id
-    std::string     tag;                // input (real or virtual)
-    std::string     opr;                // right operand
-    std::string     op;                 // operation to perform (+, -, ==, etc.)
-    std::string     resultTrue;         // what to do when true
-    std::string     resultFalse;        // what to do when false 
-    
-    bool        validateControlData(const char *buf);
-    void        copyControlData(const char *buf);
-public:
-    CompositeAlgorithm() {}
-    ~CompositeAlgorithm() {
-        printf("%s invoked", __func__);
-    }
-
-    bool load(const std::string);
-
-    void display(void);
-
-    std::string getId(void) const {
-        return id;
-    }
-    std::string getTag(void) const { 
-    return tag;
-    }
-    std::string getOpr(void) const { return opr; }
-    std::string getOp(void) const { return op; }
-    std::string getResultTrue(void) const { return resultTrue; }
-    std::string getResultFalse(void) const { return resultFalse; }
-};
-
-#endif
-
--- a/ICE-Application/src/ConfigurationHandler/ConfigurationHandler.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,733 +0,0 @@
-/******************************************************************************
- *
- * File:                ConfigurationHandler.cpp
- * Desciption:          source for the ICE Configuration Handler
- *
- *****************************************************************************/
-#include "ConfigurationHandler.h"
-#include "global.h"
-#include "SetpointControl.h"
-#include "TimerControl.h"
-#include "CompositeControl.h"
-#include "CompositeAlgorithm.h"
-#include "SensorErrorControl.h"
-#include "cJSON.h"
-#include "utilities.h"
-#include "ICELog.h"
-#include <algorithm>
-#include <stdlib.h>
-   
-//
-// The control maps
-//StringPIDMap            PIDTable;               // PID control object table
-StringSetpointMap       setpointTable;          // setpoint control object table
-StringTimerMap          timerTable;             // timer control object table
-StringManualMap         manualTable;            // manual control object table
-StringCompositeMap      compositeTable;         // composite control object table
-StringFailsafeMap       failsafeTable;          // failsafe control object table
-StringAlgorithmMap      algorithmTable;         // composite control algorithms
-StringSequenceMap       sequenceTable;          // sequence control object table
-StringSensorErrorMap    sensorErrorTable;       // sensor error object table
-
-Mutex                   manual_mutex;
-Mutex                   setpoint_mutex;
-Mutex                   timer_mutex;
-Mutex                   failsafe_mutex;
-Mutex                   composite_mutex;
-Mutex                   sequence_mutex;
-Mutex                   sensorError_mutex;
-
-// local function prototypes
-static int loadPersistentControls(void);        // load the controls on flash
-
-// local helper functions
-static int createControl(const ConfigMessage_t *msg);
-static int modifyControl(const ConfigMessage_t *msg);
-static int destroyControl(const ConfigMessage_t *msg);
-
-static unsigned int getManualControlType(const char *filename);
-
-/*****************************************************************************
- * Function:            ConfigurationHandler()
- * Description:         The ICE Configuration Handler
- *
- * @param               args (unused)
- * @return              none
- *****************************************************************************/
-void ConfigurationHandler(void const *args)
-{
-    (void)(args);
-#ifdef LOAD_PERSISTENT_CONFIGURATIONS
-    loadPersistentControls();
-#endif 
-    osSignalSet(mainThreadId, sig_control_continue);
-
-    printf("\rConfigurationHandler has started...\n");
-
-    while ( true ) {
-        // wait for an event
-        osEvent evt = ConfigHandlerMailBox.get();
-        if (evt.status == osEventMail) {
-            ConfigMessage_t *msg = (ConfigMessage_t*) evt.value.p;
-
-            logInfo("\r%s: msg->action      = %d\n", __func__, msg->action);
-            logInfo("\r%s: msg->control     = %d\n", __func__, msg->control);
-            logInfo("\r%s: msg->controlFile = %s\n", __func__, msg->controlFile);
-
-            switch ( msg->action ) {
-                case ACTION_CREATE: {
-                    (void)createControl(msg);
-                    break;
-                }
-                case ACTION_MODIFY: {
-                    (void)modifyControl(msg);
-                    break;
-                }
-                case ACTION_DESTROY: {
-                    (void)destroyControl(msg);
-                    break;
-                }
-                default:
-                    break;
-            }
-
-            // free the message
-            ConfigHandlerMailBox.free(msg);
-        }
-    }
-}
-
-//
-// function:        ConfigurationHandler_showSetpointControls
-// description:     display contents of the setpoint control table
-//
-void ConfigurationHandler_showSetpointControls(void)
-{
-    setpoint_mutex.lock();
-    if ( !setpointTable.empty() ) {
-        printf("\r\n");
-        StringSetpointMap::const_iterator pos;
-        for ( pos = setpointTable.begin(); pos != setpointTable.end(); ++pos ) {
-            pos->second->display();
-        }
-    }
-    setpoint_mutex.unlock();
-}
-
-//
-// function:        ConfigurationHandler_showManualControls
-// description:     display contents of the manual control table
-//
-void ConfigurationHandler_showManualControls(void)
-{
-    manual_mutex.lock();
-    if ( !manualTable.empty() ) {
-        printf("\r\n");
-        StringManualMap::const_iterator pos;
-        for ( pos = manualTable.begin(); pos != manualTable.end(); ++pos ) {
-            pos->second->display();
-        }
-    }
-    manual_mutex.unlock();
-}
-
-//
-// function:        ConfigurationHandler_showTimerControls
-// description:     display contents of the timer control table
-//
-void ConfigurationHandler_showTimerControls(void)
-{
-    timer_mutex.lock();
-    if ( !timerTable.empty() ) {
-        printf("\r\n");
-        StringTimerMap::const_iterator pos;
-        for ( pos = timerTable.begin(); pos != timerTable.end(); ++pos ) {
-            pos->second->display();
-        }
-    }
-    timer_mutex.unlock();
-}
-
-//
-// function:        ConfigurationHandler_showCompositeControls
-// description:     display contents of the composite control table
-//
-void ConfigurationHandler_showCompositeControls(void )
-{
-    composite_mutex.lock();
-    if ( !compositeTable.empty() ) {
-        printf("\r\n");
-        StringCompositeMap::const_iterator pos;
-        for ( pos = compositeTable.begin(); pos != compositeTable.end(); ++pos) {
-            pos->second->display();
-        }
-    }
-    composite_mutex.unlock();
-}
-
-//
-// function:        ConfigurationHandler_showFailsafeControls
-// description:     display contents of the failsafe control table
-//
-// @param[in]       none
-// @param[out]      none
-// @return          none
-//
-void ConfigurationHandler_showFailsafeControls(void)
-{
-    failsafe_mutex.lock();
-    if ( !failsafeTable.empty() ) {
-        printf("\r\n");
-        StringFailsafeMap::const_iterator pos;
-        for ( pos = failsafeTable.begin(); pos != failsafeTable.end(); ++pos ) {
-            pos->second->display();
-        }
-    }
-    failsafe_mutex.unlock();
-}
-
-//
-// function:        ConfigurationHandler_showFailsafeControls
-// description:     display contents of the failsafe control table
-//
-// @param[in]       none
-// @param[out]      none
-// @return          none
-//
-void ConfigurationHandler_showSensorErrorControls(void)
-{
-    sensorError_mutex.lock();
-    if ( !sensorErrorTable.empty() ) {
-        printf("\r\n");
-        StringSensorErrorMap::const_iterator pos;
-        for ( pos = sensorErrorTable.begin(); pos != sensorErrorTable.end(); ++pos ) {
-            pos->second->display();
-        }
-    }
-    sensorError_mutex.unlock();
-}
-
-
-//
-// function:            ConfigurationHandler_showSequenceControls()
-// description:         display contents of the sequence control table
-//
-// @param[in]           none
-// @param[out]          none
-// @return              none
-//
-void ConfigurationHandler_showSequenceControls(void)
-{
-    sequence_mutex.lock();
-    if ( !sequenceTable.empty() ) {
-        printf("\r\n");
-        StringSequenceMap::const_iterator pos;
-        for ( pos = sequenceTable.begin(); pos != sequenceTable.end(); ++pos ) {
-            pos->second->display();
-        }
-    }
-    sequence_mutex.unlock();
-}
-
-//
-// Function:            ConfigurationHandler_showControls()
-// Description:         show the controls
-//
-// @param[in]           none
-// @return              none
-//
-void ConfigurationHandler_showControls(void)
-{
-    ConfigurationHandler_showSetpointControls();
-    ConfigurationHandler_showTimerControls();
-    ConfigurationHandler_showManualControls();
-    ConfigurationHandler_showFailsafeControls();
-    ConfigurationHandler_showCompositeControls();
-    ConfigurationHandler_showSequenceControls();
-    ConfigurationHandler_showSensorErrorControls();
-    // TODO: PID controls
-}
-
-//
-// function:        ConfigurationHandler_showAlgorithms
-// description:     display the control algorithms
-//
-// @param           none
-// @return          none
-//
-void ConfigurationHandler_showAlgorithms(void)
-{
-    StringAlgorithmMap::const_iterator pos;
-
-    for ( pos = algorithmTable.begin(); pos != algorithmTable.end(); ++pos ) {
-        pos->second->display();
-    }
-}
-
-/*****************************************************************************
- * Function:            loadPersistentControls()
- * Description:         load persistent controls from flash
- *
- * @param               none
- * @return              none
- *****************************************************************************/
-static int loadPersistentControls(void)
-{
-    static bool loaded = false;
-
-    if ( !loaded ) {        // lazy protection
-
-        printf("\rLoading persistent controls: \n");
-        std::vector<std::string> file_list = GLOBAL_mdot->listUserFiles();
-
-        loaded = true;
-
-        for (std::vector<std::string>::const_iterator i = file_list.begin(); i != file_list.end(); ++i) {
-            if( strncmp( i->c_str(), CONTROL_SP_STR, strlen(CONTROL_SP_STR)) == 0 ) {
-                // create the setpoint control
-                ConfigMessage_t msg;
-                msg.control = CONTROL_SETPOINT;
-                strncpy(msg.controlFile, i->c_str(), sizeof(msg.controlFile));
-                int rc = createControl(&msg);
-                if ( rc != 0 ) {
-                    logError("%s: failed to load %s", __func__, msg.controlFile);
-                } else {
-                    printf("\r   setpoint control %s loaded.\n", msg.controlFile);
-                }
-            } else if ( strncmp( i->c_str(), CONTROL_TM_STR, strlen(CONTROL_TM_STR)) == 0  ) {
-                // create the timer control
-                ConfigMessage_t msg;
-                msg.control = CONTROL_TIMER;
-                strncpy(msg.controlFile, i->c_str(), sizeof(msg.controlFile));
-                int rc = createControl(&msg);
-                if ( rc != 0 ) {
-                    logError("%s: failed to load %s", __func__, msg.controlFile);
-
-                } else {
-                    printf("\r   timer control %s loaded.\n", msg.controlFile);
-                }
-            } else if ( strncmp( i->c_str(), CONTROL_COMP_STR, strlen(CONTROL_COMP_STR)) == 0 ) {
-                ConfigMessage_t msg;
-                msg.control = CONTROL_COMPOSITE;
-                strncpy(msg.controlFile, i->c_str(), sizeof(msg.controlFile));
-                int rc = createControl(&msg);
-                if ( rc != 0 ) {
-                    logError("%s: failed to load %s\n", __func__, msg.controlFile);
-                } else {
-                    printf("\r   composite control %s loaded.\n", msg.controlFile);
-                }
-            } else if ( strncmp( i->c_str(), CONTROL_CA_STR, strlen(CONTROL_CA_STR)) == 0 ) {
-                ConfigMessage_t msg;
-                msg.control = CONTROL_ALGORITHM;
-                strncpy(msg.controlFile, i->c_str(), sizeof(msg.controlFile));
-                int rc = createControl(&msg);
-                if ( rc != 0 ) {
-                    logError("%s: failed to load %s\n", __func__, msg.controlFile);
-                } else {
-                    printf("\r   algorithmic control %s loaded.\n", msg.controlFile);
-                }
-            } else if ( strncmp( i->c_str(), CONTROL_FS_STR, strlen(CONTROL_FS_STR)) == 0 ) {
-                ConfigMessage_t msg;
-                msg.control = CONTROL_FAILSAFE;
-                strncpy(msg.controlFile, i->c_str(), sizeof(msg.controlFile));
-                int rc = createControl(&msg);
-                if ( rc != 0 ) {
-                    logError("%s: failed to load %s\n", __func__, msg.controlFile);
-                } else {
-                    printf("\r   failsafe control %s loaded.\n", msg.controlFile);
-                }
-            } else if ( strncmp( i->c_str(), CONTROL_PID_STR, strlen(CONTROL_PID_STR)) == 0 ) {
-                // TODO:
-            } else if ( strncmp( i->c_str(), CONTROL_MN_STR, strlen(CONTROL_MN_STR)) == 0 ) {
-                // TODO: delete any timed manual control, not continuous...
-                if  ( getManualControlType(i->c_str()) == MANUAL_CONTROL_TYPE_CONTINUOUS ) {
-                    ConfigMessage_t msg;
-                    msg.control = CONTROL_MANUAL;
-                    strncpy(msg.controlFile, i->c_str(), sizeof(msg.controlFile));
-                    int rc = createControl(&msg);
-                    if ( rc != 0 ) {
-                        logError("%s: failed to load %s\n", __func__, msg.controlFile);
-                    } else {
-                        printf("\r   manual control %s loaded\n", msg.controlFile);
-                    }
-                } else {
-                    GLOBAL_mdot->deleteUserFile(i->c_str());
-                }
-            } else if ( strncmp( i->c_str(), CONTROL_SEQ_STR, strlen(CONTROL_SEQ_STR)) == 0 ) {
-                ConfigMessage_t msg;
-                msg.control = CONTROL_SEQUENCE;
-                strncpy(msg.controlFile, i->c_str(), sizeof(msg.controlFile));
-                int rc = createControl(&msg);
-                if ( rc != 0 ) {
-                    logError("%s: failed to load %s\n", __func__, msg.controlFile);
-                } else {
-                    printf("\r   sequence control %s loaded.\n", msg.controlFile);
-                }
-            } else if ( strncmp( i->c_str(), CONTROL_SE_STR, strlen(CONTROL_SE_STR)) == 0 ) {
-                ConfigMessage_t msg;
-                msg.control = CONTROL_SENSOR_ERROR;
-                strncpy(msg.controlFile, i->c_str(), sizeof(msg.controlFile));
-                int rc = createControl(&msg);
-                if ( rc != 0 ) {
-                    logError("%s: failed to load %s\n", __func__, msg.controlFile);
-                } else {
-                    printf("\r    sensor error control %s loaded.\n", msg.controlFile);
-                }
-            } else {
-                logInfo("\rNot A Control File%s\r\n", i->c_str());
-                // not a control file
-            }
-        }
-    }
-    return 0;
-}
-
-/*****************************************************************************
- * Function:            createControl()
- * Description:         creates a new control
- *
- * @param               none
- * @return              0 on success; -1 otherwise
- *****************************************************************************/
-static int createControl(const ConfigMessage_t *msg)
-{
-    int status = 0;
-
-    logInfo("\r%s invoked\n", __func__);
-
-    switch (msg->control) {
-        case CONTROL_SETPOINT: {
-            SetpointControl *setpointControl = new SetpointControl;
-            bool rc = setpointControl->load(msg->controlFile);
-            if ( rc != true ) {
-                logError("%s: failed to load %s\n", __func__, msg->controlFile);
-                delete setpointControl;
-                GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                status = -1;
-            } else {
-                setpoint_mutex.lock();
-                setpointTable[msg->controlFile] = setpointControl;
-                setpoint_mutex.unlock();
-                setpointControl->start();
-            }
-            break;
-        }
-        case CONTROL_TIMER: {
-            TimerControl *timerControl = new TimerControl;
-            bool rc = timerControl->load(msg->controlFile);
-            if ( rc != true ) {
-                logError("%s: failed to load %s\n", __func__, msg->controlFile);
-                delete timerControl;
-                GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                status = -1;
-            } else {
-                timer_mutex.lock();
-                timerTable[msg->controlFile] = timerControl;
-                timer_mutex.unlock();
-                timerControl->start();
-            }
-            break;
-        }
-        case CONTROL_MANUAL: {
-            ManualControl *manualControl = new ManualControl;
-            bool rc = manualControl->load(msg->controlFile);
-            if ( rc != true ) {
-                logError("%s: failed to load %s\n", __func__, msg->controlFile);
-                delete manualControl;
-                GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                status = -1;
-
-            } else {
-                manual_mutex.lock();
-                manualTable[msg->controlFile] = manualControl;
-                manual_mutex.unlock();
-                manualControl-> start();
-            }
-            break;
-        }
-
-        case CONTROL_PID: {
-            // TODO: PID
-            break;
-        }
-        case CONTROL_COMPOSITE: {
-            CompositeControl *compositeControl = new CompositeControl;
-            bool rc = compositeControl->load(msg->controlFile);
-            if ( rc != true ) {
-                logError("%s: failed to load %s\n", __func__, msg->controlFile);
-                delete compositeControl;
-                GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                status = -1;
-            } else {
-                composite_mutex.lock();
-                compositeTable[msg->controlFile] = compositeControl;
-                composite_mutex.unlock();
-                compositeControl->start();
-            }
-            break;
-        }
-
-        case CONTROL_SEQUENCE: {
-            SequenceControl *sequenceControl = new SequenceControl;
-            bool rc = sequenceControl->load(msg->controlFile);
-            if ( rc != true ) {
-                logError("%s: failed to load %s", __func__, msg->controlFile);
-                delete sequenceControl;
-                //GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                status = -1;
-            } else {
-                sequence_mutex.lock();
-                sequenceTable[msg->controlFile] = sequenceControl;
-                sequence_mutex.unlock();
-                sequenceControl->start();
-            }
-            break;
-        }
-        case CONTROL_FAILSAFE: {
-            FailsafeControl *failsafeControl = new FailsafeControl;
-            bool rc = failsafeControl->load(msg->controlFile);
-            if ( rc != true ) {
-                logError("%s: failed to load %s\n", __func__, msg->controlFile);
-                delete failsafeControl;
-                GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                status = -1;
-            } else {
-                failsafe_mutex.lock();
-                failsafeTable[msg->controlFile] = failsafeControl;
-                failsafe_mutex.unlock();
-                failsafeControl->start();
-            }
-            break;
-        }
-        case CONTROL_SENSOR_ERROR: {
-            SensorErrorControl *sensorErrorControl = new SensorErrorControl;
-            bool rc = sensorErrorControl->load(msg->controlFile);
-            if ( rc != true ) {
-                logError("%s: failed to load %s\n", __func__, msg->controlFile);
-                delete sensorErrorControl;
-                GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                status = -1;
-            } else {
-                sensorError_mutex.lock();
-                sensorErrorTable[msg->controlFile] = sensorErrorControl;
-                sensorError_mutex.unlock();
-                sensorErrorControl->start();
-            }
-            break;
-        }
-        case CONTROL_ALGORITHM: {
-            CompositeAlgorithm *compositeAlgorithm = new CompositeAlgorithm;
-            bool rc = compositeAlgorithm->load(msg->controlFile);
-            if ( rc != true ) {
-                logError("%s: failed to load %s\n", __func__, msg->controlFile);
-                status = -1;
-            } else {
-                // add this algorithm to the table
-                algorithmTable[compositeAlgorithm->getId()] = compositeAlgorithm;
-            }
-            break;
-        }
-        default:
-            logInfo("\r%s: control type %d not implemented yet...\n",
-                    __func__, msg->control);
-            break;
-    }
-    return status;
-}
-
-/*****************************************************************************
- * Function:            modifyControl()
- * Description:         modifies a control
- *
- * @param               msg
- * @return              none
- *****************************************************************************/
-static int modifyControl(const ConfigMessage_t *msg)
-{
-    logInfo("\r%s invoked\n", __func__);
-
-    switch (msg->control) {
-        case CONTROL_SETPOINT: {
-            // find the control in the table
-            StringSetpointMap::const_iterator pos;
-            setpoint_mutex.lock();
-            pos = setpointTable.find(msg->controlFile);
-            if ( pos != setpointTable.end() ) {
-                bool rc = pos->second->load(msg->controlFile);
-                if ( rc != true ) {
-                    logError("\rFailed to reload the setpoint control %s\n", msg->controlFile);
-                } else {
-                    logInfo("\rReloaded the setpoint control %s\n", msg->controlFile);
-                }
-            }
-            setpoint_mutex.unlock();
-            break;
-        }
-        case CONTROL_MANUAL: {
-            // find the manual control in the table
-            StringManualMap::const_iterator pos;
-            manual_mutex.lock();
-            pos = manualTable.find(msg->controlFile);
-            if ( pos != manualTable.end() ) {
-                bool rc = pos->second->load(msg->controlFile);
-                if ( rc != true ) {
-                    logError("\rFailed to reload the manual control %s\n", msg->controlFile);
-                } else {
-                    logInfo("\rReloaded the manual control %s\n", msg->controlFile);
-                }
-            }
-            manual_mutex.unlock();
-            break;
-        }
-        default:
-            logError("%s: unknown control %d\n", __func__, msg->control);
-            break;
-    }
-
-    return 0;
-}
-
-/*****************************************************************************
- * Function:            destroyControl()
- * Description:         destroys a controls
- *
- * @param               msg
- * @return              none
- *****************************************************************************/
-static int destroyControl(const ConfigMessage_t *msg)
-{
-    logInfo("\r%s invoked\n", __func__);
-
-    switch ( msg->control ) {
-        case CONTROL_SETPOINT: {
-            StringSetpointMap::iterator pos;
-            setpoint_mutex.lock();
-            pos = setpointTable.find(msg->controlFile);
-            if ( pos != setpointTable.end() ) {
-                if ( !Util_isSequenceSubControl(msg->controlFile) ) {
-                    GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                }
-                logInfo("%s: deleted %s", __func__, msg->controlFile);
-                pos->second->unregisterControl();
-                delete (pos->second);
-                setpointTable.erase(pos);
-            } else {
-                logError("%s: unable to find %s\n", __func__, msg->controlFile);
-            }
-            setpoint_mutex.unlock();
-            break;
-        }
-        case CONTROL_TIMER: {
-            StringTimerMap::iterator pos;
-            timer_mutex.lock();
-            pos = timerTable.find(msg->controlFile);
-            if ( pos != timerTable.end() ) {
-                if ( !Util_isSequenceSubControl(msg->controlFile) ) {
-                    GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                }
-                logInfo("%s: deleted %s", __func__, msg->controlFile);
-                pos->second->unregisterControl();
-                delete (pos->second);
-                timerTable.erase(pos);
-            } else {
-                logError("%s: unable to find %s\n", __func__, msg->controlFile);
-            }
-            timer_mutex.unlock();
-            break;
-        }
-        case CONTROL_MANUAL: {
-            StringManualMap::iterator pos;
-            manual_mutex.lock();
-            pos = manualTable.find(msg->controlFile);
-            if ( pos != manualTable.end() ) {
-                GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                logInfo("%s: deleted %s", __func__, msg->controlFile);
-                // unregister with the output thread
-                pos->second->unregisterControl();
-                delete (pos->second);
-                manualTable.erase(pos);
-            } else {
-                logError("%s: unable to find %s", __func__, msg->controlFile);
-            }
-            manual_mutex.unlock();
-            break;
-        }
-        case CONTROL_COMPOSITE: {
-            StringCompositeMap::iterator pos;
-            composite_mutex.lock();
-            pos = compositeTable.find(msg->controlFile);
-            if ( pos != compositeTable.end() ) {
-                GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                logInfo("%s: deleted %s", __func__, msg->controlFile);
-                pos->second->unregisterControls();
-                delete (pos->second);
-                compositeTable.erase(pos);
-            } else {
-                logError("%s: unable to find %s", __func__, msg->controlFile);
-            }
-            composite_mutex.unlock();
-            break;
-        }
-        case CONTROL_SEQUENCE: {
-            StringSequenceMap::iterator pos;
-            sequence_mutex.lock();
-            pos = sequenceTable.find(msg->controlFile);
-            if ( pos != sequenceTable.end() ) {
-                GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                logInfo("%s: delete %s", __func__, msg->controlFile);
-                // TODO:
-                // pos->second->unregisterControls();
-                delete (pos->second);
-                sequenceTable.erase(pos);
-            } else {
-                logError("%s: unable to find %s", __func__, msg->controlFile);
-            }
-            sequence_mutex.unlock();
-            break;
-        }
-        case CONTROL_SENSOR_ERROR: {
-            StringSensorErrorMap::iterator pos;
-            sensorError_mutex.lock();
-            pos = sensorErrorTable.find(msg->controlFile);
-            if ( pos != sensorErrorTable.end() ) {
-                GLOBAL_mdot->deleteUserFile(msg->controlFile);
-                logInfo("%s: deleted %s", __func__, msg->controlFile);
-                pos->second->unregisterControl();
-                delete (pos->second);
-                sensorErrorTable.erase(pos);
-            } else {
-                logError("%s: unable to find %s", __func__, msg->controlFile);
-            }
-            sensorError_mutex.unlock();
-            break;
-        }
-        case CONTROL_PID: {
-            // TODO:
-            break;
-        }
-        default:
-            break;
-    }
-    return 0;
-}
-//
-// function:            getManualControlType
-// description:         extract the manual control type (continuous or timed)
-//
-// @param[in]           filename
-// @return              control type (int)
-//
-static unsigned int getManualControlType(const char *filename)
-{
-    char buf[MAX_FILE_SIZE];
-    unsigned int type = MANUAL_CONTROL_TYPE_NONE;
-    bool rc = GLOBAL_mdot->readUserFile(filename, buf, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        logError("%s: failed to read %s", __func__, filename);
-    } else {
-        cJSON * root = cJSON_Parse(buf);
-        type = atoi(cJSON_GetObjectItem(root,"type")->valuestring);
-        cJSON_Delete(root);
-    }
-    return type;
-}
--- a/ICE-Application/src/ConfigurationHandler/ConfigurationHandler.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/******************************************************************************
- * 
- * File:                ConfigurationHandler.h
- * Desciption:          interface file for the ICE Configuration Handler
- *
- *****************************************************************************/
-#ifndef CONFIGURATIONHANDLER_H
-#define CONFIGURATIONHANDLER_H
-
-#include "./Controls/SetpointControl.h"
-#include "./Controls/TimerControl.h"
-#include "./Controls/ManualControl.h"
-#include "./Controls/CompositeControl.h"
-#include "./Controls/PIDControl.h"
-#include "./Controls/FailsafeControl.h"
-#include "./Controls/SensorErrorControl.h"
-#include "./Controls/SequenceControl.h"
-#include "./Algorithms/CompositeAlgorithm.h"
-#include <map>
-
-// file naming prefix conventions
-#define CONTROL_SP_STR          "control_sp_"
-#define CONTROL_TM_STR          "control_tm_"
-#define CONTROL_MN_STR          "control_mn_"
-#define CONTROL_COMP_STR        "control_comp_"
-#define CONTROL_CA_STR          "control_ca_"
-#define CONTROL_FS_STR          "control_fs_"
-#define CONTROL_SE_STR          "control_se_"
-#define CONTROL_PID_STR         "control_pid_"
-#define CONTROL_ADM_STR         "control_adm_"
-#define CONTROL_SEQ_STR         "control_seq_"
-
-#define VIRTUAL_OUTPUT_PREFIX   "v_"
-
-typedef struct va_tag {
-    std::string     tag;
-    std::string     opr;
-    std::string     op;
-} VirtualAlgorithm;
-    
-void ConfigurationHandler(void const *args);
-
-// Public APIs
-void ConfigurationHandler_showControls(void);
-void ConfigurationHandler_showAlgorithms(void);
-void ConfigurationHandler_showTimerControls(void);
-void ConfigurationHandler_showManualControls(void);
-void ConfigurationHandler_showSetpointControls(void);
-void ConfigurationHandler_showCompositeControls(void);
-void ConfigurationHandler_showFailsafeControls(void);
-void ConfigurationHandler_showSensorErrorControls(void);
-void ConfigurationHandler_showSequenceControls(void);
-
-// map["control_sp_1.json"] : setpointControl 
-typedef std::map<std::string, SetpointControl*> StringSetpointMap;
-
-// map["control_tm_rly01.json"] : timerControl
-typedef std::map<std::string, TimerControl*> StringTimerMap;
-
-//map["control_mn_1.json"] : manualControl 
-typedef std::map<std::string, ManualControl*> StringManualMap;
-
-// map["control_pid_1.json"] : PIDControl
-//typedef std::map<std::string, PIDControl *> StringPIDMap;
-
-// map["control_cmp_1.json"] : compositeControl 
-typedef std::map<std::string, CompositeControl*> StringCompositeMap;
-
-// map["control_fs_rly1.json"] : failsafeControl 
-typedef std::map<std::string, FailsafeControl*> StringFailsafeMap;
-
-// map["control_se_bdcond.json"] : sensorErrorControl
-typedef std::map<std::string, SensorErrorControl*> StringSensorErrorMap;
-
-// map["EQUAL_TO_1"].<operands stucture>
-typedef std::map<std::string, CompositeAlgorithm *> StringAlgorithmMap;
-
-// map["control_seq_slug.json"] : sequenceControl
-typedef std::map<std::string, SequenceControl *> StringSequenceMap;
-
-extern StringSetpointMap        setpointTable;
-extern StringTimerMap           timerTable;
-extern StringManualMap          manualTable;
-//extern StringPIDMap             PIDTable; 
-extern StringCompositeMap       compositeTable;
-extern StringAlgorithmMap       algorithmTable;
-extern StringFailsafeMap        failsafeTable;
-extern StringSensorErrorMap     sensorErrorTable;
-extern StringSequenceMap        sequenceTable;
-
-extern Mutex manual_mutex;
-extern Mutex setpoint_mutex;
-extern Mutex timer_mutex;
-extern Mutex failsafe_mutex;
-extern Mutex sensorError_mutex;
-extern Mutex composite_mutex;
-extern Mutex sequence_mutex;
-
-#endif
--- a/ICE-Application/src/ConfigurationHandler/Controls/CompositeControl.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,372 +0,0 @@
-/******************************************************************************
- *
- * File:                CompositeControl.cpp
- * Desciption:          ICE Composite Control Class implementation
- *
- *****************************************************************************/
-#include "CompositeControl.h"
-#include "ConfigurationHandler.h"
-#include "cJSON.h"
-#include "ModbusMasterApi.h"
-#include "global.h"
-#include "ICELog.h"
-#include <string>
-#include <iostream>
-#include <iomanip>
-
-#ifdef MDOT_ICE
-extern mDot *GLOBAL_mdot;
-#endif 
-
-using namespace std;
-
-
-//
-// method:          load
-// description:     load a composite control
-//
-// @param[in]       _controlFile -> the file containing the JSON data
-// @return          false if an error occurs; true otherwise
-//
-
-bool CompositeControl::load(std::string _controlFile)
-{
-    controlFile = _controlFile;
-
-
-    char dataBuf[MAX_FILE_SIZE];
-
-    // read the control data
-    bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
-    if ( rc != true ) {
-        logError("%s: failed to read %s", __func__, controlFile.c_str());
-        // caller should destroy the object
-        return false;
-    }
-
-    // validate control data
-    if ( !validateControlData(dataBuf) ) {
-        logError("%s: failed to validate control data", __func__);
-        return false;
-    }
-
-    // copy  control data
-    copyControlData(dataBuf);
-    
-    // TODO: validate the list fo outputs
-    
-    return true;
-}
-
-//
-// method:              validateControlData
-// description:         validate JSON formatted control data
-//
-// @param[in]           buf -> JSON formatted string
-// @param[out]          none
-// @return              true if valid; false otherwise
-//
-
-bool CompositeControl::validateControlData(const char *buf)
-{
-    bool rc = true;
-    cJSON * root    = cJSON_Parse(buf);
-
-    if ( !cJSON_HasObjectItem(root, "id") ||
-            !cJSON_HasObjectItem(root, "tag") ||
-            !cJSON_HasObjectItem(root, "priority") ||
-            !cJSON_HasObjectItem(root, "ca") ||
-            !cJSON_HasObjectItem(root, "outputs") ) {
-        logError("%s: control file missing expected tags", __func__);
-        cJSON_Delete(root);
-        return false;
-    }
-
-    cJSON_Delete(root);
-    return rc;
-}
-
-//
-// method:              copyControlData
-// description:         copy the JSON formatted data
-//
-// @param[in]           buf -> JSON formatted string
-// @param[out]          none
-// @return              none
-//
-void CompositeControl::copyControlData(const char *buf)
-{
-    cJSON * root    = cJSON_Parse(buf);
-
-    id              = cJSON_GetObjectItem(root,"id")->valuestring;
-    tag             = cJSON_GetObjectItem(root, "tag")->valuestring;
-    priority        = atoi(cJSON_GetObjectItem(root, "priority")->valuestring);
-    ca              = cJSON_GetObjectItem(root, "ca")->valuestring;
-    cJSON *array    = cJSON_GetObjectItem(root, "outputs");
-    for ( int i = 0; i < cJSON_GetArraySize(array); ++i ) {
-        cJSON *subitem = cJSON_GetArrayItem(array, i);
-        std::string tag      = cJSON_GetObjectItem(subitem, "tag")->valuestring;
-        std::string response = cJSON_GetObjectItem(subitem, "responseA")->valuestring;
-        OutputElement x = { tag, response };
-        outputs.push_back(x);
-    }
-    cJSON_Delete(root);
-}
-
-//
-// method:          start
-// description:     start the composite control
-//
-// @param           none
-// @return          none
-//
-void CompositeControl::start(void)
-{
-    currentState = STATE_START;
-}
-
-//
-// method:          update
-// description:     updater for the composite control
-//
-// @param           none
-// @return          none
-//
-CompositeControlError_t CompositeControl::update(void)
-{
-    CompositeControlError_t rc = COMPOSITE_CONTROL_OK;
-    std::string function;
-
-    switch ( currentState ) {
-        case STATE_INIT:
-            // do nothing
-            break;
-        case STATE_START:
-            function = executeCommand();
-            if ( function == "responseA" ) {
-                currentState = STATE_CONTROL_ON;
-                triggerOutputs(function);
-            } else if ( function == "nothing" ) {
-                currentState = STATE_CONTROL_OFF;
-            }
-            break;
-        case STATE_CONTROL_ON:
-            function = executeCommand();
-            if ( function == "nothing" ) {
-                currentState = STATE_CONTROL_OFF;
-                unregisterControls();
-            } else {
-                // do nothing
-            }
-            break;
-        case STATE_CONTROL_OFF:
-            function = executeCommand();
-            if ( function == "responseA" ) {
-                currentState = STATE_CONTROL_ON;
-                triggerOutputs(function);
-            } else {
-                // do nothing
-            }
-            break;
-        default:
-            logError("%s: unknown state %d", __func__, this->currentState);
-            rc = COMPOSITE_CONTROL_UNK_STATE;
-            break;
-    }
-    return rc;
-}
-
-//
-// method:          executeCommand
-// description:     execute the command specified in the control algorithm
-//
-// @param           none
-// @return          none
-//
-std::string CompositeControl::executeCommand(void)
-{
-    // look up the algorithm
-    StringAlgorithmMap::const_iterator pos;
-    pos = algorithmTable.find(this->ca);
-    if ( pos != algorithmTable.end() ) {
-        // we found the control algorithm
-        return this->executeOperation(pos->second);
-    }
-    return "nothing";
-}
-
-//
-// method:          executeOperation
-// description:     execute an operations from the control equation
-//
-// @param[in]       ca -> composite control algorithm
-// @return          string to the result
-//
-std::string CompositeControl::executeOperation(const CompositeAlgorithm *ca)
-{
-    // (this->tag) <op> <opr> = <result>
-    //
-    // example:
-    // this->tag = "i_flowswitch"
-    // opr = "1"
-    // op = "=="
-    // if true return "responseA" else return "nothing"
-
-    ModbusValue value;
-    bool rc = ModbusMasterReadRegister(tag,&value);
-    if ( rc != true ) {
-        logError("%s cannot find tag", __func__);
-        return "nothing";
-    }
-
-    // equal to operator
-    if ( ca->getOp() == "==" ) {
-        // perform the equality operation
-        if ( value.value == atof(ca->getOpr().c_str()) ) {
-            return ca->getResultTrue();
-        } else {
-            return ca->getResultFalse();
-        }
-    }
-    if ( ca->getOp() == ">=" ) {
-        if ( value.value >= atof(ca->getOpr().c_str()) ) {
-            return ca->getResultTrue();
-        } else {
-            return ca->getResultFalse();
-        }
-    }
-
-    if ( ca->getOp() == "&" ) {
-        if ( (int)value.value & (int)atoi(ca->getOpr().c_str()) ) {
-            return ca->getResultTrue();
-        } else {
-            return ca->getResultFalse();
-        }
-    }
-
-    // addition operator
-    if ( ca->getOp() == "+" ) {
-        // TODO
-    }
-    // multiply operator
-    if ( ca->getOp() == "*" ) {
-        // TODO:
-    }
-    // subtraction operator
-    if ( ca->getOp() == "-" ) {
-        // TODO:
-    }
-
-    return "nothing";
-}
-
-//
-// method:          triggerOutputs
-// description:     trigger the output(s) to do something
-//
-// @param[in]       result -> the result of the operation
-// @return          none
-//
-void CompositeControl::triggerOutputs(std::string result)
-{
-
-    // loop through the list
-    StringAlgorithmMap::const_iterator pos;
-    pos = algorithmTable.find(this->ca);
-    if ( pos != algorithmTable.end() ) {
-        std::vector<OutputElement>::const_iterator it;
-        for ( it = outputs.begin(); it != outputs.end(); ++it ) {
-            if ( it->response == "fixed off" ) {
-                printf("\rSending an OFF control for %s\n", it->tag.c_str());
-                sendMail(it->tag, ACTION_CONTROL_OFF);
-            } else if ( it->response == "fixed on" ) {
-                printf("\rSending an ON request for %s\n", it->tag.c_str());
-                sendMail(it->tag, ACTION_CONTROL_ON);
-            }
-        }
-    } else {
-        logError("%s: failed to find the control algorithm %s\n", __func__, this->ca.c_str());
-    }
-}
-
-//
-// method:          sendMail
-// description:     send mail to the output task
-//
-// @param[in]       io_tag  -> input/output tag
-// @param[in]       action  -> ON, OFF, UNREGISTER
-// @return          none
-//
-void CompositeControl::sendMail(const std::string io_tag, OutputAction action)
-{
-    logInfo("%s: composite control attempting to send action %d\n",
-            __func__, action);
-
-    OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-    memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-    output_mail->action         = action;
-    output_mail->controlType    = CONTROL_COMPOSITE;
-    output_mail->priority       = this->priority;
-
-    strncpy(output_mail->input_tag,  this->tag.c_str(),  sizeof(output_mail->input_tag)-1);
-    strncpy(output_mail->output_tag, io_tag.c_str(), sizeof(output_mail->output_tag)-1);
-    strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-
-    OutputMasterMailBox.put(output_mail);
-}
-
-//
-// method:          unregisterControls
-// description:     unregister the control with the output task
-//
-// @param           none
-// @return          none
-//
-void CompositeControl::unregisterControls(void)
-{
-    // loop through the list
-    StringAlgorithmMap::const_iterator pos;
-    pos = algorithmTable.find(this->ca);
-    if ( pos != algorithmTable.end() ) {
-        std::vector<OutputElement>::const_iterator it;
-        for ( it = outputs.begin(); it != outputs.end(); ++it ) {
-            sendMail(it->tag, ACTION_CONTROL_UNREGISTER);
-        }
-    } else {
-        logError("%s: failed to find the control algorithm %s\n", __func__, this->ca.c_str());
-    }
-}
-
-//
-// method:          display
-// description:     display the pertinents
-//
-// @param           none
-// @return          none
-//
-void CompositeControl::display(void)
-{
-    const char *mapper[] = { "INIT",
-                             "START",
-                             "CONTROL_OFF",
-                             "CONTROL_ON"
-                           };
-
-    printf("\r\n");
-    std::cout << left << setw(10) << setfill(' ') << "composite: ";
-    std::cout << left << setw(40) << setfill(' ') << controlFile;
-    std::cout << left << setw(20) << setfill(' ') << id;
-    std::cout << left << setw(20) << setfill(' ') << tag;
-    std::cout << left << setw(6)  << setfill(' ') << priority;
-    std::cout << left << setw(20) << setfill(' ') << ca;
-    std::cout << left << setw(16) << setfill(' ') << mapper[currentState];
-
-    vector<OutputElement>::const_iterator it;
-    for ( it = outputs.begin(); it != outputs.end(); ++it ) {
-        std::cout << left << (*it).tag << ":" << (*it).response << "  ";
-    }
-
-    std::cout.flush();
-
-}
\ No newline at end of file
--- a/ICE-Application/src/ConfigurationHandler/Controls/CompositeControl.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/******************************************************************************
- *
- * File:                CompositeControl.h
- * Desciption:          ICE Composite Control Class
- *
- *****************************************************************************/
-#ifndef COMPOSITECONTROL_H
-#define COMPOSITECONTROL_H
-
-#include <string>
-#include <vector>
-#include <stdio.h>
-#include <stdlib.h>
-#include "global.h"
-#include "./Algorithms/CompositeAlgorithm.h"
-
-typedef enum {
-    COMPOSITE_CONTROL_OK,
-    COMPOSITE_CONTROL_UNK_STATE, 
-    COMPOSITE_CONTROL_ERROR,
-    COMPOSITE_CONTROL_DESTROY
-} CompositeControlError_t;
-
-//! Composite Control - used to implement a composite control
-class CompositeControl
-{
-private:
-    typedef struct oe_tag {
-        std::string     tag;
-        std::string     response;
-    } OutputElement;
-
-    std::string                 controlFile;    // the control file
-    std::string                 id;             // composite identifier
-    std::string                 tag;            // i/o tag to evaluate
-    unsigned int                priority;       // control priority
-    std::string                 ca;             // control algorithm
-    std::vector<OutputElement>  outputs;        // (virtual) output(s)
-
-    enum State {
-        STATE_INIT,
-        STATE_START,
-        STATE_CONTROL_OFF,
-        STATE_CONTROL_ON,
-        STATE_MAX
-    };
-    State                       currentState;   // current state
-        
-    bool        validateControlData(const char *buf);
-    void        copyControlData(const char *buf);
-
-    std::string executeCommand(void);
-    std::string executeOperation(const CompositeAlgorithm*);
-    void        triggerOutputs(std::string result);
-    void        sendMail(std::string io_tag, OutputAction action);
-
-public:
-    /// constructor
-    CompositeControl() { }
-    
-    /// destructor
-    ~CompositeControl() {
-        printf("\r%s invoked\n", __func__);
-    }
-
-    /// load a composite control from a JSON configuration file
-    bool load(std::string controlFile);
-
-    /// start a composite control instance
-    void start(void);
-
-    /// update a composite control instance 
-    CompositeControlError_t update(void);
-
-    /// unregister a composite control(s) instance 
-    void unregisterControls();
-
-    /// get the composite control's control filename 
-    std::string getControlFile(void) const {
-        return controlFile;
-    }
-    
-    /// get the composite control's identifier
-    std::string getId(void) const {
-        return id;
-    }
-
-    /// get the composite control's current state 
-    State getState(void) const {
-        return currentState;
-    }
-
-    /// get the composite control's tag 
-    std::string getTag(void) const {
-        return tag;
-    }
-    
-    /// get a list of a composite control's outputs
-    std::vector<std::string> getOutputs(void) const;
-
-    void display(void);
-};
-
-#endif
--- a/ICE-Application/src/ConfigurationHandler/Controls/FailsafeControl.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,534 +0,0 @@
-/******************************************************************************
- *
- * File:                FailsafeControl.cpp
- * Desciption:          ICE Failsafe Control Class implementation
- *
- *****************************************************************************/
-#include "FailsafeControl.h"
-#include "cJSON.h"
-#include "ICELog.h"
-#include "global.h"
-#include "ModbusMasterApi.h"
-#include "utilities.h"
-#include <string>
-#include <iostream>
-#include <iomanip>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <time.h>
-
-using namespace std;
-
-#ifdef MDOT_ICE
-extern mDot *GLOBAL_mdot;
-#endif 
-
-// for debugging - this can be set via the console command:
-//      "debug-fs 1 or debug-fs 0
-bool debugFailsafeControl = false;
-
-static void debug(const char *fmt, ...)
-{
-    if ( debugFailsafeControl ) {
-        va_list vargs;
-        va_start(vargs, fmt);
-        vfprintf(stdout, fmt, vargs);
-        va_end(vargs);
-    }
-}
-
-//
-// method:          load
-// description:     load a composite control
-//
-// @param           none
-// @return          none
-//
-bool FailsafeControl::load(std::string _controlFile)
-{
-    controlFile = _controlFile;
-
-
-    // read the data into a buffer
-    char dataBuf[MAX_FILE_SIZE];
-
-    bool rc  = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
-    if ( rc != true ) { 
-        logError("%s: failed to read %s", __func__, controlFile.c_str());
-        // caller should destroy the object
-        return false;
-    }
-
-
-    if ( !validateControlData(dataBuf) ) {
-        logError("%s: failed to validate control data", __func__);
-        return false;
-    }
-
-    copyControlData(dataBuf);
-
-    ModbusValue val;
-    // validate the input & output 
-    if ( ModbusMasterReadRegister(input, &val) == false ) {
-        logError("%s failed to find input %s", id.c_str(), input.c_str());
-        return false;
-    }
-    if ( ModbusMasterReadRegister(output, &val) == false ) {
-        logError("%s failed to find output %s", id.c_str(), output.c_str());
-        return false;
-    }
-    
-    isVirtualOutput = Util_isVirtualOutput(output) ? true : false;
-    return true;
-}
-//
-// method:                  validateControlData
-// description:             validate the JSON formatted strings for
-//                          expected tags
-//
-// @param[in]               buf -> JSON formatted string
-// @param[out]              none
-// @return                  true if valid; false otherwise
-//
-bool FailsafeControl::validateControlData(const char *buf)
-{
-    bool rc = true;
-    // parse the data
-    cJSON * root    = cJSON_Parse(buf);
-
-    if ( !cJSON_HasObjectItem(root, "id") ||
-            !cJSON_HasObjectItem(root, "priority") ||
-            !cJSON_HasObjectItem(root, "input") ||
-            !cJSON_HasObjectItem(root, "output") ||
-            !cJSON_HasObjectItem(root, "hfsValue") ||
-            !cJSON_HasObjectItem(root, "hfsDutyCycle") ||
-            !cJSON_HasObjectItem(root, "hfsInterval") ||
-            !cJSON_HasObjectItem(root, "lfsValue") ||
-            !cJSON_HasObjectItem(root, "lfsDutyCycle") ||
-            !cJSON_HasObjectItem(root, "lfsInterval") ) {
-        logError("%s: control file is missing expected tags", __func__);
-        rc = false;
-    }
-
-    cJSON_Delete(root);
-    return rc;
-}
-
-//
-// method:                  copyControlData
-// description:             copy data from JSON buffer to object
-//
-// @param[in]               buf -> JSON formattted string
-// @param[out]              none
-// @return                  none
-//
-void FailsafeControl::copyControlData(const char *buf)
-{
-    cJSON *root = cJSON_Parse(buf);
-
-    id                  = cJSON_GetObjectItem(root, "id")->valuestring;
-    priority            = atoi(cJSON_GetObjectItem(root, "priority")->valuestring);
-    input               = cJSON_GetObjectItem(root, "input")->valuestring;
-    output              = cJSON_GetObjectItem(root, "output")->valuestring;
-
-    // high failsafe data
-    hfs_data.value      = atof(cJSON_GetObjectItem(root, "hfsValue")->valuestring);
-    hfs_data.dutyCycle  = atoi(cJSON_GetObjectItem(root, "hfsDutyCycle")->valuestring);
-    hfs_data.interval   = atoi(cJSON_GetObjectItem(root, "hfsInterval")->valuestring);
-
-    // low failsafe data
-    lfs_data.value      = atof(cJSON_GetObjectItem(root, "lfsValue")->valuestring);
-    lfs_data.dutyCycle  = atoi(cJSON_GetObjectItem(root, "lfsDutyCycle")->valuestring);
-    lfs_data.interval   = atoi(cJSON_GetObjectItem(root, "lfsInterval")->valuestring);
-
-    cJSON_Delete(root);
-}
-
-//
-// method:      start
-// description: start the failsafe control
-//
-// @param       none
-// @return      none
-//
-void FailsafeControl::start(void)
-{
-    currentState = STATE_START;
-}
-
-//
-// method:      update
-// description: update the faisafe control using the FSM
-//
-// @param       none
-// @return      none
-//
-FailsafeControlError_t FailsafeControl::update(void)
-{
-    FailsafeControlError_t rc = FAILSAFE_CONTROL_OK;
-
-    switch (this->currentState) {
-        case STATE_INIT:
-            // do nothing - control must be programatically started
-            break;
-        case STATE_START:
-            // control has programmatically started, do some checking
-            if ( this->aboveHighFailsafe() ) {
-                if ( hfs_data.dutyCycle) {
-                    debug("\r%s: [START]->above hfs->[ON_HFS]\n", id.c_str());
-                    // start high failsafe duty cycle
-                    this->currentState = STATE_CONTROL_ON_HFS;
-                    // turn the pump ON for the duty cycle, start the timer
-                    sendMailToOutput(ACTION_CONTROL_ON);
-                    this->startHfsDutyTimer();
-                } else {
-                    // no duty cycle specified, so go into the high-faisafe
-                    // fixed-off state
-                    debug("\r%s: [START]->above hfs && !dc->[OFF_HFS]\n", id.c_str());
-                    this->currentState = STATE_CONTROL_OFF_HFS;
-                    sendMailToOutput(ACTION_CONTROL_OFF);
-                    // no need to start the duty timer
-                }
-            } else if ( this->belowLowFailsafe() ) {
-                debug("\r%s: [START]->below lfs->[ON_LFS]\n", id.c_str());
-                // start low failsafe duty cycle
-                if ( lfs_data.dutyCycle ) {
-                    this->currentState = STATE_CONTROL_ON_LFS;
-                    // turn the pump ON for the duty cycle, start the timer
-                    sendMailToOutput(ACTION_CONTROL_ON);
-                    this->startLfsDutyTimer();
-                } else {
-                    // no duty cycle specified, so go into the low-failsafe
-                    // fixed off-state
-                    this->currentState = STATE_CONTROL_OFF_LFS;
-                    sendMailToOutput(ACTION_CONTROL_OFF);
-                    // no need to start the timer
-                }
-            } else {
-                debug("\r%s: [START]->no conditions->[OFF]\n", id.c_str());
-                this->currentState = STATE_CONTROL_OFF;
-            }
-            break;
-        case STATE_CONTROL_OFF:
-            // control is acting normal, within bounds
-            if ( this->aboveHighFailsafe() ) {
-                if ( hfs_data.dutyCycle ) {
-                    debug("\r%s: [OFF]->above hfs->[ON HFS]\n", id.c_str());
-                    this->currentState = STATE_CONTROL_ON_HFS;
-                    sendMailToOutput(ACTION_CONTROL_ON);
-                    this->startHfsDutyTimer();
-                } else {
-                    debug("\r%s: [OFF]->above hfs && no dc->[OFF HFS]\n", id.c_str());
-                    this->currentState = STATE_CONTROL_OFF_HFS;
-                    sendMailToOutput(ACTION_CONTROL_OFF);
-                }
-            } else if ( this->belowLowFailsafe() ) {
-                // restart the low failsafe duty cycle
-                debug("\r%s: [OFF]->below lfs->[ON_LFS]\n", id.c_str());
-                if ( lfs_data.dutyCycle ) {
-                    this->currentState = STATE_CONTROL_ON_LFS;
-                    sendMailToOutput(ACTION_CONTROL_ON);
-                    this->startLfsDutyTimer();
-                } else {
-                    this->currentState = STATE_CONTROL_OFF_LFS;
-                    sendMailToOutput(ACTION_CONTROL_OFF);
-                }
-            } else {
-                // do nothing
-            }
-            break;
-        case STATE_CONTROL_ON_LFS:
-            // control is in low-failsafe with duty cycle ON
-            if ( !this->belowLowFailsafe() ) {
-                // input has fallen below the failsafe, so turn off the control
-                debug("\r%s: [ON_LFS]->above lfs->[OFF]\n", id.c_str());
-                this->currentState = STATE_CONTROL_OFF;
-                this->unregisterControl();
-            } else if ( this->dutyOnExpired() ) {
-                // duty ON has expired, so let's idle in the OFF-LFS state now
-                debug("\r%s: [ON_LFS]->duty on expired->[OFF LFS]\n", id.c_str());
-                this->currentState = STATE_CONTROL_OFF_LFS;
-                sendMailToOutput(ACTION_CONTROL_OFF);
-            } else {
-                // do nothing
-            }
-            break;
-        case STATE_CONTROL_OFF_LFS:
-            // control is in low-failsafe with duty cycle OFF
-            if ( !this->belowLowFailsafe() ) {
-                // no longer in dangerous waters, so transition to OFF
-                debug("\r%s: [OFF_LFS]->above lfs->[OFF]\n", id.c_str());
-                this->currentState = STATE_CONTROL_OFF;
-                this->unregisterControl();
-            } else if ( this->dutyOffExpired() && lfs_data.dutyCycle ) {
-                debug("\r%s: [OFF_LFS]->duty OFF exp->[ON_LFS]", id.c_str());
-                // turn the PUMP back on and restart the duty timer
-                this->currentState = STATE_CONTROL_ON_LFS;
-                sendMailToOutput(ACTION_CONTROL_ON);
-                this->startLfsDutyTimer();
-
-            } else {
-                // do nothing
-            }
-            break;
-        case STATE_CONTROL_ON_HFS:
-            // control is in high-failsafe with duty cycle ON
-            if ( !this->aboveHighFailsafe() ) {
-                debug("\r%s: [ON_HFS]->below hfs->[OFF]\n", id.c_str());
-                this->currentState = STATE_CONTROL_OFF;
-                this->unregisterControl();
-            } else if ( this->dutyOnExpired() ) {
-                debug("\r%s: [ON_HFS]->duty ON expired->[OFF_HFS]\n", id.c_str());
-                this->currentState = STATE_CONTROL_OFF_HFS;
-                sendMailToOutput(ACTION_CONTROL_OFF);
-            } else {
-                // do nothing
-            }
-            break;
-        case STATE_CONTROL_OFF_HFS:
-            // control is in high-failsafe with cuty cycle OFF
-            if ( !this->aboveHighFailsafe() ) {
-                debug("\r%s: [OFF_HFS]->below hfs->[OFF]\n", id.c_str());
-                this->currentState = STATE_CONTROL_OFF;
-                this->unregisterControl();
-            } else if ( this->dutyOffExpired() && hfs_data.dutyCycle ) {
-                debug("\r%s: [OFF_HFS]->duty OFF expired->[ON_HFS]\n", id.c_str());
-                this->currentState = STATE_CONTROL_ON_HFS;
-                sendMailToOutput(ACTION_CONTROL_ON);
-                this->startHfsDutyTimer();
-            } else {
-                // do nothing
-            }
-            break;
-        default:
-            logError("%s: unknown state %d", __func__, this->currentState);
-            rc = FAILSAFE_CONTROL_UNK_STATE;
-            break;
-    }
-    return rc;
-}
-
-//
-// method:              belowFailsafe
-// description:         returns true if the input signal is below the
-//                      failsafe mark
-//
-// @param[in]           none
-// @param[out]          none
-// @return              true if below; false otherwise
-//
-bool FailsafeControl::belowLowFailsafe(void)
-{
-    // read the modbus input
-    ModbusValue value;
-    ModbusMasterReadRegister(input, &value);
-    return ( value.value <= lfs_data.value );
-}
-
-//
-// method:              aboveHighFailsafe
-// description:         returns true if the input signal is above the
-//                      failsafe mark
-//
-// @param[in]           none
-// @param[out]          none
-// @return              true if above; false otherwise
-//
-bool FailsafeControl::aboveHighFailsafe(void)
-{
-    // read the modbus input
-    ModbusValue value;
-    ModbusMasterReadRegister(input, &value);
-    return ( value.value >= hfs_data.value );
-}
-
-//
-// method:          startHfsDutyTimer
-// description:     start the high failsafe duty timer
-//
-// @param           none
-// @return          none
-//
-void FailsafeControl::startHfsDutyTimer(void)
-{
-    unsigned long currentTime = time(NULL);
-    unsigned long period = hfs_data.interval * 60;
-
-    duty_timer.offTime        = currentTime + ((double)period * ((double)hfs_data.dutyCycle/100.0));
-    duty_timer.expirationTime = currentTime + period;
-
-    debug("\r%s:%s-> currentTime = %lu\n", __func__, id.c_str(), currentTime);
-    debug("\r%s:%s-> off Time    = %lu\n", __func__, id.c_str(), duty_timer.offTime);
-    debug("\r%s:%s-> expiration  = %lu\n", __func__, id.c_str(),duty_timer.expirationTime);
-}
-
-//
-// method:          stopHfsDutyTimer
-// description:     stop the high failsafe duty timer
-//
-// @param [in]      none
-// @param[out]      none
-// @return          none
-//
-void FailsafeControl::stopHfsDutyTimer(void)
-{
-    debug("\r%sL%s-> invoked\n", __func__, id.c_str());
-    memset(&duty_timer, 0, sizeof(duty_timer));
-}
-
-//
-// method:          startLfsDutyTimer
-// descrption:      start the low failsafe duty-timer
-//
-// @param[in]       none
-// @param[out]      none
-// @return          none
-//
-void FailsafeControl::startLfsDutyTimer(void)
-{
-    unsigned long currentTime = time(NULL);
-    unsigned long period      = lfs_data.interval * 60;
-
-    duty_timer.offTime        = currentTime + ((double)period * ((double)lfs_data.dutyCycle/100.0));
-    duty_timer.expirationTime = currentTime + period;
-
-    debug("\r%s:%s-> next off time = %lu\n", __func__, id.c_str(), duty_timer.offTime);
-    debug("\r%s:%s->expiration time = %lu\n", __func__, id.c_str(), duty_timer.expirationTime);
-}
-
-//
-// method:          stopLfsDutyTimer
-// description:     stop the low failsafe duty-timer
-//
-// @param           none
-// @return          none
-//
-void FailsafeControl::stopLfsDutyTimer(void)
-{
-    debug("\r%s:5s-> invoked\n", __func__, id.c_str());
-    memset(&duty_timer, 0, sizeof(duty_timer));
-}
-
-//
-// method:          dutyOnExpired
-// description:     returns true if ON cycle has expired; false otherwise
-//
-// @param           none
-// @return          none
-//
-bool FailsafeControl::dutyOnExpired(void)
-{
-    return (time(0) >= duty_timer.offTime);
-}
-
-//
-// method:          dutyOffExpired
-// description:     returns true if OFF cycle has expired; false otherwise
-//
-// @param           none
-// @return          none
-//
-bool FailsafeControl::dutyOffExpired(void)
-{
-    return (duty_timer.expirationTime < time(NULL));
-}
-
-//
-// method:      sendMailToOutput
-// description: send mail to the output task
-//
-// @param       io_tag  -> input/output tag
-// @param       action  -> ON, OFF, UNREGISTER
-// @return      none
-//
-void FailsafeControl::sendMailToOutput(OutputAction action)
-{
-    logInfo("%s: failsafe control %s attempting to send action %d\n",
-            __func__, id.c_str(), action);
-
-    if ( isVirtualOutput ) {
-        debug("%s:%s-> updating the virtual output %s\n", __func__, id.c_str(), output.c_str());
-        ModbusMasterWriteRegister(this->output,
-                                  (action == ACTION_CONTROL_ON) ? 1.0 : 0.0);
-    } else {
-        OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-        memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-        output_mail->action         = action;
-        output_mail->controlType    = CONTROL_FAILSAFE;
-        output_mail->priority       = this->priority;
-
-        strncpy(output_mail->input_tag,  this->input.c_str(),  sizeof(output_mail->input_tag)-1);
-        strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-        strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-
-        OutputMasterMailBox.put(output_mail);
-    }
-}
-
-
-//
-// method:          unregisterControl
-// description:     unregister this control with the output task
-//
-// @param           none
-// @return          none
-//
-void FailsafeControl::unregisterControl(void)
-{
-    logInfo("%s: %s attempting to unregister %s\n",
-            __func__, id.c_str(), controlFile.c_str());
-
-    if ( isVirtualOutput ) {
-        debug("%s: %s attempting to unregister virtual output %s\n", 
-            __func__, id.c_str(), output.c_str());
-        ModbusMasterWriteRegister(output, 0.0);
-    } else {
-        OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-        memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-        output_mail->action         = ACTION_CONTROL_UNREGISTER;
-        output_mail->controlType    = CONTROL_FAILSAFE;
-        output_mail->priority       = this->priority;
-        strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-        strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-
-        OutputMasterMailBox.put(output_mail);
-    }
-}
-
-//
-// method:      display
-// description: display the pertinents
-//
-// @param       none
-// @return      none
-//
-void FailsafeControl::display(void)
-{
-    const char *mapper[] = { "INIT",
-                             "START",
-                             "OFF",
-                             "ON_LFS",
-                             "OFF_LFS",
-                             "ON_HFS",
-                             "OFF_HFS",
-                             "SENSOR_ERR",
-                             "invalid"
-                           };
-
-    printf("\r\n");
-    std::cout << left << setw(10) << setfill(' ') << "failsafe: ";
-    std::cout << left << setw(40) << setfill(' ') << controlFile;
-    std::cout << left << setw(20) << setfill(' ') << id;
-    std::cout << left << setw(6)  << setfill(' ') << priority;
-    std::cout << left << setw(20) << setfill(' ') << input;
-    std::cout << left << setw(20) << setfill(' ') << output;
-    std::cout << left << setw(16) << setfill(' ') << mapper[currentState];
-    std::cout << left  << setw(12) << setfill(' ') << "lfs-> "
-              << lfs_data.value << ":" << lfs_data.dutyCycle << ":" << lfs_data.interval;
-    std::cout << right << setw(12) << setfill(' ') << "hfs-> "
-              << hfs_data.value << ":" << hfs_data.dutyCycle << ":" << hfs_data.interval;
-
-    std::cout.flush();
-}
\ No newline at end of file
--- a/ICE-Application/src/ConfigurationHandler/Controls/FailsafeControl.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-#ifndef FAILSAFECONTROL_H
-#define FAILSAFECONTROL_H
-
-#include <stdio.h>
-#include <string>
-#include "global.h"
-
-#define FAILSAFE_CONTROL_DEBUG
-
-typedef enum {
-    FAILSAFE_CONTROL_OK,
-    FAILSAFE_CONTROL_UNK_STATE,
-    FAILSAFE_CONTROL_ERROR,
-} FailsafeControlError_t;
-
-//! FailsafeControl - implements a failsafe by reading values from an
-// input signal and manipulating an output.
-class FailsafeControl
-{
-private:
-    std::string     controlFile;            // the control file
-    std::string     id;                     // unique control identifier
-    std::string     input;                  // sensor to read
-    std::string     output;                 // output to manipulate
-    unsigned int    priority;               // control priority (typically 700)
-
-    typedef struct  hfs_tag {
-        float       value;                  // high-failsafe trigger value
-        float       dutyCycle;              // percentage of on-time
-        float       interval;               // in minutes
-    } hfs;
-    typedef struct lfs_tag {
-        float       value;                  // low-failsafe trigger value
-        float       dutyCycle;              // percentag of on-time
-        float       interval;               // in minutes
-    } lfs;
-
-    lfs             lfs_data;               // Low Failsafe data
-    hfs             hfs_data;               // High Failsafe data
-
-    typedef struct timer_tag {
-        unsigned long   offTime;            // epoch time
-        unsigned long   expirationTime;     // epoch time
-    } Timer_t;
-
-    Timer_t         duty_timer;             // the duty timer
-
-    enum State {
-        STATE_INIT,                         // object instantiated
-        STATE_START,                        // control has been started
-        STATE_CONTROL_OFF,                  // control is not above/below limit
-        STATE_CONTROL_ON_LFS,               // low-failsafe with output on
-        STATE_CONTROL_OFF_LFS,              // low-failsafe with output off
-        STATE_CONTROL_ON_HFS,               // high-failsafe with output on
-        STATE_CONTROL_OFF_HFS,              // high-failsafe with output off
-        STATE_CONTROL_SENSOR_ERROR,         // input sensor is faulted
-        STATE_MAX
-    };
-    State           currentState;
-    
-    bool            isVirtualOutput;
-
-    bool validateControlData(const char *buf);
-    void copyControlData(const char *buf);
-    
-    bool aboveHighFailsafe(void);           // boolean check if above HFS watermark
-    bool belowLowFailsafe(void);            // boolean check if below LFS watermark
-
-    void startHfsDutyTimer(void);           // start the HFS duty timer
-    void stopHfsDutyTimer(void);            // stop the HFS duty timer
-
-    void startLfsDutyTimer(void);           // start the LFS duty timer
-    void stopLfsDutyTimer(void);            // stop the LFS duty timer
-
-    bool dutyOnExpired(void);               // boolean check if duty ON-time expired
-    bool dutyOffExpired(void);              // boolean check if duty OFF-time expired
-
-    bool sensorError(void);                 // boolean check if input is faulted
-
-    void sendMailToOutput(OutputAction action);
-
-public:
-    /// Create a failsafe control instance
-    FailsafeControl() {
-        currentState = STATE_INIT;
-        isVirtualOutput = false; 
-    }
-    /// Destroy a failsafe control instance
-    ~FailsafeControl() {
-        // "erased...from existence!" -- Doc Brown
-        printf("\r%s invoked\n", __func__);
-    }
-
-    /// load a failsafe control instance with data from a JSON configuration file
-    bool load(std::string filename);
-
-    /// start a failsafe control instance
-    void start(void);
-
-    /// update a failsafe control instance
-    FailsafeControlError_t update(void);
-
-    /// unregister a failsafe control instance
-    void unregisterControl(void);
-
-
-    /// display  the pertinent data of a failsafe control instance
-    void display(void);
-
-    /// get control identifier 
-    std::string getId() const {
-        return id;
-    }
-};
-
-#endif
\ No newline at end of file
--- a/ICE-Application/src/ConfigurationHandler/Controls/ManualControl.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,295 +0,0 @@
-/******************************************************************************
- *
- * File:                ManualControl.cpp
- * Desciption:          ICE Manual Control Class implementation
- *
- *****************************************************************************/
-#include "ManualControl.h"
-#include "ICELog.h"
-#include "cJSON.h"
-#include "ModbusMasterApi.h"
-#include "global.h"
-#include <string>
-#include <iostream>
-#include <iomanip>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <time.h>
-
-using namespace std;
-
-// for debugging - this can be set via the console command:
-//      "debug-man 1 or debug-man 0
-bool debugManualControl = false;
-
-static void debug(const char *fmt, ...)
-{
-    if ( debugManualControl ) {
-        va_list vargs;
-        va_start(vargs, fmt);
-        vfprintf(stdout, fmt, vargs);
-        va_end(vargs);
-    }
-}
-
-#ifdef MDOT_ICE
-extern mDot *GLOBAL_mdot;
-#endif
-
-//
-// method:          load
-// description:     open the configuration file and assign data to the
-//                  setpoint control object
-//
-// @param           controlFile -> name of the control file
-// @return          true if data is assigned; false on error
-//
-bool ManualControl::load(std::string _controlFile)
-{
-    controlFile = _controlFile;
-    endTime = 0;
-
-    char dataBuf[MAX_FILE_SIZE];
-    
-    // read the data into the buffer
-    bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
-    if ( rc != true ) {
-        logError("%s: failed to read %s", __func__, controlFile.c_str());
-        // caller should destroy the object
-        return false;
-    }
-
-    // validate the JSON tags in the control file
-    if ( validateControlData(dataBuf) != true ) {
-        logError("%s: invalid control data.", __func__);
-        return false;
-    }
-
-    // assign object data from control file
-    copyControlData(dataBuf);
-    
-    ModbusValue val;
-    // validate the output
-    if ( ModbusMasterReadRegister(output, &val) == false ) {
-        logError("%s failed to find output %s", id.c_str(), output.c_str());
-        return false;
-    }
-
-    return true;
-}
-
-//
-// method:          validateControlData
-// description:     validate JSON formatted data
-//
-// @param[in]       buf -> JSON formatted string
-// @param[out]      none
-// @return          true if valid; false otherwise
-//
-bool ManualControl::validateControlData(const char* buf)
-{
-    bool rc = true;
-    cJSON * root = cJSON_Parse(buf);
-
-    if ( !cJSON_HasObjectItem(root, "id") ||
-            !cJSON_HasObjectItem(root, "output") ||
-            !cJSON_HasObjectItem(root, "type") ||
-            !cJSON_HasObjectItem(root, "priority") ||
-            !cJSON_HasObjectItem(root, "duration") ||
-            !cJSON_HasObjectItem(root, "setpoint") ||
-            !cJSON_HasObjectItem(root, "state") ||
-            !cJSON_HasObjectItem(root, "percent") ) {
-        logError("%s: control file is missing expected tags", __func__);
-        rc = false;
-    }
-    cJSON_Delete(root);
-    return rc;
-}
-
-//
-// method:          copyControlData
-// description:     copy JSON formatted control data to object
-//
-// @param[in]       buf -> JSON formatted string
-// @param[out]      none
-// @return          none
-//
-void ManualControl::copyControlData(const char *buf)
-{
-    cJSON * root = cJSON_Parse(buf);
-
-    id          = cJSON_GetObjectItem(root,"id")->valuestring;
-    output      = cJSON_GetObjectItem(root,"output")->valuestring;
-    type        = atoi(cJSON_GetObjectItem(root,"type")->valuestring);
-    priority    = atoi(cJSON_GetObjectItem(root, "priority")->valuestring);
-    duration    = atoi(cJSON_GetObjectItem(root, "duration")->valuestring);
-    setpoint    = atof(cJSON_GetObjectItem(root, "setpoint")->valuestring);
-    state       = atoi(cJSON_GetObjectItem(root, "state")->valuestring);
-    percent     = atoi(cJSON_GetObjectItem(root, "percent")->valuestring);
-
-    cJSON_Delete(root);
-}
-
-//
-// method:          start
-// description:     start the manual control
-//
-// @param           none
-// @return          none
-//
-void ManualControl::start(void)
-{
-    currentState = STATE_STARTUP;
-    if ( type == MANUAL_CONTROL_TYPE_TIMED ) {
-        debug("\r%s:%s-> manual control is timed\n", __func__, id.c_str());
-        endTime = time(NULL) + duration;
-    }
-}
-
-//
-// method:          update
-// description:     the manual control's state machine
-//
-// @param           none
-// @return          none
-//
-ManualControlError_t ManualControl::update(void)
-{
-    ManualControlError_t rc = MANUAL_CONTROL_OK;
-
-    switch ( this->currentState ) {
-        case STATE_INIT:
-            // do nothing
-            break;
-        case STATE_STARTUP:
-            if ( state & 0x01 ) {
-                this->currentState = STATE_CONTROL_ON;
-                debug("\r%s: [STARTUP]->manual on->[ON]\n", id.c_str());
-            } else {
-                this->currentState = STATE_CONTROL_OFF;
-                debug("\r%s: [STARTUP]->manual off->[OFF]\n", id.c_str());
-
-            }
-            //this->currentState = (state & 0x01) ? STATE_CONTROL_ON : STATE_CONTROL_OFF;
-            this->powerOutput();
-            break;
-        case STATE_CONTROL_ON:
-            if ( !(state & 0x1) ) {
-                this->currentState = STATE_CONTROL_OFF;
-                // user has changed state, so this is (or becomes) a pure
-                // manual control
-                endTime = 0;
-                this->powerOutput();
-                debug("\r%s: [ON]->manual off->[OFF]\n", id.c_str());
-            } else if ( endTime != 0 && time(NULL) >= endTime ) {
-                // timed interval has elapsed
-                currentState = STATE_CONTROL_FINISHED;
-                debug("\r%s: [ON]->timer expired->[FINISHED]\n", id.c_str());
-            }
-            break;
-        case STATE_CONTROL_OFF:
-            if ( state & 0x1 ) {
-                this->currentState = STATE_CONTROL_ON;
-                // user has changed the state, so this (or becomes) a pure
-                // manual control
-                endTime = 0;
-                this->powerOutput();
-                debug("\r%s: [OFF]->manual on->[ON]\n", id.c_str());
-            } else if ( endTime != 0 && time(NULL) >= endTime ) {
-                // timed interval has elapsed
-                currentState = STATE_CONTROL_FINISHED;
-                debug("\r%s: [OFF]->timer expired->[FINISHED]\n", id.c_str());
-            }
-            break;
-        case STATE_CONTROL_FINISHED:
-            // mark for deletion (control task will do the cleanup)
-            rc = MANUAL_CONTROL_DESTROY;
-            break;
-        default:
-            logError("%s unknown state %d\n", __func__, this->currentState);
-            rc = MANUAL_CONTROL_ERROR;
-            break;
-    }
-    return rc;
-}
-
-//
-// method:              unregisterControl
-// description:         unregister this control with the output master
-//
-// @param               none
-// @return              none
-//
-int ManualControl::unregisterControl(void)
-{
-    logInfo("%s: Attempting to unregister %s\n",
-            __func__, controlFile.c_str());
-
-    OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-    memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-    output_mail->controlType = CONTROL_MANUAL;
-    output_mail->action      = ACTION_CONTROL_UNREGISTER;
-    output_mail->priority    = this->priority;
-    strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-    strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-
-    OutputMasterMailBox.put(output_mail);
-    return 0;
-}
-
-//
-// method:          powerOutput
-// description:     send a message to the output thread to power the relay
-//
-// @param           none
-// @return          -1 on error; 0 otherwise
-//
-int ManualControl::powerOutput(void)
-{
-    printf("\r%s-> id:%s attempting to manually turn %s relay %s\n",
-           __func__, id.c_str(), (state & 0x1) ? "ON" : "OFF", output.c_str());
-
-    OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-    memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-    output_mail->controlType    = CONTROL_MANUAL;
-    output_mail->action         = (state & 0x1) ? ACTION_CONTROL_ON : ACTION_CONTROL_OFF;
-    output_mail->priority       = this->priority;
-    strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-    strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-
-    OutputMasterMailBox.put(output_mail);
-    return 0;
-}
-
-//
-// method:          display
-// description:     display the pertinents
-//
-// @param           none
-// @return          none
-//
-void ManualControl::display(void)
-{
-    string mapper[] = { "INIT",
-                        "STARTUP",
-                        "CONTROL_ON",
-                        "CONTROL_OFF"
-                      };
-
-    printf("\r\n");
-    std::cout << left << setw(10) << setfill(' ') << "manual: ";
-    std::cout << left << setw(40) << setfill(' ') << controlFile;
-    std::cout << left << setw(20) << setfill(' ') << id;
-    std::cout << left << setw(20) << setfill(' ') << output;
-    std::cout << left << setw(6)  << setfill(' ') << type;
-    std::cout << left << setw(6)  << setfill(' ') << priority;
-    std::cout << left << setw(8)  << setfill(' ') << duration;
-    //std::cout << left << setw(8)  << setfill(' ') << percent;
-    std::cout << left << setw(16) << setfill(' ') << mapper[currentState];
-    if ( type == MANUAL_CONTROL_TYPE_TIMED ) {
-        std::cout << left << setw(8) << setfill(' ') << "Time Remaining (secs): " << endTime - time(NULL);
-    }
-    std::cout.flush();
-}
\ No newline at end of file
--- a/ICE-Application/src/ConfigurationHandler/Controls/ManualControl.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-/******************************************************************************
- *
- * File:                ManualControl.h
- * Desciption:          ICE Manual Control Class
- *
- *****************************************************************************/
-#ifndef MANUALCONTROL_H
-#define MANUALCONTROL_H
-
-#include <string>
-#include <stdio.h>
-
-#define MANUAL_CONTROL_TYPE_NONE        0
-#define MANUAL_CONTROL_TYPE_CONTINUOUS  1
-#define MANUAL_CONTROL_TYPE_TIMED       2
-#define MANUAL_CONTROL_TYPE_SETPOINT    3
-
-typedef enum {
-    MANUAL_CONTROL_OK,
-    MANUAL_CONTROL_ERROR,
-    MANUAL_CONTROL_DESTROY
-} ManualControlError_t;
-
-//! Manual Control - implements a manual control.
-/// Each output, relay or analog, can be put into manual mode. Manual mode
-/// overrides automatic control of the output. A user can invoke manual mode over
-/// any output.
-///
-/// Manual On: User chooses the relay and sets the timed duration. The relay
-/// is turned ON. After the timed interval elapses, the output returns to its
-/// previous highest-prirority control. If the timed duratation is set to 0,
-/// the relay is turned on indefinitely.
-///
-/// Manual Off: Users chooses the relay and sets the timed duration The relay
-/// is turned OFF. After the timed interval elapses, the output returns to its
-/// previous highes-priority control. If the timed duration is set to 0, the
-/// relay is turned off indefinitley.
-/// @code
-/// #include "ManualControl.h"
-///
-/// int main(void)
-/// {
-///     ManualControl *m = new ManualControl();
-///     bool rc = m->load(controlFile);
-///     if ( rc != true ) {
-///         logError("%s: failed to load the manual control\n");
-///         delete m;
-///         exit(-1);
-///     }
-///
-///     m->start();
-///     for ( ;; ) {
-///         m->update();
-///     }
-/// }
-/// @endcode
-
-class ManualControl
-{
-private:
-    std::string         controlFile;        // name of the control file
-    std::string         id;                 // identifier
-    std::string         output;             // output
-    unsigned int        type;               // timed, continuous, setpoint
-    unsigned int        priority;           // control priority
-    unsigned int        duration;           // in seconds (not implemented)
-    float               setpoint;           // setpoint (not implemented)
-    unsigned int        state;              // ON or OFF
-    unsigned int        percent;            // analog/manual value
-    unsigned long       endTime;            // for timed control
-
-    enum State {
-        STATE_INIT,                     // init
-        STATE_STARTUP,                  // control has been started
-        STATE_CONTROL_ON,               // control is ON
-        STATE_CONTROL_OFF,              // control is OFF
-        STATE_CONTROL_FINISHED          // (timed) interval complete
-    };
-    State           currentState;
-
-    // validate the contents of the control file
-    bool validateControlData(const char *);
-
-    // assign control data from control file to object data
-    void copyControlData(const char *);
-
-    // power an output
-    int powerOutput(void);
-
-public:
-    /// create a manual control instance
-    ManualControl() {};
-
-    /// destructor
-    ~ManualControl() {
-        printf("\r%s invoked\n", __func__);
-    }
-    /// load a manual control instance with data from a JSON configuration file
-    /// @param filename name of the control file
-    /// @returns
-    ///   true on success,
-    ///   false on failure
-    bool load(std::string filename);
-
-    /// start a manual control instance
-    void start(void);
-
-    /// update a manual control instance (implements a simple state machine)
-    /// @returns
-    ///     MANUAL_CONTROL_OK,
-    ///     MANUAL_CONTROL_ERROR,
-    ///     MANUAL_CONTROL_DESTROY
-    ManualControlError_t update(void);
-
-    /// unregister a manual control from the output thread
-    int unregisterControl(void);
-
-    /// display pertinent data of a manual control instance
-    void display(void);
-
-    /// get control file
-    std::string getControlFile(void) const {
-        return controlFile;
-    }
-
-    /// get control identifier
-    std::string getId(void) const {
-        return id;
-    }
-
-    /// get associated output
-    std::string getOutput(void) const {
-        return output;
-    }
-
-    /// get manual control type
-    unsigned int getType(void) const {
-        return type;
-    }
-
-    /// get control priority
-    unsigned int getPriority(void) const {
-        return priority;
-    }
-
-    /// get control duration (timed)
-    unsigned int getDuration(void) const {
-        return duration;
-    }
-
-    /// get setpoint (unimplemented)
-    float getSetpoint(void) const {
-        return setpoint;
-    }
-
-    /// get manual control FSM state
-    unsigned int getState(void) const {
-        return state;
-    }
-
-    /// get analog out %
-    unsigned int getPercent(void) const {
-        return percent;
-    }
-};
-
-#endif
--- a/ICE-Application/src/ConfigurationHandler/Controls/PIDControl.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-// placeholder for PID control
--- a/ICE-Application/src/ConfigurationHandler/Controls/PIDControl.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-// placeholder for PID control
--- a/ICE-Application/src/ConfigurationHandler/Controls/SensorErrorControl.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,418 +0,0 @@
-/******************************************************************************
-*
-* File:                SensorErrorControl.cpp
-* Desciption:          ICE Sensor Error Control class implementation
-*
-*****************************************************************************/
-#include "SensorErrorControl.h"
-#include "cJSON.h"
-#include "ModbusMasterApi.h"
-#include "utilities.h"
-#include "ICELog.h"
-#include <string>
-#include <iostream>
-#include <iomanip>
-#include <stdarg.h>
-
-using namespace std;
-
-// for debugging - this can be set via the console command:
-//      "debug-se 1
-bool debugSensorError = false;
-
-static void debug(const char *fmt, ...)
-{
-    if ( debugSensorError ) {
-        va_list vargs;
-        va_start(vargs, fmt);
-        vfprintf(stdout, fmt, vargs);
-        va_end(vargs);
-    }
-}
-
-//
-// method:              load
-// description:         load data from the control file
-//
-// @param[in]           _controlFile -> the control file
-// @return              true if loaded; false otherwise
-//
-bool SensorErrorControl::load(const std::string _controlFile)
-{
-    controlFile = _controlFile;
-
-    // read the data into a buffer
-    char dataBuf[MAX_FILE_SIZE];
-
-    bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
-    if ( rc != true ) { 
-        logError("%s: failed to read %s", __func__, controlFile.c_str());
-        // caller should destroy the object
-        return false;
-    }
-
-    // validate the JSON formatted control data
-    if ( !validateControlData(dataBuf) ) {
-        logError("%s: failed to validate control data", __func__);
-        return false;
-    }
-
-    // copy the control data
-    copyControlData(dataBuf);
-    
-    ModbusValue val;
-    // validate the input 
-    if ( ModbusMasterReadRegister(input, &val) == false ) {
-        logError("%s failed to find input %s", id.c_str(), input.c_str());
-        return false;
-    }
-
-    isVirtualOutput = Util_isVirtualOutput(output) ? true : false;
-    return true;
-}
-
-//
-// @method:             validateControlData
-// @description:        vaqlidate the JSON formatted string
-//
-// @param[in]           buf -> JSON formatted string
-// @param[out]          none
-// @return              true if valid; false otherwise
-//
-bool SensorErrorControl::validateControlData(const char *buf)
-{
-    bool rc = true;
-
-    // parse the data
-    cJSON * root    = cJSON_Parse(buf);
-
-    if ( !cJSON_HasObjectItem(root, "id") ||
-            !cJSON_HasObjectItem(root, "priority") ||
-            !cJSON_HasObjectItem(root, "input") ||
-            !cJSON_HasObjectItem(root, "output") ||
-            !cJSON_HasObjectItem(root, "dutyCycle") ||
-            !cJSON_HasObjectItem(root, "interval") ) {
-        logError("%s: control file is missing expected tags", __func__);
-        rc = false;
-    }
-
-    cJSON_Delete(root);
-    return rc;
-}
-
-//
-// method:              copyControlData
-// description:         copy the data from the control file to the object
-//
-// @param[in]           buf -> JSON formatted string
-// @param[out]          none
-// @return              none
-//
-void SensorErrorControl::copyControlData(const char *buf)
-{
-    cJSON *root = cJSON_Parse(buf);
-
-    id                  = cJSON_GetObjectItem(root, "id")->valuestring;
-    priority            = atoi(cJSON_GetObjectItem(root, "priority")->valuestring);
-    input               = cJSON_GetObjectItem(root, "input")->valuestring;
-    output              = cJSON_GetObjectItem(root, "output")->valuestring;
-    dutyCycle.dutyCycle = atoi(cJSON_GetObjectItem(root, "dutyCycle")->valuestring);
-    dutyCycle.interval  = atoi(cJSON_GetObjectItem(root, "interval")->valuestring);
-
-    cJSON_Delete(root);
-}
-
-//
-// @method:             start
-// @description:        put the control in the start state
-//
-// @param[in]           none
-// @param[out]          none
-// @return              none
-//
-void SensorErrorControl::start(void)
-{
-    currentState = STATE_START;
-}
-
-//
-// @method              update
-// @description         run the simplified state machine
-//
-// @param[in]           none
-// @param[out]          none
-// @return              OK on success; error otherwise
-//
-SensorErrorControlError_t SensorErrorControl::update(void)
-{
-    SensorErrorControlError_t rc = SENSOR_ERROR_CONTROL_OK;
-
-    switch (this->currentState) {
-        case STATE_INIT:
-            // do nothing: control must be programmatically started
-            break;
-        case STATE_START:
-            if ( this->isSensorError() ) {
-                if ( dutyCycle.dutyCycle > 0 ) {
-                    this->startDutyTimer();
-                    this->currentState = STATE_DUTY_CYCLE_ON;
-                    sendMailToOutput(ACTION_CONTROL_ON);
-                    debug("\r%s: [STARTUP]->sensor error->[DUTY_CYCLE_ON] time=%lu\n", id.c_str(), time(0));
-                } else {
-                    // this is a fixed-off state
-                    this->stopDutyTimer();  // probably not needed
-                    this->currentState = STATE_DUTY_CYCLE_OFF;
-                    // tell the output task to turn off the relay
-                    sendMailToOutput(ACTION_CONTROL_OFF);
-                    debug("\r%s: [STARTUP]->sensor error (no duty)->[DUTY_CYCLE_OFF] %lu\n", id.c_str(), time(0));
-                }
-            } else {
-                // input signal is OK
-                debug("\r%s: [STARTUP]->OK->[OFF] %lu\n", id.c_str(), time(0));
-                this->currentState = STATE_CONTROL_OFF;
-            }
-            break;
-        case STATE_CONTROL_OFF:
-            if ( isSensorError() ) {
-                if ( dutyCycle.dutyCycle > 0 ) {
-                    this->startDutyTimer();
-                    this->currentState = STATE_DUTY_CYCLE_ON;
-                    sendMailToOutput(ACTION_CONTROL_ON);
-                    debug("\r%s: [STARTUP]->sensor error->[DUTY_CYCLE_ON] %lu\n", id.c_str(), time(0));
-                } else {
-                    // this is a fixed off state
-                    this->stopDutyTimer();  // probably not needed
-                    this->currentState = STATE_DUTY_CYCLE_OFF;
-                    // tell the output task to turn off the relay
-                    sendMailToOutput(ACTION_CONTROL_OFF);
-                    debug("\r%s: [STARTUP]->sensor error (no duty)->[DUTY_CYCLE_OFF] %lu\n", id.c_str(), time(0));
-                }
-            } else {
-                // input signal is OK, so don't do anything
-            }
-            break;
-        case STATE_DUTY_CYCLE_ON:
-            if ( !isSensorError() ) {
-                this->stopDutyTimer();
-                this->currentState = STATE_CONTROL_OFF;
-                this->unregisterControl();
-                debug("\r%s: [DUTY_CYCLE_ON]->no error->[OFF] %lu\n", id.c_str(), time(0));
-
-            } else if ( dutyOnExpired() )
-                if ( dutyCycle.dutyCycle < 100 ) {
-                    this->currentState = STATE_DUTY_CYCLE_OFF;
-                    sendMailToOutput(ACTION_CONTROL_OFF);
-                    debug("\r%s: [DUTY_CYCLE_ON]->on expired->[DUTY_CYCLE_OFF] %lu\n", id.c_str(), time(0));
-                } else {
-                    // fixed-on state
-                    // do nothing - we'll need to wait for the sensor error
-                    // to clear before something can happen
-                }
-            break;
-        case STATE_DUTY_CYCLE_OFF:
-            if ( !isSensorError() ) {
-                // there is no sensor error, so unregister the control and cleanup
-                this->stopDutyTimer();
-                this->currentState = STATE_CONTROL_OFF;
-                this->unregisterControl();
-                debug("\r%s: [DUTY_CYCLE_OFF]->no error->[OFF] %lu\n", id.c_str(), time(0));
-                stopDutyTimer();
-            } else if ( dutyOffExpired() ) {
-                if ( dutyCycle.dutyCycle > 0 ) {
-                    // we go back to the OFF state so the start and expiration
-                    // times are recalculated
-                    this->currentState = STATE_CONTROL_OFF;
-                    sendMailToOutput(ACTION_CONTROL_OFF);
-                    debug("\r%s: [DUTY_CYCLE_OFF]->off expired->[OFF] %lu\n", id.c_str(), time(0));
-                } else {
-                    // fixed-off state 
-                    // do nothing - we'll need to wait for the sensor error
-                    // to clear before something can happen
-                }
-            }
-            break;
-        default:
-            logError("%s: unknown state\n", __func__);
-            rc = SENSOR_ERROR_CONTROL_UNK_STATE;
-            break;
-    }
-    return rc;
-}
-
-//
-// @method:             isSensorError
-// @description:        reads the modbus register to get the error condition of
-//                      the input signal
-//
-// @param[in]           none
-// @param[out]          none
-// @return              true if in error; false otherwise
-//
-bool SensorErrorControl::isSensorError()
-{
-    ModbusValue val;
-
-    if ( ModbusMasterReadRegister(this->input, &val) != true ) {
-        logError("Failed to read %s\n", this->input.c_str());
-        return true;
-    } else if ( val.errflag ) {
-        // input is in sensor error
-        return true;
-    }
-    return false;
-}
-
-//
-// @method:             dutyOnExpired
-// @description:        returns true of duty ON time expired
-//
-// @param[in]           none
-// @param[out]          none
-// @return              true if expired; false otherwise
-//
-bool SensorErrorControl::dutyOnExpired(void)
-{
-    return (time(0) >= duty_timer.offTime);
-}
-
-//
-// @method:             dutyOffExpired
-// @description:        returns true of duty OFF time expired
-//
-// @param[in]           none
-// @param[out]          none
-// @return              true if expired; false otherwise
-//
-bool SensorErrorControl::dutyOffExpired(void)
-{
-    return (duty_timer.expirationTime < time(0));
-}
-
-//
-// method:          startDutyTimer
-// descrption:      start the sensor error duty-timer
-//
-// @param           none
-// @return          none
-//
-void SensorErrorControl::startDutyTimer(void)
-{
-    unsigned long currentTime = time(0);
-    unsigned long period      = dutyCycle.interval * 60;
-
-    duty_timer.offTime        = currentTime + ((double)period * ((double)dutyCycle.dutyCycle/100.0));
-    duty_timer.expirationTime = currentTime + period;
-
-    debug("\r%s:%s-> currentTime = %lu\n", __func__, id.c_str(), currentTime);
-    debug("\r%s:%s-> off Time    = %lu\n", __func__, id.c_str(), duty_timer.offTime);
-    debug("\r%s:%s-> expiration  = %lu\n", __func__, id.c_str(), duty_timer.expirationTime);
-}
-
-//
-// method:          stopDutyTimer
-// descrption:      stop the sensor error duty-timer
-//
-// @param           none
-// @return          none
-//
-void SensorErrorControl::stopDutyTimer(void)
-{
-    memset(&duty_timer, 0, sizeof(duty_timer));
-}
-
-//
-// method:          sendMailToOutput
-// description:     send a message to the output thread
-//
-// @param[in]       action -> on, off, etc.
-// @param[out]      none
-// @return
-//
-void SensorErrorControl::sendMailToOutput(OutputAction action)
-{
-
-    if ( isVirtualOutput ) {
-        debug("%s:%s updating the virtual output %s\n", __func__, id.c_str(), output.c_str());
-        ModbusMasterWriteRegister(this->output,
-                                  (action == ACTION_CONTROL_ON) ? 1.0 : 0.0);
-    } else {
-        debug("%s:%s sensor error control attempting to send action %d\n",
-              __func__, id.c_str(), action);
-
-        OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-        memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-        output_mail->action         = action;
-        output_mail->controlType    = CONTROL_SENSOR_ERROR;
-        output_mail->priority       = this->priority;
-
-        strncpy(output_mail->input_tag,  this->input.c_str(),  sizeof(output_mail->input_tag)-1);
-        strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-        strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-
-        OutputMasterMailBox.put(output_mail);
-    }
-}
-
-//
-// @method:             unregisterControl
-// @description:        unregister the control with the output task
-// 
-// @param[in]           none
-// @param[out]          none
-// @return              none
-//
-void SensorErrorControl::unregisterControl(void)
-{
-    if ( isVirtualOutput ) {
-        debug("%s: %s attempting to unregister virtual output %s\n", __func__, id.c_str(), output.c_str());
-        ModbusMasterWriteRegister(output, 0.0);
-    } else {
-        debug("%s: %s attempting to unregister output %s\n",
-              __func__, id.c_str(), output.c_str());
-
-        OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-        memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-        output_mail->action      = ACTION_CONTROL_UNREGISTER;
-        output_mail->controlType = CONTROL_FAILSAFE;
-        output_mail->priority     = this->priority;
-        strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-        strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-
-        OutputMasterMailBox.put(output_mail);
-    }
-}
-
-//
-// @method:             display
-// @description:        show the pertinents
-//
-// @param[in]           none
-// @param[out]          none
-// @return              none
-//    
-void SensorErrorControl::display(void)
-{
-    const char *mapper[] = { "INIT",
-                             "START",
-                             "OFF",
-                             "DUTY CYCLE ON",
-                             "DUTY CYCLE OFF",
-                             "invalid"
-                           };
-
-    printf("\r\n");
-    std::cout << left << setw(10) << setfill(' ') << "sensor error: ";
-    std::cout << left << setw(40) << setfill(' ') << controlFile;
-    std::cout << left << setw(20) << setfill(' ') << id;
-    std::cout << left << setw(6)  << setfill(' ') << priority;
-    std::cout << left << setw(20) << setfill(' ') << input;
-    std::cout << left << setw(20) << setfill(' ') << output;
-    std::cout << left << setw(16) << setfill(' ') << mapper[currentState];
-    std::cout << "duty cycle: " << left << setw(4) << setfill(' ') << dutyCycle.dutyCycle;
-    std::cout << "interval: "   << left << setw(4) << setfill(' ') << dutyCycle.interval;
-
-    std::cout.flush();
-}
-
--- a/ICE-Application/src/ConfigurationHandler/Controls/SensorErrorControl.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-#ifndef SENSORERRORCONTROL_H
-#define SENSORERRORCONTROL_H
-
-#include <stdio.h>
-#include <string>
-#include <time.h>
-
-#include "global.h"
-
-typedef enum {
-    SENSOR_ERROR_CONTROL_OK,
-    SENSOR_ERROR_CONTROL_UNK_STATE,
-    SENSOR_ERROR_CONTROL_ERROR,
-} SensorErrorControlError_t;
-
-//! SensorErrorControl - implements a sensor error control by reading an input's
-// error flag and manipulating an output (duty-cycle style)
-class SensorErrorControl
-{
-private:
-    std::string     controlFile;                // the control file
-    std::string     id;                         // unique control identifier
-    std::string     input;                      // sensor to read
-    std::string     output;                     // output to manipulate
-    unsigned int    priority;                   // control priority (typically  450)
-
-    typedef struct dutyCycle_tag {
-        unsigned int    dutyCycle;              // on-time (percentage)
-        unsigned int    interval;               // in minutes
-    } dutyCycle_t;
-
-    dutyCycle_t     dutyCycle;
-
-    typedef struct timer_tag {
-        unsigned long   offTime;                // epoch time
-        unsigned long   expirationTime;         // epoch time
-    } Timer_t;
-
-    Timer_t         duty_timer;                 // the duty timer
-
-    enum State {
-        STATE_INIT,                             // object instantiated
-        STATE_START,                            // control has been started
-        STATE_CONTROL_OFF,                      // control is not above/below limit
-        STATE_DUTY_CYCLE_ON,                    // in sensor error, duty-cycle ON
-        STATE_DUTY_CYCLE_OFF,                   // in sensor error, duty-cycle OFF
-        STATE_MAX
-    };
-
-    State currentState;                         // current state
-    bool  isVirtualOutput;                      // output is virtual
-
-    bool validateControlData(const char *buf);  // validate JSON control data
-    void copyControlData(const char *buf);      // copy JSON data to control data
-    
-    bool isSensorError(void);                   // input sig is in sensor error
-
-    void startDutyTimer(void);                  // start the duty timer
-    void stopDutyTimer(void);                   // stop the duty timer
-
-    bool dutyOnExpired(void);                   // boolean check if duty ON-time expired
-    bool dutyOffExpired(void);                  // boolean check if duty OFF-time expired
-    
-    void sendMailToOutput(OutputAction action);
-public:
-    /// Create a sensor-error control instance
-    SensorErrorControl() {
-        currentState = STATE_INIT;
-        isVirtualOutput = false;
-    }
-    /// Destroy a sensor-error control instance
-    ~SensorErrorControl() {
-        // "erased...from existence!" -- Doc Brown
-        printf("\r%s invoked\n", __func__);
-    }
-
-    /// load a sensor-error control instance with data from a JSON configuration file
-    bool load(std::string filename);
-
-    /// start a sensor-error control instance
-    void start(void);
-
-    /// update this sensor error control instance
-    SensorErrorControlError_t update(void);
-
-    /// unregister a failsafe control instance
-    void unregisterControl(void);
-
-    /// display the pertinent data of this sensor error  control instance
-    void display(void);
-
-    /// get control file
-    std::string getControlFile() const {
-        return controlFile;
-    }
-
-    /// get control identifier
-    std::string getId() const {
-        return id;
-    }
-};
-
-#endif // SENSORERRORCONTROL_H
-
--- a/ICE-Application/src/ConfigurationHandler/Controls/SequenceControl.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,546 +0,0 @@
-/******************************************************************************
-*
-* File:                SequenceControl.cpp
-* Desciption:          ICE Sequence Control class implementation
-*
-*****************************************************************************/
-
-#include "SequenceControl.h"
-#include "ICELog.h"
-#include "cJSON.h"
-#include "global.h"
-
-#include <stdlib.h>
-#include <vector>
-#include <string>
-#include <iostream>
-#include <iomanip>
-#include <stdarg.h>
-#include <assert.h>
-#include "ModbusMasterApi.h"
-#include "ConfigurationHandler.h"
-
-// for debugging - this can be set via the console command:
-//      "debug-se 1
-bool debugSequenceControl = false;
-
-static void debug(const char *fmt, ...)
-{
-    if ( debugSequenceControl ) {
-        va_list vargs;
-        va_start(vargs, fmt);
-        vfprintf(stdout, fmt, vargs);
-        va_end(vargs);
-    }
-}
-
-//
-// method:          load
-// decsription:     load data from the control file
-//
-// @param[in]       _controlFile -> the control file
-// @param[out]      none
-// @return          true on success; false on error
-//
-bool SequenceControl::load(std::string _controlFile)
-{
-    controlFile = _controlFile;
-
-    // read the data into a buffer
-    char dataBuf[MAX_FILE_SIZE*3];
-    bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
-    if ( rc != true ) {
-        logError("%s: failed to read %d bytes from %s", __func__, sizeof(dataBuf), controlFile.c_str());
-        // caller should destroy the object
-        return false;
-    }
-
-    // validate the JSON tags in the control file
-    if ( validateControlData(dataBuf) != true ) {
-        logError("%s: invalid control data.", __func__);
-        return false;
-    }
-
-    // assign object data from control file
-    copyControlData(dataBuf);
-    
-    // TODO: perform additional validation 
-
-    return true;
-}
-
-
-
-// method:          validateControlData
-// description:     validates the data in the control file
-//
-// @param[in]       dataBuf -> JSON formatted string
-// @param[out]      non
-// @return          true if valid; false otherwise
-//
-bool SequenceControl::validateControlData(const char *dataBuf)
-{
-    // parse the json data
-    bool rc = true;
-    cJSON * root = cJSON_Parse(dataBuf);
-
-    // parse the control header
-    if ( !cJSON_HasObjectItem(root, "id") ||
-            !cJSON_HasObjectItem(root, "startTrigger") ||
-            !cJSON_HasObjectItem(root, "sequence") ) {
-        logError("Sequence Control is missing expected tags");
-        cJSON_Delete(root);
-        return false;
-    }
-
-    // validate the sequence table
-    cJSON *sequenceTable  = cJSON_GetObjectItem(root, "sequence");
-    for ( int i = 0; i < cJSON_GetArraySize(sequenceTable); ++i ) {
-        cJSON *entry = cJSON_GetArrayItem(sequenceTable, i);
-        if ( !cJSON_HasObjectItem(entry, "startTrigger") ) {
-            logError("Sequence Table missing startTrigger tag");
-            rc = false;
-            break;
-        }
-        if ( !cJSON_HasObjectItem(entry, "actions") ) {
-            logError("Sequence table is missing actions tag");
-            rc = false;
-            // FIXME: finish the internals 
-            break;
-        }
-        if ( !cJSON_HasObjectItem(entry, "stopTrigger") ) {
-            logError("Sequence table is missing stopTrigger tag");
-            rc = false;
-            break;
-        }
-    }
-
-    cJSON_Delete(root);
-    return rc;
-}
-
-//
-// method:          copyControlData
-// description:     copy JSON formatted control data to object
-//
-// @param[in]       dataBuf -> JSON formatted data
-// @param[out]      none
-// @return          none
-//
-void SequenceControl::copyControlData(const char* dataBuf)
-{
-    cJSON *root = cJSON_Parse(dataBuf);
-
-    id           = cJSON_GetObjectItem(root, "id")->valuestring;
-    startTrigger = cJSON_GetObjectItem(root, "startTrigger")->valuestring;
-
-    // validate the sequence table
-    cJSON *sequenceTable  = cJSON_GetObjectItem(root, "sequence");
-    for ( int i = 0; i < cJSON_GetArraySize(sequenceTable); ++i ) {
-        cJSON *entry = cJSON_GetArrayItem(sequenceTable, i);
-
-        SequenceEntry n;
-
-        n.startTrigger = cJSON_GetObjectItem(entry, "startTrigger")->valuestring;
-        n.stopTrigger  = cJSON_GetObjectItem(entry, "stopTrigger")->valuestring;
-
-        cJSON *actionList = cJSON_GetObjectItem(entry, "actions");
-        for ( int j = 0; j < cJSON_GetArraySize(actionList); ++j ) {
-            cJSON *list = cJSON_GetArrayItem(actionList, j);
-            Action_t a;
-            a.action = cJSON_GetObjectItem(list, "action")->valuestring;
-            a.id     = cJSON_GetObjectItem(list, "id")->valuestring;
-            if ( a.action == "assign" ) {
-                a.value = atof(cJSON_GetObjectItem(list, "val")->valuestring);
-            } else {
-                a.value = 0;
-            }
-            n.actions.push_back(a);
-        }
-        // push this entry onto this sequence table
-        this->sequenceTable.push_back(n);
-    }
-
-    cJSON_Delete(root);
-}
-
-//
-// method:          start
-// decsription:     start the sequence control
-//
-// @param[in]       none
-// @param[out]      none
-// @return          none
-//
-void SequenceControl::start(void)
-{
-    currentState = SEQ_STATE_START;
-}
-
-//
-// method:          run
-// decsription:     run the sequence control (performs the updates)
-//
-// @param[in]       none
-// @param[out]      none
-// @return          OK on success; error otherwise
-//
-SequenceControlError_t SequenceControl::run(void)
-{
-    SequenceControlError_t rc = SEQUENCE_CONTROL_OK;
-
-    switch ( this->currentState ) {
-        case SEQ_STATE_INIT:
-            // do nothing
-            break;
-        case SEQ_STATE_START:
-            // here we need to wait for the start trigger to happen
-            if ( this->isControlStartTriggerOn() ) {
-                debug("\r%s: [START]->start trigger->[LOADING]\n", id.c_str());
-                ModbusValue val;
-                ModbusMasterReadRegister(startTrigger, &val);
-                debug("\r%s:%s: val.value = %f\n", id.c_str(), startTrigger.c_str(), val.value);
-                currentState = SEQ_STATE_LOADING_NEXT_ENTRY;
-            } else {
-                // just continue waiting for the start trigger to fire
-            }
-            break;
-        case SEQ_STATE_LOADING_NEXT_ENTRY: {
-            // this is a transient state
-            bool rc = this->loadNextEntry();
-            if ( rc ) {
-                debug("\r%s: [LOADING]->next entry->[WAIT-START]\n", id.c_str());
-                currentState = SEQ_STATE_WAITING_START;
-            } else {
-                debug("\r%s: [LOADING]->no entries->[FINISHED]\n", id.c_str());
-                currentState = SEQ_STATE_FINISHED;
-            }
-            break;
-        }
-        case SEQ_STATE_WAITING_START:
-            // wait for the start triggers to evaluate to true
-            if ( this->isCurrentEntryStartTriggerOn() ) {
-                debug("\r%s: [WAIT-START]->perform actions->[WAIT-STOP]\n", id.c_str());
-                performActions();
-                currentState = SEQ_STATE_WAITING_STOP;
-            } else {
-                // wait until the start trigger fires
-            }
-            break;
-        case SEQ_STATE_WAITING_STOP:
-            // wait for the stop triggers to evaluate to true
-            if ( this->isCurrentEntryStopTriggerOn() ) {
-                debug("\r%s: [WAIT-STOP]->stop trigger ON->[LOAD NEXT]\n", id.c_str());
-                currentState = SEQ_STATE_LOADING_NEXT_ENTRY;
-            } else {
-                // continue waiting
-            }
-            break;
-        case SEQ_STATE_FINISHED:
-            // do any cleanup work that's needed here.
-            debug("\r%s: [FINISHED]->clearing the reg->[START]\n", id.c_str());
-            ModbusMasterWriteRegister(this->startTrigger, 0);
-            this->currentState = SEQ_STATE_START;
-            break;
-        case SEQ_STATE_MAX:
-        default:
-            logError("%s: unknown state %u\n", __func__, this->currentState);
-            rc = SEQUENCE_CONTROL_UNK_STATE;
-            break;
-    }
-    return rc;
-}
-
-//
-// method:          isControlStartTriggerOn
-// description:     true if the start trigger evals to true
-//
-// @param[in]       none
-// @param[out]      none
-// @return          true if start trigger > 0; false otherwise
-//
-bool SequenceControl::isControlStartTriggerOn(void)
-{
-    ModbusValue value;
-    bool rc = ModbusMasterReadRegister(this->startTrigger, &value);
-    if ( rc && value.value ) {
-        return true;
-    }
-
-    return false;
-}
-
-//
-// method:          isCurrentEntryStartTriggerOn
-// description;     true the current sequence entry start trigger evals to true
-//
-// @param[in]       none
-// @param[out]      none
-// @return          none
-//
-bool SequenceControl::isCurrentEntryStartTriggerOn(void)
-{
-    ModbusValue value;
-    bool rc = ModbusMasterReadRegister(this->currentEntry.startTrigger, &value);
-    if ( rc != true ) {
-        logError("%s: failed to read %s from modbus master",
-                 __func__, this->currentEntry.startTrigger.c_str());
-        return rc;
-    } else if ( value.value ) {
-        debug("\r%s:%s-> returning true\n", __func__, id.c_str());
-        return true;
-    }
-    return false;
-}
-
-//
-// method:          isCurrentEntryStopTriggerOn
-// description;     true the current sequence entry start trigger evals to true
-//
-// @param[in]       none
-// @param[out]      none
-// @return          none
-//
-bool SequenceControl::isCurrentEntryStopTriggerOn(void)
-{
-    ModbusValue value;
-    bool rc = ModbusMasterReadRegister(this->currentEntry.stopTrigger, &value);
-    if ( rc != true ) {
-        logError("%s: failed to read %s from modbus master",
-                 __func__, this->currentEntry.stopTrigger.c_str());
-        return rc;
-    } else if ( value.value ) {
-        debug("\r%s:%s-> returning true\n", __func__, id.c_str());
-        return true;
-    }
-    return false;
-}
-
-//
-// method:          loadNextEntry
-// description:     load the next entry from the sequence table
-//
-// @param[in]       none
-// @param[out[      none
-// @return          true is loaded; false otherwise
-//
-bool SequenceControl::loadNextEntry(void)
-{
-    if ( this->sequenceTable.empty() ) {
-        debug("\r%s: sequence table is empty\n", id.c_str());
-        return false;
-    }
-    if ( nextEntryIndex < this->sequenceTable.size() ) {
-        currentEntry = sequenceTable.at(nextEntryIndex++);
-        printf("\r...successfully loaded new entry\n");
-        return true;
-    }
-    return false;
-}
-
-//
-// method:          performActions
-// description:     perform the actions associated with the current entry
-//
-// @param[in]       none
-// @param[out]      none
-// @return          none
-//
-SequenceControlError_t SequenceControl::performActions(void)
-{
-    SequenceControlError_t rc = SEQUENCE_CONTROL_OK;
-
-    // possible action types:
-    //      create      -> create a control
-    //      delete      -> delete a control
-    //      modify      -> modify a control
-    //      assign      -> assign a value to a modbus register 
-    //      execute     -> execute a script
-    if ( !currentEntry.actions.empty() ) {
-        std::vector<Action_t>::const_iterator pos;
-        for ( pos = currentEntry.actions.begin(); pos != currentEntry.actions.end(); ++pos ) {
-            debug("\raction->%s on ID->%s\n", pos->action.c_str(), pos->id.c_str());
-            // based on the action, we need to determine what to do
-            // 1: determine the action
-            // 2: see if the file exists (catastrophic)
-            // 3: if it's a create or delete action, send a message to the
-            //    configuration handler
-            if ( pos->action == "createsp" ) {
-                rc = createSubControl(pos->id, CONTROL_SETPOINT);
-                assert(!rc);
-            } else if ( pos->action == "createtm" ) {
-                rc = createSubControl(pos->id, CONTROL_TIMER);
-                assert(!rc);
-            } else if ( pos->action == "deletesp" ) {
-                rc = destroySubControl(pos->id, CONTROL_SETPOINT);
-                assert(!rc);
-            } else if ( pos->action == "deletetm" ) {
-                rc = destroySubControl(pos->id, CONTROL_TIMER);
-                assert(!rc);
-            } else if ( pos->action == "execute"  ) {
-                  // not implemented 
-            } else if ( pos->action == "assign"   ) {
-              if ( assignRegister(pos->id, pos->value) != true ) {
-                  assert(0);
-              }
-            } else {
-                logError("%s: unknown action %s (%s)", __func__, pos->action.c_str(), pos->id.c_str());
-                rc = SEQUENCE_CONTROL_BAD_ACTION;
-            }
-        }
-    } else {
-        logInfo("%s: no entries in the action table", __func__);
-    }
-    return rc;
-}
-
-//
-// method:              createSubControl
-// description:         create a control that's listed in the sequence table
-//
-// @param[in]           action (create, destroy, etc.)
-// @param[in]           id -> control identifier
-// @param[out[          none
-// @return              OK on success; error otherwise
-//
-SequenceControlError_t SequenceControl::createSubControl(const std::string controlId,     
-                                                         Control_t type) 
-{
-    std::string file_prefix;
-    
-    switch (type) {
-        case CONTROL_SETPOINT:
-            file_prefix = CONTROL_SP_STR;
-            break;
-        case CONTROL_TIMER:
-            file_prefix = CONTROL_TM_STR;
-            break;
-        default:
-            logError("%s %s unsupported type %d", __func__, id.c_str(), type);
-            return SEQUENCE_CONTROL_BAD_CONTROL_TYPE;
-    }
-    
-    char filename[64];
-    snprintf(filename, sizeof(filename), "%s%s_%s%s.json", 
-               SEQUENCE_CONTROL_FILENAME_PREFIX, 
-               this->id.c_str(), 
-               file_prefix.c_str(),
-               controlId.c_str());
-               
-    debug("\r%s: searching for %s\n", id.c_str(), filename);
-    
-    // send a message to the configuration handler to create the control
-    ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = ACTION_CREATE;
-    msg->control = (Control_t)type;
-    strncpy(msg->controlFile, filename, sizeof(msg->controlFile)-1);
-
-    printf("%s: Sending a create request for control %s\r\n",
-           __func__, msg->controlFile);
-
-    ConfigHandlerMailBox.put(msg);
-
-    return SEQUENCE_CONTROL_OK;
-}
-
-//
-// method:              destroySubControl
-// description:         destroy a control that's listed in the sequence table
-//
-// @param[in]           action (create, destroy, etc.)
-// @param[in]           id -> control identifier
-// @param[out[          none
-// @return              OK on success; error otherwise
-//
-SequenceControlError_t SequenceControl::destroySubControl(const std::string controlId,
-                                                          Control_t type)
-{
-    std::string file_prefix;
-    
-    switch (type) {
-        case CONTROL_SETPOINT:
-            file_prefix = CONTROL_SP_STR;
-            break;
-        case CONTROL_TIMER:
-            file_prefix = CONTROL_TM_STR;
-            break;
-        default:
-            logError("%s %s unsupported type %d", __func__, id.c_str(), type);
-            return SEQUENCE_CONTROL_BAD_CONTROL_TYPE;
-    }
-    
-    char filename[64];
-    snprintf(filename, sizeof(filename), "%s%s_%s%s.json", 
-               SEQUENCE_CONTROL_FILENAME_PREFIX, 
-               this->id.c_str(), 
-               file_prefix.c_str(),
-               controlId.c_str());
-               
-    debug("\r%s: searching for %s\n", id.c_str(), filename);
-
-    // send a message to the configuration handler to create the control
-    ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = ACTION_DESTROY;
-    msg->control = (Control_t)type;
-    strncpy(msg->controlFile, filename, sizeof(msg->controlFile)-1);
-
-    printf("%s: Sending a create request for control %s\r\n",
-           __func__, msg->controlFile);
-
-    ConfigHandlerMailBox.put(msg);
-
-    return SEQUENCE_CONTROL_OK;
-}
-
-bool SequenceControl::assignRegister(const std::string id, float value)
-{
-    return (ModbusMasterWriteRegister(id, value));
-}
-
-//
-// method:          display
-// decsription:     display the control data
-//
-// @param[in]       none
-// @param[out]      none
-// @return          none
-//
-void SequenceControl::display(void)
-{
-    const char *mapper[] = { "INIT",
-                             "START",
-                             "LOADING",
-                             "WAIT-START",
-                             "WAIT-STOP",
-                             "FINISHED",
-                             "FAILED",
-                             "NULL"
-                           };
-
-    printf("\rid-> %s\n", id.c_str());
-    printf("\rstartTrigger-> %s\n",  startTrigger.c_str());
-    printf("\rSequenceTable: \n");
-
-    std::vector<SequenceEntry>::const_iterator seqIt;
-
-    int entry = 0;
-
-    for ( seqIt = sequenceTable.begin(); seqIt != sequenceTable.end(); ++seqIt ) {
-        printf("\rEntry %d: %s\n \r  startTrigger: %s\n",
-               ++entry,
-               (entry == nextEntryIndex-1) ? "<-currently active" : "",
-               seqIt->startTrigger.c_str());
-        std::vector<Action_t>::const_iterator actIt;
-        for ( actIt = seqIt->actions.begin(); actIt != seqIt->actions.end(); ++actIt ) {
-            printf("\r\taction-> %s, id-> %s ", actIt->action.c_str(), actIt->id.c_str());
-            if ( actIt->action == "assign" ) printf("value -> %f", actIt->value);
-            printf("\r\n");
-        }
-        printf("\r  stopTrigger: %s\n", seqIt->stopTrigger.c_str());
-    }
-
-    printf("\r\n\rcurrent state = %s\r\n\r\n", mapper[this->currentState]);
-}
-
--- a/ICE-Application/src/ConfigurationHandler/Controls/SequenceControl.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/******************************************************************************
- *
- * File:                SetpointControl.h
- * Desciption:          ICE Timer Control Class
- *
- *****************************************************************************/
-#ifndef SEQUENCECONTROL_H
-#define SEQUENCECONTROL_H
-
-#include <global.h>
-#include <string>
-#include <stdio.h>
-#include <vector>
-
-#define SEQUENCE_CONTROL_DEBUG
-#define SEQUENCE_CONTROL_FILENAME_PREFIX    "seq_"
-
-typedef enum {
-    SEQUENCE_CONTROL_OK,
-    SEQUENCE_CONTROL_UNK_STATE,
-    SEQUENCE_CONTROL_ERROR,
-    SEQUENCE_CONTROL_DESTROY,
-    SEQUENCE_CONTROL_BAD_CONTROL_TYPE,
-    SEQUENCE_CONTROL_BAD_ACTION
-} SequenceControlError_t;
-
-//! SequenceControl - implements a sequence control that is comprised of 
-// sub-controls and operations to achieve a sequence of activities.
-class SequenceControl
-{
-private:
-    std::string     controlFile;                // the control file
-    std::string     id;                         // unique identifier 
-    std::string     startTrigger;               // start trigger: once the start
-                                                // trigger evals to true, the 
-                                                // control will start executing
-                                                // the entries in the sequence table
-                                                
-    typedef struct Action_tag {
-        std::string action;                     // create/delete/execute
-        std::string id;                         // control, vreg or script identifier 
-        float value;                            // for assignment action 
-    } Action_t; 
-        
-    // A Sequence Entry:
-    //
-    //      startTrigger    -> an expression that evals to true
-    //      actions[]       -> list of actions to perform when the start condition is satisfied
-    //      stopTrigger     -> an expression that evals to true
-    //
-    typedef struct SequenceEntry_tag { 
-        std::string             startTrigger;   // trigger to load the sequence
-        std::vector<Action_t>   actions;        // actions to perform
-        std::string             stopTrigger;    // trigger to load the next entry
-    } SequenceEntry;
-
-    // the sequence table
-    std::vector<SequenceEntry>  sequenceTable; 
-    
-    // state machine information
-    enum SequenceControlState_t {
-        SEQ_STATE_INIT,                     // object successfully created
-        SEQ_STATE_START,                    // object programmatically started
-        SEQ_STATE_LOADING_NEXT_ENTRY,       // loading the next entry (transient)
-        SEQ_STATE_WAITING_START,            // waiting for entry start trigger(s)
-        SEQ_STATE_WAITING_STOP,             // waiting for entry stop trigger(s)
-        SEQ_STATE_FINISHED,                 // finished with all entries in the sequence table
-        SEQ_STATE_FAILED,                   // something went awry
-        SEQ_STATE_MAX                       
-    };
-    
-    SequenceControlState_t  currentState;   // control's current state
-    SequenceEntry           currentEntry;   // currently loaded entry in the seq table     
-    unsigned int            nextEntryIndex; // next entry index      
-    
-    /// validate the contents of the control file 
-    bool validateControlData(const char *);
-    
-    /// assign control data from control file to object data
-    void copyControlData(const char *);
-    
-    /// has the control starting trigger fired?
-    bool isControlStartTriggerOn(void);
-    
-    /// has the sequence entry starting trigger fired?
-    bool isCurrentEntryStartTriggerOn(void);
-    
-    /// has the sequence entry stopping trigger fired?
-    bool isCurrentEntryStopTriggerOn(void);
-    
-    /// load the next entry from the sequence table
-    bool loadNextEntry(void);
-    
-    /// perform the actions from the sequence entry
-    SequenceControlError_t performActions(void);
-    
-    /// create a control from the sequence table
-    SequenceControlError_t createSubControl(const std::string controlId, 
-                                            Control_t type);
-    
-    /// delete a control from the sequence table
-    SequenceControlError_t destroySubControl(const std::string controlId,
-                                             Control_t type);
-    
-    /// assign a virtual register
-    bool assignRegister(const std::string id, float value);
-    
-public:
-    /// create  a sequence control
-    SequenceControl() {
-        currentState = SEQ_STATE_INIT;
-        nextEntryIndex = 0;
-    };
-    /// destructor
-    ~SequenceControl() {
-        printf("\r%s invoked\n", __func__);
-    }
-
-    /// load sequence control data from a JSON configuration file
-    bool load(std::string filename);
-    
-    /// start the sequence control
-    void start(void);
-    
-    /// the motor 
-    SequenceControlError_t run(void);
-    
-    /// display the pertinents 
-    void display(void);
-    
-    /// get sequence control identifier
-    std::string getId(void) const { return id; }
-    
-    /// get starting trigger 
-    std::string getStartTrigger(void) const { return startTrigger; } 
-};
-
-#endif
-
--- a/ICE-Application/src/ConfigurationHandler/Controls/SetpointControl.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,369 +0,0 @@
-/******************************************************************************
-*
-* File:                SetpointControl.cpp
-* Desciption:          ICE Setpoint Control class implementation
-*
-*****************************************************************************/
-#include "SetpointControl.h"
-#include "ICELog.h"
-#include "cJSON.h"
-#include "ModbusMasterApi.h"
-#include "global.h"
-#include "utilities.h"
-#include <string>
-#include <iostream>
-#include <iomanip>
-#include <stdarg.h>
-#include <stdlib.h>
-
-// for debugging - this can be set via the console command:
-//      "debug-sp 1 or debug-sp 0
-bool debugSetpointControl = false;
-
-static void debug(const char *fmt, ...)
-{
-    if ( debugSetpointControl ) {
-        va_list vargs;
-        va_start(vargs, fmt);
-        vfprintf(stdout, fmt, vargs);
-        va_end(vargs);
-    }
-}
-
-#ifdef MDOT_ICE
-extern mDot *GLOBAL_mdot;
-#endif 
-
-//
-// method:          load
-// description:     open the configuration file and assign data to the
-//                  setpoint control object
-//
-// @param           controlFile -> name of the control file
-// @return          true if data is assigned; false on error
-//
-bool SetpointControl::load(std::string _controlFile)
-{
-    controlFile = _controlFile;
-
-    char dataBuf[MAX_FILE_SIZE];
-    
-    // read the control data 
-    bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
-    if ( rc != true ) {
-        logError("%s: failed to read %s", __func__, controlFile.c_str());
-        // caller should destroy the object
-        return false;
-    }
-
-    // validate control data 
-    if ( !validateControlData(dataBuf) ) {
-        logError("%s: failed to validate control data", __func__);
-        return false;
-    }
-
-    // copy  control data
-    copyControlData(dataBuf);
-    
-    ModbusValue val;
-    // validate the input & output 
-    if ( ModbusMasterReadRegister(input, &val) == false ) {
-        logError("%s failed to find the input %s", id.c_str(), input.c_str());
-        return false; 
-    }
-    if ( ModbusMasterReadRegister(output, &val) == false ) {
-        logError("%s failed to find output %s", id.c_str(), output.c_str());
-        return false;
-    }
-
-    isVirtualOutput = Util_isVirtualOutput(output) ? true : false;
-    return true;
-}
-
-//
-// method:          validateControlData
-// description:     validate JSON formatted string
-//
-bool SetpointControl::validateControlData(const char *buf)
-{
-    bool rc = true;
-    cJSON * root = cJSON_Parse(buf);
-
-    if ( !cJSON_HasObjectItem(root, "id") ||
-            !cJSON_HasObjectItem(root, "priority") ||
-            !cJSON_HasObjectItem(root, "input") ||
-            !cJSON_HasObjectItem(root, "output") ||
-            !cJSON_HasObjectItem(root, "setpoint") ||
-            !cJSON_HasObjectItem(root, "prodfact") ||
-            !cJSON_HasObjectItem(root, "actingDir") ||
-            !cJSON_HasObjectItem(root, "tol") ) {
-        logError("Setpoint control is missing expected tags\n");
-        rc = false;
-    }
-
-    cJSON_Delete(root);
-    return rc;
-}
-
-//
-// method:          copyControlData
-// description:     copy JSON formatted data
-//
-void SetpointControl::copyControlData(const char *buf)
-{
-    cJSON * root = cJSON_Parse(buf);
-
-    id              = cJSON_GetObjectItem(root,"id")->valuestring;
-    priority        = atoi(cJSON_GetObjectItem(root,"priority")->valuestring);
-    input           = cJSON_GetObjectItem(root,"input")->valuestring;
-    output          = cJSON_GetObjectItem(root,"output")->valuestring;
-    setpoint        = atof(cJSON_GetObjectItem(root,"setpoint")->valuestring);
-    productFactor   = atof(cJSON_GetObjectItem(root, "prodfact")->valuestring);
-    actingDir       = atoi(cJSON_GetObjectItem(root, "actingDir")->valuestring);
-    tolerance       = atof(cJSON_GetObjectItem(root, "tol")->valuestring);
-
-    cJSON_Delete(root);
-}
-
-//
-// method:          start
-// description:     start the setpoint control
-//
-// @param           none
-// @return          none
-//
-void SetpointControl::start(void)
-{
-    // this is the initial state; what else needs to be done??
-    this->currentState = STATE_STARTUP;
-}
-
-//
-// method:
-// description:     based on the state of the control, check for
-//                  under limit and over limit values, adjust the
-//                  state accordingly
-//
-// @param           none
-// @return          none
-//
-SetpointControlError_t SetpointControl::update(void)
-{
-    SetpointControlError_t  rc = SETPOINT_CONTROL_OK;
-
-    switch (this->currentState) {
-        case STATE_INIT:
-            // do nothing
-            break;
-        case STATE_STARTUP:
-            if ( this->underLimit() ) {
-                // start the feed right away
-                this->startFeed();
-                this->currentState = STATE_CONTROL_ON;
-                debug("\r%s: [START]->under limit->[ON]\n", id.c_str());
-            } else {
-                this->currentState = STATE_CONTROL_OFF;
-                this->stopFeed();
-                debug("\r%s: [START]->!under limit->[OFF]\n", id.c_str());
-            }
-            break;
-        case STATE_CONTROL_ON:
-            if ( this->overLimit() ) {
-                // stop the feed
-                this->stopFeed();
-                this->currentState = STATE_CONTROL_OFF;
-                debug("\r%s: [ON]->over limit->[OFF]\n", id.c_str());
-            } else {
-                // do nothing
-            }
-            break;
-        case STATE_CONTROL_OFF:
-            if ( this->underLimit() ) {
-                // start the feed
-                this->startFeed();
-                this->currentState = STATE_CONTROL_ON;
-                debug("\r%s: [OFF]->under limit->[ON]\n", id.c_str()); 
-            } else {
-                // do nothing
-            }
-            break;
-        default:
-            rc = SETPOINT_CONTROL_UNK_STATE;
-            break;
-    }
-    return rc;
-}
-
-//
-// method:              overLimit
-// description:         (see @return)
-//
-// @param               none
-// @return              true if product is over the upper limit for normal mode
-//                      or under the limit for reverse mode; false otherwise
-//
-bool SetpointControl::overLimit(void)
-{
-    ModbusValue value;
-    ModbusMasterReadRegister( input, &value );
-    float flimit;
-
-    if ( !actingDir ) {
-        flimit = setpoint + tolerance;
-        return (value.value >= flimit);
-    } else {
-        flimit = setpoint - tolerance;
-        return (value.value <= flimit);
-    }
-}
-
-//
-// method:              underLimit
-// description:         (see @return)
-//
-// @param               none
-// @return              true if product is under lower limit for normal mode or
-//                      over the upper limit for reverse mode; false otherwise
-//
-bool SetpointControl::underLimit(void)
-{
-    ModbusValue value;
-    ModbusMasterReadRegister( input, &value );
-    float  flimit;
-
-    if ( !actingDir ) {
-        flimit = setpoint - tolerance;
-        return (value.value <= flimit);
-    } else {
-        flimit = setpoint + tolerance;
-        return (value.value >= flimit);
-    }
-}
-
-//
-// method:              startFeed()
-// description:         send ON indication to Output Master for this control's
-//                      relay
-//
-// @param               none
-// @return              none
-//
-void SetpointControl::startFeed(void)
-{
-    logInfo("%s: %s attempting to start feed on relay %s\n",
-            __func__, controlFile.c_str(), output.c_str());
-
-    if ( isVirtualOutput ) {
-        ModbusMasterWriteRegister(output, 1.0);
-    } else {
-        OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-        memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-        output_mail->action = ACTION_CONTROL_ON;
-        output_mail->controlType = CONTROL_SETPOINT;
-        strncpy(output_mail->input_tag,  this->input.c_str(),  sizeof(output_mail->input_tag)-1);
-        strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-        output_mail->priority = this->priority;
-        strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-        OutputMasterMailBox.put(output_mail);
-    }
-}
-
-//
-// method:              stopFeed
-// description:         send OFF indication to Output Master for this control's
-//                      relay
-//
-// @param               none
-// @return              none
-//
-void SetpointControl::stopFeed(void)
-{
-    logInfo("%s: %s attempting to stop feed on relay %s\n",
-            __func__, controlFile.c_str(), output.c_str());
-
-    if ( isVirtualOutput ) {
-        ModbusMasterWriteRegister(output, 0.0);
-    } else {
-        OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-        memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-        output_mail->action = ACTION_CONTROL_OFF;
-        output_mail->controlType = CONTROL_SETPOINT;
-        strncpy(output_mail->input_tag,  this->input.c_str(),  sizeof(output_mail->input_tag)-1);
-        strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-        output_mail->priority = this->priority;
-        strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-        OutputMasterMailBox.put(output_mail);
-    }
-}
-
-//
-// method:              unregisterControl
-// description:         send OFF indication to Output Master for this control's
-//                      relay
-//
-// @param               none
-// @return              none
-//
-void SetpointControl::unregisterControl(void)
-{
-    logInfo("%s: %s attempting to unregister %s\n",
-            __func__, id.c_str(), controlFile.c_str());
-
-    if ( isVirtualOutput ) {
-        ModbusMasterWriteRegister(output, 0.0);
-    } else {
-        OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-        memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-        output_mail->action      = ACTION_CONTROL_UNREGISTER;
-        output_mail->controlType = CONTROL_MANUAL;
-        output_mail->priority     = this->priority;
-        strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-        strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-
-        OutputMasterMailBox.put(output_mail);
-    }
-}
-
-//
-// method:              display
-// description:         display the control's information
-//
-// @param               none
-// @return              none
-//
-void SetpointControl::display(void)
-{
-    // NOTE: this mapping must be 1:1 with "State" enumeration in SetpointControl.h
-    std::string mapper[] = { "INIT",
-                        "STARTUP",
-                        "CONTROL_OFF",
-                        "CONTROL_ON",
-                        "CONTROL_DISABLE",
-                        "CONTROL_PAUSE",
-                        "CONTROL_MAX"
-                      };
-
-
-    ModbusValue inputValue;
-    ModbusMasterReadRegister(input, &inputValue);
-
-    printf("\r\n");
-    std::cout << std::left << std::setw(10) << std::setfill(' ') << "setpoint: ";
-    std::cout << std::left << std::setw(40) << std::setfill(' ') << controlFile;
-    std::cout << std::left << std::setw(20) << std::setfill(' ') << id;
-    std::cout << std::left << std::setw(6)  << std::setfill(' ') << priority;
-    std::cout << std::left << std::setw(20) << std::setfill(' ') << input;
-    std::cout << std::left << std::setw(20) << std::setfill(' ') << output;
-    std::cout << std::left << std::setw(8)  << std::setfill(' ') << setpoint;
-    std::cout << std::left << std::setw(12) << std::setfill(' ') << (actingDir ? "direct" : "indirect");
-    std::cout << std::left << std::setw(16) << std::setfill(' ') << mapper[currentState];
-    std::cout << std::right << std::setw(8) << std::setfill(' ') << setpoint + tolerance << " <- ";
-    std::cout << std::left << std::setw(8)  << std::setfill(' ') << inputValue.value << " -> ";
-    std::cout << std::left << std::setw(8)  << std::setfill(' ') << setpoint - tolerance;
-    //std::cout << left << setw(10) << setfill(' ') << highFailsafe << " : " << lowFailsafe;
-
-    std::cout.flush();
-}
\ No newline at end of file
--- a/ICE-Application/src/ConfigurationHandler/Controls/SetpointControl.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/******************************************************************************
- *
- * File:                SetpointControl.h
- * Desciption:          ICE Timer Control Class
- *
- *****************************************************************************/
-#ifndef SETPOINTCONTROL_H
-#define SETPOINTCONTROL_H
-
-#include <string>
-#include <stdio.h>
-
-typedef enum {
-    SETPOINT_CONTROL_OK,
-    SETPOINT_CONTROL_UNK_STATE, 
-    SETPOINT_CONTROL_ERROR,
-    SETPOINT_CONTROL_DESTROY
-} SetpointControlError_t;
-
-// A setpoint control is a control based on a process variable with respect
-// to a user defined control band. The output of this control object is a 
-// true/false decision (for a relay, true means power on the relay).
-
-//! SetpointControl - implements a setpoint control
-class SetpointControl
-{
-private:
-    std::string     controlFile;        // name of the control file
-    std::string     id;                 // control identifier
-    int             priority;           // control priority
-    std::string     input;              // control input
-    std::string     output;             // control output
-    double          setpoint;           // setpoint value
-    double          productFactor;
-    bool            actingDir;          // acting direction, 1 direct - pH, 0 indirect - inhibitor
-#if 0 
-    double          highAlert;
-    double          lowAlert;
-    double          highFailsafe;
-    double          lowFailsafe;
-#endif
-    double          tolerance;          // the error margining
-    enum State {
-        STATE_INIT,
-        STATE_STARTUP,
-        STATE_CONTROL_OFF,
-        STATE_CONTROL_ON,
-        STATE_DISABLE,
-        STATE_RELOAD,
-        STATE_MAX
-    };
-    State           currentState;
-    
-    bool validateControlData(const char *buf);
-    void copyControlData(const char *buf);
-
-    bool underLimit();          // check if reading is under the limit
-    bool overLimit();           // check if reading is over the limit
-
-    void startFeed(void);       // start a feed
-    void stopFeed(void);        // stop a feed
-    
-    bool isVirtualOutput;       // output is virtual
-public:
-    /// create  a setpoint control
-    SetpointControl() {
-        currentState = STATE_INIT;
-    };
-    /// destroy a setpoint control
-    ~SetpointControl() {
-        printf("\r%s invoked\n", __func__);
-    }
-
-    /// load setpoint control data from a JSON configuration file
-    bool load(std::string filename);
-
-    /// unregister a setpoint control from the output thread
-    void unregisterControl(void);
-
-    /// start a setpoint control instance
-    void start(void);
-
-    /// update a setpoint control instance
-    SetpointControlError_t update(void);
-
-    //display the pertinents
-    void display(void);
-
-    std::string getControlFile(void) const {
-        return controlFile;
-    }
-    std::string getId(void) const {
-        return id;
-    }
-    unsigned int getPriority(void) const {
-        return priority;
-    }
-    std::string getInput(void) const {
-        return input;
-    }
-    std::string getOutput(void) const {
-        return output;
-    }
-    float getProductFactor(void) const {
-        return productFactor;
-    }
-    int getActingDir(void) const {
-        return actingDir;
-    }
-    float getSetpoint(void) const {
-        return setpoint;
-    }
-    
-    State getCurrentState(void) const {
-        return currentState;
-    }
-};
-
-#endif
\ No newline at end of file
--- a/ICE-Application/src/ConfigurationHandler/Controls/TimerControl.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,467 +0,0 @@
-/******************************************************************************
- *
- * File:                TimerControl.cpp
- * Desciption:          ICE Timer Control Class implementation
- *
- *****************************************************************************/
-#include "TimerControl.h"
-#include "ModbusMasterApi.h"
-#include "ICELog.h"
-#include "cJSON.h"
-#include "global.h"
-#include "timerUtils.h"
-#include "utilities.h"
-#include <string>
-#include <iostream>
-#include <iomanip>
-
-// for debugging - this can be set via the console command:
-//      "debug-sp 1 or debug-sp 0
-bool debugTimerControl = false;
-
-static void debug(const char *fmt, ...)
-{
-    if ( debugTimerControl ) {
-        va_list vargs;
-        va_start(vargs, fmt);
-        vfprintf(stdout, fmt, vargs);
-        va_end(vargs);
-    }
-}
-
-#ifdef MDOT_ICE
-extern mDot *GLOBAL_mdot;
-#endif 
-
-//
-// method:      load
-// description: load the pertinents from the control file
-//
-// @param       _controlFile
-// @return      true if loaded; false otherwise
-//
-bool TimerControl::load(std::string _controlFile)
-{
-    controlFile = _controlFile;
-
-    char dataBuf[MAX_FILE_SIZE];
-    // read the control data 
-    bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
-    if ( rc != true ) {
-        logError("%s: failed to read %s", __func__, controlFile.c_str());
-        return false;
-    }
-
-    // validate the control data 
-    if ( !validateControlData(dataBuf) ) {
-        logError("%s: failed to validate control data", __func__);
-        return false;
-    }
-
-    // copy the control data
-    copyControlData(dataBuf);
-    
-    ModbusValue val;
-    // validate the output 
-    if ( ModbusMasterReadRegister(output, &val) == false ) {
-        logError("%s failed to find %s", id.c_str(), output.c_str());
-        return false;
-    } 
-
-    isVirtualOutput = Util_isVirtualOutput(output) ? true : false;
-
-    return true;
-
-}
-
-//
-// method:          validateControlData
-// description:     validates the data in the control file
-//
-// @param[in]       dataBuf -> JSON formatted string
-// @param[out]      non
-// @return          true if valid; false otherwise
-//
-bool TimerControl::validateControlData(const char *buf)
-{
-    bool rc = true;
-    cJSON * root = cJSON_Parse(buf);
-
-    if ( !cJSON_HasObjectItem(root, "id") ||
-            !cJSON_HasObjectItem(root, "output") ||
-            !cJSON_HasObjectItem(root, "priority") ||
-            !cJSON_HasObjectItem(root, "day") ||
-            !cJSON_HasObjectItem(root, "startHour") ||
-            !cJSON_HasObjectItem(root, "startMin") ||
-            !cJSON_HasObjectItem(root, "startSec") ||
-            !cJSON_HasObjectItem(root, "duration") ||
-            !cJSON_HasObjectItem(root, "week")) {
-        logError("%s: control file is missing expected tags", __func__);
-        rc = false;
-    }
-    cJSON_Delete(root);
-    return rc;
-}
-
-//
-// method:          copyControlData
-// description:     copy JSON formatted control data to object
-//
-// @param[in]       dataBuf -> JSON formatted data
-// @param[out]      none
-// @return          none
-//
-void TimerControl::copyControlData(const char *buf)
-{
-    cJSON *root = cJSON_Parse(buf);
-
-    id                  = cJSON_GetObjectItem(root,"id")->valuestring;
-    output              = cJSON_GetObjectItem(root, "output")->valuestring;
-    priority            = (unsigned int)atoi(cJSON_GetObjectItem(root, "priority")->valuestring);
-    std::string day_str = cJSON_GetObjectItem(root, "day")->valuestring;
-
-    if ( day_str        == "sun" ) {
-        day = DAY_SCHEDULE_SUNDAY_MASK;
-    } else if ( day_str == "mon" ) {
-        day = DAY_SCHEDULE_MONDAY_MASK;
-    } else if ( day_str == "tue" ) {
-        day = DAY_SCHEDULE_TUESDAY_MASK;
-    } else if ( day_str == "wed" ) {
-        day = DAY_SCHEDULE_WEDNESDAY_MASK;
-    } else if ( day_str == "thu" ) {
-        day = DAY_SCHEDULE_THURSDAY_MASK;
-    } else if ( day_str == "fri" ) {
-        day = DAY_SCHEDULE_FRIDAY_MASK;
-    } else if ( day_str == "sat" ) {
-        day = DAY_SCHEDULE_SATURDAY_MASK;
-    } else {
-        debug("\r%s:%s-> one-shot timer found\n", __func__, id.c_str());
-        day = DAY_SCHEDULE_NOT_SPECIFIED;       // one-shot timer
-    }
-
-    startHour       = atoi(cJSON_GetObjectItem(root, "startHour")->valuestring);
-    startMin        = atoi(cJSON_GetObjectItem(root, "startMin")->valuestring);
-    startSec        = atoi(cJSON_GetObjectItem(root, "startSec")->valuestring);
-    duration        = atoi(cJSON_GetObjectItem(root, "duration")->valuestring);
-
-    std::string week_str = cJSON_GetObjectItem(root, "week")->valuestring;
-    if ( week_str == "every" ) {
-        week = WEEKLY_CHOICE_EVERY_WEEK;
-    } else if ( week_str == "first" ) {
-        week = WEEKLY_CHOICE_FIRST_WEEK;
-    } else if ( week_str == "second" ) {
-        week = WEEKLY_CHOICE_SECOND_WEEK;
-    } else if ( week_str == "third" ) {
-        week = WEEKLY_CHOICE_THIRD_WEEK;
-    } else if ( week_str == "fourth" ) {
-        week = WEEKLY_CHOICE_FOURTH_WEEK;
-    } else if ( week_str == "last" ) {
-        week = WEEKLY_CHOICE_LAST_WEEK;
-    } else if ( week_str == "everyother") {
-        week = WEEKLY_CHOICE_EVERYOTHER_WEEK;
-    } else {
-        week = WEEKLY_CHOICE_NOT_SPECIFIED;     // one-shot timer
-    }
-
-    cJSON_Delete(root);
-}
-
-//
-// method:      start
-// description: initialize the control
-//
-// @param       none
-// @return      none
-//
-void TimerControl::start(void)
-{
-    // calculate the next scheduled start time
-    if ( day == DAY_SCHEDULE_NOT_SPECIFIED ) {
-        // start running right away
-        nextScheduledStartTime = time(0);
-        debug("\r%s: %s is a one-shot timer.\n", __func__, id.c_str());
-    } else {
-        nextScheduledStartTime = time(0) + calcStartTime();
-    }
-    struct tm * timeinfo;
-    timeinfo = localtime((time_t*)&nextScheduledStartTime);
-    debug("Timer %s started, begins at %s", this->id.c_str(), asctime(timeinfo));
-
-    currentState = STATE_OFF;
-}
-
-//
-// method:      update
-// description: run the state machine
-//
-// @param       none
-// @return      OK on success; error otherwise
-//
-TimerControlError_t TimerControl::update(void)
-{
-    TimerControlError_t rc = TIMER_CONTROL_OK;
-
-    unsigned long currentTime = time(0);
-
-    switch ( this->currentState ) {
-        case STATE_INIT:
-            // do nothing; timer is waiting for start signal
-            break;
-        case STATE_OFF: {
-            if ( currentTime >= nextScheduledStartTime &&
-                    currentTime <= nextScheduledStartTime + duration ) {
-                currentState = STATE_RUNNING;
-                this->startFeed();
-                startTime = currentTime; // record the actual start time
-                debug("\r%s: [OFF]->in timing window->[RUNNING] %s\n", id.c_str(), displayTime());
-            }
-            break;
-        }
-        case STATE_RUNNING:
-            if ( currentTime >= startTime + duration ) {
-                this->stopFeed();
-                currentState = STATE_FINISHED;
-                debug("\r%s: [RUNNING]->time elapsed->[OFF] %s\n", id.c_str(), displayTime());
-            }
-            break;
-        case STATE_FINISHED:
-            if ( day == DAY_SCHEDULE_NOT_SPECIFIED || week == WEEKLY_CHOICE_NOT_SPECIFIED ) {
-                // one shot-timer, just disable it.
-                nextScheduledStartTime = 0;
-                startTime = 0;
-                currentState = STATE_DISABLED;
-                debug("\r%s: [FINISHED]->one shot timer->[DISABLED] %s\n", id.c_str(), displayTime());
-            } else {
-                // calculate the next scheduled start time
-                nextScheduledStartTime = time(0) + calcStartTime();
-                startTime = 0;
-                // unregister with the output task
-                currentState = STATE_OFF;
-                debug("\r%s: [FINISHED]->time elapsed->[OFF] %s\n", id.c_str(), displayTime());
-            }
-            this->unregisterControl();
-            break;
-        case STATE_DISABLED:
-            // do nothing
-            break;
-        default:
-            logError("%s: unknown state %d", __func__, this->currentState);
-            rc = TIMER_CONTROL_UNK_STATE;
-            break;
-    }
-    return rc;
-}
-
-//
-// method:      startFeed
-// description: signal the output thread to start a feed
-//
-// @param       none
-// @return      none
-void TimerControl::startFeed(void)
-{
-    logInfo("%s: %s attempting to start feed on relay %s\n",
-            __func__, controlFile.c_str(), output.c_str());
-
-    if ( isVirtualOutput ) {
-        // write to the virtual register map
-        ModbusMasterWriteRegister(output, 1.0);
-    } else {
-        // send a message to the output thread
-        OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-        memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-        output_mail->action      = ACTION_CONTROL_ON;
-        output_mail->controlType = CONTROL_TIMER;
-        output_mail->priority    = priority;
-
-        strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-        strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-        OutputMasterMailBox.put(output_mail);
-    }
-}
-
-//
-// method:      stopFeed
-// description: signal the output thread to stop a feed
-//
-// @param       none
-// @return      none
-//
-void TimerControl::stopFeed(void)
-{
-    logInfo("%s: %s attempting to start feed on relay %s\n",
-            __func__, controlFile.c_str(), output.c_str());
-
-    if ( isVirtualOutput ) {
-        // write to the virtual register map
-        ModbusMasterWriteRegister(output, 0.0);
-    } else {
-        // send a message to the output thread
-        OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-        memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-        output_mail->action      = ACTION_CONTROL_OFF;
-        output_mail->controlType = CONTROL_TIMER;
-        output_mail->priority    = priority;
-
-        strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-        strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-        OutputMasterMailBox.put(output_mail);
-    }
-}
-
-//
-// method:              unregisterControl
-// description:         send OFF indication to Output Master for this control's
-//                      relay
-//
-// @param               none
-// @return              none
-//
-void TimerControl::unregisterControl(void)
-{
-    logInfo("%s: %s attempting to unregister %s\n",
-            __func__, id.c_str(), controlFile.c_str());
-
-    if ( isVirtualOutput ) {
-        ModbusMasterWriteRegister(output, 0.0);
-    } else {
-
-        OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
-        memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
-        output_mail->action       = ACTION_CONTROL_UNREGISTER;
-        output_mail->controlType  = CONTROL_TIMER;
-        output_mail->priority     = priority;
-        strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
-        strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-
-        OutputMasterMailBox.put(output_mail);
-    }
-}
-
-//
-// method:          calcStarTime
-// description:     calculate the number of seconds until the next
-//                  timer starts.
-//
-// @param[in]       none
-// @param[out]      none
-// @return          none
-//
-unsigned long TimerControl::calcStartTime(void) const
-{
-    TSC_SCHED_ELEM      schedTimeDate;
-    TSC_SCHED_ELEM      pNowTimeDate;
-    unsigned long       pDiffInSeconds;
-    CNTL_HR_MIN_STRUCT  startTime;
-
-    startTime.hour   = startHour;
-    startTime.minute = startMin;
-    startTime.second = startSec;
-
-    pNowTimeDate.calTime = time( NULL );
-    localtime_r( &pNowTimeDate.calTime, &pNowTimeDate.requestTime );
-
-    pNowTimeDate.schedule.startDate.year    = pNowTimeDate.requestTime.tm_year - 100; /* years since 1900 */
-    pNowTimeDate.schedule.startDate.year    += 2000;
-    pNowTimeDate.schedule.startDate.month   = pNowTimeDate.requestTime.tm_mon + 1; /* months 1 - 12 */
-    pNowTimeDate.schedule.startDate.day     = pNowTimeDate.requestTime.tm_mday;
-    pNowTimeDate.schedule.startTime.hour    = pNowTimeDate.requestTime.tm_hour;
-    pNowTimeDate.schedule.startTime.minute  = pNowTimeDate.requestTime.tm_min;
-    pNowTimeDate.schedule.startTime.second  = pNowTimeDate.requestTime.tm_sec;
-
-    /* setup schedTimeDate with the current date, time and the required schedule */
-    schedTimeDate.schedule.startDate        = pNowTimeDate.schedule.startDate;
-    schedTimeDate.schedule.startTime        = startTime;
-    schedTimeDate.schedule.dailySchedule    = day;
-    schedTimeDate.schedule.weeklySchedule   = (WEEKLY_CHOICES)week;
-    schedTimeDate.calTime                   = pNowTimeDate.calTime;
-    schedTimeDate.requestTime               = pNowTimeDate.requestTime;
-
-    TSCutilComputeStartDate( &schedTimeDate );
-    Util_dateTimeDiff( &pNowTimeDate.schedule, &schedTimeDate.schedule, &pDiffInSeconds );
-
-    return pDiffInSeconds;
-}
-
-const char* TimerControl::displayTime(void)
-{
-    struct tm * timeinfo;
-    time_t currentTime = time(0);
-    timeinfo = localtime(&currentTime);
-    return asctime(timeinfo);
-}
-
-//
-// method:      display
-// description: display the elements of this timer control object
-//
-// @param       none
-// @return      none
-//
-void TimerControl::display(void)
-{
-    string mapper[] = { "INIT",
-                        "OFF",
-                        "RUNNING",
-                        "FINISHED",
-                        "DISABLED"
-                      };
-
-    printf("\r\n");
-    std::string day_str;
-    if ( day == DAY_SCHEDULE_SUNDAY_MASK ) {
-        day_str = "Sun";
-    } else if ( day == DAY_SCHEDULE_MONDAY_MASK ) {
-        day_str = "Mon";
-    } else if ( day == DAY_SCHEDULE_TUESDAY_MASK ) {
-        day_str = "Tue";
-    } else if ( day == DAY_SCHEDULE_WEDNESDAY_MASK ) {
-        day_str = "Wed";
-    } else if ( day == DAY_SCHEDULE_THURSDAY_MASK ) {
-        day_str = "Thu";
-    } else if ( day == DAY_SCHEDULE_FRIDAY_MASK ) {
-        day_str = "Fri";
-    } else if ( day == DAY_SCHEDULE_SATURDAY_MASK ) {
-        day_str = "Sat";
-    }
-    std::string week_str;
-    if ( week == WEEKLY_CHOICE_EVERY_WEEK ) {
-        week_str = "every";
-    } else if ( week == WEEKLY_CHOICE_FIRST_WEEK ) {
-        week_str = "first";
-    } else if ( week == WEEKLY_CHOICE_SECOND_WEEK ) {
-        week_str = "second";
-    } else if ( week == WEEKLY_CHOICE_THIRD_WEEK ) {
-        week_str = "third";
-    } else if ( week == WEEKLY_CHOICE_FOURTH_WEEK ) {
-        week_str = "fourth";
-    } else if ( week == WEEKLY_CHOICE_LAST_WEEK ) {
-        week_str = "last";
-    } else if ( week == WEEKLY_CHOICE_EVERYOTHER_WEEK ) {
-        week_str = "everyother";
-    }
-
-    char time_str[12];
-    snprintf(time_str, sizeof(time_str), "%02d:%02d:%02d", startHour, startMin, startSec);
-
-    cout << left << setw(8) << setfill(' ') << "timer:";
-    cout << left << setw(32) << setfill(' ') << controlFile;
-    cout << left << setw(12) << setfill(' ') << id;
-    cout << "output: " << left << setw(16) << setfill(' ') << output;
-    cout << left << setw(6)  << setfill(' ') << priority;
-    cout << "("  << setw(12) << week_str << ")" << day_str << "-> ";
-    cout << left << setw(12) << setfill(' ') << time_str;
-    cout << left << setw(10) << "duration: " << left << setw(6) << setfill(' ') << duration;
-    cout << left << setw(10) << setfill(' ') << mapper[currentState];
-    if ( currentState == STATE_RUNNING )  {
-        cout << left << setw(11) << setfill(' ') << "ends in: " << (startTime + duration) - time(NULL) << " seconds ";
-    } else if ( currentState == STATE_FINISHED || currentState == STATE_DISABLED ) {
-        // show nothing
-    } else {
-        cout << left << setw(11) << setfill(' ') << "starts in: " << calcStartTime() << " seconds ";
-    }
-    cout.flush();
-}
--- a/ICE-Application/src/ConfigurationHandler/Controls/TimerControl.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/******************************************************************************
- *
- * File:                TimerControl.h
- * Desciption:          ICE Timer Control Class
- *
- *****************************************************************************/
-#ifndef TIMERCONTROL_H
-#define TIMERCONTROL_H
-
-//#include "ConfigurationHandler.h"
-#include <string>
-#include <stdio.h>
-#include <vector>
-
-typedef enum {
-    TIMER_CONTROL_OK,
-    TIMER_CONTROL_UNK_STATE,
-    TIMER_CONTROL_ERROR,
-    TIMER_CONTROL_DESTROY
-} TimerControlError_t;
-
-
-//! Timer Control - implements a timer control.
-/// @code
-/// #include "TimerControl.h"
-///
-/// int main(void)
-/// {
-///     TimerControl *t = new TimerControl();
-///     bool rc = t->load(controlFile);
-///     if ( rc != true ) {
-///         logError("%s: failed to load the manual control\n");
-///         delete t;
-///         exit(-1);
-///     }
-///
-///     t->start();
-///     for ( ;; ) {
-///         t->update();
-///     }
-/// }
-/// @endcode
-class TimerControl
-{
-private:
-    std::string     controlFile;        // file containing control data
-    std::string     id;                 // timer identifier
-    std::string     output;             // output to control
-    unsigned int    priority;           // control priority
-    unsigned int    day;
-    unsigned int    startHour;          // start hour (0-23)
-    unsigned int    startMin;           // start minute (0-59)
-    unsigned int    startSec;           // start second (0-59)
-    unsigned int    duration;           // duration in seconds
-    unsigned int    week;               // every week, first week, ...
-
-    enum State {
-        STATE_INIT,
-        STATE_OFF,
-        STATE_RUNNING,
-        STATE_FINISHED,
-        STATE_DISABLED
-    };
-    State           currentState;
-
-    unsigned long   nextScheduledStartTime;
-    unsigned long   startTime;
-
-    bool            isVirtualOutput;
-
-    // validate control file data
-    bool validateControlData(const char *buf);
-
-    // copy control file data to object
-    void copyControlData(const char *buf);
-
-    // start a feed
-    void startFeed(void);
-
-    // stop a feed
-    void stopFeed(void);
-
-    // calculate time until start
-    unsigned long calcStartTime() const;
-    
-    const char *displayTime(void);
-
-public:
-    TimerControl() {
-        currentState = STATE_INIT;
-    }
-    ~TimerControl() {
-        printf("\r%s invoked\n", __func__);
-    }
-    /// load control data from a JSON configuration file
-    bool load(std::string filename);
-
-    /// start a timer control instance
-    void start(void);
-
-    /// update a timer control instance
-    TimerControlError_t update(void);
-
-    /// unregister a timer control instance from the output thread
-    void unregisterControl(void);
-
-    /// display pertinent data of a timer control instance
-    void display(void);
-
-    std::string getControlFile(void) const {
-        return controlFile;
-    }
-
-    std::string getId(void) const {
-        return id;
-    }
-
-    std::string getOutput(void) const {
-        return output;
-    }
-
-    unsigned int getPriority(void) const {
-        return priority;
-    }
-
-    unsigned int getDuration(void) const {
-        return duration;
-    }
-
-    State getCurrentState(void) const {
-        return currentState;
-    }
-};
-
-#endif
--- a/ICE-Application/src/ControlTask/ControlTask.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,228 +0,0 @@
-/******************************************************************************
- *
- * File:                ControlTask.cpp
- * Desciption:          source for the ICE Control task
- *
- *****************************************************************************/
-
-#include "ControlTask.h"
-#include <stdio.h>
-#include "rtos.h"
-#include "ConfigurationHandler.h"
-#include "ICELog.h"
-#include "global.h"
-
-// control functions
-static void serviceManualControls(void);
-static void serviceTimerControls(void);
-static void serviceSetpointControls(void);
-static void serviceCompositeControls(void);
-static void serviceFailsafeControls(void);
-static void serviceSequenceControls(void);
-
-static void sendMail(std::string controlFile, Action_t action, Control_t control);
-
-//
-// Task:               ControlTask
-// Description:        This task will loop through all of the configued control
-//                     and run the updater
-//
-// @param[in]          none
-// @param[out]         none
-// @return             none
-//
-void ControlTask(void const *args)
-{
-    printf("\r%s has started...\n", __func__);
-
-    while ( true ) {
-
-        serviceTimerControls();
-        serviceManualControls();
-        serviceSetpointControls();
-        serviceCompositeControls();
-        serviceFailsafeControls();
-        serviceSequenceControls();
-    }
-}
-
-//
-// function:            serviceManualControls()
-// description:         run the updater on the manual controls
-//
-// @param[in]           none
-// @param[out]          none
-// @return              none
-//
-static void serviceManualControls(void)
-{
-    ManualControlError_t rc;
-
-    manual_mutex.lock();
-    if ( !manualTable.empty() ) {
-        StringManualMap::iterator pos;
-        for ( pos = manualTable.begin(); pos != manualTable.end(); ++pos) {
-            rc = pos->second->update();
-            if ( rc == MANUAL_CONTROL_DESTROY ) {
-                // send mail to the configuration handler to destroy this control
-                sendMail(pos->second->getControlFile(), ACTION_DESTROY, CONTROL_MANUAL);
-            } else if ( rc != MANUAL_CONTROL_OK ) {
-                logError("%s: error %d updating the manual control", __func__, rc);
-            }
-        }
-    }
-    manual_mutex.unlock();
-}
-
-//
-// function:            serviceSetpointControls
-// description:         run the updater on the setpoint controls
-//
-// @param[in]           none
-// @param[out]          none
-// @return              none
-//
-static void serviceSetpointControls(void)
-{
-    SetpointControlError_t  rc;
-
-    setpoint_mutex.lock();
-    if ( !setpointTable.empty() ) {
-        StringSetpointMap::const_iterator pos;
-        for ( pos = setpointTable.begin(); pos != setpointTable.end(); ++pos ) {
-            // run the updater
-            rc = pos->second->update();
-            if ( rc != SETPOINT_CONTROL_OK ) {
-                logError("%s: error (%d) updating setpoint control %s",
-                         __func__, rc, pos->second->getId().c_str());
-            }
-        }
-    }
-    setpoint_mutex.unlock();
-}
-
-//
-// function:            serviceTimerControls
-// description:         run the updater on the timer controls
-//
-// @param[in]           none
-// @param[out]          none
-// @return              none
-//
-static void serviceTimerControls(void)
-{
-    TimerControlError_t rc;
-
-    timer_mutex.lock();
-    if ( !timerTable.empty() ) {
-        StringTimerMap::const_iterator pos;
-        for ( pos = timerTable.begin(); pos != timerTable.end(); ++pos ) {
-            // run the updater
-            rc = pos->second->update();
-            if ( rc != TIMER_CONTROL_OK ) {
-                logError("%s: error (%d) updating timer control %s",
-                         __func__, rc, pos->second->getId().c_str());
-            }
-        }
-    }
-    timer_mutex.unlock();
-}
-
-//
-// function:           serviceCompositeControls
-// description:        run the updater on the composite controls
-//
-// @param[in]          none
-// @param[out]         none
-// @return             none
-//
-static void serviceCompositeControls(void)
-{
-    CompositeControlError_t rc;
-
-    // service the composite controls
-    composite_mutex.lock();
-    if ( !compositeTable.empty() ) {
-        StringCompositeMap::const_iterator pos;
-        for ( pos = compositeTable.begin(); pos != compositeTable.end(); ++pos ) {
-            // run the updater
-            rc = pos->second->update();
-            if ( rc != COMPOSITE_CONTROL_OK ) {
-                logError("%s: error (%d) updating composite control %s",
-                         __func__, rc, pos->second->getId().c_str());
-            }
-        }
-    }
-    composite_mutex.unlock();
-}
-
-//
-// function:           serviceFailsafeControls
-// description:        run the updater on the failsafe controls
-//
-// @param[in]          none
-// @param[out]         none
-// @return             none
-//
-static void serviceFailsafeControls(void)
-{
-    FailsafeControlError_t  rc;
-
-    // service the setpoint controls
-    failsafe_mutex.lock();
-    if ( !failsafeTable.empty() ) {
-        StringFailsafeMap::const_iterator pos;
-        for ( pos = failsafeTable.begin(); pos != failsafeTable.end(); ++pos ) {
-            // run the updater
-            rc = pos->second->update();
-            if ( rc != FAILSAFE_CONTROL_OK ) {
-                logError("%s: error (%d) updating failsafe control %s",
-                         __func__, rc, pos->second->getId().c_str());
-            }
-        }
-    }
-    failsafe_mutex.unlock();
-}
-
-static void serviceSequenceControls(void)
-{
-    SequenceControlError_t rc;
-
-    // service the sequence controls
-    sequence_mutex.lock();
-    if ( !sequenceTable.empty() ) {
-        StringSequenceMap::const_iterator pos;
-        for ( pos = sequenceTable.begin(); pos != sequenceTable.end(); ++pos ) {
-            rc = pos->second->run();
-            if ( rc != SEQUENCE_CONTROL_OK ) {
-                logError("%s: error (%d) running sequence control %s",
-                         __func__, rc, pos->second->getId().c_str());
-            }
-        }
-    }
-    sequence_mutex.unlock();
-}
-
-//
-// function:            sendMail
-// desctiption:         send mail to the configuration handler
-//
-// @param[in]           controlFile -> key
-// @param[in]           action -> destroy, create, modify, etc.
-// @param[in]           control -> manual, setpoint...
-// @param[out]          none
-// @return              none
-//
-static void sendMail(std::string controlFile, Action_t action, Control_t control)
-{
-    ConfigMessage_t *msg  = ConfigHandlerMailBox.alloc();
-    memset(msg, 0, sizeof(ConfigMessage_t));
-    msg->action  = action;
-    msg->control = control;
-    strncpy(msg->controlFile, controlFile.c_str(), sizeof(msg->controlFile)-1);
-
-    printf("%s: Sending a destroy request for control %s\r\n",
-           __func__, msg->controlFile);
-
-    ConfigHandlerMailBox.put(msg);
-}
\ No newline at end of file
--- a/ICE-Application/src/ControlTask/ControlTask.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-#ifndef CONTROLTASK_H
-#define CONTROLTASK_H
-
-#ifdef __cplusplus
-#define EXTERNC extern "C"
-#else
-#define EXTERNC
-#endif
-
-EXTERNC void ControlTask(void const *args);
- 
-#undef EXTERNC
-
-#endif
--- a/ICE-Application/src/DataHandler/DataHandler.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-#include "DataHandler.h"
-#include "rtos.h"
-#include <stdio.h>
-
-void DataHandler(void const *args)
-{
-    printf("\r%s has started...\n", __func__);
-    
-    while ( true ) {
-        Thread::wait(5000);
-    }
-}
--- a/ICE-Application/src/DataHandler/DataHandler.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-#ifndef DATAHANDLER_H
-#define DATAHANDLER_H
-
-#ifdef __cplusplus
-#define EXTERNC extern "C"
-#else
-#define EXTERNC
-#endif
-
-EXTERNC void DataHandler(const void *args);
-
-#undef EXTERNC
-
-#ifdef MDOT_ICE
-#include "mDot.h"
-#endif 
-#include <string>
-
-#define HEARTBEAT_MSG_MTYPE             20          // heartbeat (out)
-
-#define SETPOINT_CONTROL_MTYPE          100         // setpoint control config
-#define TIMER_CONTROL_MTYPE             101         // timer control config
-#define PID_CONTROL_MTYPE               102         // PID control config
-#define MANUAL_CONTROL_MTYPE            103         // manual control config
-#define COMPOSITE_CONTROL_MTYPE         104         // composite control config
-#define SEQUENCE_CONTROL_MTYPE          105         // sequence control 
-#define FAILSAFE_CONTROL_MTYPE          106         // failsafe conrol
-
-#define INPUT_CONFIG_MTYPE              200         // input config
-#define OUTPUT_CONFIG_MTYPE             201         // output config
-#define VINPUT_CONFIG_MTYPE             203         // virtual input config
-#define VOUTPUT_CONFIG_MTYPE            204         // virtual output config
-#define HOLDING_CONFIG_MTYPE            205         // holding config
-
-#define VIRTUAL_COMMAND_MTYPE           250         // virtual command
-#define EQUATION_COMMAND_MTYPE          251         // equation command 
-
-#define DESTROY_SETPOINT_MTYPE          300         // destroys a setpoint control
-#define DESTROY_TIMER_MTYPE             301         // destroys a timer control
-#define DESTROY_PID_MTYPE               302         // destroys a PID control
-#define DESTROY_MANUAL_MTYPE            303         // destroys a manual control
-
-#define EVENT_LOG_MTYPE                 300         // event log [out], pump actuation, etc.
-#define DEVICE_CONN_MTYPE               301         // device connected 
-#define LIVE_DATA_MTYPE                 400         // live data [out]
-
-
-// BLE requests 
-#define BT_MODBUS_HOLD_COMMAND_MTYPE    1000 
-#define BT_MODBUS_RAW_COMMAND_MTYPE     1002
-#define BT_MODBUS_COMMAND_REPLY_MTYPE   1001
-
-#define BT_GETLOG_COMMAND_MTYPE         1100
-#define BT_GETLOG_COMMAND_REPLY_MTYPE   1101
-#define BT_GETLIVE_COMMAND_MTYPE        1200
-
-#define BT_START_CAL_COMMAND_MTYPE      1300
-#define BT_1PT_CAL_COMMAND_MTYPE        1301
-
-#define SETPOINT_CONTROL_REPLY_MTYPE    500
-#define TIMER_CONTROL_REPLY_MTYPE       501
-#define MANUAL_CONTROL_REPLY_MTYPE      503
-#define COMPOSITE_CONTROL_REPLY_MTYPE   504
-#define SEQUENCE_CONTROL_REPLY_MTYPE    505
-#define FAILSAFE_CONTROL_REPLY_MTYPE    506
-
-#define INPUT_CONFIG_REPLY_MTYPE        550
-#define OUTPUT_CONFIG_REPLY_MTYPE       551
-
-#ifdef MDOT_ICE
-bool StoreReceivedFile( mDot *dot, std::string &payload_string );
-#endif
-
-#endif 
\ No newline at end of file
--- a/ICE-Application/src/DataHandler/LogHandler.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-#include "global.h"
-#include <stdio.h>
-#include <sstream>
-#include <iostream>
-#include <time.h>
-#include "LogHandler.h"
-#include "LogLocalApi.h"
-#include "LoggerApi.h"
-#ifdef MDOT_ICE
-#include "BLEDataHandler.h"
-#include "MTSLog.h"
-#include "CloudFileReceiver.h"
-#include "CloudDataHandler.h"
-#endif
-
-#ifndef MDOT_ICE
-#include "DataHandler.h"
-#endif
-#include "utilities.h"
-#include "version.h"
-
-Mail<LoggerQueue_t, 16> LoggerQueue;
-
-size_t LoggerXmitLength = LOG_BYTES_PER_ENTRY;
-
-int last_min=8;
-
-
-static void constructHeartBeat(std::string &msg);
-
-//
-// function:            LogHandler
-// description: 
-//
-// @param[in]           joined
-// @param[out]          none
-// @return              
-//
-bool LogHandler( bool joined )
-{
-    int32_t ret;
-    char buffer[LOG_BYTES_PER_ENTRY];
-    std::string tmp_buffer;
-    bool log_in_eeprom=false;
-    bool log_to_send=false;
-
-#ifdef MDOT_ICE
-    osEvent evt = LoggerQueue.get(50);
-    if( (evt.status == osEventMail) ) {
-        // pull the log event from the queue, even if we are not joined
-        LoggerQueue_t *LoggerEvent = (LoggerQueue_t*)evt.value.p;
-        logInfo("Log Msg Received: log entry: %s", LoggerEvent->log_entry);
-        strncpy( buffer, LoggerEvent->log_entry, (LoggerXmitLength-1) );
-        tmp_buffer.assign(buffer);
-        log_to_send = true;
-//        printf("%s:%d: Found Log Event on LoggerQueue to send to cloud\r\n", __func__, __LINE__);
-        LoggerQueue.free(LoggerEvent);
-    }
-
-    if( (evt.status == osEventMail) && (joined == false) ) {
-        // if we pulled a log from the queue put it in the EEPROM
-        LogLocalApi( tmp_buffer.c_str() );
-//        printf("%s:%d: Not Connected, Putting Logger event In EEPROM\r\n", __func__, __LINE__);
-        return false;
-    }
-
-    if( (evt.status != osEventMail) && joined == true) {
-        // nothing on the queue, see if there is anything in the EEPROM to send.
-        log_in_eeprom = LogLocalApi_PopEntry( buffer );
-        if( log_in_eeprom == true ) {
-            tmp_buffer.assign(buffer);
-            log_to_send = true;
-//           printf("%s:%d: Found Log Event in EEPROM to send to cloud\r\n", __func__, __LINE__);
-        } else {
-//            printf("%s:%d: Nothing in EEPROM\r\n", __func__, __LINE__);
-        }
-    }
-
-    if( log_to_send == false ) {
-        struct tm       *ts;
-        time_t curr_sec;
-
-        curr_sec = time(0);
-        ts = localtime(&curr_sec);
-//        printf("curr_sec=%ld, min=%d (last=%d) min-mod-5=%d\r\n", curr_sec, ts->tm_min, last_min, (ts->tm_min%5) );
-        if( ((ts->tm_min%1) == 0) && (ts->tm_min != last_min) ) {
-            last_min = ts->tm_min;
-            // no event log to send, send the heart beat message.
-            logInfo("\r%s:%d: sending heart beat, hr=%d min=%d\r\n", __func__, __LINE__, ts->tm_hour, ts->tm_min);
-            constructHeartBeat(tmp_buffer);
-            logInfo("\r%s (%d bytes)\n", tmp_buffer.c_str(), tmp_buffer.size());
-        } else {
-//            printf("%s:%d: Nothing to send to the cloud\r\n", __func__, __LINE__);
-            if( CloudDataHandler_RcvFile != true ) {
-                return false;
-            }
-            printf("%s:%d: currently receiveing a file\r\n", __func__, __LINE__);
-            // send so we get another packet from gateway.
-            tmp_buffer = "{\"mtype\":\"20\"}";
-        }
-    }
-
-    if( joined == true ) {
-        std::vector<uint8_t> data(tmp_buffer.begin(), tmp_buffer.end());
-        ret = GLOBAL_mdot->send(data);
-        if ( ret == mDot::MDOT_OK ) {
-            //if ((ret = GLOBAL_mdot->send(data)) == mDot::MDOT_OK) {
-//            printf("%s:%d: Successful send to cloud\r\n", __func__, __LINE__);
-            return true;
-        }
-//        printf("failed to send, ret=%d, %s\r\n", ret, mDot::getReturnCodeString(ret).c_str());
-    }
-
-    if( log_to_send == true ) {
-        // We had a log event ready to send but didn't send it.
-        // Store it in the EEPROM for the next attempt.
-//        printf("%s:%d: Could not send Log Event to cloud, store in EEPROM\r\n", __func__, __LINE__);
-        LogLocalApi( tmp_buffer.c_str() );
-    } else {
-//        printf("%s:%d: Could not send to cloud, nothing to store in EEPROM\r\n", __func__, __LINE__);
-    }
-#endif
-    return false;
-}
-
-// 
-// function:            CDH_ReplyToHandler
-// description:
-//
-// @param[in]
-// @param[out]
-// @return
-// 
-void CDH_ReplyToHandler( std::string &id, int status, float value )
-{
-    std::ostringstream reply_oss;
-
-    LoggerQueue_t *LoggerEvent = LoggerQueue.alloc();
-    memset( LoggerEvent->log_entry, 0, sizeof(LoggerEvent->log_entry) );
-
-    reply_oss << "{  \"mtype\":" << BT_MODBUS_COMMAND_REPLY_MTYPE << ", \"mbreply\":{ \"id\":\"" << id.c_str() << "\"," "\"status\":\"" << status << "\"," "\"value\":\"" << value << "\"} }";
-    std::string string_reply = reply_oss.str();
-    strncpy( LoggerEvent->log_entry, string_reply.c_str(), (sizeof(LoggerEvent->log_entry)-1));
-    printf("%s:%d: Reply is: %s\r\n",__func__,__LINE__, LoggerEvent->log_entry);
-    LoggerEvent->position = 0;
-    LoggerQueue.put(LoggerEvent);
-}
-
-//
-// function:        ReplyToHandler
-// description:     
-// 
-// @param[in]       
-// @param[out]
-// @return
-//
-void ReplyToHandler( ThreadName_t replyTo, std::string &id, int ret, float value )
-{
-#ifdef MDOT_ICE
-    if( replyTo == BLE_HANDLER ) {
-        BLE_ReplyToHandler( id, ret, value );
-    } else if( replyTo == CLOUD_DATA_HANDLER ) {
-        CDH_ReplyToHandler( id, ret, value );
-    } else {
-        logError("Unknown Thread for Command Reply");
-    }
-#else
-#undef TODO_ICE
-    // do something
-#endif 
-}
-
-//
-// function:            constructHeartBeat()
-// description:         construct the periodic heartbeat message
-//
-// @param[out]          constructed message
-// @return              none
-//
-static void constructHeartBeat(std::string &msg)
-{
-    //std::ostringstream heartbeat_msg(200);
-    std::ostringstream heartbeat_msg;
-    heartbeat_msg.precision(2);
-
-    std::string heap_data = Util_getHeapData();
-    // let's strip off everything after 'bytes'
-    std::string::size_type i = heap_data.find("bytes");
-    if (i != std::string::npos)
-        heap_data.erase(i+strlen("bytes"), heap_data.length());
-
-
-    heartbeat_msg << "{ \"mtype\":" << HEARTBEAT_MSG_MTYPE << 
-        ", \"hb\": {"
-        "\"fwver\": \"" << MAJOR_VERSION_NUMBER << "." << MINOR_VERSION_NUMBER << "." << PATCH_VERSION_NUMBER << "\","
-        "\"heap\":\"" << heap_data << "\","
-        "\"AL\":\""   << (((double)GLOBAL_analyticsLogger_thread->max_stack()/(double)GLOBAL_analyticsLogger_thread->stack_size())*100.) << "%\","
-        "\"DH\":\""   << (((double)GLOBAL_dataHandler_thread->max_stack()/(double)GLOBAL_dataHandler_thread->stack_size())*100.) << "%\","
-        "\"CFG\":\""  << (((double)GLOBAL_configHandler_thread->max_stack()/(double)GLOBAL_configHandler_thread->stack_size())*100.) << "%\","
-        "\"CT\":\""   << (((double)GLOBAL_controlTask_thread->max_stack()/(double)GLOBAL_controlTask_thread->stack_size())*100.) << "%\","
-        "\"MM\":\""   << (((double)GLOBAL_modbusMaster_thread->max_stack()/(double)GLOBAL_modbusMaster_thread->stack_size())*100.) << "%\","
-        "\"OUT\":\""  << (((double)GLOBAL_outputTask_thread->max_stack()/(double)GLOBAL_outputTask_thread->stack_size())*100.) << "%\","
-        "\"boot\":\"" << Util_getLastBootTime() << "\" "
-        "} }";
-    msg = heartbeat_msg.str();
-}
--- a/ICE-Application/src/DataHandler/LogHandler.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-#ifndef LOGHANDLER_H
-#define LOGHANDLER_H
-
-#include "global.h"
-#include "LogLocalApi.h"
-
-typedef struct logger_queue_t {
-    size_t              position;
-    char                log_entry[LOG_BYTES_PER_ENTRY];
-} LoggerQueue_t;
-
-extern Mail<LoggerQueue_t, 16> LoggerQueue;
-
-bool LogHandler( bool joined );
-
-#endif 
-
--- a/ICE-Application/src/DataHandler/LoggerApi.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-#include "LoggerApi.h"
-#include "LogHandler.h"
-#include "DataHandler.h"
-#include "ICELog.h"
-#include "global.h"
-#include <sstream>
-#include <iostream>
-#include <time.h>
-#include <stdio.h>
-
-
-void EventLoggerApi( EventReasonStruct_t &eventReason )
-{
-    time_t curr_sec = time(0);
-
-    LoggerQueue_t *LoggerEvent = LoggerQueue.alloc();
-    memset( LoggerEvent->log_entry, 0, sizeof(LoggerEvent->log_entry) );
-
-//   std::ostringstream log_event;
-//   log_event << "tag:"<< iter->first.c_str() << " value:" << float_value;
-
-    snprintf( LoggerEvent->log_entry, sizeof(LoggerEvent->log_entry),
-              "{""\"mtype\":\"%d\",""\"t\":\"%ld\",""\"e\":\"%d\",""\"i\":\"%s\",""\"iv\":\"%2.2f\",""\"o\":\"%s\",""\"ov\":\"%2.2f\"}",
-              EVENT_LOG_MTYPE, curr_sec, eventReason.eventReason, eventReason.inputTag, eventReason.inputValue,
-              eventReason.outputTag, eventReason.outputValue );
-    LoggerEvent->position = 0;
-    LoggerQueue.put(LoggerEvent);
-
-    logInfo("len=%d: %s", strlen(LoggerEvent->log_entry), LoggerEvent->log_entry );
-
-    PeriodicLogger( true );
-}
-
-void DeviceConnectedLoggerApi( unsigned int connected )
-{
-    time_t curr_sec = time(NULL);
-    LoggerQueue_t *LoggerEvent = LoggerQueue.alloc();
-    
-    memset( LoggerEvent->log_entry, 0, sizeof(LoggerEvent->log_entry) );
-
-    snprintf( LoggerEvent->log_entry, sizeof(LoggerEvent->log_entry),
-            "{""\"mtype\":\"%d\",""\"t\":\"%ld\",""\"e\":\"%u\" }",
-            DEVICE_CONN_MTYPE, curr_sec, connected);
-    LoggerEvent->position = 0;
-    LoggerQueue.put(LoggerEvent);
-    
-    logInfo("len=%d: %s", strlen(LoggerEvent->log_entry), LoggerEvent->log_entry);
-    printf("\rlen = %d: %s\n", strlen(LoggerEvent->log_entry), LoggerEvent->log_entry);
-    
-    PeriodicLogger( true );
-}
-    
-
-void LiveData2Message( const char *liveData, char *messageString, int len )
-{
-    time_t curr_sec = time(0);
-    memset( messageString, 0, len );
-    snprintf( messageString, len, "{""\"mtype\":\"%d\",""\"t\":\"%ld\",%s}", LIVE_DATA_MTYPE, curr_sec, liveData );
-    logInfo("%s:%d: packetLen=%d: %s", __func__,__LINE__,strlen(messageString), messageString );
-}
-
-void LiveDataLoggerApi( const char *liveData )
-{
-    time_t curr_sec = time(0);
-
-    LoggerQueue_t *LoggerEvent = LoggerQueue.alloc();
-
-    LiveData2Message( liveData, LoggerEvent->log_entry, sizeof(LoggerEvent->log_entry) );
-
-    LoggerEvent->position = 0;
-    LoggerQueue.put(LoggerEvent);
-
-    logInfo("dataLen=%d, packetLen=%d: %s", strlen(liveData), strlen(LoggerEvent->log_entry), LoggerEvent->log_entry );
-}
-
-void PeriodicLogger( bool force )
-{
-    bool log_sent=false;
-    std::ostringstream log_event;
-
-    int map_count = ModbusRegisterMap.size();
-    int collected_count = 0;
-
-    log_event << "\"lr\":[";
-    std::map<std::string, ModbusRegister>::iterator iter;
-    for (iter = ModbusRegisterMap.begin(); iter != ModbusRegisterMap.end(); ++iter) {
-
-        collected_count = collected_count + 1;
-
-        log_event << "{\"t\":"<< "\"" << iter->first.c_str() << "\"," << "\"v\":"<< "\"" << RegisterValueMap[iter->first].float_value<< "\"},";
-        log_sent = false;
-        if( log_event.str().size() >= 150 ) {
-            std::string str = log_event.str();
-            str.erase( str.size() - 1 );
-            if( collected_count == map_count ) {
-                str.append("],\"seq\":\"0\"");
-            } else {
-                str.append("],\"seq\":\"1\"");
-            }
-//            printf("%s:%d: Logging %s : len=%d\r\n", __func__, __LINE__, str.c_str(), str.length() );
-            LiveDataLoggerApi( str.c_str() );
-            log_event.str("");
-            log_event.clear();
-            log_event << "\"lr\":[";
-            log_sent = true;
-        }
-    }
-    if( log_sent == false ) {
-        std::string str = log_event.str();
-        str.erase( str.size() - 1 );
-        str.append("],\"seq\":\"0\"");
-        if( str.length() > 20 ) {
-//            printf("%s:%d: Logging %s : len=%d\r\n", __func__, __LINE__, str.c_str(), str.length() );
-            LiveDataLoggerApi( str.c_str() );
-        }
-    }
-}
-
-void GetCurrentReadings( char *currentReadings, int len )
-{
-    //bool log_sent=false;
-    std::ostringstream log_event;
-
-    log_event << "\"lr\":[";
-    std::map<std::string, ModbusRegister>::iterator iter;
-    for (iter = ModbusRegisterMap.begin(); iter != ModbusRegisterMap.end(); ++iter) {
-        log_event << "{\"t\":"<< "\"" << iter->first.c_str() << "\"," << "\"v\":"<< "\"" << RegisterValueMap[iter->first].float_value<< "\"},";
-    }
-
-    std::string str = log_event.str();
-    str.erase( str.size() - 1 );
-    str.append("],\"seq\":\"0\"");
-    LiveData2Message( str.c_str(), currentReadings, len );
-//    printf("GetCurrentReadings: packetLen=%d: %s, str.size(%d), (%s)\r\n", strlen(currentReadings), currentReadings, str.size(), str.c_str() );
-}
-
-void GetTagReadings( std::vector<std::string>  RequestedTags, char *currentReadings, int len )
-{
-    std::ostringstream log_event;
-
-    log_event << "\"lr\":[";
-    std::vector<std::string>::iterator iter;
-    for (iter = RequestedTags.begin(); iter != RequestedTags.end(); ++iter) {
-        log_event << "{\"t\":"<< "\"" << iter->c_str() << "\"," << "\"v\":"<< "\"" << RegisterValueMap[*iter].float_value<< "\"},";
-    }
-
-    std::string str = log_event.str();
-    str.erase( str.size() - 1 );
-    str.append("]");
-    LiveData2Message( str.c_str(), currentReadings, len );
-//    printf("GetCurrentReadings: packetLen=%d: %s, str.size(%d), (%s)\r\n", strlen(currentReadings), currentReadings, str.size(), str.c_str() );
-}
\ No newline at end of file
--- a/ICE-Application/src/DataHandler/LoggerApi.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-#ifndef LOGGERAPI_H
-#define LOGGERAPI_H
-
-#include "global.h"
-
-#include <vector>
-#include <string>
-
-extern void EventLoggerApi( EventReasonStruct_t &eventReason );
-extern void DeviceConnectedLoggerApi( unsigned int connected );
-extern void LiveDataLoggerApi( const char *liveData );
-extern void PeriodicLogger( bool force );
-extern void LiveData2Message( const char *liveData, char *messageString, int len );
-extern void GetCurrentReadings( char *currentReadings, int len );
-void GetTagReadings( std::vector<std::string>  RequestedTags, char *currentReadings, int len );
-void ReplyToHandler( ThreadName_t replyTo, std::string &id, int ret, float value );
-void CDH_ReplyToHandler( std::string &id, int status, float value );
-
-#endif 
-
--- a/ICE-Application/src/Drivers/LogLocalApi.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-#include <stdio.h>
-
-#include "LogLocalApi.h"
-#ifdef MDOT_ICE
-#include "MTSLog.h"
-#endif 
-#include "global.h"
-
-#define WAIT_TIME 5
-
-
-int LocalLogEntries = 0;
-
-void LogLocalApi( const char *logString )
-{
-    LogLocalApi_PushEntry( logString );
-}
-
-void LogLocalApi_PushEntry( const char *logString )
-{
-
-}
-
-bool LogLocalApi_PopEntry( char *logString )
-{
-    return true;
-}
-
--- a/ICE-Application/src/Drivers/LogLocalApi.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-#ifndef LOGLOCALAPI_H
-#define LOGLOCALAPI_H
-
-#include <string.h>
-
-#define LOG_BYTES_PER_ENTRY 256
-#define LOG_END_OF_STORAGE (EEP_NBYT - LOG_BYTES_PER_ENTRY)
-
-void LogLocalApi( const char *logString );
-void LogLocalApi_PushEntry( const char *logString );
-bool LogLocalApi_PopEntry( char *logString );
-
-#endif 
-
--- a/ICE-Application/src/Drivers/i2c_eeprom.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/** @file i2c_eeprom.cpp */
-/*CPP**************************************************************************
- * FILENAME :        i2c_eeprom.cpp                                           *
- *                                                                            *
- * DESCRIPTION :                                                              *
- *       Simple library for external I2C EEEPROM.                             *
- *                                                                            *
- * AUTHOR :    Olli Vanhoja        START DATE :    2011-02-17                 *
- *****************************************************************************/
- 
-#include "mbed.h"
-#include "i2c_eeprom.h"
-#include "global.h"
-
-I2C i2c_instance(I2C_SDA, I2C_SCL);
-  
-i2c_eeprom::i2c_eeprom(int hwAddr, int speed)
-{
-    i_i2c_address = hwAddr;
-//    i2c->frequency(speed);
-}
- 
-void i2c_eeprom::write(char *data, uint16_t iAddr, unsigned int n)
-{
-    char *pi2c_data[3]; // Pointers for CW items
-    char i2c_data[3];   // Final CW
-     
-    /* Convert address to hi and low byte array
-     * This is really pointless even though they are
-     * called pointers it would be lot easier to do this
-     * conversion without any pointers */
-    uint16_t *piAddr = &iAddr;
-    pi2c_data[0] = (char *)piAddr+1;
-    pi2c_data[1] = (char *)piAddr;
-    
-    for (uint16_t i=0; i < n; i++)
-    {
-        pi2c_data[2] = &data[i];
-        
-        // Apply actual values from pointer
-        //for (int n=0; n < 3; n++)
-        //    i2c_data[n] = *pi2c_data[n];
-        i2c_data[0] = *pi2c_data[0];
-        i2c_data[1] = *pi2c_data[1];
-        i2c_data[2] = *pi2c_data[2];
-        
-        // Send write command
-        strwrite:
-//        printf("(%s:%d): iAddr=0x%x, data=0x%x\r\n", __func__, __LINE__, iAddr, data[0]);
-        if(i2c->write(i_i2c_address, i2c_data, 3))
-        {
-            autoreset();
-            goto strwrite;
-        }
-        
-        iAddr++; // increment address counter
- 
-        // Wait for ACK        
-        while(i2c->write(i_i2c_address, NULL, 0)){}
-    }
-}
- 
-void i2c_eeprom::read(uint16_t iAddr, uint16_t n, char *out)
-{
-    char *pi2c_data[2]; // Pointers for CW items
-    char i2c_data[2];   // Final CW
-    
-    uint16_t *piAddr = &iAddr;
-    pi2c_data[0] = (char *)piAddr+1;
-    pi2c_data[1] = (char *)piAddr;
-        
-    // Apply actual values from pointer
-    //for (int i=0; i < 2; i++)
-    //    i2c_data[i] = *pi2c_data[i];
-    i2c_data[0] = *pi2c_data[0];
-    i2c_data[1] = *pi2c_data[1];
-    
-    // Send read command
-    strread:
-    if(i2c->write(i_i2c_address, i2c_data, 2))
-    {
-        autoreset();
-        goto strread;
-    }
-    if(i2c->read(i_i2c_address, out, n))
-    {
-        autoreset();
-        goto strread;
-    }
-//    printf("(%s:%d): iAddr=0x%x, data=0x%x\r\n", __func__, __LINE__, iAddr, *out);
-}
- 
-void i2c_eeprom::autoreset()
-{
-}
-
--- a/ICE-Application/src/Drivers/i2c_eeprom.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*H****************************************************************************
- * FILENAME :        i2c_eeprom.h                                             *
- *                                                                            *
- * DESCRIPTION :                                                              *
- *       Simple library for external I2C EEEPROM.                             *
- *                                                                            *
- * AUTHOR :    Olli Vanhoja        START DATE :    2011-02-17                 *
- ******************************************************************************
- *
- * CHANGES :
- *
- * VERSION DATE       WHO            DETAIL
- * 0.1     2011-02-21 Olli Vanhoja   Initial release version
- * 0.2     2011-02-21 Olli Vanhoja   *Added possibility change I2C speed
- *                                   *Added external reset pin and autoreset
- *                                    for read function. Thanks to Jon Ward.
- *                                   *Documentational comments added.
- * 0.3     2011-02-21 Olli Vanhoja   *Auto-reset for all error conditions
- *
- *H*/
- 
-#ifndef I2C_EEPROM_H
-#define I2C_EEPROM_H
- 
-/** I2C EEPROM access class
- * 
- * This class is used for communication with I2C EEPROM chip.
- */
-class i2c_eeprom {
-private:
-    int i_i2c_address; // I2C harware address
-    void autoreset();
-public:
-    /** Initialize communication
-    *
-    * @param hwAddr Harware address of the I2C EEPROM chip.
-    * @param speed I2C bus speed.
-    */
-    i2c_eeprom(int hwAddr, int speed);
-    
-    /** Write to I2C EEPROM
-    *
-    * Write any length of bytes to external EEPROM.
-    *
-    * @param *data Array of bytes.
-    * @param iAddr Memory address.
-    * @param n Write n bytes.
-    */
-    void write(char *data, uint16_t iAddr, unsigned int n);
-    
-    /** Read from I2C EEPROM
-    *
-    * Read any length of bytes from external EEPROM.
-    *
-    * @param iAddr Memory address.
-    * @param n Read n bytes.
-    * @param *out Returns array of bytes.
-    */
-    void read(uint16_t iAddr, uint16_t n, char *out);
-};
- 
-#endif
--- a/ICE-Application/src/Drivers/mod.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,516 +0,0 @@
-// modbus
-// ---------------------------------------------------------------------------------------------------------------------
-// includes
-
-#include "mbed.h"
-#include "global.h"
-#include "mod.h"
-
-// ---------------------------------------------------------------------------------------------------------------------
-// globals
-
-unsigned short int mod_data[MOD_DATA];
-unsigned short int mod_ireg[MOD_IREG];
-
-int mod_verbose = 0;
-
-// -------------------------------------------------------------------------------------------------
-// modbus buffers
-
-#define MOD_RXNUM 200
-#define MOD_TXNUM 200
-
-int mod_rxnum = 0;
-int mod_txnum = 0;
-
-unsigned char mod_rxbuf[MOD_RXNUM];
-unsigned char mod_txbuf[MOD_TXNUM];
-
-// -------------------------------------------------------------------------------------------------
-// print functions
-
-void print_uc(char hex, char bin, char dec, char* pre, unsigned char input, char* post)
-{
-    if(pre[0] != 0) printf("%s", pre);
-
-    if(hex)
-    {
-        printf("0x%02X", input);
-    }
-    if(bin)
-    {
-        if(hex) printf(" ");
-        for(int i=7; i>=0; i--)
-        {
-            if(i<7 && (i%4)==3) printf(" "); if(input & (1<<i)) printf("1"); else printf("0");
-        }
-    }
-    if(dec)
-    {
-        if(hex || bin) printf(" "); printf("%u", input);
-    }
-    if(post[0] != 0) printf("%s", post);
-}
-
-
-void print_us(char hex, char bin, char dec, char* pre, unsigned short int input, char* post)
-{
-    if(pre[0] != 0) printf("%s", pre);
-
-    if(hex)
-    {
-        printf("0x%04X", input);
-    }
-    if(bin)
-    {
-        if(hex) printf(" ");
-        for(int i=15; i>=0; i--)
-        {
-            if(i<15 && (i%4)==3) printf(" "); if(input & (1<<i)) printf("1"); else printf("0");
-        }
-    }
-    if(dec)
-    {
-        if(hex || bin) printf(" "); printf("%u", input);
-    }
-    if(post[0] != 0) printf("%s", post); 
-}
-
-// -------------------------------------------------------------------------------------------------
-// initialization
-
-RawSerial mod(PC_6, PC_7);
-
-DigitalOut mod_de(PC_8);
-DigitalOut mod_re(PC_9);
-
-void mod_init(void)
-{
-    mod_de = 0;
-    mod_re = 0;
-
-    mod.baud(MOD_BAUD);
-    mod.attach(&mod_process, RawSerial::RxIrq); 
-    
-    for(int i=0; i<MOD_IREG; i++) mod_ireg[i] = 0;
-}
-
-// -------------------------------------------------------------------------------------------------
-// utilities
-
-void mod_clear(void)
-{
-    mod_rxnum = 0; for(int i=0; i<MOD_RXNUM; i++) mod_rxbuf[i] = 0;
-    mod_txnum = 0; for(int i=0; i<MOD_TXNUM; i++) mod_txbuf[i] = 0;
-}
-
-unsigned short int mod_calc_crc(unsigned char *buffer, int length)
-{
-    unsigned short int temp=0xFFFF, flag;
-
-    for(int i=0; i<length; i++)
-    {
-        temp = temp ^ buffer[i];
-
-        for(int j=1; j<=8; j++)
-        {
-            flag = temp & 0x0001;
-            temp = temp >> 1;
-            if(flag) temp = temp ^ 0xA001;
-        }
-    }
-
-    return(temp);
-}
-
-void mod_ireg_dump(void)
-{
-    for(int i=0; i<MOD_IREG; i++)
-    {
-        printf("   I%02d = ", i);
-        print_us(1,0,1, "", mod_ireg[i], "\r\n");
-    }
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// process received data
-
-void mod_process(void)
-{
-    if(mod.readable())
-    {
-        if(mod_rxnum < MOD_RXNUM)
-        {
-            mod_rxbuf[mod_rxnum++] = mod.getc();
-        }
-        else
-        {
-            if(mod_verbose) printf("   [mod_process] buffer full\r\n");
-            mod_clear();
-        }
-    }
-} 
-
-// ---------------------------------------------------------------------------------------------------------------------
-// MOD_FUNC_GET_IREG (NBYT = total bytes of data transmitted)
-// MOD_FUNC_GET_HREG
-//
-//      byte:       0         1         2         3         4         5         6         7
-//      received:   ADDR      FUNC      SREG-H    SREG-L    NREG-H    NREG-L    RCRC-L    RCRC-H
-//      transmit:   ADDR      FUNC      NBYT      DATA-H    DATA-L    TCRC-L    TCRC-H    NULL
-    
-int mod_read(int inp_addr, int inp_func, int inp_sreg, int inp_nreg, unsigned char *rd_buf)
-{
-    int mod_error = 0;
-    
-    unsigned char tx_addr = inp_addr;
-    unsigned char tx_func = inp_func;
-    WORD2BYTE tx_sreg; tx_sreg.value = inp_sreg;
-    if(inp_nreg < 1) inp_nreg = 1;
-    WORD2BYTE tx_nreg; tx_nreg.value = inp_nreg;
-    
-// fill transmit buffer
-
-    mod_clear();
-    
-    mod_txbuf[mod_txnum++] = tx_addr;
-    mod_txbuf[mod_txnum++] = tx_func;
-    mod_txbuf[mod_txnum++] = tx_sreg.byte1;
-    mod_txbuf[mod_txnum++] = tx_sreg.byte0;
-    mod_txbuf[mod_txnum++] = tx_nreg.byte1;
-    mod_txbuf[mod_txnum++] = tx_nreg.byte0;
-
-    WORD2BYTE tx_crc; tx_crc.value = mod_calc_crc(mod_txbuf, mod_txnum);
-    mod_txbuf[mod_txnum++] = tx_crc.byte0;
-    mod_txbuf[mod_txnum++] = tx_crc.byte1;
-
-// transmit
-
-    mod_de = 1;
-    mod_re = 1;
-    wait_ms(1);
-    for(int i=0; i<mod_txnum; i++) mod.putc(mod_txbuf[i]);
-    wait_ms(2);
-    mod_de = 0;
-    mod_re = 0;
-
-    wait_ms(30);
-
-// output transmit buffer
-
-    if(mod_verbose)
-    {
-        printf("   mod_txbuf: %d\r\n\r\n", mod_txnum);
-        for(int i=0; i<mod_txnum; i++)
-        {
-            printf("      %02d", i); print_uc(1,0,1, " = ", mod_txbuf[i], "\r\n");
-        }
-        if(mod_txnum)
-        {
-            printf("\r\n");
-            print_uc(1,0,1, "      addr = ", tx_addr, "\r\n");
-            print_uc(1,0,1, "      func = ", tx_func, "\r\n");
-            print_us(1,0,1, "      sreg = ", tx_sreg.value, "\r\n");
-            print_us(1,0,1, "      nreg = ", tx_nreg.value, "\r\n");
-            print_us(1,0,1, "      tcrc = ", tx_crc.value, "\r\n");
-        }
-    }
-
-// process received buffer
-
-    if(mod_verbose)
-    {
-        printf("\r\n   mod_rxbuf: %d\r\n\r\n", mod_rxnum);
-        for(int i=0; i<mod_rxnum; i++)
-        {
-            printf("      %02d", i); print_uc(1,0,1, " = ", mod_rxbuf[i], "\r\n");
-        }
-    }
-    if(mod_rxnum)
-    {
-        int rxnum = 0;
-        unsigned char rx_addr = mod_rxbuf[rxnum++];
-        unsigned char rx_func = mod_rxbuf[rxnum++];
-
-        if(mod_verbose)
-        {
-            print_uc(1,0,1, "\r\n      addr = ", rx_addr, "\r\n");
-            print_uc(1,0,1,   "      func = ", rx_func, "");
-        }
-        if(rx_func == tx_func)
-        {
-            int rd_buf_index = 0;
-            unsigned char rx_nbyt = mod_rxbuf[rxnum++];
-
-            if(mod_verbose) print_uc(1,0,1, "\r\n      nbyt = ", rx_nbyt, "\r\n\r\n");
-
-            for(int i=0; i<rx_nbyt/2; i++)
-            {
-                WORD2BYTE rx_data;
-                rd_buf[rd_buf_index++] = rx_data.byte1 = mod_rxbuf[rxnum++];
-                rd_buf[rd_buf_index++] = rx_data.byte0 = mod_rxbuf[rxnum++];
-                
-                int ireg = tx_sreg.value + i;
-
-                if(ireg < MOD_IREG) mod_ireg[ireg] = rx_data.value;
-                
-                if(mod_verbose)
-                {
-                    printf("      data(%03d)", ireg);
-                    print_us(1,0,1, " = ", rx_data.value, "\r\n");
-                }
-            }
-            WORD2BYTE rx_crc;
-            rx_crc.byte0 = mod_rxbuf[rxnum++];
-            rx_crc.byte1 = mod_rxbuf[rxnum++];
-            
-            if(mod_verbose) print_us(1,0,1, "\r\n      rcrc = ", rx_crc.value, "\r\n");
-        }
-        else
-        {
-            unsigned char rx_nerr = mod_rxbuf[rxnum++]; mod_error = rx_nerr;
-
-            if(mod_verbose)
-            {
-                if(rx_func == tx_func+0x80) printf("  (func %d error)\r\n", tx_func);
-                else                        printf("  (unknown func error)\r\n");
-                print_uc(1,0,1, "      nerr = ", rx_nerr, "  (");
-
-                switch(rx_nerr)
-                {
-                    case MOD_ERROR_ILL_FUNC:     ; printf("slave received illegal function code")    ; break;
-                    case MOD_ERROR_ILL_ADDR:     ; printf("slave received illegal register address") ; break;
-                    case MOD_ERROR_ILL_DATA:     ; printf("slave received illegal register value")   ; break;
-                    case MOD_ERROR_SLAVE_FAIL:   ; printf("slave device-specific failure")           ; break;
-                    case MOD_ERROR_SLAVE_ACK:    ; printf("slave ACK")                               ; break;
-                    case MOD_ERROR_SLAVE_BUSY:   ; printf("slave is busy")                           ; break;
-                    case MOD_ERROR_SLAVE_NACK:   ; printf("slave NACK")                              ; break;
-                    case MOD_ERROR_SLAVE_PARITY: ; printf("slave memory parity error")               ; break;
-                    case MOD_ERROR_RX_TIMEOUT:   ; printf("master receive timeout")                  ; break;
-                    case MOD_ERROR_TX_TIMEOUT:   ; printf("master transmit timeout")                 ; break;
-                    case MOD_ERROR_CRC:          ; printf("master CRC error")                        ; break;
-                    default:                     ; printf("unknown error")                           ; break;
-                }
-                printf(")\r\n");
-            }
-
-            WORD2BYTE rx_crc;
-            rx_crc.byte0 = mod_rxbuf[rxnum++];
-            rx_crc.byte1 = mod_rxbuf[rxnum++];
-            
-            if(mod_verbose) print_us(1,0,1, "      rcrc = ", rx_crc.value, "\r\n");
-        }
-    }
-    else
-    {
-        mod_error = MOD_ERROR_RX_TIMEOUT; // no received data
-    }
-
-    if(mod_verbose) printf("\r\n   mod_error: %d\r\n", mod_error);
-
-    return(mod_error);
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// MOD_FUNC_SET_HREG
-//
-//      byte:       0         1         2         3         4         5         6         7         8
-//      received:   ADDR      FUNC      SREG-H    SREG-L    DATA-H    DATA-L    RCRC-L    RCRC-H
-//      transmit:   ADDR      FUNC      SREG-H    SREG-L    DATA-H    DATA-L    TCRC-L    TCRC-H    NULL
-//
-// MOD_FUNC_SET_HREGS
-//
-//      byte:       0         1         2         3         4         5         6         7         8         9         10
-//      received:   ADDR      FUNC      SREG-H    SREG-L    NREG-H    NREG-L    NBYT      DATA-H    DATA-L    RCRC-L    RCRC-H
-//      transmit:   ADDR      FUNC      SREG-H    SREG-L    NREG-H    NREG-L    TCRC-L    TCRC-H    NULL
-// 
-int mod_write(int inp_addr, int inp_func, int inp_sreg, int inp_nreg, unsigned char *xmt_data)
-{
-    int mod_error = 0;
-
-    unsigned char tx_addr = inp_addr;
-    unsigned char tx_func = inp_func;
-    WORD2BYTE tx_sreg; tx_sreg.value = inp_sreg;
-    WORD2BYTE tx_nreg; tx_nreg.value = inp_nreg;
-    WORD2BYTE data;
-    unsigned char nbyt = 2*inp_nreg;
-        
-// fill transmit buffer
-
-    mod_clear();
-    
-    mod_txbuf[mod_txnum++] = tx_addr;
-    mod_txbuf[mod_txnum++] = tx_func;
-    mod_txbuf[mod_txnum++] = tx_sreg.byte1;
-    mod_txbuf[mod_txnum++] = tx_sreg.byte0;
-    
-    if(tx_func == MOD_FUNC_SET_HREG)
-    {
-//        data.value = xmt_data[0];
-//        mod_txbuf[mod_txnum++] = data.byte1;
-//        mod_txbuf[mod_txnum++] = data.byte0;
-        mod_txbuf[mod_txnum++] = xmt_data[0];
-        mod_txbuf[mod_txnum++] = xmt_data[1];
-    }
-    else
-    {
-        mod_txbuf[mod_txnum++] = tx_nreg.byte1;
-        mod_txbuf[mod_txnum++] = tx_nreg.byte0;
-        mod_txbuf[mod_txnum++] = nbyt;
-        for(int i=0,i2=0; i<inp_nreg; i++)
-        {
- //           data.value = xmt_data[i];
- //           mod_txbuf[mod_txnum++] = data.byte1;
- //           mod_txbuf[mod_txnum++] = data.byte0;
-            mod_txbuf[mod_txnum++] = xmt_data[i2];
-            mod_txbuf[mod_txnum++] = xmt_data[(i2+1)];
-            i2=i2+2;
-        }
-    }
-    
-    WORD2BYTE tx_crc; tx_crc.value = mod_calc_crc(mod_txbuf, mod_txnum);
-    mod_txbuf[mod_txnum++] = tx_crc.byte0;
-    mod_txbuf[mod_txnum++] = tx_crc.byte1;
-
-// transmit
-
-    mod_de = 1;
-    mod_re = 1;
-    wait_ms(1);
-    for(int i=0; i<mod_txnum; i++) mod.putc(mod_txbuf[i]);
-    wait_ms(2);
-    mod_de = 0;
-    mod_re = 0;
-
-    wait_ms(30);
-
-// output transmit buffer
-
-    if(mod_verbose)
-    {
-        printf("   mod_txbuf: %d\r\n\r\n", mod_txnum);
-        for(int i=0; i<mod_txnum; i++)
-        {
-            printf("      %02d", i); print_uc(1,0,1, " = ", mod_txbuf[i], "\r\n");
-        }
-
-        if(mod_txnum)
-        {
-            print_uc(1,0,1, "\r\n      addr = ", tx_addr, "\r\n");
-            print_uc(1,0,1,   "      func = ", tx_func, "\r\n");
-            print_us(1,0,1,   "      sreg = ", tx_sreg.value, "\r\n");
-        
-            if(tx_func == MOD_FUNC_SET_HREG)
-            {
-                data.value = xmt_data[0];
-                print_us(1,0,1, "      data = ", data.value, "\r\n");
-            }
-            else
-            {
-                print_us(1,0,1, "      nreg = ", tx_nreg.value, "\r\n");
-                print_uc(1,0,1, "      nbyt = ", nbyt, "\r\n\r\n");
-
-                for(int i=0; i<inp_nreg; i++)
-                {
-                    printf("      data(%03d)", tx_sreg.value+i);
-                    data.value = xmt_data[i];
-                    print_us(1,0,1, " = ", data.value, "\r\n");
-                }
-            }
-            print_us(1,0,1, "      tcrc = ", tx_crc.value, "\r\n");
-        }
-    }
-
-// process received buffer
-
-    if(mod_verbose)
-    {
-        printf("\r\n   mod_rxbuf: %d\r\n\r\n", mod_rxnum);
-        for(int i=0; i<mod_rxnum; i++)
-        {
-            printf("      %02d", i); print_uc(1,0,1, " = ", mod_rxbuf[i], "\r\n");
-        }
-    }
-    if(mod_rxnum)
-    {
-        int rxnum = 0;
-        unsigned char rx_addr = mod_rxbuf[rxnum++];
-        unsigned char rx_func = mod_rxbuf[rxnum++];
-        
-        if(mod_verbose)
-        {
-            print_uc(1,0,1, "\r\n      addr = ", rx_addr, "\r\n");
-            print_uc(1,0,1,   "      func = ", rx_func, "");
-        }
-        
-        if(rx_func == tx_func)
-        {
-            WORD2BYTE rx_sreg;
-            rx_sreg.byte1 = mod_rxbuf[rxnum++];
-            rx_sreg.byte0 = mod_rxbuf[rxnum++];
-
-            WORD2BYTE rx_nreg;
-            rx_nreg.byte1 = mod_rxbuf[rxnum++];
-            rx_nreg.byte0 = mod_rxbuf[rxnum++];
-
-            WORD2BYTE rx_crc;
-            rx_crc.byte0 = mod_rxbuf[rxnum++];
-            rx_crc.byte1 = mod_rxbuf[rxnum++];
-
-            if(mod_verbose)
-            {
-                print_us(1,0,1, "\r\n      sreg = ", rx_sreg.value, "\r\n");
-                print_us(1,0,1,   "      nreg = ", rx_nreg.value, "\r\n");
-                print_us(1,0,1,   "      rcrc = ", rx_crc.value, "\r\n");
-            }
-        }
-        else
-        {
-            unsigned char rx_nerr = mod_rxbuf[rxnum++]; mod_error = rx_nerr;
-
-            if(mod_verbose)
-            {
-                if(rx_func == tx_func+0x80) printf("  (func %d error)\r\n", tx_func);
-                else                        printf("  (unknown func error)\r\n");
-
-                print_uc(1,0,1, "      nerr = ", rx_nerr, "  (");
-
-                switch(rx_nerr)
-                {
-                    case MOD_ERROR_ILL_FUNC:     ; printf("slave received illegal function code")    ; break;
-                    case MOD_ERROR_ILL_ADDR:     ; printf("slave received illegal register address") ; break;
-                    case MOD_ERROR_ILL_DATA:     ; printf("slave received illegal register value")   ; break;
-                    case MOD_ERROR_SLAVE_FAIL:   ; printf("slave device-specific failure")           ; break;
-                    case MOD_ERROR_SLAVE_ACK:    ; printf("slave ACK")                               ; break;
-                    case MOD_ERROR_SLAVE_BUSY:   ; printf("slave is busy")                           ; break;
-                    case MOD_ERROR_SLAVE_NACK:   ; printf("slave NACK")                              ; break;
-                    case MOD_ERROR_SLAVE_PARITY: ; printf("slave memory parity error")               ; break;
-                    case MOD_ERROR_RX_TIMEOUT:   ; printf("master receive timeout")                  ; break;
-                    case MOD_ERROR_TX_TIMEOUT:   ; printf("master transmit timeout")                 ; break;
-                    case MOD_ERROR_CRC:          ; printf("master CRC error")                        ; break;
-                    default:                     ; printf("unknown error")                           ; break;
-                }
-                printf(")\r\n");
-            }
-
-            WORD2BYTE rx_crc;
-            rx_crc.byte0 = mod_rxbuf[rxnum++];
-            rx_crc.byte1 = mod_rxbuf[rxnum++];
-            
-            if(mod_verbose) print_us(1,0,1, "      rcrc = ", rx_crc.value, "\r\n");
-        }
-    }
-    else
-    {
-        mod_error = MOD_ERROR_RX_TIMEOUT; // no received data
-    }
-
-    if(mod_verbose) printf("\r\n   mod_error: %d\r\n", mod_error);
-
-    return(mod_error);
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-
-
-
--- a/ICE-Application/src/Drivers/mod.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-#ifndef _MOD_H_
-#define _MOD_H_
-
-// -------------------------------------------------------------------------------------------------
-// globals
-
-#define MOD_DATA 4
-#define MOD_IREG 60
-#define MOD_BAUD 19200
-
-typedef struct word2byte { union
-{
-    unsigned short int value;
-    struct { unsigned char byte0; unsigned char byte1; };
-};}
-    WORD2BYTE;
-
-typedef struct sint2byte { union
-{
-    signed long int value;
-    struct { unsigned short int word0; unsigned short int word1; };
-    struct { unsigned char byte0; unsigned char byte1; unsigned char byte2; unsigned char byte3; };
-};}
-    SINT2BYTE;
-
-typedef struct uint2byte { union
-{
-    unsigned long int value;
-    struct { unsigned short int word0; unsigned short int word1; };
-    struct { unsigned char byte0; unsigned char byte1; unsigned char byte2; unsigned char byte3; };
-};}
-    UINT2BYTE;
-
-typedef struct float2byte { union
-{
-    float value;
-    struct { unsigned short int word0; unsigned short int word1; };
-    struct { unsigned char byte0; unsigned char byte1; unsigned char byte2; unsigned char byte3; };
-};}
-    FLOAT2BYTE;
-
-typedef struct float2uint { union
-{
-    float value;
-    unsigned long int uint_value;
-};}
-    FLOAT2UINT;
-
-
-extern unsigned short int mod_data[MOD_DATA];
-extern unsigned short int mod_ireg[MOD_IREG];
-
-extern int mod_verbose;
-
-// -------------------------------------------------------------------------------------------------
-// modbus standard communication structures: (from slave perspective)
-//
-// MOD_FUNC_GET_COIL (NBYT = total bytes of data transmitted)
-// MOD_FUNC_GET_DISC
-//
-//      byte:           0           1           2           3           4           5           6           7
-//      received:   ADDR        FUNC        SREG-H  SREG-L  NREG-H  NREG-L  RCRC-L  RCRC-H
-//      transmit:   ADDR        FUNC        NBYT        DATA-H  DATA-L  TCRC-L  TCRC-H  NULL
-//
-// MOD_FUNC_GET_IREG (NBYT = total bytes of data transmitted)
-// MOD_FUNC_GET_HREG
-//
-//      byte:           0           1           2           3           4           5           6           7
-//      received:   ADDR        FUNC        SREG-H  SREG-L  NREG-H  NREG-L  RCRC-L  RCRC-H
-//      transmit:   ADDR        FUNC        NBYT        DATA-H  DATA-L  TCRC-L  TCRC-H  NULL
-//
-// MOD_FUNC_SET_COIL
-//
-//      byte:           0           1           2           3           4           5           6           7           8
-//      received:   ADDR        FUNC        SREG-H  SREG-L  DATA-H  DATA-L  RCRC-L  RCRC-H
-//      transmit:   ADDR        FUNC        SREG-H  SREG-L  DATA-H  DATA-L  TCRC-L  TCRC-H  NULL
-//
-// MOD_FUNC_SET_COILS
-//
-//      byte:           0           1           2           3           4           5           6           7           8           9           10
-//      received:   ADDR        FUNC        SREG-H  SREG-L  NREG-H  NREG-L  NBYT        DATA-H  DATA-L  RCRC-L  RCRC-H
-//      transmit:   ADDR        FUNC        SREG-H  SREG-L  NREG-H  NREG-L  TCRC-L  TCRC-H  NULL
-//
-// MOD_FUNC_SET_HREG
-//
-//      byte:           0           1           2           3           4           5           6           7           8
-//      received:   ADDR        FUNC        SREG-H  SREG-L  DATA-H  DATA-L  RCRC-L  RCRC-H
-//      transmit:   ADDR        FUNC        SREG-H  SREG-L  DATA-H  DATA-L  TCRC-L  TCRC-H  NULL
-//
-// MOD_FUNC_SET_HREGS
-//
-//      byte:           0           1           2           3           4           5           6           7           8           9           10
-//      received:   ADDR        FUNC        SREG-H  SREG-L  NREG-H  NREG-L  NBYT        DATA-H  DATA-L  RCRC-L  RCRC-H
-//      transmit:   ADDR        FUNC        SREG-H  SREG-L  NREG-H  NREG-L  TCRC-L  TCRC-H  NULL
-//
-// response after error (EFUNC = FUNC + 0x80)
-//
-//      byte:           0           1           2           3           4           5
-//      transmit:   ADDR        EFUNC       ERROR       TCRC-L  TCRC-H  NULL
-//
-// -----------------------------------------------------------------------------
-// modbus definitions
-
-enum // function codes
-{
-    MOD_FUNC_00,
-    MOD_FUNC_GET_COIL,      // 01: read coil status
-    MOD_FUNC_GET_DISC,          // 02: read discrete inputs
-    MOD_FUNC_GET_HREG,      // 03: read holding registers
-    MOD_FUNC_GET_IREG,      // 04: read input registers
-    MOD_FUNC_SET_COIL,      // 05: force single coil
-    MOD_FUNC_SET_HREG,      // 06: preset single register
-    MOD_FUNC_07,
-    MOD_FUNC_08,
-    MOD_FUNC_09,
-    MOD_FUNC_10,
-    MOD_FUNC_11,
-    MOD_FUNC_12,
-    MOD_FUNC_13,
-    MOD_FUNC_14,
-    MOD_FUNC_SET_COILS,     // 15: force multiple coils
-    MOD_FUNC_SET_HREGS,     // 16: preset multiple registers
-    MOD_FUNC_NUM
-};
-
-enum // error codes ( * = used by Nubio )
-{
-    MOD_ERROR_NONE,
-    MOD_ERROR_ILL_FUNC,     // 01: * slave received illegal function code
-    MOD_ERROR_ILL_ADDR,     // 02: * slave received illegal register address
-    MOD_ERROR_ILL_DATA,     // 03: * slave received illegal register value
-    MOD_ERROR_SLAVE_FAIL,   // 04: * slave device-specific failure
-    MOD_ERROR_SLAVE_ACK,    // 05: * slave ACK
-    MOD_ERROR_SLAVE_BUSY,   // 06: slave is busy
-    MOD_ERROR_SLAVE_NACK,   // 07: * slave NACK (Nubio returns this for CRC error)
-    MOD_ERROR_SLAVE_PARITY, // 08: slave memory parity error
-    MOD_ERROR_RX_TIMEOUT,   // 09: master receive timeout
-    MOD_ERROR_TX_TIMEOUT,   // 10: master transmit timeout
-    MOD_ERROR_CRC,          // 11: master CRC error
-    MOD_ERROR_NUM
-};
-
-// -------------------------------------------------------------------------------------------------
-// function prototypes
-
-void mod_init(void);
-void mod_clear(void);
-
-void mod_process(void);
-
-void mod_ireg_dump(void);
-
-unsigned short int mod_calc_crc(unsigned char *buffer, int length);
-
-int mod_read(int inp_addr, int inp_func, int inp_sreg, int inp_nreg, unsigned char *rd_buf);
-int mod_write(int inp_addr, int inp_func, int inp_sreg, int inp_nreg, unsigned char *xmt_buf);
-
-// -------------------------------------------------------------------------------------------------
-
-#endif // _MOD_H_
--- a/ICE-Application/src/Drivers/rtc.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-// rtc.c - real time clock (MCP7940N)
-// -------------------------------------------------------------------------------------------------
-
-#include "mbed.h"
-#include "rtc.h"
-#include "global.h"
-
-// -------------------------------------------------------------------------------------------------
-// globals
-
-int rtc_verbose = 0;
-
-// -------------------------------------------------------------------------------------------------
-// initialization
-
-void rtc_init(void)
-{
-    if(rtc_verbose)
-    {
-        printf("\r\n[rtc_init] \r\n\r\n");
-    }
-    
-    char data[2];
-
-
-    data[0] = RTC_CONTROL_ADDR;
-
-    if(i2c->write(RTC_ADDR, data, RTC_SIZE_ADDR, true )) printf("no ack 1\r\n");
-    if(i2c->read (RTC_ADDR, data, RTC_SIZE_CONTROL, false)) printf("no ack 2\r\n");
-
-    if(rtc_verbose)
-    {
-        for(int i=0; i<RTC_SIZE_CONTROL; i++) { printf("   %d = ", i); printf("%d\r\n", data[i]); };
-    }
-
-    unsigned char control_reg = data[0];
-
-    if((control_reg & 0x80) == 1) // !EOSC
-    {
-        data[0] = RTC_CONTROL_ADDR;
-        data[1] = (control_reg & 0x7F); // clear !EOSC
-
-        if(i2c->write(RTC_ADDR, data, (RTC_SIZE_ADDR+RTC_SIZE_DATA), false)) printf("no ack 3\r\n");
-        
-        if(rtc_verbose) printf("   !EOSC bit reset (0x%x)\r\n\r\n", data[1]);
-    }
-
-    if(!rtc_verbose) printf("\r\nRTC: ");
-    rtc_print();
-}
-
-// -------------------------------------------------------------------------------------------------
-// read registers
-
-void rtc_regs(void)
-{
-    char data[RTC_SIZE_DATA];
-    
-    if(rtc_verbose)
-    {
-        printf("\r\n[rtc_regs] \r\n\r\n");
-    }
-
-    data[0] = 0x00; // address 0x00
-
-    if(i2c->write(RTC_ADDR, data, RTC_SIZE_ADDR, true )) printf("no ack 1\r\n");
-    if(i2c->read (RTC_ADDR, data, RTC_SIZE_DATA, false)) printf("no ack 2\r\n");
-
-    for(int i=0; i<RTC_SIZE_DATA; i++) { printf("   %d = ", i); printf("%d\r\n", data[i]); }
-}
-
-// -------------------------------------------------------------------------------------------------
-// RTC functions
-
-void rtc_get_time(int* iyr, int* imo, int* idy, int* ihr, int* imn, int* isc)
-{
-    char data[RTC_SIZE_DATA];
-    data[0] = 0x00;
-
-    if(i2c->write(RTC_ADDR, data, RTC_SIZE_ADDR, true )) printf("no ack 1\r\n");
-    if(i2c->read (RTC_ADDR, data, RTC_SIZE_DATA, false)) printf("no ack 2\r\n");
-
-    if(rtc_verbose)
-    {
-        printf("\r\n[rtc_get_time] \r\n\r\n");
-        for(int i=0; i<RTC_SIZE_DATA; i++) { printf("   %d = ", i); printf("%d\r\n", data[i]); };
-    }
-
-    *isc = 10*( (data[0] & 0x70)>>4 ) + (data[0] & 0x0F); // tens = 0b01110000(0x70), ones = 0b00001111(0x0F)
-    *imn = 10*( (data[1] & 0x70)>>4 ) + (data[1] & 0x0F); // tens = 0b01110000(0x70), ones = 0b00001111(0x0F)
-    *ihr = 10*( (data[2] & 0x10)>>4 ) + (data[2] & 0x0F); // tens = 0b00110000(0x30), ones = 0b00001111(0x0F)
-     // day of week
-    *idy = 10*( (data[4] & 0x30)>>4 ) + (data[4] & 0x0F); // tens = 0b00110000(0x30), ones = 0b00001111(0x0F)
-    *imo = 10*( (data[5] & 0x10)>>4 ) + (data[5] & 0x0F); // tens = 0b00010000(0x10), ones = 0b00001111(0x0F)
-    *iyr = 10*( (data[6] & 0xF0)>>4 ) + (data[6] & 0x0F); // tens = 0b11110000(0xF0), ones = 0b00001111(0x0F)
-    
-    *iyr += 2000;
-}
-
-void rtc_set_time(int iyr, int  imo, int  idy, int  ihr, int  imn, int  isc)
-{
-    char data[(RTC_SIZE_DATA+RTC_SIZE_ADDR)];
-    
-    int jyr = iyr; if(jyr >= 2000) jyr -= 2000;
-
-    data[0] = 0x00; // address byte
-    data[1] = 0x00; // data byte 0: seconds
-    data[2] = 0x00; // data byte 1: minutes
-    data[3] = 0x00; // data byte 2: hours
-    data[4] = 0x00; // data byte 3: weekday, set to 0x00 ? (usually reads 0x21 with OSCRUN and no PWRFAIL
-    data[5] = 0x00; // data byte 4: day
-    data[6] = 0x00; // data byte 5: month
-    data[7] = 0x00; // data byte 6: year
-
-    data[1] = ((isc/10)<<4) | (isc%10); // seconds
-    data[2] = ((imn/10)<<4) | (imn%10); // minutes
-    data[3] = ((ihr/10)<<4) | (ihr%10); // hours
-    data[5] = ((idy/10)<<4) | (idy%10); // days
-    data[6] = ((imo/10)<<4) | (imo%10); // months
-    data[7] = ((jyr/10)<<4) | (jyr%10); // years
-
-    if(i2c->write(RTC_ADDR, data, (RTC_SIZE_DATA+RTC_SIZE_ADDR), false)) printf("no ack\r\n");
-
-    if(rtc_verbose)
-    {
-        printf("\r\n[rtc_set_time] \r\n\r\n");
-        printf("   raw data\r\n");
-        for(int i=0; i<(RTC_SIZE_DATA+RTC_SIZE_ADDR); i++) { printf("   %d = ", i); printf("%d\r\n", data[i]); };
-    }
-}
-
-void rtc_set(const char* s)
-{
-    int iyr, imo, idy, ihr, imn, isc;
-
-    if(sscanf(s, "%d-%d-%d %d:%d:%d", &iyr, &imo, &idy, &ihr, &imn, &isc) != 6)
-    {
-        printf("   [rtc_set] parse error\r\n");
-    }
-    else
-    {
-        if(rtc_verbose) printf("   date: %04d-%02d-%02d %02d:%02d:%02d\r\n", iyr, imo, idy, ihr, imn, isc);
-
-        rtc_set_time(iyr, imo, idy, ihr, imn, isc);
-
-        printf("   [rtc_set] "); rtc_print();
-    }
-}
-
-void rtc_print(void)
-{
-    int iyr=0, imo=0, idy=0, ihr=0, imn=0, isc=0;
-
-    rtc_get_time(&iyr, &imo, &idy, &ihr, &imn, &isc);
-
-    printf("%04d-%02d-%02d %02d:%02d:%02d", iyr, imo, idy, ihr, imn, isc);
-}
-
-// -------------------------------------------------------------------------------------------------
--- a/ICE-Application/src/Drivers/rtc.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-#ifndef _RTC_H_
-#define _RTC_H_
-
-// -------------------------------------------------------------------------------------------------
-// globals
-
-#define RTC_ADDR 0xD0 // address byte: 0b11010000(R/W) -> DS1339
-
-#define RTC_SIZE_ADDR           1
-#define RTC_SIZE_DATA           7
-#define RTC_SIZE_CONTROL        1
-#define RTC_SIZE_STAUS          1
-
-#define RTC_SECONDS_ADDR        0x0
-#define RTC_MINUTES_ADDR        0x1
-#define RTC_HOURS_ADDR          0x2
-#define RTC_DOW_ADDR            0x3
-#define RTC_MDAY_ADDR           0x4
-#define RTC_MONTH_ADDR          0x5
-#define RTC_YEAR_ADDR           0x6
-
-#define RTC_CONTROL_ADDR        0xE
-#define RTC_STATUS_ADDR         0xF
-#define RTC_TRICKLE_ADDR        0x10
-
-extern int rtc_verbose;
-
-// -------------------------------------------------------------------------------------------------
-// function prototypes
-
-void rtc_init(void);
-void rtc_regs(void);
-
-void rtc_print(void);
-
-void rtc_get_time(int* iyr, int* imo, int* idy, int* ihr, int* imn, int* isc);
-void rtc_set_time(int  iyr, int  imo, int  idy, int  ihr, int  imn, int  isc);
-
-void rtc_set(const char* s);
-
-// -------------------------------------------------------------------------------------------------
-
-#endif // _RTC_H_
--- a/ICE-Application/src/ModbusMaster/ModbusMaster.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,802 +0,0 @@
-/******************************************************************************
- *
- * File:                ModbusMaster.cpp
- * Desciption:          source for the ICE Modbus Master
- *
- *****************************************************************************/
-#include "global.h"
-#include <stdio.h>
-#include "BLEDataHandler.h"
-#include "ModbusMaster.h"
-#include "ModbusMasterApi.h"
-#include "CloudDataHandler.h"
-#include "LoggerApi.h"
-#include "mod.h"
-#include "cJSON.h"
-#include "rtc.h"
-#include "rtos.h"
-#include "mbed.h"
-#include "v7_execute.h"
-#include "utilities.h"
-
-DigitalOut dout1(PB_0);
-DigitalOut dout2(PB_1);
-DigitalIn flow_switch(PC_12);
-DigitalIn dinp2(PC_11);
-
-/*****************************************************************************
- * Function:             ModbusMaster
- * Description:          entry point for the Modbus Master
- *
- * @param                (IN) args (user-defined arguments)
- * @return               none
- *****************************************************************************/
-//std::map<std::string,VirtualCommand> VirtualCommandMap;
-
-std::map<std::string, VirtualCommand> VirtualCommandMap;
-std::map<std::string, ExecuteJavaScript> ExecuteJavaScriptMap;
-std::map<std::string, HoldingRegister> HoldingRegisterMap;
-
-void LoadModbusConfigFile( char *fileName );
-void UpdateSimulatedInput( std::map<std::string, ModbusRegister>::iterator &modMap );
-void UpdateVirtualRegister( std::map<std::string, ModbusRegister>::iterator &modMap );
-void ReadModbusRegister( std::map<std::string, ModbusRegister>::iterator &modMap );
-void ExecuteRegisterCommand( std::string ioString, std::string Command  );
-void ExecuteRegisterOperation( std::map<std::string, VirtualCommand>::iterator &cmdMap );
-void UpdateOutputRegister( std::map<std::string, ModbusRegister>::iterator &modMap );
-
-char ModbusMasterScratchBuf[MAX_FILE_SIZE];
-void ModbusMaster(void const *args)
-{
-    printf("%s ModbusMaster has started...", __func__);
-    bool SignaledMain = false;
-    std::map<std::string, ModbusRegister>::iterator modMap;
-
-    mod_init();
-    DigitalOut mod_power(PA_8);
-    mod_power = 0; // provide power to the modbus
-
-#ifdef EXECUTE_SCRIPT
-    v7_Create_Engine();
-#endif
-
-#ifdef LOAD_PERSISTENT_CONFIGURATIONS
-    std::vector<std::string>::iterator file;
-    std::vector<std::string> file_list;
-    file_list = GLOBAL_mdot->listUserFiles();
-    for(file = file_list.begin(); file != file_list.end(); ++file) {
-//        printf("%s:%d: filename:%s\r\n", __func__, __LINE__, file->c_str() );
-        LoadModbusConfigFile( (char *)file->c_str() );
-    }
-#endif
-    
-    while ( true ) {
-        for (modMap = ModbusRegisterMap.begin(); modMap != ModbusRegisterMap.end(); ++modMap) {
-            if( modMap->second.simulated == true ) {
-                UpdateSimulatedInput( modMap );
-                continue;
-            } else if( modMap->second.node != 0 ) {
-                ReadModbusRegister( modMap );
-            } else if( (modMap->second.node == 0) && (modMap->second.regType == REG_TYPE_INPUT) ) {
-//                printf("processing PIN input=%s, reg=%d, value=%d",modMap->first.c_str(), ModbusRegisterMap[modMap->first].reg, (bool)RegisterValueMap[modMap->first].float_value);
-                if( ModbusRegisterMap[modMap->first].reg == 1 ) {
-                    // digital input
-                    RegisterValueMap[modMap->first].float_value = (float)flow_switch.read();
-                } else {
-                    RegisterValueMap[modMap->first].float_value = (float)dinp2.read();
-                }
-            } else if( modMap->second.regType == REG_TYPE_VINPUT ) {
-                UpdateVirtualRegister( modMap );
-            }
-        }
-
-        // now that all of the modbus registers are updated we can execute the register commands.
-#ifdef EXECUTE_SCRIPT
-        std::map<std::string, ExecuteJavaScript>::iterator jsMap;
-        for (jsMap = ExecuteJavaScriptMap.begin(); jsMap != ExecuteJavaScriptMap.end(); ++jsMap) {
-//            printf("%s:%d: %s\r\n", __func__, __LINE__, Util_getHeapData().c_str());
-            v7_Execute_Script( jsMap->second.script, jsMap->second.argv  );
-        }
-#else
-        for (modMap = ModbusRegisterMap.begin(); modMap != ModbusRegisterMap.end(); ++modMap) {
-            ExecuteRegisterCommand( modMap->first, modMap->second.cmd );
-        }
-#endif
-
-        // now that all of the inputs and virtuals have been updated, go through the outputs.
-        for (modMap = ModbusRegisterMap.begin(); modMap != ModbusRegisterMap.end(); ++modMap) {
-            if( modMap->second.regType == REG_TYPE_OUTPUT ) {
-                UpdateOutputRegister( modMap );
-            }
-        }
-
-        osEvent evt = ModbusMasterMailBox.get(50);
-        if (evt.status == osEventMail) {
-            ModbusMasterReq_t *mail = (ModbusMasterReq_t*)evt.value.p;
-            if( mail->action == ACTION_EXEC_CMD ) {
-                printf("Mail Received: Action: %d, Executing Command: %s\r\n", mail->action, mail->msg);
-                ModbusMasterExecCmd( mail->replyThread, mail->msg );
-            } else {
-                printf("Mail Received: Action: %d, New Input File: %s\r\n", mail->action, mail->msg);
-                LoadModbusConfigFile( mail->msg );
-            }
-            ModbusMasterMailBox.free(mail);
-        }
-        if( SignaledMain == false ) {
-            SignaledMain = true;
-            osSignalSet(mainThreadId, sig_output_continue);
-        }
-        Thread::wait(5000);
-    }
-}
-
-bool ReadModbus_32bit_float( float *float_value, int order, unsigned char *rd_buf )
-{
-    MR_REGISTER_32_BIT_FLOAT value;
-
-    switch( order ) {
-        case BigEndian:
-            value.b.lo_lo = rd_buf[3];
-            value.b.lo_hi = rd_buf[2];
-            value.b.hi_lo = rd_buf[1];
-            value.b.hi_hi = rd_buf[0];
-            break;
-        case BigEndianReverseWord:
-            value.b.lo_lo = rd_buf[1];
-            value.b.lo_hi = rd_buf[0];
-            value.b.hi_lo = rd_buf[3];
-            value.b.hi_hi = rd_buf[2];
-            break;
-        default:
-            printf("%s:%d: order not supported\r\n",__func__,__LINE__);
-            return false;
-    }
-//    printf("0x%x 0x%x 0x%x 0x%x (%2.4f)\r\n", value.b.hi_hi, value.b.hi_lo, value.b.lo_hi, value.b.lo_lo, value.f);
-    *float_value = value.f;
-    return true;
-}
-
-bool WriteModbus_32bit_float( float float_value, int order, unsigned char *xmt_buf )
-{
-    MR_REGISTER_32_BIT_FLOAT value;
-
-    value.f = float_value;
-
-    switch( order ) {
-        case BigEndian:
-            xmt_buf[3] = value.b.lo_lo;
-            xmt_buf[2] = value.b.lo_hi;
-            xmt_buf[1] = value.b.hi_lo;
-            xmt_buf[0] = value.b.hi_hi;
-            break;
-        case BigEndianReverseWord:
-            xmt_buf[1] = value.b.lo_lo;
-            xmt_buf[0] = value.b.lo_hi;
-            xmt_buf[3] = value.b.hi_lo;
-            xmt_buf[2] = value.b.hi_hi;
-            break;
-        default:
-            printf("%s:%d: order not supported\r\n",__func__,__LINE__);
-            return false;
-    }
-    printf("%s:%d: 0x%x 0x%x 0x%x 0x%x (%2.4f)\r\n",__func__,__LINE__, value.b.hi_hi, value.b.hi_lo, value.b.lo_hi, value.b.lo_lo, value.f);
-    return true;
-}
-
-bool WriteModbus_Multiple( std::vector<uint16_t>  XmtData, int order, unsigned char *xmt_buf )
-{
-    MR_REGISTER_32_BIT_FLOAT value;
-
-//    std::vector<uint16_t>::iterator iter;
-//    for (iter = XmtData.begin(); iter != XmtData.end(); ++iter) {
-//        log_event << "{\"t\":"<< "\"" << iter->c_str() << "\"," << "\"v\":"<< "\"" << ModbusRegisterMap[*iter].float_value<< "\"},";
-//    }
-
-    switch( order ) {
-        case BigEndian:
-            xmt_buf[3] = value.b.lo_lo;
-            xmt_buf[2] = value.b.lo_hi;
-            xmt_buf[1] = value.b.hi_lo;
-            xmt_buf[0] = value.b.hi_hi;
-            break;
-        case BigEndianReverseWord:
-            xmt_buf[1] = value.b.lo_lo;
-            xmt_buf[0] = value.b.lo_hi;
-            xmt_buf[3] = value.b.hi_lo;
-            xmt_buf[2] = value.b.hi_hi;
-            break;
-        default:
-            printf("%s:%d: order not supported\r\n",__func__,__LINE__);
-            return false;
-    }
-    printf("%s:%d: 0x%x 0x%x 0x%x 0x%x (%2.4f)\r\n",__func__,__LINE__, value.b.hi_hi, value.b.hi_lo, value.b.lo_hi, value.b.lo_lo, value.f);
-    return true;
-}
-
-bool ReadModbus_32bit_int( int32_t *int32_value, int order, unsigned char *rd_buf )
-{
-    MR_REGISTER_32BIT_INT value;
-
-    switch( order ) {
-        case BigEndian:
-            value.b.lo_lo = rd_buf[3];
-            value.b.lo_hi = rd_buf[2];
-            value.b.hi_lo = rd_buf[1];
-            value.b.hi_hi = rd_buf[0];
-            break;
-        case BigEndianReverseWord:
-            value.b.lo_lo = rd_buf[1];
-            value.b.lo_hi = rd_buf[0];
-            value.b.hi_lo = rd_buf[3];
-            value.b.hi_hi = rd_buf[2];
-            break;
-        default:
-            printf("%s:%d: order not supported\r\n",__func__,__LINE__);
-            return false;
-    }
-//    printf("0x%x 0x%x 0x%x 0x%x (%d)\r\n", value.b.hi_hi, value.b.hi_lo, value.b.lo_hi, value.b.lo_lo, value.i);
-    *int32_value = value.i;
-    return true;
-}
-
-bool WriteModbus_32bit_int( int32_t int32_value, int order, unsigned char *xmt_buf )
-{
-    MR_REGISTER_32BIT_INT value;
-
-    value.i = int32_value;
-
-    switch( order ) {
-        case BigEndian:
-            xmt_buf[3] = value.b.lo_lo;
-            xmt_buf[2] = value.b.lo_hi;
-            xmt_buf[1] = value.b.hi_lo;
-            xmt_buf[0] = value.b.hi_hi;
-            break;
-        case BigEndianReverseWord:
-            xmt_buf[1] = value.b.lo_lo;
-            xmt_buf[0] = value.b.lo_hi;
-            xmt_buf[3] = value.b.hi_lo;
-            xmt_buf[2] = value.b.hi_hi;
-            break;
-        default:
-            printf("%s:%d: order not supported\r\n",__func__,__LINE__);
-            return false;
-    }
-    printf("%s:%d: 0x%x 0x%x 0x%x 0x%x (%d)\r\n", __func__, __LINE__, value.b.hi_hi, value.b.hi_lo, value.b.lo_hi, value.b.lo_lo, value.i);
-    return true;
-}
-
-bool WriteModbus_16bit_int( int16_t int16_value, int order, unsigned char *xmt_buf )
-{
-    MR_REGISTER_16BIT_INT value;
-
-    value.w = int16_value;
-
-    switch( order ) {
-        case BigEndian:
-        case BigEndianReverseWord:
-            xmt_buf[1] = value.b.lo;
-            xmt_buf[0] = value.b.hi;
-            break;
-        default:
-            printf("%s:%d: order not supported\r\n",__func__,__LINE__);
-            return false;
-    }
-    printf("%s:%d: 0x%x 0x%x (%d)\r\n", __func__,__LINE__, value.b.hi, value.b.lo, value.w);
-    return true;
-}
-
-void ModbusMasterExecCmd( ThreadName_t replyTo, char *cmd )
-{
-    bool status;
-    int ret;
-    int node, func, sreg, nreg, dtype, order;
-    float value;
-    unsigned char rd_buf[16];
-    std::vector<uint16_t>  XmtData;
-
-    printf("%s:%d: command=%s\r\n", __func__, __LINE__, cmd );
-
-    cJSON * root = cJSON_Parse(cmd);
-    std::string id = cJSON_GetObjectItem(root,"id")->valuestring;
-    if ( cJSON_HasObjectItem(root, "holding") ) {
-
-        std::string key = cJSON_GetObjectItem(root,"holding")->valuestring;
-        node = HoldingRegisterMap[key].node;
-        sreg = HoldingRegisterMap[key].sreg;
-        nreg = HoldingRegisterMap[key].nreg;
-        order = HoldingRegisterMap[key].order;
-        func = MODBUS_WRITE_MULTIPLE_HOLDING;
-        dtype = TYPE_MULTI_BYTE;
-        printf("%s:%d: HOLDING REGISTER COMMAND, tag=%s, node=%d, sreg=%d, nreg=%d, order=%d, func=%d\r\n", __func__,__LINE__, key.c_str(), node, sreg, nreg, order, func);
-        cJSON *data    = cJSON_GetObjectItem(root, "data");
-        for ( int i = 0; i < cJSON_GetArraySize(data); ++i ) {
-            cJSON *item = cJSON_GetArrayItem(data, i);
-            uint16_t item_value      = atoi(cJSON_GetObjectItem(item, "v")->valuestring);
-            XmtData.push_back(item_value);
-            printf("Pushing data: %d\r\n",item_value);
-        }
-    } else {
-        node = atoi(cJSON_GetObjectItem(root,"node")->valuestring);
-        func = atoi(cJSON_GetObjectItem(root,"func")->valuestring);
-        sreg = atoi(cJSON_GetObjectItem(root,"sreg")->valuestring);
-        nreg = atoi(cJSON_GetObjectItem(root,"nreg")->valuestring);
-        dtype = atoi(cJSON_GetObjectItem(root,"dtype")->valuestring);
-        order = atoi(cJSON_GetObjectItem(root,"order")->valuestring);
-        value = atof(cJSON_GetObjectItem(root,"value")->valuestring);
-        if( dtype == TYPE_MULTI_BYTE ) {
-            if ( cJSON_HasObjectItem(root, "data") ) {
-                cJSON *data    = cJSON_GetObjectItem(root, "data");
-                for ( int i = 0; i < cJSON_GetArraySize(data); ++i ) {
-                    cJSON *item = cJSON_GetArrayItem(data, i);
-                    uint16_t item_value      = atoi(cJSON_GetObjectItem(item, "v")->valuestring);
-                    XmtData.push_back(item_value);
-                    printf("Pushing data: %d\r\n",item_value);
-                }
-            } else {
-                printf("NO DATA FOR WRITE MULTIPLE HOLDING REGISTERS\r\n");
-                ReplyToHandler( replyTo, id, DATA_ARRAY_MISSING, 0 );
-                return;
-            }
-        }
-    }
-    cJSON_Delete(root);
-
-    switch( func ) {
-        case MOD_FUNC_GET_HREG: // read holding register
-        case MOD_FUNC_GET_IREG: // read input register
-            ret = mod_read(node, func, sreg, nreg, rd_buf);
-            if( ret != MOD_ERROR_NONE ) {
-                ReplyToHandler( replyTo, id, ret, 0 );
-                printf("CMD: %s:%d: %s failed, errflag=%d\r\n", __func__, __LINE__,  id.c_str(), ret );
-                break;
-            }
-            switch( dtype ) {
-                case TYPE_32BIT_FLOAT: {
-                    float float_value;
-                    status = ReadModbus_32bit_float( &float_value, order, rd_buf );
-                    if( status == true ) {
-                        printf("CMD: %s:%d: %s value=%2.4f\r\n", __func__, __LINE__,  id.c_str(), float_value );
-                        ret = SUCCESS;
-                    } else {
-                        printf("CMD: %s:%d: %s failed\r\n", __func__, __LINE__, id.c_str() );
-                        ret = ORDER_NOT_SUPPORTED;
-                    }
-                    ReplyToHandler( replyTo, id, ret, float_value );
-                    break;
-                }
-                case TYPE_32BIT_INT:
-                case TYPE_32BIT_UINT: {
-                    int32_t int32_value;
-                    status = ReadModbus_32bit_int( &int32_value, order, rd_buf );
-                    if( status == true ) {
-                        printf("CMD: %s:%d: %s value=%d\r\n", __func__, __LINE__,  id.c_str(), int32_value );
-                        ret = SUCCESS;
-                    } else {
-                        printf("CMD: %s:%d: %s failed\r\n", __func__, __LINE__, id.c_str() );
-                        ret = ORDER_NOT_SUPPORTED;
-                    }
-                    ReplyToHandler( replyTo, id, ret, (float)int32_value );
-                    break;
-                }
-                case TYPE_16BIT_INT:
-                case TYPE_16BIT_UINT:
-                    break;
-                default:
-                    break;
-            }
-            break;
-        case MOD_FUNC_SET_HREG:  // write holding register
-        case MOD_FUNC_SET_HREGS: // write multiple registers (only supports 2 right now)
-        case MOD_FUNC_SET_COIL:  { // write coil
-            unsigned char xmt_buf[10];
-            switch( dtype ) {
-                case TYPE_32BIT_FLOAT: {
-                    status = WriteModbus_32bit_float( value, order, xmt_buf );
-                    if( status != true ) {
-                        printf("CMD: %s:%d: %s failed\r\n", __func__, __LINE__, id.c_str() );
-                        return;
-                    }
-                    printf("%s:%d: 0x%x 0x%x 0x%x 0x%x\r\n", __func__,__LINE__, xmt_buf[0], xmt_buf[1], xmt_buf[2], xmt_buf[3]);
-                    break;
-                }
-                case TYPE_32BIT_INT:
-                case TYPE_32BIT_UINT: {
-                    status = WriteModbus_32bit_int( (int32_t)value, order, xmt_buf );
-                    if( status != true ) {
-                        printf("CMD: %s:%d:  %s failed\r\n", __func__, __LINE__, id.c_str() );
-                        return;
-                    }
-                    break;
-                }
-                case TYPE_16BIT_INT:
-                case TYPE_16BIT_UINT:
-                    status = WriteModbus_16bit_int( (int16_t)value, order, xmt_buf );
-                    if( status != true ) {
-                        printf("CMD: %s:%d: %s failed\r\n", __func__, __LINE__, id.c_str() );
-                        return;
-                    }
-                    printf("%s:%d: 0x%x 0x%x\r\n", __func__,__LINE__, xmt_buf[0], xmt_buf[1]);
-                    break;
-                case TYPE_MULTI_BYTE :
-                    printf("CMD: %s:%d: WRITE MULTI-BYTE NOT IMPLEMENTED\r\n", __func__, __LINE__ );
-                    ReplyToHandler( replyTo, id, UNKNOWN_OPERATION, 0 );
-                    return;
-                    //break;
-                default:
-                    printf("CMD: %s:%d: %s NOT IMPLEMENTED\r\n", __func__, __LINE__, id.c_str() );
-                    return;
-            }
-            printf("%s:%d: 0x%x 0x%x 0x%x 0x%x\r\n", __func__,__LINE__, xmt_buf[0], xmt_buf[1], xmt_buf[2], xmt_buf[3]);
-            ret = mod_write(node, func, sreg, nreg, xmt_buf);
-            if( ret != MOD_ERROR_NONE ) {
-                printf("CMD: %s:%d: %s failed, errflag=%d\r\n", __func__, __LINE__, id.c_str(), ret );
-            } else {
-                printf("CMD: %s:%d: %s wrote to modbus func=%d reg=%d value=%2.4f, errflag=%d\r\n", __func__, __LINE__, id.c_str(), func, sreg, value, ret );
-            }
-            ReplyToHandler( replyTo, id, ret, 0 );
-            break;
-        }
-        default:
-            printf("CMD: %s:%d: %s failed, errflag=%d\r\n", __func__, __LINE__, id.c_str(), ret );
-            ReplyToHandler( replyTo, id, UNKNOWN_OPERATION, 0 );
-            break;
-    }
-}
-
-void LoadModbusConfigFile( char *fileName )
-{
-    bool status;
-    RegisterType_t regType;
-
-//    printf("%s:%d: Loading Config file: %s\r\n", __func__, __LINE__, fileName);
-
-    if( (strncmp( fileName, "cmd_", (strlen("cmd_")-1)) == 0) ) {
-        status = GLOBAL_mdot->readUserFile(fileName, ModbusMasterScratchBuf, MAX_FILE_SIZE);
-        if( status != true ) {
-            printf("(%d)read file failed, status=%d\r\n", __LINE__, status);
-            return;
-        }
-
-        cJSON * root = cJSON_Parse(ModbusMasterScratchBuf);
-        std::string id = cJSON_GetObjectItem(root,"id")->valuestring;
-        VirtualCommandMap[id].Constant = atof(cJSON_GetObjectItem(root,"Constant")->valuestring);
-        VirtualCommandMap[id].Operator = cJSON_GetObjectItem(root,"Operator")->valuestring;
-        VirtualCommandMap[id].Operand = cJSON_GetObjectItem(root,"Operand")->valuestring;
-        printf("Loaded command file: id=%s, Operand=%s, Operator=%s, Constant=%.4f\r\n", id.c_str(), VirtualCommandMap[id].Operand.c_str(), VirtualCommandMap[id].Operator.c_str(), VirtualCommandMap[id].Constant);
-        cJSON_Delete(root);
-        return;
-    }
-
-    if( (strncmp( fileName, "vreg_", (strlen("vreg_")-1)) == 0) ) {
-        printf("Loading Virtual Register File: %s\r\n", fileName);
-        status = GLOBAL_mdot->readUserFile(fileName, ModbusMasterScratchBuf, MAX_FILE_SIZE);
-        if( status != true ) {
-            printf("(%d)read file failed, status=%d\r\n", __LINE__, status);
-            return;
-        }
-
-        cJSON * root = cJSON_Parse(ModbusMasterScratchBuf);
-        std::string id = cJSON_GetObjectItem(root,"id")->valuestring;
-        RegisterValueMap[id].float_value = atof(cJSON_GetObjectItem(root,"value")->valuestring);
-        RegisterValueMap[id].errflag = 0;
-        printf("Loaded Virtual Register file: id=%s, value=%.4f\r\n", id.c_str(),  RegisterValueMap[id].float_value);
-        cJSON_Delete(root);
-        return;
-    }
-
-#ifdef EXECUTE_SCRIPT
-    if( (strncmp( fileName, "js_", (strlen("js_")-1)) == 0) ) {
-        printf("Loading JavaScript file: %s\r\n", fileName);
-        status = GLOBAL_mdot->readUserFile(fileName, ModbusMasterScratchBuf, MAX_FILE_SIZE);
-        if( status != true ) {
-            printf("(%d)read file failed, status=%d\r\n", __LINE__, status);
-            return;
-        }
-        v7_Load_Script( (const char *)ModbusMasterScratchBuf );
-//        printf("Loaded function: %s\r\n", ModbusMasterScratchBuf);
-        return;
-    }
-
-    if( (strncmp( fileName, "exe_js_", (strlen("exe_js_")-1)) == 0) ) {
-        printf("Loading JavaScript Execution file: %s\r\n", fileName);
-        status = GLOBAL_mdot->readUserFile(fileName, ModbusMasterScratchBuf, MAX_FILE_SIZE);
-        if( status != true ) {
-            printf("(%d)read file failed, status=%d\r\n", __LINE__, status);
-            return;
-        }
-        cJSON * root = cJSON_Parse(ModbusMasterScratchBuf);
-        std::string id = cJSON_GetObjectItem(root,"id")->valuestring;
-        ExecuteJavaScriptMap[id].script = cJSON_GetObjectItem(root, "script")->valuestring;
-        cJSON *args    = cJSON_GetObjectItem(root, "args");
-        printf("%s:%d: Number of array items: %d\r\n", __func__, __LINE__, cJSON_GetArraySize(args) );
-        for ( int i = 0; i < cJSON_GetArraySize(args); ++i ) {
-            cJSON *item = cJSON_GetArrayItem(args, i);
-            ExecuteJavaScriptMap[id].argv[i] = cJSON_GetObjectItem(item, "arg")->valuestring;
-//            printf("Pushing tag data %s\r\n", cJSON_GetObjectItem(item, "arg")->valuestring);
-        }
-        printf("Loaded JavaScript Execute File: id=%s, script=%s, argv0=%s, argv0=%s, argv0=%s, argv0=%s\r\n", id.c_str(), ExecuteJavaScriptMap[id].script.c_str(), ExecuteJavaScriptMap[id].argv[0].c_str(),ExecuteJavaScriptMap[id].argv[1].c_str(),ExecuteJavaScriptMap[id].argv[2].c_str(),ExecuteJavaScriptMap[id].argv[3].c_str() );
-        cJSON_Delete(root);
-        return;
-    }
-#endif
-
-    if( (strncmp( fileName, "hold", (strlen("hold")-1)) == 0) ) {
-        status = GLOBAL_mdot->readUserFile(fileName, ModbusMasterScratchBuf, MAX_FILE_SIZE);
-        if( status != true ) {
-            printf("(%d)read file failed, status=%d\r\n", __LINE__, status);
-            return;
-        }
-
-        cJSON * root = cJSON_Parse(ModbusMasterScratchBuf);
-        std::string id = cJSON_GetObjectItem(root,"id")->valuestring;
-        HoldingRegisterMap[id].node = atoi(cJSON_GetObjectItem(root,"node")->valuestring);
-        HoldingRegisterMap[id].sreg = atoi(cJSON_GetObjectItem(root,"sreg")->valuestring);
-        HoldingRegisterMap[id].nreg = atoi(cJSON_GetObjectItem(root,"nreg")->valuestring);
-        HoldingRegisterMap[id].order = atoi(cJSON_GetObjectItem(root,"order")->valuestring);
-        printf("Loaded holding register: id=%s, node=%d, sreg=%d, nreg=%d, order=%d\r\n", id.c_str(), HoldingRegisterMap[id].node, HoldingRegisterMap[id].sreg, HoldingRegisterMap[id].nreg, HoldingRegisterMap[id].order);
-        cJSON_Delete(root);
-        return;
-    }
-
-    regType = REG_TYPE_NONE;
-
-    if( (strncmp( fileName, "input", (strlen("input")-1)) == 0) ) {
-        regType = REG_TYPE_INPUT;
-    } else if( (strncmp( fileName, "output", (strlen("output")-1)) == 0) ) {
-        regType = REG_TYPE_OUTPUT;
-    } else if( (strncmp( fileName, "vinput", (strlen("vinput")-1)) == 0) ) {
-        regType = REG_TYPE_VINPUT;
-    } else if( (strncmp( fileName, "voutput", (strlen("voutput")-1)) == 0) ) {
-        regType = REG_TYPE_VOUTPUT;
-    }
-
-    if( regType != REG_TYPE_NONE ) {
-        status = GLOBAL_mdot->readUserFile(fileName, ModbusMasterScratchBuf, MAX_FILE_SIZE);
-        if( status != true ) {
-            printf("(%d)read file failed, status=%d", __LINE__, status);
-            return;
-        } else {
-//            printf("(%s:%d)loading File: %s\r\n", __func__, __LINE__, fileName );
-//            printf("%s:%d:Loaded:%s\r\n", __func__, __LINE__, ModbusMasterScratchBuf );
-        }
-        
-        cJSON * root = cJSON_Parse(ModbusMasterScratchBuf);
-        if( !cJSON_HasObjectItem(root,"id") )
-        {
-          printf("%s:%d: INVALID JSON STRING\r\n", __func__,__LINE__);
-          return;
-        }
-        std::string id = cJSON_GetObjectItem(root,"id")->valuestring;
-        ModbusRegisterMap[id].min = atof(cJSON_GetObjectItem(root,"min")->valuestring);
-        ModbusRegisterMap[id].max = atof(cJSON_GetObjectItem(root,"max")->valuestring);
-        ModbusRegisterMap[id].node = atoi(cJSON_GetObjectItem(root,"node")->valuestring);
-        ModbusRegisterMap[id].reg = atoi(cJSON_GetObjectItem(root,"reg")->valuestring);
-        ModbusRegisterMap[id].rtype = atoi(cJSON_GetObjectItem(root,"rtype")->valuestring);
-        ModbusRegisterMap[id].type = atoi(cJSON_GetObjectItem(root,"type")->valuestring);
-        ModbusRegisterMap[id].size = atoi(cJSON_GetObjectItem(root,"size")->valuestring);
-        ModbusRegisterMap[id].order = atoi(cJSON_GetObjectItem(root,"order")->valuestring);
-        ModbusRegisterMap[id].rfreq = atoi(cJSON_GetObjectItem(root,"rfreq")->valuestring);
-        ModbusRegisterMap[id].regType = regType;
-        ModbusRegisterMap[id].simulated = false;
-        RegisterValueMap[id].errflag = 0;
-        ModbusRegisterMap[id].cmd = cJSON_GetObjectItem(root,"cmd")->valuestring;
-        cJSON_Delete(root);;
-    }
-    return;
-}
-
-void UpdateSimulatedInput( std::map<std::string, ModbusRegister>::iterator &modMap )
-{
-    if ( SimulateInputMap[modMap->first].errflag ) {
-        RegisterValueMap[modMap->first].errflag = SimulateInputMap[modMap->first].errflag;
-    } else {
-        RegisterValueMap[modMap->first].errflag = 0;
-    }
-    //    printf("\r\nsimulating input=%s, min=%2.4f, max=%2.4f, start_value=%2.4f, up_step=%2.4f, down_step=%2.4f moving_up=%d\r\n",modMap->first.c_str(), SimulateInputMap[modMap->first].min, SimulateInputMap[modMap->first].max, SimulateInputMap[modMap->first].start_value, SimulateInputMap[modMap->first].up_step, SimulateInputMap[modMap->first].down_step, SimulateInputMap[modMap->first].moving_up);
-    if( (SimulateInputMap[modMap->first].min == 0) && (SimulateInputMap[modMap->first].max == 0) ) {
-        RegisterValueMap[modMap->first].float_value = SimulateInputMap[modMap->first].start_value;
-//    printf("simulating input=%s, value=%2.4f\r\n",modMap->first.c_str(), RegisterValueMap[modMap->first].float_value);
-    } else {
-        if( RegisterValueMap[modMap->first].float_value >= SimulateInputMap[modMap->first].max ) {
-            SimulateInputMap[modMap->first].moving_up = false;
-//            printf("simulating down input=%s, value=%2.4f - %2.4f\r\n",modMap->first.c_str(), RegisterValueMap[modMap->first].float_value, SimulateInputMap[modMap->first].down_step);
-            RegisterValueMap[modMap->first].float_value = RegisterValueMap[modMap->first].float_value - SimulateInputMap[modMap->first].down_step;
-        } else if( RegisterValueMap[modMap->first].float_value <= SimulateInputMap[modMap->first].min ) {
-            SimulateInputMap[modMap->first].moving_up = true;
-//            printf("simulating up input=%s, value=%2.4f + %2.4f\r\n",modMap->first.c_str(), RegisterValueMap[modMap->first].float_value, SimulateInputMap[modMap->first].up_step);
-            RegisterValueMap[modMap->first].float_value = RegisterValueMap[modMap->first].float_value + SimulateInputMap[modMap->first].up_step;
-        } else {
-            if( SimulateInputMap[modMap->first].moving_up == true ) {
-//                printf("continue simulate up input=%s, value=%2.4f + %2.4f\r\n",modMap->first.c_str(), RegisterValueMap[modMap->first].float_value, SimulateInputMap[modMap->first].up_step);
-                RegisterValueMap[modMap->first].float_value = RegisterValueMap[modMap->first].float_value + SimulateInputMap[modMap->first].up_step;
-            } else {
-//                printf("continue simulate down input=%s, value=%2.4f - %2.4f\r\n",modMap->first.c_str(), RegisterValueMap[modMap->first].float_value, SimulateInputMap[modMap->first].down_step);
-                RegisterValueMap[modMap->first].float_value = RegisterValueMap[modMap->first].float_value - SimulateInputMap[modMap->first].down_step;
-            }
-        }
-//        printf("simulating input=%s, value=%2.4f\r\n\r\n",modMap->first.c_str(), RegisterValueMap[modMap->first].float_value);
-    }
-}
-
-void UpdateVirtualRegister( std::map<std::string, ModbusRegister>::iterator &modMap )
-{
-}
-
-void ReadModbusRegister( std::map<std::string, ModbusRegister>::iterator &modMap )
-{
-    bool status;
-    unsigned char rd_buf[16];
-    memset( rd_buf, 0, 16 );
-//    printf("Processing Input: tag=%s, node=%d, reg=%d, size=%d, order=%d", modMap->first.c_str(), modMap->second.node, modMap->second.reg, modMap->second.size, modMap->second.order );
-    int ret = mod_read(modMap->second.node, modMap->second.rtype, modMap->second.reg, modMap->second.size, rd_buf);
-    switch( modMap->second.type ) {
-        case TYPE_32BIT_FLOAT:
-            float float_value;
-            if( ret != MOD_ERROR_NONE ) {
-                RegisterValueMap[modMap->first].errflag = ret;
-                break;
-            }
-            status = ReadModbus_32bit_float( &float_value, modMap->second.order, rd_buf );
-            if( status == true ) {
-                RegisterValueMap[modMap->first].float_value = float_value;
-                RegisterValueMap[modMap->first].errflag = 0;
-//                                printf("Modbus Tag:%s value=%2.4f", modMap->first.c_str(), float_value );
-            } else {
-                RegisterValueMap[modMap->first].errflag = 1000;
-//                                printf("Modbus Read Failed, tag=%s", modMap->first.c_str() );
-            }
-            break;
-        case TYPE_32BIT_INT:
-            int32_t int32_value;
-            if( ret != MOD_ERROR_NONE ) {
-                RegisterValueMap[modMap->first].errflag = ret;
-                break;
-            }
-            status = ReadModbus_32bit_int( &int32_value, modMap->second.order, rd_buf );
-            if( status == true ) {
-                RegisterValueMap[modMap->first].float_value = int32_value;
-                RegisterValueMap[modMap->first].errflag = 0;
-                printf("Modbus Tag:%s value=%2.4f", modMap->first.c_str(), RegisterValueMap[modMap->first].float_value );
-            } else {
-                RegisterValueMap[modMap->first].errflag = 1000;
-                printf("Modbus Read Failed, tag=%s", modMap->first.c_str() );
-            }
-            break;
-        case TYPE_32BIT_UINT:
-            break;
-        case TYPE_16BIT_INT:
-            break;
-        case TYPE_16BIT_UINT:
-            break;
-        default:
-            break;
-    }
-}
-
-void ExecuteRegisterCommand( std::string ioTag, std::string Command  )
-{
-    if( Command.size() == 0 ) {
-        return;
-    }
-//    printf("Executing Register Commnand: %s for %s\r\n",Command.c_str(), ioTag.c_str());
-    float operandValue = 0;
-    float ioTagValue = RegisterValueMap[ioTag].float_value;
-    if( VirtualCommandMap[Command].Operand.size() != 0 ) {
-        operandValue = RegisterValueMap[VirtualCommandMap[Command].Operand].float_value;
-    }
-    float constantValue = VirtualCommandMap[Command].Constant;
-
-    switch( VirtualCommandMap[Command].Operator.c_str()[0] ) {
-        case '=':
-            if( VirtualCommandMap[Command].Operand.size() == 0 ) {
-                RegisterValueMap[ioTag].float_value = constantValue;
-            } else {
-                RegisterValueMap[ioTag].float_value = operandValue;
-            }
-//            printf("Setting tag=%s, equal to (value=%2.4f)\r\n", ioTag.c_str(), ModbusRegisterMap[ioTag].float_value );
-            break;
-        case '*': {
-            if( VirtualCommandMap[Command].Operand.size() == 0 ) {
-                RegisterValueMap[ioTag].float_value = ioTagValue * constantValue;
-//                printf("Setting tag=%s, equal to (%2.4f*%2.4f) = %2.4f\r\n", ioTag.c_str(), ioTagValue, constantValue, ModbusRegisterMap[ioTag].float_value );
-            } else {
-                RegisterValueMap[ioTag].float_value = ioTagValue * operandValue;
-//                printf("Setting tag=%s, equal to (%2.4f*%2.4f) = %2.4f\r\n", ioTag.c_str(), ioTagValue, operandValue, ModbusRegisterMap[ioTag].float_value );
-            }
-            break;
-        }
-        case '/': {
-            if( VirtualCommandMap[Command].Operand.size() == 0 ) {
-                // constant operation
-                RegisterValueMap[ioTag].float_value = ioTagValue / constantValue;
-//                printf("Setting tag=%s, equal to (%2.4f/%2.4f) = %2.4f\r\n", ioTag.c_str(), ioTagValue, constantValue, ModbusRegisterMap[ioTag].float_value );
-            } else if( operandValue != 0 ) {
-                RegisterValueMap[ioTag].float_value = ioTagValue / operandValue;
-//                printf("Setting tag=%s, equal to (%2.4f/%2.4f) = %2.4f\r\n", ioTag.c_str(), ioTagValue, operandValue, ModbusRegisterMap[ioTag].float_value );
-            } else {
-//                printf("NOT DOING DIVIDE BY ZERO\r\n");
-            }
-            break;
-        }
-        case '+': {
-            if( VirtualCommandMap[Command].Operand.size() == 0 ) {
-                RegisterValueMap[ioTag].float_value = ioTagValue + constantValue;
-//                printf("Setting tag=%s, equal to (%2.4f+%2.4f) = %2.4f\r\n", ioTag.c_str(), ioTagValue, constantValue, ModbusRegisterMap[ioTag].float_value );
-            } else {
-                RegisterValueMap[ioTag].float_value = ioTagValue + operandValue;
-//                printf("Setting tag=%s, equal to (%2.4f+%2.4f) = %2.4f\r\n", ioTag.c_str(), ioTagValue, operandValue, ModbusRegisterMap[ioTag].float_value );
-            }
-            break;
-        }
-        case '-': {
-            if( VirtualCommandMap[Command].Operand.size() == 0 ) {
-                RegisterValueMap[ioTag].float_value = ioTagValue - constantValue;
-//                printf("Setting tag=%s, equal to (%2.4f-%2.4f) = %2.4f\r\n", ioTag.c_str(), ioTagValue, constantValue, ModbusRegisterMap[ioTag].float_value );
-            } else {
-                RegisterValueMap[ioTag].float_value = ioTagValue - operandValue;
-//                printf("Setting tag=%s, equal to (%2.4f-%2.4f) = %2.4f\r\n", ioTag.c_str(), ioTagValue, operandValue, ModbusRegisterMap[ioTag].float_value );
-            }
-            break;
-        }
-        default:
-            printf("OPERATION NOT SUPPORTED: %s\r\n", VirtualCommandMap[Command].Operator.c_str());
-            break;
-    }
-}
-
-void UpdateOutputRegister( std::map<std::string, ModbusRegister>::iterator &modMap )
-{
-    bool status;
-    int ret;
-
-    if( modMap->second.node == 0)  {
-        if( ModbusRegisterMap[modMap->first].reg == 1 ) {
-            dout1 = (bool)((int)RegisterValueMap[modMap->first].float_value&0x1);
-        } else {
-            dout2 = (bool)((int)RegisterValueMap[modMap->first].float_value&0x1);
-        }
-    } else {
-        unsigned char xmt_buf[10];
-
-        switch( ModbusRegisterMap[modMap->first].type ) {
-            case TYPE_32BIT_FLOAT: {
-                status = WriteModbus_32bit_float( RegisterValueMap[modMap->first].float_value, ModbusRegisterMap[modMap->first].order, xmt_buf );
-                if( status != true ) {
-                    printf("CMD: %s:%d: failed\r\n", __func__, __LINE__);
-                    return;
-                }
-                printf("%s:%d: 0x%x 0x%x 0x%x 0x%x\r\n", __func__,__LINE__, xmt_buf[0], xmt_buf[1], xmt_buf[2], xmt_buf[3]);
-                break;
-            }
-            case TYPE_32BIT_INT:
-            case TYPE_32BIT_UINT: {
-                status = WriteModbus_32bit_int( ((int32_t)RegisterValueMap[modMap->first].float_value&0x1), ModbusRegisterMap[modMap->first].order, xmt_buf );
-                if( status != true ) {
-                    printf("CMD: %s:%d: failed\r\n", __func__, __LINE__ );
-                    return;
-                }
-                break;
-            }
-            case TYPE_16BIT_INT:
-            case TYPE_16BIT_UINT:
-                status = WriteModbus_16bit_int( ((int16_t)RegisterValueMap[modMap->first].float_value&0x1), ModbusRegisterMap[modMap->first].order, xmt_buf );
-                if( status != true ) {
-                    printf("CMD: %s:%d: failed\r\n", __func__, __LINE__ );
-                    return;
-                }
-                printf("%s:%d: 0x%x 0x%x\r\n", __func__,__LINE__, xmt_buf[0], xmt_buf[1]);
-                break;
-            default:
-                printf("CMD: %s:%d: NOT IMPLEMENTED\r\n", __func__, __LINE__ );
-                return;
-        }
-        printf("%s:%d: 0x%x 0x%x 0x%x 0x%x\r\n", __func__,__LINE__, xmt_buf[0], xmt_buf[1], xmt_buf[2], xmt_buf[3]);
-        ret = mod_write(ModbusRegisterMap[modMap->first].node, ModbusRegisterMap[modMap->first].rtype, ModbusRegisterMap[modMap->first].reg, ModbusRegisterMap[modMap->first].size, xmt_buf);
-        if( ret != MOD_ERROR_NONE ) {
-            printf("CMD: %s:%d: failed, errflag=%d\r\n", __func__, __LINE__, ret );
-        } else {
-            printf("CMD: %s:%d: wrote to modbus func=%d reg=%d value=%2.4f, errflag=%d\r\n", __func__, __LINE__, ModbusRegisterMap[modMap->first].rtype, ModbusRegisterMap[modMap->first].reg, RegisterValueMap[modMap->first].float_value, ret );
-        }
-    }
-}
--- a/ICE-Application/src/ModbusMaster/ModbusMaster.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/******************************************************************************
- * 
- * File:                ModbusMaster.h
- * Desciption:          interface for the ICE Modbus Master
- *
- *****************************************************************************/
-#ifndef MODBUS_MASTER_H
-#define MODBUS_MASTER_H
-
-#include "global.h"
-   
-#ifdef __cplusplus
-#define EXTERNC extern "C"
-#else
-#define EXTERNC
-#endif
-
-EXTERNC void ModbusMaster(void const *args);
-
-#undef EXTERNC
-
-#define SIZE_MB_BUFFER 50
-#define MB_BAUD_RATE 19200
-
-typedef union mr_register_32_bit_float
-{
-    float f;
-    struct
-    {
-        uint16_t    lo;
-        uint16_t    hi;
-    }w;
-    struct
-    {
-        uint8_t    lo_lo;
-        uint8_t    lo_hi;
-        uint8_t    hi_lo;
-        uint8_t    hi_hi;
-    }b;
-} MR_REGISTER_32_BIT_FLOAT;
-
-typedef union mr_register_32_bit_int
-{
-    int32_t i;
-    struct
-    {
-        uint16_t    lo;
-        uint16_t    hi;
-    }w;
-    struct
-    {
-        uint8_t    lo_lo;
-        uint8_t    lo_hi;
-        uint8_t    hi_lo;
-        uint8_t    hi_hi;
-    }b;
-} MR_REGISTER_32BIT_INT;
-
-typedef union mr_register_32_bit_uint
-{
-    uint32_t i;
-    struct
-    {
-        uint16_t    lo;
-        uint16_t    hi;
-    }w;
-    struct
-    {
-        uint8_t    lo_lo;
-        uint8_t    lo_hi;
-        uint8_t    hi_lo;
-        uint8_t    hi_hi;
-    }b;
-} MR_REGISTER_32BIT_UINT;
-
-typedef union mr_register_16_bit_int
-{
-    int16_t w;
-    struct
-    {
-        uint8_t    lo;
-        uint8_t    hi;
-    }b;
-} MR_REGISTER_16BIT_INT;
-
-typedef union mr_register_16_bit_uint
-{
-    uint16_t w;
-    struct
-    {
-        uint8_t    lo;
-        uint8_t    hi;
-    }b;
-} MR_REGISTER_16BIT_UINT;
-
-#define TYPE_32BIT_FLOAT    0
-#define TYPE_32BIT_INT      1
-#define TYPE_32BIT_UINT     2
-#define TYPE_16BIT_INT      3
-#define TYPE_16BIT_UINT     4
-#define TYPE_MULTI_BYTE     5
-
-//Frame crc calucation
-uint16_t modbus_crc(uint8_t* buf, int len);
-void modbus_recv();
-void SendModbusCommand(uint8_t slave_address, uint16_t firstReg, uint16_t noRegs);
-void modbus_init( uint16_t baudRate );
-bool mbIntComplete();
-
-bool ReadModbus_32bit_float( float *float_value, int order, unsigned char *rd_buf );
-bool ReadModbus_32bit_int( int32_t *int32_value, int order, unsigned char *rd_buf );
-
-bool WriteModbus_32bit_float( float float_value, int order, unsigned char *xmt_buf );
-bool WriteModbus_32bit_int( int32_t int32_value, int order, unsigned char *xmt_buf );
-
-#endif
--- a/ICE-Application/src/ModbusMaster/ModbusMasterApi.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-#include "ModbusMasterApi.h"
-#include "ICELog.h"
-#include <stdio.h>
-
-bool ModbusMasterReadRegister( const std::string &io_tag, ModbusValue *value )
-{
-    if( !(RegisterValueMap.count(io_tag)) ) {
-        printf("%s:%d: Key=%s not in Modbus Map\r\n", __func__, __LINE__, io_tag.c_str() );
-        return false;
-    }
-
-    value->value = RegisterValueMap[io_tag].float_value;
-    value->errflag = RegisterValueMap[io_tag].errflag;
-    return true;
-}
-
-bool ModbusMasterWriteRegister( const std::string &io_tag, float value )
-{
-    if( !(RegisterValueMap.count(io_tag)) ) {
-        printf("%s:%d: Key=%s not in Modbus Map\r\n", __func__, __LINE__, io_tag.c_str() );
-        return false;
-    }
-
-    logDebug("\r[DEBUG] writing tag %s\n", io_tag.c_str());
-    RegisterValueMap[io_tag].float_value = value;
-    return true;
-}
-
-bool ScriptWriteRegister( const char *io_tag, double value )
-{
-    std::string ioString = io_tag;
-    if( !(RegisterValueMap.count(ioString)) ) {
-        printf("%s:%d: Key=%s not in Register Map\r\n", __func__, __LINE__, ioString.c_str() );
-        return false;
-    }
-
-    logDebug("\r[DEBUG] reading tag %s\n", io_tag);
-
-    RegisterValueMap[ioString].float_value = value;
-    return true;
-}
-
-double ScriptReadRegister( const char *io_tag )
-{
-    std::string ioString = io_tag;
-    if( !(RegisterValueMap.count(ioString)) ) {
-        printf("%s:%d: Key=%s not in Register Map\r\n", __func__, __LINE__, ioString.c_str() );
-        return -1;
-    }
-
-    return RegisterValueMap[ioString].float_value;
-}
\ No newline at end of file
--- a/ICE-Application/src/ModbusMaster/ModbusMasterApi.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-#ifndef MODBUSMASTERAPI_H
-#define MODBUSMASTERAPI_H
-
-#include <string>
-#include "global.h"
-
-struct ModbusValue {
-    float value;
-    uint32_t errflag;
-};
-
-bool ModbusMasterReadRegister( const std::string &io_tag, ModbusValue *value );
-bool ModbusMasterWriteRegister( const std::string &io_tag, float value );
-void ModbusMasterExecCmd( ThreadName_t replyTo, char *cmd );
-
-bool ScriptWriteRegister( const char *io_tag, double value );
-double ScriptReadRegister( const char *io_tag );
-
-#endif 
-
--- a/ICE-Application/src/OutputTask/ControlClass/Control.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/******************************************************************************
- *
- * File:                Control.cpp
- * Desciption:          ICE Control Class implementation for Output Thread
- *
- *****************************************************************************/
-#include <Control.h>
-
-//
-// method:          getMappedState
-// description:     convert the control state into its analytics code
-//                  the values here should map to the RELAY_STATUS_* codes
-//                  define in global.h
-//
-// @param           none
-// @return          relay-status code
-//
-int Control::getMappedState(void) const
-{
-    switch (controlType) {
-        case CONTROL_TIMER:
-        case CONTROL_SETPOINT:
-            // automatic control
-             return (state) ? RELAY_STATUS_AUTO_ON : RELAY_STATUS_AUTO_OFF;
-        case CONTROL_MANUAL:
-            // manual control
-            return (state) ? RELAY_STATUS_MANUAL_ON : RELAY_STATUS_MANUAL_OFF;
-        case CONTROL_FAILSAFE:
-            // failsafe control
-            return (state) ? RELAY_STATUS_FAILSAFE_ON : RELAY_STATUS_FAILSAFE_OFF;
-        case CONTROL_COMPOSITE:
-            // FIXME! This is a hack to get the correct mapped relay status
-            if ( input.compare(0, strlen("i_flowsw"), "i_flowsw") == 0 ) {
-                return ( state ) ? RELAY_STATUS_FLOW_FAILSAFE_ON : RELAY_STATUS_FLOW_FAILSAFE_OFF;
-            } else {
-                return ( state ) ? RELAY_STATUS_AUTO_ON : RELAY_STATUS_AUTO_OFF;
-            }
-        case CONTROL_PID:
-            // not implememented 
-        default:
-            return -1;
-    }
-}
--- a/ICE-Application/src/OutputTask/ControlClass/Control.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/******************************************************************************
- *
- * File:                Control.h
- * Desciption:          interface file for the ICE Output Task Control
- *
- *                      Controls are sorted by priority on the output
- *                      vector. The highest priority control manipulates
- *                      the output via Modbus writes.
- *
- *****************************************************************************/
-#ifndef CONTROL_H
-#define CONTROL_H
-
-#include <stdio.h>
-#include <string>
-
-#include "OutputTask.h"
-#include "global.h"
-
-
-//! Control - implements a control (for use with the Output thread)
-class Control
-{
-private:
-    std::string     id;             // control identifier
-    Control_t       controlType;    // control type
-    std::string     input;          // input
-    unsigned int    priority;       // control priority
-    ControlState    state;          // state (ON or OFF)
-
-public:
-    /// creates a control instance
-    Control(std::string id,
-            Control_t controlType,
-            std::string input,
-            unsigned int priority,
-            ControlState state) :
-        id(id),  controlType(controlType), input(input), priority(priority), state(state) {}
-    /// destroys a control instance 
-    ~Control() {
-        //printf("\r%s invoked\n", __func__);
-    }
-
-    /// display the pertinent data of a Control instance 
-    void display() {
-        printf("[%-24s | %3s | %u] -> ",
-               id.c_str(), (state == CONTROL_ON) ? "ON" : "OFF", priority);
-    }
-
-    std::string getId() const {
-        return id;
-    }
-
-    Control_t getControlType(void) const {
-        return controlType;
-    }
-
-    std::string getInput(void) const {
-        return input;
-    }
-
-    unsigned int getPriority() const {
-        return priority;
-    }
-
-    ControlState getState(void) const {
-        return state;
-    }
-
-    int getMappedState(void) const;
-
-    void setState(ControlState _state) {
-        state = _state;
-    }
-};
-
-#endif
\ No newline at end of file
--- a/ICE-Application/src/OutputTask/OutputTask.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,545 +0,0 @@
-/******************************************************************************
- *
- * File:                OutputTask.cpp
- * Desciption:          source for the ICE Output task
- *
- *****************************************************************************/
-#include <vector>
-#include <string>
-#include <algorithm>
-#include <assert.h>
-#include <time.h>
-#include "OutputTask.h"
-#include "global.h"
-#include "cJSON.h"
-#include "ModbusMasterApi.h"
-#include "LoggerApi.h"
-#include "Control.h"
-#include "rtc.h"
-#include "ICELog.h"
-
-//#include "../add-ons/MTSLog/MTSLog.h"
-
-
-// local functions
-static int  createOutput(const char *controlFile);
-static int  loadPersistentOutputs(void);
-static void writeOutputs(const std::string, const std::string);
-static int  enableOutputReqHandler(OutputControlMsg_t *msg);
-static int  disableOutputReqHandler(OutputControlMsg_t *msg);
-static int  unregisterControl(const char *id, unsigned int pri, const char *output);
-static void dumpEventRecord(EventReasonStruct_t &ev);
-
-//
-// The Output Map
-//
-// this is the main data structure used to distinguish which control has
-// priority of an output. the layout is as-follows:
-//
-// outputMap["o_rly1"]-> Control<"ManControl_rly1",       100, ON > <-- highest pri control manipulates relay
-//                       Control<"Flowswitch",            700  OFF> <-- lower pri  (queued up)
-//                       Control<"SetpointControl_rly1",  800, OFF> <-- lowest pri (queued up)
-//
-// outputMap["o_rly2"]-> Control<"Flowswitch",            700, OFF>
-//                    -> Control<"SetpointControl_rly2",  800, OFF>
-//
-// outputMap["o_rly3"]-> Control<"ManControl_rly3",       100, ON >
-//                       Control<"Flowswitch",            700, ON >
-//                       Control<"TimerControl_rly3",     750, ON >
-//
-//
-// The Control Vector (per relay) is always sorted by priority, whereas
-// the highest priority control (lower priority number) is at the front
-// (v.front()) of the list.
-//
-
-typedef std::map<std::string, std::vector<Control> > StringOutputVector_t;
-static StringOutputVector_t outputMap;
-
-// operator for sorting the outputs vectors
-bool operator<(const Control &control1, const Control &control2)
-{
-    return control1.getPriority() < control2.getPriority();
-}
-
-/*****************************************************************************
- * Function:            OutputTask
- * Description:         Main entry point for the Output Task
- *
- * @param               args -> not used
- * @return              none
- *****************************************************************************/
-void OutputTask(void const *args)
-{
-    int rc;
-    (void)args;
-
-    printf("\r%s has started...\n", __func__);
-
-#ifdef LOAD_PERSISTENT_CONFIGURATIONS
-    if ( loadPersistentOutputs() != 0 ) {
-        logError("Failed to load persistent outputs");
-    }
-#endif 
-
-    // signal the main thread to continue
-    osSignalSet(mainThreadId, sig_config_continue);
-
-    while (true) {
-        // wait for a message
-        osEvent evt = OutputMasterMailBox.get();
-        if (evt.status == osEventMail) {
-
-            OutputControlMsg_t *msg = (OutputControlMsg_t*) evt.value.p;
-
-            switch ( msg->action ) {
-                case ACTION_NEW:
-                    // read the file and and create an output entry
-                    rc = createOutput(msg->controlFile);
-                    if ( rc != 0 ) {
-                        logError("%s: failed to create output %s\n",
-                                 __func__, msg->controlFile);
-                    }
-                    break;
-                case ACTION_CONTROL_ON:
-                    logInfo("%s is requesting ON control of %s", msg->id, msg->output_tag);
-                    rc = enableOutputReqHandler(msg);
-                    if ( rc != 0 ) {
-                        logError("%s: failed to enable output for %s",
-                                 __func__, msg->id);
-                    }
-                    break;
-                case ACTION_CONTROL_OFF:
-                    logInfo("%s is requesting OFF control of %s", msg->id, msg->output_tag);
-                    rc = disableOutputReqHandler(msg);
-                    if ( rc != 0 ) {
-                        logError("%s: failed to disable output for %s",
-                                 __func__, msg->id);
-                    }
-                    break;
-                case ACTION_CONTROL_UNREGISTER:
-                    logInfo("%s is requesting its deletion from %s", msg->id, msg->output_tag);
-                    rc = unregisterControl(msg->id, msg->priority, msg->output_tag);
-                    if ( rc != 0 ) {
-                        logError("%s: failed to unregister control %s",
-                                 __func__, msg->id);
-                    }
-                    break;
-                default:
-                    logError("%s unknown action %u", __func__, msg->action);
-                    break;
-            }
-
-            // free the message
-            OutputMasterMailBox.free(msg);
-
-            // refresh the outputs
-            writeOutputs(msg->id, msg->output_tag);
-        }
-    }
-}
-
-/*****************************************************************************
- * Function:            publishEvent
- * Description:         publish an event to the logger
- *
- * @param               output  -> the output channel
- * @param               control -> the control, this can be null
- * @return              none
- *****************************************************************************/
-void publishEvent(std::string output, const Control *control)
-{
-
-    EventReasonStruct_t ev;
-    ModbusValue input_value;
-    ModbusValue output_value;
-    memset(&ev, 0, sizeof(ev));
-
-
-    // if there's no control, that means the only control that was on
-    // the relay stack has been destroyed, so we'll send a NO CONTROL
-    // event code.
-    if ( !control ) {
-        ev.eventReason = EVENT_REASON_NO_CONTROL;
-        ModbusMasterReadRegister(output, &output_value);
-        strncpy(ev.outputTag, output.c_str(), sizeof(ev.outputTag));
-        ev.outputValue = output_value.value;
-        dumpEventRecord(ev);
-        EventLoggerApi(ev);
-        return;
-    }
-
-    switch ( control->getControlType() ) {
-        case CONTROL_SETPOINT:
-        case CONTROL_COMPOSITE:
-            ev.eventReason = EVENT_REASON_AUTO;
-            strncpy(ev.inputTag, control->getInput().c_str(), sizeof(ev.inputTag));
-            strncpy(ev.outputTag, output.c_str(), sizeof(ev.outputTag));
-            ModbusMasterReadRegister(control->getInput(), &input_value);
-            ModbusMasterReadRegister(output, &output_value);
-            ev.inputValue = input_value.value;
-            ev.outputValue = output_value.value;
-            dumpEventRecord(ev);
-            EventLoggerApi(ev);
-            break;
-
-        case CONTROL_MANUAL:
-            ev.eventReason = EVENT_REASON_MANUAL;
-            strncpy(ev.outputTag, output.c_str(), sizeof(ev.outputTag));
-            ModbusMasterReadRegister(output, &output_value);
-            ev.outputValue = output_value.value;
-            dumpEventRecord(ev);
-            EventLoggerApi(ev);
-            break;
-
-        case CONTROL_TIMER:
-            ev.eventReason = EVENT_REASON_TIMER;
-            strncpy(ev.outputTag, output.c_str(), sizeof(ev.outputTag));
-            ModbusMasterReadRegister(output, &output_value);
-            ev.outputValue = output_value.value;
-            dumpEventRecord(ev);
-            EventLoggerApi(ev);
-            break;
-
-        case CONTROL_FAILSAFE:
-        case CONTROL_SENSOR_ERROR:
-            ev.eventReason = EVENT_REASON_FAILSAFE;
-            strncpy(ev.inputTag, control->getInput().c_str(), sizeof(ev.inputTag));
-            strncpy(ev.outputTag, output.c_str(), sizeof(ev.outputTag));
-            ModbusMasterReadRegister(control->getInput(), &input_value);
-            ModbusMasterReadRegister(output, &output_value);
-            ev.inputValue = input_value.value;
-            ev.outputValue = output_value.value;
-            dumpEventRecord(ev);
-            EventLoggerApi(ev);
-            break;
-
-        default:
-            logError("%s: unknown control type\n", __func__);
-            break;
-    }
-}
-
-/*****************************************************************************
- * Function:            writeOutputs
- * Description:         send a message to the modbus master of who's in control
- *
- *
- * @param[in]           id          -> control identifier
- * @param[in]           output_tag  -> the output to write
- * @return              none
- *****************************************************************************/
-static void writeOutputs(const std::string id, const std::string output_tag)
-{
-    (void) id;
-
-    if ( output_tag.empty() ) {
-        logError("%s: invalid output tag", __func__);
-        return;
-    }
-
-    StringOutputVector_t::const_iterator pos;
-
-    // find the output
-    pos = outputMap.find(output_tag);
-    if ( pos != outputMap.end() ) {
-        if ( pos->second.empty() ) {
-            // we found the output but nothing's controlling it...
-            ModbusMasterWriteRegister(pos->first, RELAY_STATUS_NOT_CONTROLLED);
-            publishEvent(pos->first, NULL);
-        } else {
-            // get the mapped state for the highest priority control
-            int mappedState = pos->second.begin()->getMappedState();
-
-            // read the register value for this output
-            ModbusValue value;
-            ModbusMasterReadRegister(pos->first, &value);
-
-            // a new higher priority control is manipulating the output,
-            // so send the new values to the modbus and publish an event
-            if ( value.value != mappedState ) {
-                ModbusMasterWriteRegister(pos->first, mappedState);
-                Control t = *(pos->second.begin());
-                publishEvent(pos->first, &t);
-            }
-        }
-        // TODO: This may be a virtual output, so we'll need to see if it
-        // exists in the vregmap
-    } else {
-        logError("%s failed to find the selected output %s",
-                 __func__, output_tag.c_str());
-    }
-}
-
-/*****************************************************************************
- * Function:            createOutput
- * Description:
- *
- * @param               outputFile -> name of output file
- * @return              none
- *****************************************************************************/
-static int createOutput(const char *outputFile)
-{
-    char dataBuf[MAX_FILE_SIZE];
-    bool status = GLOBAL_mdot->readUserFile(outputFile, (void *)dataBuf, sizeof(dataBuf));
-    if ( status != true ) {
-        logError("%s failed to read %s", __func__, outputFile);
-        return -1;
-    }
-
-    cJSON * root = cJSON_Parse(dataBuf);
-    if ( !cJSON_HasObjectItem(root, "id") ) {
-        logError("%s: error extracting expected tags", __func__);
-        cJSON_Delete(root);
-        return -1;
-    }
-
-    std::string id = cJSON_GetObjectItem(root,"id")->valuestring;
-    cJSON_Delete(root);
-
-    std::vector<Control> v;
-    outputMap[id] = v;
-
-    return 0;
-}
-
-/*****************************************************************************
- * Function:            enableOutputReqHandler
- * Description:         handle a request to enable an output
- *
- * @param[in]           msg -> the message request
- * @return              -1 on error
- *****************************************************************************/
-static int enableOutputReqHandler(OutputControlMsg_t *msg)
-{
-    // attempt to find the output in the map
-    StringOutputVector_t::iterator pos;
-
-    pos = outputMap.find(msg->output_tag);
-    if ( pos == outputMap.end() ) {
-        logError("%s: failed to find the designated output %s\n",
-                 __func__, msg->output_tag);
-        return -1;
-    }
-
-    if ( pos->second.empty() ) {
-        // this is a new request
-        std::string cid(msg->id);
-        std::string input(msg->input_tag);
-        Control c(cid, msg->controlType, input, msg->priority, CONTROL_ON);
-        pos->second.push_back(c);
-    } else {
-        // find this control in the list
-        std::vector<Control>::iterator v;
-        for ( v = pos->second.begin(); v != pos->second.end(); ++v ) {
-            if ( strcmp(v->getId().c_str(), msg->id) == 0 )  {
-                v->setState(CONTROL_ON);
-                break;
-            }
-        }
-        if ( v == pos->second.end() ) {
-            // this is a new request, so add it and sort the vector
-            std::string cid(msg->id);
-            std::string input(msg->input_tag);
-            Control c(cid, msg->controlType, input, msg->priority, CONTROL_ON);
-            pos->second.push_back(c);
-            std::sort(pos->second.begin(), pos->second.end());
-        }
-    }
-
-    return 0;
-}
-
-/*****************************************************************************
- * Function:            disableOutputReqHandler
- * Description:         handle a request to disable an output
- *
- * @param[in]           msg -> the message request
- * @return              none
- *****************************************************************************/
-static int disableOutputReqHandler(OutputControlMsg_t *msg)
-{
-    // attempt to find the output in the map
-    StringOutputVector_t::iterator pos;
-
-    pos = outputMap.find(msg->output_tag);
-    if ( pos == outputMap.end() ) {
-        logError("%s: failed to find the designated output %s\n",
-                 __func__, msg->output_tag);
-        return -1;
-    }
-
-    // if the control list is empty, push this control on the list
-    if ( pos->second.empty() ) {
-        std::string cid(msg->id);
-        std::string input(msg->input_tag);
-        Control c(cid, msg->controlType, input, msg->priority, CONTROL_OFF);
-        pos->second.push_back(c);
-    } else {
-        // find this control in the list
-        std::vector<Control>::iterator v;
-        for ( v = pos->second.begin(); v != pos->second.end(); ++v ) {
-            if ( strcmp(v->getId().c_str(), msg->id) == 0 )  {
-                v->setState(CONTROL_OFF);
-                break;
-            }
-        }
-
-        if ( v == pos->second.end() ) {
-            // this is a new request, so add it and sort the vector
-            std::string cid(msg->id);
-            std::string input(msg->input_tag);
-            Control c(cid, msg->controlType, input, msg->priority, CONTROL_OFF);
-            pos->second.push_back(c);
-            std::sort(pos->second.begin(), pos->second.end());
-        }
-    }
-
-    return 0;
-}
-
-/*****************************************************************************
- * Function:            unregisterControl
- * Description:
- *
- * @param               id     -> control identifier
- * @param               pri    -> priority
- * @param               output -> output (e.g. "o_rly05")
- *
- * @return              0 on success; -1 on error
- *****************************************************************************/
-static int unregisterControl(const char *id, unsigned int pri, const char *output)
-{
-    // attempt to find the output in the map
-    StringOutputVector_t::iterator pos;
-    bool found = false;
-
-    pos = outputMap.find(output);
-    if ( pos == outputMap.end() ) {
-        logError("%s: failed to find the designated output %s\n",
-                 __func__, output);
-        return -1;
-    }
-
-    // find the control in the list
-    std::vector<Control>::iterator v;
-    for ( v = pos->second.begin(); v != pos->second.end(); ++v) {
-        if ( strcmp(v->getId().c_str(), id) == 0 )  {
-            pos->second.erase(v);
-            found = true;
-            break;
-        }
-    }
-
-    if ( !found ) {
-        logError("%s: failed to find control %s in list", __func__, id);
-        return -1;
-    }
-    return 0;
-}
-
-/*****************************************************************************
- * Function:            loadPersistentOutputs
- * Description:         build the output map
- *
- * @param               none
- * @return              0 on success; -1 of failure
- *****************************************************************************/
-static int loadPersistentOutputs(void)
-{
-    bool status;
-    cJSON *root;
-    int rc = 0;
-
-    printf("\rLoading persistent outputs:\n");
-
-    std::vector<std::string> file_list = GLOBAL_mdot->listUserFiles();
-
-    for (std::vector<std::string>::const_iterator i = file_list.begin(); i != file_list.end(); ++i) {
-        // load in all of the output files
-        if( strncmp( i->c_str(), OUTPUT_STR, strlen(OUTPUT_STR)) == 0 ||
-                strncmp( i->c_str(), VOUTPUT_STR, strlen(VOUTPUT_STR)) == 0) {
-            char scratchBuf[MAX_FILE_SIZE];
-
-            status = GLOBAL_mdot->readUserFile(i->c_str(), scratchBuf, MAX_FILE_SIZE);
-            if( status != true ) {
-                logError("%s: failed to read %s", __func__, i->c_str());
-                rc = -1;
-            } else {
-                logInfo("%s: successfully read %s", __func__, i->c_str());
-            }
-
-            root = cJSON_Parse(scratchBuf);
-            std::string id = cJSON_GetObjectItem(root,"id")->valuestring;
-            printf("\r   output %s loaded\n", i->c_str());
-            cJSON_Delete(root);
-
-            // emplace the empty control vector into the output map
-            std::vector<Control> v;
-            outputMap[id] = v;
-        }
-    }
-    return rc;
-}
-
-/*****************************************************************************
- * Function:            dumpEventRecord
- * Description:         display the contents of an event record
- *
- * @param[in]           ev -> the event structure
- * @return              none
- *****************************************************************************/
-static void dumpEventRecord(EventReasonStruct_t &ev)
-{
-    const char *mapper[] = { "auto",
-                             "manual",
-                             "timer",
-                             "flow",
-                             "failsafe",
-                             "no control"
-                           };
-
-    time_t rawtime;
-    time(&rawtime);
-
-    int iyr=0, imo=0, idy=0, ihr=0, imn=0, isc=0;
-#undef TODO_ICE
-#if 0 
-    rtc_get_time(&iyr, &imo, &idy, &ihr, &imn, &isc);
-#endif 
-
-    printf("\rEVENT RECORD (%04d-%02d-%02d %02d:%02d:%02d)\r\n",
-           iyr, imo, idy, ihr, imn, isc);
-    printf("\rev.eventReason = %d (%s)\n",    ev.eventReason, mapper[ev.eventReason]);
-    printf("\rev.inputTag    = %s\n",    ev.inputTag[0]  ? ev.inputTag  : "empty");
-    printf("\rev.outputTag   = %s\n",    ev.outputTag[0] ? ev.outputTag : "empty");
-    printf("\rev.inputValue  = %.02f\n", ev.inputValue);
-    printf("\rev.outputValue = %.02f (%s)\n", ev.outputValue,
-           ((unsigned int)ev.outputValue & 1 == 1) ? "on" : "off");
-}
-
-/*****************************************************************************
- * Function:            DisplayOutputs
- * Description:         Display a list of outputs and their controls
- *
- * @param               none
- * @return              none
- *****************************************************************************/
-void DisplayOutputs(void)
-{
-    StringOutputVector_t::iterator pos;
-
-    for ( pos = outputMap.begin(); pos != outputMap.end(); ++pos ) {
-        if ( pos->second.empty() ) {
-            printf("\r  [%s]-> [no controls] \n", pos->first.c_str());
-        } else {
-            printf("\r  [%s]-> ", pos->first.c_str());
-            std::vector<Control>::iterator i;
-            for ( i = pos->second.begin(); i != pos->second.end(); ++i ) {
-                i->display();
-            }
-            printf("\n");
-        }
-    }
-    printf("\r\n");
-}
--- a/ICE-Application/src/OutputTask/OutputTask.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-#ifndef OUTPUTTASK_H
-#define OUTPUTTASK_H
-
-#ifdef __cplusplus
-#define EXTERNC extern "C"
-#else
-#define EXTERNC
-#endif
-
-// thread prototype
-EXTERNC void OutputTask(void const *args);
-
-#undef EXTERNC
-
-// FIXME: think about analog! 
-typedef enum {
-    CONTROL_OFF = 0,
-    CONTROL_ON  = 1
-} ControlState;
-
-// public functions 
-void DisplayOutputs(void);
-
-#define RELAY_STATUS_AUTO_ON             129        // automatic control ON
-#define RELAY_STATUS_AUTO_OFF            128        // automatic control OFF
-#define RELAY_STATUS_MANUAL_ON           65         // manual control ON      
-#define RELAY_STATUS_MANUAL_OFF          64         // manual control OFF
-#define RELAY_STATUS_FAILSAFE_ON         33         // general failsafe duty ON
-#define RELAY_STATUS_FAILSAFE_OFF        32         // general failsafe duty OFF
-#define RELAY_STATUS_FORCED_OFF          16         // ??
-#define RELAY_STATUS_FLOW_FAILSAFE_ON    9          // flow failsafe control ON
-#define RELAY_STATUS_FLOW_FAILSAFE_OFF   8          // flaw failsafe control OFF 
-#define RELAY_STATUS_NOT_CONTROLLED      0          // no controls      
-
-#define OUTPUT_STR  "output_"
-#define VOUTPUT_STR "voutput_"
-#endif
--- a/ICE-Application/src/Utilities/timerUtils.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1872 +0,0 @@
-/************************************************************************
- *                                                                      *
- *       Copyright (c) 2012 Nalco Company. All Rights Reserved.         *
- *                                                                      *
- ************************************************************************/
-
-/*
- * Scheduling Utilities and testing support functions
- */
- 
-#include "timerUtils.h"
-#include <time.h>
-#include "rtos.h"
- 
- /************************************************************************
- *                                                                      *
- *       Copyright (c) 2012 Nalco Company. All Rights Reserved.         *
- *                                                                      *
- ************************************************************************/
-
-// local implementation of localtime_r, not supported on IAR
-Mutex localtimeMutex;
-
-/* index with month */
-static int dayTable[2][13] =
-{/*    J  F   M    A   M   J   J   A   S   O   N   D */
-{  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
-{  0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
-
-
-int UTgetDaysInMonth(int year, int month)
-{
-    int leap;
-    if ( year < 2000 || month < 1 || month > 12 )
-    {
-        return 0;
-    }
-    leap = (( year % 4 == 0 ) && ( year % 100 != 0 ))  || ( year % 400 == 0 );
-    
-    return ( dayTable[leap][month] );
-}
-
-
-bool   timer_debug_print       = false;
-bool   timer_debug_kludge_data = false;
-unsigned long     time_data_kludge_chkpt_time = 0;
-unsigned long     time_data_kludge_boot_time  = 0;
-
-unsigned char     Util_computeDownMask( int begin_wday, int end_wday );
-bool   TSCutilEveryWeekMissed( CNTL_SCHED_STRUCT *pElem, unsigned long chkpt_local_sec, unsigned long chkpt_spm, int chkpt_wday, unsigned long boot_local_sec, unsigned long boot_spm, int boot_wday, unsigned long sched_start, unsigned long  sched_end, TSC_SCHED_MISS_REASON *pReason, int *pMisses, int *pStartToEndDiff );
-bool   TSCutilEveryWeekMissedV2( CNTL_SCHED_STRUCT *pElem, unsigned long chkpt_local_sec, unsigned long boot_local_sec, TSC_SCHED_MISS_REASON *pReason, int *pMisses, int *pStartToEndDiff );
-void        Util_computeBeginEndDownForDay( int chkpt_wday, unsigned long chkpt_spm, int boot_wday, unsigned long boot_spm, int day, unsigned long *down_begin, unsigned long *down_end);
-
-static  DAY_SCHEDULE dayMask[] = {DAY_SCHEDULE_SUNDAY_MASK, DAY_SCHEDULE_MONDAY_MASK, DAY_SCHEDULE_TUESDAY_MASK, DAY_SCHEDULE_WEDNESDAY_MASK,
-          DAY_SCHEDULE_THURSDAY_MASK, DAY_SCHEDULE_FRIDAY_MASK, DAY_SCHEDULE_SATURDAY_MASK };
-
-
-/*
- * return the number of days in the schedule
- */
-int Util_numDaysInSchedule( unsigned char dailySchedule )
-{
-    int d, numOfDaysInSchedule;
-    
-    /* only get here if starting day was NOT SUNDAY */
-    for ( d = SUNDAY, numOfDaysInSchedule = 0; d <= SATURDAY; ++d )
-    {
-        if ( dailySchedule & dayMask[d]  )
-        {
-            ++numOfDaysInSchedule;
-        }
-    }
-    
-    return numOfDaysInSchedule;
-}
-
-/*
- * Util_findAday
- * 
- * starting with (and including) the given day return the first day that is scheduled in the daily schedule
- * the starting day is given as day of week which is the number of days past sunday,
- * sunday is 0 and saturday is 6
- * 
- * the dailySchedule is based upon the DAY_SCHEDULE domain
- * DAY_SCHEDULE_SUNDAY_MASK      = 0x01
- * DAY_SCHEDULE_MONDAY_MASK      = 0x02
- * DAY_SCHEDULE_TUESDAY_MASK     = 0x04
- * DAY_SCHEDULE_WEDNESDAY_MASK   = 0x08
- * DAY_SCHEDULE_THURSDAY_MASK    = 0x10
- * DAY_SCHEDULE_FRIDAY_MASK      = 0x20
- * DAY_SCHEDULE_SATURDAY_MASK    = 0x40 
- */
-int Util_findAday( int startingDay, unsigned char dailySchedule )
-{
-    int             d;
-    
-    if ( dailySchedule == 0 )
-    {
-        //printf("dailySchedule is 0!\n");
-        return 0;
-    }
-    
-    for ( d = startingDay; d <= SATURDAY; ++d )
-    {
-        if ( dailySchedule & dayMask[d] )
-        {
-            return d;
-        }
-    }
-    
-    /* only get here if starting day was NOT SUNDAY */
-    for ( d = SUNDAY; d < startingDay; ++d )
-    {
-        if ( dailySchedule & dayMask[d]  )
-        {
-            return d;
-        }
-    }
-    
-    /* should NOT get here */
-    printf("Didn't find a day in the schedule(0x%x)", dailySchedule);
-    return 0;
-}
-#ifdef COMMENTOUT
-int Util_findAday( int startingDay, unsigned char dailySchedule )
-{
-    int d;
-    if ( dailySchedule == 0 )
-    {
-        //printf("dailySchedule is 0!\n");
-        return 0;
-    }
-    
-    for ( d = startingDay; d <= SATURDAY; ++d )
-    {
-        if ( dailySchedule & (0x1 << d) )
-        {
-            return d;
-        }
-    }
-    
-    /* only get here if starting day was NOT SUNDAY */
-    for ( d = SUNDAY; d < startingDay; ++d )
-    {
-        if ( dailySchedule & (0x1 << d) )
-        {
-            return d;
-        }
-    }
-    
-    /* should NOT get here */
-    //printf("Didn't find a day in the schedule!\n");
-    return 0;
-}
-#endif
-
-
-/*
- * TSCutilCmpStartTimes( pA, pB )
- *  
- *  < 0     schedule A preceeds schedule B
- *  == 0    schedules A and B overlap in some way
- *  > 0     schedule A follows schedule B
- *  
- *  Converting the start and end times to seconds past midnight greatly simplifies
- *  the time comparisons
- *  
- */
-int     TSCutilCmpStartTimes( TSC_SCHED_ELEM *pA, TSC_SCHED_ELEM *pB )
-{
-    int aStart, aEnd, bStart, bEnd; /* seconds past midnight of the starting and ending times */
-    
-    aStart  = pA->schedule.startTime.hour * SECONDS_PER_HOUR;
-    aStart  += pA->schedule.startTime.minute * SECONDS_PER_MINUTE;
-    aStart  += pA->schedule.startTime.second;
-    
-    aEnd    = pA->schedule.endTime.hour * SECONDS_PER_HOUR;
-    aEnd    += pA->schedule.endTime.minute * SECONDS_PER_MINUTE;
-    aEnd    += pA->schedule.endTime.second;
-    
-    bStart  = pB->schedule.startTime.hour * SECONDS_PER_HOUR;
-    bStart  += pB->schedule.startTime.minute * SECONDS_PER_MINUTE;
-    bStart  += pB->schedule.startTime.second;
-    
-    bEnd    = pB->schedule.endTime.hour * SECONDS_PER_HOUR;
-    bEnd    += pB->schedule.endTime.minute * SECONDS_PER_MINUTE;
-    bEnd    += pB->schedule.endTime.second;
-    
-#ifdef COMMENTOUT
-    printf("\t%s: StartTimes aHr(%ld),aMin(%ld), aSec(%ld), bHr(%ld), bMin(%ld), bSec(%ld)\n", __FUNCTION__,
-            pA->schedule.startTime.hour, pA->schedule.startTime.minute, pA->schedule.startTime.second,
-            pB->schedule.startTime.hour, pB->schedule.startTime.minute, pB->schedule.startTime.second);
-    
-    printf("\t%s: EndTimes aHr(%ld),aMin(%ld), aSec(%ld), bHr(%ld), bMin(%ld), bSec(%ld)\n",__FUNCTION__,
-            pA->schedule.endTime.hour, pA->schedule.endTime.minute, pA->schedule.endTime.second,
-            pB->schedule.endTime.hour, pB->schedule.endTime.minute, pB->schedule.endTime.second);
-    
-    printf("\t%s: aStart(%d), aEnd(%d)\n", __FUNCTION__,aStart, aEnd);
-    printf("\t%s: bStart(%d), bEnd(%d)\n", __FUNCTION__,bStart, bEnd);
-#endif  
-    
-    if ( aStart > bStart )
-    {
-        if ( aStart > bEnd )
-        {
-            return 1;
-        }
-        return 0;
-    }
-    
-    if ( aStart < bStart )
-    {
-        if ( aEnd < bStart )
-        {
-            return -1;
-        }
-        
-        return 0;
-    }
-    
-    return 0;
-
-}
-/*
- * Util_getMonthWeek
- * 
- *  return the month week for the given date
- *  
- *  THE GIVEN DATE MUST BE >= CURRENT DATE
- *  
- *  The algorithm requires the knowning the weekDay for the given monthDay.
- * 
- */
-
-
-int Util_getMonthWeek( TSC_SCHED_ELEM *pSchedElem, CNTL_DATE_STRUCT *pDate )
-{
-    time_t      calTime;
-    struct tm   brokenDownTime;
-    int         dayOfWeek, dom, wom;
-    
-    calTime = pSchedElem->calTime;
-    brokenDownTime = pSchedElem->requestTime;
-    
-    /* verify the given date assertion */
-    if ( brokenDownTime.tm_year > pDate->year || 
-         ( brokenDownTime.tm_year == pDate->year && brokenDownTime.tm_mon > pDate->month) ||
-         (brokenDownTime.tm_year == pDate->year && brokenDownTime.tm_mon == pDate->month && brokenDownTime.tm_mday < pDate->day)
-         )
-    {
-        //printf("%s: Given date (%2.2ld/%2.2ld/%2.2ld) is in the past\n", __FUNCTION__, pDate->month, pDate->day, pDate->year);
-        return 0;
-    }
-
-    /* get the day of week for the first day of the month */
-    dayOfWeek = Util_getDoWThisMonth( pSchedElem, 1 );
-    
-    /* the day of the month that was the last day in the first week */
-    for ( dom = 7 - dayOfWeek, wom = 1; wom < 5; dom += 7, ++wom )
-    {
-        if ( pDate->day <= dom )
-        {
-            return wom;
-        }
-    }
-
-    return ( WEEKLY_CHOICE_LAST_WEEK );
-}
-
-
-/*
- * Util_getDoWThisMonth
- * 
- * Get the day of week for a given day of the month in the current month
- * 
- * This function assumes the given day of month is in the current month
- * the day of month computation is slightly different depending upon if the given
- * day is before or after the current day of the month
- */
-int Util_getDoWThisMonth( TSC_SCHED_ELEM *pSchedElem, int dom )
-{
-    time_t      calTime;
-    struct tm   brokenDownTime;
-    int         dayOfWeek, dayDiff;
-    
-    calTime = pSchedElem->calTime;
-    brokenDownTime = pSchedElem->requestTime;
-    
-    if ( dom < 1 || dom > 31 )
-    {
-        return 0;
-    }
-    
-    if ( dom == brokenDownTime.tm_mday )
-    {
-        return brokenDownTime.tm_wday;
-    }
-    
-    /* compute day of month for a day following today */
-    if ( dom > brokenDownTime.tm_mday )
-    {
-        dayDiff = dom - brokenDownTime.tm_mday;
-        dayOfWeek = (brokenDownTime.tm_wday + dayDiff) % 7;
-        
-        return dayOfWeek;
-    }
-    
-    /* compute day of month for a day preceeding the current day */
-    
-    dayDiff = ( brokenDownTime.tm_mday - dom ) % 7;
-    dayOfWeek = ((7 - dayDiff) + brokenDownTime.tm_wday) % 7;
-    
-    return dayOfWeek;
-}
-
-/*
- * int Util_dateTimeDiff( CNTL_SCHED_STRUCT *pDateTime1, CNTL_SCHED_STRUCT *pDateTime2, long *pDiffInSeconds )
- * 
- * Return
- *      OK and the difference in seconds of dateTime1, dateTime2 in pDiffInSeconds
- *      ERROR if any paramter pointer is NULL or dateTime1 > dateTime2
- * 
- */
-int Util_dateTimeDiff( CNTL_SCHED_STRUCT *pDateTime1, CNTL_SCHED_STRUCT *pDateTime2, unsigned long *pDiffInSeconds )
-{
-    DMSTRING128 errorString;
-    int      chk = ERROR;
-    time_t      calTime;
-    struct  tm  brokenDownTime;
-    int         days, hours, minutes, seconds, totalSeconds, m, daysInMonth;
-    
-    do
-    {   
-        if ( pDateTime1 == NULL || pDateTime2 == NULL || pDiffInSeconds == NULL )
-        {
-            //printf("bad params");
-            snprintf(errorString, sizeof(DMSTRING128),"%s: NULL parameter, pDateTime1(%p), pDateTime2(%p) pDiffInSeconds(%p)",
-                    __FUNCTION__, pDateTime1, pDateTime2, pDiffInSeconds );
-            break;
-        }
-
-        /*
-         * For testing purposes
-         */
-#ifdef COMMENTOUT
-        printf("    Date1(%2.2ld/%2.2ld/%4.4ld),Time1(%2.2ld:%2.2ld)\n",
-                pDateTime1->startDate.month, pDateTime1->startDate.day, pDateTime1->startDate.year,
-                pDateTime1->startTime.hour, pDateTime1->startTime.minute);
-        
-        printf("    Date2(%2.2ld/%2.2ld/%4.4ld),Time2(%2.2ld:%2.2ld)\n\n",
-                        pDateTime2->startDate.month, pDateTime2->startDate.day, pDateTime2->startDate.year,
-                        pDateTime2->startTime.hour, pDateTime2->startTime.minute);
-#endif
-        /* verify dateTime1 <= dateTime2 */
-        
-        if ( pDateTime1->startDate.year > pDateTime2->startDate.year )
-        {
-            //printf("bad year");
-            snprintf(errorString, sizeof(DMSTRING128),"%s: dateTime1 year(%ld) > dateTime2 year(%ld)",
-                    __FUNCTION__, pDateTime1->startDate.year, pDateTime2->startDate.year );
-            break;
-        }
-        if ( (pDateTime1->startDate.year + 1) < pDateTime2->startDate.year )
-        {
-            //printf("bad year");
-            snprintf(errorString, sizeof(DMSTRING128),"%s: dateTime2 year(%ld) >= dateTime1 + 1 (%ld)",
-                    __FUNCTION__, pDateTime2->startDate.year, pDateTime1->startDate.year );
-            break;
-        }
-        if ( pDateTime1->startDate.year == pDateTime2->startDate.year )
-        {
-            if ( pDateTime1->startDate.month > pDateTime2->startDate.month )
-            {   
-                //printf("bad month");
-                snprintf(errorString, sizeof(DMSTRING128),"%s: dateTime1 month(%ld) > dateTime2 month(%ld)",
-                        __FUNCTION__, pDateTime1->startDate.month, pDateTime2->startDate.month );
-                break;
-            }
-            if ( pDateTime1->startDate.month == pDateTime2->startDate.month )
-            {
-                if ( pDateTime1->startDate.day > pDateTime2->startDate.day )
-                {
-                    //printf("bad day");
-                    snprintf(errorString, sizeof(DMSTRING128),"%s: dateTime1 day(%ld) > dateTime2 day(%ld)",
-                            __FUNCTION__, pDateTime1->startDate.day, pDateTime2->startDate.day );
-                    break;
-                }
-                if ( pDateTime1->startDate.day == pDateTime2->startDate.day )
-                {
-                    if ( pDateTime1->startTime.hour > pDateTime2->startTime.hour )
-                    {
-                        //printf("bad hour");
-                        snprintf(errorString, sizeof(DMSTRING128),"%s: dateTime1 hour(%ld) > dateTime2 hour(%ld)",
-                                __FUNCTION__, pDateTime1->startTime.hour, pDateTime2->startTime.hour );
-                        break;
-                    }
-                    if ( pDateTime1->startTime.hour == pDateTime2->startTime.hour )
-                    {
-                        if ( pDateTime1->startTime.minute > pDateTime2->startTime.minute )
-                        {
-                            //printf("bad minute");
-                            snprintf(errorString, sizeof(DMSTRING128),"%s: dateTime1 minute(%ld) > dateTime2 minute(%ld)",
-                                    __FUNCTION__, pDateTime1->startTime.minute, pDateTime2->startTime.minute );
-                            break;
-                        }
-                    }
-                }   
-            }
-        }
-        
-        /* all the checks pass so */
-        chk = OK;
-        break;
-        
-    } while ( 0 );
-    
-    if ( chk == ERROR )
-    {
-        printf("%s", errorString );
-        return chk;
-    }
-    
-    /*
-     * all the checks pass so on to computing the difference
-     * only the seconds past the hour are used from brokenDownTime, all other time
-     * attributes come from the two parameters. The seconds is a bit of a fudge
-     * implying DateTime1 is the current date/Time 
-     */
-    calTime = time( NULL );
-    localtime_r( &calTime, &brokenDownTime );   /* need to know the seconds past the minute */
-    
-    days = hours = minutes = seconds = totalSeconds = 0;
-    
-    if ( pDateTime1->startDate.year < pDateTime2->startDate.year )
-    {
-        /* accumulate days */
-        if ( pDateTime1->startDate.month < 12 )
-        {
-            for ( m = pDateTime1->startDate.month + 1; m <= 12; ++m )
-            {
-                days += UTgetDaysInMonth(pDateTime1->startDate.year, m);
-            }
-        }
-        /* days to end of month  */
-        daysInMonth = UTgetDaysInMonth(pDateTime1->startDate.year, pDateTime1->startDate.month);
-        if ( pDateTime1->startDate.day < daysInMonth )
-        {
-            days += daysInMonth - pDateTime1->startDate.day ;
-        }
-        
-        /* days in time2 year */
-        for ( m = 1; m < pDateTime2->startDate.month; ++m )
-        {
-            days += UTgetDaysInMonth(pDateTime2->startDate.year, m);
-        }
-        
-        /* days up to start day in time2 year */
-        days += pDateTime2->startDate.day - 1;
-    
-        /* accumulate the hours and minutes */
-        hours = HOURS_PER_DAY - (pDateTime1->startTime.hour + 1);
-        minutes = MINUTES_PER_HOUR - (pDateTime1->startTime.minute + 1);
-        
-        hours += pDateTime2->startTime.hour;
-        minutes += pDateTime2->startTime.minute;
-        
-        totalSeconds = days * SECONDS_PER_DAY;
-        totalSeconds += hours * SECONDS_PER_HOUR;
-        totalSeconds += minutes * SECONDS_PER_MINUTE;
-        totalSeconds += SECONDS_PER_MINUTE - brokenDownTime.tm_sec;
-        *pDiffInSeconds = totalSeconds;
-        
-        return OK;
-    }
-    
-    /*
-     * Same Year different months
-     */
-    if ( pDateTime1->startDate.month < pDateTime2->startDate.month )
-    {
-        for ( m = pDateTime1->startDate.month + 1; m < pDateTime2->startDate.month; ++m )
-        {
-            days += UTgetDaysInMonth(pDateTime1->startDate.year, m);
-        }
-        
-        daysInMonth = UTgetDaysInMonth(pDateTime1->startDate.year, pDateTime1->startDate.month);
-        if ( pDateTime1->startDate.day < daysInMonth )
-        {
-            days += daysInMonth - pDateTime1->startDate.day ;
-        }
-        days += pDateTime2->startDate.day - 1;
-        
-        /* accumulate the hours and minutes */
-        hours = HOURS_PER_DAY - (pDateTime1->startTime.hour + 1);
-        minutes = MINUTES_PER_HOUR - (pDateTime1->startTime.minute + 1);
-        
-        hours += pDateTime2->startTime.hour;
-        minutes += pDateTime2->startTime.minute;
-        
-        totalSeconds = days * SECONDS_PER_DAY;
-        totalSeconds += hours * SECONDS_PER_HOUR;
-        totalSeconds += minutes * SECONDS_PER_MINUTE;
-        totalSeconds += SECONDS_PER_MINUTE - brokenDownTime.tm_sec;
-        *pDiffInSeconds = totalSeconds;
-
-        return OK;
-    }
-    
-    /*
-     * Same Year, month
-     */
-    if ( pDateTime1->startDate.day < pDateTime2->startDate.day )
-    {
-        days = pDateTime2->startDate.day - (pDateTime1->startDate.day + 1);
-        
-        /* accumulate the hours and minutes */
-        hours = HOURS_PER_DAY - (pDateTime1->startTime.hour + 1);
-        minutes = MINUTES_PER_HOUR - (pDateTime1->startTime.minute + 1);
-        
-        hours += pDateTime2->startTime.hour;
-        minutes += pDateTime2->startTime.minute;
-        
-        totalSeconds = days * SECONDS_PER_DAY;
-        totalSeconds += hours * SECONDS_PER_HOUR;
-        totalSeconds += minutes * SECONDS_PER_MINUTE;
-        totalSeconds += SECONDS_PER_MINUTE - brokenDownTime.tm_sec;
-        *pDiffInSeconds = totalSeconds;
-
-        return OK;
-    }
-    
-    /*
-     * Same Year, month, day
-     */
-    if ( pDateTime1->startTime.hour < pDateTime2->startTime.hour )
-    {
-        hours = pDateTime2->startTime.hour - (pDateTime1->startTime.hour + 1);
-        minutes = MINUTES_PER_HOUR - (pDateTime1->startTime.minute + 1);
-        
-        minutes += pDateTime2->startTime.minute;
-        
-        totalSeconds += hours * SECONDS_PER_HOUR;
-        totalSeconds += minutes * SECONDS_PER_MINUTE;
-        totalSeconds += SECONDS_PER_MINUTE - brokenDownTime.tm_sec;
-        *pDiffInSeconds = totalSeconds;
-
-        return OK;
-        
-    }
-    
-    /*
-     * Same Year, month, day, hour, given the dateTime check above the time1 minute < time2 minute
-     */
-    
-    minutes = pDateTime2->startTime.minute - (pDateTime1->startTime.minute + 1);
-
-    totalSeconds += minutes * SECONDS_PER_MINUTE;
-    totalSeconds += SECONDS_PER_MINUTE - brokenDownTime.tm_sec;
-    *pDiffInSeconds = totalSeconds;
-
-    return OK;
-}
-
-
-
-/*
- * TSCutilComputeStartDate
- * 
- * Depending upon the specified schedule:
- * start time, daily schedule, weekly schedule, the start date may move from today.
- * 
- * Scheduling falls into 3 buckets
- *      One Shot
- *      Every Week or Every Other Week
- *      Specific Week of the Month
- */
-void TSCutilComputeStartDate( TSC_SCHED_ELEM *pSchedElem )
-{   
-    switch ( pSchedElem->schedule.weeklySchedule )
-    {   
-    case WEEKLY_CHOICE_FIRST_WEEK:
-    case WEEKLY_CHOICE_SECOND_WEEK:
-    case WEEKLY_CHOICE_THIRD_WEEK:
-    case WEEKLY_CHOICE_FOURTH_WEEK:
-    case WEEKLY_CHOICE_LAST_WEEK:
-        TSCutilScheduleOneWeekPerMonth( pSchedElem );
-        break;
-        
-    case WEEKLY_CHOICE_EVERY_WEEK:
-    case WEEKLY_CHOICE_EVERYOTHER_WEEK:
-        TSCutilScheduleWithInWeek( pSchedElem );
-        break;
-
-    default:
-        printf("%s: Unknown Weekly Schedule (%d) Specified\n", __FUNCTION__, pSchedElem->schedule.weeklySchedule);
-        break;
-    }
-}
-
-
-/*
- * TSCutilScheduleWithInWeek
- * 
- * update the CNTL_SCHED_STRUCT with the start date
- * 
- * Based upon the selected day and start time the start day may move
- * 
- * return the seconds to start date and time in addition to update the date
- * 
- * Look for schedules that specify multiple days yet to come
- * 
- */
-void TSCutilScheduleWithInWeek( TSC_SCHED_ELEM *pSchedElem )
-{
-    struct tm   brokenDownTime, newDate;
-    int         d, day, anotherDay, newMonth, newDay, newYear, seconds, minutes, hours, totalSeconds;
-    int         currentTimeInSeconds, scheduleTimeInSeconds;
-    time_t      calTime;
-    
-    brokenDownTime  = pSchedElem->requestTime;
-    calTime         = pSchedElem->calTime;
-    
-    /* find the first day of the week in the schedule, starting from today */
-    day = Util_findAday( brokenDownTime.tm_wday, pSchedElem->schedule.dailySchedule );
-    
-    //printf("\t%s: sched_day(%d), today(%d)\n", __FUNCTION__, day, brokenDownTime.tm_wday);
-    
-    if ( brokenDownTime.tm_wday == day )
-    {
-        //printf("\t%s: today is in schedule\n", __FUNCTION__);
-        /*
-         * Today is in the schedule if the start time has passed (hour, minute, second)
-         *  then schedule for next week otherwise a schedule change is not required
-         *  compute the seconds past midnight and compare with the start time (in seconds past midnight)
-         *  All schedules start on the minute
-         */
-        scheduleTimeInSeconds = pSchedElem->schedule.startTime.hour * SECONDS_PER_HOUR;
-        scheduleTimeInSeconds += pSchedElem->schedule.startTime.minute * SECONDS_PER_MINUTE;
-        
-        currentTimeInSeconds = brokenDownTime.tm_hour * SECONDS_PER_HOUR;
-        currentTimeInSeconds += brokenDownTime.tm_min * SECONDS_PER_MINUTE;
-        currentTimeInSeconds += brokenDownTime.tm_sec;
-        
-        if ( currentTimeInSeconds < scheduleTimeInSeconds )
-        {
-            /* the scheduled time has not passed so no schedule change is required */
-            //printf("\t%s: start time yet to occur no schedule change required\n", __FUNCTION__);
-            return;
-        }
-
-        //printf("\t%s: start time has passed schedule change required\n", __FUNCTION__);
-        /*
-         * Today is on the schedule but the start time has passed.
-         * Is there a day past today on the schedule
-         */
-        anotherDay = (day + 1) % 7;
-        anotherDay = Util_findAday( anotherDay, pSchedElem->schedule.dailySchedule );
-        
-        //printf("\t%s: next scheduled day(%d)\n", __FUNCTION__, anotherDay);
-        
-        if ( anotherDay == day )
-        {
-            //printf("\t%s: schedule for next week\n", __FUNCTION__);
-            /*
-             * There is only one day in the schedule so schedule same day next week
-             */
-            /* add in the time from now to end of day */
-            hours = 24 - (brokenDownTime.tm_hour + 1);
-            minutes = 60 - (brokenDownTime.tm_min + 1);
-            seconds = 60 - brokenDownTime.tm_sec;
-            totalSeconds = SECONDS_PER_HOUR * hours;
-            totalSeconds += SECONDS_PER_MINUTE * minutes;
-            totalSeconds += seconds;
-            
-            /*
-             * totalSeconds moves the clock to midnight tomorrow
-             * counting from tomorrow there are 6 days to the next scheduled day (anotherDay)
-             * If the weekly schedule is every other week an additional 7 days is added
-             */
-            if ( pSchedElem->schedule.weeklySchedule == WEEKLY_CHOICE_EVERYOTHER_WEEK )
-            {
-                totalSeconds += SECONDS_PER_DAY * 7;
-            }
-            
-            totalSeconds += SECONDS_PER_DAY * 6;
-            
-            calTime += totalSeconds;
-            localtime_r( &calTime, &newDate );
-            
-            newDay      = newDate.tm_mday;
-            newMonth    = newDate.tm_mon + 1;
-            newYear     = (newDate.tm_year - 100) + 2000;
-            
-            pSchedElem->schedule.startDate.year     = newYear;
-            pSchedElem->schedule.startDate.month    = newMonth;
-            pSchedElem->schedule.startDate.day      = newDay;
-            
-            return;
-        }
-        
-        /*
-         * The starting day is not today
-         * add in the time from now to end of day
-         * accumulate full days seconds from the day after today to starting day
-         */
-        //printf("\t%s: schedule change move date forward\n", __FUNCTION__);
-        
-        hours = 24 - (brokenDownTime.tm_hour + 1);
-        minutes = 60 - (brokenDownTime.tm_min + 1);
-        seconds = 60 - brokenDownTime.tm_sec;
-        totalSeconds = SECONDS_PER_HOUR * hours;
-        totalSeconds += SECONDS_PER_MINUTE * minutes;
-        totalSeconds += seconds;
-        
-        //printf("\t%s: seconds to midnight(%ld)\n", __FUNCTION__, totalSeconds);
-        
-        /* count days from today until first day in schedule */
-        //printf("\t%s: anotherDay(%d) brokenDownTime.tm_wday(%d)\n", __FUNCTION__, anotherDay, brokenDownTime.tm_wday );
-
-        if ( anotherDay > brokenDownTime.tm_wday )
-        {
-            /* a day following today */
-            totalSeconds += (anotherDay - (brokenDownTime.tm_wday + 1)) * SECONDS_PER_DAY;
-        }
-        else
-        {
-            /* a day before today, handle the wrap around */
-            d = (SATURDAY - brokenDownTime.tm_wday) + anotherDay;
-
-            totalSeconds += d * SECONDS_PER_DAY;
-            
-            /* since the next day in the schedule is a day before today, schedule for next week or every other week */
-            if ( pSchedElem->schedule.weeklySchedule == WEEKLY_CHOICE_EVERYOTHER_WEEK )
-            {
-                totalSeconds += SECONDS_PER_DAY * 7;
-            }
-        }
-                
-        /* add in the time from midnight of the starting day to the start time */
-        totalSeconds += pSchedElem->schedule.startTime.hour * SECONDS_PER_HOUR;
-        totalSeconds += pSchedElem->schedule.startTime.minute * SECONDS_PER_MINUTE;
-        
-        //printf("\t%s: seconds to next day in schedule(%ld)\n", __FUNCTION__, totalSeconds);
-
-        calTime += totalSeconds;
-        localtime_r( &calTime, &newDate );
-        
-        newDay      = newDate.tm_mday;
-        newMonth    = newDate.tm_mon + 1;
-        newYear     = (newDate.tm_year - 100) + 2000;
-        
-        pSchedElem->schedule.startDate.year     = newYear;
-        pSchedElem->schedule.startDate.month    = newMonth;
-        pSchedElem->schedule.startDate.day      = newDay;
-        
-        return;
-    }
-
-    
-    /*
-     * The starting day is not today
-     * add in the time from now to end of day
-     * accumulate full days seconds from the day after today to starting day
-     */
-    
-    hours = 24 - (brokenDownTime.tm_hour + 1);
-    minutes = 60 - (brokenDownTime.tm_min + 1);
-    seconds = 60 - brokenDownTime.tm_sec;
-    totalSeconds = SECONDS_PER_HOUR * hours;
-    totalSeconds += SECONDS_PER_MINUTE * minutes;
-    totalSeconds += seconds;
-    
-    /* count days from today until first day in schedule */
-    if ( day > brokenDownTime.tm_wday )
-    {
-        totalSeconds += (day - (brokenDownTime.tm_wday + 1)) * SECONDS_PER_DAY;
-    }
-    else
-    {
-        /* handle the wrap around */
-        /* since the next day in the schedule is a day before today, schedule for next week or every other week */
-        if ( pSchedElem->schedule.weeklySchedule == WEEKLY_CHOICE_EVERYOTHER_WEEK )
-        {
-            totalSeconds += SECONDS_PER_DAY * 7;
-        }
-        d = ((6 - brokenDownTime.tm_wday) + day) % 7 ;
-        totalSeconds += d * SECONDS_PER_DAY;
-    }
-    
-    
-    /* add in the time from midnight of the starting day to the start time */
-    totalSeconds += pSchedElem->schedule.startTime.hour * SECONDS_PER_HOUR;
-    totalSeconds += pSchedElem->schedule.startTime.minute * SECONDS_PER_MINUTE;
-    
-    calTime += totalSeconds;
-    localtime_r( &calTime, &newDate );
-    
-    newDay      = newDate.tm_mday;
-    newMonth    = newDate.tm_mon + 1;
-    newYear     = (newDate.tm_year - 100) + 2000;
-    
-    pSchedElem->schedule.startDate.year     = newYear;
-    pSchedElem->schedule.startDate.month    = newMonth;
-    pSchedElem->schedule.startDate.day      = newDay;
-    
-    return;
-}
-
-/*
- * TSCutilScheduleOneWeekPerMonth
- * 
- * The schedule is to start on a specific month week, i.e. First, Second, Third, Fourth, Last
- * 
- * At least one day in the daily schedule must occur in the given week
- * AND the daily schedule MUST NOT cross a month boundry. These constraints
- * determine how the 'last' week of the month is interpreted. The 'last' week of the
- * month must contain sufficient days to statisfy the daily schedule.
- * Therefore 'last' may be the 4th or 5th weeks of the month.
- * is the 4th week and in
- * 
- * Given the current monthDay determine what monthWeek we are in and handle the following cases
- *  (1) In the current monthWeek
- *          Given the current weekDay is there a schedule-weekDay that works
- *          (both the day and time are in the future) if not the start is next month
- *          
- *  (2) Required monthWeek is yet to come
- *          compute time to first scheduled day in required monthWeek
- *          
- *  (3) Required monthWeek has passed
- *          compute time to required start next month
- *      
- */
-void    TSCutilScheduleOneWeekPerMonth( TSC_SCHED_ELEM *pSchedElem )
-{
-    time_t      calTime;
-    struct tm   brokenDownTime, scheduledTime;
-    int         currentYear, currentDay, currentMonth, dayOfWeek, dom, dow, wom, days, scheduleDay;
-    int         currentMonthWeek, hours, minutes, seconds, totalSeconds;
-    int         daysInSchedule, scheduleCheckCount;
-    CNTL_DATE_STRUCT    currentDate, nextMonth;
-    
-    /* verify the schedule is requesting a week of the month */
-    if ( pSchedElem->schedule.weeklySchedule != WEEKLY_CHOICE_FIRST_WEEK &&
-        pSchedElem->schedule.weeklySchedule != WEEKLY_CHOICE_SECOND_WEEK &&
-        pSchedElem->schedule.weeklySchedule != WEEKLY_CHOICE_THIRD_WEEK &&
-            pSchedElem->schedule.weeklySchedule != WEEKLY_CHOICE_FOURTH_WEEK &&
-            pSchedElem->schedule.weeklySchedule != WEEKLY_CHOICE_LAST_WEEK )
-    {
-        printf("%s: Weekly schedule (%d) does not specify a week of the month\n", __FUNCTION__, pSchedElem->schedule.weeklySchedule);
-        return;
-    }
-    
-    brokenDownTime  = pSchedElem->requestTime;
-    calTime         = pSchedElem->calTime;
-    
-    currentYear = brokenDownTime.tm_year - 100; // tm_year: years since 1900
-    currentYear += 2000;
-    currentMonth = brokenDownTime.tm_mon + 1;
-    currentDay = brokenDownTime.tm_mday;
-    
-    currentDate.year    = currentYear;
-    currentDate.month   = currentMonth;
-    currentDate.day     = currentDay;
-
-    currentMonthWeek = Util_getMonthWeek( pSchedElem, &currentDate );
-    
-    //printf("    %s: currentWeek(%d) scheduleWeek(%d)\n", __FUNCTION__, currentMonthWeek, pSchedElem->schedule.weeklySchedule);
-    
-    if ( currentMonthWeek < pSchedElem->schedule.weeklySchedule )
-    {
-        /* the schedule week is in the future, move to the SUNDAY of the required week, find the first scheduled day and set startDate */
-        dow = Util_getDayOfWeek( pSchedElem, &currentDate );
-        days = (SATURDAY - dow) + 1; /* days to start of next week */
-        
-        /* count weeks up to the required week */
-        for ( wom = currentMonthWeek + 1; wom < pSchedElem->schedule.weeklySchedule; ++wom )
-        {
-            days += 7;
-        }
-        
-        /* find the first day (SUNDAY to SATURDAY) in the schedule */
-        scheduleDay = Util_findAday( SUNDAY, pSchedElem->schedule.dailySchedule );
-        
-        pSchedElem->schedule.startDate = currentDate;
-        pSchedElem->schedule.startDate.day += (days + scheduleDay);
-        
-        return;
-    }
-    
-    if ( currentMonthWeek == pSchedElem->schedule.weeklySchedule )
-    {
-        /*
-         * the right week of the month, don't know the if the daily schedule fits,
-         * start with today and see if a day in the schedule fits
-         */
-        dow = brokenDownTime.tm_wday;
-        //dow = Util_getDayOfWeek( pSchedElem, &currentDate );
-        scheduleDay = Util_findAday( dow, pSchedElem->schedule.dailySchedule );
-        daysInSchedule = Util_numDaysInSchedule( pSchedElem->schedule.dailySchedule );
-        
-        scheduleCheckCount = 0;
-        while ( scheduleCheckCount < daysInSchedule )
-        {   
-            //printf("    dow(%d) scheduleDay(%d)\n", dow, scheduleDay);
-            /* if dow is < schedule day OR (dow == schedule day AND the start time >= current time) the schedule fits */
-            if ( (dow < scheduleDay) || /* first schedule day is after today */
-                ( dow == scheduleDay && ( pSchedElem->schedule.startTime.hour > brokenDownTime.tm_hour || /* today is first day and the time hasn't passed */
-                (pSchedElem->schedule.startTime.hour == brokenDownTime.tm_hour && pSchedElem->schedule.startTime.minute >= brokenDownTime.tm_min)) )
-                )
-            {
-                /* the schedule fits, update the starting date */
-                pSchedElem->schedule.startDate      = currentDate;
-                pSchedElem->schedule.startDate.day  += (scheduleDay - dow);
-                        
-                return;
-            }
-            ++scheduleCheckCount;
-            ++scheduleDay;
-            if ( scheduleDay <= SATURDAY )
-            {
-                scheduleDay = Util_findAday( scheduleDay, pSchedElem->schedule.dailySchedule );
-            }
-            
-        }
-    }
-    
-    /*
-     * required week has passed so schedule for next month
-     *
-     * By defintion the first day of the month defines the 'first' week of the month.
-     * count from the first week to the required week and update the start date
-     */
-    //printf("%s: currentWeek > scheduleWeek\n", __FUNCTION__);
-    
-    nextMonth = currentDate;
-    if ( nextMonth.month == 12 )
-    {
-        nextMonth.year += 1;
-        nextMonth.month = 1;
-    }
-    else
-    {
-        nextMonth.month += 1;
-    }
-    nextMonth.day = 1;
-    
-    /* get the day of week for the first day of nextMonth */
-    dow = Util_getDayOfWeek( pSchedElem, &nextMonth );
-
-    if ( pSchedElem->schedule.weeklySchedule == WEEKLY_CHOICE_FIRST_WEEK )
-    {
-        /* determine if the schedule fits in the very first week of the month */
-        scheduleDay = Util_findAday( dow, pSchedElem->schedule.dailySchedule );
-        
-        //printf("%s: dow(%s), firstDay(%s)\n", __FUNCTION__, Util_getDayString(dow), Util_getDayString(firstDay));
-        
-        if ( dow <= scheduleDay )
-        {
-            //printf("%s: schedule fits\n", __FUNCTION__);
-            /* the first day (and day of the week) of the month preceeds the first day in the schedule, set start date */
-            pSchedElem->schedule.startDate = nextMonth;
-            pSchedElem->schedule.startDate.day += scheduleDay - dow;
-            
-            return;
-        }
-        
-        /* schedule doesn't fit starting from very first week so move to the next (and full) week */
-        //printf("%s: moving schedule one week ahead\n",__FUNCTION__);
-        days = (SATURDAY - dow) + 1;
-        scheduleDay = Util_findAday( SUNDAY, pSchedElem->schedule.dailySchedule );
-        pSchedElem->schedule.startDate = nextMonth;
-        pSchedElem->schedule.startDate.day += ( days + scheduleDay );
-        
-        return;
-    }
-    
-    /*
-     * accumulate days up to SUNDAY of the required week
-     * add in the first scheduled day
-     * bobs your uncle
-     */
-    //printf("%s: dow(%s)\n", __FUNCTION__, Util_getDayString(dow));
-    
-    days = (SATURDAY - dow) + 1;
-    
-    /* count weeks up to the required week */
-    for ( wom = 2; wom < pSchedElem->schedule.weeklySchedule; ++wom )
-    {
-        days += 7;
-    }
-    
-    /* find the first day (SUNDAY to SATURDAY) in the schedule */
-    scheduleDay = Util_findAday( SUNDAY, pSchedElem->schedule.dailySchedule );
-    
-    //printf("%s: firstDay(%s)\n", __FUNCTION__, Util_getDayString(firstDay));
-    
-    pSchedElem->schedule.startDate = nextMonth;
-    pSchedElem->schedule.startDate.day += (days + scheduleDay);
-
-    return;
-}
-
-/*
- * Util_getDayOfWeek
- * 
- * Get the day of week for a given day in the FUTURE
- * This function asserts the given date is >= the current date
- */
-int Util_getDayOfWeek( TSC_SCHED_ELEM *pSchedElem, CNTL_DATE_STRUCT *pDate )
-{
-    time_t      calTime;
-    struct tm   brokenDownTime;
-    int         currentYear, currentDay, currentMonth, dayOfWeek, days, d, dayDiff;
-    
-    calTime         = pSchedElem->calTime;
-    brokenDownTime  = pSchedElem->requestTime;
-    
-    currentYear = brokenDownTime.tm_year - 100; // tm_year: years since 1900
-    currentYear += 2000;
-    currentMonth = brokenDownTime.tm_mon + 1;
-    currentDay = brokenDownTime.tm_mday;
-    
-    /* verify the given date assertion */
-    if ( currentYear > pDate->year || 
-         ( currentYear == pDate->year && currentMonth > pDate->month) ||
-         (currentYear == pDate->year && currentMonth == pDate->month && currentDay > pDate->day)
-         )
-    {
-        printf("%s: Given date (%2.2ld/%2.2ld/%2.2ld) is in the past\n", __FUNCTION__, pDate->month, pDate->day, pDate->year);
-        
-        return 0;
-    }
-
-    /*
-     * The assertion verified the given date is >= the current date
-     */
-    if ( currentYear < pDate->year )
-    {
-        /* accumulate days for the remainder of month,  */
-        //days = UTgetDaysInMonth(currentYear, brokenDownTime.tm_mon); replaced with following tm_mon is months since jan, should be THE month
-        days = UTgetDaysInMonth(currentYear, currentMonth);
-        days -= currentDay;
-        
-        /* accumulate days to end of year */
-        for ( d = currentMonth + 1; d <= 12; ++d )
-        {
-            days += UTgetDaysInMonth(currentYear, d);
-        }
-        
-        /* accumulate days in following year up to GIVEN MONTH */
-        for ( d = 0 + 1; d < pDate->month; ++d )
-        {
-            days += UTgetDaysInMonth(pDate->year, d);
-        }
-        
-        /* days contains the number of days to the first day of the required month */
-        
-        /* accumulate days in GIVEN MONTH */
-        //days += (pDate->day - 1) ; AFH 5/26
-        days += pDate->day;
-        
-        dayOfWeek = (brokenDownTime.tm_wday + days) % 7;
-        
-        return dayOfWeek;
-    }
-    else
-    {
-        /* same year */
-        if ( currentMonth < pDate->month )
-        {
-            /* same year, different month, start by accumulating days to end of month */
-            //days = UTgetDaysInMonth(currentYear, brokenDownTime.tm_mon); replaced with following tm_mon is months since jan, should be THE month
-            days = UTgetDaysInMonth(currentYear, currentMonth);
-            days -= currentDay;
-            
-            /* accumulate months of days to the start of the given month */
-            
-            for ( d = currentMonth + 1; d < pDate->month; ++d )
-            {
-                days += UTgetDaysInMonth(currentYear, d);
-            }
-            
-            /* days contains the number of days to the first day of the required month */
-            
-            /* add in the days to GIVEN DAY */ 
-            //days += (pDate->day - 1) ; AFH 5/26
-            days += pDate->day;
-            
-            dayOfWeek = (brokenDownTime.tm_wday + days) % 7;
-            
-            return dayOfWeek;
-        }
-        else
-        {
-            /* same year, same month so GIVEN DAY must be >= currentDay */
-            if ( pDate->day > currentDay )
-            {
-                /* count modulo 7 (day 0 is SUNDAY from current day to GIVEN DAY */
-                dayDiff = pDate->day - currentDay;
-                dayOfWeek = (brokenDownTime.tm_wday + dayDiff) % 7;
-                return dayOfWeek;
-            }
-            else
-            {
-                /* same year, month, day */
-                return brokenDownTime.tm_wday;
-            }
-        }
-    }
-}
-
-
-
-char *Util_getDayString( int dayOfWeek )
-{
-    switch ( dayOfWeek )
-    {
-    case SUNDAY:
-        return "SUNDAY";
-        
-    case MONDAY:
-        return "MONDAY";
-        
-    case TUESDAY:
-        return "TUESDAY";
-        
-    case WEDNESDAY:
-        return "WEDNESDAY";
-        
-    case THURSDAY:
-        return "THURSDAY";
-        
-    case FRIDAY:
-        return "FRIDAY";
-        
-    case SATURDAY:
-        return "SATURDAY";
-        
-    default:
-        return "UnKnown";
-    }
-}
-void Util_displayDailySchedule( CNTL_SCHED_STRUCT *pTimeStruct )
-{
-    int     d;
-    printf("Daily Schedule       : %s\n", Util_getDailyScheduleString(pTimeStruct));
-
-}
-
-
-char    *Util_getDailyScheduleString( CNTL_SCHED_STRUCT *pTimeStruct )
-{
-    int d;
-    static DMSTRING128 dailyString;
-    memset(dailyString, 0x0, sizeof(dailyString));
-    
-    if ( pTimeStruct->dailySchedule & DAY_SCHEDULE_SUNDAY_MASK )
-    {
-        strncat(dailyString, "Sunday", sizeof(dailyString) - strlen(dailyString) - 1);
-        strncat(dailyString, " ", sizeof(dailyString) - strlen(dailyString) - 1);
-    }
-    if ( pTimeStruct->dailySchedule & DAY_SCHEDULE_MONDAY_MASK )
-    {
-        strncat(dailyString, "Monday", sizeof(dailyString) - strlen(dailyString) - 1);
-        strncat(dailyString, " ", sizeof(dailyString) - strlen(dailyString) - 1);
-    }
-    if ( pTimeStruct->dailySchedule & DAY_SCHEDULE_TUESDAY_MASK )
-    {
-        strncat(dailyString, "Tuesday", sizeof(dailyString) - strlen(dailyString) - 1);
-        strncat(dailyString, " ", sizeof(dailyString) - strlen(dailyString) - 1);
-    }
-    if ( pTimeStruct->dailySchedule & DAY_SCHEDULE_WEDNESDAY_MASK )
-    {
-        strncat(dailyString, "Wednesday", sizeof(dailyString) - strlen(dailyString) - 1);
-        strncat(dailyString, " ", sizeof(dailyString) - strlen(dailyString) - 1);
-    }
-    if ( pTimeStruct->dailySchedule & DAY_SCHEDULE_THURSDAY_MASK )
-    {
-        strncat(dailyString, "Thursday", sizeof(dailyString) - strlen(dailyString) - 1);
-        strncat(dailyString, " ", sizeof(dailyString) - strlen(dailyString) - 1);
-    }
-    if ( pTimeStruct->dailySchedule & DAY_SCHEDULE_FRIDAY_MASK )
-    {
-        strncat(dailyString, "Friday", sizeof(dailyString) - strlen(dailyString) - 1);
-        strncat(dailyString, " ", sizeof(dailyString) - strlen(dailyString) - 1);
-    }
-    if ( pTimeStruct->dailySchedule & DAY_SCHEDULE_SATURDAY_MASK )
-    {
-        strncat(dailyString, "Saturday", sizeof(dailyString) - strlen(dailyString) - 1);
-        strncat(dailyString, " ", sizeof(dailyString) - strlen(dailyString) - 1);
-    }
-    return dailyString;
-}
-
-char    *Util_getWeeklyScheduleString( CNTL_SCHED_STRUCT *pTimeStruct )
-{
-    char    *week;
-    static DMSTRING128 weeklyString;
-    memset(weeklyString, 0x0, sizeof(weeklyString));
-    
-    switch ( pTimeStruct->weeklySchedule )
-    {   
-    case WEEKLY_CHOICE_FIRST_WEEK:
-        week = "First";
-        snprintf(weeklyString, sizeof(weeklyString), "The %s week of the month", week);
-        break; 
-        
-    case WEEKLY_CHOICE_SECOND_WEEK:
-        week = "Second";
-        snprintf(weeklyString, sizeof(weeklyString), "The %s week of the month", week);
-        break;
-        
-    case WEEKLY_CHOICE_THIRD_WEEK:
-        week = "Third";
-        snprintf(weeklyString, sizeof(weeklyString), "The %s week of the month", week);
-        break;
-        
-    case WEEKLY_CHOICE_FOURTH_WEEK:
-        week = "Fourth";
-        snprintf(weeklyString, sizeof(weeklyString), "The %s week of the month", week);
-        break;
-        
-    case WEEKLY_CHOICE_LAST_WEEK:
-        week = "Last";
-        snprintf(weeklyString, sizeof(weeklyString), "The %s week of the month", week);
-        break;
-        
-    case WEEKLY_CHOICE_EVERY_WEEK:
-        snprintf(weeklyString, sizeof(weeklyString), "Every week of the month");
-        break;
-        
-    case WEEKLY_CHOICE_EVERYOTHER_WEEK:
-        snprintf(weeklyString, sizeof(weeklyString), "Every other week of the month");
-        break;
-        
-    default:
-        snprintf(weeklyString, sizeof(weeklyString), "Unknown week of the month");
-        break;
-    }
-    
-    return weeklyString;
-}
-
-
-void Util_displayWeeklySchedule( CNTL_SCHED_STRUCT *pTimeStruct )
-{
-    char *week;
-    printf("Weekly Schedule      : %s\n", Util_getWeeklyScheduleString( pTimeStruct ));
-}
-
-/*
- * Load the time schedules from RL_Timer_Controls and build a time schedule list
- */
-int TSCutilLoadSchedules()
-{
-    
-    return OK;
-
-}
-
-// version 2
-/*
- * week_time_stamps indexed by 'days past Sunday', Sunday(0), Sat(6)
- * contains the localtime in seconds for each day at midnight (past the epoch), based upon the bootup local time
- * Given the localtime seconds for each day at midnight the local seconds for the schedule begin and end can be computed
- * to determine if the schedule was missed AND to determine which missed schedule was closest to boot up.
- */
-static unsigned long week_time_stamps[ 7 ];
-
-/*
- * chkpt_local_sec  epoch time when the controller went down
- * boot_local_sec   epoch time when the controller booted up
- * pElem            pointer to scheduling struct with the beginning and ending time (hh:mm), the weekly choices, daily choices
- * pReason          pointer to return missed reason
- * pMisses          pointer to return number of missed schedules
- * pStartToEndDiff  pointer to return time in seconds from schedule start to bootup
- */
-bool TSCutilEveryWeekMissedV2( CNTL_SCHED_STRUCT *pElem, unsigned long chkpt_local_sec, unsigned long boot_local_sec,  TSC_SCHED_MISS_REASON *pReason, int *pMisses, int *pStartToEndDiff )
-{   
-#if 0 
-    struct tm   chkptBDT, sysbootBDT, sched_beginBDT, sched_endBDT; /* broken down time structures */
-    bool   ans = false;
-    unsigned long     boot_spm;
-    unsigned long     s_b, s_e, starting_time_stamp;
-    unsigned char     down_days, down_intersection;
-    int         day, missed_schedules, start_delta, i, d, day_diff;
-    char        *pInfoReason;
-    DMSTRING32  buf;
-
-    
-    do
-    {
-        /*
-         * If the daily schedule intersects the interruption interval then check the actual times
-         * chkptBDT     - check-point-broken-down-time - the last check point taken before the system went down 
-         * sysbootBDT   - system-boot-broken-down-time - the boot time snapshot taken by the control system task
-         * 
-         * for schedules that were missed or interrupted determine the nearest schedule start to the boot time (when the systen came back up)
-         * i.e. the smallest start_delta
-         */
-        //localtime_r((time_t *)&boot_local_sec, &sysbootBDT);
-        //localtime_r((time_t *)&chkpt_local_sec, &chkptBDT);
-        localtime((time_t *)&boot_local_sec, &sysbootBDT);
-        localtime((time_t *)&chkpt_local_sec, &chkptBDT);
-        
-        /*
-         * Compute the week_time_stamps
-         * Starting with today (the day the system initialized) subtract the seconds past midnight from the boot time seconds
-         */
-        day = sysbootBDT.tm_wday;
-        boot_spm = sysbootBDT.tm_hour * SECONDS_PER_HOUR;
-        boot_spm += sysbootBDT.tm_min * SECONDS_PER_MINUTE;
-        boot_spm += sysbootBDT.tm_sec;
-        
-        starting_time_stamp = boot_local_sec - boot_spm;
-        
-        /* now fill in the remaining days of the week, the wrap around assumes all days are prior to the reboot */
-        for ( i = 0, d = day; i < 7; ++i )
-        {
-            day_diff = day - d ;
-            if ( day_diff < 0 )
-            {
-                day_diff = 7 + day_diff;
-            }
-            week_time_stamps[ d ] = starting_time_stamp - (SECONDS_PER_DAY * day_diff);
-            //UTformatDateAndTimeGivenSeconds( week_time_stamps[d], buf, sizeof(buf) );
-            //printf("\t%s\n", buf);
-            ++d;
-            d = d % 7;
-
-        }
-        
-#ifdef COMMENTOUT
-        printf("\n\nBootup on day(%d) week_time_stamps follow\n", day);
-
-        for ( i = 0; i < 7; ++i )
-        {
-            UTformatDateAndTimeGivenSeconds( week_time_stamps[i], buf, sizeof(buf) );
-            printf("\t%s\n", buf);
-        }
-        printf("\n");
-#endif  
-        missed_schedules    = 0;
-        start_delta         = SECONDS_PER_DAY * 365;
-        
-        *pReason =  TSC_SCHEDULE_NOT_MISSED;
-        
-        /*
-         * create a bit field representing of the days the controller was down on a schedule feed day
-         * boot_local_sec - chkpt_local_sec
-         * if down for more than 7 days the mask is all one's
-         */
-        if ( boot_local_sec - chkpt_local_sec >= SECONDS_PER_DAY * 7 )
-        {
-            down_days = 0x7f;
-        }
-        else
-        {
-            down_days = Util_computeDownMask( chkptBDT.tm_wday, sysbootBDT.tm_wday );
-
-        }
-        
-        down_intersection = down_days & pElem->dailySchedule;
-                
-        if ( timer_debug_print )
-        {
-            printf("\t%s: feed schedule & down interval intersection(0x%x)\n", __FUNCTION__,down_intersection);
-        }
-        
-        /*
-         * for each intersecting day determine if the feed schedule was interrupted or missed
-         */
-        for ( day = 0; day < 7; ++day )
-        {
-            if ( down_intersection & (0x01 << day) )
-            {
-                /* compute the epoch seconds schedule beginning, midnight seconds + starting hh:mm:ss */
-                s_b = week_time_stamps[day];
-                s_b += pElem->startTime.hour * SECONDS_PER_HOUR;
-                s_b += pElem->startTime.minute * SECONDS_PER_MINUTE;
-                s_b += pElem->startTime.second;
-
-                /* compute the epoch seconds schedule end, midnight seconds + starting hh:mm:ss */
-                s_e = week_time_stamps[day];
-                s_e += pElem->endTime.hour * SECONDS_PER_HOUR;
-                s_e += pElem->endTime.minute * SECONDS_PER_MINUTE;
-                s_e += pElem->endTime.second;
-                s_e -= 1; /* for scheduling purposes the end time is reduced by 1 second, so the end of timer-A is the same as the start of timer-B */
-                
-                localtime_r((time_t *)&s_b, &sched_beginBDT);
-
-#ifdef COMMENTOUT
-                printf("Inspecting Schedule %2.2d/%2.2d %2.2ld:%2.2ld to %2.2ld:%2.2ld",
-                        sched_beginBDT.tm_mon+1, sched_beginBDT.tm_mday, pElem->startTime.hour, pElem->startTime.minute, pElem->endTime.hour, pElem->endTime.minute);
-#endif
-                /*
-                 * determine if a schedule was interrupted or missed
-                 * a schedule is interrupted if it begins before chkpt_local_sec and ends after chkpt_local_sec
-                 * a schedule is missed if it is between chkpt_local_sec and boot_local_sec or 
-                 * it starts after down_begin and stops after down_end
-                 */
-                if (    (s_b < chkpt_local_sec && chkpt_local_sec < s_e ) ||    // straddle the checkpoint
-                        (s_b > chkpt_local_sec && s_e < boot_local_sec) ||      // in between checkpoint & bootup
-                        (s_b < boot_local_sec && s_e > boot_local_sec)          // straddle bootup
-                        )
-                {
-                    ++missed_schedules;
-                    
-                    start_delta = (boot_local_sec - s_b) < start_delta ? boot_local_sec - s_b : start_delta;
-                    //  between power down and power up
-                    // straddle power up
-                    if ( (chkpt_local_sec <= s_b && s_e <= boot_local_sec) || ( s_b <= boot_local_sec && s_e >= boot_local_sec ) )  
-                    {
-                        *pReason = TSC_SCHEDULE_MISSED;
-                        pInfoReason = "missed";
-                    }
-                    else if ( s_b <= chkpt_local_sec && chkpt_local_sec < s_e ) // straddle power down
-                    {
-                        *pReason = TSC_SCHEDULE_INTERRUPTED;
-                        pInfoReason = "interrupted";
-
-                    }
-                    
-                    printf("schedule %s %2.2d/%2.2d %2.2ld:%2.2ld to %2.2ld:%2.2ld %s, controller down from %2.2d/%2.2d %2.2d:%2.2d to %2.2d/%2.2d %2.2d:%2.2d", 
-                            Util_getDayString(day), sched_beginBDT.tm_mon+1, sched_beginBDT.tm_mday, pElem->startTime.hour, pElem->startTime.minute, pElem->endTime.hour, pElem->endTime.minute, pInfoReason,
-                            chkptBDT.tm_mon+1, chkptBDT.tm_mday, chkptBDT.tm_hour, chkptBDT.tm_min, sysbootBDT.tm_mon+1, sysbootBDT.tm_mday, sysbootBDT.tm_hour, sysbootBDT.tm_min );
-                }
-                else
-                {
-                    printf("Schedule %2.2d/%2.2d %2.2ld:%2.2ld to %2.2ld:%2.2ld NOT Missed",
-                            sched_beginBDT.tm_mon+1, sched_beginBDT.tm_mday, pElem->startTime.hour, pElem->startTime.minute, pElem->endTime.hour, pElem->endTime.minute);
-                }
-            }
-        }
-    } while ( 0 );
-
-    ans = ( missed_schedules ) ? true : false;
-    
-    *pMisses = missed_schedules;
-    *pStartToEndDiff = start_delta;
-    
-    return ans;
-#else
-    return false;
-#endif 
-}
-
-
-
-// version 1
-bool TSCutilEveryWeekMissed( CNTL_SCHED_STRUCT *pElem, unsigned long chkpt_local_sec, unsigned long chkpt_spm, int chkpt_wday, unsigned long boot_local_sec, unsigned long boot_spm, int boot_wday, unsigned long sched_start, unsigned long sched_end, TSC_SCHED_MISS_REASON *pReason, int *pMisses, int *pStartToEndDiff )
-{   
-    bool   ans = false;
-    unsigned long     down_begin, down_end;
-    unsigned long     b_h, b_m, e_h, e_m;
-    unsigned long     s_b_h, s_b_m, s_e_h, s_e_m, s_b, s_e;
-    unsigned char     down_days, down_intersection;
-    int         day, missed_schedules, start_delta;
-    
-    do
-    {
-        /*
-         * If the daily schedule intersects the interruption interval then check the actual times
-         * chkptBDT     - check-point-broken-down-time - the last check point taken before the system went down 
-         * sysbootBDT   - system-boot-broken-down-time - the boot time snapshot taken by the control system task
-         * 
-         * for schedules that were missed or interrupted determine the nearest schedule start to the boot time (when the systen came back up)
-         * i.e. the smallest start_delta
-         */
-        
-        /*
-         * Compute the week_time_stamps
-         * Starting with today (the day the system initialized) subtract the seconds past midnight from the boot time seconds
-         */
-        day = boot_wday;
-        
-        missed_schedules    = 0;
-        start_delta         = SECONDS_PER_DAY * 365;
-        
-        if ( timer_debug_print )
-        {
-            printf("\t%s: daily schedule(0x%x), checkPoint day(%1.1d) boot day(%1.1d)\n", __FUNCTION__,pElem->dailySchedule, chkpt_wday, boot_wday);
-        }
-        
-        *pReason =  TSC_SCHEDULE_NOT_MISSED;
-        /*
-         * create a bit field representing of the days the controller was down on a schedule feed day
-         */
-        down_days = Util_computeDownMask( chkpt_wday, boot_wday );
-        down_intersection = down_days & pElem->dailySchedule;
-        
-        if ( timer_debug_print )
-        {
-            printf("\t%s: feed schedule & down interval intersection(0x%x)\n", __FUNCTION__,down_intersection);
-        }
-        
-        /*
-         * for each intersecting day determine if the feed schedule was interrupted or missed
-         */
-        for ( day = 0; day < 7; ++day )
-        {
-            if ( down_intersection & (0x01 << day) )
-            {
-                /* an entire day of 'down' is identified as down_begin == 0 and down_end == SECONDS_PER_DAY */
-                Util_computeBeginEndDownForDay( chkpt_wday, chkpt_spm, boot_wday, boot_spm, day, &down_begin, &down_end);
-                
-                /*
-                 * determine if a schedule was interrupted or missed
-                 * a schedule is interrupted if it starts before down_begin and stops after down_begin
-                 * a schedule is missed if it is between down_begin and down_end or 
-                 * it starts after down_begin and stops after down_end
-                 */
-                if (    (down_begin <= sched_start && sched_end <= down_end)    || 
-                        ( sched_start <= down_end && sched_end >= down_end )    ||
-                        ( sched_start <= down_begin && down_begin < sched_end ) )
-                {
-                    ++missed_schedules;
-                    
-                    start_delta = (down_end - sched_start < start_delta) ? down_end - sched_start : start_delta;
-                    
-                    /* the schedule was missed or was interrupted, compute the schedule starting and ending time for the log message */
-                    s_b_h = sched_start / SECONDS_PER_HOUR;
-                    s_b_m = (sched_start - SECONDS_PER_HOUR * s_b_h)/SECONDS_PER_MINUTE;
-                    
-                    /* 1 second is subtracted for scheduling purpoes so add it back so a 1 minute timer appears to start and stop on different minutes */
-                    s_e_h = sched_end / SECONDS_PER_HOUR;
-                    s_e_m = (1 + (sched_end - SECONDS_PER_HOUR * s_e_h))/SECONDS_PER_MINUTE;
-                    if ( s_e_m == MINUTES_PER_HOUR )
-                    {
-                        s_e_h += 1;
-                        s_e_m = 0;
-                    }
-                    
-                    b_h = down_begin/SECONDS_PER_HOUR;
-                    b_m = (down_begin - SECONDS_PER_HOUR * b_h)/SECONDS_PER_MINUTE;
-
-                    e_h = down_end/SECONDS_PER_HOUR;
-                    e_m = (down_end - SECONDS_PER_HOUR * e_h)/SECONDS_PER_MINUTE;
-                    
-                    if (down_begin <= sched_start && sched_end <= down_end)
-                    {
-                        *pReason = TSC_SCHEDULE_MISSED;
-                        printf("%s schedule %2.2ld:%2.2ld to %2.2ld:%2.2ld missed, controller down from %2.2ld:%2.2ld to %2.2ld:%2.2ld", 
-                                Util_getDayString(day), s_b_h, s_b_m, s_e_h, s_e_m, b_h, b_m, e_h, e_m );
-                    }
-                    else if ( sched_start <= down_end && sched_end >= down_end )
-                    {
-                        *pReason = TSC_SCHEDULE_MISSED;
-                        printf("%s schedule %2.2ld:%2.2ld to %2.2ld:%2.2ld missed, controller down from %2.2ld:%2.2ld to %2.2ld:%2.2ld", 
-                                Util_getDayString(day), s_b_h, s_b_m, s_e_h, s_e_m, b_h, b_m, e_h, e_m );
-
-                    }
-                    else if ( sched_start <= down_begin && down_begin < sched_end )
-                    {
-                        printf("%s schedule %2.2ld:%2.2ld to %2.2ld:%2.2ld interrupted, controller down from %2.2ld:%2.2ld to %2.2ld:%2.2ld", 
-                                Util_getDayString(day), s_b_h, s_b_m, s_e_h, s_e_m, b_h, b_m, e_h, e_m );
-                        *pReason = TSC_SCHEDULE_INTERRUPTED;
-                    }
-                }
-            }
-        }
-        
-    } while ( 0 );
-
-    ans = ( missed_schedules ) ? true : false;
-    
-    *pMisses = missed_schedules;
-    *pStartToEndDiff = start_delta;
-    
-    return ans;
-}
-
-
-unsigned char Util_computeDownMask( int begin_wday, int end_wday )
-{
-    char  startStopMap;
-    int     i, b_day, e_day, num_days;
-    
-    startStopMap = 0;
-    
-    if ( timer_debug_print )
-    {
-        printf("\t%s: begin_wday(%d), end_wday(%d)\n", __FUNCTION__,begin_wday, end_wday);
-    }
-    
-    /* adding one to change from days past sunday to day of the week */
-    b_day = begin_wday +1 ;
-    e_day = end_wday + 1;
-    
-    /*
-     * start_day > stop_day the weekend was crossed
-     */
-    if ( b_day > e_day )
-    {
-        num_days = 7 - b_day;
-        num_days += e_day;
-    }
-    else
-    {
-        num_days = e_day - b_day;
-    }
-    ++num_days;
-    
-    if ( timer_debug_print )
-    {
-        printf("\t%s: b_day(%d), e_day(%d), num_days(%d)\n", __FUNCTION__, b_day, e_day, num_days);
-    }
-    
-    b_day = begin_wday;
-    
-    if ( timer_debug_print )
-    {
-        printf("\t%s: b_day(%d)\n", __FUNCTION__, b_day);
-    }
-    
-    for ( i = 0; i < num_days; ++i )
-    {
-        startStopMap = startStopMap | (0x01 << b_day);
-        ++b_day;
-        b_day = b_day % 7;
-    }
-    
-    if ( timer_debug_print )
-    {
-        printf("\t%s: startStopMap(0x%x)\n",  __FUNCTION__, startStopMap);
-    }
-    
-    return startStopMap;
-}
-
-/*
- * Util_computeBeginEndDownForDay for the given day compute the down time begin and end
- * The 'day' parameter is a day in the down time interval, it can be the first day of the down interval or a day within the interval
- * Consider the follwing down time intervals
- *      the chkpt and boot day are the same
- *      the chkpt and boot day span 2 or more days
- *      
- *      down_begin and down_end are speconds past midnight
- */
-void Util_computeBeginEndDownForDay( int chkpt_wday, unsigned long chkpt_spm, int boot_wday, unsigned long boot_spm, int day, unsigned long *down_begin, unsigned long *down_end)
-{
-    if ( day == chkpt_wday )
-    {
-        *down_begin = chkpt_spm;
-        
-        if ( day == boot_wday)
-        {
-            *down_end = boot_spm;
-        }
-        else
-        {
-            *down_end = SECONDS_PER_DAY;
-        }
-    }
-    else
-    {
-        *down_begin = 0;
-        
-        if ( day == boot_wday)
-        {
-            *down_end = boot_spm;
-        }
-        else
-        {
-            *down_end = SECONDS_PER_DAY;
-        }
-    }
-    
-    if ( timer_debug_print )
-    {
-        printf("\t%s: chkpt_wday(%d), chkpt_spm(%ld), boot_wday(%d), boot_spm(%ld) day(%d), down_being(%ld), down_end(%ld)\n",
-                __FUNCTION__,chkpt_wday, chkpt_spm, boot_wday, boot_spm, day, *down_begin, *down_end);
-    }
-}
-
-int TSCgetNumericSuffix(char* input)
-{
-    if (!input) {
-        return -1;
-    }
-    int instance = 0;
-    int multiplier = 1;
-    char*   p = input + strlen(input);
-
-    while (--p >= input) {
-        if (*p < '0' || *p > '9') {
-            break;
-        }
-        instance += multiplier * (*p - '0');
-        multiplier *= 10;
-    }
-    return instance;
-}
-
-
-/*
- * TSCnewComputeWaitTimer
- * 
- *  
- */
-int TSCnewComputeWaitTimer( CNTL_SCHED_STRUCT *pSchedule, TSC_UTIL_SCHED_STATE scheduleingState, TSC_SCHED_ELEM *pNowTimeDate, unsigned long *pDiffInSeconds )
-{
-#if 0 
-    TSC_SCHED_ELEM  schedTimeDate;
-    int          chk;
-    
-    /*
-     * Schedule the next timer activity
-     * 
-     * The timer is either
-     *      Regular priority - no special treatment
-     *      High priority and was not interrupted
-     *      High priority was interrupted but a restart is not allowed, in which case the missed timer alarm was set
-     *      
-     *      
-     * compute the time difference from now until the start of the schedule
-     * schedTimeDate starts with current date and TSCutilComputeStartDate will
-     * move the starting date to the next date in the schedule based upon the
-     * starting time and the daily + weekly schedule
-     */
-    pNowTimeDate->calTime = time( NULL );
-
-    localtime_r( &pNowTimeDate->calTime, &pNowTimeDate->requestTime );
-    
-    pNowTimeDate->schedule.startDate.year   = pNowTimeDate->requestTime.tm_year - 100; /* years since 1900 */
-    pNowTimeDate->schedule.startDate.year   += 2000;
-    pNowTimeDate->schedule.startDate.month  = pNowTimeDate->requestTime.tm_mon + 1; /* months 1 - 12 */
-    pNowTimeDate->schedule.startDate.day    = pNowTimeDate->requestTime.tm_mday;
-    pNowTimeDate->schedule.startTime.hour   = pNowTimeDate->requestTime.tm_hour;
-    pNowTimeDate->schedule.startTime.minute = pNowTimeDate->requestTime.tm_min;
-    pNowTimeDate->schedule.startTime.second = pNowTimeDate->requestTime.tm_sec;
-
-    /* setup schedTimeDate with the current date, time and the required schedule */
-    schedTimeDate.schedule.startDate        = pNowTimeDate->schedule.startDate;
-    schedTimeDate.schedule.startTime        = pSchedule->startTime;
-    schedTimeDate.schedule.dailySchedule    = pSchedule->dailySchedule;
-    schedTimeDate.schedule.weeklySchedule   = pSchedule->weeklySchedule;
-    schedTimeDate.calTime                   = pNowTimeDate->calTime;
-    schedTimeDate.requestTime               = pNowTimeDate->requestTime;
-
-    /*
-     * Adjust the starting date to correspond with the first scheduled event
-     * This is where the heavy lifting occurs
-     * TSCutilComputeStartDate will move the date from 'now' to the next date that satisfies the schedule
-     * Util_dateTimeDiff computes the difference in seconds of schedTimeDate and nowTimeDate
-     */
-    //printf("\t%s: startTime.hour(%ld), startTime.minute(%ld)\n", __FUNCTION__, schedTimeDate.schedule.startTime.hour, schedTimeDate.schedule.startTime.minute);
-    TSCutilComputeStartDate( &schedTimeDate );
-
-#ifdef COMMENTOUT
-    printf("    schedTimeDateDate(%2.2ld/%2.2ld/%4.4ld),schedTimeDateTime(%2.2ld:%2.2ld)\n\n",
-            schedTimeDate.schedule.startDate.month, schedTimeDate.schedule.startDate.day, schedTimeDate.schedule.startDate.year,
-            schedTimeDate.schedule.startTime.hour, schedTimeDate.schedule.startTime.minute);
-#endif
-    
-    /*
-     * Util_dateTimeDiff computes the difference (in seconds) from now (date and time) to
-     * schedTimeDate (date and scheduled starting hour, minute, second) 
-     */
-    if ( Util_dateTimeDiff( &pNowTimeDate->schedule, &schedTimeDate.schedule, pDiffInSeconds ) != OK )
-    {
-        printf("%s: Util_dateTimeDiff failed", __FUNCTION__ );
-        return ERROR;
-    }
-    
-    /*
-     * The computed start date should NOT be today if this is a reschedule
-     * a given timer schedule may execute only ONCE per day
-     */
-    if ( scheduleingState == TSC_RESCHEDULE )
-    {
-        /*
-         * the scheduled start date should not be the current date so move the
-         * 'current' reference time forward to 1 minute past the schedule start time
-         * and recompute the starting date and time prior to computing the difference interval
-         */
-        if ( memcmp(&pNowTimeDate->schedule.startDate, &schedTimeDate.schedule.startDate, sizeof(pNowTimeDate->schedule.startDate)) == 0 )
-        {
-            printf("\tTime change fall back case: start (%ld/%ld/%ld),(%ld:%ld)\n", 
-                    schedTimeDate.schedule.startDate.month, schedTimeDate.schedule.startDate.day, schedTimeDate.schedule.startDate.year,
-                    schedTimeDate.schedule.startTime.hour, schedTimeDate.schedule.startTime.minute);
-            printf("\tTime change fall back case: diffInSeconds(%ld)\n", *pDiffInSeconds);
-            
-            /*
-             * diffInSeconds is the interval inseconds to the go-off
-             * Add one minute to the diff and reschedule the timer from that time
-             * which will result in a date and time past today
-             */
-            *pDiffInSeconds += SECONDS_PER_MINUTE;
-            
-            printf("\tadding (%ld) seconds and recomputing\n", *pDiffInSeconds);
-            
-            /*
-             * establish the new fall-back time reference
-             * move the scheduleTimeDate time to 1 minute past the scheduled go-off
-             * reschedule with a request time that is past the scheduled start
-             */
-            schedTimeDate.calTime += *pDiffInSeconds;
-            localtime_r( &schedTimeDate.calTime, &schedTimeDate.requestTime );
-            
-            TSCutilComputeStartDate( &schedTimeDate );
-            
-            /* this diff is from now time to the rescheduled start time */
-            if ( Util_dateTimeDiff( &pNowTimeDate->schedule, &schedTimeDate.schedule, pDiffInSeconds ) != OK )
-            {
-                printf("Util_dateTimeDiff failed" );
-                return ERROR;
-            }
-            
-            /* The new diff based upon now and the re-re-scheduled time  */
-            printf("\trecomputed diffInSeconds(%ld)\n", *pDiffInSeconds);
-        }
-    }
-#endif  
-    return OK;  
-}
-
-
-typedef struct tsc_down_time_struct
-{
-    CNTL_SCHED_STRUCT   sched_elem; // timer schedule
-    unsigned long             chkpt_sec;  // checkpoint time before controller went down
-    unsigned long             chkpt_spm;  // checkpoint seconds past midnight
-    int                 chkpt_wday; // checkpoint weekday
-    unsigned long             boot_sec;   // time when controller reinitialized
-    unsigned long             boot_spm;   // bootup seconds past midnight
-    int                 boot_wday;  // bootup weekday
-    unsigned long             sched_start;// schedule start seconds past midnight 
-    unsigned long             sched_end;  // schedule end seconds past midnight
-    int                 *pMisses;   // return the number of missed schedules
-    int                 *pStartToEndDiff;   // return the time interval from schedule to bootup in seconds
-    TSC_SCHED_MISS_REASON *pReason; // return the reason for schedule miss
-} TSC_DOWN_TIME_STRUCT;
-
-
-/*
- * TSCcountMissedSchedules( someStruct *pstruct )
- * 
- * The function TSCcountMissedSchedules will replace the function TSCutilEveryWeekMissed
- * 
- * count the number of timer missed timer schedules between the checkpoint and boot-up times.
- * 
- * for each day between the check point day (the day the controller went down) and boot up day
- *  1. compute the beginning and ending down time in terms of seconds past midnight for the day
- *  2. determine if the timer had a schedule that day
- *  3. determine if the schedule was interrupted or completely missed
- *  4. accumulate missed or interrupted schedules
- *  5. determine the closest missed schedule to the boot up time
- *  
- *   
- */
-
-bool   TSCcountMissedSchedules( TSC_DOWN_TIME_STRUCT *pDTinfo)
-{
-    return false;
-}
-
-#ifdef __ICCARM__
-struct tm *localtime_r(const time_t *const timep, struct tm *result)
-{
-  struct tm *time;
-  localtimeMutex.lock();
-  time = localtime(timep);
-  if ( time ) {
-    *result = *time;
-  }
-  localtimeMutex.unlock();
-  return time ? result : NULL;
-}
-#endif 
-
-  
--- a/ICE-Application/src/Utilities/timerUtils.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,269 +0,0 @@
-#ifndef __CNTL_TIME_SHEDULE_UTILS_H__
-#define __CNTL_TIME_SHEDULE_UTILS_H__
-/************************************************************************
- *                                                                      *
- *       Copyright (c) 2012 Nalco Company. All Rights Reserved.         *
- *                                                                      *
- ************************************************************************/
- 
-#include <mbed.h>
-#include "rtos.h"
-  
-#ifdef __ICCARM__ 
-struct tm *localtime_r(const time_t *const timep, struct tm *result);
-#endif
-    
-typedef char                DMSTRING32[32];
-typedef char                DMSTRING128[128];
-typedef DMSTRING32          DM_TAG;
-
-#define ERROR -1
-#define OK 0
-
-typedef enum cntl_check_schedule_returns
-{
-    CNTL_SCHED_CHECK_INTERNAL_ERROR     = -3,   // internal implementation error
-    CNTL_SCHED_CHECK_BAD_PARAMS         = -2,   // problem with the schedule data passed
-    CNTL_SCHED_CHECK_SCHED_OK           = 0,    // no problems or conflicts with the schedule
-    CNTL_SCHED_CHECK_OUTPUT_CONFLICT    = 1,    // conflict on output relay
-    CNTL_SCHED_CHECK_PRODUCT_CONFLICT   = 2,    // product conflict with another relay timer
-    CNTL_SCHED_CHECK_BLOWDOWN_CONFLICT  = 3     // blowdown conflict with another relay timer
-} CNTL_CHECK_SCHEDULE_RETURNS;
-
-#define CNTL_MAX_SCHEDULE_ELEMENTS 64
-#define TSC_ALARM_PRIORITY  (90)    /* Very high alarm priority so no other alarm can cancel it, i.e. interlock, maintenance mode, etc.*/
-#define TSC_12_HOURS_IN_SECONDS             (SECONDS_PER_MINUTE * MINUTES_PER_HOUR * 12 )
-#define TSC_31_DAYS_IN_SECONDS              (SECONDS_PER_MINUTE * MINUTES_PER_HOUR * HOURS_PER_DAY * 31)
-
-
-#define SUNDAY_MASK         (0x001)
-#define MONDAY_MASK         (0x002)
-#define TUESDAY_MASK        (0x004)
-#define WEDNESDAY_MASK      (0x008)
-#define THURSDAY_MASK       (0x010)
-#define FRIDAY_MASK         (0x020)
-#define SATURDAY_MASK       (0x040)
-#define EVERY_DAY_MASK      (0x080)
-#define EVERY_WEEK_DAY_MASK (0x100)
-#define SUN_TO_SAT_MASK     (SUNDAY_MASK | MONDAY_MASK | TUESDAY_MASK | WEDNESDAY_MASK | THURSDAY_MASK | FRIDAY_MASK | SATURDAY_MASK)
-
-typedef struct
-{
-    int days;
-    int hours;
-    int minutes;
-    int seconds;
-} UTtimeInterval;
-
-/*
- * A general date and time struct
- */
-typedef struct
-{
-    int hour;
-    int minute;
-    int day;
-    int month;
-    int year;
-} UT_DATE_TIME;
-
-typedef struct cntl_date_struct
-{
-    unsigned long  month;
-    unsigned long  day;
-    unsigned long  year;
-} CNTL_DATE_STRUCT;
-
-typedef struct cntl_hr_min_struct
-{
-    unsigned long  hour;
-    unsigned long  minute;
-    unsigned long  second;
-} CNTL_HR_MIN_STRUCT;
-
-#define SECONDS_PER_MINUTE      (60)
-#define MINUTES_PER_HOUR        (60)
-#define HOURS_PER_DAY           (24)
-#define DAYS_PER_WEEK           (7)
-#define DAYS_PER_YEAR           (365)
-#define HOURS_PER_WEEK          (HOURS_PER_DAY * DAYS_PER_WEEK)
-#define MINUTES_PER_DAY         (MINUTES_PER_HOUR * HOURS_PER_DAY)
-#define MINUTES_PER_WEEK        (MINUTES_PER_HOUR * HOURS_PER_WEEK)
-#define SECONDS_PER_HOUR        (SECONDS_PER_MINUTE*MINUTES_PER_HOUR)
-#define SECONDS_PER_DAY         (SECONDS_PER_HOUR*HOURS_PER_DAY)
-#define SECONDS_PER_WEEK        (SECONDS_PER_HOUR*HOURS_PER_WEEK)
-
-
-#define CNTL_SUNDAY_MASK        (0x01)
-#define CNTL_MONDAY_MASK        (0x02)
-#define CNTL_TUESDAY_MASK       (0x04)
-#define CNTL_WEDNESDAY_MASK     (0x08)
-#define CNTL_THURSDAY_MASK      (0x10)
-#define CNTL_FRIDAY_MASK        (0x20)
-#define CNTL_SATURDAY_MASK      (0x40)
-#define CNTL_SUN_TO_SAT_MASK    (CNTL_SUNDAY_MASK | CNTL_MONDAY_MASK | CNTL_TUESDAY_MASK | CNTL_WEDNESDAY_MASK | CNTL_THURSDAY_MASK | CNTL_FRIDAY_MASK | CNTL_SATURDAY_MASK)
-#define CNTL_WEEKDAY_MASK       (CNTL_MONDAY_MASK | CNTL_TUESDAY_MASK | CNTL_WEDNESDAY_MASK | CNTL_THURSDAY_MASK | CNTL_FRIDAY_MASK)
-
-typedef enum
-{
-      DAY_SCHEDULE_NOT_SPECIFIED     = 0x00,
-      DAY_SCHEDULE_SUNDAY_MASK       = 0x01,
-      DAY_SCHEDULE_MONDAY_MASK       = 0x02,
-      DAY_SCHEDULE_TUESDAY_MASK      = 0x04,
-      DAY_SCHEDULE_WEDNESDAY_MASK    = 0x08,
-      DAY_SCHEDULE_THURSDAY_MASK     = 0x10,
-      DAY_SCHEDULE_FRIDAY_MASK       = 0x20,
-      DAY_SCHEDULE_SATURDAY_MASK     = 0x40,
-      DAY_SCHEDULE_WEEKDAY_MASK      = ( DAY_SCHEDULE_MONDAY_MASK | DAY_SCHEDULE_TUESDAY_MASK | DAY_SCHEDULE_WEDNESDAY_MASK | DAY_SCHEDULE_THURSDAY_MASK | DAY_SCHEDULE_FRIDAY_MASK ),
-      DAY_SCHEDULE_SAT_TO_SUN_MASK   = ( DAY_SCHEDULE_SUNDAY_MASK | DAY_SCHEDULE_WEEKDAY_MASK | DAY_SCHEDULE_SATURDAY_MASK )
-} DAY_SCHEDULE;
-
-typedef enum
-{
-      WEEKLY_CHOICE_EVERY_WEEK       = 0,
-      WEEKLY_CHOICE_FIRST_WEEK       = 1,
-      WEEKLY_CHOICE_SECOND_WEEK      = 2,
-      WEEKLY_CHOICE_THIRD_WEEK       = 3,
-      WEEKLY_CHOICE_FOURTH_WEEK      = 4,
-      WEEKLY_CHOICE_LAST_WEEK        = 5,
-      WEEKLY_CHOICE_EVERYOTHER_WEEK  = 6,
-      WEEKLY_CHOICE_NOT_SPECIFIED    = 7
-} WEEKLY_CHOICES;
-
-
-typedef enum cntl_days_of_wk
-{
-    SUNDAY      = 0,
-    MONDAY      = 1,
-    TUESDAY     = 2,
-    WEDNESDAY   = 3,
-    THURSDAY    = 4,
-    FRIDAY      = 5,
-    SATURDAY    = 6
-} CNTL_DAYS_OF_WK;
-
-/*
- * CNLT_SCHED_STRUCT contains everything needed to specify a schedule
- */
-typedef struct cntl_sched_struct
-{
-    CNTL_DATE_STRUCT    startDate;      // always valid, mm/dd/yyyy when schedule starts all schedules have a startDate
-    CNTL_HR_MIN_STRUCT  startTime;      // always valid, hour and minute when output is activated, all schedules have startTime
-    CNTL_HR_MIN_STRUCT  endTime;        // always valid, hour and minute when output is activation stops, all schedules have stopTime
-    WEEKLY_CHOICES   weeklySchedule; // default is EVERY
-    unsigned char       dailySchedule;  // default is the current day of the week  
-} CNTL_SCHED_STRUCT;
-
-typedef struct
-{
-    CNTL_SCHED_STRUCT   schedule;       /* the schedule */
-    time_t              calTime;        /* time in seconds passed to localtime to populate the requestTime structure */
-    struct tm           requestTime;    /* the broken down time when the request was made, used to determine the initial starting date */
-    unsigned long       outputDuty;     /* scaled output duty 3 digits 1 decimal 0 <= outputDuty <= 1000 */
-    bool                preBleedorLockout; /* the timer specifies preBleed or lockout */
-} TSC_SCHED_ELEM;
-
-#define TSC_NULL_INSTANCE   (-1)
-
-/*
- * To be deprecated
- */
-typedef enum
-{
-    TSC_UTIL_ONE_OUTPUT     = 1,
-    TSC_UTIL_ALL_OUTPUTS    = 2,
-} TSC_UTIL_OUTPUT_CHECK;
-
-/*
- * Tell the general checking function what to look for
- */
-typedef enum
-{
-    TSC_UTIL_THEOUTPUT_CHECK,
-    TSC_UTIL_BLOWDOWN_CHECK,
-    TSC_UTIL_OXNONOX_CHECK
-} TSC_UTIL_WHAT_TO_CHECK;
-
-/*
- * The attribute to look for when filtering the list of timer schedules
- * it's up to the pruning filter functions to include or exclude based upon the
- * pruning attribute
- */
-typedef enum
-{
-    TSC_UTIL_PRUNE_PRODUCTS = 1,
-    TSC_UTIL_PRUNE_BLOWDOWN = 2
-} TSC_UTIL_PRUNE_ATTRIBUTE;
-
-/*
- * attribute indicates if a timer scheduling is for the first time or a reschedule 
- */
-typedef enum
-{
-    TSC_INITIAL_SCHEDULE,
-    TSC_RESCHEDULE
-} TSC_UTIL_SCHED_STATE;
-
-typedef enum tsc_sched_miss_reason
-{
-    TSC_SCHEDULE_NOT_MISSED,
-    TSC_SCHEDULE_MISSED,
-    TSC_SCHEDULE_INTERRUPTED
-} TSC_SCHED_MISS_REASON;
-
-
-/*
- * renamed utility functions replacing CNTL_xyz functions
- */
-
-void    TSCutilScheduleWithInWeek( TSC_SCHED_ELEM *pSchedElem );
-void    TSCutilPreviousScheduleWithInWeek( TSC_SCHED_ELEM *pSchedElem );
-void    TSCutilComputeStartDate( TSC_SCHED_ELEM *pSchedElem );
-void    TSCutilScheduleOneWeekPerMonth( TSC_SCHED_ELEM *pSchedElem );
-void    TSCutilInitFreeLists();
-bool   TSCutilWasPreviousScheduleInterrupted( CNTL_SCHED_STRUCT *pElem, TSC_SCHED_MISS_REASON *pReason, unsigned long create_time_stamp, int *pmiss_count, int *pstart_to_end_diff );
-int  TSCgetCreateTime( DM_TAG relay, unsigned long starting_hour, unsigned long starting_minute, unsigned long *create_time );
-int  TSCnewComputeWaitTimer( CNTL_SCHED_STRUCT *pSchedule, TSC_UTIL_SCHED_STATE scheduleingState, TSC_SCHED_ELEM *pNowTimeDate, unsigned long *pDiffInSeconds );
-bool   TSCIsTimerSchedLT12Hr( unsigned long *pGo_Off, DMSTRING32 id_info );
-
-int  TSCutilLoadSchedules();
-int  TSCutilAddElemToScheduleList( TSC_SCHED_ELEM *pElem );
-int  TSCutilPutFreeSchedElem( TSC_SCHED_ELEM *pElem );
-
-
-int  TSCutilDeleteSchedElem( TSC_SCHED_ELEM *pElem );
-
-TSC_SCHED_ELEM  *TSCutilGetFreeSchedElem( );
-TSC_SCHED_ELEM  *TSCutilGetFirstSchedule();
-TSC_SCHED_ELEM  *TSCutilGetNextSchedule( TSC_SCHED_ELEM *pElem );
-
-int TSCutilgetScheduleCount();
-int TSCutilCmpStartTimes( TSC_SCHED_ELEM *pNewElem, TSC_SCHED_ELEM *pListElem );
-
-bool       TSCutilDoesScheduleConflict( TSC_SCHED_ELEM *pNewElem, TSC_UTIL_OUTPUT_CHECK which_check );
-
-
-
-int  Util_addTupleToTimeControl( int instance, TSC_SCHED_ELEM *pElem );
-int  Util_addTupleToRLcontrol( int instance, TSC_SCHED_ELEM *pElem, DM_TAG keyTag );
-int  Util_dateTimeDiff( CNTL_SCHED_STRUCT *pDateTime1, CNTL_SCHED_STRUCT *pDateTime2, unsigned long *pDiffInSeconds );
-
-
-void    Util_displayStartDateTime( CNTL_SCHED_STRUCT *pTimeStruct );
-void    Util_displayWeeklySchedule( CNTL_SCHED_STRUCT *pTimeStruct );
-void    Util_displayDailySchedule( CNTL_SCHED_STRUCT *pTimeStruct );
-
-int Util_getDayOfWeek( TSC_SCHED_ELEM *pSchedElem, CNTL_DATE_STRUCT *pDate );
-int Util_getMonthWeek( TSC_SCHED_ELEM *pSchedElem, CNTL_DATE_STRUCT *pDate  );
-int Util_findAday( int startingDay, unsigned char dailySchedule );
-int Util_getDoWThisMonth( TSC_SCHED_ELEM *pSchedElem, int dom );
-int Util_numDaysInSchedule( unsigned char dailySchedule );
-
-char *Util_getDailyScheduleString( CNTL_SCHED_STRUCT *pTimeStruct );
-char *Util_getWeeklyScheduleString( CNTL_SCHED_STRUCT *pTimeStruct);
-char *Util_getDayString( int dayOfWeek );
-
-int TSCgetNumericSuffix(char* input);
-char * TSCinterruptReasonToString( TSC_SCHED_MISS_REASON reason );
-
-#endif
--- a/ICE-Application/src/Utilities/utilities.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/******************************************************************************
- * File:            utilities.cpp
- * Description:
- ******************************************************************************/
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include "mbed.h"
-#include "global.h"
-#include "cJSON.h"
-#include "ICELog.h"
-#include "utilities.h"
-
-//
-// function:            capture
-// description:         captures the output from the __heapstats function
-//
-static int capture(void* pBuffer, char const* pFormatString, ...)
-{
-    char*   pStringEnd = (char*)pBuffer + strlen((char*)pBuffer);
-    va_list valist;
-
-    va_start(valist, pFormatString);
-    return vsprintf(pStringEnd, pFormatString, valist);
-}
-
-//
-// function:            Util_isSequenceSubControl
-// description:         
-//
-bool Util_isSequenceSubControl(std::string controlFile)
-{
-    return (controlFile.substr(0, 4) == "seq_") ? true : false;
-}
-
-// 
-// function:            Util_isVirtualOutput
-// description:         
-//
-bool Util_isVirtualOutput(std::string output) 
-{
-    return (output.substr(0, 2) == "v_" ) ? true : false;
-}
-
-//
-// function:            getHeapData
-// description:         cleaned version of __heapstats()
-//
-// @param[in]           none
-// @param[out]          none
-// @return              none
-//
-std::string Util_getHeapData(void)
-{
-#ifndef __ICCARM__
-    char data[256];
-    memset(data, 0, sizeof(data));
-    __heapstats(capture, data);
-    std::string msg = data;
-    std::string::size_type pos = 0;
-    while ((pos = msg.find("\n", pos)) != std::string::npos) {
-        msg.erase(pos, std::string::npos);
-    }
-    return msg;
-#endif 
-}
-
-//
-// function:            getLastBootTime
-// description:         read the boot.time file and return the timestamp
-//
-// @param[in]           none
-// @param[out]          none
-// @return              none
-//
-std::string Util_getLastBootTime(void)
-{
-#ifdef MDOT_ICE
-    mDot::mdot_file file = GLOBAL_mdot->openUserFile("boot.time", mDot::FM_RDONLY);
-    if ( file.fd < 0 ) {
-        logError("%s: failed to open boot.time", __func__);
-        return "error";
-    }
-    char *data_buf = (char*) malloc(file.size);
-    bool rc = GLOBAL_mdot->readUserFile(file, data_buf, file.size);
-    if ( rc != true ) {
-        logError("%s: failed to read boot.time", __func__);
-        free(data_buf);
-        GLOBAL_mdot->closeUserFile(file);
-        return "error";
-    }
-    std::string bootTime = data_buf;
-
-    free(data_buf);
-    GLOBAL_mdot->closeUserFile(file);
-    return bootTime;
-#endif
-    return 0;
-}
-
-std::string Util_GetFileById(const std::string id)
-{
-    // loop through all the files looking for a matching ID
-    
-}
-
-std::string Util_GetIdbyFile(const std::string filename)
-{
-    char buf[MAX_FILE_SIZE];
-    std::string id = "";
-    int n = GLOBAL_mdot->readUserFile(filename.c_str(), (void*) buf, sizeof(buf));
-    if ( n != sizeof(buf) ) {
-        logError("%s: error reading %s", __func__, filename.c_str());
-        return id;
-    }
-    cJSON *root = cJSON_Parse(buf);
-    if ( !cJSON_HasObjectItem(root, "id") ) {
-        logError("%s: failed to find id in file %s\n", __func__, filename.c_str());
-    }
-    id = cJSON_GetObjectItem(root, "id")->valuestring;
-    cJSON_Delete(root);
-    return id;
-}
--- a/ICE-Application/src/Utilities/utilities.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-#ifndef UTILITIES_H
-#define UTILITIES_H
-
-#include <string>
-
-bool        Util_isVirtualOutput(std::string);
-std::string Util_getHeapData(void);
-std::string Util_getLastBootTime(void);
-bool        Util_isSequenceSubControl(std::string);
-
-#endif
\ No newline at end of file
--- a/ICE-Application/src/Utilities/v7_c_calls.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-#include "global.h"
-#include <stdio.h>
-#include <string>
-#include <sstream>
-#include <iostream>
-#include "v7_c_calls.h"
-#include "utilities.h"
-#include "ModbusMasterApi.h"
-#include "cJSON.h"
-#include "ConfigurationHandler.h"
-
-#ifdef EXECUTE_SCRIPT
-
-char FileBuffer[MAX_FILE_SIZE];
-
-enum v7_err js_modifySetpoint(struct v7 *v7, v7_val_t *res)
-{
-    std::ostringstream filename;
-    
-    // id of control i.e. INH_TRA_01
-    v7_val_t arg0 = v7_arg(v7, 0);
-    const char *arg0_str = v7_get_cstring(v7, &arg0);
-    // setpoint
-    v7_val_t arg1 = v7_arg(v7, 0);
-    const char *arg1_str = v7_get_cstring(v7, &arg1);
-        
-    filename << CONTROL_SP_STR << arg0_str << ".json";
-    
-    printf("%s:%d: filename = %s\r\n",__func__, __LINE__, filename.str().c_str() );
-    
-    // read the file
-    bool rc = GLOBAL_mdot->readUserFile(filename.str().c_str(), (void*)FileBuffer, MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("%s:%d: Failed to read %s\r\n",__func__, __LINE__, filename.str().c_str());
-        return V7_INTERNAL_ERROR;
-    }
-
-    cJSON * root = cJSON_Parse(FileBuffer);
-    strncpy( cJSON_GetObjectItem(root,"setpoint")->valuestring, arg1_str, (strlen(arg1_str)-1) );
-    std::string s = cJSON_PrintUnformatted(root);
-    cJSON_Delete(root);
-
-    printf("%s:%d: writing back: %s\r\n",__func__, __LINE__, s.c_str());
-
-    rc = GLOBAL_mdot->saveUserFile(filename.str().c_str(), (void*)s.c_str(), MAX_FILE_SIZE);
-    if ( rc != true ) {
-        printf("%s:%d: Failed to write %s\r\n",__func__, __LINE__, filename.str().c_str());
-        return V7_INTERNAL_ERROR;
-    }
-    return V7_OK;
-}
-
-enum v7_err js_getTime(struct v7 *v7, v7_val_t *res)
-{
-    time_t curr_sec = time(NULL);
-//    printf("%s:%d: time=%ld\r\n", __func__, __LINE__, curr_sec );
-    *res = v7_mk_number(v7, curr_sec);
-    return V7_OK;
-}
-
-enum v7_err js_setRegister(struct v7 *v7, v7_val_t *res)
-{
-    v7_val_t argv0 = v7_arg(v7, 0);
-    if( v7_is_string(argv0) ) {
-//        printf("first param is a string\r\n");
-    }
-    const char *arg_str = v7_get_cstring(v7, &argv0);
-    double arg1 = v7_get_double(v7, v7_arg(v7, 1));
-    (void)ScriptWriteRegister( arg_str, arg1 );
-//    printf("%s:%d: string=%s, value=%2.2f\r\n", __func__, __LINE__, arg_str, arg1 );
-
-    *res = v7_mk_number(v7, 1);
-    return V7_OK;
-}
-
-enum v7_err js_getRegister(struct v7 *v7, v7_val_t *res)
-{
-    v7_val_t argv0 = v7_arg(v7, 0);
-    if( v7_is_string(argv0) ) {
-//        printf("first param is a string\r\n");
-    }
-    const char *arg_str = v7_get_cstring(v7, &argv0);
-    double reg_value = ScriptReadRegister( arg_str );
-//    printf("%s:%d: string=%s, value=%2.2f\r\n", __func__, __LINE__, arg_str, reg_value );
-
-    *res = v7_mk_number(v7, reg_value);
-    return V7_OK;
-}
-
-bool v7_Register_C_Calls(struct v7 *v7)
-{
-    v7_set_method(v7, v7_get_global(v7), "getTime", &js_getTime);
-    v7_set_method(v7, v7_get_global(v7), "setRegister", &js_setRegister);
-    v7_set_method(v7, v7_get_global(v7), "getRegister", &js_getRegister);
-    v7_set_method(v7, v7_get_global(v7), "modifySetpoint", &js_modifySetpoint);
-    return true;
-}
-#endif
\ No newline at end of file
--- a/ICE-Application/src/Utilities/v7_c_calls.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-#ifndef V7_C_CALLS_H
-#define V7_C_CALLS_H
-
-#include "v7.h"
-
-bool v7_Register_C_Calls(struct v7 *v7);
-
-#endif
\ No newline at end of file
--- a/ICE-Application/src/Utilities/v7_execute.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-#include <stdio.h>
-#include "v7_execute.h"
-#include "utilities.h"
-#include "rtos.h"
-
-#ifdef EXECUTE_SCRIPT
-
-struct v7 *v7;
-Mutex v7_mutex;
-
-void v7_Create_Engine(void)
-{
-    v7 = v7_create();
-    v7_Register_C_Calls(v7);
-}
-
-void v7_Load_Script(const char * scriptString)
-{
-    enum v7_err rcode;
-    v7_val_t result;
-    
-    osStatus mutex_ret = v7_mutex.lock();
-    if( mutex_ret != osOK ) printf("%s:%d: did not lock mutex, ret=0x%x\r\n", __func__, __LINE__, mutex_ret);
-    rcode = v7_exec(v7, scriptString, &result);
-    mutex_ret = v7_mutex.unlock();
-    if( mutex_ret != osOK ) printf("%s:%d: did not unlock mutex, ret=0x%x\r\n", __func__, __LINE__, mutex_ret);
-    if( rcode != V7_OK )
-    {
-        printf("%s:%d: Failed to load script: %s (len=%d), ret=%d\r\n", __func__, __LINE__, scriptString, strlen(scriptString), rcode);
-    }
-}
-
-void v7_Execute_Script( std::string Command, std::string argv[NUM_SCRIPT_ARGS] )
-{
-    v7_val_t func, result, args;
-    double argv_array[NUM_SCRIPT_ARGS];
-
-    if( Command.size() == 0 ) {
-        return;
-    }
-//    printf("\r%s\r\n", Util_getHeapData().c_str());
-
-    memset( argv_array, 0, (sizeof(double) * NUM_SCRIPT_ARGS));
-    for( int i=0; i<NUM_SCRIPT_ARGS; i++ ) {
-        if( argv[i].size() != 0 ) {
-            argv_array[i] = RegisterValueMap[argv[i]].float_value;
-        }
-    }
-
-//    printf("Command.size=%d, Command=%s(%s=%2.2f,%s=%2.2f,%s=%2.2f,%s=%2.2f)\r\n", Command.size() ,Command.c_str(), argv[0].c_str(), argv_array[0], argv[1].c_str(), argv_array[1], argv[2].c_str(), argv_array[2], argv[3].c_str(), argv_array[3]);
-
-    osStatus mutex_ret = v7_mutex.lock();
-    if( mutex_ret != osOK ) printf("%s:%d: did not lock mutex, ret=0x%x\r\n", __func__, __LINE__, mutex_ret);
-    
-    func = v7_get(v7, v7_get_global(v7), Command.c_str(), Command.size());
-
-    args = v7_mk_array(v7);
-    for( int i=0; i<NUM_SCRIPT_ARGS; i++ ) {
-        if( argv[i].size() != 0 ) {
-//            printf("Pushing %s\r\n", argv[i].c_str());
-            v7_array_push(v7, args, v7_mk_string(v7, argv[i].c_str(), argv[i].size(), false));
-        }
-    }
-
-    if (v7_apply(v7, func, V7_UNDEFINED, args, &result) == V7_OK) {
-//        printf("Result: %g\r\n", v7_get_double(v7, result));
-    } else {
-        printf("Error while calling %s\r\n", Command.c_str());
-    }
-    
-    mutex_ret = v7_mutex.unlock();
-    if( mutex_ret != osOK ) printf("%s:%d: did not unlock mutex, ret=0x%x\r\n", __func__, __LINE__, mutex_ret);
-}
-#endif
\ No newline at end of file
--- a/ICE-Application/src/Utilities/v7_execute.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-#ifndef V7_EXECUTE_H
-#define V7_EXECUTE_H
-
-#include "global.h"
-#include "v7.h"
-#include "v7_c_calls.h"
-
-void v7_Create_Engine(void);
-void v7_Load_Script(const char * scriptString);
-void v7_Execute_Script( std::string Command, std::string argv[NUM_SCRIPT_ARGS] );
-
-#endif
\ No newline at end of file
--- a/ICE-Application/src/add-ons/BLE/inc/ble_init.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-
-/**
-  ******************************************************************************
-  * @file    ble_types.h
-  * @author  Happiesstminds Firmware Team
-  * @version v1.0
-  * @date    4-Oct-2016
-  * @brief   
-  *
-  ******************************************************************************
-  * @attention
-  *  
-  *
-  ******************************************************************************
-  */
-
-#ifndef _BLE_INIT_H
-#define _BLE_INIT_H
-
-class BLE_INIT
-{
-   public:
-      // Member functions declaration
-        uint8_t SendBleData(uint8_t *tx_buf, uint8_t len);
-        uint8_t InitBLEModule(void);
-        uint8_t SetDeviceName(void);
-        uint8_t SetAdvertisingData(void);
-        uint8_t SendInitBleCommand(const char *device_name);
-};
-
-
-
-
-#endif
-/******************************************************************************/
-/* END OF FILE                                                                */
-/******************************************************************************/
\ No newline at end of file
--- a/ICE-Application/src/add-ons/BLE/inc/ble_main.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    ble_types.h
-  * @author  Happiesstminds Firmware Team
-  * @version v1.0
-  * @date    4-Oct-2016
-  * @brief   
-  *
-  ******************************************************************************
-  * @attention
-  *  
-  *
-  ******************************************************************************
-  */
-
-#ifndef _BLE_MAIN_H
-#define _BLE_MAIN_H
-
-uint8_t PollBLEEvents(void);
-
-typedef void (*ble_data_ready_callback_t) (uint8_t *rx_data, uint8_t data_length);
-void BleDataRxCbRegister(ble_data_ready_callback_t data_rx_callback);
-class BLE_FILE
-{
-   public:
-      // Member functions declaration
-        uint8_t ConfigureBLEDevice(const char * device_name);
-        void SendFile(uint8_t* json_file,uint8_t len);
-        bool GetBleConnectionState(void);
-};
-
-
-#define COMMAND_LENGTH  4
-#define DATA_LENGTH     0
-#define FAILURE 0
-#define MAX_PAYLOAD_BYTES 20
-
-#endif
-/******************************************************************************/
-/* END OF FILE                                                                */
-/******************************************************************************/
\ No newline at end of file
--- a/ICE-Application/src/add-ons/BLE/inc/ble_msg_handler.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    ble_types.h
-  * @author  Happiesstminds Firmware Team
-  * @version v1.0
-  * @date    4-Oct-2016
-  * @brief   
-  *
-  ******************************************************************************
-  * @attention
-  *  
-  *
-  ******************************************************************************
-  */
-
-#ifndef _BLE_MSG_HANDLER_H
-#define _BLE_MSG_HANDLER_H
-#include "ble_main.h"
-
-void ProcessBleRxEvents(uint8_t *spi_rcv_array);
-#endif
-/******************************************************************************/
-/* END OF FILE                                                                */
-/******************************************************************************/
\ No newline at end of file
--- a/ICE-Application/src/add-ons/BLE/inc/ble_spi.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    ble_types.h
-  * @author  Happiesstminds Firmware Team
-  * @version v1.0
-  * @date    4-Oct-2016
-  * @brief   
-  *
-  ******************************************************************************
-  * @attention
-  *  
-  *
-  ******************************************************************************
-  */
-
-#ifndef _BLE_SPI_H
-#define _BLE_TYPES_H
-
-#define BLE_SOF_CMD                 0x01
-#define BLE_EOT_CMD                 0x04
-
-#define BLE_INIT_CMD                0xA1
-#define BLE_START_ADV_CMD           0xA2
-#define BLE_CONNECTION_EVNT_CMD     0xA3
-#define BLE_START_OF_FILE           0xA4
-#define BLE_SEND_DATA_CMD           0xA5
-#define BLE_END_OF_FILE             0xA6
-#define BLE_REC_DATA_CMD            0xA7
-#define BLE_DISCONNECTION_EVNT_CMD  0xA8
-#define BLE_ACK_CMD                 0xAA
-
-#include "ble_main.h"
-
-uint8_t WriteSpiData(uint8_t * p_buffer, uint16_t length);
-uint8_t InitSpiMaster(void);
-uint8_t ReadSpiData(uint8_t *);
-#endif
-
-/******************************************************************************/
-/* END OF FILE                                                                */
-/******************************************************************************/
\ No newline at end of file
--- a/ICE-Application/src/add-ons/BLE/src/ble_init.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    ble_init.cpp
-  * @author  Happiesstminds Firmware Team
-  * @version v1.0
-  * @date    4-Oct-2016
-  * @brief   
-  *
-  ******************************************************************************
-  * @attention
-  *  
-  *
-  ******************************************************************************
-  */
-
-/******************************************************************************/
-/* Include Files*/
-/******************************************************************************/
-#include "mbed.h"
-#include "ble_main.h" 
-#include "ble_spi.h"
-#include "ble_msg_handler.h"
-#include "ble_init.h"  
-/******************************************************************************/
-/* Local Defines                                                              */
-/******************************************************************************/
-
-/******************************************************************************/
-/* Global Functions                                                           */
-/******************************************************************************/
-
-/*****************************************************************************
- * Function:            InitBLEModule()
- * Description:         initialise GPIo and SPI
- *
- * @param               BLE SPI Command
- * @return              status
- *****************************************************************************/
-uint8_t BLE_INIT :: InitBLEModule(void)
-{
-    uint8_t status = SUCCESS;
-   
-   /*TODO
-        wait(3) second delay added to make sure that Nano BLE initialised first 
-        after a power on reset.Within 3 seconds, expecting Nano BLE init is 
-        succesfull and waiting for the commands from mDOt.
-    */
-  
-    wait(3);         
-    printf("\rInitializing BLE...");
-    status = InitSpiMaster();    
-    if ( status != SUCCESS ) {
-        printf("failed %d)\n\r\n.", status);
-    } else {
-        printf("success.\n\r\n");
-    }
-    return status;
-}
-
-
-
-/*****************************************************************************
- * Function:            SendCommand()
- * Description:         Send command to BLE
- *
- * @param               BLE SPI Command
- * @return              none
- *****************************************************************************/
-
-static void SendCommand(uint8_t command)
-{
-    uint8_t packet[4];
-              
-    packet[0]= BLE_SOF_CMD;
-    packet[1]= command;
-    packet[2]= DATA_LENGTH;
-    packet[3]= BLE_EOT_CMD;         
-    WriteSpiData(packet,COMMAND_LENGTH);
-}
-
-
-/*****************************************************************************
- * Function:            send BLE init command()
- * Description:         Send command to BLE
- *
- * @param               none
- * @return              uint8_t status
- *****************************************************************************/
-uint8_t BLE_INIT :: SendInitBleCommand(const char *device_name)
-{   
-    uint8_t packet[50];
-    uint8_t len =strlen(device_name);                 
-    packet[0]= BLE_SOF_CMD;
-    packet[1]= BLE_INIT_CMD;
-    packet[2]= len;
-    if(len>31)
-    {
-        /*maximum allowded device name length is 31*/
-        len =31;
-    }
-    memcpy(&packet[3], device_name, len);
-    packet[len + 3]= BLE_EOT_CMD;      
-    WriteSpiData(packet,(len + 4));
-    return 0;
-}
-
-/*****************************************************************************
- * Function:            StartAdvertisingData()
- * Description:         Send startAdvertisingData Command 
- *
- * @param               none
- * @return              uint8_t status
- *****************************************************************************/
-uint8_t StartAdvertisingData(void)
-{
-   uint8_t status =SUCCESS;
-   SendCommand(BLE_START_ADV_CMD);
-   return status;
-}
-
-/*****************************************************************************
- * Function:            SendBleData()
- * Description:         Send data over BLE (Max 20 bytes)
- *
- * @param               txBuf
-  * @param              data length
- * @return              uint8_t status
- *****************************************************************************/
-uint8_t BLE_INIT :: SendBleData(uint8_t *tx_buf, uint8_t len)
-{
-    uint8_t packet[24];
-    uint8_t status = SUCCESS;        
-    uint8_t packetlength;      
-    packetlength = len + 4; 
-    
-    if(len<=20)
-    {
-        packet[0]= BLE_SOF_CMD;
-        packet[1]= BLE_SEND_DATA_CMD;
-        packet[2]= len;
-
-        memcpy(&packet[3], tx_buf, len);
-        packet[len + 3]= BLE_EOT_CMD;         
-        WriteSpiData(packet, packetlength);
-    }
-    else
-    {
-        status = FAILURE;
-    }
-    return status;
-}
-/******************************************************************************/
-/* END OF FILE                                                                */
-/******************************************************************************/
\ No newline at end of file
--- a/ICE-Application/src/add-ons/BLE/src/ble_main.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    ble_uart.cpp
-  * @author  Happiesstminds Firmware Team
-  * @version v1.0
-  * @date    4-Oct-2016
-  * @brief   
-  *
-  ******************************************************************************
-  * @attention
-  *  
-  *
-  ******************************************************************************
-  */
-
-/******************************************************************************/
-/* Include Files*/
-/******************************************************************************/
-#include "mbed.h"
-#include "ble_main.h" 
-#include "ble_spi.h"
-#include "ble_msg_handler.h"
-#include "ble_init.h"
-
-
- 
-/******************************************************************************/
-/* Global Functions                                                           */
-/******************************************************************************/
-BLE_INIT BLE_INIT;
-extern volatile bool isDeviceConnected;
-uint8_t temp_buf[30];
-uint8_t dummy_bytes;
-/*******************************************************************************
- * Function:            ConfigureBLEDevice()
- * Description:         Initialise and configure BLE
- *
- * @param               none
- * @return              none
- ******************************************************************************/
- 
-uint8_t BLE_FILE :: ConfigureBLEDevice(const char * device_name)
-{
-    
-    uint8_t status = SUCCESS;
-    BLE_INIT.InitBLEModule();            //initialising BLE SPI GPIO etc. 
-    /*
-        The below function called 3 times to makse sure that mDot board 
-        initialise properly.The nano BLE code handle this by making sure that 
-        initialisation happening only once.
-    */
-    BLE_INIT.SendInitBleCommand(device_name);       //initializing BLE
-    BLE_INIT.SendInitBleCommand(device_name);       //initializing BLE
-    BLE_INIT.SendInitBleCommand(device_name);       //initializing BLE
-    return status;
-}
-
-/*****************************************************************************
- * Function:            GetBleConnectionState()
- * Description:         check whether device is connected or not
- *
- * @param               none
- * @return              uint8_t status(connected or disconnected)
- *****************************************************************************/
-
-bool BLE_FILE :: GetBleConnectionState(void)
-{
-    return isDeviceConnected;
-} 
-
-/*****************************************************************************
- * Function:            SendSOF()
- * Description:         This function send Start of File transfer frame
- *
- * @param               tx_buf
-* @param                data length
- * @return              none
- *****************************************************************************/
-static void SendSOF(void)
-{ 
-    uint8_t packet[24];
-    packet[0] =BLE_SOF_CMD;
-    packet[1] =BLE_START_OF_FILE;
-    packet[2] =MAX_PAYLOAD_BYTES;
-    packet[3] ='S';
-    packet[4] ='O';
-    packet[5] ='F';    
-    memset(&packet[6], '@', 17);
-    packet[23]=BLE_EOT_CMD;               
-    WriteSpiData(packet,24);
-}
-
-/*****************************************************************************
- * Function:            ClearBuffer
- * Description:         This function clear the receive buffer. This is to make
- *                      sure that receive buffer is empty.Sending 20 dummy bytes
-                        (@)to BLE device.
- * @param               void
- * @return              none
- *****************************************************************************/
-static void ClearBuffer(void)
-{ 
-    uint8_t packet[24];
-    packet[0] =BLE_SOF_CMD;
-    packet[1] =0xFF;
-    packet[2] =MAX_PAYLOAD_BYTES;  
-    memset(&packet[3], '@', 20);
-    packet[23]=BLE_EOT_CMD;               
-    WriteSpiData(packet,24);
-}
-/*****************************************************************************
- * Function:            SendEOF()
- * Description:         This function send End of File transfer frame
- *
- * @param               none
- * @return              none
- *****************************************************************************/
-static void SendEOF(void)
-{
-    uint8_t packet[24];
-  
-    packet[0] =BLE_SOF_CMD;
-    packet[1] =BLE_END_OF_FILE;
-    packet[2] =MAX_PAYLOAD_BYTES;
-    packet[3] ='E';
-    packet[4] ='O';
-    packet[5] ='F';    
-    memset(&packet[6], '@', 17);
-    packet[23]=BLE_EOT_CMD;               
-    WriteSpiData(packet,24);
-}
-
-/*****************************************************************************
- * Function:            SendFile()
- * Description:         This function receive the json file data and transmit 
-                        data over BLE 
- *
- * @param               json file data
- * @param               data length
- * @return              none
- *****************************************************************************/
-void BLE_FILE :: SendFile(uint8_t* json_file,uint8_t len)
-{
-    uint8_t num_writes,rem_bytes,start_index =0;   
-    
-    num_writes = ((len)/MAX_PAYLOAD_BYTES);
-    rem_bytes =((len)%MAX_PAYLOAD_BYTES);
-    /* Clearing the buffer to make sure that transmit buffer is empty*/
-    ClearBuffer();
-    
-    SendSOF();
-                       
-    for(int packets=0;packets<(num_writes);packets++)
-    {
-        BLE_INIT.SendBleData(&json_file[start_index], MAX_PAYLOAD_BYTES);
-        start_index= start_index+MAX_PAYLOAD_BYTES;
-    }
-    if(rem_bytes)
-    {
-        dummy_bytes = MAX_PAYLOAD_BYTES-rem_bytes;
-        memcpy(temp_buf,&json_file[start_index],rem_bytes);
-        /*Filling the remaining bytes with characcter '@' */
-        memset(&temp_buf[rem_bytes],'@',dummy_bytes);
-        BLE_INIT.SendBleData(temp_buf, MAX_PAYLOAD_BYTES);       
-    }
-           
-    SendEOF();    
-
-}
-
-
-/******************************************************************************/
-/* END OF FILE                                                                */
-/******************************************************************************/
\ No newline at end of file
--- a/ICE-Application/src/add-ons/BLE/src/ble_msg_handler.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    ble_uart.cpp
-  * @author  Happiesstminds Firmware Team
-  * @version v1.0
-  * @date    4-Oct-2016
-  * @brief   
-  *
-  ******************************************************************************
-  * @attention
-  *  
-  *
-  ******************************************************************************
-  */
-
-/******************************************************************************/
-/* Include Files*/
-/******************************************************************************/
-
-#include "mbed.h"
-#include "ble_msg_handler.h"
-#include "ble_spi.h"
-#include "ble_main.h"
-#include "LoggerApi.h"
-/******************************************************************************/
-/* Defines                                                                    */
-/******************************************************************************/
-#define BLE_MAX_FILE_SIZE 500
-#define HEADER_LENGTH 5
-volatile bool isDeviceConnected;
-static ble_data_ready_callback_t data_ready_cb;
-
-/******************************************************************************
- * Function:            BLE data receive callback
- * Description:         Function used to register ble data receive callback 
- *
- * @param               ble_data_ready_callback_t
- * @return              none
- *****************************************************************************/
-void BleDataRxCbRegister(ble_data_ready_callback_t data_rx_callback)
-{
-    data_ready_cb = data_rx_callback;
-}
-
-/*****************************************************************************
- * Function:            ProcessBleRxEvents()
- * Description:         Process BLE data 
- *
- * @param               spi_rcv_array
- * @return              none
- *****************************************************************************/
-void ProcessBleRxEvents(uint8_t *spi_rcv_array)
-{
-    static bool file_receiving_flag = false;
-    static uint8_t json_array[BLE_MAX_FILE_SIZE];
-    static uint16_t file_index,file_size;
-    
-    if(spi_rcv_array !=NULL)
-    {
-        if (spi_rcv_array[0] == BLE_SOF_CMD) {
-            switch (spi_rcv_array[1])
-            {
-                case BLE_CONNECTION_EVNT_CMD:
-                    printf("Mobile device connected...\n\r");
-                    isDeviceConnected =true;
-                    DeviceConnectedLoggerApi(isDeviceConnected);
-                    break;
-                    
-                case BLE_REC_DATA_CMD:
-                                    
-                    if(file_receiving_flag ==true)
-                    {
-                        /*reassembling packets */
-                        memcpy(&json_array[file_index],&spi_rcv_array[3], (spi_rcv_array[2]-HEADER_LENGTH));
-    
-                        file_index+= (spi_rcv_array[2]-HEADER_LENGTH);    //((spi_rcv_array[2]-5) contains packet length excluding headers                    
-                        if(file_index > file_size)
-                        {
-                            data_ready_cb(json_array, file_size);
-                            file_index =0;
-                            file_size =0;
-                            file_receiving_flag = false;
-                        }   
-                    }                
-                    break;
-                    
-                case BLE_DISCONNECTION_EVNT_CMD:
-                    printf("Mobile device disconnected...\n\r");
-                    isDeviceConnected =false;
-                    DeviceConnectedLoggerApi(isDeviceConnected);
-                    break;
-                    
-                case BLE_START_OF_FILE:            
-    
-                    file_index =0;
-                    file_receiving_flag = true;
-                    
-                    /*extract the json string length from SOF. */           
-                    file_size = ((spi_rcv_array[3]<<8)|spi_rcv_array[4]);
-                    printf("Received file size is %d \n\r",file_size);
-                    if(file_size>BLE_MAX_FILE_SIZE)
-                    {
-                        printf("Received file larger than buffer (len=%d)\r\n", BLE_MAX_FILE_SIZE );
-                        file_receiving_flag = false;
-                        file_size =0;
-                    }
-                       
-                    break;
-                    
-                case BLE_END_OF_FILE:                
-                    /* Reset the File Parameters.Currently not using */
-                    file_receiving_flag = false;
-                    break;  
-                      
-                default:
-                    printf("Unknown ID\n\r");
-                    break;            
-            }
-        } else {
-            printf("SOF not found\n\r");
-        }
-    }
-}
-
-/******************************************************************************/
-/* END OF FILE                                                                */
-/******************************************************************************/
--- a/ICE-Application/src/add-ons/BLE/src/ble_spi.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    ble_uart.cpp
-  * @author  Happiesstminds Firmware Team
-  * @version v1.0
-  * @date    4-Oct-2016
-  * @brief
-  *
-  ******************************************************************************
-  * @attention
-  *
-  *
-  ******************************************************************************
-  */
-
-/******************************************************************************/
-/* Include Files*/
-/******************************************************************************/
-#include "mbed.h"
-#include "ble_msg_handler.h"
-/******************************************************************************/
-/* Local Defines                                                              */
-/******************************************************************************/
-uint8_t rx_buf[24];
-//SPI spimaster(SPI1_MOSI, SPI1_MISO, SPI1_SCK);
-//DigitalOut cs(SPI1_CS);
-
-/******************************************************************************/
-/* Global Functions                                                           */
-/******************************************************************************/
-
-
-/*****************************************************************************
- * Function:            InitSpiMaster()
- * Description:         InitSpiMaster
- *
- * @param               None
- * @return              none
- *****************************************************************************/
-uint8_t InitSpiMaster(void)
-{
-    uint8_t status = SUCCESS;
-    // Chip must be deselected
-//    cs = 1;
-    // Setup the spi for 8 bit data, high steady state clock,
-    // second edge capture, with a 1MHz clock rate
-//    spimaster.format(8, 0);
-    // spimaster.frequency(1000000);
-//    spimaster.frequency(1000000);
-    return status;
-}
-
-/*****************************************************************************
- * Function:            WriteSpiData()
- * Description:         WriteSpiData
- *
- * @param               pointer to buffer
-  * @param              length
- * @return              none
- *****************************************************************************/
-uint8_t WriteSpiData(uint8_t * p_buffer, uint16_t length)
-{
-    uint8_t i;
-    uint8_t status = SUCCESS;
-//    int response;  //need to be removed
-    // Select the device by seting chip select low
-
-    for(i=0; i<length; i++) {
-//        cs = 0;
-//        response = spimaster.write(p_buffer[i]);
-//        cs = 1;
-        wait_us(600);
-    }
-
-    return status;
-}
-
-/*****************************************************************************
- * Function:            PollBLEEvents()
- * Description:         Polls for BLE events
- * @param               pointer to rx_buf
- * @return              none
- *****************************************************************************/
-
-uint8_t PollBLEEvents(void)
-{
-    uint8_t i =0;
-    uint8_t msg_len;
-
-//    cs = 0;
-//    rx_buf[0] = spimaster.write(0xAA);
-//    cs = 1;
-    wait_us(600);
-
-    if(rx_buf[0]==0x01) {
-//        cs = 0;
- //       rx_buf[1] = spimaster.write(0xAA);
-//        cs = 1;
-        wait_us(600);
-//        cs = 0;
-//        rx_buf[2] = spimaster.write(0xAA);
-//        cs = 1;
-        wait_us(600);
-
-        msg_len = rx_buf[2];
-        for(i = 3; i < msg_len; i++) {
-//            cs = 0;
-//            rx_buf[i] = spimaster.write(0xFF);
-//            cs = 1;
-            wait_us(600);
-        }
-
-        ProcessBleRxEvents(rx_buf);
-    }
-    return  rx_buf[0];
-}
-/******************************************************************************/
-/* END OF FILE                                                                */
-/******************************************************************************/
--- a/ICE-Application/src/add-ons/ConfigFS/ConfigFs.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-#include "ConfigFs.h"
-#include "mbed.h"
-#include "mfs.h"
-
-bool ConfigFs::saveUserFile(const char *filename, void *file_buf, int file_size)
-{
-//  printf("Writing filename=%s, size=%d\r\n", filename, file_size);
-    mfs fs0(0xA0);
-    fs0.createFile((char *)filename);
-    file *fp = new file(&fs0, (char *)filename, AWRITE);
-    fp->write((char *)file_buf, file_size);
-    if( fp->flush() != 0 ) {
-        printf("Flush Failed\r\n");
-    }
-    delete fp;
-    return true;
-}
-
-bool ConfigFs::readUserFile(const char *filename, void *file_buf, int file_size)
-{
-    mfs fs0(0xA0);
-//   printf("%s, len=%d\r\n", filename, strlen(filename));
-    file *fp = new file(&fs0, (char *)filename, AWRITE);
-    fp->read((char *)file_buf, file_size);
-    delete fp;
-//    printf("File Read: %s; bytes=%d, len=%d\n\r", (char *)file_buf, file_size, strlen((char *)file_buf));
-    return true;
-}
-
-bool ConfigFs::deleteUserFile(const char *filename)
-{
-    mfs fs0(0xA0);
-    fs0.removeFile((char *)filename);
-    return true;
-}
-
-std::vector<std::string> ConfigFs::listUserFiles()
-{
-    mfs fs0(0xA0);
-    unsigned int n;
-    char found_file[FILENAME_LENGTH];
-    std::vector<std::string> filelist;
-
-    n=0;
-    while (1) {
-        if (fs0.findNextFile(n, found_file, &n) == 0 ) {
-            filelist.push_back(found_file);
-        } else {
-            break; // Reach end of fs
-        }
-        n++;
-    }
-    return filelist;
-
-}
\ No newline at end of file
--- a/ICE-Application/src/add-ons/ConfigFS/ConfigFs.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-#ifndef CONFIGFS_H
-#define CONFIGFS_H
-
-#include <vector>
-#include <map>
-#include <string>
-
-class ConfigFs
-{
-public:
-    bool saveUserFile(const char *FileName, void *file_buf, int file_size);
-    bool readUserFile(const char *FileName, void *file_buf, int file_size);
-    bool deleteUserFile(const char *filename);
-    std::vector<std::string> listUserFiles();
-};
-
-#endif
\ No newline at end of file
--- a/ICE-Application/src/add-ons/ConfigFS/mfs.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,686 +0,0 @@
-/** @file mfs.cpp */
-/*CPP**************************************************************************
- * FILENAME :        mfs.cpp                                                  *
- *                                                                            *
- * DESCRIPTION :                                                              *
- *       mFS file system implementation for mBED with external I2C EEEPROM.   *
- *                                                                            *
- * AUTHOR :    Olli Vanhoja        START DATE :    2011-02-21                 *
- *****************************************************************************/
- 
-#include "mbed.h"
-#include "mfs.h"
-#include "i2c_eeprom.h"
- 
-#define BLOCK_LLEN 2        /**< Block number link length in bytes */
-#define RB 1+2*BLOCK_LLEN   /**< Reseved bytes per block (1 attrb B, 2 B for next/prev pointers */
-#define MFS_I2C_SPEED 100000    /**< I2C bus speed in Hz */
-#define DEBUG               /**< Adds extra safety in reading and writing */
-  
-mfs::mfs(int i2c_address)
-{
-    mem = new i2c_eeprom(i2c_address, MFS_I2C_SPEED);
-}
- 
-char mfs::read(char *data, uint32_t block, uint32_t byte, uint32_t n)
-{
-    // Faster reading without DEBUG mode
-    #ifdef DEBUG
-    if ((byte+n-1 >= BS))
-        return 1;
-    #endif
-    mem->read(BS*block+byte, n, data);
- 
-    return 0;
-}
- 
-char mfs::write(char *data, uint32_t block, uint32_t byte, uint32_t n)
-{
-    // Faster writing without DEBUG mode
-    #ifdef DEBUG
-    if (byte+n >= BS)
-        return 1;
-    #endif
-    mem->write(data, BS*block+byte, n);
-    
-    return 0;
-}
- 
-char mfs::getNextFreeBlock(uint32_t *blockOut)
-{    
-    // Locate free block by seeking EERPOM
-    char cFlags[1];
-    
-    for (*blockOut=0; *blockOut < BC; (*blockOut)++)
-    {
-        read(cFlags, *blockOut, 0, 1);
-        if (cFlags[0] == 0x04)
-            break;
-        if (*blockOut >= BC-1)
-            return 1;
-    }
-    
-    return 0;
-}
- 
-char mfs::findNextFile(uint32_t block, char *filenameOut, uint32_t *blockOut)
-{
-    uint32_t i=block;
-    char cFlags[1];
-    
-    while (i < BC)
-    {
-        read(cFlags, i, 0, 1);
-        
-        if ((cFlags[0] & 0x8C) == 0x8C)
-            break; // File found
-        else
-            i++;
-    }
-    
-    if(i == BC)
-    {
-        strcpy(filenameOut, "");
-        return 1; // Empty fs
-    }
-    
-    // Read filename
-    read(filenameOut, i, RB, FILENAME_LENGTH);
-    *blockOut = i; // Return block number
-    return 0;
-}
- 
-char mfs::getFirstBlockOfFile(char filename[FILENAME_LENGTH], uint32_t *blockOut)
-{
-    *blockOut=0;
-    char tmpFilename[FILENAME_LENGTH]="";
- 
-    while (1)
-    {
-        if (findNextFile(*blockOut, tmpFilename, blockOut) == 0)
-        {
-            if(strcmp(tmpFilename, filename) == 0)
-                return 0; // File exists
-        }
-        else return 1; // File doesn't exist
-        (*blockOut)++;
-    }
-}
- 
-char mfs::createFile(char filename[FILENAME_LENGTH])
-{
-    char tmpFilename[FILENAME_LENGTH];
-    uint32_t n;
-    uint32_t fb;
- 
-    for (n=0; n < BC; n++)
-    {
-        if(findNextFile(n, tmpFilename, &n) == 0)
-        {
-            if(strcmp(tmpFilename, filename) == 0)
-                return 1; // File exist
-        }
-        else break; // We already reached the edge of the universe
-        n++;
-    }
- 
-    if(getNextFreeBlock(&fb) != 0)
-        return 2; // Out of space
-    
-    char cData[RB+FILENAME_LENGTH+1];
-    cData[0] = '\xCC';   // Necessary flags for a file
-    cData[1] = '\0';     // No more blocks yet
-    cData[2] = '\0';
-    cData[3] = '\0';     // First block so there is no prev blocks
-    cData[4] = '\0';
-    cData[RB+FILENAME_LENGTH] = mEOF; // Set EOF at the begining
-    
-    for (char i=0; i < FILENAME_LENGTH; i++)
-        cData[RB+i] = filename[i];
-    
-    // Create file
-    write(cData, fb, 0, RB+FILENAME_LENGTH+1);
-        
-    return 0;
-}
- 
-char mfs::removeFile(char filename[FILENAME_LENGTH])
-{
-    uint32_t block;
-    char cData[RB-BLOCK_LLEN];
-    char cDataNew[RB] = {'\x04', '\0', '\0', '\0', '\0'};
-    uint32_t i=0;
- 
-    // Check if file exists
-    if (getFirstBlockOfFile(filename, &block) != 0)
-        return 1; // File not found
-    
-    read(cData, block, 0, RB-BLOCK_LLEN);
-    
-    // Check credentials
-     if (((cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3) & 0x04) != 0)
-        return 2; // RO file
-    
-    // Clear blocks reserved by the file    
-    while(1)
-    {
-        write(cDataNew, block, 0, RB);
-        if ((cData[0] & 0x4C) == 0x4C)
-            break; // End of file found
-        else block = (uint32_t)(cData[1])<<8|cData[2]; // Set next block number
-        i++;
-        if (i > BC)
-            return 1; // fs is corrupted
-        read(cData, block, 0, RB-BLOCK_LLEN);
-    }
-    
-    return 0; // Everything went better than expected
-}
- 
-char mfs::renameFile(char oldFilename[FILENAME_LENGTH], char newFilename[FILENAME_LENGTH])
-{
-    uint32_t block;
-    char cData[1];
- 
-    // Check if file exists
-    if (getFirstBlockOfFile(oldFilename, &block) != 0)
-        return 1; // File not found
-    
-    // Check credentials
-    read(cData, block, 0, 1);
-     char flags = (cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3);
-     if ((flags & 0x04) != 0)
-        return 2; // RO file
-    
-    write(newFilename, block, RB, FILENAME_LENGTH);
-    
-    return 0; // Everything went better than expected
-}
- 
-char mfs::setFileFlags(char *flags, char filename[FILENAME_LENGTH])
-{
-    /* RO|HIDDEN|LOCK  *
-     * H            L */
-    
-    uint32_t n;
-    char cData[1] = {'\0'};
-    char cFlags;
- 
-    // Check if file exists
-    if (getFirstBlockOfFile(filename, &n) != 0)
-        return 1; // File not found
-    
-    read(cData, n, 0, 1);
-    cFlags    = ((flags[0] & 0x01)|((flags[0] & 0x02) << 3)|((flags[0] & 0x04) << 3));
-    cData[0]  = cData[0] & (~0x31) | cFlags;
-    write(cData, n, 0, 1);
-    
-    return 0;
-}
- 
-char mfs::getFileFlags(char *flags, char filename[FILENAME_LENGTH])
-{
-    /* RO|HIDDEN|LOCK  *
-     * H            L */
-    
-    uint32_t n;
-    char cData[1] = {'\0'};
- 
-    // Check if file exists
-    if (getFirstBlockOfFile(filename, &n) != 0)
-        return 1; // File not found
-    
-    read(cData, n, 0, 1);
-    flags[0] = (cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3);
-    
-    return 0;
-}
- 
-// Return number of free blocks
-uint32_t mfs::free()
-{
-    uint32_t blocks=0;
-    uint32_t r;
-    char cFlags[1];
-    
-    for (r=0; r < BC; r++)
-    {
-        read(cFlags, r, 0, 1);
-        if (cFlags[0] == 0x04)
-            blocks++;
-        if (r >= BC-1)
-            return blocks;
-    }
-    
-    return 0;
-}
- 
-uint32_t mfs::mkfs(bool createLabel)
-{
-    uint32_t iAddr = 0;
-    uint32_t i = 0;
-    uint32_t bad = 0; // For counting bad block headers
-    char cFlags[RB] = {'\0', '\0', '\0', '\0', '\0'}, o[1];
-    
-    if (createLabel == true)
-    {
-        // Write Volume label
-        cFlags[0] = '\x0E';
-        mem->write(cFlags, iAddr, RB);
-        iAddr = BS;
-        i = 1;
-    }
-    
-    cFlags[0] = '\x04';
-    for (; i < BC; i++)
-    {
-        mem->write(cFlags, iAddr, RB);
-        mem->read(iAddr, 1, o);
-        if (o[0] != cFlags[0])
-            bad++;
-        iAddr += BS;
-    }
-    
-    return bad;
-}
- 
-file::file(mfs *fs_ref, char filename[FILENAME_LENGTH], FileOpenMode operation)
-{
-    fMode = operation;
-    
-    fs = fs_ref; // Don't forget this :)
-    
-    uint32_t n;
-    char cData[1] = {'\0'};
- 
-    // Check if file exists
-    if (fs->getFirstBlockOfFile(filename, &n) != 0)
-        error("Oops, file \"%s\" not found! n=0x%X", filename, n); // File not found
-    
-    fs->read(cData, n, 0, 1);
-    char flags = (cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3);
-    
-    if ((fMode != RO) && ((flags & 0x04) != 0))
-        error("Oops, cant open in RW mode!");
- 
-    // Store FBOF number
-    firstBlock = n;
-    currBlock = n;
-    blockPos = RB+FILENAME_LENGTH; // skip flags + pointers + filename
-    byteCount = 0; // First byte of the file
- 
-    // Initialize buffer
-    for (unsigned int i=0; i < BUF; i++)
-        buffer[i] = '\0';
-    bufPos = 0;
-}
- 
-file::~file()
-{
-    flush();
-}
- 
-char file::getBlockLink(BlockLinkType linkSelection, uint32_t *blockOut)
-{
-    char cData[1+BLOCK_LLEN];
- 
-    if (linkSelection == NEXT)
-    {
-        // Fetch link to next block
-        fs->read(cData, currBlock, 0, 1+BLOCK_LLEN);
-        if ((cData[0] & 0x40) == 0)
-        {
-            *blockOut  = ((uint32_t)(cData[1])) << 8; // Hbyte of next block link
-            *blockOut |= (uint32_t)cData[2];          // Lbyte of next block link
-            return 0;
-        } else return 1; // Already at last block
-    } else if (linkSelection == PREV)
-    {
-        if (currBlock != firstBlock)
-        {
-            fs->read(cData, currBlock, 1+BLOCK_LLEN, BLOCK_LLEN);
-            *blockOut  = ((uint32_t)(cData[0])) << 8; // Hbyte of next block link
-            *blockOut |= (uint32_t)cData[1];          // Lbyte of next block link
-            return 0;
-        } else return 1; // Already at first block
-    }
-    
-    return 0;
-}
- 
-char file::removeFollowingBlocks(uint32_t block)
-{
-    char cData[RB-BLOCK_LLEN];
-    char cDataNew[RB] = {'\x04', '\0', '\0', '\0', '\0'};
-    uint32_t i=0;
-    
-    while(1)
-    {
-        fs->read(cData, block, 0, RB-BLOCK_LLEN);
-        fs->write(cDataNew, block, 0, RB);
-        if ((cData[0] & 0x4C) == 0x4C)
-            break; // End of file found
-        else block = (uint32_t)(cData[0])<<8|cData[1]; // Set next block number
-        i++;
-        if (i > BC)
-            return 1; // fs is corrupted
-    }
-    
-    return 0;
-}
- 
-void file::rewind()
-{
-    flush();
-    currBlock = firstBlock;
-    blockPos = RB+FILENAME_LENGTH; // skip flags & pointers + filename
-    byteCount = 0;
-}
- 
-char file::rewind(uint32_t n)
-{
-    uint32_t i;
-    uint32_t block;
-    uint32_t varBlockOffset;
-    
-    flush(); // Check if flush is needed
-    
-    for (i=0; i < n; i++)
-    {
-        blockPos--;
-        byteCount--;
-    
-        // Change Block?
-        if (blockPos == firstBlock)
-            varBlockOffset = RB+FILENAME_LENGTH;
-        else
-            varBlockOffset = RB;
-        if ((blockPos < varBlockOffset) && (currBlock > firstBlock))
-        {
-            // Fetch link to previous block
-            if(getBlockLink(PREV, &block) == 0)
-            {
-                currBlock = block;
-                blockPos  = BS-1; // blockPos should be set at the end of block
-            } else {
-                blockPos++;
-                byteCount++;
-                return 1; // This is the first block and byte
-            }
-        }
-    }
-    
-    return 0; // OK
-}
- 
-char file::forward()
-{
-    return forward(1);
-}
- 
-char file::forward(uint32_t n)
-{
-    uint32_t i;
-    uint32_t block; // Next block number
-    char cData[1];
- 
-    flush(); // Check if flush is needed
-    
-    for (i=0; i < n; i++)
-    {
-        // If this is empty file EOF will be at first byte
-        fs->read(cData, currBlock, blockPos, 1);
-        if (cData[0] == mEOF)
-        {
-            return 1;
-        }
-        
-        blockPos++;
-        byteCount++;
-    
-        // Change Block?
-        if (blockPos >= BS)
-        {
-            // Fetch link to next block
-            if (getBlockLink(NEXT, &block) == 0)
-            {
-                currBlock = block;
-                blockPos = RB; // Reset block position offset
-            } else {
-                blockPos--;
-                byteCount--;
-                return 1; // This is the last block & byte
-            }
-        }
-        fs->read(cData, currBlock, blockPos, 1);
-        if (cData[0] == mEOF)
-        {
-            rewind(1); // Get back to the byte before EOF
-            return 1;
-        }
-    }
-    
-    return 0; // OK
-}
- 
-char file::seek(uint32_t byte)
-{
-    if (byte > byteCount)
-        return forward(byte-byteCount);
-    else if (byte < byteCount)
-        return rewind(byteCount-byte);
-    else return 0;
-}
- 
-// Respects mEOF and automatically sets '\0' at the end of string
-void file::read(char *data, uint32_t n)
-{
-    uint32_t i;
-    uint32_t block;
-    char cData[1];
-    
-    if( flush() != 0 ) {
-        printf("(%s:%d): flush failed\r\n", __func__, __LINE__);
-    }
-    
-    for (i=0; i < n; i++)
-    {
-        // Change block?
-        if (blockPos >= BS-1)
-        {
-//            printf("(%s:%d): pos=%d, BS-1=%d\r\n", __func__, __LINE__, blockPos, BS-1);
-            // Fetch link to next block
-            if (getBlockLink(NEXT, &block) == 0)
-            {
-                currBlock = block;
-                blockPos  = RB; // Reset block position offset
-            } else goto stop;
-        }
-        
-        // Read data
-    
-        fs->read(cData, currBlock, blockPos, 1);
-        if (cData[0] == mEOF)
-        {
-//      printf("(%s:%d): Found EOF: currBlock=%d, blockPos=%d\r\n", __func__, __LINE__, currBlock, blockPos);
-            stop:
-            data[i]='\0';
-            return;
-        } else {
-            data[i] = cData[0];
-//      printf("(%s:%d): blk=%d, pos=%d, char=%c\r\n", __func__, __LINE__, currBlock, blockPos, data[i]);
-            blockPos++;
-            byteCount++;
-        }
-    }
-    if (data[n-1] != '\0') {
-    printf("(%s:%d): Adding NULL\r\n", __func__, __LINE__ );
-        data[n-1] = '\0';
-    }
-}
- 
-// Ignores mEOF and doesn't set '\0' markings
-void file::readBin(char *data, uint32_t n)
-{
-    uint32_t i;
-    uint32_t block;
-    char cData[1];
-    
-    for (i=0; i < n; i++)
-    {
-        // Change block?
-        if (blockPos == BS-1)
-        {
-            // Fetch link to next block
-            if (getBlockLink(NEXT, &block) == 0)
-            {
-                currBlock = block;
-                blockPos = RB; // Reset block position offset
-            } else return;
-        }
-        
-        // Read data
-        fs->read(cData, currBlock, blockPos, 1);
-        data[i] = cData[0];
-        
-        blockPos++;
-        byteCount++;
-    }
-}
- 
-// Always binary
-char file::write(char *data, uint32_t n)
-{
-    if (fMode == RO) return 1;
-    
-    for (uint32_t i=0; i < n; i++)
-    {
-        // write to the buffer
-        buffer[bufPos] = data[i];
-        bufPos++;
-        
-        // If the buffer is full then flush
-        if(bufPos == BUF)
-        {
-        printf("(%s:%d): flushing buffer: bufPos=%d\r\n", __func__, __LINE__, bufPos);
-            if(flush() != 0);
-                return 1; // Flush failed
-        }
-    }
-    
-    return 0;
-}
- 
-char file::flush()
-{
-    char cData[RB], cDataOB[RB-BLOCK_LLEN], c[1];
-    uint32_t nextFree;
-    uint32_t i;
-    uint32_t leftSpaceEOF;
-    
-    bool destructiveFlag = false; // Set this true if there is any data to be removed
-    uint32_t destructiveBlock=0;  // First block to be removed by DWRITE
-    
-    static bool fEOFow = false;   /* END of file found while appending (and overwritten).
-                                     Must be static because we don't want to found many EOF's. */
-    
-    
-    if (bufPos == 0) return 0; // File up-to date
-    if (fMode == RO) return 1;
-    
-    for (i=0; i <= bufPos; i++)
-    {
-     if( blockPos == 255 )
-     {
-//       printf("%s:%d:\r\n",__func__, __LINE__);
-     }
-
-        // Change Block?
-        if ((bufPos - i) == 1)
-            leftSpaceEOF = 1;
-        else
-            leftSpaceEOF = 0;
-        if (blockPos+1 >= BS-leftSpaceEOF)
-        {
-//      printf("(%s:%d): fetching unused block: currBlock=%d, blockPos=%d, bufPos=%d\r\n", __func__, __LINE__, currBlock, blockPos, bufPos );
-            // Fetch new unused block number
-            if(fs->getNextFreeBlock(&nextFree) != 0)
-                return 2; // No free space left
-            
-            // Read flags from current block
-            fs->read(cDataOB, currBlock, 0, RB-BLOCK_LLEN);
-            
-            /* If destructive write is set then check if there is something
-               to be marked for removal */
-            if (((cDataOB[0] & 0x40) != 0x40) && (fMode == DWRITE))
-            {
-                destructiveFlag = true;
-                destructiveBlock = (uint32_t)cDataOB[1]<<8|cDataOB[2];
-//          printf("(%s:%d): destructive flag set: currBlock=%d, blockPos=%d, bufPos=%d\r\n", __func__, __LINE__, currBlock, blockPos, bufPos );
-                goto allocate_new_block;
-            } else if ((cDataOB[0] & 0x40) != 0x40) // fMode == AWRITE
-            {
-                // Update current block info
-                currBlock = (uint32_t)cDataOB[1]<<8|cDataOB[2];
-                blockPos  = RB; // Reset block position offset
-//          printf("(%s:%d): resetting block position: currBlock=%d, blockPos=%d, bufPos=%d\r\n", __func__, __LINE__, currBlock, blockPos, bufPos );
-            } else // There is no block to append so we allocate a new one
-            {
-                allocate_new_block:
-                // Allocate new block for use
-                cData[0] = 0x4C;                              // New flags
-                cData[1] = '\0';                              // Hbyte of Next Block link
-                cData[2] = '\0';                              // Lbyte of Next Block link
-                cData[3] = (char)((currBlock & 0xff00) >> 8); // Hbyte of Prev Block link
-                cData[4] = (char)(currBlock & 0x00ff);        // Lbyte of Prev Block link
-                fs->write(cData, nextFree, 0, RB);            // Update Block Data
-            
-                // Link old block with new block
-                cDataOB[0] &= ~0x40;                             // Clear LBOF flag if set
-                cDataOB[1]  = (char)((nextFree & 0xff00) >> 8);  // Hbyte of Next Block link
-                cDataOB[2]  = (char)(nextFree & 0x00ff);         // Lbyte of Next Block link
-                fs->write(cDataOB, currBlock, 0, RB-BLOCK_LLEN); // Update Block Data
-
-                // Update current block info
-                currBlock = nextFree;
-                blockPos  = RB; // Reset block position offset
-
-//          printf("(%s:%d): allocating new block: currBlock=%d, blockPos=%d, bufPos=%d\r\n", __func__, __LINE__, currBlock, blockPos, bufPos );
-            }
-        }
-        
-        if (fMode == AWRITE) // Check if EOF is here
-        {
-            fs->read(c, currBlock, blockPos, 1);
-            if ((c[0] == mEOF) && (fEOFow == false))
-                fEOFow = true;
-        }
-        
-        // Write file
-        c[0]=buffer[i];
-        fs->write(c, currBlock, blockPos, 1);
-//  printf("(%s:%d): blk=%d, pos=%d, char=%c\r\n", __func__, __LINE__, currBlock, blockPos, c[0] );
-        blockPos++;
-        byteCount++;
-        
-        // For fail safe, write EOF now
-        if ((fMode == DWRITE)||(fEOFow == true))
-        {
-          char fs_data[] = { mEOF };
-          fs->write(fs_data, currBlock, blockPos, 1); // Write mEOF
-//          printf("(%s:%d): Writing EOF, blk=%d, pos=%d, char=0x%x\r\n", __func__, __LINE__, currBlock, blockPos, fs_data[0] );
-        }
-    }
-    
-    bufPos = 0; // Reset buffer position counter
-    
-    /* If destructive write flag is set
-       and there is data to be removed then remove data now */
-    if (destructiveFlag == true) {
-        if(removeFollowingBlocks(destructiveBlock) != 0) {
-            return 3;
-        }
-    }
-        
-    return 0;
-}
--- a/ICE-Application/src/add-ons/ConfigFS/mfs.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,332 +0,0 @@
-/** @file mfs.h */
-/*H****************************************************************************
- * FILENAME :        mfs.h                                                    *
- *                                                                            *
- * DESCRIPTION :                                                              *
- *       mFS file system implementation for mBED with external I2C EEEPROM.   *
- *                                                                            *
- * ---------------------------------------------------------------------------*
- * "THE BEER-WARE LICENSE" (Revision 42):                                     *
- * <olli.vanhoja@gmail.com> wrote this file. As long as you retain this notice*
- * you can do whatever you want with this stuff. If we meet some day, and you *
- * think this stuff is worth it, you can buy me a beer in return Olli Vanhoja *
- * ---------------------------------------------------------------------------*
- *                                                                            *
- * 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.                                                  *
- *                                                                            *
- *                                                                            *
- * Block Flags:                                                               *
- * 7:FBOF      Begining of file                                               *
- * 6:LBOF      Last block of file                                             *
- * 5:RO        Read only file (Used only with FBOF)                           *
- * 4:HIDDEN    Hidden file (Used only with FBOF)                              *
- * 3:INUSE     Block in use                                                   *
- * 2:NBAD      Bad block (INV)                                                *
- * 1:VOL       Volume label (Used only with FBOF)                             *
- * 0:LOCK      Locked file (Used only with FBOF)                              *
- *                                                                            *
- * AUTHOR :         Olli Vanhoja       START DATE :    2011-02-18             *
- ******************************************************************************
- *
- * CHANGES :
- *
- * VERSION DATE       WHO            DETAIL
- * 0.1     2011-02-21 Olli Vanhoja   Initial release version
- * 0.2     2011-02-21 Olli Vanhoja   Documentational comments added
- * 0.3     2011-02-21 Olli Vanhoja   * File::read issues fixed, rewind/forward
- *                                     functions improved
- *                                   * Added possibility change I2C speed
- *                                   * I2C autoreset on failure
- * 0.4     2011-02-22 Olli Vanhoja   * mfs::renameFile(char [FILENAME_LENGTH], char [FILENAME_LENGTH] function added
- *                                   * Incresed fault tolerance by first allocating new
- *                                     block and then linking to it from previous block
- *                                   * Reconstructed initialization and use of some variables
- * 0.5     2011-02-22 Olli Vanhoja   * Improved documentation
- *                                   * Block variables changed from char to uint32_t for
- *                                     code optimization (and for possible 16bit update which
- *                                     would technically allow 256 TB volume sizes)
- *                                   * Optimized file searching algorithms
- * 0.6     2011-02-22 Olli Vanhoja   * Fixed file remove issue
- *                                   * Fixed mkfs bug
- * 0.7     2011-02-23 Olli Vanhoja   * file::seek(uint32_t) added
- * 0.7     2011-02-23 Olli Vanhoja   * Fixed destroying prev link issue on flush
- *                                   * Fixed Forwarding issue which moved cursor at the begining
- *                                     of the filename block
- *                                   * Separated locating of next/prev links functionality
- *                                     into its own private function
- *                                   * 16 bit block number pointers 256 TB theoretical maximum
- *                                     volume size, WHOA \O/
- *                                   * Remove and rename respects RO bit
- *                                   * SetFileFlags fixed
- *                                   * New file write mode DWRITE
- * 0.8     2011-02-24 Olli Vanhoja   * EOF should be now found in AWRITE mode and EOF is
- *                                   * also written by mfs::createFile() so there should
- *                                     be no more confusing situations with new files.
- *
- * TODO :
- *          * Directory support (VOL blocks?)
- *          * RAID 0 & 1
- *H*/
-
-#ifndef MFS_H
-#define MFS_H
-
-#include "i2c_eeprom.h"
-
-const unsigned int VOL_SIZE=65536; /**< EEPROM chip size in bytes */
-const unsigned int BS=256; /**< How many bytes per block (default: 256 bytes) */
-const unsigned int BC=VOL_SIZE / BS; // block count
-const char mEOF='\x01'; // End Of File/Section marked
-const unsigned int BUF=1050; /**< File buffer length */
-const unsigned int FILENAME_LENGTH=64;
-
-/** mFS File System class
- *
- * This class is used as a handle for the fs in use.
- */
-class mfs
-{
-private:
-    i2c_eeprom *mem; // Only 512 kB I2C EEPROM is supported ATM
-public:
-    /** Create a new file system object
-    *
-    * @param xi2c_address a Physical I2C address of the EEPROM chip
-    */
-    mfs(int i2c_address);
-
-    /** Read data from specified fs block
-    *
-    * @param *data Pointer for readed data
-    * @param block Block number.
-    * @param byte Selected byte.
-    * @param n Bytes to be read.
-    * @returns Error code: 0 = OK, 1 = Incorrect input
-    */
-    char read(char *data, uint32_t block, uint32_t byte, uint32_t n);
-
-    /** Write data to specified fs block
-    *
-    * @param *data Pointer for readed data
-    * @param block Block number.
-    * @param byte Selected byte.
-    * @param n Bytes to be read.
-    * @returns Error code: 0 = OK, 1 = Incorrect input
-    */
-    char write(char *data, uint32_t block, uint32_t byte, uint32_t n);
-
-    /** Locate next free block
-    *
-    * @param *blockOut Returns next free block from begining of the fs.
-    * @returns Error code: 0 = OK, 1 = Out of space
-    */
-    char getNextFreeBlock(uint32_t *blockOut);
-
-    /** Locates next starting file from parameter block
-    *
-    * @param block Start scanning from this block.
-    * @param *filenameOut Return name of the file found.
-    * @param Returns block number of the file found.
-    * @returns Error code: 0 = OK, 1 = Empty fs
-    */
-    char findNextFile(uint32_t block, char *filenameOut, uint32_t *blockOut);
-
-    /** Get block number of the given file
-    *
-    * Returns block number of the block flaged with FBOF flag.
-    *
-    * @param filename[FILENAME_LENGTH] Filename input.
-    * @param Returns block number of the first block of the given file.
-    * @returns Error code: 0 = OK, 1 = File not found
-    */
-    char getFirstBlockOfFile(char filename[FILENAME_LENGTH], uint32_t *blockOut);
-
-    /** Create a new empty file
-    *
-    * Reserves one block for the file created.
-    *
-    * @param filename[FILENAME_LENGTH] Filename input.
-    * @returns Error code: 0 = OK, 1 = File exists already, 2 = Out of space
-    */
-    char createFile(char filename[FILENAME_LENGTH]);
-
-    /** Remove a file from the file system
-    *
-    * @param filename[FILENAME_LENGTH] Filename input.
-    * @returns Error code: 0 = OK, 1 = File doesn't exists, 2 = RO file
-    */
-    char removeFile(char filename[FILENAME_LENGTH]);
-
-    /** Rename a file
-    *
-    * @param oldFilename[FILENAME_LENGTH] Old filename.
-    * @param newFilename[FILENAME_LENGTH] New file name.
-    * @returns Error code: 0 = OK, 1 = File doesn't exists, 2 = RO file, 3 = fs is corrupted
-    */
-    char renameFile(char oldFilename[FILENAME_LENGTH], char newFilename[FILENAME_LENGTH]);
-
-    /** Set user modifiable flags.
-    *
-    * \code
-    * desc RO|HIDDEN|LOCK
-    * bit  3    2       1
-    * \endcode
-    *
-    * @param *flags Flag input
-    * @param filename[FILENAME_LENGTH] Filename input.
-    * @returns Error code: 0 = OK, 1 = File doesn't exists, 2 = File system is corrupted
-    */
-    char setFileFlags(char *flags, char filename[FILENAME_LENGTH]);
-
-    /** Read user modifiable flags.
-    *
-    * \code
-    * desc RO|HIDDEN|LOCK
-    * bit  3    2       1
-    * \endcode
-    *
-    * @param *flags Flag output
-    * @param filename[FILENAME_LENGTH] Filename input.
-    * @returns Error code: 0 = OK, 1 = File doesn't exists
-    */
-    char getFileFlags(char *flags, char filename[FILENAME_LENGTH]);
-
-    /** Get number of free blocks
-    *
-    * @returns Number of free blocks.
-    */
-    uint32_t free();
-
-    /** Format new file system
-    *
-    * \note Keep in mind that only first byte is checked for functionality and
-    * if it's broken the who file system is useless.
-    *
-    * @param createLabel Create volume label at the begining of the file system. (there is no specified use for volume labels atm).
-    * @returns Number of bad block headers.
-    */
-    uint32_t mkfs(bool createLabel);
-};
-
-enum BlockLinkType {NEXT, PREV};
-enum FileOpenMode {RO, AWRITE, DWRITE};
-
-/** mFS File handle class
- *
- * This class provides a file handle and data manipulation methods to be
- * used for files stored in mFS files system.
- */
-class file
-{
-private:
-    mfs *fs;   // Reference to the file system in use
-    FileOpenMode fMode;
-    char buffer[BUF]; // Write buffer
-    uint32_t bufPos; // "Cursor" position in buffer
-    uint32_t firstBlock; // First block of the file
-    uint32_t currBlock; // Current block in use
-    uint32_t blockPos; // "head" position on the current block
-    uint32_t byteCount; // Stores current "cursor" position in file for seek
-    // Private functions
-    char getBlockLink(BlockLinkType linkSelection, uint32_t *blockOut);
-    char removeFollowingBlocks(uint32_t block); // Offers destructive write/very simple wear levelling
-public:
-    /** Create file handle
-    *
-    * \warning File must be created before it can be opened!
-    * Opening non-existing file will trip the system to error();
-    * If read only file is opened in rw mode system will trip to error().
-    *
-    * \b AWRITE is a file access mode where cursor can be moved along the file
-    * and write can be started at any point. write() function will overwrite
-    * only as many bytes as you chosen to write.
-    *
-    * \b DWRITE is a file access mode similiar to AWRITE but when you start
-    * writing all the data after cursor will be removed permanently and flush()
-    * will set a new EOF marker.
-    *
-    * @param filename[FILENAME_LENGTH] Filename input.
-    * @param operation RO = Read only, AWRITE = read and write, DWRITE = read + destructive write.
-    */
-    file(mfs *fs_ref, char filename[FILENAME_LENGTH], FileOpenMode operation);
-
-    /** Close file handle
-    *
-    * Flushes the file and closes the handle.
-    */
-    ~file(); // Close file handle and flush
-
-    /** Rewind to the start postion of the file
-    *
-    */
-    void rewind();
-
-    /** Reverse n bytes back
-    *
-    * @param n Number of bytes.
-    * @returns Error code: 0 = OK, 1 = First byte of file.
-    */
-    char rewind(uint32_t n);
-
-    /** Forward one byte
-    *
-    * @returns Error code: 0 = OK, 1 = End of file.
-    */
-    char forward();
-
-    /** Forward n bytes
-    *
-    * @param n Number of blocks.
-    * @returns Error code: 0 = OK, 1 = End of file.
-    */
-    char forward(uint32_t n);
-
-    /** Seek to byte given
-    *
-    * @param byte Byte number where to seek.
-    * @returns Error code: 0 = OK, 1 = End of file or already at first byte.
-    */
-    char seek(uint32_t byte);
-
-    /** Reads a string of bytes
-    *
-    * Always places '\0' at the end of string.
-    *
-    * @param data Output buffer.
-    * @param n Number of bytes to be read.
-    * @returns Error code. 0 = OK, 1 = Last block of the file
-    */
-    void read(char *data, uint32_t n);
-
-    /** Reads a binary array of bytes
-    *
-    * Doesn't add '\0' at the end of data array and doesn't respect mEOF byte.
-    *
-    * @param data Output buffer.
-    * @param n Number of bytes to be read.
-    */
-    void readBin(char *data, uint32_t n);
-
-    /** Write byte array to a file (buffer)
-    *
-    * @param data Input data.
-    * @param n Number of bytes to be read.
-    * @returns Error code: 0 = OK, 1 = Flush failed.
-    */
-    char write(char *data, uint32_t n);
-
-    /** Flush file buffer
-    * Writes buffer to the EEPROM chip in use.
-    *
-    * @returns Error code: 0 = OK, 1 = Out of free space, 2 = Destructive operation failed (fs is corrupted).
-    */
-    char flush();
-};
-
-#endif
--- a/ICE-Application/src/add-ons/ICELog/ICELog.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-#include "mbed.h"
-#include <stdarg.h>
-#include "ICELog.h"
- 
-//using namespace mts;
- 
-int ICELog::currentLevel = ICELog::WARNING_LEVEL;
- 
-const char* ICELog::NONE_LABEL = "NONE";
-const char* ICELog::FATAL_LABEL = "FATAL";
-const char* ICELog::ERROR_LABEL = "ERROR";
-const char* ICELog::WARNING_LABEL = "WARNING";
-const char* ICELog::INFO_LABEL = "INFO";
-const char* ICELog::DEBUG_LABEL = "DEBUG";
-const char* ICELog::TRACE_LABEL = "TRACE";
- 
-void ICELog::printMessage(int level, const char* format, ...) {
-    if (printable(level)) {
-        va_list argptr;
-        va_start(argptr, format);
-        vprintf(format, argptr);
-        va_end(argptr);
-    }
-}
- 
-bool ICELog::printable(int level) {
-    return level <= currentLevel;
-}
- 
-void ICELog::setLogLevel(int level) {
-    if (level < NONE_LEVEL)
-        currentLevel = NONE_LEVEL;
-    else if (level > TRACE_LEVEL)
-        currentLevel = TRACE_LEVEL;
-    else
-    currentLevel = level;
-}
- 
-int ICELog::getLogLevel() {
-    return currentLevel;
-}
- 
-const char* ICELog::getLogLevelString() {
-    switch (currentLevel) {
-        case NONE_LEVEL:
-            return NONE_LABEL;
-        case FATAL_LEVEL:
-            return FATAL_LABEL;
-        case ERROR_LEVEL:
-            return ERROR_LABEL;
-        case WARNING_LEVEL:
-            return WARNING_LABEL;
-        case INFO_LEVEL:
-            return INFO_LABEL;
-        case DEBUG_LEVEL:
-            return DEBUG_LABEL;
-        case TRACE_LEVEL:
-            return TRACE_LABEL;
-        default:
-            return "unknown";
-    }
-}
- 
\ No newline at end of file
--- a/ICE-Application/src/add-ons/ICELog/ICELog.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-#ifndef ICELOG_H
-#define ICELOG_H
-
-#include <string>
-
-inline const char* className(const std::string& prettyFunction)
-{
-    size_t colons = prettyFunction.find_last_of("::");
-    if (colons == std::string::npos)
-        return "";
-    size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1;
-    size_t end = colons - begin;
-
-    return prettyFunction.substr(begin,end).c_str();
-}
-
-#define __CLASSNAME__ className(__PRETTY_FUNCTION__)
-
-
-#ifdef MTS_DEBUG
-
-#define logFatal(format, ...) \
-    ICELog::printMessage(ICELog::FATAL_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, ICELog::FATAL_LABEL, ##__VA_ARGS__)
-#define logError(format, ...) \
-    ICELog::printMessage(ICELog::ERROR_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, ICELog::ERROR_LABEL, ##__VA_ARGS__)
-#define logWarning(format, ...) \
-    ICELog::printMessage(ICELog::WARNING_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, ICELog::WARNING_LABEL, ##__VA_ARGS__)
-#define logInfo(format, ...) \
-    ICELog::printMessage(ICELog::INFO_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, ICELog::INFO_LABEL, ##__VA_ARGS__)
-#define logDebug(format, ...) \
-    ICELog::printMessage(ICELog::DEBUG_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, ICELog::DEBUG_LABEL, ##__VA_ARGS__)
-#define logTrace(format, ...) \
-    ICELog::printMessage(ICELog::TRACE_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, ICELog::TRACE_LABEL, ##__VA_ARGS__)
-      
-#else
-      
-#define logFatal(format, ...) \
-    ICELog::printMessage(ICELog::FATAL_LEVEL, "[%s] " format "\r\n", ICELog::FATAL_LABEL, ##__VA_ARGS__)
-#define logError(format, ...) \
-    ICELog::printMessage(ICELog::ERROR_LEVEL, "[%s] " format "\r\n", ICELog::ERROR_LABEL, ##__VA_ARGS__)
-#define logWarning(format, ...) \
-    ICELog::printMessage(ICELog::WARNING_LEVEL, "[%s] " format "\r\n", ICELog::WARNING_LABEL, ##__VA_ARGS__)
-#define logInfo(format, ...) \
-    ICELog::printMessage(ICELog::INFO_LEVEL, "[%s] " format "\r\n", ICELog::INFO_LABEL, ##__VA_ARGS__)
-#define logDebug(format, ...) \
-    ICELog::printMessage(ICELog::DEBUG_LEVEL, "[%s] " format "\r\n", ICELog::DEBUG_LABEL, ##__VA_ARGS__)
-#define logTrace(format, ...) \
-    ICELog::printMessage(ICELog::TRACE_LEVEL, "[%s] " format "\r\n", ICELog::TRACE_LABEL, ##__VA_ARGS__)
-      
-#endif // MTS_DEBUG 
-
-class ICELog
-{
-public:
-
-    /** Enum of log levels.
-     */
-    enum logLevel {
-        NONE_LEVEL = 0,
-        FATAL_LEVEL = 1,
-        ERROR_LEVEL = 2,
-        WARNING_LEVEL = 3,
-        INFO_LEVEL = 4,
-        DEBUG_LEVEL = 5,
-        TRACE_LEVEL = 6
-    };
-
-    /** Print log message.
-     */
-    static void printMessage(int level, const char* format, ...);
-
-    /** Determine if the given level is currently printable.
-     */
-    static bool printable(int level);
-
-    /** Set log level
-     * Messages with lower priority than the current level will not be printed.
-     * If the level is set to NONE, no messages will print.
-     */
-    static void setLogLevel(int level);
-
-    /** Get the current log level.
-     */
-    static int getLogLevel();
-
-    /** Get string representation of the current log level.
-     */
-    static const char* getLogLevelString();
-
-    static const char* NONE_LABEL;
-    static const char* FATAL_LABEL;
-    static const char* ERROR_LABEL;
-    static const char* WARNING_LABEL;
-    static const char* INFO_LABEL;
-    static const char* DEBUG_LABEL;
-    static const char* TRACE_LABEL;
-    
-    ICELog() {}
-    
-private:
-    static int currentLevel;
-    //ICELog();
-};
-
-#endif
--- a/ICE-Application/src/add-ons/NaturalTinyShell.lib	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-https://developer.mbed.org/users/jmarkel44/code/NaturalTinyShell/#2cafac575f61
--- a/ICE-Application/src/add-ons/cJSON/cJSON.c	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,752 +0,0 @@
-
-/*
-  Copyright (c) 2009 Dave Gamble
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-  The above copyright notice and this permission notice shall be included in
-  all copies or substantial portions of the Software.
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-  THE SOFTWARE.
-*/
-
-/* cJSON */
-/* JSON parser in C. */
-
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-#include <stdlib.h>
-#include <float.h>
-#include <limits.h>
-#include <ctype.h>
-#include "cJSON.h"
-
-static const char *global_ep;
-
-const char *cJSON_GetErrorPtr(void) {return global_ep;}
-
-static int cJSON_strcasecmp(const char *s1,const char *s2)
-{
-    if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
-    for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0)    return 0;
-    return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
-}
-
-static void *(*cJSON_malloc)(size_t sz) = malloc;
-static void (*cJSON_free)(void *ptr) = free;
-
-static char* cJSON_strdup(const char* str)
-{
-      size_t len;
-      char* copy;
-
-      len = strlen(str) + 1;
-      if (!(copy = (char*)cJSON_malloc(len))) return 0;
-      memcpy(copy,str,len);
-      return copy;
-}
-
-void cJSON_InitHooks(cJSON_Hooks* hooks)
-{
-    if (!hooks) { /* Reset hooks */
-        cJSON_malloc = malloc;
-        cJSON_free = free;
-        return;
-    }
-
-    cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
-    cJSON_free   = (hooks->free_fn)?hooks->free_fn:free;
-}
-
-/* Internal constructor. */
-static cJSON *cJSON_New_Item(void)
-{
-    cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
-    if (node) memset(node,0,sizeof(cJSON));
-    return node;
-}
-
-/* Delete a cJSON structure. */
-void cJSON_Delete(cJSON *c)
-{
-    cJSON *next;
-    while (c)
-    {
-        next=c->next;
-        if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
-        if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
-        if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string);
-        cJSON_free(c);
-        c=next;
-    }
-}
-
-/* Parse the input text to generate a number, and populate the result into item. */
-static const char *parse_number(cJSON *item,const char *num)
-{
-    double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
-
-    if (*num=='-') sign=-1,num++;   /* Has sign? */
-    if (*num=='0') num++;           /* is zero */
-    if (*num>='1' && *num<='9') do  n=(n*10.0)+(*num++ -'0');   while (*num>='0' && *num<='9'); /* Number? */
-    if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;        do  n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}  /* Fractional part? */
-    if (*num=='e' || *num=='E')     /* Exponent? */
-    {   num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++;      /* With sign? */
-        while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');   /* Number? */
-    }
-
-    n=sign*n*pow(10.0,(scale+subscale*signsubscale));   /* number = +/- number.fraction * 10^+/- exponent */
-    
-    item->valuedouble=n;
-    item->valueint=(int)n;
-    item->type=cJSON_Number;
-    return num;
-}
-
-static int pow2gt (int x)   {   --x;    x|=x>>1;    x|=x>>2;    x|=x>>4;    x|=x>>8;    x|=x>>16;   return x+1; }
-
-typedef struct {char *buffer; int length; int offset; } printbuffer;
-
-static char* ensure(printbuffer *p,int needed)
-{
-    char *newbuffer;int newsize;
-    if (!p || !p->buffer) return 0;
-    needed+=p->offset;
-    if (needed<=p->length) return p->buffer+p->offset;
-
-    newsize=pow2gt(needed);
-    newbuffer=(char*)cJSON_malloc(newsize);
-    if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;}
-    if (newbuffer) memcpy(newbuffer,p->buffer,p->length);
-    cJSON_free(p->buffer);
-    p->length=newsize;
-    p->buffer=newbuffer;
-    return newbuffer+p->offset;
-}
-
-static int update(printbuffer *p)
-{
-    char *str;
-    if (!p || !p->buffer) return 0;
-    str=p->buffer+p->offset;
-    return p->offset+strlen(str);
-}
-
-/* Render the number nicely from the given item into a string. */
-static char *print_number(cJSON *item,printbuffer *p)
-{
-    char *str=0;
-    double d=item->valuedouble;
-    if (d==0)
-    {
-        if (p)  str=ensure(p,2);
-        else    str=(char*)cJSON_malloc(2); /* special case for 0. */
-        if (str) strcpy(str,"0");
-    }
-    else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
-    {
-        if (p)  str=ensure(p,21);
-        else    str=(char*)cJSON_malloc(21);    /* 2^64+1 can be represented in 21 chars. */
-        if (str)    sprintf(str,"%d",item->valueint);
-    }
-    else
-    {
-        if (p)  str=ensure(p,64);
-        else    str=(char*)cJSON_malloc(64);    /* This is a nice tradeoff. */
-        if (str)
-        {
-            if (d*0!=0)                                                 sprintf(str,"null");    /* This checks for NaN and Infinity */
-            else if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)   sprintf(str,"%.0f",d);
-            else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)                   sprintf(str,"%e",d);
-            else                                                        sprintf(str,"%f",d);
-        }
-    }
-    return str;
-}
-
-static unsigned parse_hex4(const char *str)
-{
-    unsigned h=0;
-    if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
-    h=h<<4;str++;
-    if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
-    h=h<<4;str++;
-    if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
-    h=h<<4;str++;
-    if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
-    return h;
-}
-
-/* Parse the input text into an unescaped cstring, and populate item. */
-static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-static const char *parse_string(cJSON *item,const char *str,const char **ep)
-{
-    const char *ptr=str+1,*end_ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
-    if (*str!='\"') {*ep=str;return 0;} /* not a string! */
-    
-    while (*end_ptr!='\"' && *end_ptr && ++len) if (*end_ptr++ == '\\') end_ptr++;  /* Skip escaped quotes. */
-    
-    out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
-    if (!out) return 0;
-    item->valuestring=out; /* assign here so out will be deleted during cJSON_Delete() later */
-    item->type=cJSON_String;
-    
-    ptr=str+1;ptr2=out;
-    while (ptr < end_ptr)
-    {
-        if (*ptr!='\\') *ptr2++=*ptr++;
-        else
-        {
-            ptr++;
-            switch (*ptr)
-            {
-                case 'b': *ptr2++='\b'; break;
-                case 'f': *ptr2++='\f'; break;
-                case 'n': *ptr2++='\n'; break;
-                case 'r': *ptr2++='\r'; break;
-                case 't': *ptr2++='\t'; break;
-                case 'u':    /* transcode utf16 to utf8. */
-                    uc=parse_hex4(ptr+1);ptr+=4;    /* get the unicode char. */
-                    if (ptr >= end_ptr) {*ep=str;return 0;} /* invalid */
-                    
-                    if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)    {*ep=str;return 0;} /* check for invalid.   */
-                    
-                    if (uc>=0xD800 && uc<=0xDBFF)   /* UTF16 surrogate pairs.   */
-                    {
-                        if (ptr+6 > end_ptr)    {*ep=str;return 0;} /* invalid */
-                        if (ptr[1]!='\\' || ptr[2]!='u')    {*ep=str;return 0;} /* missing second-half of surrogate.    */
-                        uc2=parse_hex4(ptr+3);ptr+=6;
-                        if (uc2<0xDC00 || uc2>0xDFFF)       {*ep=str;return 0;} /* invalid second-half of surrogate.    */
-                        uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
-                    }
-
-                    len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
-                    
-                    switch (len) {
-                        case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
-                        case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
-                        case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
-                        case 1: *--ptr2 =(uc | firstByteMark[len]);
-                    }
-                    ptr2+=len;
-                    break;
-                default:  *ptr2++=*ptr; break;
-            }
-            ptr++;
-        }
-    }
-    *ptr2=0;
-    if (*ptr=='\"') ptr++;
-    return ptr;
-}
-
-/* Render the cstring provided to an escaped version that can be printed. */
-static char *print_string_ptr(const char *str,printbuffer *p)
-{
-    const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token;
-
-    if (!str)
-    {
-        if (p)  out=ensure(p,3);
-        else    out=(char*)cJSON_malloc(3);
-        if (!out) return 0;
-        strcpy(out,"\"\"");
-        return out;
-    }
-    
-    for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0;
-    if (!flag)
-    {
-        len=ptr-str;
-        if (p) out=ensure(p,len+3);
-        else        out=(char*)cJSON_malloc(len+3);
-        if (!out) return 0;
-        ptr2=out;*ptr2++='\"';
-        strcpy(ptr2,str);
-        ptr2[len]='\"';
-        ptr2[len+1]=0;
-        return out;
-    }
-    
-    ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
-    
-    if (p)  out=ensure(p,len+3);
-    else    out=(char*)cJSON_malloc(len+3);
-    if (!out) return 0;
-
-    ptr2=out;ptr=str;
-    *ptr2++='\"';
-    while (*ptr)
-    {
-        if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
-        else
-        {
-            *ptr2++='\\';
-            switch (token=*ptr++)
-            {
-                case '\\':  *ptr2++='\\';   break;
-                case '\"':  *ptr2++='\"';   break;
-                case '\b':  *ptr2++='b';    break;
-                case '\f':  *ptr2++='f';    break;
-                case '\n':  *ptr2++='n';    break;
-                case '\r':  *ptr2++='r';    break;
-                case '\t':  *ptr2++='t';    break;
-                default: sprintf(ptr2,"u%04x",token);ptr2+=5;   break;  /* escape and print */
-            }
-        }
-    }
-    *ptr2++='\"';*ptr2++=0;
-    return out;
-}
-/* Invote print_string_ptr (which is useful) on an item. */
-static char *print_string(cJSON *item,printbuffer *p)   {return print_string_ptr(item->valuestring,p);}
-
-/* Predeclare these prototypes. */
-static const char *parse_value(cJSON *item,const char *value,const char **ep);
-static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p);
-static const char *parse_array(cJSON *item,const char *value,const char **ep);
-static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p);
-static const char *parse_object(cJSON *item,const char *value,const char **ep);
-static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p);
-
-/* Utility to jump whitespace and cr/lf */
-static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
-
-/* Parse an object - create a new root, and populate. */
-cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
-{
-    const char *end=0,**ep=return_parse_end?return_parse_end:&global_ep;
-    cJSON *c=cJSON_New_Item();
-    *ep=0;
-    if (!c) return 0;       /* memory fail */
-
-    end=parse_value(c,skip(value),ep);
-    if (!end)   {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */
-
-    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
-    if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);*ep=end;return 0;}}
-    if (return_parse_end) *return_parse_end=end;
-    return c;
-}
-/* Default options for cJSON_Parse */
-cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
-
-/* Render a cJSON item/entity/structure to text. */
-char *cJSON_Print(cJSON *item)              {return print_value(item,0,1,0);}
-char *cJSON_PrintUnformatted(cJSON *item)   {return print_value(item,0,0,0);}
-
-char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt)
-{
-    printbuffer p;
-    p.buffer=(char*)cJSON_malloc(prebuffer);
-    p.length=prebuffer;
-    p.offset=0;
-    return print_value(item,0,fmt,&p);
-}
-
-
-/* Parser core - when encountering text, process appropriately. */
-static const char *parse_value(cJSON *item,const char *value,const char **ep)
-{
-    if (!value)                     return 0;   /* Fail on null. */
-    if (!strncmp(value,"null",4))   { item->type=cJSON_NULL;  return value+4; }
-    if (!strncmp(value,"false",5))  { item->type=cJSON_False; return value+5; }
-    if (!strncmp(value,"true",4))   { item->type=cJSON_True; item->valueint=1;  return value+4; }
-    if (*value=='\"')               { return parse_string(item,value,ep); }
-    if (*value=='-' || (*value>='0' && *value<='9'))    { return parse_number(item,value); }
-    if (*value=='[')                { return parse_array(item,value,ep); }
-    if (*value=='{')                { return parse_object(item,value,ep); }
-
-    *ep=value;return 0; /* failure. */
-}
-
-/* Render a value to text. */
-static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p)
-{
-    char *out=0;
-    if (!item) return 0;
-    if (p)
-    {
-        switch ((item->type)&255)
-        {
-            case cJSON_NULL:    {out=ensure(p,5);   if (out) strcpy(out,"null");    break;}
-            case cJSON_False:   {out=ensure(p,6);   if (out) strcpy(out,"false");   break;}
-            case cJSON_True:    {out=ensure(p,5);   if (out) strcpy(out,"true");    break;}
-            case cJSON_Number:  out=print_number(item,p);break;
-            case cJSON_String:  out=print_string(item,p);break;
-            case cJSON_Array:   out=print_array(item,depth,fmt,p);break;
-            case cJSON_Object:  out=print_object(item,depth,fmt,p);break;
-        }
-    }
-    else
-    {
-        switch ((item->type)&255)
-        {
-            case cJSON_NULL:    out=cJSON_strdup("null");   break;
-            case cJSON_False:   out=cJSON_strdup("false");break;
-            case cJSON_True:    out=cJSON_strdup("true"); break;
-            case cJSON_Number:  out=print_number(item,0);break;
-            case cJSON_String:  out=print_string(item,0);break;
-            case cJSON_Array:   out=print_array(item,depth,fmt,0);break;
-            case cJSON_Object:  out=print_object(item,depth,fmt,0);break;
-        }
-    }
-    return out;
-}
-
-/* Build an array from input text. */
-static const char *parse_array(cJSON *item,const char *value,const char **ep)
-{
-    cJSON *child;
-    if (*value!='[')    {*ep=value;return 0;}   /* not an array! */
-
-    item->type=cJSON_Array;
-    value=skip(value+1);
-    if (*value==']') return value+1;    /* empty array. */
-
-    item->child=child=cJSON_New_Item();
-    if (!item->child) return 0;      /* memory fail */
-    value=skip(parse_value(child,skip(value),ep));  /* skip any spacing, get the value. */
-    if (!value) return 0;
-
-    while (*value==',')
-    {
-        cJSON *new_item;
-        if (!(new_item=cJSON_New_Item())) return 0;     /* memory fail */
-        child->next=new_item;new_item->prev=child;child=new_item;
-        value=skip(parse_value(child,skip(value+1),ep));
-        if (!value) return 0;   /* memory fail */
-    }
-
-    if (*value==']') return value+1;    /* end of array */
-    *ep=value;return 0; /* malformed. */
-}
-
-/* Render an array to text */
-static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p)
-{
-    char **entries;
-    char *out=0,*ptr,*ret;int len=5;
-    cJSON *child=item->child;
-    int numentries=0,i=0,fail=0;
-    size_t tmplen=0;
-    
-    /* How many entries in the array? */
-    while (child) numentries++,child=child->next;
-    /* Explicitly handle numentries==0 */
-    if (!numentries)
-    {
-        if (p)  out=ensure(p,3);
-        else    out=(char*)cJSON_malloc(3);
-        if (out) strcpy(out,"[]");
-        return out;
-    }
-
-    if (p)
-    {
-        /* Compose the output array. */
-        i=p->offset;
-        ptr=ensure(p,1);if (!ptr) return 0; *ptr='[';   p->offset++;
-        child=item->child;
-        while (child && !fail)
-        {
-            print_value(child,depth+1,fmt,p);
-            p->offset=update(p);
-            if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;}
-            child=child->next;
-        }
-        ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0;
-        out=(p->buffer)+i;
-    }
-    else
-    {
-        /* Allocate an array to hold the values for each */
-        entries=(char**)cJSON_malloc(numentries*sizeof(char*));
-        if (!entries) return 0;
-        memset(entries,0,numentries*sizeof(char*));
-        /* Retrieve all the results: */
-        child=item->child;
-        while (child && !fail)
-        {
-            ret=print_value(child,depth+1,fmt,0);
-            entries[i++]=ret;
-            if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
-            child=child->next;
-        }
-        
-        /* If we didn't fail, try to malloc the output string */
-        if (!fail)  out=(char*)cJSON_malloc(len);
-        /* If that fails, we fail. */
-        if (!out) fail=1;
-
-        /* Handle failure. */
-        if (fail)
-        {
-            for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
-            cJSON_free(entries);
-            return 0;
-        }
-        
-        /* Compose the output array. */
-        *out='[';
-        ptr=out+1;*ptr=0;
-        for (i=0;i<numentries;i++)
-        {
-            tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen;
-            if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
-            cJSON_free(entries[i]);
-        }
-        cJSON_free(entries);
-        *ptr++=']';*ptr++=0;
-    }
-    return out; 
-}
-
-/* Build an object from the text. */
-static const char *parse_object(cJSON *item,const char *value,const char **ep)
-{
-    cJSON *child;
-    if (*value!='{')    {*ep=value;return 0;}   /* not an object! */
-    
-    item->type=cJSON_Object;
-    value=skip(value+1);
-    if (*value=='}') return value+1;    /* empty array. */
-    
-    item->child=child=cJSON_New_Item();
-    if (!item->child) return 0;
-    value=skip(parse_string(child,skip(value),ep));
-    if (!value) return 0;
-    child->string=child->valuestring;child->valuestring=0;
-    if (*value!=':') {*ep=value;return 0;}  /* fail! */
-    value=skip(parse_value(child,skip(value+1),ep));    /* skip any spacing, get the value. */
-    if (!value) return 0;
-    
-    while (*value==',')
-    {
-        cJSON *new_item;
-        if (!(new_item=cJSON_New_Item()))   return 0; /* memory fail */
-        child->next=new_item;new_item->prev=child;child=new_item;
-        value=skip(parse_string(child,skip(value+1),ep));
-        if (!value) return 0;
-        child->string=child->valuestring;child->valuestring=0;
-        if (*value!=':') {*ep=value;return 0;}  /* fail! */
-        value=skip(parse_value(child,skip(value+1),ep));    /* skip any spacing, get the value. */
-        if (!value) return 0;
-    }
-    
-    if (*value=='}') return value+1;    /* end of array */
-    *ep=value;return 0; /* malformed. */
-}
-
-/* Render an object to text. */
-static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p)
-{
-    char **entries=0,**names=0;
-    char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
-    cJSON *child=item->child;
-    int numentries=0,fail=0;
-    size_t tmplen=0;
-    /* Count the number of entries. */
-    while (child) numentries++,child=child->next;
-    /* Explicitly handle empty object case */
-    if (!numentries)
-    {
-        if (p) out=ensure(p,fmt?depth+4:3);
-        else    out=(char*)cJSON_malloc(fmt?depth+4:3);
-        if (!out)   return 0;
-        ptr=out;*ptr++='{';
-        if (fmt) {*ptr++='\n';for (i=0;i<depth;i++) *ptr++='\t';}
-        *ptr++='}';*ptr++=0;
-        return out;
-    }
-    if (p)
-    {
-        /* Compose the output: */
-        i=p->offset;
-        len=fmt?2:1;    ptr=ensure(p,len+1);    if (!ptr) return 0;
-        *ptr++='{'; if (fmt) *ptr++='\n';   *ptr=0; p->offset+=len;
-        child=item->child;depth++;
-        while (child)
-        {
-            if (fmt)
-            {
-                ptr=ensure(p,depth);    if (!ptr) return 0;
-                for (j=0;j<depth;j++) *ptr++='\t';
-                p->offset+=depth;
-            }
-            print_string_ptr(child->string,p);
-            p->offset=update(p);
-            
-            len=fmt?2:1;
-            ptr=ensure(p,len);  if (!ptr) return 0;
-            *ptr++=':';if (fmt) *ptr++='\t';
-            p->offset+=len;
-            
-            print_value(child,depth,fmt,p);
-            p->offset=update(p);
-
-            len=(fmt?1:0)+(child->next?1:0);
-            ptr=ensure(p,len+1); if (!ptr) return 0;
-            if (child->next) *ptr++=',';
-            if (fmt) *ptr++='\n';*ptr=0;
-            p->offset+=len;
-            child=child->next;
-        }
-        ptr=ensure(p,fmt?(depth+1):2);   if (!ptr) return 0;
-        if (fmt)    for (i=0;i<depth-1;i++) *ptr++='\t';
-        *ptr++='}';*ptr=0;
-        out=(p->buffer)+i;
-    }
-    else
-    {
-        /* Allocate space for the names and the objects */
-        entries=(char**)cJSON_malloc(numentries*sizeof(char*));
-        if (!entries) return 0;
-        names=(char**)cJSON_malloc(numentries*sizeof(char*));
-        if (!names) {cJSON_free(entries);return 0;}
-        memset(entries,0,sizeof(char*)*numentries);
-        memset(names,0,sizeof(char*)*numentries);
-
-        /* Collect all the results into our arrays: */
-        child=item->child;depth++;if (fmt) len+=depth;
-        while (child && !fail)
-        {
-            names[i]=str=print_string_ptr(child->string,0);
-            entries[i++]=ret=print_value(child,depth,fmt,0);
-            if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
-            child=child->next;
-        }
-        
-        /* Try to allocate the output string */
-        if (!fail)  out=(char*)cJSON_malloc(len);
-        if (!out) fail=1;
-
-        /* Handle failure */
-        if (fail)
-        {
-            for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
-            cJSON_free(names);cJSON_free(entries);
-            return 0;
-        }
-        
-        /* Compose the output: */
-        *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
-        for (i=0;i<numentries;i++)
-        {
-            if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
-            tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen;
-            *ptr++=':';if (fmt) *ptr++='\t';
-            strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
-            if (i!=numentries-1) *ptr++=',';
-            if (fmt) *ptr++='\n';*ptr=0;
-            cJSON_free(names[i]);cJSON_free(entries[i]);
-        }
-        
-        cJSON_free(names);cJSON_free(entries);
-        if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
-        *ptr++='}';*ptr++=0;
-    }
-    return out; 
-}
-
-/* Get Array size/item / object item. */
-int    cJSON_GetArraySize(cJSON *array)                         {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
-cJSON *cJSON_GetArrayItem(cJSON *array,int item)                {cJSON *c=array?array->child:0;while (c && item>0) item--,c=c->next; return c;}
-cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)    {cJSON *c=object?object->child:0;while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
-int cJSON_HasObjectItem(cJSON *object,const char *string)       {return cJSON_GetObjectItem(object,string)?1:0;}
-
-/* Utility for array list handling. */
-static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
-/* Utility for handling references. */
-static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
-
-/* Add item to array/object. */
-void   cJSON_AddItemToArray(cJSON *array, cJSON *item)                      {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
-void   cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item)  {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
-void   cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item)    {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);}
-void    cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)                        {cJSON_AddItemToArray(array,create_reference(item));}
-void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)    {cJSON_AddItemToObject(object,string,create_reference(item));}
-
-cJSON *cJSON_DetachItemFromArray(cJSON *array,int which)            {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
-    if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
-void   cJSON_DeleteItemFromArray(cJSON *array,int which)            {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
-cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
-void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
-
-/* Replace array/object items with new ones. */
-void   cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem)       {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;}
-    newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;}
-void   cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)      {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
-    newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
-    if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
-void   cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
-
-/* Create basic types: */
-cJSON *cJSON_CreateNull(void)                   {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
-cJSON *cJSON_CreateTrue(void)                   {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
-cJSON *cJSON_CreateFalse(void)                  {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
-cJSON *cJSON_CreateBool(int b)                  {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
-cJSON *cJSON_CreateNumber(double num)           {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
-cJSON *cJSON_CreateString(const char *string)   {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);if(!item->valuestring){cJSON_Delete(item);return 0;}}return item;}
-cJSON *cJSON_CreateArray(void)                  {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
-cJSON *cJSON_CreateObject(void)                 {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
-
-/* Create Arrays: */
-cJSON *cJSON_CreateIntArray(const int *numbers,int count)       {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
-cJSON *cJSON_CreateFloatArray(const float *numbers,int count)   {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
-cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
-cJSON *cJSON_CreateStringArray(const char **strings,int count)  {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
-
-/* Duplication */
-cJSON *cJSON_Duplicate(cJSON *item,int recurse)
-{
-    cJSON *newitem,*cptr,*nptr=0,*newchild;
-    /* Bail on bad ptr */
-    if (!item) return 0;
-    /* Create new item */
-    newitem=cJSON_New_Item();
-    if (!newitem) return 0;
-    /* Copy over all vars */
-    newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
-    if (item->valuestring)  {newitem->valuestring=cJSON_strdup(item->valuestring);  if (!newitem->valuestring)  {cJSON_Delete(newitem);return 0;}}
-    if (item->string)       {newitem->string=cJSON_strdup(item->string);            if (!newitem->string)       {cJSON_Delete(newitem);return 0;}}
-    /* If non-recursive, then we're done! */
-    if (!recurse) return newitem;
-    /* Walk the ->next chain for the child. */
-    cptr=item->child;
-    while (cptr)
-    {
-        newchild=cJSON_Duplicate(cptr,1);       /* Duplicate (with recurse) each item in the ->next chain */
-        if (!newchild) {cJSON_Delete(newitem);return 0;}
-        if (nptr)   {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}    /* If newitem->child already set, then crosswire ->prev and ->next and move on */
-        else        {newitem->child=newchild;nptr=newchild;}                    /* Set newitem->child and move to it */
-        cptr=cptr->next;
-    }
-    return newitem;
-}
-
-void cJSON_Minify(char *json)
-{
-    char *into=json;
-    while (*json)
-    {
-        if (*json==' ') json++;
-        else if (*json=='\t') json++;   /* Whitespace characters. */
-        else if (*json=='\r') json++;
-        else if (*json=='\n') json++;
-        else if (*json=='/' && json[1]=='/')  while (*json && *json!='\n') json++;  /* double-slash comments, to end of line. */
-        else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}   /* multiline comments. */
-        else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */
-        else *into++=*json++;           /* All other characters. */
-    }
-    *into=0;    /* and null-terminate. */
-}
\ No newline at end of file
--- a/ICE-Application/src/add-ons/cJSON/cJSON.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
-  Copyright (c) 2009 Dave Gamble
- 
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
- 
-  The above copyright notice and this permission notice shall be included in
-  all copies or substantial portions of the Software.
- 
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-  THE SOFTWARE.
-*/
-
-#ifndef cJSON__h
-#define cJSON__h
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/* cJSON Types: */
-#define cJSON_False  (1 << 0)
-#define cJSON_True   (1 << 1)
-#define cJSON_NULL   (1 << 2)
-#define cJSON_Number (1 << 3)
-#define cJSON_String (1 << 4)
-#define cJSON_Array  (1 << 5)
-#define cJSON_Object (1 << 6)
-    
-#define cJSON_IsReference 256
-#define cJSON_StringIsConst 512
-
-/* The cJSON structure: */
-typedef struct cJSON {
-    struct cJSON *next,*prev;   /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
-    struct cJSON *child;        /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
-
-    int type;                   /* The type of the item, as above. */
-
-    char *valuestring;          /* The item's string, if type==cJSON_String */
-    int valueint;               /* The item's number, if type==cJSON_Number */
-    double valuedouble;         /* The item's number, if type==cJSON_Number */
-
-    char *string;               /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
-} cJSON;
-
-typedef struct cJSON_Hooks {
-      void *(*malloc_fn)(size_t sz);
-      void (*free_fn)(void *ptr);
-} cJSON_Hooks;
-
-/* Supply malloc, realloc and free functions to cJSON */
-extern void cJSON_InitHooks(cJSON_Hooks* hooks);
-
-
-/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
-extern cJSON *cJSON_Parse(const char *value);
-/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
-extern char  *cJSON_Print(cJSON *item);
-/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
-extern char  *cJSON_PrintUnformatted(cJSON *item);
-/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
-extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
-/* Delete a cJSON entity and all subentities. */
-extern void   cJSON_Delete(cJSON *c);
-
-/* Returns the number of items in an array (or object). */
-extern int    cJSON_GetArraySize(cJSON *array);
-/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
-extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
-/* Get item "string" from object. Case insensitive. */
-extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
-extern int cJSON_HasObjectItem(cJSON *object,const char *string);
-/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
-extern const char *cJSON_GetErrorPtr(void);
-    
-/* These calls create a cJSON item of the appropriate type. */
-extern cJSON *cJSON_CreateNull(void);
-extern cJSON *cJSON_CreateTrue(void);
-extern cJSON *cJSON_CreateFalse(void);
-extern cJSON *cJSON_CreateBool(int b);
-extern cJSON *cJSON_CreateNumber(double num);
-extern cJSON *cJSON_CreateString(const char *string);
-extern cJSON *cJSON_CreateArray(void);
-extern cJSON *cJSON_CreateObject(void);
-
-/* These utilities create an Array of count items. */
-extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
-extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
-extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
-extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
-
-/* Append item to the specified array/object. */
-extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
-extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
-extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item);  /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */
-/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
-extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
-extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
-
-/* Remove/Detatch items from Arrays/Objects. */
-extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
-extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);
-extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
-extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);
-    
-/* Update array items. */
-extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */
-extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
-extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
-
-/* Duplicate a cJSON item */
-extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
-/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
-need to be released. With recurse!=0, it will duplicate any children connected to the item.
-The item->next and ->prev pointers are always zero on return from Duplicate. */
-
-/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
-/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */
-extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
-
-extern void cJSON_Minify(char *json);
-
-/* Macros for creating things quickly. */
-#define cJSON_AddNullToObject(object,name)      cJSON_AddItemToObject(object, name, cJSON_CreateNull())
-#define cJSON_AddTrueToObject(object,name)      cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
-#define cJSON_AddFalseToObject(object,name)     cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
-#define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
-#define cJSON_AddNumberToObject(object,name,n)  cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
-#define cJSON_AddStringToObject(object,name,s)  cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
-
-/* When assigning an integer value, it needs to be propagated to valuedouble too. */
-#define cJSON_SetIntValue(object,val)           ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
-#define cJSON_SetNumberValue(object,val)        ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
-
-/* Macro for iterating over an array */
-#define cJSON_ArrayForEach(pos, head)           for(pos = (head)->child; pos != NULL; pos = pos->next)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
\ No newline at end of file
--- a/ICE-Application/src/add-ons/crc32/crc.cpp	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-#include "mbed.h"
-#include "crc.h"
-
-static const unsigned int crc32tab[256] = { 
-    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
-    0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
-    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
-    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
-    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
-    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
-    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
-    0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
-    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
-    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
-    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
-    0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
-    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
-    0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
-    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
-    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
-    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
-    0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
-    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
-    0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
-    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
-    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
-    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
-    0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
-    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
-    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
-    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
-    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
-    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
-    0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
-    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
-    0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
-    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
-    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
-    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
-    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
-    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
-    0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
-    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
-    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
-    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
-    0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
-    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
-    0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
-    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
-    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
-    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
-    0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
-    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
-    0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
-    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
-    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
-    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
-    0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
-    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
-    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
-    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
-    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
-    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
-    0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
-    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
-    0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
-    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
-    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
-};
-
-
-unsigned int crc32(char *p, int len)
-{
-    unsigned int crcinit = 0;
-    unsigned int crc = 0;
-
-    crc = crcinit ^ 0xFFFFFFFF;
-    for (; len--; p++) {
-        crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*p)) & 0xFF];
-    }
-    return crc ^ 0xFFFFFFFF;
-}
--- a/ICE-Application/src/add-ons/crc32/crc.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-#ifndef CRC_H
-#define CRC_H
-
-#include "mbed.h"
-
-unsigned int crc32(char *p, int len);
-
-#endif 
--- a/ICE-Application/src/add-ons/v7/v7.c	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34484 +0,0 @@
-#include "v7.h"
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/license.h"
-#endif
-/*
- * Copyright (c) 2013-2014 Cesanta Software Limited
- * All rights reserved
- *
- * This software is dual-licensed: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. For the terms of this
- * license, see <http://www.gnu.org/licenses/>.
- *
- * You are free to use this software under the terms of the GNU General
- * Public License, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * Alternatively, you can license this software under a commercial
- * license, as set out in <https://www.cesanta.com/license>.
- */
-
-#ifdef V7_EXPOSE_PRIVATE
-#define V7_PRIVATE
-#define V7_EXTERN extern
-#else
-#define V7_PRIVATE static
-#define V7_EXTERN static
-#endif /* CS_V7_SRC_LICENSE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/platform.h"
-#endif
-#ifndef CS_COMMON_PLATFORM_H_
-#define CS_COMMON_PLATFORM_H_
-
-/*
- * For the "custom" platform, includes and dependencies can be
- * provided through mg_locals.h.
- */
-#define CS_P_CUSTOM 0
-#define CS_P_UNIX 1
-#define CS_P_WINDOWS 2
-#define CS_P_ESP_LWIP 3
-#define CS_P_CC3200 4
-#define CS_P_MSP432 5
-#define CS_P_CC3100 6
-#define CS_P_MBED 7
-
-/* If not specified explicitly, we guess platform by defines. */
-#ifndef CS_PLATFORM
-
-#if defined(TARGET_IS_MSP432P4XX) || defined(__MSP432P401R__)
-
-#define CS_PLATFORM CS_P_MSP432
-#elif defined(cc3200)
-#define CS_PLATFORM CS_P_CC3200
-#elif defined(__unix__) || defined(__APPLE__)
-#define CS_PLATFORM CS_P_UNIX
-#elif defined(_WIN32)
-#define CS_PLATFORM CS_P_WINDOWS
-#elif defined(__MBED__)
-#define CS_PLATFORM CS_P_MBED
-#warning "CS_PLATFORM_CS_P_MBED"
-#endif
-
-#ifndef CS_PLATFORM
-#error "CS_PLATFORM is not specified and we couldn't guess it."
-#endif
-
-#endif /* !defined(CS_PLATFORM) */
-
-/* Amalgamated: #include "common/platforms/platform_unix.h" */
-/* Amalgamated: #include "common/platforms/platform_windows.h" */
-/* Amalgamated: #include "common/platforms/platform_esp_lwip.h" */
-/* Amalgamated: #include "common/platforms/platform_cc3200.h" */
-/* Amalgamated: #include "common/platforms/platform_cc3100.h" */
-/* Amalgamated: #include "common/platforms/platform_mbed.h" */
-
-/* Common stuff */
-
-#ifdef __GNUC__
-#define NORETURN __attribute__((noreturn))
-#define NOINLINE __attribute__((noinline))
-#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-#define NOINSTR __attribute__((no_instrument_function))
-#else
-#define NORETURN
-#define NOINLINE
-#define WARN_UNUSED_RESULT
-#define NOINSTR
-#endif /* __GNUC__ */
-
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
-#endif
-
-#endif /* CS_COMMON_PLATFORM_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/platforms/platform_windows.h"
-#endif
-#ifndef CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_
-#define CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_
-#if CS_PLATFORM == CS_P_WINDOWS
-
-/*
- * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
- * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
- * MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
- * MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
- * MSVC++ 9.0  _MSC_VER == 1500 (Visual Studio 2008)
- * MSVC++ 8.0  _MSC_VER == 1400 (Visual Studio 2005)
- * MSVC++ 7.1  _MSC_VER == 1310 (Visual Studio 2003)
- * MSVC++ 7.0  _MSC_VER == 1300
- * MSVC++ 6.0  _MSC_VER == 1200
- * MSVC++ 5.0  _MSC_VER == 1100
- */
-#ifdef _MSC_VER
-#pragma warning(disable : 4127) /* FD_SET() emits warning, disable it */
-#pragma warning(disable : 4204) /* missing c99 support */
-#endif
-
-#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
-#define _CRT_SECURE_NO_WARNINGS
-
-#include <assert.h>
-#include <direct.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <io.h>
-#include <limits.h>
-#include <signal.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <time.h>
-
-#ifdef _MSC_VER
-#pragma comment(lib, "ws2_32.lib") /* Linking with winsock library */
-#endif
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-#include <process.h>
-
-#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define strdup _strdup
-#endif
-
-#ifndef EINPROGRESS
-#define EINPROGRESS WSAEINPROGRESS
-#endif
-#ifndef EWOULDBLOCK
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#endif
-#ifndef __func__
-#define STRX(x) #x
-#define STR(x) STRX(x)
-#define __func__ __FILE__ ":" STR(__LINE__)
-#endif
-#define snprintf _snprintf
-#define fileno _fileno
-#define vsnprintf _vsnprintf
-#define sleep(x) Sleep((x) *1000)
-#define to64(x) _atoi64(x)
-#if !defined(__MINGW32__) && !defined(__MINGW64__)
-#define popen(x, y) _popen((x), (y))
-#define pclose(x) _pclose(x)
-#endif
-#define rmdir _rmdir
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-#define fseeko(x, y, z) _fseeki64((x), (y), (z))
-#else
-#define fseeko(x, y, z) fseek((x), (y), (z))
-#endif
-#if defined(_MSC_VER) && _MSC_VER <= 1200
-typedef unsigned long uintptr_t;
-typedef long intptr_t;
-#endif
-typedef int socklen_t;
-#if _MSC_VER >= 1700
-#include <stdint.h>
-#else
-typedef signed char int8_t;
-typedef unsigned char uint8_t;
-typedef int int32_t;
-typedef unsigned int uint32_t;
-typedef short int16_t;
-typedef unsigned short uint16_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-#endif
-typedef SOCKET sock_t;
-typedef uint32_t in_addr_t;
-#ifndef UINT16_MAX
-#define UINT16_MAX 65535
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX 4294967295
-#endif
-#ifndef pid_t
-#define pid_t HANDLE
-#endif
-#define INT64_FMT "I64d"
-#define INT64_X_FMT "I64x"
-#define SIZE_T_FMT "Iu"
-#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
-typedef struct stat cs_stat_t;
-#else
-typedef struct _stati64 cs_stat_t;
-#endif
-#ifndef S_ISDIR
-#define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
-#endif
-#ifndef S_ISREG
-#define S_ISREG(x) (((x) &_S_IFMT) == _S_IFREG)
-#endif
-#define DIRSEP '\\'
-
-#ifndef va_copy
-#ifdef __va_copy
-#define va_copy __va_copy
-#else
-#define va_copy(x, y) (x) = (y)
-#endif
-#endif
-
-#ifndef MG_MAX_HTTP_REQUEST_SIZE
-#define MG_MAX_HTTP_REQUEST_SIZE 8192
-#endif
-
-#ifndef MG_MAX_HTTP_SEND_MBUF
-#define MG_MAX_HTTP_SEND_MBUF 4096
-#endif
-
-#ifndef MG_MAX_HTTP_HEADERS
-#define MG_MAX_HTTP_HEADERS 40
-#endif
-
-#endif /* CS_PLATFORM == CS_P_WINDOWS */
-#endif /* CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/platforms/platform_unix.h"
-#endif
-#ifndef CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_
-#define CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_
-#if CS_PLATFORM == CS_P_UNIX
-
-#ifndef _XOPEN_SOURCE
-#define _XOPEN_SOURCE 600
-#endif
-
-/* <inttypes.h> wants this for C++ */
-#ifndef __STDC_FORMAT_MACROS
-#define __STDC_FORMAT_MACROS
-#endif
-
-/* C++ wants that for INT64_MAX */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS
-#endif
-
-/* Enable fseeko() and ftello() functions */
-#ifndef _LARGEFILE_SOURCE
-#define _LARGEFILE_SOURCE
-#endif
-
-/* Enable 64-bit file offsets */
-#ifndef _FILE_OFFSET_BITS
-#define _FILE_OFFSET_BITS 64
-#endif
-
-#include <arpa/inet.h>
-#include <assert.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <limits.h>
-#include <math.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <pthread.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-/*
- * osx correctly avoids defining strtoll when compiling in strict ansi mode.
- * We require strtoll, and if your embedded pre-c99 compiler lacks one, please
- * implement a shim.
- */
-#if !(defined(__DARWIN_C_LEVEL) && __DARWIN_C_LEVEL >= 200809L)
-long long strtoll(const char *, char **, int);
-#endif
-
-typedef int sock_t;
-#define INVALID_SOCKET (-1)
-#define SIZE_T_FMT "zu"
-typedef struct stat cs_stat_t;
-#define DIRSEP '/'
-#define to64(x) strtoll(x, NULL, 10)
-#define INT64_FMT PRId64
-#define INT64_X_FMT PRIx64
-
-#ifndef __cdecl
-#define __cdecl
-#endif
-
-#ifndef va_copy
-#ifdef __va_copy
-#define va_copy __va_copy
-#else
-#define va_copy(x, y) (x) = (y)
-#endif
-#endif
-
-#define closesocket(x) close(x)
-
-#ifndef MG_MAX_HTTP_REQUEST_SIZE
-#define MG_MAX_HTTP_REQUEST_SIZE 8192
-#endif
-
-#ifndef MG_MAX_HTTP_SEND_MBUF
-#define MG_MAX_HTTP_SEND_MBUF 4096
-#endif
-
-#ifndef MG_MAX_HTTP_HEADERS
-#define MG_MAX_HTTP_HEADERS 40
-#endif
-
-#endif /* CS_PLATFORM == CS_P_UNIX */
-#endif /* CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/platforms/platform_esp_lwip.h"
-#endif
-#ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_
-#define CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_
-#if CS_PLATFORM == CS_P_ESP_LWIP
-
-#include <assert.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <lwip/err.h>
-#include <lwip/ip_addr.h>
-#include <lwip/inet.h>
-#include <lwip/netdb.h>
-#include <lwip/dns.h>
-
-#ifndef LWIP_PROVIDE_ERRNO
-#include <errno.h>
-#endif
-
-#define LWIP_TIMEVAL_PRIVATE 0
-
-#if LWIP_SOCKET
-#include <lwip/sockets.h>
-#define SOMAXCONN 10
-#else
-/* We really need the definitions from sockets.h. */
-#undef LWIP_SOCKET
-#define LWIP_SOCKET 1
-#include <lwip/sockets.h>
-#undef LWIP_SOCKET
-#define LWIP_SOCKET 0
-#endif
-
-typedef int sock_t;
-#define INVALID_SOCKET (-1)
-#define SIZE_T_FMT "u"
-typedef struct stat cs_stat_t;
-#define DIRSEP '/'
-#define to64(x) strtoll(x, NULL, 10)
-#define INT64_FMT PRId64
-#define INT64_X_FMT PRIx64
-#define __cdecl
-
-unsigned long os_random(void);
-#define random os_random
-
-#endif /* CS_PLATFORM == CS_P_ESP_LWIP */
-#endif /* CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/mbuf.h"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Memory Buffers
- *
- * Mbufs are mutable/growing memory buffers, like C++ strings.
- * Mbuf can append data to the end of a buffer or insert data into arbitrary
- * position in the middle of a buffer. The buffer grows automatically when
- * needed.
- */
-
-#ifndef CS_COMMON_MBUF_H_
-#define CS_COMMON_MBUF_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#include <stdlib.h>
-
-#ifndef MBUF_SIZE_MULTIPLIER
-#define MBUF_SIZE_MULTIPLIER 1.5
-#endif
-
-/* Memory buffer descriptor */
-struct mbuf {
-  char *buf;   /* Buffer pointer */
-  size_t len;  /* Data length. Data is located between offset 0 and len. */
-  size_t size; /* Buffer size allocated by realloc(1). Must be >= len */
-};
-
-/*
- * Initialises an Mbuf.
- * `initial_capacity` specifies the initial capacity of the mbuf.
- */
-void mbuf_init(struct mbuf *, size_t initial_capacity);
-
-/* Frees the space allocated for the mbuffer and resets the mbuf structure. */
-void mbuf_free(struct mbuf *);
-
-/*
- * Appends data to the Mbuf.
- *
- * Returns the number of bytes appended or 0 if out of memory.
- */
-size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
-
-/*
- * Inserts data at a specified offset in the Mbuf.
- *
- * Existing data will be shifted forwards and the buffer will
- * be grown if necessary.
- * Returns the number of bytes inserted.
- */
-size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t);
-
-/* Removes `data_size` bytes from the beginning of the buffer. */
-void mbuf_remove(struct mbuf *, size_t data_size);
-
-/*
- * Resizes an Mbuf.
- *
- * If `new_size` is smaller than buffer's `len`, the
- * resize is not performed.
- */
-void mbuf_resize(struct mbuf *, size_t new_size);
-
-/* Shrinks an Mbuf by resizing its `size` to `len`. */
-void mbuf_trim(struct mbuf *);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_COMMON_MBUF_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/platforms/simplelink/cs_simplelink.h"
-#endif
-/*
- * Copyright (c) 2014-2016 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
-#define CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
-
-/* If simplelink.h is already included, all bets are off. */
-#if defined(MG_SOCKET_SIMPLELINK) && !defined(__SIMPLELINK_H__)
-
-#include <stdbool.h>
-
-#ifndef __TI_COMPILER_VERSION__
-#undef __CONCAT
-#undef FD_CLR
-#undef FD_ISSET
-#undef FD_SET
-#undef FD_SETSIZE
-#undef FD_ZERO
-#undef fd_set
-#endif
-
-/* We want to disable SL_INC_STD_BSD_API_NAMING, so we include user.h ourselves
- * and undef it. */
-#define PROVISIONING_API_H_
-#include <simplelink/user.h>
-#undef PROVISIONING_API_H_
-#undef SL_INC_STD_BSD_API_NAMING
-
-#include <simplelink/include/simplelink.h>
-#include <simplelink/include/netapp.h>
-
-/* Now define only the subset of the BSD API that we use.
- * Notably, close(), read() and write() are not defined. */
-#define AF_INET SL_AF_INET
-
-#define socklen_t SlSocklen_t
-#define sockaddr SlSockAddr_t
-#define sockaddr_in SlSockAddrIn_t
-#define in_addr SlInAddr_t
-
-#define SOCK_STREAM SL_SOCK_STREAM
-#define SOCK_DGRAM SL_SOCK_DGRAM
-
-#define htonl sl_Htonl
-#define ntohl sl_Ntohl
-#define htons sl_Htons
-#define ntohs sl_Ntohs
-
-#ifndef EACCES
-#define EACCES SL_EACCES
-#endif
-#ifndef EAFNOSUPPORT
-#define EAFNOSUPPORT SL_EAFNOSUPPORT
-#endif
-#ifndef EAGAIN
-#define EAGAIN SL_EAGAIN
-#endif
-#ifndef EBADF
-#define EBADF SL_EBADF
-#endif
-#ifndef EINVAL
-#define EINVAL SL_EINVAL
-#endif
-#ifndef ENOMEM
-#define ENOMEM SL_ENOMEM
-#endif
-#ifndef EWOULDBLOCK
-#define EWOULDBLOCK SL_EWOULDBLOCK
-#endif
-
-#define SOMAXCONN 8
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
-char *inet_ntoa(struct in_addr in);
-int inet_pton(int af, const char *src, void *dst);
-
-struct mg_mgr;
-struct mg_connection;
-
-typedef void (*mg_init_cb)(struct mg_mgr *mgr);
-bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init);
-
-void mg_run_in_task(void (*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg);
-
-int sl_fs_init(void);
-
-void sl_restart_cb(struct mg_mgr *mgr);
-
-int sl_set_ssl_opts(struct mg_connection *nc);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* defined(MG_SOCKET_SIMPLELINK) && !defined(__SIMPLELINK_H__) */
-
-#endif /* CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/platforms/platform_cc3200.h"
-#endif
-/*
- * Copyright (c) 2014-2016 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_
-#define CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_
-#if CS_PLATFORM == CS_P_CC3200
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef __TI_COMPILER_VERSION__
-#include <fcntl.h>
-#include <sys/time.h>
-#endif
-
-#define MG_SOCKET_SIMPLELINK 1
-#define MG_DISABLE_SOCKETPAIR 1
-#define MG_DISABLE_SYNC_RESOLVER 1
-#define MG_DISABLE_POPEN 1
-#define MG_DISABLE_CGI 1
-/* Only SPIFFS supports directories, SLFS does not. */
-#ifndef CC3200_FS_SPIFFS
-#define MG_DISABLE_DAV 1
-#define MG_DISABLE_DIRECTORY_LISTING 1
-#endif
-
-/* Amalgamated: #include "common/platforms/simplelink/cs_simplelink.h" */
-
-typedef int sock_t;
-#define INVALID_SOCKET (-1)
-#define SIZE_T_FMT "u"
-typedef struct stat cs_stat_t;
-#define DIRSEP '/'
-#define to64(x) strtoll(x, NULL, 10)
-#define INT64_FMT PRId64
-#define INT64_X_FMT PRIx64
-#define __cdecl
-
-#define fileno(x) -1
-
-/* Some functions we implement for Mongoose. */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __TI_COMPILER_VERSION__
-struct SlTimeval_t;
-#define timeval SlTimeval_t
-int gettimeofday(struct timeval *t, void *tz);
-
-int asprintf(char **strp, const char *fmt, ...);
-
-#endif
-
-/* TI's libc does not have stat & friends, add them. */
-#ifdef __TI_COMPILER_VERSION__
-
-#include <file.h>
-
-typedef unsigned int mode_t;
-typedef size_t _off_t;
-typedef long ssize_t;
-
-struct stat {
-  int st_ino;
-  mode_t st_mode;
-  int st_nlink;
-  time_t st_mtime;
-  off_t st_size;
-};
-
-int _stat(const char *pathname, struct stat *st);
-#define stat(a, b) _stat(a, b)
-
-#define __S_IFMT 0170000
-
-#define __S_IFDIR 0040000
-#define __S_IFCHR 0020000
-#define __S_IFREG 0100000
-
-#define __S_ISTYPE(mode, mask) (((mode) &__S_IFMT) == (mask))
-
-#define S_IFDIR __S_IFDIR
-#define S_IFCHR __S_IFCHR
-#define S_IFREG __S_IFREG
-#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
-#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG)
-
-/* As of 5.2.7, TI compiler does not support va_copy() yet. */
-#define va_copy(apc, ap) ((apc) = (ap))
-
-#endif /* __TI_COMPILER_VERSION__ */
-
-#ifdef CC3200_FS_SPIFFS
-#include <common/spiffs/spiffs.h>
-
-typedef struct {
-  spiffs_DIR dh;
-  struct spiffs_dirent de;
-} DIR;
-
-#define d_name name
-#define dirent spiffs_dirent
-
-DIR *opendir(const char *dir_name);
-int closedir(DIR *dir);
-struct dirent *readdir(DIR *dir);
-#endif /* CC3200_FS_SPIFFS */
-
-#ifdef CC3200_FS_SLFS
-#define MG_FS_SLFS
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* CS_PLATFORM == CS_P_CC3200 */
-#endif /* CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/platforms/platform_cc3100.h"
-#endif
-/*
- * Copyright (c) 2014-2016 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_
-#define CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_
-#if CS_PLATFORM == CS_P_CC3100
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <string.h>
-#include <time.h>
-
-#define MG_SOCKET_SIMPLELINK 1
-#define MG_DISABLE_SOCKETPAIR 1
-#define MG_DISABLE_SYNC_RESOLVER 1
-#define MG_DISABLE_POPEN 1
-#define MG_DISABLE_CGI 1
-#define MG_DISABLE_DAV 1
-#define MG_DISABLE_DIRECTORY_LISTING 1
-#define MG_DISABLE_FILESYSTEM 1
-
-/*
- * CC3100 SDK and STM32 SDK include headers w/out path, just like
- * #include "simplelink.h". As result, we have to add all required directories
- * into Makefile IPATH and do the same thing (include w/out path)
- */
-
-#include <simplelink.h>
-#include <netapp.h>
-#undef timeval 
-
-typedef int sock_t;
-#define INVALID_SOCKET (-1)
-
-#define to64(x) strtoll(x, NULL, 10)
-#define INT64_FMT PRId64
-#define INT64_X_FMT PRIx64
-#define SIZE_T_FMT "u"
-
-#define SOMAXCONN 8
-
-const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
-char *inet_ntoa(struct in_addr in);
-int inet_pton(int af, const char *src, void *dst);
-
-#endif /* CS_PLATFORM == CS_P_CC3100 */
-#endif /* CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/platforms/platform_mbed.h"
-#endif
-/*
- * Copyright (c) 2014-2016 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_PLATFORMS_PLATFORM_MBED_H_
-#define CS_COMMON_PLATFORMS_PLATFORM_MBED_H_
-#if CS_PLATFORM == CS_P_MBED
-
-/* Amalgamated: #include "mbed.h" */
-
-#endif /* CS_PLATFORM == CS_P_MBED */
-#endif /* CS_COMMON_PLATFORMS_PLATFORM_MBED_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/str_util.h"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_STR_UTIL_H_
-#define CS_COMMON_STR_UTIL_H_
-
-#include <stdarg.h>
-#include <stdlib.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-size_t c_strnlen(const char *s, size_t maxlen);
-int c_snprintf(char *buf, size_t buf_size, const char *format, ...);
-int c_vsnprintf(char *buf, size_t buf_size, const char *format, va_list ap);
-/*
- * Find the first occurrence of find in s, where the search is limited to the
- * first slen characters of s.
- */
-const char *c_strnstr(const char *s, const char *find, size_t slen);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* CS_COMMON_STR_UTIL_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/utf.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_UTF_H_
-#define CS_COMMON_UTF_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-typedef unsigned char uchar;
-
-typedef unsigned short Rune; /* 16 bits */
-
-#define nelem(a) (sizeof(a) / sizeof(a)[0])
-
-enum {
-  UTFmax = 3,               /* maximum bytes per rune */
-  Runesync = 0x80,          /* cannot represent part of a UTF sequence (<) */
-  Runeself = 0x80,          /* rune and UTF sequences are the same (<) */
-  Runeerror = 0xFFFD        /* decoding error in UTF */
-  /* Runemax    = 0xFFFC */ /* maximum rune value */
-};
-
-/* Edit .+1,/^$/ | cfn $PLAN9/src/lib9/utf/?*.c | grep -v static |grep -v __ */
-int chartorune(Rune *rune, const char *str);
-int fullrune(const char *str, int n);
-int isdigitrune(Rune c);
-int isnewline(Rune c);
-int iswordchar(Rune c);
-int isalpharune(Rune c);
-int islowerrune(Rune c);
-int isspacerune(Rune c);
-int isupperrune(Rune c);
-int runetochar(char *str, Rune *rune);
-Rune tolowerrune(Rune c);
-Rune toupperrune(Rune c);
-int utfnlen(const char *s, long m);
-const char *utfnshift(const char *s, long m);
-
-#if 0 /* Not implemented. */
-int istitlerune(Rune c);
-int runelen(Rune c);
-int runenlen(Rune *r, int nrune);
-Rune *runestrcat(Rune *s1, Rune *s2);
-Rune *runestrchr(Rune *s, Rune c);
-Rune *runestrcpy(Rune *s1, Rune *s2);
-Rune *runestrdup(Rune *s);
-Rune *runestrecpy(Rune *s1, Rune *es1, Rune *s2);
-int runestrcmp(Rune *s1, Rune *s2);
-long runestrlen(Rune *s);
-Rune *runestrncat(Rune *s1, Rune *s2, long n);
-int runestrncmp(Rune *s1, Rune *s2, long n);
-Rune *runestrncpy(Rune *s1, Rune *s2, long n);
-Rune *runestrrchr(Rune *s, Rune c);
-Rune *runestrstr(Rune *s1, Rune *s2);
-Rune totitlerune(Rune c);
-char *utfecpy(char *to, char *e, char *from);
-int utflen(char *s);
-char *utfrrune(char *s, long c);
-char *utfrune(char *s, long c);
-char *utfutf(char *s1, char *s2);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-#endif /* CS_COMMON_UTF_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/base64.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_BASE64_H_
-#define CS_COMMON_BASE64_H_
-
-#ifndef DISABLE_BASE64
-
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (*cs_base64_putc_t)(char, void *);
-
-struct cs_base64_ctx {
-  /* cannot call it putc because it's a macro on some environments */
-  cs_base64_putc_t b64_putc;
-  unsigned char chunk[3];
-  int chunk_size;
-  void *user_data;
-};
-
-void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t putc,
-                    void *user_data);
-void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len);
-void cs_base64_finish(struct cs_base64_ctx *ctx);
-
-void cs_base64_encode(const unsigned char *src, int src_len, char *dst);
-void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len);
-int cs_base64_decode(const unsigned char *s, int len, char *dst);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* DISABLE_BASE64 */
-
-#endif /* CS_COMMON_BASE64_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/md5.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_MD5_H_
-#define CS_COMMON_MD5_H_
-
-/* Amalgamated: #include "common/platform.h" */
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-typedef struct MD5Context {
-  uint32_t buf[4];
-  uint32_t bits[2];
-  unsigned char in[64];
-} MD5_CTX;
-
-void MD5_Init(MD5_CTX *c);
-void MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len);
-void MD5_Final(unsigned char *md, MD5_CTX *c);
-
-/*
- * Return stringified MD5 hash for NULL terminated list of pointer/length pairs.
- * A length should be specified as size_t variable.
- * Example:
- *
- *    char buf[33];
- *    cs_md5(buf, "foo", (size_t) 3, "bar", (size_t) 3, NULL);
- */
-char *cs_md5(char buf[33], ...);
-
-/*
- * Stringify binary data. Output buffer size must be 2 * size_of_input + 1
- * because each byte of input takes 2 bytes in string representation
- * plus 1 byte for the terminating \0 character.
- */
-void cs_to_hex(char *to, const unsigned char *p, size_t len);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CS_COMMON_MD5_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/sha1.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_SHA1_H_
-#define CS_COMMON_SHA1_H_
-
-#ifndef DISABLE_SHA1
-
-/* Amalgamated: #include "common/platform.h" */
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-typedef struct {
-  uint32_t state[5];
-  uint32_t count[2];
-  unsigned char buffer[64];
-} cs_sha1_ctx;
-
-void cs_sha1_init(cs_sha1_ctx *);
-void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len);
-void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *);
-void cs_hmac_sha1(const unsigned char *key, size_t key_len,
-                  const unsigned char *text, size_t text_len,
-                  unsigned char out[20]);
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* DISABLE_SHA1 */
-
-#endif /* CS_COMMON_SHA1_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/cs_dirent.h"
-#endif
-/*
- * Copyright (c) 2014-2016 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_CS_DIRENT_H_
-#define CS_COMMON_CS_DIRENT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#ifdef CS_ENABLE_SPIFFS
-
-#include <spiffs.h>
-
-typedef struct {
-  spiffs_DIR dh;
-  struct spiffs_dirent de;
-} DIR;
-
-#define d_name name
-#define dirent spiffs_dirent
-
-int rmdir(const char *path);
-int mkdir(const char *path, mode_t mode);
-
-#endif
-
-#if defined(_WIN32)
-struct dirent {
-  char d_name[MAX_PATH];
-};
-
-typedef struct DIR {
-  HANDLE handle;
-  WIN32_FIND_DATAW info;
-  struct dirent result;
-} DIR;
-#endif
-
-#if defined(_WIN32) || defined(CS_ENABLE_SPIFFS)
-DIR *opendir(const char *dir_name);
-int closedir(DIR *dir);
-struct dirent *readdir(DIR *dir);
-#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CS_COMMON_CS_DIRENT_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/cs_file.h"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_CS_FILE_H_
-#define CS_COMMON_CS_FILE_H_
-
-/* Amalgamated: #include "common/platform.h" */
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Read whole file `path` in memory. It is responsibility of the caller
- * to `free()` allocated memory. File content is guaranteed to be
- * '\0'-terminated. File size is returned in `size` variable, which does not
- * count terminating `\0`.
- * Return: allocated memory, or NULL on error.
- */
-char *cs_read_file(const char *path, size_t *size);
-
-#ifdef CS_MMAP
-char *cs_mmap_file(const char *path, size_t *size);
-#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CS_COMMON_CS_FILE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/coroutine.h"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * Module that provides generic macros and functions to implement "coroutines",
- * i.e. C code that uses `mbuf` as a stack for function calls.
- *
- * More info: see the design doc: https://goo.gl/kfcG61
- */
-
-#ifndef CS_COMMON_COROUTINE_H_
-#define CS_COMMON_COROUTINE_H_
-
-/* Amalgamated: #include "common/mbuf.h" */
-/* Amalgamated: #include "common/platform.h" */
-
-/* user-defined union, this module only operates on the pointer */
-union user_arg_ret;
-
-/*
- * Type that represents size of local function variables. We assume we'll never
- * need more than 255 bytes of stack frame.
- */
-typedef uint8_t cr_locals_size_t;
-
-/*
- * Descriptor of a single function; const array of such descriptors should
- * be given to `cr_context_init()`
- */
-struct cr_func_desc {
-  /*
-   * Size of the function's data that should be stored on stack.
-   *
-   * NOTE: you should use `CR_LOCALS_SIZEOF(your_type)` instead of `sizeof()`,
-   * since this value should be aligned by the word boundary, and
-   * `CR_LOCALS_SIZEOF()` takes care of this.
-   */
-  cr_locals_size_t locals_size;
-};
-
-enum cr_status {
-  CR_RES__OK,
-  CR_RES__OK_YIELDED,
-
-  CR_RES__ERR_STACK_OVERFLOW,
-
-  /* Underflow can only be caused by memory corruption or bug in CR */
-  CR_RES__ERR_STACK_DATA_UNDERFLOW,
-  /* Underflow can only be caused by memory corruption or bug in CR */
-  CR_RES__ERR_STACK_CALL_UNDERFLOW,
-
-  CR_RES__ERR_UNCAUGHT_EXCEPTION,
-};
-
-/* Context of the coroutine engine */
-struct cr_ctx {
-  /*
-   * id of the next "function" to call. If no function is going to be called,
-   * it's CR_FID__NONE.
-   */
-  uint8_t called_fid;
-
-  /*
-   * when `called_fid` is not `CR_FID__NONE`, this field holds called
-   * function's stack frame size
-   */
-  size_t call_locals_size;
-
-  /*
-   * when `called_fid` is not `CR_FID__NONE`, this field holds called
-   * function's arguments size
-   */
-  size_t call_arg_size;
-
-  /*
-   * pointer to the current function's locals.
-   * Needed to make `CR_CUR_LOCALS_PT()` fast.
-   */
-  uint8_t *p_cur_func_locals;
-
-  /* data stack */
-  struct mbuf stack_data;
-
-  /* return stack */
-  struct mbuf stack_ret;
-
-  /* index of the current fid + 1 in return stack */
-  size_t cur_fid_idx;
-
-  /* pointer to the array of function descriptors */
-  const struct cr_func_desc *p_func_descrs;
-
-  /* thrown exception. If nothing is currently thrown, it's `CR_EXC_ID__NONE` */
-  uint8_t thrown_exc;
-
-  /* status: normally, it's `CR_RES__OK` */
-  enum cr_status status;
-
-  /*
-   * pointer to user-dependent union of arguments for all functions, as well as
-   * return values, yielded and resumed values.
-   */
-  union user_arg_ret *p_arg_retval;
-
-  /* true if currently running function returns */
-  unsigned need_return : 1;
-
-  /* true if currently running function yields */
-  unsigned need_yield : 1;
-
-#if defined(CR_TRACK_MAX_STACK_LEN)
-  size_t stack_data_max_len;
-  size_t stack_ret_max_len;
-#endif
-};
-
-/*
- * User's enum with function ids should use items of this one like this:
- *
- *   enum my_func_id {
- *     my_func_none = CR_FID__NONE,
- *
- *     my_foo = CR_FID__USER,
- *     my_foo1,
- *     my_foo2,
- *
- *     my_bar,
- *     my_bar1,
- *   };
- *
- */
-enum cr_fid {
-  CR_FID__NONE,
-  CR_FID__USER,
-
-  /* for internal usage only */
-  CR_FID__TRY_MARKER = 0xff,
-};
-
-/*
- * User's enum with exception ids should use items of this one like this:
- *
- *   enum my_exc_id {
- *     MY_EXC_ID__FIRST = CR_EXC_ID__USER,
- *     MY_EXC_ID__SECOND,
- *     MY_EXC_ID__THIRD,
- *   };
- */
-enum cr_exc_id {
-  CR_EXC_ID__NONE,
-  CR_EXC_ID__USER,
-};
-
-/*
- * A type whose size is a special case for macros `CR_LOCALS_SIZEOF()` and
- * `CR_ARG_SIZEOF()` : it is assumed as zero size.
- *
- * This hackery is needed because empty structs (that would yield sizeof 0) are
- * illegal in plain C.
- */
-typedef struct { uint8_t _dummy[((cr_locals_size_t) -1)]; } cr_zero_size_type_t;
-
-/*
- * To be used in dispatcher switch: depending on the "fid" (function id), we
- * jump to the appropriate label.
- */
-#define CR_DEFINE_ENTRY_POINT(fid) \
-  case fid:                        \
-    goto fid
-
-/*
- * Returns lvalue: id of the currently active "function". It just takes the id
- * from the appropriate position of the "stack".
- *
- * Client code only needs it in dispatcher switch.
- */
-#define CR_CURR_FUNC_C(p_ctx) \
-  *(((cr_locals_size_t *) (p_ctx)->stack_ret.buf) + (p_ctx)->cur_fid_idx - 1)
-
-/*
- * Prepare context for calling first function.
- *
- * Should be used outside of the exec loop, right after initializing
- * context with `cr_context_init()`
- *
- * `call_fid`: id of the function to be called
- */
-#define CR_FIRST_CALL_PREPARE_C(p_ctx, call_fid)                           \
-  _CR_CALL_PREPARE(p_ctx, call_fid, CR_LOCALS_SIZEOF(call_fid##_locals_t), \
-                   CR_ARG_SIZEOF(call_fid##_arg_t), CR_FID__NONE)
-
-/*
- * Call "function" with id `call_fid`: uses `_CR_CALL_PREPARE()` to prepare
- * stuff, and then jumps to the `_cr_iter_begin`, which will perform all
- * necessary bookkeeping.
- *
- * Should be used from eval loop only.
- *
- * `local_ret_fid`: id of the label right after the function call (where
- * currently running function will be resumed later)
- */
-#define CR_CALL_C(p_ctx, call_fid, local_ret_fid)                            \
-  do {                                                                       \
-    _CR_CALL_PREPARE(p_ctx, call_fid, CR_LOCALS_SIZEOF(call_fid##_locals_t), \
-                     CR_ARG_SIZEOF(call_fid##_arg_t), local_ret_fid);        \
-    goto _cr_iter_begin;                                                     \
-  local_ret_fid:                                                             \
-    /* we'll get here when called function returns */                        \
-    ;                                                                        \
-  } while (0)
-
-/*
- * "Return" the value `retval` from the current "function" with id `cur_fid`.
- * You have to specify `cur_fid` since different functions may have different
- * return types.
- *
- * Should be used from eval loop only.
- */
-#define CR_RETURN_C(p_ctx, cur_fid, retval)         \
-  do {                                              \
-    /* copy ret to arg_retval */                    \
-    CR_ARG_RET_PT_C(p_ctx)->ret.cur_fid = (retval); \
-    /* set need_return flag */                      \
-    (p_ctx)->need_return = 1;                       \
-    goto _cr_iter_begin;                            \
-  } while (0)
-
-/*
- * Same as `CR_RETURN_C`, but without any return value
- */
-#define CR_RETURN_VOID_C(p_ctx) \
-  do {                          \
-    /* set need_return flag */  \
-    (p_ctx)->need_return = 1;   \
-    goto _cr_iter_begin;        \
-  } while (0)
-
-/*
- * Yield with the value `value`. It will be set just by the assigment operator
- * in the `yielded` field of the `union user_arg_ret`.
- *
- * `local_ret_fid`: id of the label right after the yielding (where currently
- * running function will be resumed later)
- *
- */
-#define CR_YIELD_C(p_ctx, value, local_ret_fid)           \
-  do {                                                    \
-    /* copy ret to arg_retval */                          \
-    CR_ARG_RET_PT_C(p_ctx)->yielded = (value);            \
-    /* set need_yield flag */                             \
-    (p_ctx)->need_yield = 1;                              \
-                                                          \
-    /* adjust return func id */                           \
-    CR_CURR_FUNC_C(p_ctx) = (local_ret_fid);              \
-                                                          \
-    goto _cr_iter_begin;                                  \
-  local_ret_fid:                                          \
-    /* we'll get here when the machine will be resumed */ \
-    ;                                                     \
-  } while (0)
-
-/*
- * Prepare context for resuming with the given value. After using this
- * macro, you need to call your user-dependent exec function.
- */
-#define CR_RESUME_C(p_ctx, value)                \
-  do {                                           \
-    if ((p_ctx)->status == CR_RES__OK_YIELDED) { \
-      CR_ARG_RET_PT_C(p_ctx)->resumed = (value); \
-      (p_ctx)->status = CR_RES__OK;              \
-    }                                            \
-  } while (0)
-
-/*
- * Evaluates to the yielded value (value given to `CR_YIELD_C()`)
- */
-#define CR_YIELDED_C(p_ctx) (CR_ARG_RET_PT_C(p_ctx)->yielded)
-
-/*
- * Evaluates to the value given to `CR_RESUME_C()`
- */
-#define CR_RESUMED_C(p_ctx) (CR_ARG_RET_PT_C(p_ctx)->resumed)
-
-/*
- * Beginning of the try-catch block.
- *
- * Should be used in eval loop only.
- *
- * `first_catch_fid`: function id of the first catch block.
- */
-#define CR_TRY_C(p_ctx, first_catch_fid)                                   \
-  do {                                                                     \
-    _CR_STACK_RET_ALLOC((p_ctx), _CR_TRY_SIZE);                            \
-    /* update pointer to current function's locals (may be invalidated) */ \
-    _CR_CUR_FUNC_LOCALS_UPD(p_ctx);                                        \
-    /*  */                                                                 \
-    _CR_TRY_MARKER(p_ctx) = CR_FID__TRY_MARKER;                            \
-    _CR_TRY_CATCH_FID(p_ctx) = (first_catch_fid);                          \
-  } while (0)
-
-/*
- * Beginning of the individual catch block (and the end of the previous one, if
- * any)
- *
- * Should be used in eval loop only.
- *
- * `exc_id`: exception id to catch
- *
- * `catch_fid`: function id of this catch block.
- *
- * `next_catch_fid`: function id of the next catch block (or of the
- * `CR_ENDCATCH()`)
- */
-#define CR_CATCH_C(p_ctx, exc_id, catch_fid, next_catch_fid) \
-  catch_fid:                                                 \
-  do {                                                       \
-    if ((p_ctx)->thrown_exc != (exc_id)) {                   \
-      goto next_catch_fid;                                   \
-    }                                                        \
-    (p_ctx)->thrown_exc = CR_EXC_ID__NONE;                   \
-  } while (0)
-
-/*
- * End of all catch blocks.
- *
- * Should be used in eval loop only.
- *
- * `endcatch_fid`: function id of this endcatch.
- */
-#define CR_ENDCATCH_C(p_ctx, endcatch_fid)                                   \
-  endcatch_fid:                                                              \
-  do {                                                                       \
-    (p_ctx)->stack_ret.len -= _CR_TRY_SIZE;                                  \
-    /* if we still have non-handled exception, continue unwinding "stack" */ \
-    if ((p_ctx)->thrown_exc != CR_EXC_ID__NONE) {                            \
-      goto _cr_iter_begin;                                                   \
-    }                                                                        \
-  } while (0)
-
-/*
- * Throw exception.
- *
- * Should be used from eval loop only.
- *
- * `exc_id`: exception id to throw
- */
-#define CR_THROW_C(p_ctx, exc_id)                        \
-  do {                                                   \
-    assert((enum cr_exc_id)(exc_id) != CR_EXC_ID__NONE); \
-    /* clear need_return flag */                         \
-    (p_ctx)->thrown_exc = (exc_id);                      \
-    goto _cr_iter_begin;                                 \
-  } while (0)
-
-/*
- * Get latest returned value from the given "function".
- *
- * `fid`: id of the function which returned value. Needed to ret value value
- * from the right field in the `(p_ctx)->arg_retval.ret` (different functions
- * may have different return types)
- */
-#define CR_RETURNED_C(p_ctx, fid) (CR_ARG_RET_PT_C(p_ctx)->ret.fid)
-
-/*
- * Get currently thrown exception id. If nothing is being thrown at the moment,
- * `CR_EXC_ID__NONE` is returned
- */
-#define CR_THROWN_C(p_ctx) ((p_ctx)->thrown_exc)
-
-/*
- * Like `sizeof()`, but it always evaluates to the multiple of `sizeof(void *)`
- *
- * It should be used for (struct cr_func_desc)::locals_size
- *
- * NOTE: instead of checking `sizeof(type) <= ((cr_locals_size_t) -1)`, I'd
- * better put the calculated value as it is, and if it overflows, then compiler
- * will generate warning, and this would help us to reveal our mistake. But
- * unfortunately, clang *always* generates this warning (even if the whole
- * expression yields 0), so we have to apply a bit more of dirty hacks here.
- */
-#define CR_LOCALS_SIZEOF(type)                                                \
-  ((sizeof(type) == sizeof(cr_zero_size_type_t))                              \
-       ? 0                                                                    \
-       : (sizeof(type) <= ((cr_locals_size_t) -1)                             \
-              ? ((cr_locals_size_t)(((sizeof(type)) + (sizeof(void *) - 1)) & \
-                                    (~(sizeof(void *) - 1))))                 \
-              : ((cr_locals_size_t) -1)))
-
-#define CR_ARG_SIZEOF(type) \
-  ((sizeof(type) == sizeof(cr_zero_size_type_t)) ? 0 : sizeof(type))
-
-/*
- * Returns pointer to the current function's stack locals, and casts to given
- * type.
- *
- * Typical usage might look as follows:
- *
- *    #undef L
- *    #define L CR_CUR_LOCALS_PT(p_ctx, struct my_foo_locals)
- *
- * Then, assuming `struct my_foo_locals` has the field `bar`, we can access it
- * like this:
- *
- *    L->bar
- */
-#define CR_CUR_LOCALS_PT_C(p_ctx, type) ((type *) ((p_ctx)->p_cur_func_locals))
-
-/*
- * Returns pointer to the user-defined union of arguments and return values:
- * `union user_arg_ret`
- */
-#define CR_ARG_RET_PT_C(p_ctx) ((p_ctx)->p_arg_retval)
-
-#define CR_ARG_RET_PT() CR_ARG_RET_PT_C(p_ctx)
-
-#define CR_CUR_LOCALS_PT(type) CR_CUR_LOCALS_PT_C(p_ctx, type)
-
-#define CR_CURR_FUNC() CR_CURR_FUNC_C(p_ctx)
-
-#define CR_CALL(call_fid, local_ret_fid) \
-  CR_CALL_C(p_ctx, call_fid, local_ret_fid)
-
-#define CR_RETURN(cur_fid, retval) CR_RETURN_C(p_ctx, cur_fid, retval)
-
-#define CR_RETURN_VOID() CR_RETURN_VOID_C(p_ctx)
-
-#define CR_RETURNED(fid) CR_RETURNED_C(p_ctx, fid)
-
-#define CR_YIELD(value, local_ret_fid) CR_YIELD_C(p_ctx, value, local_ret_fid)
-
-#define CR_YIELDED() CR_YIELDED_C(p_ctx)
-
-#define CR_RESUME(value) CR_RESUME_C(p_ctx, value)
-
-#define CR_RESUMED() CR_RESUMED_C(p_ctx)
-
-#define CR_TRY(catch_name) CR_TRY_C(p_ctx, catch_name)
-
-#define CR_CATCH(exc_id, catch_name, next_catch_name) \
-  CR_CATCH_C(p_ctx, exc_id, catch_name, next_catch_name)
-
-#define CR_ENDCATCH(endcatch_name) CR_ENDCATCH_C(p_ctx, endcatch_name)
-
-#define CR_THROW(exc_id) CR_THROW_C(p_ctx, exc_id)
-
-/* Private macros {{{ */
-
-#define _CR_CUR_FUNC_LOCALS_UPD(p_ctx)                                 \
-  do {                                                                 \
-    (p_ctx)->p_cur_func_locals = (uint8_t *) (p_ctx)->stack_data.buf + \
-                                 (p_ctx)->stack_data.len -             \
-                                 _CR_CURR_FUNC_LOCALS_SIZE(p_ctx);     \
-  } while (0)
-
-/*
- * Size of the stack needed for each try-catch block.
- * Use `_CR_TRY_MARKER()` and `_CR_TRY_CATCH_FID()` to get/set parts.
- */
-#define _CR_TRY_SIZE 2 /*CR_FID__TRY_MARKER, catch_fid*/
-
-/*
- * Evaluates to lvalue where `CR_FID__TRY_MARKER` should be stored
- */
-#define _CR_TRY_MARKER(p_ctx) \
-  *(((uint8_t *) (p_ctx)->stack_ret.buf) + (p_ctx)->stack_ret.len - 1)
-
-/*
- * Evaluates to lvalue where `catch_fid` should be stored
- */
-#define _CR_TRY_CATCH_FID(p_ctx) \
-  *(((uint8_t *) (p_ctx)->stack_ret.buf) + (p_ctx)->stack_ret.len - 2)
-
-#define _CR_CURR_FUNC_LOCALS_SIZE(p_ctx) \
-  ((p_ctx)->p_func_descrs[CR_CURR_FUNC_C(p_ctx)].locals_size)
-
-/*
- * Prepare context for calling next function.
- *
- * See comments for `CR_CALL()` macro.
- */
-#define _CR_CALL_PREPARE(p_ctx, _call_fid, _locals_size, _arg_size, \
-                         local_ret_fid)                             \
-  do {                                                              \
-    /* adjust return func id */                                     \
-    CR_CURR_FUNC_C(p_ctx) = (local_ret_fid);                        \
-                                                                    \
-    /* set called_fid */                                            \
-    (p_ctx)->called_fid = (_call_fid);                              \
-                                                                    \
-    /* set sizes: locals and arg */                                 \
-    (p_ctx)->call_locals_size = (_locals_size);                     \
-    (p_ctx)->call_arg_size = (_arg_size);                           \
-  } while (0)
-
-#define _CR_STACK_DATA_OVF_CHECK(p_ctx, inc) (0)
-
-#define _CR_STACK_DATA_UND_CHECK(p_ctx, dec) ((p_ctx)->stack_data.len < (dec))
-
-#define _CR_STACK_RET_OVF_CHECK(p_ctx, inc) (0)
-
-#define _CR_STACK_RET_UND_CHECK(p_ctx, dec) ((p_ctx)->stack_ret.len < (dec))
-
-#define _CR_STACK_FID_OVF_CHECK(p_ctx, inc) (0)
-
-#define _CR_STACK_FID_UND_CHECK(p_ctx, dec) ((p_ctx)->cur_fid_idx < (dec))
-
-#if defined(CR_TRACK_MAX_STACK_LEN)
-
-#define _CR_STACK_DATA_ALLOC(p_ctx, inc)                         \
-  do {                                                           \
-    mbuf_append(&((p_ctx)->stack_data), NULL, (inc));            \
-    if ((p_ctx)->stack_data_max_len < (p_ctx)->stack_data.len) { \
-      (p_ctx)->stack_data_max_len = (p_ctx)->stack_data.len;     \
-    }                                                            \
-  } while (0)
-
-#define _CR_STACK_RET_ALLOC(p_ctx, inc)                        \
-  do {                                                         \
-    mbuf_append(&((p_ctx)->stack_ret), NULL, (inc));           \
-    if ((p_ctx)->stack_ret_max_len < (p_ctx)->stack_ret.len) { \
-      (p_ctx)->stack_ret_max_len = (p_ctx)->stack_ret.len;     \
-    }                                                          \
-  } while (0)
-
-#else
-
-#define _CR_STACK_DATA_ALLOC(p_ctx, inc)              \
-  do {                                                \
-    mbuf_append(&((p_ctx)->stack_data), NULL, (inc)); \
-  } while (0)
-
-#define _CR_STACK_RET_ALLOC(p_ctx, inc)              \
-  do {                                               \
-    mbuf_append(&((p_ctx)->stack_ret), NULL, (inc)); \
-  } while (0)
-
-#endif
-
-#define _CR_STACK_DATA_FREE(p_ctx, dec) \
-  do {                                  \
-    (p_ctx)->stack_data.len -= (dec);   \
-  } while (0)
-
-#define _CR_STACK_RET_FREE(p_ctx, dec) \
-  do {                                 \
-    (p_ctx)->stack_ret.len -= (dec);   \
-  } while (0)
-
-#define _CR_STACK_FID_ALLOC(p_ctx, inc) \
-  do {                                  \
-    (p_ctx)->cur_fid_idx += (inc);      \
-  } while (0)
-
-#define _CR_STACK_FID_FREE(p_ctx, dec) \
-  do {                                 \
-    (p_ctx)->cur_fid_idx -= (dec);     \
-  } while (0)
-
-/* }}} */
-
-/*
- * Should be used in eval loop right after `_cr_iter_begin:` label
- */
-enum cr_status cr_on_iter_begin(struct cr_ctx *p_ctx);
-
-/*
- * Initialize context `p_ctx`.
- *
- * `p_arg_retval`: pointer to the user-defined `union user_arg_ret`
- *
- * `p_func_descrs`: array of all user function descriptors
- */
-void cr_context_init(struct cr_ctx *p_ctx, union user_arg_ret *p_arg_retval,
-                     size_t arg_retval_size,
-                     const struct cr_func_desc *p_func_descrs);
-
-/*
- * free resources occupied by context (at least, "stack" arrays)
- */
-void cr_context_free(struct cr_ctx *p_ctx);
-
-#endif /* CS_COMMON_COROUTINE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/features_profiles.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_FEATURES_PROFILES_H_
-#define CS_V7_SRC_FEATURES_PROFILES_H_
-
-#define V7_BUILD_PROFILE_MINIMAL 1
-#define V7_BUILD_PROFILE_MEDIUM 2
-#define V7_BUILD_PROFILE_FULL 3
-
-#ifndef V7_BUILD_PROFILE
-#define V7_BUILD_PROFILE V7_BUILD_PROFILE_FULL
-#endif
-
-#endif /* CS_V7_SRC_FEATURES_PROFILES_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/features_minimal.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/features_profiles.h" */
-
-#if V7_BUILD_PROFILE == V7_BUILD_PROFILE_MINIMAL
-
-/* This space is intentionally left blank. */
-
-#endif /* CS_V7_SRC_FEATURES_MINIMAL_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/features_medium.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/features_profiles.h" */
-
-#if V7_BUILD_PROFILE == V7_BUILD_PROFILE_MEDIUM
-
-#define V7_ENABLE__Date 1
-#define V7_ENABLE__Date__now 1
-#define V7_ENABLE__Date__UTC 1
-#define V7_ENABLE__Math 1
-#define V7_ENABLE__Math__atan2 1
-#define V7_ENABLE__RegExp 1
-
-#endif /* CS_V7_SRC_FEATURES_MEDIUM_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/features_full.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_FEATURES_FULL_H_
-#define CS_V7_SRC_FEATURES_FULL_H_
-
-/* Amalgamated: #include "v7/src/features_profiles.h" */
-
-#if V7_BUILD_PROFILE == V7_BUILD_PROFILE_FULL
-/*
- * DO NOT EDIT.
- * This file is generated by scripts/gen-features-full.pl.
- */
-#ifndef CS_ENABLE_UTF8
-#define CS_ENABLE_UTF8 1
-#endif
-
-#define V7_ENABLE__Array__reduce 1
-#define V7_ENABLE__Blob 1
-#define V7_ENABLE__Date 1
-#define V7_ENABLE__Date__UTC 1
-#define V7_ENABLE__Date__getters 1
-#define V7_ENABLE__Date__now 1
-#define V7_ENABLE__Date__parse 1
-#define V7_ENABLE__Date__setters 1
-#define V7_ENABLE__Date__toJSON 1
-#define V7_ENABLE__Date__toLocaleString 1
-#define V7_ENABLE__Date__toString 1
-#define V7_ENABLE__File__list 1
-#define V7_ENABLE__File__require 1
-#define V7_ENABLE__Function__bind 1
-#define V7_ENABLE__Function__call 1
-#define V7_ENABLE__Math 1
-#define V7_ENABLE__Math__abs 1
-#define V7_ENABLE__Math__acos 1
-#define V7_ENABLE__Math__asin 1
-#define V7_ENABLE__Math__atan 1
-#define V7_ENABLE__Math__atan2 1
-#define V7_ENABLE__Math__ceil 1
-#define V7_ENABLE__Math__constants 1
-#define V7_ENABLE__Math__cos 1
-#define V7_ENABLE__Math__exp 1
-#define V7_ENABLE__Math__floor 1
-#define V7_ENABLE__Math__log 1
-#define V7_ENABLE__Math__max 1
-#define V7_ENABLE__Math__min 1
-#define V7_ENABLE__Math__pow 1
-#define V7_ENABLE__Math__random 1
-#define V7_ENABLE__Math__round 1
-#define V7_ENABLE__Math__sin 1
-#define V7_ENABLE__Math__sqrt 1
-#define V7_ENABLE__Math__tan 1
-#define V7_ENABLE__Memory__stats 1
-#define V7_ENABLE__NUMBER__NEGATIVE_INFINITY 1
-#define V7_ENABLE__NUMBER__POSITIVE_INFINITY 1
-#define V7_ENABLE__Object__create 1
-#define V7_ENABLE__Object__defineProperties 1
-#define V7_ENABLE__Object__getOwnPropertyDescriptor 1
-#define V7_ENABLE__Object__getOwnPropertyNames 1
-#define V7_ENABLE__Object__getPrototypeOf 1
-#define V7_ENABLE__Object__hasOwnProperty 1
-#define V7_ENABLE__Object__isExtensible 1
-#define V7_ENABLE__Object__isFrozen 1
-#define V7_ENABLE__Object__isPrototypeOf 1
-#define V7_ENABLE__Object__isSealed 1
-#define V7_ENABLE__Object__keys 1
-#define V7_ENABLE__Object__preventExtensions 1
-#define V7_ENABLE__Object__propertyIsEnumerable 1
-#define V7_ENABLE__Proxy 1
-#define V7_ENABLE__RegExp 1
-#define V7_ENABLE__StackTrace 1
-#define V7_ENABLE__String__localeCompare 1
-#define V7_ENABLE__String__localeLowerCase 1
-#define V7_ENABLE__String__localeUpperCase 1
-
-#endif /* V7_BUILD_PROFILE == V7_BUILD_PROFILE_FULL */
-
-#endif /* CS_V7_SRC_FEATURES_FULL_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/v7_features.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_V7_FEATURES_H_
-#define CS_V7_SRC_V7_FEATURES_H_
-
-/* Only one will actually be used based on V7_BUILD_PROFILE. */
-/* Amalgamated: #include "v7/src/features_minimal.h" */
-/* Amalgamated: #include "v7/src/features_medium.h" */
-/* Amalgamated: #include "v7/src/features_full.h" */
-
-#endif /* CS_V7_SRC_V7_FEATURES_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/platform.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_PLATFORM_H_
-#define CS_V7_SRC_PLATFORM_H_
-
-#ifdef __arm
-#undef V7_ENABLE__Date
-#define V7_ENABLE__Date 0
-#endif
-
-#endif /* CS_V7_SRC_PLATFORM_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/internal.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_INTERNAL_H_
-#define CS_V7_SRC_INTERNAL_H_
-
-/* Amalgamated: #include "v7/src/license.h" */
-
-/* Check whether we're compiling in an environment with no filesystem */
-#if defined(ARDUINO) && (ARDUINO == 106)
-#define V7_NO_FS
-#endif
-
-#ifndef FAST
-#define FAST
-#endif
-
-#ifndef STATIC
-#define STATIC
-#endif
-
-#ifndef ENDL
-#define ENDL "\n"
-#endif
-
-/*
- * In some compilers (watcom) NAN == NAN (and other comparisons) don't follow
- * the rules of IEEE 754. Since we don't know a priori which compilers
- * will generate correct code, we disable the fallback on selected platforms.
- * TODO(mkm): selectively disable on clang/gcc once we test this out.
- */
-#define V7_BROKEN_NAN
-
-#undef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200809L
-
-#include <assert.h>
-#ifndef NO_LIBC
-#include <ctype.h>
-#endif
-#include <errno.h>
-#include <float.h>
-#include <limits.h>
-#include <math.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <setjmp.h>
-
-/* Public API. Implemented in api.c */
-/* Amalgamated: #include "common/platform.h" */
-
-#ifdef V7_WINDOWS
-#define vsnprintf _vsnprintf
-#define snprintf _snprintf
-
-/* VS2015 Update 1 has ISO C99 `isnan` and `isinf` defined in math.h */
-#if _MSC_FULL_VER < 190023506
-#define isnan(x) _isnan(x)
-#define isinf(x) (!_finite(x))
-#endif
-
-#define __unused __pragma(warning(suppress : 4100))
-typedef __int64 int64_t;
-typedef int int32_t;
-typedef unsigned int uint32_t;
-typedef unsigned short uint16_t;
-typedef unsigned char uint8_t;
-
-/* For 64bit VisualStudio 2010 */
-#ifndef _UINTPTR_T_DEFINED
-typedef unsigned long uintptr_t;
-#endif
-
-#ifndef __func__
-#define __func__ ""
-#endif
-
-#else
-#include <stdint.h>
-#endif
-
-/* Amalgamated: #include "v7/src/v7_features.h" */
-/* Amalgamated: #include "v7/src/platform.h" */
-
-/* MSVC6 doesn't have standard C math constants defined */
-#ifndef M_E
-#define M_E 2.71828182845904523536028747135266250
-#endif
-
-#ifndef M_LOG2E
-#define M_LOG2E 1.44269504088896340735992468100189214
-#endif
-
-#ifndef M_LOG10E
-#define M_LOG10E 0.434294481903251827651128918916605082
-#endif
-
-#ifndef M_LN2
-#define M_LN2 0.693147180559945309417232121458176568
-#endif
-
-#ifndef M_LN10
-#define M_LN10 2.30258509299404568401799145468436421
-#endif
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846264338327950288
-#endif
-
-#ifndef M_SQRT2
-#define M_SQRT2 1.41421356237309504880168872420969808
-#endif
-
-#ifndef M_SQRT1_2
-#define M_SQRT1_2 0.707106781186547524400844362104849039
-#endif
-
-#ifndef NAN
-extern double _v7_nan;
-#define HAS_V7_NAN
-#define NAN (_v7_nan)
-#endif
-
-#ifndef INFINITY
-extern double _v7_infinity;
-#define HAS_V7_INFINITY
-#define INFINITY (_v7_infinity)
-#endif
-
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif
-
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif
-
-#if defined(V7_ENABLE_GC_CHECK) || defined(V7_STACK_GUARD_MIN_SIZE) || \
-    defined(V7_ENABLE_STACK_TRACKING) || defined(V7_ENABLE_CALL_TRACE)
-/* Need to enable GCC/clang instrumentation */
-#define V7_CYG_PROFILE_ON
-#endif
-
-#if defined(V7_CYG_PROFILE_ON)
-extern struct v7 *v7_head;
-
-#if defined(V7_STACK_GUARD_MIN_SIZE)
-extern void *v7_sp_limit;
-#endif
-#endif
-
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
-#endif
-
-#define V7_STATIC_ASSERT(COND, MSG) \
-  typedef char static_assertion_##MSG[2 * (!!(COND)) - 1]
-
-#define BUF_LEFT(size, used) (((size_t)(used) < (size)) ? ((size) - (used)) : 0)
-
-#endif /* CS_V7_SRC_INTERNAL_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/core_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Core
- */
-
-#ifndef CS_V7_SRC_CORE_PUBLIC_H_
-#define CS_V7_SRC_CORE_PUBLIC_H_
-
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200809L
-#endif
-
-/* Amalgamated: #include "v7/src/license.h" */
-/* Amalgamated: #include "v7/src/v7_features.h" */
-/* Amalgamated: #include "v7/src/platform.h" */
-
-#include <stddef.h> /* For size_t */
-#include <stdio.h>  /* For FILE */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * TODO(dfrank) : improve amalgamation, so that we'll be able to include
- * files here, and include common/platform.h
- *
- * For now, copy-pasting `WARN_UNUSED_RESULT` here
- */
-#ifdef __GNUC__
-#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-#define NOINSTR __attribute__((no_instrument_function))
-#else
-#define WARN_UNUSED_RESULT
-#define NOINSTR
-#endif
-
-#define V7_VERSION "1.0"
-
-#if (defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)) || \
-    (defined(_MSC_VER) && _MSC_VER <= 1200)
-#define V7_WINDOWS
-#endif
-
-#ifdef V7_WINDOWS
-typedef unsigned __int64 uint64_t;
-#else
-#include <inttypes.h>
-#endif
-/* 64-bit value, used to store JS values */
-typedef uint64_t v7_val_t;
-
-/* JavaScript `null` value */
-#define V7_NULL ((uint64_t) 0xfffe << 48)
-
-/* JavaScript `undefined` value */
-#define V7_UNDEFINED ((uint64_t) 0xfffd << 48)
-
-/* This if-0 is a dirty workaround to force etags to pick `struct v7` */
-#if 0
-/* Opaque structure. V7 engine context. */
-struct v7 {
-  /* ... */
-};
-#endif
-
-struct v7;
-
-/*
- * Code which is returned by some of the v7 functions. If something other than
- * `V7_OK` is returned from some function, the caller function typically should
- * either immediately cleanup and return the code further, or handle the error.
- */
-enum v7_err {
-  V7_OK,
-  V7_SYNTAX_ERROR,
-  V7_EXEC_EXCEPTION,
-  V7_AST_TOO_LARGE,
-  V7_INTERNAL_ERROR,
-};
-
-/* JavaScript -> C call interface */
-WARN_UNUSED_RESULT
-typedef enum v7_err(v7_cfunction_t)(struct v7 *v7, v7_val_t *res);
-
-/* Create V7 instance */
-struct v7 *v7_create(void);
-
-/*
- * Customizations of initial V7 state; used by `v7_create_opt()`.
- */
-struct v7_create_opts {
-  size_t object_arena_size;
-  size_t function_arena_size;
-  size_t property_arena_size;
-#ifdef V7_STACK_SIZE
-  void *c_stack_base;
-#endif
-#ifdef V7_FREEZE
-  /* if not NULL, dump JS heap after init */
-  char *freeze_file;
-#endif
-};
-
-/*
- * Like `v7_create()`, but allows to customize initial v7 state, see `struct
- * v7_create_opts`.
- */
-struct v7 *v7_create_opt(struct v7_create_opts opts);
-
-/* Destroy V7 instance */
-void v7_destroy(struct v7 *v7);
-
-/* Return root level (`global`) object of the given V7 instance. */
-v7_val_t v7_get_global(struct v7 *v);
-
-/* Return current `this` object. */
-v7_val_t v7_get_this(struct v7 *v);
-
-/* Return current `arguments` array */
-v7_val_t v7_get_arguments(struct v7 *v);
-
-/* Return i-th argument */
-v7_val_t v7_arg(struct v7 *v, unsigned long i);
-
-/* Return the length of `arguments` */
-unsigned long v7_argc(struct v7 *v7);
-
-/*
- * Tells the GC about a JS value variable/field owned
- * by C code.
- *
- * User C code should own v7_val_t variables
- * if the value's lifetime crosses any invocation
- * to the v7 runtime that creates new objects or new
- * properties and thus can potentially trigger GC.
- *
- * The registration of the variable prevents the GC from mistakenly treat
- * the object as garbage. The GC might be triggered potentially
- * allows the GC to update pointers
- *
- * User code should also explicitly disown the variables with v7_disown once
- * it goes out of scope or the structure containing the v7_val_t field is freed.
- *
- * Example:
- *
- *  ```
- *    struct v7_val cb;
- *    v7_own(v7, &cb);
- *    cb = v7_array_get(v7, args, 0);
- *    // do something with cb
- *    v7_disown(v7, &cb);
- *  ```
- */
-void v7_own(struct v7 *v7, v7_val_t *v);
-
-/*
- * Returns 1 if value is found, 0 otherwise
- */
-int v7_disown(struct v7 *v7, v7_val_t *v);
-
-/*
- * Enable or disable GC.
- *
- * Must be called before invoking v7_exec or v7_apply
- * from within a cfunction unless you know what you're doing.
- *
- * GC is disabled during execution of cfunctions in order to simplify
- * memory management of simple cfunctions.
- * However executing even small snippets of JS code causes a lot of memory
- * pressure. Enabling GC solves that but forces you to take care of the
- * reachability of your temporary V7 v7_val_t variables, as the GC needs
- * to know where they are since objects and strings can be either reclaimed
- * or relocated during a GC pass.
- */
-void v7_set_gc_enabled(struct v7 *v7, int enabled);
-
-/*
- * Set an optional C stack limit.
- *
- * It sets a flag that will cause the interpreter
- * to throw an InterruptedError.
- * It's safe to call it from signal handlers and ISRs
- * on single threaded environments.
- */
-void v7_interrupt(struct v7 *v7);
-
-/* Returns last parser error message. TODO: rename it to `v7_get_error()` */
-const char *v7_get_parser_error(struct v7 *v7);
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-/*
- * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
- *
- * Stack metric id. See `v7_stack_stat()`
- */
-enum v7_stack_stat_what {
-  /* max stack size consumed by `i_exec()` */
-  V7_STACK_STAT_EXEC,
-  /* max stack size consumed by `parse()` (which is called from `i_exec()`) */
-  V7_STACK_STAT_PARSER,
-
-  V7_STACK_STATS_CNT
-};
-
-/*
- * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
- *
- * Returns stack metric specified by the metric id `what`. See
- * `v7_stack_stat_clean()`
- */
-int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what);
-
-/*
- * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
- *
- * Clean all stack statistics gathered so far. See `v7_stack_stat()`
- */
-void v7_stack_stat_clean(struct v7 *v7);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_CORE_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_error.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_ERROR_H_
-#define CS_V7_SRC_STD_ERROR_H_
-
-/* Amalgamated: #include "v7/src/license.h" */
-
-struct v7;
-
-/*
- * JavaScript error types
- */
-#define TYPE_ERROR "TypeError"
-#define SYNTAX_ERROR "SyntaxError"
-#define REFERENCE_ERROR "ReferenceError"
-#define INTERNAL_ERROR "InternalError"
-#define RANGE_ERROR "RangeError"
-#define EVAL_ERROR "EvalError"
-#define ERROR_CTOR_MAX 6
-/*
- * TODO(mkm): EvalError is not so important, we should guard it behind
- * something like `V7_ENABLE__EvalError`. However doing so makes it hard to
- * keep ERROR_CTOR_MAX up to date; perhaps let's find a better way of doing it.
- *
- * EvalError is useful mostly because we now have ecma tests failing:
- *
- * 8129 FAIL ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-7-c-iii-24.js (tail -c
- * +7600043 tests/ecmac.db|head -c 496): [{"message":"[EvalError] is not
- * defined"}]
- *
- * Those tests are not EvalError specific, and they do test that the exception
- * handling machinery works as intended.
- */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void init_error(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STD_ERROR_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/mm.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_MM_H_
-#define CS_V7_SRC_MM_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-typedef void (*gc_cell_destructor_t)(struct v7 *v7, void *);
-
-struct gc_block {
-  struct gc_block *next;
-  struct gc_cell *base;
-  size_t size;
-};
-
-struct gc_arena {
-  struct gc_block *blocks;
-  size_t size_increment;
-  struct gc_cell *free; /* head of free list */
-  size_t cell_size;
-
-#if V7_ENABLE__Memory__stats
-  unsigned long allocations; /* cumulative counter of allocations */
-  unsigned long garbage;     /* cumulative counter of garbage */
-  unsigned long alive;       /* number of living cells */
-#endif
-
-  gc_cell_destructor_t destructor;
-
-  int verbose;
-  const char *name; /* for debugging purposes */
-};
-
-#endif /* CS_V7_SRC_MM_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/parser.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_PARSER_H_
-#define CS_V7_SRC_PARSER_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if !defined(V7_NO_COMPILER)
-
-struct v7;
-struct ast;
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-struct v7_pstate {
-  const char *file_name;
-  const char *source_code;
-  const char *pc;      /* Current parsing position */
-  const char *src_end; /* End of source code */
-  int line_no;         /* Line number */
-  int prev_line_no;    /* Line number of previous token */
-  int inhibit_in;      /* True while `in` expressions are inhibited */
-  int in_function;     /* True if in a function */
-  int in_loop;         /* True if in a loop */
-  int in_switch;       /* True if in a switch block */
-  int in_strict;       /* True if in strict mode */
-};
-
-V7_PRIVATE enum v7_err parse(struct v7 *v7, struct ast *a, const char *src,
-                             size_t src_len, int is_json);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_NO_COMPILER */
-
-#endif /* CS_V7_SRC_PARSER_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/object_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Objects
- */
-
-#ifndef CS_V7_SRC_OBJECT_PUBLIC_H_
-#define CS_V7_SRC_OBJECT_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Property attributes bitmask
- */
-typedef unsigned short v7_prop_attr_t;
-#define V7_PROPERTY_NON_WRITABLE (1 << 0)
-#define V7_PROPERTY_NON_ENUMERABLE (1 << 1)
-#define V7_PROPERTY_NON_CONFIGURABLE (1 << 2)
-#define V7_PROPERTY_GETTER (1 << 3)
-#define V7_PROPERTY_SETTER (1 << 4)
-#define _V7_PROPERTY_HIDDEN (1 << 5)
-/* property not managed by V7 HEAP */
-#define _V7_PROPERTY_OFF_HEAP (1 << 6)
-/* special property holding user data and destructor cb */
-#define _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR (1 << 7)
-/*
- * not a property attribute, but a flag for `v7_def()`. It's here in order to
- * keep all offsets in one place
- */
-#define _V7_DESC_PRESERVE_VALUE (1 << 8)
-
-#define V7_PROP_ATTR_IS_WRITABLE(a) (!(a & V7_PROPERTY_NON_WRITABLE))
-#define V7_PROP_ATTR_IS_ENUMERABLE(a) (!(a & V7_PROPERTY_NON_ENUMERABLE))
-#define V7_PROP_ATTR_IS_CONFIGURABLE(a) (!(a & V7_PROPERTY_NON_CONFIGURABLE))
-
-/*
- * Internal helpers for `V7_DESC_...` macros
- */
-#define _V7_DESC_SHIFT 16
-#define _V7_DESC_MASK ((1 << _V7_DESC_SHIFT) - 1)
-#define _V7_MK_DESC(v, n) \
-  (((v7_prop_attr_desc_t)(n)) << _V7_DESC_SHIFT | ((v) ? (n) : 0))
-#define _V7_MK_DESC_INV(v, n) _V7_MK_DESC(!(v), (n))
-
-/*
- * Property attribute descriptors that may be given to `v7_def()`: for each
- * attribute (`v7_prop_attr_t`), there is a corresponding macro, which takes
- * param: either 1 (set attribute) or 0 (clear attribute). If some particular
- * attribute isn't mentioned at all, it's left unchanged (or default, if the
- * property is being created)
- *
- * There is additional flag: `V7_DESC_PRESERVE_VALUE`. If it is set, the
- * property value isn't changed (or set to `undefined` if the property is being
- * created)
- */
-typedef unsigned long v7_prop_attr_desc_t;
-#define V7_DESC_WRITABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_WRITABLE)
-#define V7_DESC_ENUMERABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_ENUMERABLE)
-#define V7_DESC_CONFIGURABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_CONFIGURABLE)
-#define V7_DESC_GETTER(v) _V7_MK_DESC(v, V7_PROPERTY_GETTER)
-#define V7_DESC_SETTER(v) _V7_MK_DESC(v, V7_PROPERTY_SETTER)
-#define V7_DESC_PRESERVE_VALUE _V7_DESC_PRESERVE_VALUE
-
-#define _V7_DESC_HIDDEN(v) _V7_MK_DESC(v, _V7_PROPERTY_HIDDEN)
-#define _V7_DESC_OFF_HEAP(v) _V7_MK_DESC(v, _V7_PROPERTY_OFF_HEAP)
-
-/* See `v7_set_destructor_cb` */
-typedef void(v7_destructor_cb_t)(struct v7 *v7, void *ud);
-
-/* Make an empty object */
-v7_val_t v7_mk_object(struct v7 *v7);
-
-/*
- * Returns true if the given value is an object or function.
- * i.e. it returns true if the value holds properties and can be
- * used as argument to `v7_get`, `v7_set` and `v7_def`.
- */
-int v7_is_object(v7_val_t v);
-
-/* Set object's prototype. Return old prototype or undefined on error. */
-v7_val_t v7_set_proto(struct v7 *v7, v7_val_t obj, v7_val_t proto);
-
-/* Get object's prototype. */
-v7_val_t v7_get_proto(struct v7 *v7, v7_val_t obj);
-
-/*
- * Lookup property `name` in object `obj`. If `obj` holds no such property,
- * an `undefined` value is returned.
- *
- * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
- * `strlen(name)` is used.
- */
-v7_val_t v7_get(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len);
-
-/*
- * Like `v7_get()`, but "returns" value through `res` pointer argument.
- * `res` must not be `NULL`.
- *
- * Caller should check the error code returned, and if it's something other
- * than `V7_OK`, perform cleanup and return this code further.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_get_throwing(struct v7 *v7, v7_val_t obj, const char *name,
-                            size_t name_len, v7_val_t *res);
-
-/*
- * Define object property, similar to JavaScript `Object.defineProperty()`.
- *
- * `name`, `name_len` specify property name, `val` is a property value.
- * `attrs_desc` is a set of flags which can affect property's attributes,
- * see comment of `v7_prop_attr_desc_t` for details.
- *
- * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
- * `strlen(name)` is used.
- *
- * Returns non-zero on success, 0 on error (e.g. out of memory).
- *
- * See also `v7_set()`.
- */
-int v7_def(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len,
-           v7_prop_attr_desc_t attrs_desc, v7_val_t v);
-
-/*
- * Set object property. Behaves just like JavaScript assignment.
- *
- * See also `v7_def()`.
- */
-int v7_set(struct v7 *v7, v7_val_t obj, const char *name, size_t len,
-           v7_val_t val);
-
-/*
- * A helper function to define object's method backed by a C function `func`.
- * `name` must be NUL-terminated.
- *
- * Return value is the same as for `v7_set()`.
- */
-int v7_set_method(struct v7 *, v7_val_t obj, const char *name,
-                  v7_cfunction_t *func);
-
-/*
- * Delete own property `name` of the object `obj`. Does not follow the
- * prototype chain.
- *
- * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
- * `strlen(name)` is used.
- *
- * Returns 0 on success, -1 on error.
- */
-int v7_del(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len);
-
-#if V7_ENABLE__Proxy
-struct prop_iter_proxy_ctx;
-#endif
-
-/*
- * Context for property iteration, see `v7_next_prop()`.
- *
- * Clients should not interpret contents of this structure, it's here merely to
- * allow clients to allocate it not from the heap.
- */
-struct prop_iter_ctx {
-#if V7_ENABLE__Proxy
-  struct prop_iter_proxy_ctx *proxy_ctx;
-#endif
-  struct v7_property *cur_prop;
-
-  unsigned init : 1;
-};
-
-/*
- * Initialize the property iteration context `ctx`, see `v7_next_prop()` for
- * usage example.
- */
-enum v7_err v7_init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
-                                  struct prop_iter_ctx *ctx);
-
-/*
- * Destruct the property iteration context `ctx`, see `v7_next_prop()` for
- * usage example
- */
-void v7_destruct_prop_iter_ctx(struct v7 *v7, struct prop_iter_ctx *ctx);
-
-/*
- * Iterate over the `obj`'s properties.
- *
- * Usage example (here we assume we have some `v7_val_t obj`):
- *
- *     struct prop_iter_ctx ctx;
- *     v7_val_t name, val;
- *     v7_prop_attr_t attrs;
- *
- *     v7_init_prop_iter_ctx(v7, obj, &ctx);
- *     while (v7_next_prop(v7, &ctx, &name, &val, &attrs)) {
- *       if (V7_PROP_ATTR_IS_ENUMERABLE(attrs)) continue;
- *       ...
- *     }
- *     v7_destruct_prop_iter_ctx(v7, &ctx);
- *
- * As you see, v7_next_prop will iterate through all properties, including
- * non-enumerable ones, and it's your responsibility to test the attributes
- * with the provided `V7_PROP_ATTR_*` macros and proceed as you see fit.
- */
-int v7_next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, v7_val_t *name,
-                 v7_val_t *value, v7_prop_attr_t *attrs);
-
-/* Returns true if the object is an instance of a given constructor. */
-int v7_is_instanceof(struct v7 *v7, v7_val_t o, const char *c);
-
-/* Returns true if the object is an instance of a given constructor. */
-int v7_is_instanceof_v(struct v7 *v7, v7_val_t o, v7_val_t c);
-
-/*
- * Associates an opaque C value (anything that can be casted to a `void * )
- * with an object.
- *
- * You can achieve a similar effect by just setting a special property with
- * a foreign value (see `v7_mk_foreign`), except user data offers the following
- * advantages:
- *
- * 1. You don't have to come up with some arbitrary "special" property name.
- * 2. JS scripts cannot access user data by mistake via property lookup.
- * 3. The user data is available to the destructor. When the desctructor is
- *    invoked you cannot access any of its properties.
- * 4. Allows the implementation to use a more compact encoding
- *
- * Does nothing if `obj` is not a mutable object.
- */
-void v7_set_user_data(struct v7 *v7, v7_val_t obj, void *ud);
-
-/*
- * Get the opaque user data set with `v7_set_user_data`.
- *
- * Returns NULL if there is no user data set or if `obj` is not an object.
- */
-void *v7_get_user_data(struct v7 *v7, v7_val_t obj);
-
-/*
- * Register a callback which will be invoked when a given object gets
- * reclaimed by the garbage collector.
- *
- * The callback will be invoked while garbage collection is still in progress
- * and hence the internal state of the JS heap is in an undefined state.
- *
- * The only v7 API which is safe to use in this callback is `v7_disown()`,
- * that's why `v7` pointer is given to it. *Calls to any other v7 functions are
- * illegal here*.
- *
- * The intended use case is to reclaim resources allocated by C code.
- */
-void v7_set_destructor_cb(struct v7 *v7, v7_val_t obj, v7_destructor_cb_t *d);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_OBJECT_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/tokenizer.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_TOKENIZER_H_
-#define CS_V7_SRC_TOKENIZER_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-#if !defined(V7_NO_COMPILER)
-
-enum v7_tok {
-  TOK_END_OF_INPUT,
-  TOK_NUMBER,
-  TOK_STRING_LITERAL,
-  TOK_REGEX_LITERAL,
-  TOK_IDENTIFIER,
-
-  /* Punctuators */
-  TOK_OPEN_CURLY,
-  TOK_CLOSE_CURLY,
-  TOK_OPEN_PAREN,
-  TOK_CLOSE_PAREN,
-  TOK_COMMA,
-  TOK_OPEN_BRACKET,
-  TOK_CLOSE_BRACKET,
-  TOK_DOT,
-  TOK_COLON,
-  TOK_SEMICOLON,
-
-  /* Equality ops, in this order */
-  TOK_EQ,
-  TOK_EQ_EQ,
-  TOK_NE,
-  TOK_NE_NE,
-
-  /* Assigns */
-  TOK_ASSIGN,
-  TOK_REM_ASSIGN,
-  TOK_MUL_ASSIGN,
-  TOK_DIV_ASSIGN,
-  TOK_XOR_ASSIGN,
-  TOK_PLUS_ASSIGN,
-  TOK_MINUS_ASSIGN,
-  TOK_OR_ASSIGN,
-  TOK_AND_ASSIGN,
-  TOK_LSHIFT_ASSIGN,
-  TOK_RSHIFT_ASSIGN,
-  TOK_URSHIFT_ASSIGN,
-  TOK_AND,
-  TOK_LOGICAL_OR,
-  TOK_PLUS,
-  TOK_MINUS,
-  TOK_PLUS_PLUS,
-  TOK_MINUS_MINUS,
-  TOK_LOGICAL_AND,
-  TOK_OR,
-  TOK_QUESTION,
-  TOK_TILDA,
-  TOK_REM,
-  TOK_MUL,
-  TOK_DIV,
-  TOK_XOR,
-
-  /* Relational ops, must go in this order */
-  TOK_LE,
-  TOK_LT,
-  TOK_GE,
-  TOK_GT,
-  TOK_LSHIFT,
-  TOK_RSHIFT,
-  TOK_URSHIFT,
-  TOK_NOT,
-
-  /* Keywords. must be in the same order as tokenizer.c::s_keywords array */
-  TOK_BREAK,
-  TOK_CASE,
-  TOK_CATCH,
-  TOK_CONTINUE,
-  TOK_DEBUGGER,
-  TOK_DEFAULT,
-  TOK_DELETE,
-  TOK_DO,
-  TOK_ELSE,
-  TOK_FALSE,
-  TOK_FINALLY,
-  TOK_FOR,
-  TOK_FUNCTION,
-  TOK_IF,
-  TOK_IN,
-  TOK_INSTANCEOF,
-  TOK_NEW,
-  TOK_NULL,
-  TOK_RETURN,
-  TOK_SWITCH,
-  TOK_THIS,
-  TOK_THROW,
-  TOK_TRUE,
-  TOK_TRY,
-  TOK_TYPEOF,
-  TOK_VAR,
-  TOK_VOID,
-  TOK_WHILE,
-  TOK_WITH,
-
-  /* TODO(lsm): process these reserved words too */
-  TOK_CLASS,
-  TOK_ENUM,
-  TOK_EXTENDS,
-  TOK_SUPER,
-  TOK_CONST,
-  TOK_EXPORT,
-  TOK_IMPORT,
-  TOK_IMPLEMENTS,
-  TOK_LET,
-  TOK_PRIVATE,
-  TOK_PUBLIC,
-  TOK_INTERFACE,
-  TOK_PACKAGE,
-  TOK_PROTECTED,
-  TOK_STATIC,
-  TOK_YIELD,
-
-  NUM_TOKENS
-};
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE int skip_to_next_tok(const char **ptr, const char *src_end);
-V7_PRIVATE enum v7_tok get_tok(const char **s, const char *src_end, double *n,
-                               enum v7_tok prev_tok);
-V7_PRIVATE int is_reserved_word_token(enum v7_tok tok);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_NO_COMPILER */
-
-#endif /* CS_V7_SRC_TOKENIZER_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/opcodes.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_OPCODES_H_
-#define CS_V7_SRC_OPCODES_H_
-
-/*
- * ==== Instructions
- *
- * Bytecode instructions consist of 1-byte opcode, optionally followed by N
- * bytes of arguments.
- *
- * Opcodes that accept an index in the literal table (PUSH_LIT, GET_VAR,
- * SET_VAR, ...) also accept inline literals. In order to distinguish indices in
- * the literals table and the inline literals, indices 0 and 1 are reserved as
- * type tags for inline literals:
- *
- * if 0, the following bytes encode a string literal
- * if 1, they encode a number (textual, like in the AST)
- *
- * (see enum bcode_inline_lit_type_tag)
- *
- *
- * Stack diagrams follow the syntax and semantics of:
- *
- * http://everything2.com/title/Forth+stack+diagrams[Forth stack diagrams].
- *
- * We use the following extension in the terminology:
- *
- * `T`: "Try stack".
- * `A`: opcode arguments.
- * `S`: stash register (one element stack).
- *
- */
-enum opcode {
-  /*
-   * Removes an item from the top of the stack. It is undefined what happens if
-   * the stack is empty.
-   *
-   * `( a -- )`
-  */
-  OP_DROP,
-  /*
-   * Duplicates a value on top of the stack.
-   *
-   * `( a -- a a)`
-  */
-  OP_DUP,
-  /*
-   * Duplicates 2 values from the top of the stack in the same order.
-   *
-   * `( a b -- a b a b)`
-  */
-  OP_2DUP,
-  /*
-   * Swap the top two items on the stack.
-   *
-   * `( a b -- b a )`
-   */
-  OP_SWAP,
-  /*
-   * Copy current top of the stack to the temporary stash register.
-   *
-   * The content of the stash register will be cleared in the event of an
-   * exception.
-   *
-   * `( a S: b -- a S: a)` saves TOS to stash reg
-   */
-  OP_STASH,
-  /*
-   * Replace the top of the stack with the content of the temporary stash
-   * register.
-   *
-   * The stash register is cleared afterwards.
-   *
-   * `( a S: b -- b S: nil )` replaces tos with stash reg
-   */
-  OP_UNSTASH,
-
-  /*
-   * Effectively drops the last-but-one element from stack
-   *
-   * `( a b -- b )`
-   */
-  OP_SWAP_DROP,
-
-  /*
-   * Pushes `undefined` onto the stack.
-   *
-   * `( -- undefined )`
-   */
-  OP_PUSH_UNDEFINED,
-  /*
-   * Pushes `null` onto the stack.
-   *
-   * `( -- null )`
-   */
-  OP_PUSH_NULL,
-  /*
-   * Pushes current value of `this` onto the stack.
-   *
-   * `( -- this )`
-   */
-  OP_PUSH_THIS,
-  /*
-   * Pushes `true` onto the stack.
-   *
-   * `( -- true )`
-   */
-  OP_PUSH_TRUE,
-  /*
-   * Pushes `false` onto the stack.
-   *
-   * `( -- false )`
-   */
-  OP_PUSH_FALSE,
-  /*
-   * Pushes `0` onto the stack.
-   *
-   * `( -- 0 )`
-   */
-  OP_PUSH_ZERO,
-  /*
-   * Pushes `1` onto the stack.
-   *
-   * `( -- 1 )`
-   */
-  OP_PUSH_ONE,
-
-  /*
-   * Pushes a value from literals table onto the stack.
-   *
-   * The opcode takes a varint operand interpreted as an index in the current
-   * literal table (see lit table).
-   *
-   * ( -- a )
-   */
-  OP_PUSH_LIT,
-
-  OP_NOT,
-  OP_LOGICAL_NOT,
-
-  /*
-   * Takes a number from the top of the stack, inverts the sign and pushes it
-   * back.
-   *
-   * `( a -- -a )`
-   */
-  OP_NEG,
-  /*
-   * Takes a number from the top of the stack pushes the evaluation of
-   * `Number()`.
-   *
-   * `( a -- Number(a) )`
-   */
-  OP_POS,
-
-  /*
-   * Takes 2 values from the top of the stack and performs addition operation:
-   * If any of the two values is not `undefined`, number or boolean, both values
-   * are converted into strings and concatenated.
-   * Otherwise, both values are treated as numbers:
-   * * `undefined` is converted into NaN
-   * * `true` is converted into 1
-   * * `false` is converted into 0
-   *
-   * Result is pushed back onto the stack.
-   *
-   * TODO: make it behave exactly like JavaScript's `+` operator.
-   *
-   * `( a b -- a+b )`
-   */
-  OP_ADD,
-  OP_SUB,     /* ( a b -- a-b ) */
-  OP_REM,     /* ( a b -- a%b ) */
-  OP_MUL,     /* ( a b -- a*b ) */
-  OP_DIV,     /* ( a b -- a/b ) */
-  OP_LSHIFT,  /* ( a b -- a<<b ) */
-  OP_RSHIFT,  /* ( a b -- a>>b ) */
-  OP_URSHIFT, /* ( a b -- a>>>b ) */
-  OP_OR,      /* ( a b -- a|b ) */
-  OP_XOR,     /* ( a b -- a^b ) */
-  OP_AND,     /* ( a b -- a&b ) */
-
-  /*
-   * Takes two numbers form the top of the stack and pushes `true` if they are
-   * equal, or `false` if they are not equal.
-   *
-   * ( a b -- a===b )
-   */
-  OP_EQ_EQ,
-  OP_EQ,    /* ( a b -- a==b ) */
-  OP_NE,    /* ( a b -- a!=b ) */
-  OP_NE_NE, /* ( a b -- a!==b ) */
-  OP_LT,    /* ( a b -- a<b ) */
-  OP_LE,    /* ( a b -- a<=b ) */
-  OP_GT,    /* ( a b -- a>b ) */
-  OP_GE,    /* ( a b -- a>=b ) */
-  OP_INSTANCEOF,
-
-  OP_TYPEOF,
-
-  OP_IN,
-  /*
-   * Takes 2 values from the stack, treats the top of the stack as property name
-   * and the next value must be an object, an array or a string.
-   * If it's an object, pushes the value of its named property onto the stack.
-   * If it's an array or a string, returns a value at a given position.
-  */
-  OP_GET,
-  /*
-   * Takes 3 items from the stack: value, property name, object. Sets the given
-   * property of a given object to a given value, pushes value back onto the
-   *stack.
-   *
-   * `( a b c -- a[b]=c )`
-  */
-  OP_SET,
-  /*
-   * Takes 1 value from the stack and a varint argument -- index of the var name
-   * in the literals table. Tries to find the variable in the current scope
-   * chain and assign the value to it. If the varialble is not found -- creates
-   * a new one in the global scope. Pushes the value back to the stack.
-   *
-   * `( a -- a )`
-   */
-  OP_SET_VAR,
-  /*
-   * Takes a varint argument -- index of the var name in the literals table.
-   * Looks up that variable in the scope chain and pushes its value onto the
-   * stack.
-   *
-   * `( -- a )`
-   */
-  OP_GET_VAR,
-
-  /*
-   * Like OP_GET_VAR but returns undefined
-   * instead of throwing reference error.
-   *
-   * `( -- a )`
-   */
-  OP_SAFE_GET_VAR,
-
-  /*
-   * ==== Jumps
-   *
-   * All jump instructions take one 4-byte argument: offset to jump to. Offset
-   *is a
-   * index of the byte in the instruction stream, starting with 0. No byte order
-   * conversion is applied.
-   *
-   * TODO: specify byte order for the offset.
-   */
-
-  /*
-   * Unconditiona jump.
-   */
-  OP_JMP,
-  /*
-   * Takes one value from the stack and performs a jump if conversion of that
-   * value to boolean results in `true`.
-   *
-   * `( a -- )`
-  */
-  OP_JMP_TRUE,
-  /*
-   * Takes one value from the stack and performs a jump if conversion of that
-   * value to boolean results in `false`.
-   *
-   * `( a -- )`
-   */
-  OP_JMP_FALSE,
-  /*
-   * Like OP_JMP_TRUE but if the branch
-   * is taken it also drops another stack element:
-   *
-   * if `b` is true: `( a b -- )`
-   * if `b` is false: `( a b -- a )`
-   */
-  OP_JMP_TRUE_DROP,
-
-  /*
-   * Conditional jump on the v7->is_continuing flag.
-   * Clears the flag once executed.
-   *
-   * `( -- )`
-   */
-  OP_JMP_IF_CONTINUE,
-
-  /*
-   * Constructs a new empty object and pushes it onto the stack.
-   *
-   * `( -- {} )`
-   */
-  OP_CREATE_OBJ,
-  /*
-   * Constructs a new empty array and pushes it onto the stack.
-   *
-   * `( -- [] )`
-   */
-  OP_CREATE_ARR,
-
-  /*
-   * Allocates the iteration context (for `OP_NEXT_PROP`) from heap and pushes
-   * a foreign pointer to it on stack. The allocated data is stored as "user
-   * data" of the object, and it will be reclaimed automatically when the
-   * object gets garbage-collected.
-   *
-   * `( -- ctx )`
-   */
-  OP_PUSH_PROP_ITER_CTX,
-
-  /*
-   * Yields the next property name.
-   * Used in the for..in construct.
-   *
-   * The first evaluation must receive `null` as handle.
-   * Subsequent evaluations will either:
-   *
-   * a) produce a new handle, the key and true value:
-   *
-   * `( o h -- o h' key true)`
-   *
-   * b) produce a false value only, indicating no more properties:
-   *
-   * `( o h -- false)`
-   */
-  OP_NEXT_PROP,
-
-  /*
-   * Copies the function object at TOS and assigns current scope
-   * in func->scope.
-   *
-   * `( a -- a )`
-   */
-  OP_FUNC_LIT,
-  /*
-   * Takes the number of arguments as parameter.
-   *
-   * Pops N function arguments from stack, then pops function, then pops `this`.
-   * Calls a function and populates TOS with the returned value.
-   *
-   * `( this f a0 a1 ... aN -- f(a0,a1,...) )`
-   */
-  OP_CALL,
-  OP_NEW,
-  /*
-   * Checks that TOS is a callable and if not saves an exception
-   * that will will be thrown by CALL after all arguments have been evaluated.
-   */
-  OP_CHECK_CALL,
-  /*
-   * Returns the current function.
-   *
-   * It has no stack side effects. The function upon return will leave the
-   * return value on the stack. The return value must be pushed on the stack
-   * prior to invoking a RET.
-   *
-   * `( -- )`
-   */
-  OP_RET,
-
-  /*
-   * Deletes the property of given name `p` from the given object `o`. Returns
-   * boolean value `a`.
-   *
-   * `( o p -- a )`
-   */
-  OP_DELETE,
-
-  /*
-   * Like `OP_DELETE`, but uses the current scope as an object to delete
-   * a property from.
-   *
-   * `( p -- a )`
-   */
-  OP_DELETE_VAR,
-
-  /*
-   * Pushes a value (bcode offset of `catch` block) from opcode argument to
-   * "try stack".
-   *
-   * Used in the beginning of the `try` block.
-   *
-   * `( A: a -- T: a )`
-   */
-  OP_TRY_PUSH_CATCH,
-
-  /*
-   * Pushes a value (bcode offset of `finally` block) from opcode argument to
-   * "try stack".
-   *
-   * Used in the beginning of the `try` block.
-   *
-   * `( A: a -- T: a )`
-   *
-   * TODO: implement me
-   */
-  OP_TRY_PUSH_FINALLY,
-
-  /*
-   * Pushes a value (bcode offset of a label) from opcode argument to
-   * "try stack".
-   *
-   * Used at the beginning of loops that contain break or continue.
-   * Possible optimisation: don't emit if we can ensure that no break or
-   * continue statement is used.
-   *
-   * `( A: a -- T: a )`
-   */
-  OP_TRY_PUSH_LOOP,
-
-  /*
-   * Pushes a value (bcode offset of a label) from opcode argument to
-   * "try stack".
-   *
-   * Used at the beginning of switch statements.
-   *
-   * `( A: a -- T: a )`
-   */
-  OP_TRY_PUSH_SWITCH,
-
-  /*
-   * Pops a value (bcode offset of `finally` or `catch` block) from "try
-   * stack", and discards it
-   *
-   * Used in the end of the `try` block, as well as in the beginning of the
-   * `catch` and `finally` blocks
-   *
-   * `( T: a -- T: )`
-   */
-  OP_TRY_POP,
-
-  /*
-   * Used in the end of the `finally` block:
-   *
-   * - if some value is currently being thrown, keep throwing it.
-   *   If eventually we encounter `catch` block, the thrown value gets
-   *   populated on TOS:
-   *
-   *   `( -- a )`
-   *
-   * - if there is some pending value to return, keep returning it.
-   *   If we encounter no further `finally` blocks, then the returned value
-   *   gets populated on TOS:
-   *
-   *   `( -- a )`
-   *
-   *   And return is performed.
-   *
-   * - otherwise, do nothing
-   */
-  OP_AFTER_FINALLY,
-
-  /*
-   * Throw value from TOS. First of all, it pops the value and saves it into
-   * `v7->vals.thrown_error`:
-   *
-   * `( a -- )`
-   *
-   * Then unwinds stack looking for the first `catch` or `finally` blocks.
-   *
-   * - if `finally` is found, thrown value is kept into `v7->vals.thrown_error`.
-   * - if `catch` is found, thrown value is pushed back to the stack:
-   *   `( -- a )`
-   * - otherwise, thrown value is kept into `v7->vals.thrown_error`
-   */
-  OP_THROW,
-
-  /*
-   * Unwind to next break entry in the try stack, evaluating
-   * all finally blocks on its way up.
-   *
-   * `( -- )`
-   */
-  OP_BREAK,
-
-  /*
-   * Like OP_BREAK, but sets the v7->is_continuing flag
-   * which will cause OP_JMP_IF_CONTINUE to restart the loop.
-   *
-   * `( -- )`
-   */
-  OP_CONTINUE,
-
-  /*
-   * Used when we enter the `catch` block. Takes a varint argument -- index of
-   * the exception variable name in the literals table.
-   *
-   * Pops the exception value from the stack, creates a private frame,
-   * sets exception property on it with the given name. pushes this
-   * private frame to call stack.
-   *
-   * `( e -- )`
-   */
-  OP_ENTER_CATCH,
-
-  /*
-   * Ued when we exit from the `catch` block. Merely pops the private frame
-   * from the call stack.
-   *
-   * `( -- )`
-   */
-  OP_EXIT_CATCH,
-
-  OP_MAX,
-};
-
-#define _OP_LINE_NO 0x80
-
-#endif /* CS_V7_SRC_OPCODES_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/core.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_CORE_H_
-#define CS_V7_SRC_CORE_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-/* Amalgamated: #include "common/mbuf.h" */
-/* Amalgamated: #include "v7/src/std_error.h" */
-/* Amalgamated: #include "v7/src/mm.h" */
-/* Amalgamated: #include "v7/src/parser.h" */
-/* Amalgamated: #include "v7/src/object_public.h" */
-/* Amalgamated: #include "v7/src/tokenizer.h" */
-/* Amalgamated: #include "v7/src/opcodes.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-typedef uint64_t val_t;
-
-#if defined(V7_ENABLE_ENTITY_IDS)
-
-typedef unsigned short entity_id_t;
-typedef unsigned char entity_id_part_t;
-
-/*
- * Magic numbers that are stored in various objects in order to identify their
- * type in runtime
- */
-#define V7_ENTITY_ID_PROP 0xe9a1
-#define V7_ENTITY_ID_PART_OBJ 0x57
-#define V7_ENTITY_ID_PART_GEN_OBJ 0x31
-#define V7_ENTITY_ID_PART_JS_FUNC 0x0d
-
-#define V7_ENTITY_ID_NONE 0xa5a5
-#define V7_ENTITY_ID_PART_NONE 0xa5
-
-#endif
-
-/*
- *  Double-precision floating-point number, IEEE 754
- *
- *  64 bit (8 bytes) in total
- *  1  bit sign
- *  11 bits exponent
- *  52 bits mantissa
- *      7         6        5        4        3        2        1        0
- *  seeeeeee|eeeemmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm
- *
- * If an exponent is all-1 and mantissa is all-0, then it is an INFINITY:
- *  11111111|11110000|00000000|00000000|00000000|00000000|00000000|00000000
- *
- * If an exponent is all-1 and mantissa's MSB is 1, it is a quiet NaN:
- *  11111111|11111000|00000000|00000000|00000000|00000000|00000000|00000000
- *
- *  V7 NaN-packing:
- *    sign and exponent is 0xfff
- *    4 bits specify type (tag), must be non-zero
- *    48 bits specify value
- *
- *  11111111|1111tttt|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv
- *   NaN marker |type|  48-bit placeholder for values: pointers, strings
- *
- * On 64-bit platforms, pointers are really 48 bit only, so they can fit,
- * provided they are sign extended
- */
-
-/*
- * A tag is made of the sign bit and the 4 lower order bits of byte 6.
- * So in total we have 32 possible tags.
- *
- * Tag (1,0) however cannot hold a zero payload otherwise it's interpreted as an
- * INFINITY; for simplicity we're just not going to use that combination.
- */
-#define MAKE_TAG(s, t) \
-  ((uint64_t)(s) << 63 | (uint64_t) 0x7ff0 << 48 | (uint64_t)(t) << 48)
-
-#define V7_TAG_OBJECT MAKE_TAG(1, 0xF)
-#define V7_TAG_FOREIGN MAKE_TAG(1, 0xE)
-#define V7_TAG_UNDEFINED MAKE_TAG(1, 0xD)
-#define V7_TAG_BOOLEAN MAKE_TAG(1, 0xC)
-#define V7_TAG_NAN MAKE_TAG(1, 0xB)
-#define V7_TAG_STRING_I MAKE_TAG(1, 0xA)  /* Inlined string len < 5 */
-#define V7_TAG_STRING_5 MAKE_TAG(1, 0x9)  /* Inlined string len 5 */
-#define V7_TAG_STRING_O MAKE_TAG(1, 0x8)  /* Owned string */
-#define V7_TAG_STRING_F MAKE_TAG(1, 0x7)  /* Foreign string */
-#define V7_TAG_STRING_C MAKE_TAG(1, 0x6)  /* String chunk */
-#define V7_TAG_FUNCTION MAKE_TAG(1, 0x5)  /* JavaScript function */
-#define V7_TAG_CFUNCTION MAKE_TAG(1, 0x4) /* C function */
-#define V7_TAG_STRING_D MAKE_TAG(1, 0x3)  /* Dictionary string  */
-#define V7_TAG_REGEXP MAKE_TAG(1, 0x2)    /* Regex */
-#define V7_TAG_NOVALUE MAKE_TAG(1, 0x1)   /* Sentinel for no value */
-#define V7_TAG_MASK MAKE_TAG(1, 0xF)
-
-#define _V7_NULL V7_TAG_FOREIGN
-#define _V7_UNDEFINED V7_TAG_UNDEFINED
-
-V7_STATIC_ASSERT(_V7_NULL == V7_NULL, public_V7_NULL_is_wrong);
-V7_STATIC_ASSERT(_V7_UNDEFINED == V7_UNDEFINED, public_V7_UNDEFINED_is_wrong);
-
-/*
- * Object attributes bitmask
- */
-typedef unsigned char v7_obj_attr_t;
-#define V7_OBJ_NOT_EXTENSIBLE (1 << 0) /* TODO(lsm): store this in LSB */
-#define V7_OBJ_DENSE_ARRAY (1 << 1)    /* TODO(mkm): store in some tag */
-#define V7_OBJ_FUNCTION (1 << 2)       /* function object */
-#define V7_OBJ_OFF_HEAP (1 << 3)       /* object not managed by V7 HEAP */
-#define V7_OBJ_HAS_DESTRUCTOR (1 << 4) /* has user data */
-#define V7_OBJ_PROXY (1 << 5)          /* it's a Proxy object */
-
-/*
- * JavaScript value is either a primitive, or an object.
- * There are 5 primitive types: Undefined, Null, Boolean, Number, String.
- * Non-primitive type is an Object type. There are several classes of Objects,
- * see description of `struct v7_generic_object` below for more details.
- * This enumeration combines types and object classes in one enumeration.
- * NOTE(lsm): compile with `-fshort-enums` to reduce sizeof(enum v7_type) to 1.
- */
-enum v7_type {
-  /* Primitive types */
-  V7_TYPE_UNDEFINED,
-  V7_TYPE_NULL,
-  V7_TYPE_BOOLEAN,
-  V7_TYPE_NUMBER,
-  V7_TYPE_STRING,
-  V7_TYPE_FOREIGN,
-  V7_TYPE_CFUNCTION,
-
-  /* Different classes of Object type */
-  V7_TYPE_GENERIC_OBJECT,
-  V7_TYPE_BOOLEAN_OBJECT,
-  V7_TYPE_STRING_OBJECT,
-  V7_TYPE_NUMBER_OBJECT,
-  V7_TYPE_FUNCTION_OBJECT,
-  V7_TYPE_CFUNCTION_OBJECT,
-  V7_TYPE_REGEXP_OBJECT,
-  V7_TYPE_ARRAY_OBJECT,
-  V7_TYPE_DATE_OBJECT,
-  V7_TYPE_ERROR_OBJECT,
-  V7_TYPE_MAX_OBJECT_TYPE,
-  V7_NUM_TYPES
-};
-
-/*
- * Call frame type mask: we have a "class hierarchy" of the call frames, see
- * `struct v7_call_frame_base`, and the `type_mask` field represents the exact
- * frame type.
- *
- * Possible values are:
- *
- * - `V7_CALL_FRAME_MASK_PRIVATE | V7_CALL_FRAME_MASK_BCODE`: the most popular
- *   frame type: call frame for bcode execution, either top-level code or JS
- *   function.
- * - `V7_CALL_FRAME_MASK_PRIVATE`: used for `catch` clauses only: the variables
- *   we create in `catch` clause should not be visible from the outside of the
- *   clause, so we have to create a separate scope object for it.
- * - `V7_CALL_FRAME_MASK_CFUNC`: call frame for C function.
- */
-typedef uint8_t v7_call_frame_mask_t;
-#define V7_CALL_FRAME_MASK_BCODE (1 << 0)
-#define V7_CALL_FRAME_MASK_PRIVATE (1 << 1)
-#define V7_CALL_FRAME_MASK_CFUNC (1 << 2)
-
-/*
- * Base of the call frame; includes the pointer to the previous frame,
- * and the frame type.
- *
- * In order to save memory, it also contains some bitfields which actually
- * belong to some "sub-structures".
- *
- * The hierarchy is as follows:
- *
- *   - v7_call_frame_base
- *     - v7_call_frame_private
- *       - v7_call_frame_bcode
- *     - v7_call_frame_cfunc
- */
-struct v7_call_frame_base {
-  struct v7_call_frame_base *prev;
-
-  /* See comment for `v7_call_frame_mask_t` */
-  v7_call_frame_mask_t type_mask : 3;
-
-  /* Belongs to `struct v7_call_frame_private` */
-  unsigned int line_no : 16;
-
-  /* Belongs to `struct v7_call_frame_bcode` */
-  unsigned is_constructor : 1;
-
-  /* Belongs to `struct v7_call_frame_bcode` */
-  unsigned int is_thrown : 1;
-};
-
-/*
- * "private" call frame, used in `catch` blocks, merely for using a separate
- * scope object there. It is also a "base class" for the bcode call frame,
- * see `struct v7_call_frame_bcode`.
- *
- * TODO(dfrank): probably implement it differently, so that we can get rid of
- * the separate "private" frames whatsoever (and just include it into struct
- * v7_call_frame_bcode )
- */
-struct v7_call_frame_private {
-  struct v7_call_frame_base base;
-  size_t stack_size;
-  struct {
-    /*
-     * Current execution scope. Initially, it is equal to the `global_object`;
-     * and at each function call, it is augmented by the new scope object, which
-     * has the previous value as a prototype.
-     */
-    val_t scope;
-
-    val_t try_stack;
-  } vals;
-};
-
-/*
- * "bcode" call frame, augments "private" frame with `bcode` and the position
- * in it, and `this` object. It is the primary frame type, used when executing
- * a bcode script or calling a function.
- */
-struct v7_call_frame_bcode {
-  struct v7_call_frame_private base;
-  struct {
-    val_t this_obj;
-    val_t thrown_error;
-  } vals;
-  struct bcode *bcode;
-  char *bcode_ops;
-};
-
-/*
- * "cfunc" call frame, used when calling cfunctions.
- */
-struct v7_call_frame_cfunc {
-  struct v7_call_frame_base base;
-
-  struct {
-    val_t this_obj;
-  } vals;
-
-  v7_cfunction_t *cfunc;
-};
-
-/*
- * This structure groups together all val_t logical members
- * of struct v7 so that GC and freeze logic can easily access all
- * of them together. This structure must contain only val_t members.
- */
-struct v7_vals {
-  val_t global_object;
-
-  val_t arguments; /* arguments of current call */
-
-  val_t object_prototype;
-  val_t array_prototype;
-  val_t boolean_prototype;
-  val_t error_prototype;
-  val_t string_prototype;
-  val_t regexp_prototype;
-  val_t number_prototype;
-  val_t date_prototype;
-  val_t function_prototype;
-  val_t proxy_prototype;
-
-  /*
-   * temporary register for `OP_STASH` and `OP_UNSTASH` instructions. Valid if
-   * `v7->is_stashed` is non-zero
-   */
-  val_t stash;
-
-  val_t error_objects[ERROR_CTOR_MAX];
-
-  /*
-   * Value that is being thrown. Valid if `is_thrown` is non-zero (see below)
-   */
-  val_t thrown_error;
-
-  /*
-   * value that is going to be returned. Needed when some `finally` block needs
-   * to be executed after `return my_value;` was issued. Used in bcode.
-   * See also `is_returned` below
-   */
-  val_t returned_value;
-
-  val_t last_name[2]; /* used for error reporting */
-  /* most recent OP_CHECK_CALL exceptions, to be thrown by OP_CALL|OP_NEW */
-  val_t call_check_ex;
-};
-
-struct v7 {
-  struct v7_vals vals;
-
-  /*
-   * Stack of call frames.
-   *
-   * Execution contexts are contained in two chains:
-   * - Stack of call frames: to allow returning, throwing, and stack trace
-   *   generation;
-   * - In the lexical scope via their prototype chain (to allow variable
-   *   lookup), see `struct v7_call_frame_private::scope`.
-   *
-   * Execution contexts should be allocated on heap, because they might not be
-   * on a call stack but still referenced (closures).
-   *
-   * New call frame is created every time some top-level code is evaluated,
-   * or some code is being `eval`-d, or some function is called, either JS
-   * function or C function (although the call frame types are different for
-   * JS functions and cfunctions, see `struct v7_call_frame_base` and its
-   * sub-structures)
-   *
-   * When no code is being evaluated at the moment, `call_stack` is `NULL`.
-   *
-   * See comment for `struct v7_call_frame_base` for some more details.
-   */
-  struct v7_call_frame_base *call_stack;
-
-  /*
-   * Bcode executes until it reaches `bottom_call_frame`. When some top-level
-   * or `eval`-d code starts execution, the `bottom_call_frame` is set to the
-   * call frame which was just created for the execution.
-   */
-  struct v7_call_frame_base *bottom_call_frame;
-
-  struct mbuf stack; /* value stack for bcode interpreter */
-
-  struct mbuf owned_strings;   /* Sequence of (varint len, char data[]) */
-  struct mbuf foreign_strings; /* Sequence of (varint len, char *data) */
-
-  struct mbuf tmp_stack; /* Stack of val_t* elements, used as root set */
-  int need_gc;           /* Set to true to trigger GC when safe */
-
-  struct gc_arena generic_object_arena;
-  struct gc_arena function_arena;
-  struct gc_arena property_arena;
-#if V7_ENABLE__Memory__stats
-  size_t function_arena_ast_size;
-  size_t bcode_ops_size;
-  size_t bcode_lit_total_size;
-  size_t bcode_lit_deser_size;
-#endif
-  struct mbuf owned_values; /* buffer for GC roots owned by C code */
-
-  /*
-   * Stack of the root bcodes being executed at the moment. Note that when some
-   * regular JS function is called inside `eval_bcode()`, the function's bcode
-   * is NOT added here. Buf if some cfunction is called, which in turn calls
-   * `b_exec()` (or `b_apply()`) recursively, the new bcode is added to this
-   * stack.
-   */
-  struct mbuf act_bcodes;
-
-  char error_msg[80]; /* Exception message */
-
-  struct mbuf json_visited_stack; /* Detecting cycle in to_json */
-
-/* Parser state */
-#if !defined(V7_NO_COMPILER)
-  struct v7_pstate pstate; /* Parsing state */
-  enum v7_tok cur_tok;     /* Current token */
-  const char *tok;         /* Parsed terminal token (ident, number, string) */
-  unsigned long tok_len;   /* Length of the parsed terminal token */
-  size_t last_var_node;    /* Offset of last var node or function/script node */
-  int after_newline;       /* True if the cur_tok starts a new line */
-  double cur_tok_dbl;      /* When tokenizing, parser stores TOK_NUMBER here */
-
-  /*
-   * Current linenumber. Currently it is used by parser, compiler and bcode
-   * evaluator.
-   *
-   * - Parser: it's the last line_no emitted to AST
-   * - Compiler: it's the last line_no emitted to bcode
-   */
-  int line_no;
-#endif /* V7_NO_COMPILER */
-
-  /* singleton, pointer because of amalgamation */
-  struct v7_property *cur_dense_prop;
-
-  volatile int interrupted;
-#ifdef V7_STACK_SIZE
-  void *sp_limit;
-  void *sp_lwm;
-#endif
-
-#if defined(V7_CYG_PROFILE_ON)
-  /* linked list of v7 contexts, needed by cyg_profile hooks */
-  struct v7 *next_v7;
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-  /* linked list of stack tracking contexts */
-  struct stack_track_ctx *stack_track_ctx;
-
-  int stack_stat[V7_STACK_STATS_CNT];
-#endif
-
-#endif
-
-#ifdef V7_MALLOC_GC
-  struct mbuf malloc_trace;
-#endif
-
-/*
- * TODO(imax): remove V7_DISABLE_STR_ALLOC_SEQ knob after 2015/12/01 if there
- * are no issues.
- */
-#ifndef V7_DISABLE_STR_ALLOC_SEQ
-  uint16_t gc_next_asn; /* Next sequence number to use. */
-  uint16_t gc_min_asn;  /* Minimal sequence number currently in use. */
-#endif
-
-#if defined(V7_TRACK_MAX_PARSER_STACK_SIZE)
-  size_t parser_stack_data_max_size;
-  size_t parser_stack_ret_max_size;
-  size_t parser_stack_data_max_len;
-  size_t parser_stack_ret_max_len;
-#endif
-
-#ifdef V7_FREEZE
-  FILE *freeze_file;
-#endif
-
-  /*
-   * true if exception is currently being created. Needed to avoid recursive
-   * exception creation
-   */
-  unsigned int creating_exception : 1;
-  /* while true, GC is inhibited */
-  unsigned int inhibit_gc : 1;
-  /* true if `thrown_error` is valid */
-  unsigned int is_thrown : 1;
-  /* true if `returned_value` is valid */
-  unsigned int is_returned : 1;
-  /* true if a finally block is executing while breaking */
-  unsigned int is_breaking : 1;
-  /* true when a continue OP is executed, reset by `OP_JMP_IF_CONTINUE` */
-  unsigned int is_continuing : 1;
-  /* true if some value is currently stashed (`v7->vals.stash`) */
-  unsigned int is_stashed : 1;
-  /* true if last emitted statement does not affect data stack */
-  unsigned int is_stack_neutral : 1;
-  /* true if precompiling; affects compiler bcode choices */
-  unsigned int is_precompiling : 1;
-
-  enum opcode last_ops[2]; /* trace of last ops, used for error reporting */
-};
-
-struct v7_property {
-  struct v7_property *
-      next; /* Linkage in struct v7_generic_object::properties */
-  v7_prop_attr_t attributes;
-#if defined(V7_ENABLE_ENTITY_IDS)
-  entity_id_t entity_id;
-#endif
-  val_t name;  /* Property name (a string) */
-  val_t value; /* Property value */
-};
-
-/*
- * "base object": structure which is shared between objects and functions.
- */
-struct v7_object {
-  /* First HIDDEN property in a chain is an internal object value */
-  struct v7_property *properties;
-  v7_obj_attr_t attributes;
-#if defined(V7_ENABLE_ENTITY_IDS)
-  entity_id_part_t entity_id_base;
-  entity_id_part_t entity_id_spec;
-#endif
-};
-
-/*
- * An object is an unordered collection of properties.
- * A function stored in a property of an object is called a method.
- * A property has a name, a value, and set of attributes.
- * Attributes are: ReadOnly, DontEnum, DontDelete, Internal.
- *
- * A constructor is a function that creates and initializes objects.
- * Each constructor has an associated prototype object that is used for
- * inheritance and shared properties. When a constructor creates an object,
- * the new object references the constructor’s prototype.
- *
- * Objects could be a "generic objects" which is a collection of properties,
- * or a "typed object" which also hold an internal value like String or Number.
- * Those values are implicit, unnamed properties of the respective types,
- * and can be coerced into primitive types by calling a respective constructor
- * as a function:
- *    var a = new Number(123);
- *    typeof(a) == 'object';
- *    typeof(Number(a)) == 'number';
- */
-struct v7_generic_object {
-  /*
-   * This has to be the first field so that objects can be managed by the GC.
-   */
-  struct v7_object base;
-  struct v7_object *prototype;
-};
-
-/*
- * Variables are function-scoped and are hoisted.
- * Lexical scoping & closures: each function has a chain of scopes, defined
- * by the lexicographic order of function definitions.
- * Scope is different from the execution context.
- * Execution context carries "variable object" which is variable/value
- * mapping for all variables defined in a function, and `this` object.
- * If function is not called as a method, then `this` is a global object.
- * Otherwise, `this` is an object that contains called method.
- * New execution context is created each time a function call is performed.
- * Passing arguments through recursion is done using execution context, e.g.
- *
- *    var factorial = function(num) {
- *      return num < 2 ? 1 : num * factorial(num - 1);
- *    };
- *
- * Here, recursion calls the same function `factorial` several times. Execution
- * contexts for each call form a stack. Each context has different variable
- * object, `vars`, with different values of `num`.
- */
-
-struct v7_js_function {
-  /*
-   * Functions are objects. This has to be the first field so that function
-   * objects can be managed by the GC.
-   */
-  struct v7_object base;
-  struct v7_generic_object *scope; /* lexical scope of the closure */
-
-  /* bytecode, might be shared between functions */
-  struct bcode *bcode;
-};
-
-struct v7_regexp {
-  val_t regexp_string;
-  struct slre_prog *compiled_regexp;
-  long lastIndex;
-};
-
-/* Vector, describes some memory location pointed by `p` with length `len` */
-struct v7_vec {
-  char *p;
-  size_t len;
-};
-
-/*
- * Constant vector, describes some const memory location pointed by `p` with
- * length `len`
- */
-struct v7_vec_const {
-  const char *p;
-  size_t len;
-};
-
-#define V7_VEC(str) \
-  { (str), sizeof(str) - 1 }
-
-/*
- * Returns current execution scope.
- *
- * See comment for `struct v7_call_frame_private::vals::scope`
- */
-V7_PRIVATE v7_val_t get_scope(struct v7 *v7);
-
-/*
- * Returns 1 if currently executing bcode in the "strict mode", 0 otherwise
- */
-V7_PRIVATE uint8_t is_strict_mode(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_CORE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/primitive_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Primitives
- *
- * All primitive values but strings.
- *
- * "foreign" values are also here, see `v7_mk_foreign()`.
- */
-
-#ifndef CS_V7_SRC_PRIMITIVE_PUBLIC_H_
-#define CS_V7_SRC_PRIMITIVE_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/* Make numeric primitive value */
-NOINSTR v7_val_t v7_mk_number(struct v7 *v7, double num);
-
-/*
- * Returns number value stored in `v7_val_t` as `double`.
- *
- * Returns NaN for non-numbers.
- */
-NOINSTR double v7_get_double(struct v7 *v7, v7_val_t v);
-
-/*
- * Returns number value stored in `v7_val_t` as `int`. If the number value is
- * not an integer, the fraction part will be discarded.
- *
- * If the given value is a non-number, or NaN, the result is undefined.
- */
-NOINSTR int v7_get_int(struct v7 *v7, v7_val_t v);
-
-/* Returns true if given value is a primitive number value */
-int v7_is_number(v7_val_t v);
-
-/* Make boolean primitive value (either `true` or `false`) */
-NOINSTR v7_val_t v7_mk_boolean(struct v7 *v7, int is_true);
-
-/*
- * Returns boolean stored in `v7_val_t`:
- *  0 for `false` or non-boolean, non-0 for `true`
- */
-NOINSTR int v7_get_bool(struct v7 *v7, v7_val_t v);
-
-/* Returns true if given value is a primitive boolean value */
-int v7_is_boolean(v7_val_t v);
-
-/*
- * Make `null` primitive value.
- *
- * NOTE: this function is deprecated and will be removed in future releases.
- * Use `V7_NULL` instead.
- */
-NOINSTR v7_val_t v7_mk_null(void);
-
-/* Returns true if given value is a primitive `null` value */
-int v7_is_null(v7_val_t v);
-
-/*
- * Make `undefined` primitive value.
- *
- * NOTE: this function is deprecated and will be removed in future releases.
- * Use `V7_UNDEFINED` instead.
- */
-NOINSTR v7_val_t v7_mk_undefined(void);
-
-/* Returns true if given value is a primitive `undefined` value */
-int v7_is_undefined(v7_val_t v);
-
-/*
- * Make JavaScript value that holds C/C++ `void *` pointer.
- *
- * A foreign value is completely opaque and JS code cannot do anything useful
- * with it except holding it in properties and passing it around.
- * It behaves like a sealed object with no properties.
- *
- * NOTE:
- * Only valid pointers (as defined by each supported architecture) will fully
- * preserved. In particular, all supported 64-bit architectures (x86_64, ARM-64)
- * actually define a 48-bit virtual address space.
- * Foreign values will be sign-extended as required, i.e creating a foreign
- * value of something like `(void *) -1` will work as expected. This is
- * important because in some 64-bit OSs (e.g. Solaris) the user stack grows
- * downwards from the end of the address space.
- *
- * If you need to store exactly sizeof(void*) bytes of raw data where
- * `sizeof(void*)` >= 8, please use byte arrays instead.
- */
-NOINSTR v7_val_t v7_mk_foreign(struct v7 *v7, void *ptr);
-
-/*
- * Returns `void *` pointer stored in `v7_val_t`.
- *
- * Returns NULL if the value is not a foreign pointer.
- */
-NOINSTR void *v7_get_ptr(struct v7 *v7, v7_val_t v);
-
-/* Returns true if given value holds `void *` pointer */
-int v7_is_foreign(v7_val_t v);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_PRIMITIVE_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/primitive.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_PRIMITIVE_H_
-#define CS_V7_SRC_PRIMITIVE_H_
-
-/* Amalgamated: #include "v7/src/primitive_public.h" */
-
-/* Amalgamated: #include "v7/src/core.h" */
-
-/* Returns true if given value is a number, not NaN and not Infinity. */
-V7_PRIVATE int is_finite(struct v7 *v7, v7_val_t v);
-
-V7_PRIVATE val_t pointer_to_value(void *p);
-V7_PRIVATE void *get_ptr(val_t v);
-
-#endif /* CS_V7_SRC_PRIMITIVE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/string_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Strings
- */
-
-#ifndef CS_V7_SRC_STRING_PUBLIC_H_
-#define CS_V7_SRC_STRING_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Creates a string primitive value.
- * `str` must point to the utf8 string of length `len`.
- * If `len` is ~0, `str` is assumed to be NUL-terminated and `strlen(str)` is
- * used.
- *
- * If `copy` is non-zero, the string data is copied and owned by the GC. The
- * caller can free the string data afterwards. Otherwise (`copy` is zero), the
- * caller owns the string data, and is responsible for not freeing it while it
- * is used.
- */
-v7_val_t v7_mk_string(struct v7 *v7, const char *str, size_t len, int copy);
-
-/* Returns true if given value is a primitive string value */
-int v7_is_string(v7_val_t v);
-
-/*
- * Returns a pointer to the string stored in `v7_val_t`.
- *
- * String length returned in `len`, which is allowed to be NULL. Returns NULL
- * if the value is not a string.
- *
- * JS strings can contain embedded NUL chars and may or may not be NUL
- * terminated.
- *
- * CAUTION: creating new JavaScript object, array, or string may kick in a
- * garbage collector, which in turn may relocate string data and invalidate
- * pointer returned by `v7_get_string()`.
- *
- * Short JS strings are embedded inside the `v7_val_t` value itself. This is why
- * a pointer to a `v7_val_t` is required. It also means that the string data
- * will become invalid once that `v7_val_t` value goes out of scope.
- */
-const char *v7_get_string(struct v7 *v7, v7_val_t *v, size_t *len);
-
-/*
- * Returns a pointer to the string stored in `v7_val_t`.
- *
- * Returns NULL if the value is not a string or if the string is not compatible
- * with a C string.
- *
- * C compatible strings contain exactly one NUL char, in terminal position.
- *
- * All strings owned by the V7 engine (see `v7_mk_string()`) are guaranteed to
- * be NUL terminated. Out of these, those that don't include embedded NUL chars
- * are guaranteed to be C compatible.
- */
-const char *v7_get_cstring(struct v7 *v7, v7_val_t *v);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STRING_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/string.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STRING_H_
-#define CS_V7_SRC_STRING_H_
-
-/* Amalgamated: #include "v7/src/string_public.h" */
-
-/* Amalgamated: #include "v7/src/core.h" */
-
-/*
- * Size of the extra space for strings mbuf that is needed to avoid frequent
- * reallocations
- */
-#define _V7_STRING_BUF_RESERVE 500
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err v7_char_code_at(struct v7 *v7, v7_val_t s, v7_val_t at,
-                                       double *res);
-V7_PRIVATE int s_cmp(struct v7 *, val_t a, val_t b);
-V7_PRIVATE val_t s_concat(struct v7 *, val_t, val_t);
-
-/*
- * Convert a C string to to an unsigned integer.
- * `ok` will be set to true if the string conforms to
- * an unsigned long.
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err str_to_ulong(struct v7 *v7, val_t v, int *ok,
-                                    unsigned long *res);
-
-/*
- * Convert a V7 string to to an unsigned integer.
- * `ok` will be set to true if the string conforms to
- * an unsigned long.
- *
- * Use it if only you need strong conformity of the value to an integer;
- * otherwise, use `to_long()` or `to_number_v()` instead.
- */
-V7_PRIVATE unsigned long cstr_to_ulong(const char *s, size_t len, int *ok);
-
-enum embstr_flags {
-  EMBSTR_ZERO_TERM = (1 << 0),
-  EMBSTR_UNESCAPE = (1 << 1),
-};
-
-V7_PRIVATE void embed_string(struct mbuf *m, size_t offset, const char *p,
-                             size_t len, uint8_t /*enum embstr_flags*/ flags);
-
-V7_PRIVATE size_t unescape(const char *s, size_t len, char *to);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STRING_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/exceptions_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Exceptions
- */
-
-#ifndef CS_V7_SRC_EXCEPTIONS_PUBLIC_H_
-#define CS_V7_SRC_EXCEPTIONS_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/* Throw an exception with an already existing value. */
-WARN_UNUSED_RESULT
-enum v7_err v7_throw(struct v7 *v7, v7_val_t v);
-
-/*
- * Throw an exception with given formatted message.
- *
- * Pass "Error" as typ for a generic error.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_throwf(struct v7 *v7, const char *typ, const char *err_fmt, ...);
-
-/*
- * Rethrow the currently thrown object. In fact, it just returns
- * V7_EXEC_EXCEPTION.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_rethrow(struct v7 *v7);
-
-/*
- * Returns the value that is being thrown at the moment, or `undefined` if
- * nothing is being thrown. If `is_thrown` is not `NULL`, it will be set
- * to either 0 or 1, depending on whether something is thrown at the moment.
- */
-v7_val_t v7_get_thrown_value(struct v7 *v7, unsigned char *is_thrown);
-
-/* Clears currently thrown value, if any. */
-void v7_clear_thrown_value(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_EXCEPTIONS_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/exceptions.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_EXCEPTIONS_H_
-#define CS_V7_SRC_EXCEPTIONS_H_
-
-/* Amalgamated: #include "v7/src/exceptions_public.h" */
-
-/* Amalgamated: #include "v7/src/core.h" */
-
-/*
- * Try to perform some arbitrary call, and if the result is other than `V7_OK`,
- * "throws" an error with `V7_THROW()`
- */
-#define V7_TRY2(call, clean_label)           \
-  do {                                       \
-    enum v7_err _e = call;                   \
-    V7_CHECK2(_e == V7_OK, _e, clean_label); \
-  } while (0)
-
-/*
- * Sets return value to the provided one, and `goto`s `clean`.
- *
- * For this to work, you should have local `enum v7_err rcode` variable,
- * and a `clean` label.
- */
-#define V7_THROW2(err_code, clean_label)                              \
-  do {                                                                \
-    (void) v7;                                                        \
-    rcode = (err_code);                                               \
-    assert(rcode != V7_OK);                                           \
-    assert(!v7_is_undefined(v7->vals.thrown_error) && v7->is_thrown); \
-    goto clean_label;                                                 \
-  } while (0)
-
-/*
- * Checks provided condition `cond`, and if it's false, then "throws"
- * provided `err_code` (see `V7_THROW()`)
- */
-#define V7_CHECK2(cond, err_code, clean_label) \
-  do {                                         \
-    if (!(cond)) {                             \
-      V7_THROW2(err_code, clean_label);        \
-    }                                          \
-  } while (0)
-
-/*
- * Checks provided condition `cond`, and if it's false, then "throws"
- * internal error
- *
- * TODO(dfrank): it would be good to have formatted string: then, we can
- * specify file and line.
- */
-#define V7_CHECK_INTERNAL2(cond, clean_label)                         \
-  do {                                                                \
-    if (!(cond)) {                                                    \
-      enum v7_err __rcode = v7_throwf(v7, "Error", "Internal error"); \
-      (void) __rcode;                                                 \
-      V7_THROW2(V7_INTERNAL_ERROR, clean_label);                      \
-    }                                                                 \
-  } while (0)
-
-/*
- * Shortcuts for the macros above, but they assume the clean label `clean`.
- */
-
-#define V7_TRY(call) V7_TRY2(call, clean)
-#define V7_THROW(err_code) V7_THROW2(err_code, clean)
-#define V7_CHECK(cond, err_code) V7_CHECK2(cond, err_code, clean)
-#define V7_CHECK_INTERNAL(cond) V7_CHECK_INTERNAL2(cond, clean)
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * At the moment, most of the exception-related functions are public, and are
- * declared in `exceptions_public.h`
- */
-
-/*
- * Create an instance of the exception with type `typ` (see `TYPE_ERROR`,
- * `SYNTAX_ERROR`, etc), and message `msg`.
- */
-V7_PRIVATE enum v7_err create_exception(struct v7 *v7, const char *typ,
-                                        const char *msg, val_t *res);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_EXCEPTIONS_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/object.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_OBJECT_H_
-#define CS_V7_SRC_OBJECT_H_
-
-/* Amalgamated: #include "v7/src/object_public.h" */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-V7_PRIVATE val_t mk_object(struct v7 *v7, val_t prototype);
-V7_PRIVATE val_t v7_object_to_value(struct v7_object *o);
-V7_PRIVATE struct v7_generic_object *get_generic_object_struct(val_t v);
-
-/*
- * Returns pointer to the struct representing an object.
- * Given value must be an object (the caller can verify it
- * by calling `v7_is_object()`)
- */
-V7_PRIVATE struct v7_object *get_object_struct(v7_val_t v);
-
-/*
- * Return true if given value is a JavaScript object (will return
- * false for function)
- */
-V7_PRIVATE int v7_is_generic_object(v7_val_t v);
-
-V7_PRIVATE struct v7_property *v7_mk_property(struct v7 *v7);
-
-V7_PRIVATE struct v7_property *v7_get_own_property2(struct v7 *v7, val_t obj,
-                                                    const char *name,
-                                                    size_t len,
-                                                    v7_prop_attr_t attrs);
-
-V7_PRIVATE struct v7_property *v7_get_own_property(struct v7 *v7, val_t obj,
-                                                   const char *name,
-                                                   size_t len);
-
-/*
- * If `len` is -1/MAXUINT/~0, then `name` must be 0-terminated
- *
- * Returns a pointer to the property structure, given an object and a name of
- * the property as a pointer to string buffer and length.
- *
- * See also `v7_get_property_v`
- */
-V7_PRIVATE struct v7_property *v7_get_property(struct v7 *v7, val_t obj,
-                                               const char *name, size_t len);
-
-/*
- * Just like `v7_get_property`, but takes name as a `v7_val_t`
- */
-V7_PRIVATE enum v7_err v7_get_property_v(struct v7 *v7, val_t obj,
-                                         v7_val_t name,
-                                         struct v7_property **res);
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err v7_get_throwing_v(struct v7 *v7, v7_val_t obj,
-                                         v7_val_t name, v7_val_t *res);
-
-V7_PRIVATE void v7_destroy_property(struct v7_property **p);
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err v7_invoke_setter(struct v7 *v7, struct v7_property *prop,
-                                        val_t obj, val_t val);
-
-/*
- * Like `set_property`, but takes property name as a `val_t`
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err set_property_v(struct v7 *v7, val_t obj, val_t name,
-                                      val_t val, struct v7_property **res);
-
-/*
- * Like JavaScript assignment: set a property with given `name` + `len` at
- * the object `obj` to value `val`. Returns a property through the `res`
- * (which may be `NULL` if return value is not required)
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err set_property(struct v7 *v7, val_t obj, const char *name,
-                                    size_t len, v7_val_t val,
-                                    struct v7_property **res);
-
-/*
- * Like `def_property()`, but takes property name as a `val_t`
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err def_property_v(struct v7 *v7, val_t obj, val_t name,
-                                      v7_prop_attr_desc_t attrs_desc, val_t val,
-                                      uint8_t as_assign,
-                                      struct v7_property **res);
-
-/*
- * Define object property, similar to JavaScript `Object.defineProperty()`.
- *
- * Just like public `v7_def()`, but returns `enum v7_err`, and therefore can
- * throw.
- *
- * Additionally, takes param `as_assign`: if it is non-zero, it behaves
- * similarly to plain JavaScript assignment in terms of some exception-related
- * corner cases.
- *
- * `res` may be `NULL`.
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err def_property(struct v7 *v7, val_t obj, const char *name,
-                                    size_t len, v7_prop_attr_desc_t attrs_desc,
-                                    v7_val_t val, uint8_t as_assign,
-                                    struct v7_property **res);
-
-V7_PRIVATE int set_method(struct v7 *v7, val_t obj, const char *name,
-                          v7_cfunction_t *func, int num_args);
-
-V7_PRIVATE int set_cfunc_prop(struct v7 *v7, val_t o, const char *name,
-                              v7_cfunction_t *func);
-
-/* Return address of property value or NULL if the passed property is NULL */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err v7_property_value(struct v7 *v7, val_t obj,
-                                         struct v7_property *p, val_t *res);
-
-#if V7_ENABLE__Proxy
-/*
- * Additional context for property iteration of a proxied object, see
- * `v7_next_prop()`.
- */
-struct prop_iter_proxy_ctx {
-  /* Proxy target object */
-  v7_val_t target_obj;
-  /* Proxy handler object */
-  v7_val_t handler_obj;
-
-  /*
-   * array returned by the `ownKeys` callback, valid if only `has_own_keys` is
-   * set
-   */
-  v7_val_t own_keys;
-  /*
-   * callback to get property descriptor, one of these:
-   *   - a JS or cfunction `getOwnPropertyDescriptor`
-   *     (if `has_get_own_prop_desc_C` is not set);
-   *   - a C callback `v7_get_own_prop_desc_cb_t`.
-   *     (if `has_get_own_prop_desc_C` is set);
-   */
-  v7_val_t get_own_prop_desc;
-
-  /*
-   * if `has_own_keys` is set, `own_key_idx` represents next index in the
-   * `own_keys` array
-   */
-  unsigned own_key_idx : 29;
-
-  /* if set, `own_keys` is valid */
-  unsigned has_own_keys : 1;
-  /* if set, `get_own_prop_desc` is valid */
-  unsigned has_get_own_prop_desc : 1;
-  /*
-   * if set, `get_own_prop_desc` is a C callback `has_get_own_prop_desc_C`, not
-   * a JS callback
-   */
-  unsigned has_get_own_prop_desc_C : 1;
-};
-#endif
-
-/*
- * Like public function `v7_init_prop_iter_ctx()`, but it takes additional
- * argument `proxy_transp`; if it is zero, and the given `obj` is a Proxy, it
- * will iterate the properties of the proxy itself, not the Proxy's target.
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
-                                          int proxy_transp,
-                                          struct prop_iter_ctx *ctx);
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err next_prop(struct v7 *v7, struct prop_iter_ctx *ctx,
-                                 v7_val_t *name, v7_val_t *value,
-                                 v7_prop_attr_t *attrs, int *ok);
-
-/*
- * Set new prototype `proto` for the given object `obj`. Returns `0` at
- * success, `-1` at failure (it may fail if given `obj` is a function object:
- * it's impossible to change function object's prototype)
- */
-V7_PRIVATE int obj_prototype_set(struct v7 *v7, struct v7_object *obj,
-                                 struct v7_object *proto);
-
-/*
- * Given a pointer to the object structure, returns a
- * pointer to the prototype object, or `NULL` if there is
- * no prototype.
- */
-V7_PRIVATE struct v7_object *obj_prototype(struct v7 *v7,
-                                           struct v7_object *obj);
-
-V7_PRIVATE int is_prototype_of(struct v7 *v7, val_t o, val_t p);
-
-/* Get the property holding user data and destructor, or NULL */
-V7_PRIVATE struct v7_property *get_user_data_property(v7_val_t obj);
-
-#endif /* CS_V7_SRC_OBJECT_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/exec_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Execution of JavaScript code
- */
-
-#ifndef CS_V7_SRC_EXEC_PUBLIC_H_
-#define CS_V7_SRC_EXEC_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Execute JavaScript `js_code`. The result of evaluation is stored in
- * the `result` variable.
- *
- * Return:
- *
- *  - V7_OK on success. `result` contains the result of execution.
- *  - V7_SYNTAX_ERROR if `js_code` in not a valid code. `result` is undefined.
- *  - V7_EXEC_EXCEPTION if `js_code` threw an exception. `result` stores
- *    an exception object.
- *  - V7_AST_TOO_LARGE if `js_code` contains an AST segment longer than 16 bit.
- *    `result` is undefined. To avoid this error, build V7 with V7_LARGE_AST.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_exec(struct v7 *v7, const char *js_code, v7_val_t *result);
-
-/*
- * Options for `v7_exec_opt()`. To get default options, like `v7_exec()` uses,
- * just zero out this struct.
- */
-struct v7_exec_opts {
-  /* Filename, used for stack traces only */
-  const char *filename;
-
-  /*
-   * Object to be used as `this`. Note: when it is zeroed out, i.e. it's a
-   * number `0`, the `undefined` value is assumed. It means that it's
-   * impossible to actually use the number `0` as `this` object, but it makes
-   * little sense anyway.
-   */
-  v7_val_t this_obj;
-
-  /* Whether the given `js_code` should be interpreted as JSON, not JS code */
-  unsigned is_json : 1;
-};
-
-/*
- * Customizable version of `v7_exec()`: allows to specify various options, see
- * `struct v7_exec_opts`.
- */
-enum v7_err v7_exec_opt(struct v7 *v7, const char *js_code,
-                        const struct v7_exec_opts *opts, v7_val_t *res);
-
-/*
- * Same as `v7_exec()`, but loads source code from `path` file.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_exec_file(struct v7 *v7, const char *path, v7_val_t *result);
-
-/*
- * Parse `str` and store corresponding JavaScript object in `res` variable.
- * String `str` should be '\0'-terminated.
- * Return value and semantic is the same as for `v7_exec()`.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_parse_json(struct v7 *v7, const char *str, v7_val_t *res);
-
-/*
- * Same as `v7_parse_json()`, but loads JSON string from `path`.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_parse_json_file(struct v7 *v7, const char *path, v7_val_t *res);
-
-#if !defined(V7_NO_COMPILER)
-
-/*
- * Compile JavaScript code `js_code` into the byte code and write generated
- * byte code into opened file stream `fp`. If `generate_binary_output` is 0,
- * then generated byte code is in human-readable text format. Otherwise, it is
- * in the binary format, suitable for execution by V7 instance.
- * NOTE: `fp` must be a valid, opened, writable file stream.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_compile(const char *js_code, int generate_binary_output,
-                       int use_bcode, FILE *fp);
-
-#endif /* V7_NO_COMPILER */
-
-/*
- * Call function `func` with arguments `args`, using `this_obj` as `this`.
- * `args` should be an array containing arguments or `undefined`.
- *
- * `res` can be `NULL` if return value is not required.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
-                     v7_val_t args, v7_val_t *res);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_EXEC_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/exec.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_EXEC_H_
-#define CS_V7_SRC_EXEC_H_
-
-/* Amalgamated: #include "v7/src/exec_public.h" */
-
-/* Amalgamated: #include "v7/src/core.h" */
-
-#if !defined(V7_NO_COMPILER)
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * At the moment, all exec-related functions are public, and are declared in
- * `exec_public.h`
- */
-
-WARN_UNUSED_RESULT
-enum v7_err _v7_compile(const char *js_code, size_t js_code_size,
-                        int generate_binary_output, int use_bcode, FILE *fp);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_NO_COMPILER */
-
-#endif /* CS_V7_SRC_EXEC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/array_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Arrays
- */
-
-#ifndef CS_V7_SRC_ARRAY_PUBLIC_H_
-#define CS_V7_SRC_ARRAY_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/* Make an empty array object */
-v7_val_t v7_mk_array(struct v7 *v7);
-
-/* Returns true if given value is an array object */
-int v7_is_array(struct v7 *v7, v7_val_t v);
-
-/* Returns length on an array. If `arr` is not an array, 0 is returned. */
-unsigned long v7_array_length(struct v7 *v7, v7_val_t arr);
-
-/* Insert value `v` in array `arr` at the end of the array. */
-int v7_array_push(struct v7 *, v7_val_t arr, v7_val_t v);
-
-/*
- * Like `v7_array_push()`, but "returns" value through the `res` pointer
- * argument. `res` is allowed to be `NULL`.
- *
- * Caller should check the error code returned, and if it's something other
- * than `V7_OK`, perform cleanup and return this code further.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_array_push_throwing(struct v7 *v7, v7_val_t arr, v7_val_t v,
-                                   int *res);
-
-/*
- * Return array member at index `index`. If `index` is out of bounds, undefined
- * is returned.
- */
-v7_val_t v7_array_get(struct v7 *, v7_val_t arr, unsigned long index);
-
-/* Insert value `v` into `arr` at index `index`. */
-int v7_array_set(struct v7 *v7, v7_val_t arr, unsigned long index, v7_val_t v);
-
-/*
- * Like `v7_array_set()`, but "returns" value through the `res` pointer
- * argument. `res` is allowed to be `NULL`.
- *
- * Caller should check the error code returned, and if it's something other
- * than `V7_OK`, perform cleanup and return this code further.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_array_set_throwing(struct v7 *v7, v7_val_t arr,
-                                  unsigned long index, v7_val_t v, int *res);
-
-/* Delete value in array `arr` at index `index`, if it exists. */
-void v7_array_del(struct v7 *v7, v7_val_t arr, unsigned long index);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_ARRAY_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/array.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_ARRAY_H_
-#define CS_V7_SRC_ARRAY_H_
-
-/* Amalgamated: #include "v7/src/array_public.h" */
-
-/* Amalgamated: #include "v7/src/core.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE v7_val_t v7_mk_dense_array(struct v7 *v7);
-V7_PRIVATE val_t
-v7_array_get2(struct v7 *v7, v7_val_t arr, unsigned long index, int *has);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_ARRAY_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/conversion_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Conversion
- */
-
-#ifndef CS_V7_SRC_CONVERSION_PUBLIC_H_
-#define CS_V7_SRC_CONVERSION_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/* Stringify mode, see `v7_stringify()` and `v7_stringify_throwing()` */
-enum v7_stringify_mode {
-  V7_STRINGIFY_DEFAULT,
-  V7_STRINGIFY_JSON,
-  V7_STRINGIFY_DEBUG,
-};
-
-/*
- * Generate string representation of the JavaScript value `val` into a buffer
- * `buf`, `len`. If `len` is too small to hold a generated string,
- * `v7_stringify()` allocates required memory. In that case, it is caller's
- * responsibility to free the allocated buffer. Generated string is guaranteed
- * to be 0-terminated.
- *
- * Available stringification modes are:
- *
- * - `V7_STRINGIFY_DEFAULT`:
- *   Convert JS value to string, using common JavaScript semantics:
- *   - If value is an object:
- *     - call `toString()`;
- *     - If `toString()` returned non-primitive value, call `valueOf()`;
- *     - If `valueOf()` returned non-primitive value, throw `TypeError`.
- *   - Now we have a primitive, and if it's not a string, then stringify it.
- *
- * - `V7_STRINGIFY_JSON`:
- *   Generate JSON output
- *
- * - `V7_STRINGIFY_DEBUG`:
- *   Mostly like JSON, but will not omit non-JSON objects like functions.
- *
- * Example code:
- *
- *     char buf[100], *p;
- *     p = v7_stringify(v7, obj, buf, sizeof(buf), V7_STRINGIFY_DEFAULT);
- *     printf("JSON string: [%s]\n", p);
- *     if (p != buf) {
- *       free(p);
- *     }
- */
-char *v7_stringify(struct v7 *v7, v7_val_t v, char *buf, size_t len,
-                   enum v7_stringify_mode mode);
-
-/*
- * Like `v7_stringify()`, but "returns" value through the `res` pointer
- * argument. `res` must not be `NULL`.
- *
- * Caller should check the error code returned, and if it's something other
- * than `V7_OK`, perform cleanup and return this code further.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_stringify_throwing(struct v7 *v7, v7_val_t v, char *buf,
-                                  size_t size, enum v7_stringify_mode mode,
-                                  char **res);
-
-/*
- * A shortcut for `v7_stringify()` with `V7_STRINGIFY_JSON`
- */
-#define v7_to_json(a, b, c, d) v7_stringify(a, b, c, d, V7_STRINGIFY_JSON)
-
-/* Returns true if given value evaluates to true, as in `if (v)` statement. */
-int v7_is_truthy(struct v7 *v7, v7_val_t v);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_CONVERSION_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/conversion.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_CONVERSION_H_
-#define CS_V7_SRC_CONVERSION_H_
-
-/* Amalgamated: #include "v7/src/conversion_public.h" */
-
-/* Amalgamated: #include "v7/src/core.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Conversion API
- * ==============
- *
- * - If you need to convert any JS value to string using common JavaScript
- *   semantics, use `to_string()`, which can convert to both `v7_val_t` or your
- *   C buffer.
- *
- * - If you need to convert any JS value to number using common JavaScript
- *   semantics, use `to_number_v()`;
- *
- * - If you need to convert any JS value to primitive, without forcing it to
- *   string or number, use `to_primitive()` (see comments for this function for
- *   details);
- *
- * - If you have a primitive value, and you want to convert it to either string
- *   or number, you can still use functions above: `to_string()` and
- *   `to_number_v()`. But if you want to save a bit of work, use:
- *   - `primitive_to_str()`
- *   - `primitive_to_number()`
- *
- *   In fact, these are a bit lower level functions, which are used by
- *   `to_string()` and `to_number_v()` after converting value to
- *   primitive.
- *
- * - If you want to call `valueOf()` on the object, use `obj_value_of()`;
- * - If you want to call `toString()` on the object, use `obj_to_string()`;
- *
- * - If you need to convert any JS value to boolean using common JavaScript
- *   semantics (as in the expression `if (v)` or `Boolean(v)`), use
- *   `to_boolean_v()`.
- *
- * - If you want to get the JSON representation of a value, use
- *   `to_json_or_debug()`, passing `0` as `is_debug` : writes data to your C
- *   buffer;
- *
- * - There is one more kind of representation: `DEBUG`. It's very similar to
- *   JSON, but it will not omit non-JSON values, such as functions. Again, use
- *   `to_json_or_debug()`, but pass `1` as `is_debug` this time: writes data to
- *   your C buffer;
- *
- * Additionally, for any kind of to-string conversion into C buffer, you can
- * use a convenience wrapper function (mostly for public API), which can
- * allocate the buffer for you:
- *
- *   - `v7_stringify_throwing()`;
- *   - `v7_stringify()` : the same as above, but doesn't throw.
- *
- * There are a couple of more specific conversions, which I'd like to probably
- * refactor or remove in the future:
- *
- * - `to_long()` : if given value is `undefined`, returns provided default
- *   value; otherwise, converts value to number, and then truncates to `long`.
- * - `str_to_ulong()` : converts the value to string, and tries to parse it as
- *   an integer. Use it if only you need strong conformity ov the value to an
- *   integer (currently, it's used only when examining keys of array object)
- *
- * ----------------------------------------------------------------------------
- *
- * TODO(dfrank):
- *   - Rename functions like `v7_get_double(v7, )`, `get_object_struct()` to
- *something
- *     that will clearly identify that they convert to some C entity, not
- *     `v7_val_t`
- *   - Maybe make `to_string()` private? But then, there will be no way
- *     in public API to convert value to `v7_val_t` string, so, for now
- *     it's here.
- *   - When we agree on what goes to public API, and what does not, write
- *     similar conversion guide for public API (in `conversion_public.h`)
- */
-
-/*
- * Convert any JS value to number, using common JavaScript semantics:
- *
- * - If value is an object:
- *   - call `valueOf()`;
- *   - If `valueOf()` returned non-primitive value, call `toString()`;
- *   - If `toString()` returned non-primitive value, throw `TypeError`.
- * - Now we have a primitive, and if it's not a number, then:
- *   - If `undefined`, return `NaN`
- *   - If `null`, return 0.0
- *   - If boolean, return either 1 or 0
- *   - If string, try to parse it.
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err to_number_v(struct v7 *v7, v7_val_t v, v7_val_t *res);
-
-/*
- * Convert any JS value to string, using common JavaScript semantics,
- * see `v7_stringify()` and `V7_STRINGIFY_DEFAULT`.
- *
- * This function can return multiple things:
- *
- * - String as a `v7_val_t` (if `res` is not `NULL`)
- * - String copied to buffer `buf` with max size `buf_size` (if `buf` is not
- *   `NULL`)
- * - Length of actual string, independently of `buf_size` (if `res_len` is not
- *   `NULL`)
- *
- * The rationale of having multiple formats of returned value is the following:
- *
- * Initially, to-string conversion always returned `v7_val_t`. But it turned
- * out that there are situations where such an approach adds useless pressure
- * on GC: e.g. when converting `undefined` to string, and the caller actually
- * needs a C buffer, not a `v7_val_t`.
- *
- * Always returning string through `buf`+`buf_size` is bad as well: if we
- * convert from object to string, and either `toString()` or `valueOf()`
- * returned string, then we'd have to get string data from it, write to buffer,
- * and if caller actually need `v7_val_t`, then it will have to create new
- * instance of the same string: again, useless GC pressure.
- *
- * So, we have to use the combined approach. This function will make minimal
- * work depending on give `res` and `buf`.
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err to_string(struct v7 *v7, v7_val_t v, v7_val_t *res,
-                                 char *buf, size_t buf_size, size_t *res_len);
-
-/*
- * Convert value to primitive, if it's not already.
- *
- * For object-to-primitive conversion, each object in JavaScript has two
- * methods: `toString()` and `valueOf()`.
- *
- * When converting object to string, JavaScript does the following:
- *   - call `toString()`;
- *   - If `toString()` returned non-primitive value, call `valueOf()`;
- *   - If `valueOf()` returned non-primitive value, throw `TypeError`.
- *
- * When converting object to number, JavaScript calls the same functions,
- * but in reverse:
- *   - call `valueOf()`;
- *   - If `valueOf()` returned non-primitive value, call `toString()`;
- *   - If `toString()` returned non-primitive value, throw `TypeError`.
- *
- * This function `to_primitive()` performs either type of conversion,
- * depending on the `hint` argument (see `enum to_primitive_hint`).
- */
-enum to_primitive_hint {
-  /* Call `valueOf()` first, then `toString()` if needed */
-  V7_TO_PRIMITIVE_HINT_NUMBER,
-
-  /* Call `toString()` first, then `valueOf()` if needed */
-  V7_TO_PRIMITIVE_HINT_STRING,
-
-  /* STRING for Date, NUMBER for everything else */
-  V7_TO_PRIMITIVE_HINT_AUTO,
-};
-WARN_UNUSED_RESULT
-enum v7_err to_primitive(struct v7 *v7, v7_val_t v, enum to_primitive_hint hint,
-                         v7_val_t *res);
-
-/*
- * Convert primitive value to string, using common JavaScript semantics. If
- * you need to convert any value to string (either object or primitive),
- * see `to_string()` or `v7_stringify_throwing()`.
- *
- * This function can return multiple things:
- *
- * - String as a `v7_val_t` (if `res` is not `NULL`)
- * - String copied to buffer `buf` with max size `buf_size` (if `buf` is not
- *   `NULL`)
- * - Length of actual string, independently of `buf_size` (if `res_len` is not
- *   `NULL`)
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err primitive_to_str(struct v7 *v7, val_t v, val_t *res,
-                                        char *buf, size_t buf_size,
-                                        size_t *res_len);
-
-/*
- * Convert primitive value to number, using common JavaScript semantics. If you
- * need to convert any value to number (either object or primitive), see
- * `to_number_v()`
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err primitive_to_number(struct v7 *v7, val_t v, val_t *res);
-
-/*
- * Convert value to JSON or "debug" representation, depending on whether
- * `is_debug` is non-zero. The "debug" is the same as JSON, but non-JSON values
- * (functions, `undefined`, etc) will not be omitted.
- *
- * See also `v7_stringify()`, `v7_stringify_throwing()`.
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err to_json_or_debug(struct v7 *v7, val_t v, char *buf,
-                                        size_t size, size_t *res_len,
-                                        uint8_t is_debug);
-
-/*
- * Calls `valueOf()` on given object `v`
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err obj_value_of(struct v7 *v7, val_t v, val_t *res);
-
-/*
- * Calls `toString()` on given object `v`
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err obj_to_string(struct v7 *v7, val_t v, val_t *res);
-
-/*
- * If given value is `undefined`, returns `default_value`; otherwise,
- * converts value to number, and then truncates to `long`.
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err to_long(struct v7 *v7, val_t v, long default_value,
-                               long *res);
-
-/*
- * Converts value to boolean as in the expression `if (v)` or `Boolean(v)`.
- *
- * NOTE: it can't throw (even if the given value is an object with `valueOf()`
- * that throws), so it returns `val_t` directly.
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE val_t to_boolean_v(struct v7 *v7, val_t v);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_CONVERSION_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/varint.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_VARINT_H_
-#define CS_V7_SRC_VARINT_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE int encode_varint(size_t len, unsigned char *p);
-V7_PRIVATE size_t decode_varint(const unsigned char *p, int *llen);
-V7_PRIVATE int calc_llen(size_t len);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_VARINT_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "common/cs_strtod.h"
-#endif
-/*
- * Copyright (c) 2014-2016 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_COMMON_CS_STRTOD_H_
-#define CS_COMMON_CS_STRTOD_H_
-
-double cs_strtod(const char *str, char **endptr);
-
-#endif /* CS_COMMON_CS_STRTOD_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/ast.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_AST_H_
-#define CS_V7_SRC_AST_H_
-
-#include <stdio.h>
-/* Amalgamated: #include "common/mbuf.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-#if !defined(V7_NO_COMPILER)
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-#define BIN_AST_SIGNATURE "V\007ASTV10"
-
-enum ast_tag {
-  AST_NOP,
-  AST_SCRIPT,
-  AST_VAR,
-  AST_VAR_DECL,
-  AST_FUNC_DECL,
-  AST_IF,
-  AST_FUNC,
-
-  AST_ASSIGN,
-  AST_REM_ASSIGN,
-  AST_MUL_ASSIGN,
-  AST_DIV_ASSIGN,
-  AST_XOR_ASSIGN,
-  AST_PLUS_ASSIGN,
-  AST_MINUS_ASSIGN,
-  AST_OR_ASSIGN,
-  AST_AND_ASSIGN,
-  AST_LSHIFT_ASSIGN,
-  AST_RSHIFT_ASSIGN,
-  AST_URSHIFT_ASSIGN,
-
-  AST_NUM,
-  AST_IDENT,
-  AST_STRING,
-  AST_REGEX,
-  AST_LABEL,
-
-  AST_SEQ,
-  AST_WHILE,
-  AST_DOWHILE,
-  AST_FOR,
-  AST_FOR_IN,
-  AST_COND,
-
-  AST_DEBUGGER,
-  AST_BREAK,
-  AST_LABELED_BREAK,
-  AST_CONTINUE,
-  AST_LABELED_CONTINUE,
-  AST_RETURN,
-  AST_VALUE_RETURN,
-  AST_THROW,
-
-  AST_TRY,
-  AST_SWITCH,
-  AST_CASE,
-  AST_DEFAULT,
-  AST_WITH,
-
-  AST_LOGICAL_OR,
-  AST_LOGICAL_AND,
-  AST_OR,
-  AST_XOR,
-  AST_AND,
-
-  AST_EQ,
-  AST_EQ_EQ,
-  AST_NE,
-  AST_NE_NE,
-
-  AST_LE,
-  AST_LT,
-  AST_GE,
-  AST_GT,
-  AST_IN,
-  AST_INSTANCEOF,
-
-  AST_LSHIFT,
-  AST_RSHIFT,
-  AST_URSHIFT,
-
-  AST_ADD,
-  AST_SUB,
-
-  AST_REM,
-  AST_MUL,
-  AST_DIV,
-
-  AST_POSITIVE,
-  AST_NEGATIVE,
-  AST_NOT,
-  AST_LOGICAL_NOT,
-  AST_VOID,
-  AST_DELETE,
-  AST_TYPEOF,
-  AST_PREINC,
-  AST_PREDEC,
-
-  AST_POSTINC,
-  AST_POSTDEC,
-
-  AST_MEMBER,
-  AST_INDEX,
-  AST_CALL,
-
-  AST_NEW,
-
-  AST_ARRAY,
-  AST_OBJECT,
-  AST_PROP,
-  AST_GETTER,
-  AST_SETTER,
-
-  AST_THIS,
-  AST_TRUE,
-  AST_FALSE,
-  AST_NULL,
-  AST_UNDEFINED,
-
-  AST_USE_STRICT,
-
-  AST_MAX_TAG
-};
-
-struct ast {
-  struct mbuf mbuf;
-  int refcnt;
-  int has_overflow;
-};
-
-typedef unsigned long ast_off_t;
-
-#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 8
-#define GCC_HAS_PRAGMA_DIAGNOSTIC
-#endif
-
-#ifdef GCC_HAS_PRAGMA_DIAGNOSTIC
-/*
- * TODO(mkm): GCC complains that bitfields on char are not standard
- */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpedantic"
-#endif
-struct ast_node_def {
-#ifndef V7_DISABLE_AST_TAG_NAMES
-  const char *name; /* tag name, for debugging and serialization */
-#endif
-  unsigned char has_varint : 1;   /* has a varint body */
-  unsigned char has_inlined : 1;  /* inlined data whose size is in varint fld */
-  unsigned char num_skips : 3;    /* number of skips */
-  unsigned char num_subtrees : 3; /* number of fixed subtrees */
-};
-extern const struct ast_node_def ast_node_defs[];
-#if V7_ENABLE_FOOTPRINT_REPORT
-extern const size_t ast_node_defs_size;
-extern const size_t ast_node_defs_count;
-#endif
-#ifdef GCC_HAS_PRAGMA_DIAGNOSTIC
-#pragma GCC diagnostic pop
-#endif
-
-enum ast_which_skip {
-  AST_END_SKIP = 0,
-  AST_VAR_NEXT_SKIP = 1,
-  AST_SCRIPT_FIRST_VAR_SKIP = AST_VAR_NEXT_SKIP,
-  AST_FOR_BODY_SKIP = 1,
-  AST_DO_WHILE_COND_SKIP = 1,
-  AST_END_IF_TRUE_SKIP = 1,
-  AST_TRY_CATCH_SKIP = 1,
-  AST_TRY_FINALLY_SKIP = 2,
-  AST_FUNC_FIRST_VAR_SKIP = AST_VAR_NEXT_SKIP,
-  AST_FUNC_BODY_SKIP = 2,
-  AST_SWITCH_DEFAULT_SKIP = 1
-};
-
-V7_PRIVATE void ast_init(struct ast *, size_t);
-V7_PRIVATE void ast_optimize(struct ast *);
-V7_PRIVATE void ast_free(struct ast *);
-
-/*
- * Begins an AST node by inserting a tag to the AST at the given offset.
- *
- * It also allocates space for the fixed_size payload and the space for
- * the skips.
- *
- * The caller is responsible for appending children.
- *
- * Returns the offset of the node payload (one byte after the tag).
- * This offset can be passed to `ast_set_skip`.
- */
-V7_PRIVATE ast_off_t
-ast_insert_node(struct ast *a, ast_off_t pos, enum ast_tag tag);
-
-/*
- * Modify tag which is already added to buffer. Keeps `AST_TAG_LINENO_PRESENT`
- * flag.
- */
-V7_PRIVATE void ast_modify_tag(struct ast *a, ast_off_t tag_off,
-                               enum ast_tag tag);
-
-#ifndef V7_DISABLE_LINE_NUMBERS
-/*
- * Add line_no varint after all skips of the tag at the offset `tag_off`, and
- * marks the tag byte.
- *
- * Byte at the offset `tag_off` should be a valid tag.
- */
-V7_PRIVATE void ast_add_line_no(struct ast *a, ast_off_t tag_off, int line_no);
-#endif
-
-/*
- * Patches a given skip slot for an already emitted node with the
- * current write cursor position (e.g. AST length).
- *
- * This is intended to be invoked when a node with a variable number
- * of child subtrees is closed, or when the consumers need a shortcut
- * to the next sibling.
- *
- * Each node type has a different number and semantic for skips,
- * all of them defined in the `ast_which_skip` enum.
- * All nodes having a variable number of child subtrees must define
- * at least the `AST_END_SKIP` skip, which effectively skips a node
- * boundary.
- *
- * Every tree reader can assume this and safely skip unknown nodes.
- *
- * `pos` should be an offset of the byte right after a tag.
- */
-V7_PRIVATE ast_off_t
-ast_set_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip);
-
-/*
- * Patches a given skip slot for an already emitted node with the value
- * (stored as delta relative to the `pos` node) of the `where` argument.
- */
-V7_PRIVATE ast_off_t ast_modify_skip(struct ast *a, ast_off_t pos,
-                                     ast_off_t where, enum ast_which_skip skip);
-
-/*
- * Returns the offset in AST to which the given `skip` points.
- *
- * `pos` should be an offset of the byte right after a tag.
- */
-V7_PRIVATE ast_off_t
-ast_get_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip);
-
-/*
- * Returns the tag from the offset `ppos`, and shifts `ppos` by 1.
- */
-V7_PRIVATE enum ast_tag ast_fetch_tag(struct ast *a, ast_off_t *ppos);
-
-/*
- * Moves the cursor to the tag's varint and inlined data (if there are any, see
- * `struct ast_node_def::has_varint` and `struct ast_node_def::has_inlined`).
- *
- * Technically, it skips node's "skips" and line number data, if either is
- * present.
- *
- * Assumes a cursor (`ppos`) positioned right after a tag.
- */
-V7_PRIVATE void ast_move_to_inlined_data(struct ast *a, ast_off_t *ppos);
-
-/*
- * Moves the cursor to the tag's subtrees (if there are any,
- * see `struct ast_node_def::num_subtrees`), or to the next node in case the
- * current node has no subtrees.
- *
- * Technically, it skips node's "skips", line number data, and inlined data, if
- * either is present.
- *
- * Assumes a cursor (`ppos`) positioned right after a tag.
- */
-V7_PRIVATE void ast_move_to_children(struct ast *a, ast_off_t *ppos);
-
-/* Helper to add a node with inlined data. */
-V7_PRIVATE ast_off_t ast_insert_inlined_node(struct ast *a, ast_off_t pos,
-                                             enum ast_tag tag, const char *name,
-                                             size_t len);
-
-/*
- * Returns the line number encoded in the node, or `0` in case of none is
- * encoded.
- *
- * `pos` should be an offset of the byte right after a tag.
- */
-V7_PRIVATE int ast_get_line_no(struct ast *a, ast_off_t pos);
-
-/*
- * `pos` should be an offset of the byte right after a tag
- */
-V7_PRIVATE char *ast_get_inlined_data(struct ast *a, ast_off_t pos, size_t *n);
-
-/*
- * Returns the `double` number inlined in the node
- */
-V7_PRIVATE double ast_get_num(struct ast *a, ast_off_t pos);
-
-/*
- * Skips the node and all its subnodes.
- *
- * Cursor (`ppos`) should be at the tag byte
- */
-V7_PRIVATE void ast_skip_tree(struct ast *a, ast_off_t *ppos);
-
-V7_PRIVATE void ast_dump_tree(FILE *fp, struct ast *a, ast_off_t *ppos,
-                              int depth);
-
-V7_PRIVATE void release_ast(struct v7 *v7, struct ast *a);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_NO_COMPILER */
-
-#endif /* CS_V7_SRC_AST_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/bcode.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_BCODE_H_
-#define CS_V7_SRC_BCODE_H_
-
-#define BIN_BCODE_SIGNATURE "V\007BCODE:"
-
-#if !defined(V7_NAMES_CNT_WIDTH)
-#define V7_NAMES_CNT_WIDTH 10
-#endif
-
-#if !defined(V7_ARGS_CNT_WIDTH)
-#define V7_ARGS_CNT_WIDTH 8
-#endif
-
-#define V7_NAMES_CNT_MAX ((1 << V7_NAMES_CNT_WIDTH) - 1)
-#define V7_ARGS_CNT_MAX ((1 << V7_ARGS_CNT_WIDTH) - 1)
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/opcodes.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "common/mbuf.h" */
-
-enum bcode_inline_lit_type_tag {
-  BCODE_INLINE_STRING_TYPE_TAG = 0,
-  BCODE_INLINE_NUMBER_TYPE_TAG,
-  BCODE_INLINE_FUNC_TYPE_TAG,
-  BCODE_INLINE_REGEXP_TYPE_TAG,
-
-  BCODE_MAX_INLINE_TYPE_TAG
-};
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-typedef uint32_t bcode_off_t;
-
-/*
- * Each JS function will have one bcode structure
- * containing the instruction stream, a literal table, and function
- * metadata.
- * Instructions contain references to literals (strings, constants, etc)
- *
- * The bcode struct can be shared between function instances
- * and keeps a reference count used to free it in the function destructor.
- */
-struct bcode {
-  /*
-   * Names + instruction opcode.
-   * Names are null-terminates strings. For function's bcode, there are:
-   *  - function name (for anonymous function, the name is still present: an
-   *    empty string);
-   *  - arg names (a number of args is determined by `args_cnt`, see below);
-   *  - local names (a number or locals can be calculated:
-   *    `(names_cnt - args_cnt - 1)`).
-   *
-   * For script's bcode, there are just local names.
-   */
-  struct v7_vec ops;
-
-  /* Literal table */
-  struct v7_vec lit;
-
-#ifndef V7_DISABLE_FILENAMES
-  /* Name of the file from which this bcode was generated (used for debug) */
-  void *filename;
-#endif
-
-  /* Reference count */
-  uint8_t refcnt;
-
-  /* Total number of null-terminated strings in the beginning of `ops` */
-  unsigned int names_cnt : V7_NAMES_CNT_WIDTH;
-
-  /* Number of args (should be <= `(names_cnt + 1)`) */
-  unsigned int args_cnt : V7_ARGS_CNT_WIDTH;
-
-  unsigned int strict_mode : 1;
-  /*
-   * If true this structure lives on read only memory, either
-   * mmapped or constant data section.
-   */
-  unsigned int frozen : 1;
-
-  /* If set, `ops.buf` points to ROM, so we shouldn't free it */
-  unsigned int ops_in_rom : 1;
-  /* Set for deserialized bcode. Used for metrics only */
-  unsigned int deserialized : 1;
-
-  /* Set when `ops` contains function name as the first `name` */
-  unsigned int func_name_present : 1;
-
-#ifndef V7_DISABLE_FILENAMES
-  /* If set, `filename` points to ROM, so we shouldn't free it */
-  unsigned int filename_in_rom : 1;
-#endif
-};
-
-/*
- * Bcode builder context: it contains mutable mbufs for opcodes and literals,
- * whereas the bcode itself contains just vectors (`struct v7_vec`).
- */
-struct bcode_builder {
-  struct v7 *v7;
-  struct bcode *bcode;
-
-  struct mbuf ops; /* names + instruction opcode */
-  struct mbuf lit; /* literal table */
-};
-
-V7_PRIVATE void bcode_builder_init(struct v7 *v7,
-                                   struct bcode_builder *bbuilder,
-                                   struct bcode *bcode);
-V7_PRIVATE void bcode_builder_finalize(struct bcode_builder *bbuilder);
-
-/*
- * Note: `filename` must be either:
- *
- * - `NULL`. In this case, `filename_in_rom` is ignored.
- * - A pointer to ROM (or to any other unmanaged memory). `filename_in_rom`
- *   must be set to 1.
- * - A pointer returned by `shdata_create()`, i.e. a pointer to shared data.
- *
- * If you need to copy filename from another bcode, just pass NULL initially,
- * and after bcode is initialized, call `bcode_copy_filename_from()`.
- *
- * To get later a proper null-terminated filename string from bcode, use
- * `bcode_get_filename()`.
- */
-V7_PRIVATE void bcode_init(struct bcode *bcode, uint8_t strict_mode,
-                           void *filename, uint8_t filename_in_rom);
-V7_PRIVATE void bcode_free(struct v7 *v7, struct bcode *bcode);
-V7_PRIVATE void release_bcode(struct v7 *v7, struct bcode *bcode);
-V7_PRIVATE void retain_bcode(struct v7 *v7, struct bcode *bcode);
-
-#ifndef V7_DISABLE_FILENAMES
-/*
- * Return a pointer to null-terminated filename string
- */
-V7_PRIVATE const char *bcode_get_filename(struct bcode *bcode);
-#endif
-
-/*
- * Copy filename from `src` to `dst`. If source filename is a pointer to ROM,
- * then just the pointer is copied; otherwise, appropriate shdata pointer is
- * retained.
- */
-V7_PRIVATE void bcode_copy_filename_from(struct bcode *dst, struct bcode *src);
-
-/*
- * Serialize a bcode structure.
- *
- * All literals, including functions, are inlined into `ops` data; see
- * the serialization logic in `bcode_op_lit()`.
- *
- * The root bcode looks just like a regular function.
- *
- * This function is used only internally, but used in a complicated mix of
- * configurations, hence the commented V7_PRIVATE
- */
-/*V7_PRIVATE*/ void bcode_serialize(struct v7 *v7, struct bcode *bcode,
-                                    FILE *f);
-
-V7_PRIVATE void bcode_deserialize(struct v7 *v7, struct bcode *bcode,
-                                  const char *data);
-
-#ifdef V7_BCODE_DUMP
-V7_PRIVATE void dump_bcode(struct v7 *v7, FILE *, struct bcode *);
-#endif
-
-/* mode of literal storage: in literal table or inlined in `ops` */
-enum lit_mode {
-  /* literal stored in table, index is in `lit_t::lit_idx` */
-  LIT_MODE__TABLE,
-  /* literal should be inlined in `ops`, value is in `lit_t::inline_val` */
-  LIT_MODE__INLINED,
-};
-
-/*
- * Result of the addition of literal value to bcode (see `bcode_add_lit()`).
- * There are two possible cases:
- *
- * - Literal is added to the literal table. In this case, `mode ==
- *   LIT_MODE__TABLE`, and the index of the literal is stored in `lit_idx`
- * - Literal is not added anywhere, and should be inlined into `ops`. In this
- *   case, `mode == LIT_MODE__INLINED`, and the value to inline is stored in
- *   `inline_val`.
- *
- * It's `bcode_op_lit()` who handles both of these cases.
- */
-typedef struct {
-  union {
-    /*
-     * index in literal table;
-     * NOTE: valid if only `mode == LIT_MODE__TABLE`
-     */
-    size_t lit_idx;
-
-    /*
-     * value to be inlined into `ops`;
-     * NOTE: valid if only `mode == LIT_MODE__INLINED`
-     */
-    v7_val_t inline_val;
-  } v; /* anonymous unions are a c11 feature */
-
-  /*
-   * mode of literal storage (see `enum lit_mode`)
-   * NOTE: we need one more bit, because enum can be signed
-   * on some compilers (e.g. msvc) and thus will get signextended
-   * when moved to a `enum lit_mode` variable basically corrupting
-   * the value. See https://github.com/cesanta/v7/issues/551
-   */
-  enum lit_mode mode : 2;
-} lit_t;
-
-V7_PRIVATE void bcode_op(struct bcode_builder *bbuilder, uint8_t op);
-
-#ifndef V7_DISABLE_LINE_NUMBERS
-V7_PRIVATE void bcode_append_lineno(struct bcode_builder *bbuilder,
-                                    int line_no);
-#endif
-
-/*
- * Add a literal to the bcode literal table, or just decide that the literal
- * should be inlined into `ops`. See `lit_t` for details.
- */
-V7_PRIVATE
-lit_t bcode_add_lit(struct bcode_builder *bbuilder, v7_val_t val);
-
-/* disabled because of short lits */
-#if 0
-V7_PRIVATE v7_val_t bcode_get_lit(struct bcode *bcode, size_t idx);
-#endif
-
-/*
- * Emit an opcode `op`, and handle the literal `lit` (see `bcode_add_lit()`,
- * `lit_t`). Depending on the literal storage mode (see `enum lit_mode`), this
- * function either emits literal table index or inlines the literal directly
- * into `ops.`
- */
-V7_PRIVATE void bcode_op_lit(struct bcode_builder *bbuilder, enum opcode op,
-                             lit_t lit);
-
-/* Helper function, equivalent of `bcode_op_lit(bbuilder, OP_PUSH_LIT, lit)` */
-V7_PRIVATE void bcode_push_lit(struct bcode_builder *bbuilder, lit_t lit);
-
-/*
- * Add name to bcode. If `idx` is null, a name is appended to the end of the
- * `bcode->ops.buf`. If `idx` is provided, it should point to the index at
- * which new name should be inserted; and it is updated by the
- * `bcode_add_name()` to point right after newly added name.
- *
- * This function is used only internally, but used in a complicated mix of
- * configurations, hence the commented V7_PRIVATE
- */
-WARN_UNUSED_RESULT
-    /*V7_PRIVATE*/ enum v7_err
-    bcode_add_name(struct bcode_builder *bbuilder, const char *p, size_t len,
-                   size_t *idx);
-
-/*
- * Takes a pointer to the beginning of `ops` buffer and names count, returns
- * a pointer where actual opcodes begin (i.e. skips names).
- *
- * It takes two distinct arguments instead of just `struct bcode` pointer,
- * because during bcode building `ops` is stored in builder.
- *
- * This function is used only internally, but used in a complicated mix of
- * configurations, hence the commented V7_PRIVATE
- */
-/*V7_PRIVATE*/ char *bcode_end_names(char *ops, size_t names_cnt);
-
-/*
- * Given a pointer to `ops` (which should be `bcode->ops` or a pointer returned
- * from previous invocation of `bcode_next_name()`), yields a name string via
- * arguments `pname`, `plen`.
- *
- * Returns a pointer that should be given to `bcode_next_name()` to get a next
- * string (Whether there is a next string should be determined via the
- * `names_cnt`; since if there are no more names, this function will return an
- * invalid non-null pointer as next name pointer)
- */
-V7_PRIVATE char *bcode_next_name(char *ops, char **pname, size_t *plen);
-
-/*
- * Like `bcode_next_name()`, but instead of yielding a C string, it yields a
- * `val_t` value (via `res`).
- */
-V7_PRIVATE char *bcode_next_name_v(struct v7 *v7, struct bcode *bcode,
-                                   char *ops, val_t *res);
-
-V7_PRIVATE bcode_off_t bcode_pos(struct bcode_builder *bbuilder);
-
-V7_PRIVATE bcode_off_t bcode_add_target(struct bcode_builder *bbuilder);
-/*
- * This function is used only internally, but used in a complicated mix of
- * configurations, hence the commented V7_PRIVATE
- */
-/*V7_PRIVATE*/ bcode_off_t bcode_op_target(struct bcode_builder *bbuilder,
-                                           uint8_t op);
-/*V7_PRIVATE*/ void bcode_patch_target(struct bcode_builder *bbuilder,
-                                       bcode_off_t label, bcode_off_t target);
-
-V7_PRIVATE void bcode_add_varint(struct bcode_builder *bbuilder, size_t value);
-/*
- * Reads varint-encoded integer from the provided pointer, and adjusts
- * the pointer appropriately
- */
-V7_PRIVATE size_t bcode_get_varint(char **ops);
-
-/*
- * Decode a literal value from a string of opcodes and update the cursor to
- * point past it
- */
-V7_PRIVATE
-v7_val_t bcode_decode_lit(struct v7 *v7, struct bcode *bcode, char **ops);
-
-#if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE)
-V7_PRIVATE void dump_op(struct v7 *v7, FILE *f, struct bcode *bcode,
-                        char **ops);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_BCODE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/gc_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Garbage Collector
- */
-
-#ifndef CS_V7_SRC_GC_PUBLIC_H_
-#define CS_V7_SRC_GC_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-#if V7_ENABLE__Memory__stats
-
-/* Heap metric id, see `v7_heap_stat()` */
-enum v7_heap_stat_what {
-  V7_HEAP_STAT_HEAP_SIZE,
-  V7_HEAP_STAT_HEAP_USED,
-  V7_HEAP_STAT_STRING_HEAP_RESERVED,
-  V7_HEAP_STAT_STRING_HEAP_USED,
-  V7_HEAP_STAT_OBJ_HEAP_MAX,
-  V7_HEAP_STAT_OBJ_HEAP_FREE,
-  V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE,
-  V7_HEAP_STAT_FUNC_HEAP_MAX,
-  V7_HEAP_STAT_FUNC_HEAP_FREE,
-  V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE,
-  V7_HEAP_STAT_PROP_HEAP_MAX,
-  V7_HEAP_STAT_PROP_HEAP_FREE,
-  V7_HEAP_STAT_PROP_HEAP_CELL_SIZE,
-  V7_HEAP_STAT_FUNC_AST_SIZE,
-  V7_HEAP_STAT_BCODE_OPS_SIZE,
-  V7_HEAP_STAT_BCODE_LIT_TOTAL_SIZE,
-  V7_HEAP_STAT_BCODE_LIT_DESER_SIZE,
-  V7_HEAP_STAT_FUNC_OWNED,
-  V7_HEAP_STAT_FUNC_OWNED_MAX
-};
-
-/* Returns a given heap statistics */
-int v7_heap_stat(struct v7 *v7, enum v7_heap_stat_what what);
-#endif
-
-/*
- * Perform garbage collection.
- * Pass true to full in order to reclaim unused heap back to the OS.
- */
-void v7_gc(struct v7 *v7, int full);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_GC_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/gc.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_GC_H_
-#define CS_V7_SRC_GC_H_
-
-/* Amalgamated: #include "v7/src/gc_public.h" */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-/*
- * Macros for marking reachable things: use bit 0.
- */
-#define MARK(p) (((struct gc_cell *) (p))->head.word |= 1)
-#define UNMARK(p) (((struct gc_cell *) (p))->head.word &= ~1)
-#define MARKED(p) (((struct gc_cell *) (p))->head.word & 1)
-
-/*
- * Similar to `MARK()` / `UNMARK()` / `MARKED()`, but `.._FREE` counterparts
- * are intended to mark free cells (as opposed to used ones), so they use
- * bit 1.
- */
-#define MARK_FREE(p) (((struct gc_cell *) (p))->head.word |= 2)
-#define UNMARK_FREE(p) (((struct gc_cell *) (p))->head.word &= ~2)
-#define MARKED_FREE(p) (((struct gc_cell *) (p))->head.word & 2)
-
-/*
- * performs arithmetics on gc_cell pointers as if they were arena->cell_size
- * bytes wide
- */
-#define GC_CELL_OP(arena, cell, op, arg) \
-  ((struct gc_cell *) (((char *) (cell)) op((arg) * (arena)->cell_size)))
-
-struct gc_tmp_frame {
-  struct v7 *v7;
-  size_t pos;
-};
-
-struct gc_cell {
-  union {
-    struct gc_cell *link;
-    uintptr_t word;
-  } head;
-};
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE struct v7_generic_object *new_generic_object(struct v7 *);
-V7_PRIVATE struct v7_property *new_property(struct v7 *);
-V7_PRIVATE struct v7_js_function *new_function(struct v7 *);
-
-V7_PRIVATE void gc_mark(struct v7 *, val_t);
-
-V7_PRIVATE void gc_arena_init(struct gc_arena *, size_t, size_t, size_t,
-                              const char *);
-V7_PRIVATE void gc_arena_destroy(struct v7 *, struct gc_arena *a);
-V7_PRIVATE void gc_sweep(struct v7 *, struct gc_arena *, size_t);
-V7_PRIVATE void *gc_alloc_cell(struct v7 *, struct gc_arena *);
-
-V7_PRIVATE struct gc_tmp_frame new_tmp_frame(struct v7 *);
-V7_PRIVATE void tmp_frame_cleanup(struct gc_tmp_frame *);
-V7_PRIVATE void tmp_stack_push(struct gc_tmp_frame *, val_t *);
-
-V7_PRIVATE void compute_need_gc(struct v7 *);
-/* perform gc if not inhibited */
-V7_PRIVATE int maybe_gc(struct v7 *);
-
-#ifndef V7_DISABLE_STR_ALLOC_SEQ
-V7_PRIVATE uint16_t
-gc_next_allocation_seqn(struct v7 *v7, const char *str, size_t len);
-V7_PRIVATE int gc_is_valid_allocation_seqn(struct v7 *v7, uint16_t n);
-V7_PRIVATE void gc_check_valid_allocation_seqn(struct v7 *v7, uint16_t n);
-#endif
-
-V7_PRIVATE uint64_t gc_string_val_to_offset(val_t v);
-
-/* return 0 if v is an object/function with a bad pointer */
-V7_PRIVATE int gc_check_val(struct v7 *v7, val_t v);
-
-/* checks whether a pointer is within the ranges of an arena */
-V7_PRIVATE int gc_check_ptr(const struct gc_arena *a, const void *p);
-
-#if V7_ENABLE__Memory__stats
-V7_PRIVATE size_t gc_arena_size(struct gc_arena *);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_GC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/regexp_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === RegExp
- */
-
-#ifndef CS_V7_SRC_REGEXP_PUBLIC_H_
-#define CS_V7_SRC_REGEXP_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Make RegExp object.
- * `regex`, `regex_len` specify a pattern, `flags` and `flags_len` specify
- * flags. Both utf8 encoded. For example, `regex` is `(.+)`, `flags` is `gi`.
- * If `regex_len` is ~0, `regex` is assumed to be NUL-terminated and
- * `strlen(regex)` is used.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_mk_regexp(struct v7 *v7, const char *regex, size_t regex_len,
-                         const char *flags, size_t flags_len, v7_val_t *res);
-
-/* Returns true if given value is a JavaScript RegExp object*/
-int v7_is_regexp(struct v7 *v7, v7_val_t v);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_REGEXP_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/regexp.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_REGEXP_H_
-#define CS_V7_SRC_REGEXP_H_
-
-/* Amalgamated: #include "v7/src/regexp_public.h" */
-
-/* Amalgamated: #include "v7/src/core.h" */
-
-#if V7_ENABLE__RegExp
-
-/*
- * Maximum number of flags returned by get_regexp_flags_str().
- * NOTE: does not include null-terminate byte.
- */
-#define _V7_REGEXP_MAX_FLAGS_LEN 3
-
-struct v7_regexp;
-
-V7_PRIVATE struct v7_regexp *v7_get_regexp_struct(struct v7 *, v7_val_t);
-
-/*
- * Generates a string containing regexp flags, e.g. "gi".
- *
- * `buf` should point to a buffer of minimum `_V7_REGEXP_MAX_FLAGS_LEN` bytes.
- * Returns length of the resulted string (saved into `buf`)
- */
-V7_PRIVATE size_t
-get_regexp_flags_str(struct v7 *v7, struct v7_regexp *rp, char *buf);
-#endif /* V7_ENABLE__RegExp */
-
-#endif /* CS_V7_SRC_REGEXP_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/function_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Functions
- */
-
-#ifndef CS_V7_SRC_FUNCTION_PUBLIC_H_
-#define CS_V7_SRC_FUNCTION_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Make a JS function object backed by a cfunction.
- *
- * `func` is a C callback.
- *
- * A function object is JS object having the Function prototype that holds a
- * cfunction value in a hidden property.
- *
- * The function object will have a `prototype` property holding an object that
- * will be used as the prototype of objects created when calling the function
- * with the `new` operator.
- */
-v7_val_t v7_mk_function(struct v7 *, v7_cfunction_t *func);
-
-/*
- * Make f a JS function with specified prototype `proto`, so that the resulting
- * function is better suited for the usage as a constructor.
- */
-v7_val_t v7_mk_function_with_proto(struct v7 *v7, v7_cfunction_t *f,
-                                   v7_val_t proto);
-
-/*
- * Make a JS value that holds C/C++ callback pointer.
- *
- * CAUTION: This is a low-level function value. It's not a real object and
- * cannot hold user defined properties. You should use `v7_mk_function` unless
- * you know what you're doing.
- */
-v7_val_t v7_mk_cfunction(v7_cfunction_t *func);
-
-/*
- * Returns true if given value is callable (i.e. it's either a JS function or
- * cfunction)
- */
-int v7_is_callable(struct v7 *v7, v7_val_t v);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_FUNCTION_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/function.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_FUNCTION_H_
-#define CS_V7_SRC_FUNCTION_H_
-
-/* Amalgamated: #include "v7/src/function_public.h" */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE struct v7_js_function *get_js_function_struct(val_t v);
-V7_PRIVATE val_t
-mk_js_function(struct v7 *v7, struct v7_generic_object *scope, val_t proto);
-V7_PRIVATE int is_js_function(val_t v);
-V7_PRIVATE v7_val_t mk_cfunction_lite(v7_cfunction_t *f);
-
-/* Returns true if given value holds a pointer to C callback */
-V7_PRIVATE int is_cfunction_lite(v7_val_t v);
-
-/* Returns true if given value holds an object which represents C callback */
-V7_PRIVATE int is_cfunction_obj(struct v7 *v7, v7_val_t v);
-
-/*
- * Returns `v7_cfunction_t *` callback pointer stored in `v7_val_t`, or NULL
- * if given value is neither cfunction pointer nor cfunction object.
- */
-V7_PRIVATE v7_cfunction_t *get_cfunction_ptr(struct v7 *v7, v7_val_t v);
-
-/*
- * Like v7_mk_function but also sets the function's `length` property.
- *
- * The `length` property is useful for introspection and the stdlib defines it
- * for many core functions mostly because the ECMA test suite requires it and we
- * don't want to skip otherwise useful tests just because the `length` property
- * check fails early in the test. User defined functions don't need to specify
- * the length and passing -1 is a safe choice, as it will also reduce the
- * footprint.
- *
- * The subtle difference between set `length` explicitly to 0 rather than
- * just defaulting the `0` value from the prototype is that in the former case
- * the property cannot be change since it's read only. This again, is important
- * only for ecma compliance and your user code might or might not find this
- * relevant.
- *
- * NODO(lsm): please don't combine v7_mk_function_arg and v7_mk_function
- * into one function. Currently `num_args` is useful only internally. External
- * users can just use `v7_def` to set the length.
- */
-V7_PRIVATE
-v7_val_t mk_cfunction_obj(struct v7 *v7, v7_cfunction_t *func, int num_args);
-
-/*
- * Like v7_mk_function_with_proto but also sets the function's `length`
- *property.
- *
- * NODO(lsm): please don't combine mk_cfunction_obj_with_proto and
- * v7_mk_function_with_proto.
- * into one function. Currently `num_args` is useful only internally. External
- * users can just use `v7_def` to set the length.
- */
-V7_PRIVATE
-v7_val_t mk_cfunction_obj_with_proto(struct v7 *v7, v7_cfunction_t *f,
-                                     int num_args, v7_val_t proto);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_FUNCTION_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/util_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Utility functions
- */
-
-#ifndef CS_V7_SRC_UTIL_PUBLIC_H_
-#define CS_V7_SRC_UTIL_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/* Output a string representation of the value to stdout.
- * V7_STRINGIFY_DEBUG mode is used. */
-void v7_print(struct v7 *v7, v7_val_t v);
-
-/* Output a string representation of the value to stdout followed by a newline.
- * V7_STRINGIFY_DEBUG mode is used. */
-void v7_println(struct v7 *v7, v7_val_t v);
-
-/* Output a string representation of the value to a file.
- * V7_STRINGIFY_DEBUG mode is used. */
-void v7_fprint(FILE *f, struct v7 *v7, v7_val_t v);
-
-/* Output a string representation of the value to a file followed by a newline.
- * V7_STRINGIFY_DEBUG mode is used. */
-void v7_fprintln(FILE *f, struct v7 *v7, v7_val_t v);
-
-/* Output stack trace recorded in the exception `e` to file `f` */
-void v7_fprint_stack_trace(FILE *f, struct v7 *v7, v7_val_t e);
-
-/* Output error object message and possibly stack trace to f */
-void v7_print_error(FILE *f, struct v7 *v7, const char *ctx, v7_val_t e);
-
-#if V7_ENABLE__Proxy
-
-struct v7_property;
-
-/*
- * C callback, analogue of JS callback `getOwnPropertyDescriptor()`.
- * Callbacks of this type are used for C API only, see `m7_mk_proxy()`.
- *
- * `name` is the name of the property, and the function should fill `attrs` and
- * `value` with the property data. Before this callback is called, `attrs` is
- * set to 0, and `value` is `V7_UNDEFINED`.
- *
- * It should return non-zero if the property should be considered existing, or
- * zero otherwise.
- *
- * You can inspect the property attributes with the `V7_PROP_ATTR_IS_*` macros.
- */
-typedef int(v7_get_own_prop_desc_cb_t)(struct v7 *v7, v7_val_t target,
-                                       v7_val_t name, v7_prop_attr_t *attrs,
-                                       v7_val_t *value);
-
-/* Handler for `v7_mk_proxy()`; each item is a cfunction */
-typedef struct {
-  v7_cfunction_t *get;
-  v7_cfunction_t *set;
-  v7_cfunction_t *own_keys;
-  v7_get_own_prop_desc_cb_t *get_own_prop_desc;
-} v7_proxy_hnd_t;
-
-/*
- * Create a Proxy object, see:
- * https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy
- *
- * Only two traps are implemented so far: `get()` and `set()`. Note that
- * `Object.defineProperty()` bypasses the `set()` trap.
- *
- * If `target` is not an object, the empty object will be used, so it's safe
- * to pass `V7_UNDEFINED` as `target`.
- */
-v7_val_t v7_mk_proxy(struct v7 *v7, v7_val_t target,
-                     const v7_proxy_hnd_t *handler);
-
-#endif /* V7_ENABLE__Proxy */
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_UTIL_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/util.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_UTIL_H_
-#define CS_V7_SRC_UTIL_H_
-
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/util_public.h" */
-
-struct bcode;
-
-V7_PRIVATE enum v7_type val_type(struct v7 *v7, val_t v);
-
-#ifndef V7_DISABLE_LINE_NUMBERS
-V7_PRIVATE uint8_t msb_lsb_swap(uint8_t b);
-#endif
-
-/*
- * At the moment, all other utility functions are public, and are declared in
- * `util_public.h`
- */
-
-#endif /* CS_V7_SRC_UTIL_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/shdata.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * shdata (stands for "shared data") is a simple module that allows to have
- * reference count for an arbitrary payload data, which will be freed as
- * necessary. A poor man's shared_ptr.
- */
-
-#ifndef CS_V7_SRC_SHDATA_H_
-#define CS_V7_SRC_SHDATA_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-#if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
-struct shdata {
-  /* Reference count */
-  uint8_t refcnt;
-
-  /*
-   * Note: we'd use `unsigned char payload[];` here, but we can't, since this
-   * feature was introduced in C99 only
-   */
-};
-
-/*
- * Allocate memory chunk of appropriate size, copy given `payload` data there,
- * retain (`shdata_retain()`), and return it.
- */
-V7_PRIVATE struct shdata *shdata_create(const void *payload, size_t size);
-
-V7_PRIVATE struct shdata *shdata_create_from_string(const char *src);
-
-/*
- * Increment reference count for the given shared data
- */
-V7_PRIVATE void shdata_retain(struct shdata *p);
-
-/*
- * Decrement reference count for the given shared data
- */
-V7_PRIVATE void shdata_release(struct shdata *p);
-
-/*
- * Get payload data
- */
-V7_PRIVATE void *shdata_get_payload(struct shdata *p);
-
-#endif
-#endif /* CS_V7_SRC_SHDATA_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/eval.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_EVAL_H_
-#define CS_V7_SRC_EVAL_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/bcode.h" */
-
-struct v7_call_frame_base;
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err eval_bcode(struct v7 *v7, struct bcode *bcode,
-                                  val_t this_object, uint8_t reset_line_no,
-                                  val_t *_res);
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err b_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
-                               v7_val_t args, uint8_t is_constructor,
-                               v7_val_t *res);
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err b_exec(struct v7 *v7, const char *src, size_t src_len,
-                              const char *filename, val_t func, val_t args,
-                              val_t this_object, int is_json, int fr,
-                              uint8_t is_constructor, val_t *res);
-
-/*
- * Try to find the call frame whose `type_mask` intersects with the given
- * `type_mask`.
- *
- * Start from the top call frame, and go deeper until the matching frame is
- * found, or there's no more call frames. If the needed frame was not found,
- * returns `NULL`.
- */
-V7_PRIVATE struct v7_call_frame_base *find_call_frame(struct v7 *v7,
-                                                      uint8_t type_mask);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_EVAL_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/compiler.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_COMPILER_H_
-#define CS_V7_SRC_COMPILER_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/bcode.h" */
-/* Amalgamated: #include "v7/src/ast.h" */
-
-#if !defined(V7_NO_COMPILER)
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE enum v7_err compile_script(struct v7 *v7, struct ast *a,
-                                      struct bcode *bcode);
-
-V7_PRIVATE enum v7_err compile_expr(struct v7 *v7, struct ast *a,
-                                    ast_off_t *ppos, struct bcode *bcode);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_NO_COMPILER */
-
-#endif /* CS_V7_SRC_COMPILER_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/cyg_profile.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_CYG_PROFILE_H_
-#define CS_V7_SRC_CYG_PROFILE_H_
-
-/*
- * This file contains GCC/clang instrumentation callbacks, as well as
- * accompanying code. The actual code in these callbacks depends on enabled
- * features. See cyg_profile.c for some implementation details rationale.
- */
-
-struct v7;
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-
-/*
- * Stack-tracking functionality:
- *
- * The idea is that the caller should allocate `struct stack_track_ctx`
- * (typically on stack) in the function to track the stack usage of, and call
- * `v7_stack_track_start()` in the beginning.
- *
- * Before quitting current stack frame (for example, before returning from
- * function), call `v7_stack_track_end()`, which returns the maximum stack
- * consumed size.
- *
- * These calls can be nested: for example, we may track the stack usage of the
- * whole application by using these functions in `main()`, as well as track
- * stack usage of any nested functions.
- *
- * Just to stress: both `v7_stack_track_start()` / `v7_stack_track_end()`
- * should be called for the same instance of `struct stack_track_ctx` in the
- * same stack frame.
- */
-
-/* stack tracking context */
-struct stack_track_ctx {
-  struct stack_track_ctx *next;
-  void *start;
-  void *max;
-};
-
-/* see explanation above */
-void v7_stack_track_start(struct v7 *v7, struct stack_track_ctx *ctx);
-/* see explanation above */
-int v7_stack_track_end(struct v7 *v7, struct stack_track_ctx *ctx);
-
-void v7_stack_stat_clean(struct v7 *v7);
-
-#endif /* V7_ENABLE_STACK_TRACKING */
-
-#endif /* CS_V7_SRC_CYG_PROFILE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/builtin/builtin.h"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Non-Standard API
- *
- *   V7 has several non-standard extensions for `String.prototype` in
- *   order to give a compact and fast API to access raw data obtained from
- *   File, Socket, and hardware input/output such as I2C.
- *   V7 IO API functions return
- *   string data as a result of read operations, and that string data is a
- *   raw byte array. ECMA6 provides `ArrayBuffer` and `DataView` API for dealing
- *   with raw bytes, because strings in JavaScript are Unicode. That standard
- *   API is too bloated for the embedded use, and does not allow to use handy
- *   String API (e.g. `.match()`) against data.
- *
- *   V7 internally stores strings as byte arrays. All strings created by the
- *   String API are UTF8 encoded. Strings that are the result of
- *   input/output API calls might not be a valid UTF8 strings, but nevertheless
- *   they are represented as strings, and the following API allows to access
- *   underlying byte sequence:
- *
- * ==== String.prototype.at(position) -> number or NaN
- *      Return byte at index
- *     `position`. Byte value is in 0,255 range. If `position` is out of bounds
- *     (either negative or larger then the byte array length), NaN is returned.
- *     Example: `"Ñ‹".at(0)` returns 0xd1.
- *
- * ==== String.prototype.blen -> number
- *     Return string length in bytes.
- *     Example: `"Ñ‹".blen` returns 2. Note that `"Ñ‹".length` is 1, since that
- *     string consists of a single Unicode character (2-byte).
- *
- * === Builtin API
- *
- * Builtin API provides additional JavaScript interfaces available for V7
- * scripts.
- * File API is a wrapper around standard C calls `fopen()`, `fclose()`,
- * `fread()`, `fwrite()`, `rename()`, `remove()`.
- * Crypto API provides functions for base64, md5, and sha1 encoding/decoding.
- * Socket API provides low-level socket API.
- *
- * ==== File.eval(file_name)
- * Parse and run `file_name`.
- * Throws an exception if the file doesn't exist, cannot be parsed or if the
- * script throws any exception.
- *
- * ==== File.read(file_name) -> string or undefined
- * Read file `file_name` and return a string with a file content.
- * On any error, return `undefined` as a result.
- *
- * ==== File.write(file_name, str) -> true or false
- * Write string `str` to a file `file_name`. Return `true` on success,
- * `false` on error.
- *
- * ==== File.open(file_name [, mode]) -> file_object or null
- * Open a file `path`. For
- * list of valid `mode` values, see `fopen()` documentation. If `mode` is
- * not specified, mode `rb` is used, i.e. file is opened in read-only mode.
- * Return an opened file object, or null on error. Example:
- * `var f = File.open('/etc/passwd'); f.close();`
- *
- * ==== file_obj.close() -> undefined
- * Close opened file object.
- * NOTE: it is user's responsibility to close all opened file streams. V7
- * does not do that automatically.
- *
- * ==== file_obj.read() -> string
- * Read portion of data from
- * an opened file stream. Return string with data, or empty string on EOF
- * or error.
- *
- * ==== file_obj.write(str) -> num_bytes_written
- * Write string `str` to the opened file object. Return number of bytes written.
- *
- * ==== File.rename(old_name, new_name) -> errno
- * Rename file `old_name` to
- * `new_name`. Return 0 on success, or `errno` value on error.
- *
- * ==== File.list(dir_name) -> array_of_names
- * Return a list of files in a given directory, or `undefined` on error.
- *
- * ==== File.remove(file_name) -> errno
- * Delete file `file_name`.
- * Return 0 on success, or `errno` value on error.
- *
- * ==== Crypto.base64_encode(str)
- * Base64-encode input string `str` and return encoded string.
- *
- * ==== Crypto.base64_decode(str)
- * Base64-decode input string `str` and return decoded string.
- *
- * ==== Crypto.md5(str), Crypto.md5_hex(str)
- * Generate MD5 hash from input string `str`. Return 16-byte hash (`md5()`),
- * or stringified hexadecimal representation of the hash (`md5_hex`).
- *
- * ==== Crypto.sha1(str), Crypto.sha1_hex(str)
- * Generate SHA1 hash from input string `str`. Return 20-byte hash (`sha1()`),
- * or stringified hexadecimal representation of the hash (`sha1_hex`).
- *
- * ==== Socket.connect(host, port [, is_udp]) -> socket_obj
- * Connect to a given host. `host` can be a string IP address, or a host name.
- * Optional `is_udp` parameter, if true, indicates that socket should be UDP.
- * Return socket object on success, null on error.
- *
- * ==== Socket.listen(port [, ip_address [,is_udp]]) -> socket_obj
- * Create a listening socket on a given port. Optional `ip_address` argument
- * specifies and IP address to bind to. Optional `is_udp` parameter, if true,
- * indicates that socket should be UDP. Return socket object on success,
- * null on error.
- *
- * ==== socket_obj.accept() -> socket_obj
- * Sleep until new incoming connection is arrived. Return accepted socket
- * object on success, or `null` on error.
- *
- * ==== socket_obj.close() -> numeric_errno
- * Close socket object. Return 0 on success, or system errno on error.
- *
- * ==== socket_obj.recv() -> string
- * Read data from socket. Return data string, or empty string if peer has
- * disconnected, or `null` on error.
- *
- * ==== socket_obj.recvAll() -> string
- * Same as `recv()`, but keeps reading data until socket is closed.
- *
- * ==== sock.send(string) -> num_bytes_sent
- * Send string to the socket. Return number of bytes sent, or 0 on error.
- * Simple HTTP client example:
- *
- *    var s = Socket.connect("google.com", 80);
- *    s.send("GET / HTTP/1.0\n\n");
- *    var reply = s.recv();
- */
-
-#ifndef CS_V7_BUILTIN_BUILTIN_H_
-#define CS_V7_BUILTIN_BUILTIN_H_
-
-struct v7;
-
-void init_file(struct v7 *);
-void init_socket(struct v7 *);
-void init_crypto(struct v7 *);
-
-#endif /* CS_V7_BUILTIN_BUILTIN_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/slre.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- *
- * This software is dual-licensed: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. For the terms of this
- * license, see <http://www.gnu.org/licenses/>.
- *
- * You are free to use this software under the terms of the GNU General
- * Public License, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * Alternatively, you can license this software under a commercial
- * license, as set out in <https://www.cesanta.com/license>.
- */
-
-#ifndef CS_V7_SRC_SLRE_H_
-#define CS_V7_SRC_SLRE_H_
-
-/* Return codes for slre_compile() */
-enum slre_error {
-  SLRE_OK,
-  SLRE_INVALID_DEC_DIGIT,
-  SLRE_INVALID_HEX_DIGIT,
-  SLRE_INVALID_ESC_CHAR,
-  SLRE_UNTERM_ESC_SEQ,
-  SLRE_SYNTAX_ERROR,
-  SLRE_UNMATCH_LBR,
-  SLRE_UNMATCH_RBR,
-  SLRE_NUM_OVERFLOW,
-  SLRE_INF_LOOP_M_EMP_STR,
-  SLRE_TOO_MANY_CHARSETS,
-  SLRE_INV_CHARSET_RANGE,
-  SLRE_CHARSET_TOO_LARGE,
-  SLRE_MALFORMED_CHARSET,
-  SLRE_INVALID_BACK_REFERENCE,
-  SLRE_TOO_MANY_CAPTURES,
-  SLRE_INVALID_QUANTIFIER,
-  SLRE_BAD_CHAR_AFTER_USD
-};
-
-#if V7_ENABLE__RegExp
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Regex flags */
-#define SLRE_FLAG_G 1  /* Global - match in the whole string */
-#define SLRE_FLAG_I 2  /* Ignore case */
-#define SLRE_FLAG_M 4  /* Multiline */
-#define SLRE_FLAG_RE 8 /* flag RegExp/String */
-
-/* Describes single capture */
-struct slre_cap {
-  const char *start; /* points to the beginning of the capture group */
-  const char *end;   /* points to the end of the capture group */
-};
-
-/* Describes all captures */
-#define SLRE_MAX_CAPS 32
-struct slre_loot {
-  int num_captures;
-  struct slre_cap caps[SLRE_MAX_CAPS];
-};
-
-/* Opaque structure that holds compiled regular expression */
-struct slre_prog;
-
-int slre_compile(const char *regexp, size_t regexp_len, const char *flags,
-                 size_t flags_len, struct slre_prog **, int is_regex);
-int slre_exec(struct slre_prog *prog, int flag_g, const char *start,
-              const char *end, struct slre_loot *loot);
-void slre_free(struct slre_prog *prog);
-
-int slre_match(const char *, size_t, const char *, size_t, const char *, size_t,
-               struct slre_loot *);
-int slre_replace(struct slre_loot *loot, const char *src, size_t src_len,
-                 const char *replace, size_t rep_len, struct slre_loot *dst);
-int slre_get_flags(struct slre_prog *);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* V7_ENABLE__RegExp */
-
-#endif /* CS_V7_SRC_SLRE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/stdlib.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STDLIB_H_
-#define CS_V7_SRC_STDLIB_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*V7_PRIVATE*/ void init_stdlib(struct v7 *v7);
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err std_eval(struct v7 *v7, v7_val_t arg, v7_val_t this_obj,
-                                int is_json, v7_val_t *res);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STDLIB_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/heapusage.h"
-#endif
-/*
- * Copyright (c) 2014-2016 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_HEAPUSAGE_H_
-#define CS_V7_SRC_HEAPUSAGE_H_
-
-#if defined(V7_HEAPUSAGE_ENABLE)
-
-extern volatile int heap_dont_count;
-
-/*
- * Returns total heap-allocated size in bytes (without any overhead of the
- * heap implementation)
- */
-size_t heapusage_alloc_size(void);
-
-/*
- * Returns number of active allocations
- */
-size_t heapusage_allocs_cnt(void);
-
-/*
- * Must be called before allocating some memory that should not be indicated as
- * memory consumed for some particular operation: for example, when we
- * preallocate some GC buffer.
- */
-#define heapusage_dont_count(a) \
-  do {                          \
-    heap_dont_count = a;        \
-  } while (0)
-
-#else /* V7_HEAPUSAGE_ENABLE */
-
-#define heapusage_alloc_size() (0)
-#define heapusage_allocs_cnt() (0)
-#define heapusage_dont_count(a)
-
-#endif /* V7_HEAPUSAGE_ENABLE */
-
-#endif /* CS_V7_SRC_HEAPUSAGE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_proxy.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_PROXY_H_
-#define CS_V7_SRC_STD_PROXY_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-#if V7_ENABLE__Proxy
-
-#define _V7_PROXY_TARGET_NAME "__tgt"
-#define _V7_PROXY_HANDLER_NAME "__hnd"
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-#if V7_ENABLE__Proxy
-
-V7_PRIVATE enum v7_err Proxy_ctor(struct v7 *v7, v7_val_t *res);
-
-V7_PRIVATE void init_proxy(struct v7 *v7);
-
-/*
- * Returns whether the given name is one of the special Proxy names
- * (_V7_PROXY_TARGET_NAME or _V7_PROXY_HANDLER_NAME)
- */
-V7_PRIVATE int is_special_proxy_name(const char *name, size_t name_len);
-
-#endif
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_ENABLE__Proxy */
-
-#endif /* CS_V7_SRC_STD_PROXY_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/freeze.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_FREEZE_H_
-#define CS_V7_SRC_FREEZE_H_
-
-#ifdef V7_FREEZE
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-struct v7_property;
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void freeze(struct v7 *v7, char *filename);
-V7_PRIVATE void freeze_obj(struct v7 *v7, FILE *f, v7_val_t v);
-V7_PRIVATE void freeze_prop(struct v7 *v7, FILE *f, struct v7_property *prop);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_FREEZE */
-
-#endif /* CS_V7_SRC_FREEZE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_array.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_ARRAY_H_
-#define CS_V7_SRC_STD_ARRAY_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void init_array(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STD_ARRAY_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_boolean.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_BOOLEAN_H_
-#define CS_V7_SRC_STD_BOOLEAN_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void init_boolean(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STD_BOOLEAN_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_date.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_DATE_H_
-#define CS_V7_SRC_STD_DATE_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-#if V7_ENABLE__Date
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void init_date(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_ENABLE__Date */
-#endif /* CS_V7_SRC_STD_DATE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_function.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_FUNCTION_H_
-#define CS_V7_SRC_STD_FUNCTION_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void init_function(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STD_FUNCTION_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_json.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_JSON_H_
-#define CS_V7_SRC_STD_JSON_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void init_json(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STD_JSON_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_math.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_MATH_H_
-#define CS_V7_SRC_STD_MATH_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-#if V7_ENABLE__Math
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void init_math(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_ENABLE__Math */
-#endif /* CS_V7_SRC_STD_MATH_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_number.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_NUMBER_H_
-#define CS_V7_SRC_STD_NUMBER_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void init_number(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STD_NUMBER_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_object.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_OBJECT_H_
-#define CS_V7_SRC_STD_OBJECT_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-struct v7;
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void init_object(struct v7 *v7);
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_valueOf(struct v7 *v7, v7_val_t *res);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STD_OBJECT_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_regex.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_REGEX_H_
-#define CS_V7_SRC_STD_REGEX_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-#if V7_ENABLE__RegExp
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE enum v7_err Regex_ctor(struct v7 *v7, v7_val_t *res);
-V7_PRIVATE enum v7_err rx_exec(struct v7 *v7, v7_val_t rx, v7_val_t vstr,
-                               int lind, v7_val_t *res);
-
-V7_PRIVATE void init_regex(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_ENABLE__RegExp */
-
-#endif /* CS_V7_SRC_STD_REGEX_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_string.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_STD_STRING_H_
-#define CS_V7_SRC_STD_STRING_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-/* Max captures for String.replace() */
-#define V7_RE_MAX_REPL_SUB 20
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void init_string(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STD_STRING_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/js_stdlib.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_JS_STDLIB_H_
-#define CS_V7_SRC_JS_STDLIB_H_
-
-/* Amalgamated: #include "v7/src/internal.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-V7_PRIVATE void init_js_stdlib(struct v7 *);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_JS_STDLIB_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/main_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === v7 main()
- */
-
-#ifndef CS_V7_SRC_MAIN_PUBLIC_H_
-#define CS_V7_SRC_MAIN_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * V7 executable main function.
- *
- * There are various callbacks available:
- *
- * `pre_freeze_init()` and `pre_init()` are optional intialization functions,
- * aimed to export any extra functionality into vanilla v7 engine. They are
- * called after v7 initialization, before executing given files or inline
- * expressions. `pre_freeze_init()` is called before "freezing" v7 state;
- * whereas `pre_init` called afterwards.
- *
- * `post_init()`, if provided, is called after executing files and expressions,
- * before destroying v7 instance and exiting.
- */
-int v7_main(int argc, char *argv[], void (*pre_freeze_init)(struct v7 *),
-            void (*pre_init)(struct v7 *), void (*post_init)(struct v7 *));
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_MAIN_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/main.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_MAIN_H_
-#define CS_V7_SRC_MAIN_H_
-
-/* Amalgamated: #include "v7/src/main_public.h" */
-
-#endif /* CS_V7_SRC_MAIN_H_ */
-#ifndef V7_EXPORT_INTERNAL_HEADERS
-#ifdef V7_MODULE_LINES
-#line 1 "common/mbuf.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef EXCLUDE_COMMON
-
-#include <assert.h>
-#include <string.h>
-/* Amalgamated: #include "common/mbuf.h" */
-
-#ifndef MBUF_REALLOC
-#define MBUF_REALLOC realloc
-#endif
-
-#ifndef MBUF_FREE
-#define MBUF_FREE free
-#endif
-
-void mbuf_init(struct mbuf *mbuf, size_t initial_size) {
-  mbuf->len = mbuf->size = 0;
-  mbuf->buf = NULL;
-  mbuf_resize(mbuf, initial_size);
-}
-
-void mbuf_free(struct mbuf *mbuf) {
-  if (mbuf->buf != NULL) {
-    MBUF_FREE(mbuf->buf);
-    mbuf_init(mbuf, 0);
-  }
-}
-
-void mbuf_resize(struct mbuf *a, size_t new_size) {
-  if (new_size > a->size || (new_size < a->size && new_size >= a->len)) {
-    char *buf = (char *) MBUF_REALLOC(a->buf, new_size);
-    /*
-     * In case realloc fails, there's not much we can do, except keep things as
-     * they are. Note that NULL is a valid return value from realloc when
-     * size == 0, but that is covered too.
-     */
-    if (buf == NULL && new_size != 0) return;
-    a->buf = buf;
-    a->size = new_size;
-  }
-}
-
-void mbuf_trim(struct mbuf *mbuf) {
-  mbuf_resize(mbuf, mbuf->len);
-}
-
-size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t len) {
-  char *p = NULL;
-
-  assert(a != NULL);
-  assert(a->len <= a->size);
-  assert(off <= a->len);
-
-  /* check overflow */
-  if (~(size_t) 0 - (size_t) a->buf < len) return 0;
-
-  if (a->len + len <= a->size) {
-    memmove(a->buf + off + len, a->buf + off, a->len - off);
-    if (buf != NULL) {
-      memcpy(a->buf + off, buf, len);
-    }
-    a->len += len;
-  } else {
-    size_t new_size = (size_t)((a->len + len) * MBUF_SIZE_MULTIPLIER);
-    if ((p = (char *) MBUF_REALLOC(a->buf, new_size)) != NULL) {
-      a->buf = p;
-      memmove(a->buf + off + len, a->buf + off, a->len - off);
-      if (buf != NULL) memcpy(a->buf + off, buf, len);
-      a->len += len;
-      a->size = new_size;
-    } else {
-      len = 0;
-    }
-  }
-
-  return len;
-}
-
-size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) {
-  return mbuf_insert(a, a->len, buf, len);
-}
-
-void mbuf_remove(struct mbuf *mb, size_t n) {
-  if (n > 0 && n <= mb->len) {
-    memmove(mb->buf, mb->buf + n, mb->len - n);
-    mb->len -= n;
-  }
-}
-
-#endif /* EXCLUDE_COMMON */
-#ifdef V7_MODULE_LINES
-#line 1 "common/str_util.c"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef EXCLUDE_COMMON
-
-/* Amalgamated: #include "common/platform.h" */
-/* Amalgamated: #include "common/str_util.h" */
-
-size_t c_strnlen(const char *s, size_t maxlen) {
-  size_t l = 0;
-  for (; l < maxlen && s[l] != '\0'; l++) {
-  }
-  return l;
-}
-
-#define C_SNPRINTF_APPEND_CHAR(ch)       \
-  do {                                   \
-    if (i < (int) buf_size) buf[i] = ch; \
-    i++;                                 \
-  } while (0)
-
-#define C_SNPRINTF_FLAG_ZERO 1
-
-#ifdef C_DISABLE_BUILTIN_SNPRINTF
-int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) {
-  return vsnprintf(buf, buf_size, fmt, ap);
-}
-#else
-static int c_itoa(char *buf, size_t buf_size, int64_t num, int base, int flags,
-                  int field_width) {
-  char tmp[40];
-  int i = 0, k = 0, neg = 0;
-
-  if (num < 0) {
-    neg++;
-    num = -num;
-  }
-
-  /* Print into temporary buffer - in reverse order */
-  do {
-    int rem = num % base;
-    if (rem < 10) {
-      tmp[k++] = '0' + rem;
-    } else {
-      tmp[k++] = 'a' + (rem - 10);
-    }
-    num /= base;
-  } while (num > 0);
-
-  /* Zero padding */
-  if (flags && C_SNPRINTF_FLAG_ZERO) {
-    while (k < field_width && k < (int) sizeof(tmp) - 1) {
-      tmp[k++] = '0';
-    }
-  }
-
-  /* And sign */
-  if (neg) {
-    tmp[k++] = '-';
-  }
-
-  /* Now output */
-  while (--k >= 0) {
-    C_SNPRINTF_APPEND_CHAR(tmp[k]);
-  }
-
-  return i;
-}
-
-int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) {
-  int ch, i = 0, len_mod, flags, precision, field_width;
-
-  while ((ch = *fmt++) != '\0') {
-    if (ch != '%') {
-      C_SNPRINTF_APPEND_CHAR(ch);
-    } else {
-      /*
-       * Conversion specification:
-       *   zero or more flags (one of: # 0 - <space> + ')
-       *   an optional minimum  field  width (digits)
-       *   an  optional precision (. followed by digits, or *)
-       *   an optional length modifier (one of: hh h l ll L q j z t)
-       *   conversion specifier (one of: d i o u x X e E f F g G a A c s p n)
-       */
-      flags = field_width = precision = len_mod = 0;
-
-      /* Flags. only zero-pad flag is supported. */
-      if (*fmt == '0') {
-        flags |= C_SNPRINTF_FLAG_ZERO;
-      }
-
-      /* Field width */
-      while (*fmt >= '0' && *fmt <= '9') {
-        field_width *= 10;
-        field_width += *fmt++ - '0';
-      }
-      /* Dynamic field width */
-      if (*fmt == '*') {
-        field_width = va_arg(ap, int);
-        fmt++;
-      }
-
-      /* Precision */
-      if (*fmt == '.') {
-        fmt++;
-        if (*fmt == '*') {
-          precision = va_arg(ap, int);
-          fmt++;
-        } else {
-          while (*fmt >= '0' && *fmt <= '9') {
-            precision *= 10;
-            precision += *fmt++ - '0';
-          }
-        }
-      }
-
-      /* Length modifier */
-      switch (*fmt) {
-        case 'h':
-        case 'l':
-        case 'L':
-        case 'I':
-        case 'q':
-        case 'j':
-        case 'z':
-        case 't':
-          len_mod = *fmt++;
-          if (*fmt == 'h') {
-            len_mod = 'H';
-            fmt++;
-          }
-          if (*fmt == 'l') {
-            len_mod = 'q';
-            fmt++;
-          }
-          break;
-      }
-
-      ch = *fmt++;
-      if (ch == 's') {
-        const char *s = va_arg(ap, const char *); /* Always fetch parameter */
-        int j;
-        int pad = field_width - (precision >= 0 ? c_strnlen(s, precision) : 0);
-        for (j = 0; j < pad; j++) {
-          C_SNPRINTF_APPEND_CHAR(' ');
-        }
-
-        /* `s` may be NULL in case of %.*s */
-        if (s != NULL) {
-          /* Ignore negative and 0 precisions */
-          for (j = 0; (precision <= 0 || j < precision) && s[j] != '\0'; j++) {
-            C_SNPRINTF_APPEND_CHAR(s[j]);
-          }
-        }
-      } else if (ch == 'c') {
-        ch = va_arg(ap, int); /* Always fetch parameter */
-        C_SNPRINTF_APPEND_CHAR(ch);
-      } else if (ch == 'd' && len_mod == 0) {
-        i += c_itoa(buf + i, buf_size - i, va_arg(ap, int), 10, flags,
-                    field_width);
-      } else if (ch == 'd' && len_mod == 'l') {
-        i += c_itoa(buf + i, buf_size - i, va_arg(ap, long), 10, flags,
-                    field_width);
-#ifdef SSIZE_MAX
-      } else if (ch == 'd' && len_mod == 'z') {
-        i += c_itoa(buf + i, buf_size - i, va_arg(ap, ssize_t), 10, flags,
-                    field_width);
-#endif
-      } else if (ch == 'd' && len_mod == 'q') {
-        i += c_itoa(buf + i, buf_size - i, va_arg(ap, int64_t), 10, flags,
-                    field_width);
-      } else if ((ch == 'x' || ch == 'u') && len_mod == 0) {
-        i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned),
-                    ch == 'x' ? 16 : 10, flags, field_width);
-      } else if ((ch == 'x' || ch == 'u') && len_mod == 'l') {
-        i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned long),
-                    ch == 'x' ? 16 : 10, flags, field_width);
-      } else if ((ch == 'x' || ch == 'u') && len_mod == 'z') {
-        i += c_itoa(buf + i, buf_size - i, va_arg(ap, size_t),
-                    ch == 'x' ? 16 : 10, flags, field_width);
-      } else if (ch == 'p') {
-        unsigned long num = (unsigned long) (uintptr_t) va_arg(ap, void *);
-        C_SNPRINTF_APPEND_CHAR('0');
-        C_SNPRINTF_APPEND_CHAR('x');
-        i += c_itoa(buf + i, buf_size - i, num, 16, flags, 0);
-      } else {
-#ifndef NO_LIBC
-        /*
-         * TODO(lsm): abort is not nice in a library, remove it
-         * Also, ESP8266 SDK doesn't have it
-         */
-        abort();
-#endif
-      }
-    }
-  }
-
-  /* Zero-terminate the result */
-  if (buf_size > 0) {
-    buf[i < (int) buf_size ? i : (int) buf_size - 1] = '\0';
-  }
-
-  return i;
-}
-#endif
-
-int c_snprintf(char *buf, size_t buf_size, const char *fmt, ...) {
-  int result;
-  va_list ap;
-  va_start(ap, fmt);
-  result = c_vsnprintf(buf, buf_size, fmt, ap);
-  va_end(ap);
-  return result;
-}
-
-#ifdef _WIN32
-int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) {
-  int ret;
-  char buf[MAX_PATH * 2], buf2[MAX_PATH * 2], *p;
-
-  strncpy(buf, path, sizeof(buf));
-  buf[sizeof(buf) - 1] = '\0';
-
-  /* Trim trailing slashes. Leave backslash for paths like "X:\" */
-  p = buf + strlen(buf) - 1;
-  while (p > buf && p[-1] != ':' && (p[0] == '\\' || p[0] == '/')) *p-- = '\0';
-
-  memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
-  ret = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
-
-  /*
-   * Convert back to Unicode. If doubly-converted string does not match the
-   * original, something is fishy, reject.
-   */
-  WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
-                      NULL, NULL);
-  if (strcmp(buf, buf2) != 0) {
-    wbuf[0] = L'\0';
-    ret = 0;
-  }
-
-  return ret;
-}
-#endif /* _WIN32 */
-
-/* The simplest O(mn) algorithm. Better implementation are GPLed */
-const char *c_strnstr(const char *s, const char *find, size_t slen) {
-  size_t find_length = strlen(find);
-  size_t i;
-
-  for (i = 0; i < slen; i++) {
-    if (i + find_length > slen) {
-      return NULL;
-    }
-
-    if (strncmp(&s[i], find, find_length) == 0) {
-      return &s[i];
-    }
-  }
-
-  return NULL;
-}
-
-#endif /* EXCLUDE_COMMON */
-#ifdef V7_MODULE_LINES
-#line 1 "common/utf.c"
-#endif
-/*
- * The authors of this software are Rob Pike and Ken Thompson.
- *              Copyright (c) 2002 by Lucent Technologies.
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
- * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- */
-
-#ifndef EXCLUDE_COMMON
-
-/* clang-format off */
-
-#include <stdarg.h>
-#include <string.h>
-/* Amalgamated: #include "common/platform.h" */
-/* Amalgamated: #include "common/utf.h" */
-
-#if CS_ENABLE_UTF8
-enum {
-  Bit1 = 7,
-  Bitx = 6,
-  Bit2 = 5,
-  Bit3 = 4,
-  Bit4 = 3,
-  Bit5 = 2,
-
-  T1 = ((1 << (Bit1 + 1)) - 1) ^ 0xFF, /* 0000 0000 */
-  Tx = ((1 << (Bitx + 1)) - 1) ^ 0xFF, /* 1000 0000 */
-  T2 = ((1 << (Bit2 + 1)) - 1) ^ 0xFF, /* 1100 0000 */
-  T3 = ((1 << (Bit3 + 1)) - 1) ^ 0xFF, /* 1110 0000 */
-  T4 = ((1 << (Bit4 + 1)) - 1) ^ 0xFF, /* 1111 0000 */
-  T5 = ((1 << (Bit5 + 1)) - 1) ^ 0xFF, /* 1111 1000 */
-
-  Rune1 = (1 << (Bit1 + 0 * Bitx)) - 1, /* 0000 0000 0000 0000 0111 1111 */
-  Rune2 = (1 << (Bit2 + 1 * Bitx)) - 1, /* 0000 0000 0000 0111 1111 1111 */
-  Rune3 = (1 << (Bit3 + 2 * Bitx)) - 1, /* 0000 0000 1111 1111 1111 1111 */
-  Rune4 = (1 << (Bit4 + 3 * Bitx)) - 1, /* 0011 1111 1111 1111 1111 1111 */
-
-  Maskx = (1 << Bitx) - 1, /* 0011 1111 */
-  Testx = Maskx ^ 0xFF,    /* 1100 0000 */
-
-  Bad = Runeerror
-};
-
-int chartorune(Rune *rune, const char *str) {
-  int c, c1, c2 /* , c3 */;
-  unsigned short l;
-
-  /*
-   * one character sequence
-   *    00000-0007F => T1
-   */
-  c = *(uchar *) str;
-  if (c < Tx) {
-    *rune = c;
-    return 1;
-  }
-
-  /*
-   * two character sequence
-   *    0080-07FF => T2 Tx
-   */
-  c1 = *(uchar *) (str + 1) ^ Tx;
-  if (c1 & Testx) goto bad;
-  if (c < T3) {
-    if (c < T2) goto bad;
-    l = ((c << Bitx) | c1) & Rune2;
-    if (l <= Rune1) goto bad;
-    *rune = l;
-    return 2;
-  }
-
-  /*
-   * three character sequence
-   *    0800-FFFF => T3 Tx Tx
-   */
-  c2 = *(uchar *) (str + 2) ^ Tx;
-  if (c2 & Testx) goto bad;
-  if (c < T4) {
-    l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
-    if (l <= Rune2) goto bad;
-    *rune = l;
-    return 3;
-  }
-
-/*
- * four character sequence
- *  10000-10FFFF => T4 Tx Tx Tx
- */
-/* if(UTFmax >= 4) {
-        c3 = *(uchar*)(str+3) ^ Tx;
-        if(c3 & Testx)
-                goto bad;
-        if(c < T5) {
-                l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) &
-Rune4;
-                if(l <= Rune3)
-                        goto bad;
-                if(l > Runemax)
-                        goto bad;
-                *rune = l;
-                return 4;
-        }
-} */
-
-/*
- * bad decoding
- */
-bad:
-  *rune = Bad;
-  return 1;
-}
-
-int runetochar(char *str, Rune *rune) {
-  unsigned short c;
-
-  /*
-   * one character sequence
-   *    00000-0007F => 00-7F
-   */
-  c = *rune;
-  if (c <= Rune1) {
-    str[0] = c;
-    return 1;
-  }
-
-  /*
-   * two character sequence
-   *    00080-007FF => T2 Tx
-   */
-  if (c <= Rune2) {
-    str[0] = T2 | (c >> 1 * Bitx);
-    str[1] = Tx | (c & Maskx);
-    return 2;
-  }
-
-  /*
-   * three character sequence
-   *    00800-0FFFF => T3 Tx Tx
-   */
-  /* if(c > Runemax)
-          c = Runeerror; */
-  /* if(c <= Rune3) { */
-  str[0] = T3 | (c >> 2 * Bitx);
-  str[1] = Tx | ((c >> 1 * Bitx) & Maskx);
-  str[2] = Tx | (c & Maskx);
-  return 3;
-  /* } */
-
-  /*
-   * four character sequence
-   *    010000-1FFFFF => T4 Tx Tx Tx
-   */
-  /* str[0] = T4 |  (c >> 3*Bitx);
-  str[1] = Tx | ((c >> 2*Bitx) & Maskx);
-  str[2] = Tx | ((c >> 1*Bitx) & Maskx);
-  str[3] = Tx |  (c & Maskx);
-  return 4; */
-}
-
-int fullrune(const char *str, int n) {
-  int c;
-
-  if (n <= 0) return 0;
-  c = *(uchar *) str;
-  if (c < Tx) return 1;
-  if (c < T3) return n >= 2;
-  if (UTFmax == 3 || c < T4) return n >= 3;
-  return n >= 4;
-}
-
-int utfnlen(const char *s, long m) {
-  int c;
-  long n;
-  Rune rune;
-  const char *es;
-
-  es = s + m;
-  for (n = 0; s < es; n++) {
-    c = *(uchar *) s;
-    if (c < Runeself) {
-      s++;
-      continue;
-    }
-    if (!fullrune(s, es - s)) break;
-    s += chartorune(&rune, s);
-  }
-  return n;
-}
-
-const char *utfnshift(const char *s, long m) {
-  int c;
-  long n;
-  Rune rune;
-
-  for (n = 0; n < m; n++) {
-    c = *(uchar *) s;
-    if (c < Runeself) {
-      s++;
-      continue;
-    }
-    s += chartorune(&rune, s);
-  }
-  return s;
-}
-
-/*
- * The authors of this software are Rob Pike and Ken Thompson.
- *              Copyright (c) 2002 by Lucent Technologies.
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
- * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- */
-#include <stdarg.h>
-#include <string.h>
-/* Amalgamated: #include "common/utf.h" */
-
-/*
- * alpha ranges -
- *  only covers ranges not in lower||upper
- */
-static Rune __alpha2[] = {
-    0x00d8, 0x00f6, /* Ø - ö */
-    0x00f8, 0x01f5, /* ø - ǵ */
-    0x0250, 0x02a8, /* ɐ - ʨ */
-    0x038e, 0x03a1, /* Ύ - Ρ */
-    0x03a3, 0x03ce, /* Σ - ώ */
-    0x03d0, 0x03d6, /* ϐ - ϖ */
-    0x03e2, 0x03f3, /* Ϣ - ϳ */
-    0x0490, 0x04c4, /* Ґ - ӄ */
-    0x0561, 0x0587, /* Õ¡ - Ö‡ */
-    0x05d0, 0x05ea, /* א - ת */
-    0x05f0, 0x05f2, /* װ - ײ */
-    0x0621, 0x063a, /* ء - غ */
-    0x0640, 0x064a, /* Ù€ - ÙŠ */
-    0x0671, 0x06b7, /* Ù± - Ú· */
-    0x06ba, 0x06be, /* Úº - Ú¾ */
-    0x06c0, 0x06ce, /* Û€ - ÛŽ */
-    0x06d0, 0x06d3, /* ې - ۓ */
-    0x0905, 0x0939, /* अ - ह */
-    0x0958, 0x0961, /* क़ - ॡ */
-    0x0985, 0x098c, /* অ - ঌ */
-    0x098f, 0x0990, /* এ - ঐ */
-    0x0993, 0x09a8, /* ও - ন */
-    0x09aa, 0x09b0, /* প - র */
-    0x09b6, 0x09b9, /* শ - হ */
-    0x09dc, 0x09dd, /* ড় - ঢ় */
-    0x09df, 0x09e1, /* à§Ÿ - à§¡ */
-    0x09f0, 0x09f1, /* à§° - à§± */
-    0x0a05, 0x0a0a, /* ਅ - ਊ */
-    0x0a0f, 0x0a10, /* ਏ - ਐ */
-    0x0a13, 0x0a28, /* ਓ - ਨ */
-    0x0a2a, 0x0a30, /* ਪ - ਰ */
-    0x0a32, 0x0a33, /* ਲ - ਲ਼ */
-    0x0a35, 0x0a36, /* ਵ - ਸ਼ */
-    0x0a38, 0x0a39, /* ਸ - ਹ */
-    0x0a59, 0x0a5c, /* ਖ਼ - ੜ */
-    0x0a85, 0x0a8b, /* અ - ઋ */
-    0x0a8f, 0x0a91, /* એ - ઑ */
-    0x0a93, 0x0aa8, /* ઓ - ન */
-    0x0aaa, 0x0ab0, /* પ - ર */
-    0x0ab2, 0x0ab3, /* લ - ળ */
-    0x0ab5, 0x0ab9, /* વ - હ */
-    0x0b05, 0x0b0c, /* ଅ - ଌ */
-    0x0b0f, 0x0b10, /* ଏ - ଐ */
-    0x0b13, 0x0b28, /* ଓ - ନ */
-    0x0b2a, 0x0b30, /* ପ - ର */
-    0x0b32, 0x0b33, /* ଲ - ଳ */
-    0x0b36, 0x0b39, /* ଶ - ହ */
-    0x0b5c, 0x0b5d, /* ଡ଼ - ଢ଼ */
-    0x0b5f, 0x0b61, /* à­Ÿ - à­¡ */
-    0x0b85, 0x0b8a, /* அ - ஊ */
-    0x0b8e, 0x0b90, /* எ - ஐ */
-    0x0b92, 0x0b95, /* ஒ - க */
-    0x0b99, 0x0b9a, /* ங - ச */
-    0x0b9e, 0x0b9f, /* ஞ - ட */
-    0x0ba3, 0x0ba4, /* ண - த */
-    0x0ba8, 0x0baa, /* ந - ப */
-    0x0bae, 0x0bb5, /* ம - வ */
-    0x0bb7, 0x0bb9, /* ஷ - ஹ */
-    0x0c05, 0x0c0c, /* అ - ఌ */
-    0x0c0e, 0x0c10, /* ఎ - ఐ */
-    0x0c12, 0x0c28, /* à°’ - à°¨ */
-    0x0c2a, 0x0c33, /* à°ª - à°³ */
-    0x0c35, 0x0c39, /* à°µ - à°¹ */
-    0x0c60, 0x0c61, /* ౠ - ౡ */
-    0x0c85, 0x0c8c, /* ಅ - ಌ */
-    0x0c8e, 0x0c90, /* ಎ - ಐ */
-    0x0c92, 0x0ca8, /* ಒ - ನ */
-    0x0caa, 0x0cb3, /* ಪ - ಳ */
-    0x0cb5, 0x0cb9, /* ವ - ಹ */
-    0x0ce0, 0x0ce1, /* ೠ - ೡ */
-    0x0d05, 0x0d0c, /* അ - ഌ */
-    0x0d0e, 0x0d10, /* എ - ഐ */
-    0x0d12, 0x0d28, /* à´’ - à´¨ */
-    0x0d2a, 0x0d39, /* à´ª - à´¹ */
-    0x0d60, 0x0d61, /* ൠ - ൡ */
-    0x0e01, 0x0e30, /* ก - ะ */
-    0x0e32, 0x0e33, /* า - ำ */
-    0x0e40, 0x0e46, /* เ - ๆ */
-    0x0e5a, 0x0e5b, /* ๚ - ๛ */
-    0x0e81, 0x0e82, /* ກ - ຂ */
-    0x0e87, 0x0e88, /* ງ - ຈ */
-    0x0e94, 0x0e97, /* ດ - ທ */
-    0x0e99, 0x0e9f, /* ນ - ຟ */
-    0x0ea1, 0x0ea3, /* ມ - ຣ */
-    0x0eaa, 0x0eab, /* ສ - ຫ */
-    0x0ead, 0x0eae, /* ອ - ຮ */
-    0x0eb2, 0x0eb3, /* າ - ຳ */
-    0x0ec0, 0x0ec4, /* ເ - ໄ */
-    0x0edc, 0x0edd, /* ໜ - ໝ */
-    0x0f18, 0x0f19, /* ༘ - ༙ */
-    0x0f40, 0x0f47, /* ཀ - ཇ */
-    0x0f49, 0x0f69, /* ཉ - ཀྵ */
-    0x10d0, 0x10f6, /* ა - ჶ */
-    0x1100, 0x1159, /* á„€ - á…™ */
-    0x115f, 0x11a2, /* ᅟ - ᆢ */
-    0x11a8, 0x11f9, /* ᆨ - ᇹ */
-    0x1e00, 0x1e9b, /* Ḁ - ẛ */
-    0x1f50, 0x1f57, /* ὐ - ὗ */
-    0x1f80, 0x1fb4, /* á¾€ - á¾´ */
-    0x1fb6, 0x1fbc, /* á¾¶ - á¾¼ */
-    0x1fc2, 0x1fc4, /* á¿‚ - á¿„ */
-    0x1fc6, 0x1fcc, /* ῆ - ῌ */
-    0x1fd0, 0x1fd3, /* ῐ - ΐ */
-    0x1fd6, 0x1fdb, /* á¿– - á¿› */
-    0x1fe0, 0x1fec, /* ῠ - Ῥ */
-    0x1ff2, 0x1ff4, /* ῲ - ῴ */
-    0x1ff6, 0x1ffc, /* ῶ - ῼ */
-    0x210a, 0x2113, /* ℊ - ℓ */
-    0x2115, 0x211d, /* ℕ - ℝ */
-    0x2120, 0x2122, /* â„  - â„¢ */
-    0x212a, 0x2131, /* K - ℱ */
-    0x2133, 0x2138, /* ℳ - ℸ */
-    0x3041, 0x3094, /* ぁ - ゔ */
-    0x30a1, 0x30fa, /* ァ - ヺ */
-    0x3105, 0x312c, /* ㄅ - ㄬ */
-    0x3131, 0x318e, /* ㄱ - ㆎ */
-    0x3192, 0x319f, /* ㆒ - ㆟ */
-    0x3260, 0x327b, /* ㉠ - ㉻ */
-    0x328a, 0x32b0, /* ㊊ - ㊰ */
-    0x32d0, 0x32fe, /* ㋐ - ㋾ */
-    0x3300, 0x3357, /* ㌀ - ㍗ */
-    0x3371, 0x3376, /* ㍱ - ㍶ */
-    0x337b, 0x3394, /* ㍻ - ㎔ */
-    0x3399, 0x339e, /* ㎙ - ㎞ */
-    0x33a9, 0x33ad, /* ㎩ - ㎭ */
-    0x33b0, 0x33c1, /* ㎰ - ㏁ */
-    0x33c3, 0x33c5, /* ㏃ - ㏅ */
-    0x33c7, 0x33d7, /* ㏇ - ㏗ */
-    0x33d9, 0x33dd, /* ㏙ - ㏝ */
-    0x4e00, 0x9fff, /* 一 - 鿿 */
-    0xac00, 0xd7a3, /* 가 - 힣 */
-    0xf900, 0xfb06, /* 豈 - st */
-    0xfb13, 0xfb17, /* ﬓ - ﬗ */
-    0xfb1f, 0xfb28, /* ײַ - ﬨ */
-    0xfb2a, 0xfb36, /* שׁ - זּ */
-    0xfb38, 0xfb3c, /* טּ - לּ */
-    0xfb40, 0xfb41, /* נּ - סּ */
-    0xfb43, 0xfb44, /* ï­ƒ - ï­„ */
-    0xfb46, 0xfbb1, /* ï­† - ï®± */
-    0xfbd3, 0xfd3d, /* ﯓ - ﴽ */
-    0xfd50, 0xfd8f, /* ﵐ - ﶏ */
-    0xfd92, 0xfdc7, /* ï¶’ - ï·‡ */
-    0xfdf0, 0xfdf9, /* ï·° - ï·¹ */
-    0xfe70, 0xfe72, /* ï¹° - ï¹² */
-    0xfe76, 0xfefc, /* ﹶ - ﻼ */
-    0xff66, 0xff6f, /* ヲ - ッ */
-    0xff71, 0xff9d, /* ア - ン */
-    0xffa0, 0xffbe, /* ï¾  - ï¾¾ */
-    0xffc2, 0xffc7, /* ᅡ - ᅦ */
-    0xffca, 0xffcf, /* ᅧ - ᅬ */
-    0xffd2, 0xffd7, /* ï¿’ - ï¿— */
-    0xffda, 0xffdc, /* ᅳ - ᅵ */
-};
-
-/*
- * alpha singlets -
- *  only covers ranges not in lower||upper
- */
-static Rune __alpha1[] = {
-    0x00aa, /* ª */
-    0x00b5, /* µ */
-    0x00ba, /* º */
-    0x03da, /* Ïš */
-    0x03dc, /* Ϝ */
-    0x03de, /* Ïž */
-    0x03e0, /* Ï  */
-    0x06d5, /* Û• */
-    0x09b2, /* ল */
-    0x0a5e, /* ਫ਼ */
-    0x0a8d, /* ઍ */
-    0x0ae0, /* à«  */
-    0x0b9c, /* ஜ */
-    0x0cde, /* ೞ */
-    0x0e4f, /* ๏ */
-    0x0e84, /* ຄ */
-    0x0e8a, /* ຊ */
-    0x0e8d, /* ຍ */
-    0x0ea5, /* ລ */
-    0x0ea7, /* ວ */
-    0x0eb0, /* ະ */
-    0x0ebd, /* ຽ */
-    0x1fbe, /* á¾¾ */
-    0x207f, /* ⁿ */
-    0x20a8, /* ₨ */
-    0x2102, /* â„‚ */
-    0x2107, /* ℇ */
-    0x2124, /* ℤ */
-    0x2126, /* Ω */
-    0x2128, /* ℨ */
-    0xfb3e, /* מּ */
-    0xfe74, /* ï¹´ */
-};
-
-/*
- * space ranges
- */
-static Rune __space2[] = {
-    0x0009, 0x000a, /* tab and newline */
-    0x0020, 0x0020, /* space */
-    0x00a0, 0x00a0, /*   */
-    0x2000, 0x200b, /*   - ​ */
-    0x2028, 0x2029, /* 
 - 
 */
-    0x3000, 0x3000, /*   */
-    0xfeff, 0xfeff, /*  */
-};
-
-/*
- * lower case ranges
- *  3rd col is conversion excess 500
- */
-static Rune __toupper2[] = {
-    0x0061, 0x007a, 468, /* a-z A-Z */
-    0x00e0, 0x00f6, 468, /* à-ö À-Ö */
-    0x00f8, 0x00fe, 468, /* ø-þ Ø-Þ */
-    0x0256, 0x0257, 295, /* ɖ-ɗ Ɖ-Ɗ */
-    0x0258, 0x0259, 298, /* ɘ-ə Ǝ-Ə */
-    0x028a, 0x028b, 283, /* ʊ-ʋ Ʊ-Ʋ */
-    0x03ad, 0x03af, 463, /* έ-ί Έ-Ί */
-    0x03b1, 0x03c1, 468, /* α-ρ Α-Ρ */
-    0x03c3, 0x03cb, 468, /* σ-ϋ Σ-Ϋ */
-    0x03cd, 0x03ce, 437, /* ύ-ώ Ύ-Ώ */
-    0x0430, 0x044f, 468, /* а-я А-Я */
-    0x0451, 0x045c, 420, /* ё-ќ Ё-Ќ */
-    0x045e, 0x045f, 420, /* ў-џ Ў-Џ */
-    0x0561, 0x0586, 452, /* Õ¡-Ö† Ô±-Õ– */
-    0x1f00, 0x1f07, 508, /* ἀ-ἇ Ἀ-Ἇ */
-    0x1f10, 0x1f15, 508, /* ἐ-ἕ Ἐ-Ἕ */
-    0x1f20, 0x1f27, 508, /* ἠ-ἧ Ἠ-Ἧ */
-    0x1f30, 0x1f37, 508, /* ἰ-ἷ Ἰ-Ἷ */
-    0x1f40, 0x1f45, 508, /* ὀ-ὅ Ὀ-Ὅ */
-    0x1f60, 0x1f67, 508, /* ὠ-ὧ Ὠ-Ὧ */
-    0x1f70, 0x1f71, 574, /* ὰ-ά Ὰ-Ά */
-    0x1f72, 0x1f75, 586, /* ὲ-ή Ὲ-Ή */
-    0x1f76, 0x1f77, 600, /* ὶ-ί Ὶ-Ί */
-    0x1f78, 0x1f79, 628, /* ὸ-ό Ὸ-Ό */
-    0x1f7a, 0x1f7b, 612, /* ὺ-ύ Ὺ-Ύ */
-    0x1f7c, 0x1f7d, 626, /* ὼ-ώ Ὼ-Ώ */
-    0x1f80, 0x1f87, 508, /* ᾀ-ᾇ ᾈ-ᾏ */
-    0x1f90, 0x1f97, 508, /* ᾐ-ᾗ ᾘ-ᾟ */
-    0x1fa0, 0x1fa7, 508, /* ᾠ-ᾧ ᾨ-ᾯ */
-    0x1fb0, 0x1fb1, 508, /* ᾰ-ᾱ Ᾰ-Ᾱ */
-    0x1fd0, 0x1fd1, 508, /* ῐ-ῑ Ῐ-Ῑ */
-    0x1fe0, 0x1fe1, 508, /* ῠ-ῡ Ῠ-Ῡ */
-    0x2170, 0x217f, 484, /* â…°-â…¿ â… -â…¯ */
-    0x24d0, 0x24e9, 474, /* ⓐ-ⓩ Ⓐ-Ⓩ */
-    0xff41, 0xff5a, 468, /* a-z A-Z */
-};
-
-/*
- * lower case singlets
- *  2nd col is conversion excess 500
- */
-static Rune __toupper1[] = {
-    0x00ff, 621, /* ÿ Ÿ */
-    0x0101, 499, /* ā Ā */
-    0x0103, 499, /* ă Ă */
-    0x0105, 499, /* Ä… Ä„ */
-    0x0107, 499, /* ć Ć */
-    0x0109, 499, /* ĉ Ĉ */
-    0x010b, 499, /* Ä‹ ÄŠ */
-    0x010d, 499, /* č Č */
-    0x010f, 499, /* ď Ď */
-    0x0111, 499, /* đ Đ */
-    0x0113, 499, /* Ä“ Ä’ */
-    0x0115, 499, /* Ä• Ä” */
-    0x0117, 499, /* Ä— Ä– */
-    0x0119, 499, /* ę Ę */
-    0x011b, 499, /* Ä› Äš */
-    0x011d, 499, /* ĝ Ĝ */
-    0x011f, 499, /* ÄŸ Äž */
-    0x0121, 499, /* Ä¡ Ä  */
-    0x0123, 499, /* ģ Ģ */
-    0x0125, 499, /* ĥ Ĥ */
-    0x0127, 499, /* ħ Ħ */
-    0x0129, 499, /* ĩ Ĩ */
-    0x012b, 499, /* ī Ī */
-    0x012d, 499, /* ĭ Ĭ */
-    0x012f, 499, /* į Į */
-    0x0131, 268, /* ı I */
-    0x0133, 499, /* ij IJ */
-    0x0135, 499, /* ĵ Ĵ */
-    0x0137, 499, /* ķ Ķ */
-    0x013a, 499, /* ĺ Ĺ */
-    0x013c, 499, /* ļ Ļ */
-    0x013e, 499, /* ľ Ľ */
-    0x0140, 499, /* ŀ Ŀ */
-    0x0142, 499, /* ł Ł */
-    0x0144, 499, /* ń Ń */
-    0x0146, 499, /* ņ Ņ */
-    0x0148, 499, /* ň Ň */
-    0x014b, 499, /* Å‹ ÅŠ */
-    0x014d, 499, /* ō Ō */
-    0x014f, 499, /* ŏ Ŏ */
-    0x0151, 499, /* ő Ő */
-    0x0153, 499, /* Å“ Å’ */
-    0x0155, 499, /* Å• Å” */
-    0x0157, 499, /* Å— Å– */
-    0x0159, 499, /* ř Ř */
-    0x015b, 499, /* Å› Åš */
-    0x015d, 499, /* ŝ Ŝ */
-    0x015f, 499, /* ÅŸ Åž */
-    0x0161, 499, /* Å¡ Å  */
-    0x0163, 499, /* ţ Ţ */
-    0x0165, 499, /* ť Ť */
-    0x0167, 499, /* ŧ Ŧ */
-    0x0169, 499, /* ũ Ũ */
-    0x016b, 499, /* ū Ū */
-    0x016d, 499, /* ŭ Ŭ */
-    0x016f, 499, /* ů Ů */
-    0x0171, 499, /* ű Ű */
-    0x0173, 499, /* ų Ų */
-    0x0175, 499, /* ŵ Ŵ */
-    0x0177, 499, /* ŷ Ŷ */
-    0x017a, 499, /* ź Ź */
-    0x017c, 499, /* ż Ż */
-    0x017e, 499, /* ž Ž */
-    0x017f, 200, /* Å¿ S */
-    0x0183, 499, /* ƃ Ƃ */
-    0x0185, 499, /* Æ… Æ„ */
-    0x0188, 499, /* ƈ Ƈ */
-    0x018c, 499, /* ƌ Ƌ */
-    0x0192, 499, /* Æ’ Æ‘ */
-    0x0199, 499, /* ƙ Ƙ */
-    0x01a1, 499, /* Æ¡ Æ  */
-    0x01a3, 499, /* ƣ Ƣ */
-    0x01a5, 499, /* ƥ Ƥ */
-    0x01a8, 499, /* ƨ Ƨ */
-    0x01ad, 499, /* ƭ Ƭ */
-    0x01b0, 499, /* ư Ư */
-    0x01b4, 499, /* ƴ Ƴ */
-    0x01b6, 499, /* ƶ Ƶ */
-    0x01b9, 499, /* ƹ Ƹ */
-    0x01bd, 499, /* ƽ Ƽ */
-    0x01c5, 499, /* Ç… Ç„ */
-    0x01c6, 498, /* dž DŽ */
-    0x01c8, 499, /* Lj LJ */
-    0x01c9, 498, /* lj LJ */
-    0x01cb, 499, /* Ç‹ ÇŠ */
-    0x01cc, 498, /* nj NJ */
-    0x01ce, 499, /* ǎ Ǎ */
-    0x01d0, 499, /* ǐ Ǐ */
-    0x01d2, 499, /* Ç’ Ç‘ */
-    0x01d4, 499, /* Ç” Ç“ */
-    0x01d6, 499, /* Ç– Ç• */
-    0x01d8, 499, /* ǘ Ǘ */
-    0x01da, 499, /* Çš Ç™ */
-    0x01dc, 499, /* ǜ Ǜ */
-    0x01df, 499, /* ÇŸ Çž */
-    0x01e1, 499, /* Ç¡ Ç  */
-    0x01e3, 499, /* ǣ Ǣ */
-    0x01e5, 499, /* ǥ Ǥ */
-    0x01e7, 499, /* ǧ Ǧ */
-    0x01e9, 499, /* ǩ Ǩ */
-    0x01eb, 499, /* ǫ Ǫ */
-    0x01ed, 499, /* ǭ Ǭ */
-    0x01ef, 499, /* ǯ Ǯ */
-    0x01f2, 499, /* Dz DZ */
-    0x01f3, 498, /* dz DZ */
-    0x01f5, 499, /* ǵ Ǵ */
-    0x01fb, 499, /* ǻ Ǻ */
-    0x01fd, 499, /* ǽ Ǽ */
-    0x01ff, 499, /* ǿ Ǿ */
-    0x0201, 499, /* ȁ Ȁ */
-    0x0203, 499, /* ȃ Ȃ */
-    0x0205, 499, /* È… È„ */
-    0x0207, 499, /* ȇ Ȇ */
-    0x0209, 499, /* ȉ Ȉ */
-    0x020b, 499, /* È‹ ÈŠ */
-    0x020d, 499, /* ȍ Ȍ */
-    0x020f, 499, /* ȏ Ȏ */
-    0x0211, 499, /* ȑ Ȑ */
-    0x0213, 499, /* È“ È’ */
-    0x0215, 499, /* È• È” */
-    0x0217, 499, /* È— È– */
-    0x0253, 290, /* ɓ Ɓ */
-    0x0254, 294, /* ɔ Ɔ */
-    0x025b, 297, /* ɛ Ɛ */
-    0x0260, 295, /* É  Æ“ */
-    0x0263, 293, /* ɣ Ɣ */
-    0x0268, 291, /* ɨ Ɨ */
-    0x0269, 289, /* É© Æ– */
-    0x026f, 289, /* ɯ Ɯ */
-    0x0272, 287, /* ɲ Ɲ */
-    0x0283, 282, /* ʃ Ʃ */
-    0x0288, 282, /* ʈ Ʈ */
-    0x0292, 281, /* Ê’ Æ· */
-    0x03ac, 462, /* ά Ά */
-    0x03cc, 436, /* ό Ό */
-    0x03d0, 438, /* ϐ Β */
-    0x03d1, 443, /* ϑ Θ */
-    0x03d5, 453, /* ϕ Φ */
-    0x03d6, 446, /* ϖ Π */
-    0x03e3, 499, /* ϣ Ϣ */
-    0x03e5, 499, /* ϥ Ϥ */
-    0x03e7, 499, /* ϧ Ϧ */
-    0x03e9, 499, /* ϩ Ϩ */
-    0x03eb, 499, /* ϫ Ϫ */
-    0x03ed, 499, /* ϭ Ϭ */
-    0x03ef, 499, /* ϯ Ϯ */
-    0x03f0, 414, /* ϰ Κ */
-    0x03f1, 420, /* ϱ Ρ */
-    0x0461, 499, /* Ñ¡ Ñ  */
-    0x0463, 499, /* ѣ Ѣ */
-    0x0465, 499, /* ѥ Ѥ */
-    0x0467, 499, /* ѧ Ѧ */
-    0x0469, 499, /* ѩ Ѩ */
-    0x046b, 499, /* ѫ Ѫ */
-    0x046d, 499, /* ѭ Ѭ */
-    0x046f, 499, /* ѯ Ѯ */
-    0x0471, 499, /* ѱ Ѱ */
-    0x0473, 499, /* ѳ Ѳ */
-    0x0475, 499, /* ѵ Ѵ */
-    0x0477, 499, /* ѷ Ѷ */
-    0x0479, 499, /* ѹ Ѹ */
-    0x047b, 499, /* ѻ Ѻ */
-    0x047d, 499, /* ѽ Ѽ */
-    0x047f, 499, /* ѿ Ѿ */
-    0x0481, 499, /* ҁ Ҁ */
-    0x0491, 499, /* ґ Ґ */
-    0x0493, 499, /* Ò“ Ò’ */
-    0x0495, 499, /* Ò• Ò” */
-    0x0497, 499, /* Ò— Ò– */
-    0x0499, 499, /* Ò™ Ò˜ */
-    0x049b, 499, /* Ò› Òš */
-    0x049d, 499, /* ҝ Ҝ */
-    0x049f, 499, /* ÒŸ Òž */
-    0x04a1, 499, /* Ò¡ Ò  */
-    0x04a3, 499, /* Ò£ Ò¢ */
-    0x04a5, 499, /* Ò¥ Ò¤ */
-    0x04a7, 499, /* Ò§ Ò¦ */
-    0x04a9, 499, /* Ò© Ò¨ */
-    0x04ab, 499, /* Ò« Òª */
-    0x04ad, 499, /* Ò­ Ò¬ */
-    0x04af, 499, /* Ò¯ Ò® */
-    0x04b1, 499, /* Ò± Ò° */
-    0x04b3, 499, /* Ò³ Ò² */
-    0x04b5, 499, /* Òµ Ò´ */
-    0x04b7, 499, /* Ò· Ò¶ */
-    0x04b9, 499, /* Ò¹ Ò¸ */
-    0x04bb, 499, /* Ò» Òº */
-    0x04bd, 499, /* Ò½ Ò¼ */
-    0x04bf, 499, /* Ò¿ Ò¾ */
-    0x04c2, 499, /* ӂ Ӂ */
-    0x04c4, 499, /* Ó„ Óƒ */
-    0x04c8, 499, /* Óˆ Ó‡ */
-    0x04cc, 499, /* ӌ Ӌ */
-    0x04d1, 499, /* ӑ Ӑ */
-    0x04d3, 499, /* Ó“ Ó’ */
-    0x04d5, 499, /* Ó• Ó” */
-    0x04d7, 499, /* Ó— Ó– */
-    0x04d9, 499, /* Ó™ Ó˜ */
-    0x04db, 499, /* Ó› Óš */
-    0x04dd, 499, /* ӝ Ӝ */
-    0x04df, 499, /* ÓŸ Óž */
-    0x04e1, 499, /* Ó¡ Ó  */
-    0x04e3, 499, /* Ó£ Ó¢ */
-    0x04e5, 499, /* Ó¥ Ó¤ */
-    0x04e7, 499, /* Ó§ Ó¦ */
-    0x04e9, 499, /* Ó© Ó¨ */
-    0x04eb, 499, /* Ó« Óª */
-    0x04ef, 499, /* Ó¯ Ó® */
-    0x04f1, 499, /* Ó± Ó° */
-    0x04f3, 499, /* Ó³ Ó² */
-    0x04f5, 499, /* Óµ Ó´ */
-    0x04f9, 499, /* Ó¹ Ó¸ */
-    0x1e01, 499, /* ḁ Ḁ */
-    0x1e03, 499, /* ḃ Ḃ */
-    0x1e05, 499, /* ḅ Ḅ */
-    0x1e07, 499, /* ḇ Ḇ */
-    0x1e09, 499, /* ḉ Ḉ */
-    0x1e0b, 499, /* ḋ Ḋ */
-    0x1e0d, 499, /* ḍ Ḍ */
-    0x1e0f, 499, /* ḏ Ḏ */
-    0x1e11, 499, /* ḑ Ḑ */
-    0x1e13, 499, /* ḓ Ḓ */
-    0x1e15, 499, /* ḕ Ḕ */
-    0x1e17, 499, /* ḗ Ḗ */
-    0x1e19, 499, /* ḙ Ḙ */
-    0x1e1b, 499, /* ḛ Ḛ */
-    0x1e1d, 499, /* ḝ Ḝ */
-    0x1e1f, 499, /* ḟ Ḟ */
-    0x1e21, 499, /* ḡ Ḡ */
-    0x1e23, 499, /* ḣ Ḣ */
-    0x1e25, 499, /* ḥ Ḥ */
-    0x1e27, 499, /* ḧ Ḧ */
-    0x1e29, 499, /* ḩ Ḩ */
-    0x1e2b, 499, /* ḫ Ḫ */
-    0x1e2d, 499, /* ḭ Ḭ */
-    0x1e2f, 499, /* ḯ Ḯ */
-    0x1e31, 499, /* ḱ Ḱ */
-    0x1e33, 499, /* ḳ Ḳ */
-    0x1e35, 499, /* ḵ Ḵ */
-    0x1e37, 499, /* ḷ Ḷ */
-    0x1e39, 499, /* ḹ Ḹ */
-    0x1e3b, 499, /* ḻ Ḻ */
-    0x1e3d, 499, /* ḽ Ḽ */
-    0x1e3f, 499, /* ḿ Ḿ */
-    0x1e41, 499, /* ṁ Ṁ */
-    0x1e43, 499, /* ṃ Ṃ */
-    0x1e45, 499, /* ṅ Ṅ */
-    0x1e47, 499, /* ṇ Ṇ */
-    0x1e49, 499, /* ṉ Ṉ */
-    0x1e4b, 499, /* ṋ Ṋ */
-    0x1e4d, 499, /* ṍ Ṍ */
-    0x1e4f, 499, /* ṏ Ṏ */
-    0x1e51, 499, /* ṑ Ṑ */
-    0x1e53, 499, /* ṓ Ṓ */
-    0x1e55, 499, /* ṕ Ṕ */
-    0x1e57, 499, /* á¹— á¹– */
-    0x1e59, 499, /* ṙ Ṙ */
-    0x1e5b, 499, /* ṛ Ṛ */
-    0x1e5d, 499, /* ṝ Ṝ */
-    0x1e5f, 499, /* ṟ Ṟ */
-    0x1e61, 499, /* ṡ Ṡ */
-    0x1e63, 499, /* á¹£ á¹¢ */
-    0x1e65, 499, /* ṥ Ṥ */
-    0x1e67, 499, /* ṧ Ṧ */
-    0x1e69, 499, /* ṩ Ṩ */
-    0x1e6b, 499, /* ṫ Ṫ */
-    0x1e6d, 499, /* ṭ Ṭ */
-    0x1e6f, 499, /* ṯ Ṯ */
-    0x1e71, 499, /* á¹± á¹° */
-    0x1e73, 499, /* á¹³ á¹² */
-    0x1e75, 499, /* á¹µ á¹´ */
-    0x1e77, 499, /* á¹· á¹¶ */
-    0x1e79, 499, /* ṹ Ṹ */
-    0x1e7b, 499, /* ṻ Ṻ */
-    0x1e7d, 499, /* á¹½ á¹¼ */
-    0x1e7f, 499, /* ṿ Ṿ */
-    0x1e81, 499, /* ẁ Ẁ */
-    0x1e83, 499, /* ẃ Ẃ */
-    0x1e85, 499, /* ẅ Ẅ */
-    0x1e87, 499, /* ẇ Ẇ */
-    0x1e89, 499, /* ẉ Ẉ */
-    0x1e8b, 499, /* ẋ Ẋ */
-    0x1e8d, 499, /* ẍ Ẍ */
-    0x1e8f, 499, /* ẏ Ẏ */
-    0x1e91, 499, /* ẑ Ẑ */
-    0x1e93, 499, /* ẓ Ẓ */
-    0x1e95, 499, /* ẕ Ẕ */
-    0x1ea1, 499, /* ạ Ạ */
-    0x1ea3, 499, /* ả Ả */
-    0x1ea5, 499, /* ấ Ấ */
-    0x1ea7, 499, /* ầ Ầ */
-    0x1ea9, 499, /* ẩ Ẩ */
-    0x1eab, 499, /* ẫ Ẫ */
-    0x1ead, 499, /* ậ Ậ */
-    0x1eaf, 499, /* ắ Ắ */
-    0x1eb1, 499, /* ằ Ằ */
-    0x1eb3, 499, /* ẳ Ẳ */
-    0x1eb5, 499, /* ẵ Ẵ */
-    0x1eb7, 499, /* ặ Ặ */
-    0x1eb9, 499, /* ẹ Ẹ */
-    0x1ebb, 499, /* ẻ Ẻ */
-    0x1ebd, 499, /* ẽ Ẽ */
-    0x1ebf, 499, /* ế Ế */
-    0x1ec1, 499, /* ề Ề */
-    0x1ec3, 499, /* ể Ể */
-    0x1ec5, 499, /* ễ Ễ */
-    0x1ec7, 499, /* ệ Ệ */
-    0x1ec9, 499, /* ỉ Ỉ */
-    0x1ecb, 499, /* ị Ị */
-    0x1ecd, 499, /* ọ Ọ */
-    0x1ecf, 499, /* ỏ Ỏ */
-    0x1ed1, 499, /* ố Ố */
-    0x1ed3, 499, /* ồ Ồ */
-    0x1ed5, 499, /* ổ Ổ */
-    0x1ed7, 499, /* á»— á»– */
-    0x1ed9, 499, /* ộ Ộ */
-    0x1edb, 499, /* ớ Ớ */
-    0x1edd, 499, /* ờ Ờ */
-    0x1edf, 499, /* ở Ở */
-    0x1ee1, 499, /* ỡ Ỡ */
-    0x1ee3, 499, /* ợ Ợ */
-    0x1ee5, 499, /* ụ Ụ */
-    0x1ee7, 499, /* ủ Ủ */
-    0x1ee9, 499, /* ứ Ứ */
-    0x1eeb, 499, /* ừ Ừ */
-    0x1eed, 499, /* ử Ử */
-    0x1eef, 499, /* ữ Ữ */
-    0x1ef1, 499, /* á»± á»° */
-    0x1ef3, 499, /* ỳ Ỳ */
-    0x1ef5, 499, /* ỵ Ỵ */
-    0x1ef7, 499, /* á»· á»¶ */
-    0x1ef9, 499, /* ỹ Ỹ */
-    0x1f51, 508, /* ὑ Ὑ */
-    0x1f53, 508, /* ὓ Ὓ */
-    0x1f55, 508, /* ὕ Ὕ */
-    0x1f57, 508, /* ὗ Ὗ */
-    0x1fb3, 509, /* á¾³ á¾¼ */
-    0x1fc3, 509, /* ῃ ῌ */
-    0x1fe5, 507, /* ῥ Ῥ */
-    0x1ff3, 509, /* ῳ ῼ */
-};
-
-/*
- * upper case ranges
- *  3rd col is conversion excess 500
- */
-static Rune __tolower2[] = {
-    0x0041, 0x005a, 532, /* A-Z a-z */
-    0x00c0, 0x00d6, 532, /* À-Ö à-ö */
-    0x00d8, 0x00de, 532, /* Ø-Þ ø-þ */
-    0x0189, 0x018a, 705, /* Ɖ-Ɗ ɖ-ɗ */
-    0x018e, 0x018f, 702, /* Ǝ-Ə ɘ-ə */
-    0x01b1, 0x01b2, 717, /* Ʊ-Ʋ ʊ-ʋ */
-    0x0388, 0x038a, 537, /* Έ-Ί έ-ί */
-    0x038e, 0x038f, 563, /* Ύ-Ώ ύ-ώ */
-    0x0391, 0x03a1, 532, /* Α-Ρ α-ρ */
-    0x03a3, 0x03ab, 532, /* Σ-Ϋ σ-ϋ */
-    0x0401, 0x040c, 580, /* Ё-Ќ ё-ќ */
-    0x040e, 0x040f, 580, /* Ў-Џ ў-џ */
-    0x0410, 0x042f, 532, /* А-Я а-я */
-    0x0531, 0x0556, 548, /* Ô±-Õ– Õ¡-Ö† */
-    0x10a0, 0x10c5, 548, /* Ⴀ-Ⴥ ა-ჵ */
-    0x1f08, 0x1f0f, 492, /* Ἀ-Ἇ ἀ-ἇ */
-    0x1f18, 0x1f1d, 492, /* Ἐ-Ἕ ἐ-ἕ */
-    0x1f28, 0x1f2f, 492, /* Ἠ-Ἧ ἠ-ἧ */
-    0x1f38, 0x1f3f, 492, /* Ἰ-Ἷ ἰ-ἷ */
-    0x1f48, 0x1f4d, 492, /* Ὀ-Ὅ ὀ-ὅ */
-    0x1f68, 0x1f6f, 492, /* Ὠ-Ὧ ὠ-ὧ */
-    0x1f88, 0x1f8f, 492, /* ᾈ-ᾏ ᾀ-ᾇ */
-    0x1f98, 0x1f9f, 492, /* ᾘ-ᾟ ᾐ-ᾗ */
-    0x1fa8, 0x1faf, 492, /* ᾨ-ᾯ ᾠ-ᾧ */
-    0x1fb8, 0x1fb9, 492, /* Ᾰ-Ᾱ ᾰ-ᾱ */
-    0x1fba, 0x1fbb, 426, /* Ὰ-Ά ὰ-ά */
-    0x1fc8, 0x1fcb, 414, /* Ὲ-Ή ὲ-ή */
-    0x1fd8, 0x1fd9, 492, /* Ῐ-Ῑ ῐ-ῑ */
-    0x1fda, 0x1fdb, 400, /* Ὶ-Ί ὶ-ί */
-    0x1fe8, 0x1fe9, 492, /* Ῠ-Ῡ ῠ-ῡ */
-    0x1fea, 0x1feb, 388, /* Ὺ-Ύ ὺ-ύ */
-    0x1ff8, 0x1ff9, 372, /* Ὸ-Ό ὸ-ό */
-    0x1ffa, 0x1ffb, 374, /* Ὼ-Ώ ὼ-ώ */
-    0x2160, 0x216f, 516, /* â… -â…¯ â…°-â…¿ */
-    0x24b6, 0x24cf, 526, /* Ⓐ-Ⓩ ⓐ-ⓩ */
-    0xff21, 0xff3a, 532, /* A-Z a-z */
-};
-
-/*
- * upper case singlets
- *  2nd col is conversion excess 500
- */
-static Rune __tolower1[] = {
-    0x0100, 501, /* Ā ā */
-    0x0102, 501, /* Ă ă */
-    0x0104, 501, /* Ä„ Ä… */
-    0x0106, 501, /* Ć ć */
-    0x0108, 501, /* Ĉ ĉ */
-    0x010a, 501, /* ÄŠ Ä‹ */
-    0x010c, 501, /* Č č */
-    0x010e, 501, /* Ď ď */
-    0x0110, 501, /* Đ đ */
-    0x0112, 501, /* Ä’ Ä“ */
-    0x0114, 501, /* Ä” Ä• */
-    0x0116, 501, /* Ä– Ä— */
-    0x0118, 501, /* Ę ę */
-    0x011a, 501, /* Äš Ä› */
-    0x011c, 501, /* Ĝ ĝ */
-    0x011e, 501, /* Äž ÄŸ */
-    0x0120, 501, /* Ä  Ä¡ */
-    0x0122, 501, /* Ģ ģ */
-    0x0124, 501, /* Ĥ ĥ */
-    0x0126, 501, /* Ħ ħ */
-    0x0128, 501, /* Ĩ ĩ */
-    0x012a, 501, /* Ī ī */
-    0x012c, 501, /* Ĭ ĭ */
-    0x012e, 501, /* Į į */
-    0x0130, 301, /* İ i */
-    0x0132, 501, /* IJ ij */
-    0x0134, 501, /* Ĵ ĵ */
-    0x0136, 501, /* Ķ ķ */
-    0x0139, 501, /* Ĺ ĺ */
-    0x013b, 501, /* Ļ ļ */
-    0x013d, 501, /* Ľ ľ */
-    0x013f, 501, /* Ŀ ŀ */
-    0x0141, 501, /* Ł ł */
-    0x0143, 501, /* Ń ń */
-    0x0145, 501, /* Ņ ņ */
-    0x0147, 501, /* Ň ň */
-    0x014a, 501, /* ÅŠ Å‹ */
-    0x014c, 501, /* Ō ō */
-    0x014e, 501, /* Ŏ ŏ */
-    0x0150, 501, /* Ő ő */
-    0x0152, 501, /* Å’ Å“ */
-    0x0154, 501, /* Å” Å• */
-    0x0156, 501, /* Å– Å— */
-    0x0158, 501, /* Ř ř */
-    0x015a, 501, /* Åš Å› */
-    0x015c, 501, /* Ŝ ŝ */
-    0x015e, 501, /* Åž ÅŸ */
-    0x0160, 501, /* Å  Å¡ */
-    0x0162, 501, /* Ţ ţ */
-    0x0164, 501, /* Ť ť */
-    0x0166, 501, /* Ŧ ŧ */
-    0x0168, 501, /* Ũ ũ */
-    0x016a, 501, /* Ū ū */
-    0x016c, 501, /* Ŭ ŭ */
-    0x016e, 501, /* Ů ů */
-    0x0170, 501, /* Ű ű */
-    0x0172, 501, /* Ų ų */
-    0x0174, 501, /* Ŵ ŵ */
-    0x0176, 501, /* Ŷ ŷ */
-    0x0178, 379, /* Ÿ ÿ */
-    0x0179, 501, /* Ź ź */
-    0x017b, 501, /* Ż ż */
-    0x017d, 501, /* Ž ž */
-    0x0181, 710, /* Ɓ ɓ */
-    0x0182, 501, /* Ƃ ƃ */
-    0x0184, 501, /* Æ„ Æ… */
-    0x0186, 706, /* Ɔ ɔ */
-    0x0187, 501, /* Ƈ ƈ */
-    0x018b, 501, /* Ƌ ƌ */
-    0x0190, 703, /* Ɛ ɛ */
-    0x0191, 501, /* Æ‘ Æ’ */
-    0x0193, 705, /* Æ“ É  */
-    0x0194, 707, /* Ɣ ɣ */
-    0x0196, 711, /* Æ– É© */
-    0x0197, 709, /* Ɨ ɨ */
-    0x0198, 501, /* Ƙ ƙ */
-    0x019c, 711, /* Ɯ ɯ */
-    0x019d, 713, /* Ɲ ɲ */
-    0x01a0, 501, /* Æ  Æ¡ */
-    0x01a2, 501, /* Ƣ ƣ */
-    0x01a4, 501, /* Ƥ ƥ */
-    0x01a7, 501, /* Ƨ ƨ */
-    0x01a9, 718, /* Ʃ ʃ */
-    0x01ac, 501, /* Ƭ ƭ */
-    0x01ae, 718, /* Ʈ ʈ */
-    0x01af, 501, /* Ư ư */
-    0x01b3, 501, /* Ƴ ƴ */
-    0x01b5, 501, /* Ƶ ƶ */
-    0x01b7, 719, /* Æ· Ê’ */
-    0x01b8, 501, /* Ƹ ƹ */
-    0x01bc, 501, /* Ƽ ƽ */
-    0x01c4, 502, /* DŽ dž */
-    0x01c5, 501, /* Dž dž */
-    0x01c7, 502, /* LJ lj */
-    0x01c8, 501, /* Lj lj */
-    0x01ca, 502, /* NJ nj */
-    0x01cb, 501, /* Nj nj */
-    0x01cd, 501, /* Ǎ ǎ */
-    0x01cf, 501, /* Ǐ ǐ */
-    0x01d1, 501, /* Ç‘ Ç’ */
-    0x01d3, 501, /* Ç“ Ç” */
-    0x01d5, 501, /* Ç• Ç– */
-    0x01d7, 501, /* Ǘ ǘ */
-    0x01d9, 501, /* Ç™ Çš */
-    0x01db, 501, /* Ǜ ǜ */
-    0x01de, 501, /* Çž ÇŸ */
-    0x01e0, 501, /* Ç  Ç¡ */
-    0x01e2, 501, /* Ǣ ǣ */
-    0x01e4, 501, /* Ǥ ǥ */
-    0x01e6, 501, /* Ǧ ǧ */
-    0x01e8, 501, /* Ǩ ǩ */
-    0x01ea, 501, /* Ǫ ǫ */
-    0x01ec, 501, /* Ǭ ǭ */
-    0x01ee, 501, /* Ǯ ǯ */
-    0x01f1, 502, /* DZ dz */
-    0x01f2, 501, /* Dz dz */
-    0x01f4, 501, /* Ǵ ǵ */
-    0x01fa, 501, /* Ǻ ǻ */
-    0x01fc, 501, /* Ǽ ǽ */
-    0x01fe, 501, /* Ǿ ǿ */
-    0x0200, 501, /* Ȁ ȁ */
-    0x0202, 501, /* Ȃ ȃ */
-    0x0204, 501, /* È„ È… */
-    0x0206, 501, /* Ȇ ȇ */
-    0x0208, 501, /* Ȉ ȉ */
-    0x020a, 501, /* ÈŠ È‹ */
-    0x020c, 501, /* Ȍ ȍ */
-    0x020e, 501, /* Ȏ ȏ */
-    0x0210, 501, /* Ȑ ȑ */
-    0x0212, 501, /* È’ È“ */
-    0x0214, 501, /* È” È• */
-    0x0216, 501, /* È– È— */
-    0x0386, 538, /* Ά ά */
-    0x038c, 564, /* Ό ό */
-    0x03e2, 501, /* Ϣ ϣ */
-    0x03e4, 501, /* Ϥ ϥ */
-    0x03e6, 501, /* Ϧ ϧ */
-    0x03e8, 501, /* Ϩ ϩ */
-    0x03ea, 501, /* Ϫ ϫ */
-    0x03ec, 501, /* Ϭ ϭ */
-    0x03ee, 501, /* Ϯ ϯ */
-    0x0460, 501, /* Ñ  Ñ¡ */
-    0x0462, 501, /* Ѣ ѣ */
-    0x0464, 501, /* Ѥ ѥ */
-    0x0466, 501, /* Ѧ ѧ */
-    0x0468, 501, /* Ѩ ѩ */
-    0x046a, 501, /* Ѫ ѫ */
-    0x046c, 501, /* Ѭ ѭ */
-    0x046e, 501, /* Ѯ ѯ */
-    0x0470, 501, /* Ѱ ѱ */
-    0x0472, 501, /* Ѳ ѳ */
-    0x0474, 501, /* Ѵ ѵ */
-    0x0476, 501, /* Ѷ ѷ */
-    0x0478, 501, /* Ѹ ѹ */
-    0x047a, 501, /* Ѻ ѻ */
-    0x047c, 501, /* Ѽ ѽ */
-    0x047e, 501, /* Ѿ ѿ */
-    0x0480, 501, /* Ҁ ҁ */
-    0x0490, 501, /* Ґ ґ */
-    0x0492, 501, /* Ò’ Ò“ */
-    0x0494, 501, /* Ò” Ò• */
-    0x0496, 501, /* Ò– Ò— */
-    0x0498, 501, /* Ò˜ Ò™ */
-    0x049a, 501, /* Òš Ò› */
-    0x049c, 501, /* Ҝ ҝ */
-    0x049e, 501, /* Òž ÒŸ */
-    0x04a0, 501, /* Ò  Ò¡ */
-    0x04a2, 501, /* Ò¢ Ò£ */
-    0x04a4, 501, /* Ò¤ Ò¥ */
-    0x04a6, 501, /* Ò¦ Ò§ */
-    0x04a8, 501, /* Ò¨ Ò© */
-    0x04aa, 501, /* Òª Ò« */
-    0x04ac, 501, /* Ò¬ Ò­ */
-    0x04ae, 501, /* Ò® Ò¯ */
-    0x04b0, 501, /* Ò° Ò± */
-    0x04b2, 501, /* Ò² Ò³ */
-    0x04b4, 501, /* Ò´ Òµ */
-    0x04b6, 501, /* Ò¶ Ò· */
-    0x04b8, 501, /* Ò¸ Ò¹ */
-    0x04ba, 501, /* Òº Ò» */
-    0x04bc, 501, /* Ò¼ Ò½ */
-    0x04be, 501, /* Ò¾ Ò¿ */
-    0x04c1, 501, /* Ӂ ӂ */
-    0x04c3, 501, /* Óƒ Ó„ */
-    0x04c7, 501, /* Ó‡ Óˆ */
-    0x04cb, 501, /* Ӌ ӌ */
-    0x04d0, 501, /* Ӑ ӑ */
-    0x04d2, 501, /* Ó’ Ó“ */
-    0x04d4, 501, /* Ó” Ó• */
-    0x04d6, 501, /* Ó– Ó— */
-    0x04d8, 501, /* Ó˜ Ó™ */
-    0x04da, 501, /* Óš Ó› */
-    0x04dc, 501, /* Ӝ ӝ */
-    0x04de, 501, /* Óž ÓŸ */
-    0x04e0, 501, /* Ó  Ó¡ */
-    0x04e2, 501, /* Ó¢ Ó£ */
-    0x04e4, 501, /* Ó¤ Ó¥ */
-    0x04e6, 501, /* Ó¦ Ó§ */
-    0x04e8, 501, /* Ó¨ Ó© */
-    0x04ea, 501, /* Óª Ó« */
-    0x04ee, 501, /* Ó® Ó¯ */
-    0x04f0, 501, /* Ó° Ó± */
-    0x04f2, 501, /* Ó² Ó³ */
-    0x04f4, 501, /* Ó´ Óµ */
-    0x04f8, 501, /* Ó¸ Ó¹ */
-    0x1e00, 501, /* Ḁ ḁ */
-    0x1e02, 501, /* Ḃ ḃ */
-    0x1e04, 501, /* Ḅ ḅ */
-    0x1e06, 501, /* Ḇ ḇ */
-    0x1e08, 501, /* Ḉ ḉ */
-    0x1e0a, 501, /* Ḋ ḋ */
-    0x1e0c, 501, /* Ḍ ḍ */
-    0x1e0e, 501, /* Ḏ ḏ */
-    0x1e10, 501, /* Ḑ ḑ */
-    0x1e12, 501, /* Ḓ ḓ */
-    0x1e14, 501, /* Ḕ ḕ */
-    0x1e16, 501, /* Ḗ ḗ */
-    0x1e18, 501, /* Ḙ ḙ */
-    0x1e1a, 501, /* Ḛ ḛ */
-    0x1e1c, 501, /* Ḝ ḝ */
-    0x1e1e, 501, /* Ḟ ḟ */
-    0x1e20, 501, /* Ḡ ḡ */
-    0x1e22, 501, /* Ḣ ḣ */
-    0x1e24, 501, /* Ḥ ḥ */
-    0x1e26, 501, /* Ḧ ḧ */
-    0x1e28, 501, /* Ḩ ḩ */
-    0x1e2a, 501, /* Ḫ ḫ */
-    0x1e2c, 501, /* Ḭ ḭ */
-    0x1e2e, 501, /* Ḯ ḯ */
-    0x1e30, 501, /* Ḱ ḱ */
-    0x1e32, 501, /* Ḳ ḳ */
-    0x1e34, 501, /* Ḵ ḵ */
-    0x1e36, 501, /* Ḷ ḷ */
-    0x1e38, 501, /* Ḹ ḹ */
-    0x1e3a, 501, /* Ḻ ḻ */
-    0x1e3c, 501, /* Ḽ ḽ */
-    0x1e3e, 501, /* Ḿ ḿ */
-    0x1e40, 501, /* Ṁ ṁ */
-    0x1e42, 501, /* Ṃ ṃ */
-    0x1e44, 501, /* Ṅ ṅ */
-    0x1e46, 501, /* Ṇ ṇ */
-    0x1e48, 501, /* Ṉ ṉ */
-    0x1e4a, 501, /* Ṋ ṋ */
-    0x1e4c, 501, /* Ṍ ṍ */
-    0x1e4e, 501, /* Ṏ ṏ */
-    0x1e50, 501, /* Ṑ ṑ */
-    0x1e52, 501, /* Ṓ ṓ */
-    0x1e54, 501, /* Ṕ ṕ */
-    0x1e56, 501, /* á¹– á¹— */
-    0x1e58, 501, /* Ṙ ṙ */
-    0x1e5a, 501, /* Ṛ ṛ */
-    0x1e5c, 501, /* Ṝ ṝ */
-    0x1e5e, 501, /* Ṟ ṟ */
-    0x1e60, 501, /* Ṡ ṡ */
-    0x1e62, 501, /* á¹¢ á¹£ */
-    0x1e64, 501, /* Ṥ ṥ */
-    0x1e66, 501, /* Ṧ ṧ */
-    0x1e68, 501, /* Ṩ ṩ */
-    0x1e6a, 501, /* Ṫ ṫ */
-    0x1e6c, 501, /* Ṭ ṭ */
-    0x1e6e, 501, /* Ṯ ṯ */
-    0x1e70, 501, /* á¹° á¹± */
-    0x1e72, 501, /* á¹² á¹³ */
-    0x1e74, 501, /* á¹´ á¹µ */
-    0x1e76, 501, /* á¹¶ á¹· */
-    0x1e78, 501, /* Ṹ ṹ */
-    0x1e7a, 501, /* Ṻ ṻ */
-    0x1e7c, 501, /* á¹¼ á¹½ */
-    0x1e7e, 501, /* Ṿ ṿ */
-    0x1e80, 501, /* Ẁ ẁ */
-    0x1e82, 501, /* Ẃ ẃ */
-    0x1e84, 501, /* Ẅ ẅ */
-    0x1e86, 501, /* Ẇ ẇ */
-    0x1e88, 501, /* Ẉ ẉ */
-    0x1e8a, 501, /* Ẋ ẋ */
-    0x1e8c, 501, /* Ẍ ẍ */
-    0x1e8e, 501, /* Ẏ ẏ */
-    0x1e90, 501, /* Ẑ ẑ */
-    0x1e92, 501, /* Ẓ ẓ */
-    0x1e94, 501, /* Ẕ ẕ */
-    0x1ea0, 501, /* Ạ ạ */
-    0x1ea2, 501, /* Ả ả */
-    0x1ea4, 501, /* Ấ ấ */
-    0x1ea6, 501, /* Ầ ầ */
-    0x1ea8, 501, /* Ẩ ẩ */
-    0x1eaa, 501, /* Ẫ ẫ */
-    0x1eac, 501, /* Ậ ậ */
-    0x1eae, 501, /* Ắ ắ */
-    0x1eb0, 501, /* Ằ ằ */
-    0x1eb2, 501, /* Ẳ ẳ */
-    0x1eb4, 501, /* Ẵ ẵ */
-    0x1eb6, 501, /* Ặ ặ */
-    0x1eb8, 501, /* Ẹ ẹ */
-    0x1eba, 501, /* Ẻ ẻ */
-    0x1ebc, 501, /* Ẽ ẽ */
-    0x1ebe, 501, /* Ế ế */
-    0x1ec0, 501, /* Ề ề */
-    0x1ec2, 501, /* Ể ể */
-    0x1ec4, 501, /* Ễ ễ */
-    0x1ec6, 501, /* Ệ ệ */
-    0x1ec8, 501, /* Ỉ ỉ */
-    0x1eca, 501, /* Ị ị */
-    0x1ecc, 501, /* Ọ ọ */
-    0x1ece, 501, /* Ỏ ỏ */
-    0x1ed0, 501, /* Ố ố */
-    0x1ed2, 501, /* Ồ ồ */
-    0x1ed4, 501, /* Ổ ổ */
-    0x1ed6, 501, /* á»– á»— */
-    0x1ed8, 501, /* Ộ ộ */
-    0x1eda, 501, /* Ớ ớ */
-    0x1edc, 501, /* Ờ ờ */
-    0x1ede, 501, /* Ở ở */
-    0x1ee0, 501, /* Ỡ ỡ */
-    0x1ee2, 501, /* Ợ ợ */
-    0x1ee4, 501, /* Ụ ụ */
-    0x1ee6, 501, /* Ủ ủ */
-    0x1ee8, 501, /* Ứ ứ */
-    0x1eea, 501, /* Ừ ừ */
-    0x1eec, 501, /* Ử ử */
-    0x1eee, 501, /* Ữ ữ */
-    0x1ef0, 501, /* á»° á»± */
-    0x1ef2, 501, /* Ỳ ỳ */
-    0x1ef4, 501, /* Ỵ ỵ */
-    0x1ef6, 501, /* á»¶ á»· */
-    0x1ef8, 501, /* Ỹ ỹ */
-    0x1f59, 492, /* Ὑ ὑ */
-    0x1f5b, 492, /* Ὓ ὓ */
-    0x1f5d, 492, /* Ὕ ὕ */
-    0x1f5f, 492, /* Ὗ ὗ */
-    0x1fbc, 491, /* á¾¼ á¾³ */
-    0x1fcc, 491, /* ῌ ῃ */
-    0x1fec, 493, /* Ῥ ῥ */
-    0x1ffc, 491, /* ῼ ῳ */
-};
-
-static Rune *rune_bsearch(Rune c, Rune *t, int n, int ne) {
-  Rune *p;
-  int m;
-
-  while (n > 1) {
-    m = n / 2;
-    p = t + m * ne;
-    if (c >= p[0]) {
-      t = p;
-      n = n - m;
-    } else
-      n = m;
-  }
-  if (n && c >= t[0]) return t;
-  return 0;
-}
-
-Rune tolowerrune(Rune c) {
-  Rune *p;
-
-  p = rune_bsearch(c, __tolower2, nelem(__tolower2) / 3, 3);
-  if (p && c >= p[0] && c <= p[1]) return c + p[2] - 500;
-  p = rune_bsearch(c, __tolower1, nelem(__tolower1) / 2, 2);
-  if (p && c == p[0]) return c + p[1] - 500;
-  return c;
-}
-
-Rune toupperrune(Rune c) {
-  Rune *p;
-
-  p = rune_bsearch(c, __toupper2, nelem(__toupper2) / 3, 3);
-  if (p && c >= p[0] && c <= p[1]) return c + p[2] - 500;
-  p = rune_bsearch(c, __toupper1, nelem(__toupper1) / 2, 2);
-  if (p && c == p[0]) return c + p[1] - 500;
-  return c;
-}
-
-int islowerrune(Rune c) {
-  Rune *p;
-
-  p = rune_bsearch(c, __toupper2, nelem(__toupper2) / 3, 3);
-  if (p && c >= p[0] && c <= p[1]) return 1;
-  p = rune_bsearch(c, __toupper1, nelem(__toupper1) / 2, 2);
-  if (p && c == p[0]) return 1;
-  return 0;
-}
-
-int isupperrune(Rune c) {
-  Rune *p;
-
-  p = rune_bsearch(c, __tolower2, nelem(__tolower2) / 3, 3);
-  if (p && c >= p[0] && c <= p[1]) return 1;
-  p = rune_bsearch(c, __tolower1, nelem(__tolower1) / 2, 2);
-  if (p && c == p[0]) return 1;
-  return 0;
-}
-
-int isdigitrune(Rune c) {
-  return c >= '0' && c <= '9';
-}
-
-int isnewline(Rune c) {
-  return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029;
-}
-
-int iswordchar(Rune c) {
-  return c == '_' || isdigitrune(c) || (c >= 'a' && c <= 'z') ||
-         (c >= 'A' && c <= 'Z');
-}
-
-int isalpharune(Rune c) {
-  Rune *p;
-
-  if (isupperrune(c) || islowerrune(c)) return 1;
-  p = rune_bsearch(c, __alpha2, nelem(__alpha2) / 2, 2);
-  if (p && c >= p[0] && c <= p[1]) return 1;
-  p = rune_bsearch(c, __alpha1, nelem(__alpha1), 1);
-  if (p && c == p[0]) return 1;
-  return 0;
-}
-
-int isspacerune(Rune c) {
-  Rune *p;
-
-  p = rune_bsearch(c, __space2, nelem(__space2) / 2, 2);
-  if (p && c >= p[0] && c <= p[1]) return 1;
-  return 0;
-}
-
-#else /* CS_ENABLE_UTF8 */
-
-int chartorune(Rune *rune, const char *str) {
-  *rune = *(uchar *) str;
-  return 1;
-}
-
-int fullrune(const char *str, int n) {
-  (void) str;
-  return (n <= 0) ? 0 : 1;
-}
-
-int isdigitrune(Rune c) {
-  return isdigit(c);
-}
-
-int isnewline(Rune c) {
-  return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029;
-}
-
-int iswordchar(Rune c) {
-  return c == '_' || isdigitrune(c) || (c >= 'a' && c <= 'z') ||
-         (c >= 'A' && c <= 'Z');
-}
-
-int isalpharune(Rune c) {
-  return isalpha(c);
-}
-int islowerrune(Rune c) {
-  return islower(c);
-}
-int isspacerune(Rune c) {
-  return isspace(c);
-}
-int isupperrune(Rune c) {
-  return isupper(c);
-}
-
-int runetochar(char *str, Rune *rune) {
-  str[0] = (char) *rune;
-  return 1;
-}
-
-Rune tolowerrune(Rune c) {
-  return tolower(c);
-}
-Rune toupperrune(Rune c) {
-  return toupper(c);
-}
-int utfnlen(const char *s, long m) {
-  (void) s;
-  return (int) c_strnlen(s, (size_t) m);
-}
-
-const char *utfnshift(const char *s, long m) {
-  return s + m;
-}
-
-#endif /* CS_ENABLE_UTF8 */
-
-#endif /* EXCLUDE_COMMON */
-#ifdef V7_MODULE_LINES
-#line 1 "common/base64.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef EXCLUDE_COMMON
-
-/* Amalgamated: #include "common/base64.h" */
-#include <string.h>
-
-/* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ */
-
-#define NUM_UPPERCASES ('Z' - 'A' + 1)
-#define NUM_LETTERS (NUM_UPPERCASES * 2)
-#define NUM_DIGITS ('9' - '0' + 1)
-
-/*
- * Emit a base64 code char.
- *
- * Doesn't use memory, thus it's safe to use to safely dump memory in crashdumps
- */
-static void cs_base64_emit_code(struct cs_base64_ctx *ctx, int v) {
-  if (v < NUM_UPPERCASES) {
-    ctx->b64_putc(v + 'A', ctx->user_data);
-  } else if (v < (NUM_LETTERS)) {
-    ctx->b64_putc(v - NUM_UPPERCASES + 'a', ctx->user_data);
-  } else if (v < (NUM_LETTERS + NUM_DIGITS)) {
-    ctx->b64_putc(v - NUM_LETTERS + '0', ctx->user_data);
-  } else {
-    ctx->b64_putc(v - NUM_LETTERS - NUM_DIGITS == 0 ? '+' : '/',
-                  ctx->user_data);
-  }
-}
-
-static void cs_base64_emit_chunk(struct cs_base64_ctx *ctx) {
-  int a, b, c;
-
-  a = ctx->chunk[0];
-  b = ctx->chunk[1];
-  c = ctx->chunk[2];
-
-  cs_base64_emit_code(ctx, a >> 2);
-  cs_base64_emit_code(ctx, ((a & 3) << 4) | (b >> 4));
-  if (ctx->chunk_size > 1) {
-    cs_base64_emit_code(ctx, (b & 15) << 2 | (c >> 6));
-  }
-  if (ctx->chunk_size > 2) {
-    cs_base64_emit_code(ctx, c & 63);
-  }
-}
-
-void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t b64_putc,
-                    void *user_data) {
-  ctx->chunk_size = 0;
-  ctx->b64_putc = b64_putc;
-  ctx->user_data = user_data;
-}
-
-void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len) {
-  const unsigned char *src = (const unsigned char *) str;
-  size_t i;
-  for (i = 0; i < len; i++) {
-    ctx->chunk[ctx->chunk_size++] = src[i];
-    if (ctx->chunk_size == 3) {
-      cs_base64_emit_chunk(ctx);
-      ctx->chunk_size = 0;
-    }
-  }
-}
-
-void cs_base64_finish(struct cs_base64_ctx *ctx) {
-  if (ctx->chunk_size > 0) {
-    int i;
-    memset(&ctx->chunk[ctx->chunk_size], 0, 3 - ctx->chunk_size);
-    cs_base64_emit_chunk(ctx);
-    for (i = 0; i < (3 - ctx->chunk_size); i++) {
-      ctx->b64_putc('=', ctx->user_data);
-    }
-  }
-}
-
-#define BASE64_ENCODE_BODY                                                \
-  static const char *b64 =                                                \
-      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \
-  int i, j, a, b, c;                                                      \
-                                                                          \
-  for (i = j = 0; i < src_len; i += 3) {                                  \
-    a = src[i];                                                           \
-    b = i + 1 >= src_len ? 0 : src[i + 1];                                \
-    c = i + 2 >= src_len ? 0 : src[i + 2];                                \
-                                                                          \
-    BASE64_OUT(b64[a >> 2]);                                              \
-    BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)]);                           \
-    if (i + 1 < src_len) {                                                \
-      BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)]);                          \
-    }                                                                     \
-    if (i + 2 < src_len) {                                                \
-      BASE64_OUT(b64[c & 63]);                                            \
-    }                                                                     \
-  }                                                                       \
-                                                                          \
-  while (j % 4 != 0) {                                                    \
-    BASE64_OUT('=');                                                      \
-  }                                                                       \
-  BASE64_FLUSH()
-
-#define BASE64_OUT(ch) \
-  do {                 \
-    dst[j++] = (ch);   \
-  } while (0)
-
-#define BASE64_FLUSH() \
-  do {                 \
-    dst[j++] = '\0';   \
-  } while (0)
-
-void cs_base64_encode(const unsigned char *src, int src_len, char *dst) {
-  BASE64_ENCODE_BODY;
-}
-
-#undef BASE64_OUT
-#undef BASE64_FLUSH
-
-#ifndef CS_DISABLE_STDIO
-#define BASE64_OUT(ch)      \
-  do {                      \
-    fprintf(f, "%c", (ch)); \
-    j++;                    \
-  } while (0)
-
-#define BASE64_FLUSH()
-
-void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len) {
-  BASE64_ENCODE_BODY;
-}
-
-#undef BASE64_OUT
-#undef BASE64_FLUSH
-#endif /* !CS_DISABLE_STDIO */
-
-/* Convert one byte of encoded base64 input stream to 6-bit chunk */
-static unsigned char from_b64(unsigned char ch) {
-  /* Inverse lookup map */
-  static const unsigned char tab[128] = {
-      255, 255, 255, 255,
-      255, 255, 255, 255, /*  0 */
-      255, 255, 255, 255,
-      255, 255, 255, 255, /*  8 */
-      255, 255, 255, 255,
-      255, 255, 255, 255, /*  16 */
-      255, 255, 255, 255,
-      255, 255, 255, 255, /*  24 */
-      255, 255, 255, 255,
-      255, 255, 255, 255, /*  32 */
-      255, 255, 255, 62,
-      255, 255, 255, 63, /*  40 */
-      52,  53,  54,  55,
-      56,  57,  58,  59, /*  48 */
-      60,  61,  255, 255,
-      255, 200, 255, 255, /*  56   '=' is 200, on index 61 */
-      255, 0,   1,   2,
-      3,   4,   5,   6, /*  64 */
-      7,   8,   9,   10,
-      11,  12,  13,  14, /*  72 */
-      15,  16,  17,  18,
-      19,  20,  21,  22, /*  80 */
-      23,  24,  25,  255,
-      255, 255, 255, 255, /*  88 */
-      255, 26,  27,  28,
-      29,  30,  31,  32, /*  96 */
-      33,  34,  35,  36,
-      37,  38,  39,  40, /*  104 */
-      41,  42,  43,  44,
-      45,  46,  47,  48, /*  112 */
-      49,  50,  51,  255,
-      255, 255, 255, 255, /*  120 */
-  };
-  return tab[ch & 127];
-}
-
-int cs_base64_decode(const unsigned char *s, int len, char *dst) {
-  unsigned char a, b, c, d;
-  int orig_len = len;
-  while (len >= 4 && (a = from_b64(s[0])) != 255 &&
-         (b = from_b64(s[1])) != 255 && (c = from_b64(s[2])) != 255 &&
-         (d = from_b64(s[3])) != 255) {
-    s += 4;
-    len -= 4;
-    if (a == 200 || b == 200) break; /* '=' can't be there */
-    *dst++ = a << 2 | b >> 4;
-    if (c == 200) break;
-    *dst++ = b << 4 | c >> 2;
-    if (d == 200) break;
-    *dst++ = c << 6 | d;
-  }
-  *dst = 0;
-  return orig_len - len;
-}
-
-#endif /* EXCLUDE_COMMON */
-#ifdef V7_MODULE_LINES
-#line 1 "common/md5.c"
-#endif
-/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest.  This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-
-#if !defined(DISABLE_MD5) && !defined(EXCLUDE_COMMON)
-
-/* Amalgamated: #include "common/md5.h" */
-
-#ifndef CS_ENABLE_NATIVE_MD5
-static void byteReverse(unsigned char *buf, unsigned longs) {
-/* Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN */
-#if BYTE_ORDER == BIG_ENDIAN
-  do {
-    uint32_t t = (uint32_t)((unsigned) buf[3] << 8 | buf[2]) << 16 |
-                 ((unsigned) buf[1] << 8 | buf[0]);
-    *(uint32_t *) buf = t;
-    buf += 4;
-  } while (--longs);
-#else
-  (void) buf;
-  (void) longs;
-#endif
-}
-
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-#define MD5STEP(f, w, x, y, z, data, s) \
-  (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
-
-/*
- * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
-void MD5_Init(MD5_CTX *ctx) {
-  ctx->buf[0] = 0x67452301;
-  ctx->buf[1] = 0xefcdab89;
-  ctx->buf[2] = 0x98badcfe;
-  ctx->buf[3] = 0x10325476;
-
-  ctx->bits[0] = 0;
-  ctx->bits[1] = 0;
-}
-
-static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) {
-  register uint32_t a, b, c, d;
-
-  a = buf[0];
-  b = buf[1];
-  c = buf[2];
-  d = buf[3];
-
-  MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
-  MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
-  MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
-  MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
-  MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
-  MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
-  MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
-  MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
-  MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
-  MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
-  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
-  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
-  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
-  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
-  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
-  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
-  MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
-  MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
-  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
-  MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
-  MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
-  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
-  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
-  MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
-  MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
-  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
-  MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
-  MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
-  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
-  MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
-  MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
-  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
-  MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
-  MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
-  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
-  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
-  MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
-  MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
-  MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
-  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
-  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
-  MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
-  MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
-  MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
-  MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
-  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
-  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
-  MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
-  MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
-  MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
-  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
-  MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
-  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
-  MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
-  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
-  MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
-  MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
-  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
-  MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
-  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
-  MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
-  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
-  MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
-  MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
-  buf[0] += a;
-  buf[1] += b;
-  buf[2] += c;
-  buf[3] += d;
-}
-
-void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, size_t len) {
-  uint32_t t;
-
-  t = ctx->bits[0];
-  if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++;
-  ctx->bits[1] += (uint32_t) len >> 29;
-
-  t = (t >> 3) & 0x3f;
-
-  if (t) {
-    unsigned char *p = (unsigned char *) ctx->in + t;
-
-    t = 64 - t;
-    if (len < t) {
-      memcpy(p, buf, len);
-      return;
-    }
-    memcpy(p, buf, t);
-    byteReverse(ctx->in, 16);
-    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
-    buf += t;
-    len -= t;
-  }
-
-  while (len >= 64) {
-    memcpy(ctx->in, buf, 64);
-    byteReverse(ctx->in, 16);
-    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
-    buf += 64;
-    len -= 64;
-  }
-
-  memcpy(ctx->in, buf, len);
-}
-
-void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) {
-  unsigned count;
-  unsigned char *p;
-  uint32_t *a;
-
-  count = (ctx->bits[0] >> 3) & 0x3F;
-
-  p = ctx->in + count;
-  *p++ = 0x80;
-  count = 64 - 1 - count;
-  if (count < 8) {
-    memset(p, 0, count);
-    byteReverse(ctx->in, 16);
-    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
-    memset(ctx->in, 0, 56);
-  } else {
-    memset(p, 0, count - 8);
-  }
-  byteReverse(ctx->in, 14);
-
-  a = (uint32_t *) ctx->in;
-  a[14] = ctx->bits[0];
-  a[15] = ctx->bits[1];
-
-  MD5Transform(ctx->buf, (uint32_t *) ctx->in);
-  byteReverse((unsigned char *) ctx->buf, 4);
-  memcpy(digest, ctx->buf, 16);
-  memset((char *) ctx, 0, sizeof(*ctx));
-}
-#endif /* CS_ENABLE_NATIVE_MD5 */
-
-/*
- * Stringify binary data. Output buffer size must be 2 * size_of_input + 1
- * because each byte of input takes 2 bytes in string representation
- * plus 1 byte for the terminating \0 character.
- */
-void cs_to_hex(char *to, const unsigned char *p, size_t len) {
-  static const char *hex = "0123456789abcdef";
-
-  for (; len--; p++) {
-    *to++ = hex[p[0] >> 4];
-    *to++ = hex[p[0] & 0x0f];
-  }
-  *to = '\0';
-}
-
-char *cs_md5(char buf[33], ...) {
-  unsigned char hash[16];
-  const unsigned char *p;
-  va_list ap;
-  MD5_CTX ctx;
-
-  MD5_Init(&ctx);
-
-  va_start(ap, buf);
-  while ((p = va_arg(ap, const unsigned char *) ) != NULL) {
-    size_t len = va_arg(ap, size_t);
-    MD5_Update(&ctx, p, len);
-  }
-  va_end(ap);
-
-  MD5_Final(hash, &ctx);
-  cs_to_hex(buf, hash, sizeof(hash));
-
-  return buf;
-}
-
-#endif /* EXCLUDE_COMMON */
-#ifdef V7_MODULE_LINES
-#line 1 "common/sha1.c"
-#endif
-/* Copyright(c) By Steve Reid <steve@edmweb.com> */
-/* 100% Public Domain */
-
-#if !defined(DISABLE_SHA1) && !defined(EXCLUDE_COMMON)
-
-/* Amalgamated: #include "common/sha1.h" */
-
-#define SHA1HANDSOFF
-#if defined(__sun)
-/* Amalgamated: #include "common/solarisfixes.h" */
-#endif
-
-union char64long16 {
-  unsigned char c[64];
-  uint32_t l[16];
-};
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-static uint32_t blk0(union char64long16 *block, int i) {
-/* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
-#if BYTE_ORDER == LITTLE_ENDIAN
-  block->l[i] =
-      (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF);
-#endif
-  return block->l[i];
-}
-
-/* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
-#undef blk
-#undef R0
-#undef R1
-#undef R2
-#undef R3
-#undef R4
-
-#define blk(i)                                                               \
-  (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
-                              block->l[(i + 2) & 15] ^ block->l[i & 15],     \
-                          1))
-#define R0(v, w, x, y, z, i)                                          \
-  z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
-  w = rol(w, 30);
-#define R1(v, w, x, y, z, i)                                  \
-  z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
-  w = rol(w, 30);
-#define R2(v, w, x, y, z, i)                          \
-  z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
-  w = rol(w, 30);
-#define R3(v, w, x, y, z, i)                                        \
-  z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
-  w = rol(w, 30);
-#define R4(v, w, x, y, z, i)                          \
-  z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
-  w = rol(w, 30);
-
-void cs_sha1_transform(uint32_t state[5], const unsigned char buffer[64]) {
-  uint32_t a, b, c, d, e;
-  union char64long16 block[1];
-
-  memcpy(block, buffer, 64);
-  a = state[0];
-  b = state[1];
-  c = state[2];
-  d = state[3];
-  e = state[4];
-  R0(a, b, c, d, e, 0);
-  R0(e, a, b, c, d, 1);
-  R0(d, e, a, b, c, 2);
-  R0(c, d, e, a, b, 3);
-  R0(b, c, d, e, a, 4);
-  R0(a, b, c, d, e, 5);
-  R0(e, a, b, c, d, 6);
-  R0(d, e, a, b, c, 7);
-  R0(c, d, e, a, b, 8);
-  R0(b, c, d, e, a, 9);
-  R0(a, b, c, d, e, 10);
-  R0(e, a, b, c, d, 11);
-  R0(d, e, a, b, c, 12);
-  R0(c, d, e, a, b, 13);
-  R0(b, c, d, e, a, 14);
-  R0(a, b, c, d, e, 15);
-  R1(e, a, b, c, d, 16);
-  R1(d, e, a, b, c, 17);
-  R1(c, d, e, a, b, 18);
-  R1(b, c, d, e, a, 19);
-  R2(a, b, c, d, e, 20);
-  R2(e, a, b, c, d, 21);
-  R2(d, e, a, b, c, 22);
-  R2(c, d, e, a, b, 23);
-  R2(b, c, d, e, a, 24);
-  R2(a, b, c, d, e, 25);
-  R2(e, a, b, c, d, 26);
-  R2(d, e, a, b, c, 27);
-  R2(c, d, e, a, b, 28);
-  R2(b, c, d, e, a, 29);
-  R2(a, b, c, d, e, 30);
-  R2(e, a, b, c, d, 31);
-  R2(d, e, a, b, c, 32);
-  R2(c, d, e, a, b, 33);
-  R2(b, c, d, e, a, 34);
-  R2(a, b, c, d, e, 35);
-  R2(e, a, b, c, d, 36);
-  R2(d, e, a, b, c, 37);
-  R2(c, d, e, a, b, 38);
-  R2(b, c, d, e, a, 39);
-  R3(a, b, c, d, e, 40);
-  R3(e, a, b, c, d, 41);
-  R3(d, e, a, b, c, 42);
-  R3(c, d, e, a, b, 43);
-  R3(b, c, d, e, a, 44);
-  R3(a, b, c, d, e, 45);
-  R3(e, a, b, c, d, 46);
-  R3(d, e, a, b, c, 47);
-  R3(c, d, e, a, b, 48);
-  R3(b, c, d, e, a, 49);
-  R3(a, b, c, d, e, 50);
-  R3(e, a, b, c, d, 51);
-  R3(d, e, a, b, c, 52);
-  R3(c, d, e, a, b, 53);
-  R3(b, c, d, e, a, 54);
-  R3(a, b, c, d, e, 55);
-  R3(e, a, b, c, d, 56);
-  R3(d, e, a, b, c, 57);
-  R3(c, d, e, a, b, 58);
-  R3(b, c, d, e, a, 59);
-  R4(a, b, c, d, e, 60);
-  R4(e, a, b, c, d, 61);
-  R4(d, e, a, b, c, 62);
-  R4(c, d, e, a, b, 63);
-  R4(b, c, d, e, a, 64);
-  R4(a, b, c, d, e, 65);
-  R4(e, a, b, c, d, 66);
-  R4(d, e, a, b, c, 67);
-  R4(c, d, e, a, b, 68);
-  R4(b, c, d, e, a, 69);
-  R4(a, b, c, d, e, 70);
-  R4(e, a, b, c, d, 71);
-  R4(d, e, a, b, c, 72);
-  R4(c, d, e, a, b, 73);
-  R4(b, c, d, e, a, 74);
-  R4(a, b, c, d, e, 75);
-  R4(e, a, b, c, d, 76);
-  R4(d, e, a, b, c, 77);
-  R4(c, d, e, a, b, 78);
-  R4(b, c, d, e, a, 79);
-  state[0] += a;
-  state[1] += b;
-  state[2] += c;
-  state[3] += d;
-  state[4] += e;
-  /* Erase working structures. The order of operations is important,
-   * used to ensure that compiler doesn't optimize those out. */
-  memset(block, 0, sizeof(block));
-  a = b = c = d = e = 0;
-  (void) a;
-  (void) b;
-  (void) c;
-  (void) d;
-  (void) e;
-}
-
-void cs_sha1_init(cs_sha1_ctx *context) {
-  context->state[0] = 0x67452301;
-  context->state[1] = 0xEFCDAB89;
-  context->state[2] = 0x98BADCFE;
-  context->state[3] = 0x10325476;
-  context->state[4] = 0xC3D2E1F0;
-  context->count[0] = context->count[1] = 0;
-}
-
-void cs_sha1_update(cs_sha1_ctx *context, const unsigned char *data,
-                    uint32_t len) {
-  uint32_t i, j;
-
-  j = context->count[0];
-  if ((context->count[0] += len << 3) < j) context->count[1]++;
-  context->count[1] += (len >> 29);
-  j = (j >> 3) & 63;
-  if ((j + len) > 63) {
-    memcpy(&context->buffer[j], data, (i = 64 - j));
-    cs_sha1_transform(context->state, context->buffer);
-    for (; i + 63 < len; i += 64) {
-      cs_sha1_transform(context->state, &data[i]);
-    }
-    j = 0;
-  } else
-    i = 0;
-  memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *context) {
-  unsigned i;
-  unsigned char finalcount[8], c;
-
-  for (i = 0; i < 8; i++) {
-    finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >>
-                                      ((3 - (i & 3)) * 8)) &
-                                     255);
-  }
-  c = 0200;
-  cs_sha1_update(context, &c, 1);
-  while ((context->count[0] & 504) != 448) {
-    c = 0000;
-    cs_sha1_update(context, &c, 1);
-  }
-  cs_sha1_update(context, finalcount, 8);
-  for (i = 0; i < 20; i++) {
-    digest[i] =
-        (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
-  }
-  memset(context, '\0', sizeof(*context));
-  memset(&finalcount, '\0', sizeof(finalcount));
-}
-
-void cs_hmac_sha1(const unsigned char *key, size_t keylen,
-                  const unsigned char *data, size_t datalen,
-                  unsigned char out[20]) {
-  cs_sha1_ctx ctx;
-  unsigned char buf1[64], buf2[64], tmp_key[20], i;
-
-  if (keylen > sizeof(buf1)) {
-    cs_sha1_init(&ctx);
-    cs_sha1_update(&ctx, key, keylen);
-    cs_sha1_final(tmp_key, &ctx);
-    key = tmp_key;
-    keylen = sizeof(tmp_key);
-  }
-
-  memset(buf1, 0, sizeof(buf1));
-  memset(buf2, 0, sizeof(buf2));
-  memcpy(buf1, key, keylen);
-  memcpy(buf2, key, keylen);
-
-  for (i = 0; i < sizeof(buf1); i++) {
-    buf1[i] ^= 0x36;
-    buf2[i] ^= 0x5c;
-  }
-
-  cs_sha1_init(&ctx);
-  cs_sha1_update(&ctx, buf1, sizeof(buf1));
-  cs_sha1_update(&ctx, data, datalen);
-  cs_sha1_final(out, &ctx);
-
-  cs_sha1_init(&ctx);
-  cs_sha1_update(&ctx, buf2, sizeof(buf2));
-  cs_sha1_update(&ctx, out, 20);
-  cs_sha1_final(out, &ctx);
-}
-
-#endif /* EXCLUDE_COMMON */
-#ifdef V7_MODULE_LINES
-#line 1 "common/cs_dirent.c"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef EXCLUDE_COMMON
-
-/* Amalgamated: #include "common/cs_dirent.h" */
-
-/*
- * This file contains POSIX opendir/closedir/readdir API implementation
- * for systems which do not natively support it (e.g. Windows).
- */
-
-#ifndef MG_FREE
-#define MG_FREE free
-#endif
-
-#ifndef MG_MALLOC
-#define MG_MALLOC malloc
-#endif
-
-#ifdef _WIN32
-DIR *opendir(const char *name) {
-  DIR *dir = NULL;
-  wchar_t wpath[MAX_PATH];
-  DWORD attrs;
-
-  if (name == NULL) {
-    SetLastError(ERROR_BAD_ARGUMENTS);
-  } else if ((dir = (DIR *) MG_MALLOC(sizeof(*dir))) == NULL) {
-    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-  } else {
-    to_wchar(name, wpath, ARRAY_SIZE(wpath));
-    attrs = GetFileAttributesW(wpath);
-    if (attrs != 0xFFFFFFFF && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
-      (void) wcscat(wpath, L"\\*");
-      dir->handle = FindFirstFileW(wpath, &dir->info);
-      dir->result.d_name[0] = '\0';
-    } else {
-      MG_FREE(dir);
-      dir = NULL;
-    }
-  }
-
-  return dir;
-}
-
-int closedir(DIR *dir) {
-  int result = 0;
-
-  if (dir != NULL) {
-    if (dir->handle != INVALID_HANDLE_VALUE)
-      result = FindClose(dir->handle) ? 0 : -1;
-    MG_FREE(dir);
-  } else {
-    result = -1;
-    SetLastError(ERROR_BAD_ARGUMENTS);
-  }
-
-  return result;
-}
-
-struct dirent *readdir(DIR *dir) {
-  struct dirent *result = NULL;
-
-  if (dir) {
-    if (dir->handle != INVALID_HANDLE_VALUE) {
-      result = &dir->result;
-      (void) WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, -1,
-                                 result->d_name, sizeof(result->d_name), NULL,
-                                 NULL);
-
-      if (!FindNextFileW(dir->handle, &dir->info)) {
-        (void) FindClose(dir->handle);
-        dir->handle = INVALID_HANDLE_VALUE;
-      }
-
-    } else {
-      SetLastError(ERROR_FILE_NOT_FOUND);
-    }
-  } else {
-    SetLastError(ERROR_BAD_ARGUMENTS);
-  }
-
-  return result;
-}
-#endif
-
-#ifdef CS_ENABLE_SPIFFS
-
-DIR *opendir(const char *dir_name) {
-  DIR *dir = NULL;
-  extern spiffs fs;
-
-  if (dir_name != NULL && (dir = (DIR *) malloc(sizeof(*dir))) != NULL &&
-      SPIFFS_opendir(&fs, (char *) dir_name, &dir->dh) == NULL) {
-    free(dir);
-    dir = NULL;
-  }
-
-  return dir;
-}
-
-int closedir(DIR *dir) {
-  if (dir != NULL) {
-    SPIFFS_closedir(&dir->dh);
-    free(dir);
-  }
-  return 0;
-}
-
-struct dirent *readdir(DIR *dir) {
-  return SPIFFS_readdir(&dir->dh, &dir->de);
-}
-
-/* SPIFFs doesn't support directory operations */
-int rmdir(const char *path) {
-  (void) path;
-  return ENOTDIR;
-}
-
-int mkdir(const char *path, mode_t mode) {
-  (void) path;
-  (void) mode;
-  /* for spiffs supports only root dir, which comes from mongoose as '.' */
-  return (strlen(path) == 1 && *path == '.') ? 0 : ENOTDIR;
-}
-
-#endif /* CS_ENABLE_SPIFFS */
-
-#endif /* EXCLUDE_COMMON */
-
-/* ISO C requires a translation unit to contain at least one declaration */
-typedef int cs_dirent_dummy;
-#ifdef V7_MODULE_LINES
-#line 1 "common/cs_file.c"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/cs_file.h" */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef CS_MMAP
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#endif
-
-#ifndef EXCLUDE_COMMON
-char *cs_read_file(const char *path, size_t *size) {
-  FILE *fp;
-  char *data = NULL;
-  if ((fp = fopen(path, "rb")) == NULL) {
-  } else if (fseek(fp, 0, SEEK_END) != 0) {
-    fclose(fp);
-  } else {
-    *size = ftell(fp);
-    data = (char *) malloc(*size + 1);
-    if (data != NULL) {
-      fseek(fp, 0, SEEK_SET); /* Some platforms might not have rewind(), Oo */
-      if (fread(data, 1, *size, fp) != *size) {
-        free(data);
-        return NULL;
-      }
-      data[*size] = '\0';
-    }
-    fclose(fp);
-  }
-  return data;
-}
-#endif /* EXCLUDE_COMMON */
-
-#ifdef CS_MMAP
-char *cs_mmap_file(const char *path, size_t *size) {
-  char *r;
-  int fd = open(path, O_RDONLY);
-  struct stat st;
-  if (fd == -1) return NULL;
-  fstat(fd, &st);
-  *size = (size_t) st.st_size;
-  r = (char *) mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-  if (r == MAP_FAILED) return NULL;
-  return r;
-}
-#endif
-#ifdef V7_MODULE_LINES
-#line 1 "common/cs_strtod.c"
-#endif
-#include <ctype.h>
-#include <math.h>
-
-#include <stdlib.h>
-
-int cs_strncasecmp(const char *s1, const char *s2, size_t n) {
-  if (n == 0) {
-    return 0;
-  }
-
-  while (n-- != 0 && tolower((int) *s1) == tolower((int) *s2)) {
-    if (n == 0 || *s1 == '\0' || *s2 == '\0') {
-      break;
-    }
-    s1++;
-    s2++;
-  }
-
-  return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
-}
-
-/*
- * based on Source:
- * https://github.com/anakod/Sming/blob/master/Sming/system/stringconversion.cpp#L93
- */
-
-double cs_strtod(const char *str, char **endptr) {
-  double result = 0.0;
-  char c;
-  const char *str_start;
-  struct {
-    unsigned neg : 1;        /* result is negative */
-    unsigned decimals : 1;   /* parsing decimal part */
-    unsigned is_exp : 1;     /* parsing exponent like e+5 */
-    unsigned is_exp_neg : 1; /* exponent is negative */
-  } flags = {0, 0, 0, 0};
-
-  while (isspace((int) *str)) {
-    str++;
-  }
-
-  if (*str == 0) {
-    /* only space in str? */
-    if (endptr != 0) *endptr = (char *) str;
-    return result;
-  }
-
-  /* Handle leading plus/minus signs */
-  while (*str == '-' || *str == '+') {
-    if (*str == '-') {
-      flags.neg = !flags.neg;
-    }
-    str++;
-  }
-
-  if (cs_strncasecmp(str, "NaN", 3) == 0) {
-    if (endptr != 0) *endptr = (char *) str + 3;
-    return NAN;
-  }
-
-  if (cs_strncasecmp(str, "INF", 3) == 0) {
-    str += 3;
-    if (cs_strncasecmp(str, "INITY", 5) == 0) str += 5;
-    if (endptr != 0) *endptr = (char *) str;
-    return flags.neg ? -INFINITY : INFINITY;
-  }
-
-  str_start = str;
-
-  if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) {
-    /* base 16 */
-    str += 2;
-    while ((c = tolower((int) *str))) {
-      int d;
-      if (c >= '0' && c <= '9') {
-        d = c - '0';
-      } else if (c >= 'a' && c <= 'f') {
-        d = 10 + (c - 'a');
-      } else {
-        break;
-      }
-      result = 16 * result + d;
-      str++;
-    }
-  } else if (*str == '0' && (*(str + 1) == 'b' || *(str + 1) == 'B')) {
-    /* base 2 */
-    str += 2;
-    while ((c = *str)) {
-      int d = c - '0';
-      if (c != '0' && c != '1') break;
-      result = 2 * result + d;
-      str++;
-    }
-  } else if (*str == '0' && *(str + 1) >= '0' && *(str + 1) <= '7') {
-    /* base 8 */
-    while ((c = *str)) {
-      int d = c - '0';
-      if (c < '0' || c > '7') {
-        /* fallback to base 10 */
-        str = str_start;
-        break;
-      }
-      result = 8 * result + d;
-      str++;
-    }
-  }
-
-  if (str == str_start) {
-    /* base 10 */
-
-    /* exponent specified explicitly, like in 3e-5, exponent is -5 */
-    int exp = 0;
-    /* exponent calculated from dot, like in 1.23, exponent is -2 */
-    int exp_dot = 0;
-
-    result = 0;
-
-    while ((c = *str)) {
-      int d;
-
-      if (c == '.') {
-        if (!flags.decimals) {
-          /* going to parse decimal part */
-          flags.decimals = 1;
-          str++;
-          continue;
-        } else {
-          /* non-expected dot: assume number data is over */
-          break;
-        }
-      } else if (c == 'e' || c == 'E') {
-        /* going to parse exponent part */
-        flags.is_exp = 1;
-        str++;
-        c = *str;
-
-        /* check sign of the exponent */
-        if (c == '-' || c == '+') {
-          if (c == '-') {
-            flags.is_exp_neg = 1;
-          }
-          str++;
-        }
-
-        continue;
-      }
-
-      d = c - '0';
-      if (d < 0 || d > 9) {
-        break;
-      }
-
-      if (!flags.is_exp) {
-        /* apply current digit to the result */
-        result = 10 * result + d;
-        if (flags.decimals) {
-          exp_dot--;
-        }
-      } else {
-        /* apply current digit to the exponent */
-        if (flags.is_exp_neg) {
-          if (exp > -1022) {
-            exp = 10 * exp - d;
-          }
-        } else {
-          if (exp < 1023) {
-            exp = 10 * exp + d;
-          }
-        }
-      }
-
-      str++;
-    }
-
-    exp += exp_dot;
-
-    /*
-     * TODO(dfrank): it probably makes sense not to adjust intermediate `double
-     * result`, but build double number accordingly to IEEE 754 from taken
-     * (integer) mantissa, exponent and sign. That would work faster, and we
-     * can avoid any possible round errors.
-     */
-
-    /* if exponent is non-zero, apply it */
-    if (exp != 0) {
-      if (exp < 0) {
-        while (exp++ != 0) {
-          result /= 10;
-        }
-      } else {
-        while (exp-- != 0) {
-          result *= 10;
-        }
-      }
-    }
-  }
-
-  if (flags.neg) {
-    result = -result;
-  }
-
-  if (endptr != 0) {
-    *endptr = (char *) str;
-  }
-
-  return result;
-}
-#ifdef V7_MODULE_LINES
-#line 1 "common/coroutine.c"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * Module that provides generic macros and functions to implement "coroutines",
- * i.e. C code that uses `mbuf` as a stack for function calls.
- *
- * More info: see the design doc: https://goo.gl/kfcG61
- */
-
-#include <string.h>
-#include <stdlib.h>
-
-/* Amalgamated: #include "common/coroutine.h" */
-
-/*
- * Unwinds stack by 1 function. Used when we're returning from function and
- * when an exception is thrown.
- */
-static void _level_up(struct cr_ctx *p_ctx) {
-  /* get size of current function's stack data */
-  size_t locals_size = _CR_CURR_FUNC_LOCALS_SIZE(p_ctx);
-
-  /* check stacks underflow */
-  if (_CR_STACK_FID_UND_CHECK(p_ctx, 1 /*fid*/)) {
-    p_ctx->status = CR_RES__ERR_STACK_CALL_UNDERFLOW;
-    return;
-  } else if (_CR_STACK_DATA_UND_CHECK(p_ctx, locals_size)) {
-    p_ctx->status = CR_RES__ERR_STACK_DATA_UNDERFLOW;
-    return;
-  }
-
-  /* decrement stacks */
-  _CR_STACK_DATA_FREE(p_ctx, locals_size);
-  _CR_STACK_FID_FREE(p_ctx, 1 /*fid*/);
-  p_ctx->stack_ret.len = p_ctx->cur_fid_idx;
-
-  /* if we have exception marker here, adjust cur_fid_idx */
-  while (CR_CURR_FUNC_C(p_ctx) == CR_FID__TRY_MARKER) {
-    /* check for stack underflow */
-    if (_CR_STACK_FID_UND_CHECK(p_ctx, _CR_TRY_SIZE)) {
-      p_ctx->status = CR_RES__ERR_STACK_CALL_UNDERFLOW;
-      return;
-    }
-    _CR_STACK_FID_FREE(p_ctx, _CR_TRY_SIZE);
-  }
-}
-
-enum cr_status cr_on_iter_begin(struct cr_ctx *p_ctx) {
-  if (p_ctx->status != CR_RES__OK) {
-    goto out;
-  } else if (p_ctx->called_fid != CR_FID__NONE) {
-    /* need to call new function */
-
-    size_t locals_size = p_ctx->p_func_descrs[p_ctx->called_fid].locals_size;
-    /*
-     * increment stack pointers
-     */
-    /* make sure this function has correct `struct cr_func_desc` entry */
-    assert(locals_size == p_ctx->call_locals_size);
-    /*
-     * make sure we haven't mistakenly included "zero-sized" `.._arg_t`
-     * structure in `.._locals_t` struct
-     *
-     * By "zero-sized" I mean `cr_zero_size_type_t`.
-     */
-    assert(locals_size < sizeof(cr_zero_size_type_t));
-
-    _CR_STACK_DATA_ALLOC(p_ctx, locals_size);
-    _CR_STACK_RET_ALLOC(p_ctx, 1 /*fid*/);
-    p_ctx->cur_fid_idx = p_ctx->stack_ret.len;
-
-    /* copy arguments to our "stack" (and advance locals stack pointer) */
-    memcpy(p_ctx->stack_data.buf + p_ctx->stack_data.len - locals_size,
-           p_ctx->p_arg_retval, p_ctx->call_arg_size);
-
-    /* set function id */
-    CR_CURR_FUNC_C(p_ctx) = p_ctx->called_fid;
-
-    /* clear called_fid */
-    p_ctx->called_fid = CR_FID__NONE;
-
-  } else if (p_ctx->need_return) {
-    /* need to return from the currently running function */
-
-    _level_up(p_ctx);
-    if (p_ctx->status != CR_RES__OK) {
-      goto out;
-    }
-
-    p_ctx->need_return = 0;
-
-  } else if (p_ctx->need_yield) {
-    /* need to yield */
-
-    p_ctx->need_yield = 0;
-    p_ctx->status = CR_RES__OK_YIELDED;
-    goto out;
-
-  } else if (p_ctx->thrown_exc != CR_EXC_ID__NONE) {
-    /* exception was thrown */
-
-    /* unwind stack until we reach the bottom, or find some try-catch blocks */
-    do {
-      _level_up(p_ctx);
-      if (p_ctx->status != CR_RES__OK) {
-        goto out;
-      }
-
-      if (_CR_TRY_MARKER(p_ctx) == CR_FID__TRY_MARKER) {
-        /* we have some try-catch here, go to the first catch */
-        CR_CURR_FUNC_C(p_ctx) = _CR_TRY_CATCH_FID(p_ctx);
-        break;
-      } else if (CR_CURR_FUNC_C(p_ctx) == CR_FID__NONE) {
-        /* we've reached the bottom of the stack */
-        p_ctx->status = CR_RES__ERR_UNCAUGHT_EXCEPTION;
-        break;
-      }
-
-    } while (1);
-  }
-
-  /* remember pointer to current function's locals */
-  _CR_CUR_FUNC_LOCALS_UPD(p_ctx);
-
-out:
-  return p_ctx->status;
-}
-
-void cr_context_init(struct cr_ctx *p_ctx, union user_arg_ret *p_arg_retval,
-                     size_t arg_retval_size,
-                     const struct cr_func_desc *p_func_descrs) {
-  /*
-   * make sure we haven't mistakenly included "zero-sized" `.._arg_t`
-   * structure in `union user_arg_ret`.
-   *
-   * By "zero-sized" I mean `cr_zero_size_type_t`.
-   */
-  assert(arg_retval_size < sizeof(cr_zero_size_type_t));
-#ifdef NDEBUG
-  (void) arg_retval_size;
-#endif
-
-  memset(p_ctx, 0x00, sizeof(*p_ctx));
-
-  p_ctx->p_func_descrs = p_func_descrs;
-  p_ctx->p_arg_retval = p_arg_retval;
-
-  mbuf_init(&p_ctx->stack_data, 0);
-  mbuf_init(&p_ctx->stack_ret, 0);
-
-  mbuf_append(&p_ctx->stack_ret, NULL, 1 /*starting byte for CR_FID__NONE*/);
-  p_ctx->cur_fid_idx = p_ctx->stack_ret.len;
-
-  _CR_CALL_PREPARE(p_ctx, CR_FID__NONE, 0, 0, CR_FID__NONE);
-}
-
-void cr_context_free(struct cr_ctx *p_ctx) {
-  mbuf_free(&p_ctx->stack_data);
-  mbuf_free(&p_ctx->stack_ret);
-}
-#ifdef V7_MODULE_LINES
-#line 1 "common/platforms/mbed/mbed_libc.c"
-#endif
-/*
- * Copyright (c) 2014-2016 Cesanta Software Limited
- * All rights reserved
- */
-
-#if CS_PLATFORM == CS_P_MBED
-
-long timezone;
-
-#endif /* CS_PLATFORM == CS_P_MBED */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/builtin/file.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/exec.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "common/mbuf.h" */
-/* Amalgamated: #include "common/cs_file.h" */
-/* Amalgamated: #include "v7/src/v7_features.h" */
-/* Amalgamated: #include "common/cs_dirent.h" */
-
-#if defined(V7_ENABLE_FILE) && !defined(V7_NO_FS)
-
-static const char s_fd_prop[] = "__fd";
-
-#ifndef NO_LIBC
-static FILE *v7_val_to_file(struct v7 *v7, v7_val_t val) {
-  (void) v7;
-  return (FILE *) v7_get_ptr(v7, val);
-}
-
-static v7_val_t v7_file_to_val(struct v7 *v7, FILE *file) {
-  (void) v7;
-  return v7_mk_foreign(v7, file);
-}
-
-static int v7_is_file_type(v7_val_t val) {
-  return v7_is_foreign(val);
-}
-#else
-FILE *v7_val_to_file(struct v7 *v7, v7_val_t val);
-v7_val_t v7_file_to_val(struct v7 *v7, FILE *file);
-int v7_is_file_type(v7_val_t val);
-#endif
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_eval(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-
-  *res = V7_UNDEFINED;
-
-  if (v7_is_string(arg0)) {
-    const char *s = v7_get_cstring(v7, &arg0);
-    if (s == NULL) {
-      rcode = v7_throwf(v7, "TypeError", "Invalid string");
-      goto clean;
-    }
-
-    v7_set_gc_enabled(v7, 1);
-    rcode = v7_exec_file(v7, s, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_exists(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-
-  *res = v7_mk_boolean(v7, 0);
-
-  if (v7_is_string(arg0)) {
-    const char *fname = v7_get_cstring(v7, &arg0);
-    if (fname != NULL) {
-      struct stat st;
-      if (stat(fname, &st) == 0) *res = v7_mk_boolean(v7, 1);
-    }
-  }
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err f_read(struct v7 *v7, int all, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t this_obj = v7_get_this(v7);
-  v7_val_t arg0 = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1);
-
-  if (v7_is_file_type(arg0)) {
-    struct mbuf m;
-    char buf[BUFSIZ];
-    int n;
-    FILE *fp = v7_val_to_file(v7, arg0);
-
-    /* Read file contents into mbuf */
-    mbuf_init(&m, 0);
-    while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
-      mbuf_append(&m, buf, n);
-      if (!all) {
-        break;
-      }
-    }
-
-    if (m.len > 0) {
-      *res = v7_mk_string(v7, m.buf, m.len, 1);
-      mbuf_free(&m);
-      goto clean;
-    }
-  }
-  *res = v7_mk_string(v7, "", 0, 1);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_obj_read(struct v7 *v7, v7_val_t *res) {
-  return f_read(v7, 0, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_obj_write(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t this_obj = v7_get_this(v7);
-  v7_val_t arg0 = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1);
-  v7_val_t arg1 = v7_arg(v7, 0);
-  size_t n, sent = 0, len = 0;
-
-  if (v7_is_file_type(arg0) && v7_is_string(arg1)) {
-    const char *s = v7_get_string(v7, &arg1, &len);
-    FILE *fp = v7_val_to_file(v7, arg0);
-    while (sent < len && (n = fwrite(s + sent, 1, len - sent, fp)) > 0) {
-      sent += n;
-    }
-  }
-
-  *res = v7_mk_number(v7, sent);
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_obj_close(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t this_obj = v7_get_this(v7);
-  v7_val_t prop = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1);
-  int ires = -1;
-
-  if (v7_is_file_type(prop)) {
-    ires = fclose(v7_val_to_file(v7, prop));
-  }
-
-  *res = v7_mk_number(v7, ires);
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_open(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-  v7_val_t arg1 = v7_arg(v7, 1);
-  FILE *fp = NULL;
-
-  if (v7_is_string(arg0)) {
-    const char *s1 = v7_get_cstring(v7, &arg0);
-    const char *s2 = "rb"; /* Open files in read mode by default */
-
-    if (v7_is_string(arg1)) {
-      s2 = v7_get_cstring(v7, &arg1);
-    }
-
-    if (s1 == NULL || s2 == NULL) {
-      *res = V7_NULL;
-      goto clean;
-    }
-
-    fp = fopen(s1, s2);
-    if (fp != NULL) {
-      v7_val_t obj = v7_mk_object(v7);
-      v7_val_t file_proto = v7_get(
-          v7, v7_get(v7, v7_get_global(v7), "File", ~0), "prototype", ~0);
-      v7_set_proto(v7, obj, file_proto);
-      v7_def(v7, obj, s_fd_prop, sizeof(s_fd_prop) - 1, V7_DESC_ENUMERABLE(0),
-             v7_file_to_val(v7, fp));
-      *res = obj;
-      goto clean;
-    }
-  }
-
-  *res = V7_NULL;
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_read(struct v7 *v7, v7_val_t *res) {
-  v7_val_t arg0 = v7_arg(v7, 0);
-
-  if (v7_is_string(arg0)) {
-    const char *path = v7_get_cstring(v7, &arg0);
-    size_t size = 0;
-    char *data = cs_read_file(path, &size);
-    if (data != NULL) {
-      *res = v7_mk_string(v7, data, size, 1);
-      free(data);
-    }
-  }
-
-  return V7_OK;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_write(struct v7 *v7, v7_val_t *res) {
-  v7_val_t arg0 = v7_arg(v7, 0);
-  v7_val_t arg1 = v7_arg(v7, 1);
-  *res = v7_mk_boolean(v7, 0);
-
-  if (v7_is_string(arg0) && v7_is_string(arg1)) {
-    const char *path = v7_get_cstring(v7, &arg0);
-    size_t len;
-    const char *buf = v7_get_string(v7, &arg1, &len);
-    FILE *fp = fopen(path, "wb+");
-    if (fp != NULL) {
-      if (fwrite(buf, 1, len, fp) == len) {
-        *res = v7_mk_boolean(v7, 1);
-      }
-      fclose(fp);
-    }
-  }
-
-  return V7_OK;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_rename(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-  v7_val_t arg1 = v7_arg(v7, 1);
-  int ires = -1;
-
-  if (v7_is_string(arg0) && v7_is_string(arg1)) {
-    const char *from = v7_get_cstring(v7, &arg0);
-    const char *to = v7_get_cstring(v7, &arg1);
-    if (from == NULL || to == NULL) {
-      *res = v7_mk_number(v7, ENOENT);
-      goto clean;
-    }
-
-    ires = rename(from, to);
-  }
-
-  *res = v7_mk_number(v7, ires == 0 ? 0 : errno);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_loadJSON(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-
-  *res = V7_UNDEFINED;
-
-  if (v7_is_string(arg0)) {
-    const char *file_name = v7_get_cstring(v7, &arg0);
-    if (file_name == NULL) {
-      goto clean;
-    }
-
-    rcode = v7_parse_json_file(v7, file_name, res);
-    if (rcode != V7_OK) {
-      /* swallow exception and return undefined */
-      v7_clear_thrown_value(v7);
-      rcode = V7_OK;
-      *res = V7_UNDEFINED;
-    }
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_remove(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-  int ires = -1;
-
-  if (v7_is_string(arg0)) {
-    const char *path = v7_get_cstring(v7, &arg0);
-    if (path == NULL) {
-      *res = v7_mk_number(v7, ENOENT);
-      goto clean;
-    }
-    ires = remove(path);
-  }
-  *res = v7_mk_number(v7, ires == 0 ? 0 : errno);
-
-clean:
-  return rcode;
-}
-
-#if V7_ENABLE__File__list
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err File_list(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-
-  *res = V7_UNDEFINED;
-
-  if (v7_is_string(arg0)) {
-    const char *path = v7_get_cstring(v7, &arg0);
-    struct dirent *dp;
-    DIR *dirp;
-
-    if (path == NULL) {
-      goto clean;
-    }
-
-    if ((dirp = (opendir(path))) != NULL) {
-      *res = v7_mk_array(v7);
-      while ((dp = readdir(dirp)) != NULL) {
-        /* Do not show current and parent dirs */
-        if (strcmp((const char *) dp->d_name, ".") == 0 ||
-            strcmp((const char *) dp->d_name, "..") == 0) {
-          continue;
-        }
-        /* Add file name to the list */
-        v7_array_push(v7, *res,
-                      v7_mk_string(v7, (const char *) dp->d_name,
-                                   strlen((const char *) dp->d_name), 1));
-      }
-      closedir(dirp);
-    }
-  }
-
-clean:
-  return rcode;
-}
-#endif /* V7_ENABLE__File__list */
-
-void init_file(struct v7 *v7) {
-  v7_val_t file_obj = v7_mk_object(v7), file_proto = v7_mk_object(v7);
-  v7_set(v7, v7_get_global(v7), "File", 4, file_obj);
-  v7_set(v7, file_obj, "prototype", 9, file_proto);
-
-  v7_set_method(v7, file_obj, "eval", File_eval);
-  v7_set_method(v7, file_obj, "exists", File_exists);
-  v7_set_method(v7, file_obj, "remove", File_remove);
-  v7_set_method(v7, file_obj, "rename", File_rename);
-  v7_set_method(v7, file_obj, "open", File_open);
-  v7_set_method(v7, file_obj, "read", File_read);
-  v7_set_method(v7, file_obj, "write", File_write);
-  v7_set_method(v7, file_obj, "loadJSON", File_loadJSON);
-#if V7_ENABLE__File__list
-  v7_set_method(v7, file_obj, "list", File_list);
-#endif
-
-  v7_set_method(v7, file_proto, "close", File_obj_close);
-  v7_set_method(v7, file_proto, "read", File_obj_read);
-  v7_set_method(v7, file_proto, "write", File_obj_write);
-
-#if V7_ENABLE__File__require
-  v7_def(v7, v7_get_global(v7), "_modcache", ~0, 0, v7_mk_object(v7));
-  if (v7_exec(v7,
-              "function require(m) { "
-              "  if (m in _modcache) { return _modcache[m]; }"
-              "  var module = {exports:{}};"
-              "  File.eval(m);"
-              "  return (_modcache[m] = module.exports)"
-              " }",
-              NULL) != V7_OK) {
-    /* TODO(mkm): percolate failure */
-  }
-#endif
-}
-#else
-void init_file(struct v7 *v7) {
-  (void) v7;
-}
-#endif /* NO_LIBC */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/builtin/socket.c"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "common/mbuf.h" */
-/* Amalgamated: #include "common/platform.h" */
-
-#ifdef V7_ENABLE_SOCKET
-
-#ifdef __WATCOM__
-#define SOMAXCONN 128
-#endif
-
-#ifndef RECV_BUF_SIZE
-#define RECV_BUF_SIZE 1024
-#endif
-
-static const char s_sock_prop[] = "__sock";
-
-static uint32_t s_resolve(struct v7 *v7, v7_val_t ip_address) {
-  size_t n;
-  const char *s = v7_get_string(v7, &ip_address, &n);
-  struct hostent *he = gethostbyname(s);
-  return he == NULL ? 0 : *(uint32_t *) he->h_addr_list[0];
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err s_fd_to_sock_obj(struct v7 *v7, sock_t fd, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t sock_proto =
-      v7_get(v7, v7_get(v7, v7_get_global(v7), "Socket", ~0), "prototype", ~0);
-
-  *res = v7_mk_object(v7);
-  v7_set_proto(v7, *res, sock_proto);
-  v7_def(v7, *res, s_sock_prop, sizeof(s_sock_prop) - 1, V7_DESC_ENUMERABLE(0),
-         v7_mk_number(v7, fd));
-
-  return rcode;
-}
-
-/* Socket.connect(host, port [, is_udp]) -> socket_object */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Socket_connect(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-  v7_val_t arg1 = v7_arg(v7, 1);
-  v7_val_t arg2 = v7_arg(v7, 2);
-
-  if (v7_is_number(arg1) && v7_is_string(arg0)) {
-    struct sockaddr_in sin;
-    sock_t sock =
-        socket(AF_INET, v7_is_truthy(v7, arg2) ? SOCK_DGRAM : SOCK_STREAM, 0);
-    memset(&sin, 0, sizeof(sin));
-    sin.sin_family = AF_INET;
-    sin.sin_addr.s_addr = s_resolve(v7, arg0);
-    sin.sin_port = htons((uint16_t) v7_get_double(v7, arg1));
-    if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
-      closesocket(sock);
-    } else {
-      rcode = s_fd_to_sock_obj(v7, sock, res);
-      goto clean;
-    }
-  }
-
-  *res = V7_NULL;
-
-clean:
-  return rcode;
-}
-
-/* Socket.listen(port [, ip_address [,is_udp]]) -> sock */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Socket_listen(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-  v7_val_t arg1 = v7_arg(v7, 1);
-  v7_val_t arg2 = v7_arg(v7, 2);
-
-  if (v7_is_number(arg0)) {
-    struct sockaddr_in sin;
-    int on = 1;
-    sock_t sock =
-        socket(AF_INET, v7_is_truthy(v7, arg2) ? SOCK_DGRAM : SOCK_STREAM, 0);
-    memset(&sin, 0, sizeof(sin));
-    sin.sin_family = AF_INET;
-    sin.sin_port = htons((uint16_t) v7_get_double(v7, arg0));
-    if (v7_is_string(arg1)) {
-      sin.sin_addr.s_addr = s_resolve(v7, arg1);
-    }
-
-#if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE)
-    /* "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" http://goo.gl/RmrFTm */
-    setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void *) &on, sizeof(on));
-#endif
-
-#if !defined(_WIN32) || defined(SO_EXCLUSIVEADDRUSE)
-    /*
-     * SO_RESUSEADDR is not enabled on Windows because the semantics of
-     * SO_REUSEADDR on UNIX and Windows is different. On Windows,
-     * SO_REUSEADDR allows to bind a socket to a port without error even if
-     * the port is already open by another program. This is not the behavior
-     * SO_REUSEADDR was designed for, and leads to hard-to-track failure
-     * scenarios. Therefore, SO_REUSEADDR was disabled on Windows unless
-     * SO_EXCLUSIVEADDRUSE is supported and set on a socket.
-     */
-    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on));
-#endif
-
-    if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) == 0) {
-      listen(sock, SOMAXCONN);
-      rcode = s_fd_to_sock_obj(v7, sock, res);
-      goto clean;
-    } else {
-      closesocket(sock);
-    }
-  }
-
-  *res = V7_NULL;
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Socket_accept(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t this_obj = v7_get_this(v7);
-  v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
-
-  if (v7_is_number(prop)) {
-    struct sockaddr_in sin;
-    socklen_t len = sizeof(sin);
-    sock_t sock = (sock_t) v7_get_double(v7, prop);
-    sock_t fd = accept(sock, (struct sockaddr *) &sin, &len);
-    if (fd != INVALID_SOCKET) {
-      rcode = s_fd_to_sock_obj(v7, fd, res);
-      if (rcode == V7_OK) {
-        char *remote_host = inet_ntoa(sin.sin_addr);
-        v7_set(v7, *res, "remoteHost", ~0,
-               v7_mk_string(v7, remote_host, ~0, 1));
-      }
-      goto clean;
-    }
-  }
-  *res = V7_NULL;
-
-clean:
-  return rcode;
-}
-
-/* sock.close() -> errno */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Socket_close(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t this_obj = v7_get_this(v7);
-  v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
-  *res = v7_mk_number(v7, closesocket((sock_t) v7_get_double(v7, prop)));
-
-  return rcode;
-}
-
-/* sock.recv() -> string */
-WARN_UNUSED_RESULT
-static enum v7_err s_recv(struct v7 *v7, int all, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t this_obj = v7_get_this(v7);
-  v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
-
-  if (v7_is_number(prop)) {
-    char buf[RECV_BUF_SIZE];
-    sock_t sock = (sock_t) v7_get_double(v7, prop);
-    struct mbuf m;
-    int n;
-
-    mbuf_init(&m, 0);
-    while ((n = recv(sock, buf, sizeof(buf), 0)) > 0) {
-      mbuf_append(&m, buf, n);
-      if (!all) {
-        break;
-      }
-    }
-
-    if (n <= 0) {
-      closesocket(sock);
-      v7_def(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1,
-             V7_DESC_ENUMERABLE(0), v7_mk_number(v7, INVALID_SOCKET));
-    }
-
-    if (m.len > 0) {
-      *res = v7_mk_string(v7, m.buf, m.len, 1);
-      mbuf_free(&m);
-      goto clean;
-    }
-  }
-
-  *res = V7_NULL;
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Socket_recvAll(struct v7 *v7, v7_val_t *res) {
-  return s_recv(v7, 1, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Socket_recv(struct v7 *v7, v7_val_t *res) {
-  return s_recv(v7, 0, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Socket_send(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t this_obj = v7_get_this(v7);
-  v7_val_t arg0 = v7_arg(v7, 0);
-  v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
-  size_t len, sent = 0;
-
-  if (v7_is_number(prop) && v7_is_string(arg0)) {
-    const char *s = v7_get_string(v7, &arg0, &len);
-    sock_t sock = (sock_t) v7_get_double(v7, prop);
-    int n;
-
-    while (sent < len && (n = send(sock, s + sent, len - sent, 0)) > 0) {
-      sent += n;
-    }
-  }
-
-  *res = v7_mk_number(v7, sent);
-
-  return rcode;
-}
-
-void init_socket(struct v7 *v7) {
-  v7_val_t socket_obj = v7_mk_object(v7), sock_proto = v7_mk_object(v7);
-
-  v7_set(v7, v7_get_global(v7), "Socket", 6, socket_obj);
-  sock_proto = v7_mk_object(v7);
-  v7_set(v7, socket_obj, "prototype", 9, sock_proto);
-
-  v7_set_method(v7, socket_obj, "connect", Socket_connect);
-  v7_set_method(v7, socket_obj, "listen", Socket_listen);
-
-  v7_set_method(v7, sock_proto, "accept", Socket_accept);
-  v7_set_method(v7, sock_proto, "send", Socket_send);
-  v7_set_method(v7, sock_proto, "recv", Socket_recv);
-  v7_set_method(v7, sock_proto, "recvAll", Socket_recvAll);
-  v7_set_method(v7, sock_proto, "close", Socket_close);
-
-#ifdef _WIN32
-  {
-    WSADATA data;
-    WSAStartup(MAKEWORD(2, 2), &data);
-    /* TODO(alashkin): add WSACleanup call */
-  }
-#else
-  signal(SIGPIPE, SIG_IGN);
-#endif
-}
-#else
-void init_socket(struct v7 *v7) {
-  (void) v7;
-}
-#endif
-#ifdef V7_MODULE_LINES
-#line 1 "v7/builtin/crypto.c"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "common/md5.h" */
-/* Amalgamated: #include "common/sha1.h" */
-/* Amalgamated: #include "common/base64.h" */
-
-#ifdef V7_ENABLE_CRYPTO
-
-typedef void (*b64_func_t)(const unsigned char *, int, char *);
-
-WARN_UNUSED_RESULT
-static enum v7_err b64_transform(struct v7 *v7, b64_func_t func, double mult,
-                                 v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-  *res = V7_UNDEFINED;
-
-  if (v7_is_string(arg0)) {
-    size_t n;
-    const char *s = v7_get_string(v7, &arg0, &n);
-    char *buf = (char *) malloc(n * mult + 4);
-    if (buf != NULL) {
-      func((const unsigned char *) s, (int) n, buf);
-      *res = v7_mk_string(v7, buf, strlen(buf), 1);
-      free(buf);
-    }
-  }
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Crypto_base64_decode(struct v7 *v7, v7_val_t *res) {
-  return b64_transform(v7, (b64_func_t) cs_base64_decode, 0.75, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Crypto_base64_encode(struct v7 *v7, v7_val_t *res) {
-  return b64_transform(v7, cs_base64_encode, 1.5, res);
-}
-
-static void v7_md5(const char *data, size_t len, char buf[16]) {
-  MD5_CTX ctx;
-  MD5_Init(&ctx);
-  MD5_Update(&ctx, (unsigned char *) data, len);
-  MD5_Final((unsigned char *) buf, &ctx);
-}
-
-static void v7_sha1(const char *data, size_t len, char buf[20]) {
-  cs_sha1_ctx ctx;
-  cs_sha1_init(&ctx);
-  cs_sha1_update(&ctx, (unsigned char *) data, len);
-  cs_sha1_final((unsigned char *) buf, &ctx);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Crypto_md5(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-
-  if (v7_is_string(arg0)) {
-    size_t len;
-    const char *data = v7_get_string(v7, &arg0, &len);
-    char buf[16];
-    v7_md5(data, len, buf);
-    *res = v7_mk_string(v7, buf, sizeof(buf), 1);
-    goto clean;
-  }
-
-  *res = V7_NULL;
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Crypto_md5_hex(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-
-  if (v7_is_string(arg0)) {
-    size_t len;
-    const char *data = v7_get_string(v7, &arg0, &len);
-    char hash[16], buf[sizeof(hash) * 2 + 1];
-    v7_md5(data, len, hash);
-    cs_to_hex(buf, (unsigned char *) hash, sizeof(hash));
-    *res = v7_mk_string(v7, buf, sizeof(buf) - 1, 1);
-    goto clean;
-  }
-  *res = V7_NULL;
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Crypto_sha1(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-
-  if (v7_is_string(arg0)) {
-    size_t len;
-    const char *data = v7_get_string(v7, &arg0, &len);
-    char buf[20];
-    v7_sha1(data, len, buf);
-    *res = v7_mk_string(v7, buf, sizeof(buf), 1);
-    goto clean;
-  }
-  *res = V7_NULL;
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Crypto_sha1_hex(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = v7_arg(v7, 0);
-
-  if (v7_is_string(arg0)) {
-    size_t len;
-    const char *data = v7_get_string(v7, &arg0, &len);
-    char hash[20], buf[sizeof(hash) * 2 + 1];
-    v7_sha1(data, len, hash);
-    cs_to_hex(buf, (unsigned char *) hash, sizeof(hash));
-    *res = v7_mk_string(v7, buf, sizeof(buf) - 1, 1);
-    goto clean;
-  }
-  *res = V7_NULL;
-
-clean:
-  return rcode;
-}
-#endif
-
-void init_crypto(struct v7 *v7) {
-#ifdef V7_ENABLE_CRYPTO
-  v7_val_t obj = v7_mk_object(v7);
-  v7_set(v7, v7_get_global(v7), "Crypto", 6, obj);
-  v7_set_method(v7, obj, "md5", Crypto_md5);
-  v7_set_method(v7, obj, "md5_hex", Crypto_md5_hex);
-  v7_set_method(v7, obj, "sha1", Crypto_sha1);
-  v7_set_method(v7, obj, "sha1_hex", Crypto_sha1_hex);
-  v7_set_method(v7, obj, "base64_encode", Crypto_base64_encode);
-  v7_set_method(v7, obj, "base64_decode", Crypto_base64_decode);
-#else
-  (void) v7;
-#endif
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/varint.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/varint.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Strings in AST are encoded as tuples (length, string).
- * Length is variable-length: if high bit is set in a byte, next byte is used.
- * Maximum string length with such encoding is 2 ^ (7 * 4) == 256 MiB,
- * assuming that sizeof(size_t) == 4.
- * Small string length (less then 128 bytes) is encoded in 1 byte.
- */
-V7_PRIVATE size_t decode_varint(const unsigned char *p, int *llen) {
-  size_t i = 0, string_len = 0;
-
-  do {
-    /*
-     * Each byte of varint contains 7 bits, in little endian order.
-     * MSB is a continuation bit: it tells whether next byte is used.
-     */
-    string_len |= (p[i] & 0x7f) << (7 * i);
-    /*
-     * First we increment i, then check whether it is within boundary and
-     * whether decoded byte had continuation bit set.
-     */
-  } while (++i < sizeof(size_t) && (p[i - 1] & 0x80));
-  *llen = i;
-
-  return string_len;
-}
-
-/* Return number of bytes to store length */
-V7_PRIVATE int calc_llen(size_t len) {
-  int n = 0;
-
-  do {
-    n++;
-  } while (len >>= 7);
-
-  return n;
-}
-
-V7_PRIVATE int encode_varint(size_t len, unsigned char *p) {
-  int i, llen = calc_llen(len);
-
-  for (i = 0; i < llen; i++) {
-    p[i] = (len & 0x7f) | (i < llen - 1 ? 0x80 : 0);
-    len >>= 7;
-  }
-
-  return llen;
-}
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/tokenizer.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/cs_strtod.h" */
-/* Amalgamated: #include "common/utf.h" */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-#if !defined(V7_NO_COMPILER)
-
-/*
- * NOTE(lsm): Must be in the same order as enum for keywords. See comment
- * for function get_tok() for rationale for that.
- */
-static const struct v7_vec_const s_keywords[] = {
-    V7_VEC("break"),      V7_VEC("case"),     V7_VEC("catch"),
-    V7_VEC("continue"),   V7_VEC("debugger"), V7_VEC("default"),
-    V7_VEC("delete"),     V7_VEC("do"),       V7_VEC("else"),
-    V7_VEC("false"),      V7_VEC("finally"),  V7_VEC("for"),
-    V7_VEC("function"),   V7_VEC("if"),       V7_VEC("in"),
-    V7_VEC("instanceof"), V7_VEC("new"),      V7_VEC("null"),
-    V7_VEC("return"),     V7_VEC("switch"),   V7_VEC("this"),
-    V7_VEC("throw"),      V7_VEC("true"),     V7_VEC("try"),
-    V7_VEC("typeof"),     V7_VEC("var"),      V7_VEC("void"),
-    V7_VEC("while"),      V7_VEC("with")};
-
-V7_PRIVATE int is_reserved_word_token(enum v7_tok tok) {
-  return tok >= TOK_BREAK && tok <= TOK_WITH;
-}
-
-/*
- * Move ptr to the next token, skipping comments and whitespaces.
- * Return number of new line characters detected.
- */
-V7_PRIVATE int skip_to_next_tok(const char **ptr, const char *src_end) {
-  const char *s = *ptr, *p = NULL;
-  int num_lines = 0;
-
-  while (s != p && s < src_end && *s != '\0' &&
-         (isspace((unsigned char) *s) || *s == '/')) {
-    p = s;
-    while (s < src_end && *s != '\0' && isspace((unsigned char) *s)) {
-      if (*s == '\n') num_lines++;
-      s++;
-    }
-    if ((s + 1) < src_end && s[0] == '/' && s[1] == '/') {
-      s += 2;
-      while (s < src_end && s[0] != '\0' && s[0] != '\n') s++;
-    }
-    if ((s + 1) < src_end && s[0] == '/' && s[1] == '*') {
-      s += 2;
-      while (s < src_end && s[0] != '\0' && !(s[-1] == '/' && s[-2] == '*')) {
-        if (s[0] == '\n') num_lines++;
-        s++;
-      }
-    }
-  }
-  *ptr = s;
-
-  return num_lines;
-}
-
-/* Advance `s` pointer to the end of identifier  */
-static void ident(const char **s, const char *src_end) {
-  const unsigned char *p = (unsigned char *) *s;
-  int n;
-  Rune r;
-
-  while ((const char *) p < src_end && p[0] != '\0') {
-    if (p[0] == '$' || p[0] == '_' || isalnum(p[0])) {
-      /* $, _, or any alphanumeric are valid identifier characters */
-      p++;
-    } else if ((const char *) (p + 5) < src_end && p[0] == '\\' &&
-               p[1] == 'u' && isxdigit(p[2]) && isxdigit(p[3]) &&
-               isxdigit(p[4]) && isxdigit(p[5])) {
-      /* Unicode escape, \uXXXX . Could be used like "var \u0078 = 1;" */
-      p += 6;
-    } else if ((n = chartorune(&r, (char *) p)) > 1 && isalpharune(r)) {
-      /*
-       * TODO(dfrank): the chartorune() call above can read `p` past the
-       * src_end, so it might crash on incorrect code. The solution would be
-       * to modify `chartorune()` to accept src_end argument as well.
-       */
-      /* Unicode alphanumeric character */
-      p += n;
-    } else {
-      break;
-    }
-  }
-
-  *s = (char *) p;
-}
-
-static enum v7_tok kw(const char *s, size_t len, int ntoks, enum v7_tok tok) {
-  int i;
-
-  for (i = 0; i < ntoks; i++) {
-    if (s_keywords[(tok - TOK_BREAK) + i].len == len &&
-        memcmp(s_keywords[(tok - TOK_BREAK) + i].p + 1, s + 1, len - 1) == 0)
-      break;
-  }
-
-  return i == ntoks ? TOK_IDENTIFIER : (enum v7_tok)(tok + i);
-}
-
-static enum v7_tok punct1(const char **s, const char *src_end, int ch1,
-                          enum v7_tok tok1, enum v7_tok tok2) {
-  (*s)++;
-  if (*s < src_end && **s == ch1) {
-    (*s)++;
-    return tok1;
-  } else {
-    return tok2;
-  }
-}
-
-static enum v7_tok punct2(const char **s, const char *src_end, int ch1,
-                          enum v7_tok tok1, int ch2, enum v7_tok tok2,
-                          enum v7_tok tok3) {
-  if ((*s + 2) < src_end && s[0][1] == ch1 && s[0][2] == ch2) {
-    (*s) += 3;
-    return tok2;
-  }
-
-  return punct1(s, src_end, ch1, tok1, tok3);
-}
-
-static enum v7_tok punct3(const char **s, const char *src_end, int ch1,
-                          enum v7_tok tok1, int ch2, enum v7_tok tok2,
-                          enum v7_tok tok3) {
-  (*s)++;
-  if (*s < src_end) {
-    if (**s == ch1) {
-      (*s)++;
-      return tok1;
-    } else if (**s == ch2) {
-      (*s)++;
-      return tok2;
-    }
-  }
-  return tok3;
-}
-
-static void parse_number(const char *s, const char **end, double *num) {
-  *num = cs_strtod(s, (char **) end);
-}
-
-static enum v7_tok parse_str_literal(const char **p, const char *src_end) {
-  const char *s = *p;
-  int quote = '\0';
-
-  if (s < src_end) {
-    quote = *s++;
-  }
-
-  /* Scan string literal, handle escape sequences */
-  for (; s < src_end && *s != '\0' && *s != quote; s++) {
-    if (*s == '\\') {
-      switch (s[1]) {
-        case 'b':
-        case 'f':
-        case 'n':
-        case 'r':
-        case 't':
-        case 'v':
-        case '\\':
-          s++;
-          break;
-        default:
-          if (s[1] == quote) s++;
-          break;
-      }
-    }
-  }
-
-  if (s < src_end && *s == quote) {
-    s++;
-    *p = s;
-    return TOK_STRING_LITERAL;
-  } else {
-    return TOK_END_OF_INPUT;
-  }
-}
-
-/*
- * This function is the heart of the tokenizer.
- * Organized as a giant switch statement.
- *
- * Switch statement is by the first character of the input stream. If first
- * character begins with a letter, it could be either keyword or identifier.
- * get_tok() calls ident() which shifts `s` pointer to the end of the word.
- * Now, tokenizer knows that the word begins at `p` and ends at `s`.
- * It calls function kw() to scan over the keywords that start with `p[0]`
- * letter. Therefore, keyword tokens and keyword strings must be in the
- * same order, to let kw() function work properly.
- * If kw() finds a keyword match, it returns keyword token.
- * Otherwise, it returns TOK_IDENTIFIER.
- * NOTE(lsm): `prev_tok` is a previously parsed token. It is needed for
- * correctly parsing regex literals.
- */
-V7_PRIVATE enum v7_tok get_tok(const char **s, const char *src_end, double *n,
-                               enum v7_tok prev_tok) {
-  const char *p = *s;
-
-  if (p >= src_end) {
-    return TOK_END_OF_INPUT;
-  }
-
-  switch (*p) {
-    /* Letters */
-    case 'a':
-      ident(s, src_end);
-      return TOK_IDENTIFIER;
-    case 'b':
-      ident(s, src_end);
-      return kw(p, *s - p, 1, TOK_BREAK);
-    case 'c':
-      ident(s, src_end);
-      return kw(p, *s - p, 3, TOK_CASE);
-    case 'd':
-      ident(s, src_end);
-      return kw(p, *s - p, 4, TOK_DEBUGGER);
-    case 'e':
-      ident(s, src_end);
-      return kw(p, *s - p, 1, TOK_ELSE);
-    case 'f':
-      ident(s, src_end);
-      return kw(p, *s - p, 4, TOK_FALSE);
-    case 'g':
-    case 'h':
-      ident(s, src_end);
-      return TOK_IDENTIFIER;
-    case 'i':
-      ident(s, src_end);
-      return kw(p, *s - p, 3, TOK_IF);
-    case 'j':
-    case 'k':
-    case 'l':
-    case 'm':
-      ident(s, src_end);
-      return TOK_IDENTIFIER;
-    case 'n':
-      ident(s, src_end);
-      return kw(p, *s - p, 2, TOK_NEW);
-    case 'o':
-    case 'p':
-    case 'q':
-      ident(s, src_end);
-      return TOK_IDENTIFIER;
-    case 'r':
-      ident(s, src_end);
-      return kw(p, *s - p, 1, TOK_RETURN);
-    case 's':
-      ident(s, src_end);
-      return kw(p, *s - p, 1, TOK_SWITCH);
-    case 't':
-      ident(s, src_end);
-      return kw(p, *s - p, 5, TOK_THIS);
-    case 'u':
-      ident(s, src_end);
-      return TOK_IDENTIFIER;
-    case 'v':
-      ident(s, src_end);
-      return kw(p, *s - p, 2, TOK_VAR);
-    case 'w':
-      ident(s, src_end);
-      return kw(p, *s - p, 2, TOK_WHILE);
-    case 'x':
-    case 'y':
-    case 'z':
-      ident(s, src_end);
-      return TOK_IDENTIFIER;
-
-    case '_':
-    case '$':
-    case 'A':
-    case 'B':
-    case 'C':
-    case 'D':
-    case 'E':
-    case 'F':
-    case 'G':
-    case 'H':
-    case 'I':
-    case 'J':
-    case 'K':
-    case 'L':
-    case 'M':
-    case 'N':
-    case 'O':
-    case 'P':
-    case 'Q':
-    case 'R':
-    case 'S':
-    case 'T':
-    case 'U':
-    case 'V':
-    case 'W':
-    case 'X':
-    case 'Y':
-    case 'Z':
-    case '\\': /* Identifier may start with unicode escape sequence */
-      ident(s, src_end);
-      return TOK_IDENTIFIER;
-
-    /* Numbers */
-    case '0':
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':
-      parse_number(p, s, n);
-      return TOK_NUMBER;
-
-    /* String literals */
-    case '\'':
-    case '"':
-      return parse_str_literal(s, src_end);
-
-    /* Punctuators */
-    case '=':
-      return punct2(s, src_end, '=', TOK_EQ, '=', TOK_EQ_EQ, TOK_ASSIGN);
-    case '!':
-      return punct2(s, src_end, '=', TOK_NE, '=', TOK_NE_NE, TOK_NOT);
-
-    case '%':
-      return punct1(s, src_end, '=', TOK_REM_ASSIGN, TOK_REM);
-    case '*':
-      return punct1(s, src_end, '=', TOK_MUL_ASSIGN, TOK_MUL);
-    case '/':
-      /*
-       * TOK_DIV, TOK_DIV_ASSIGN, and TOK_REGEX_LITERAL start with `/` char.
-       * Division can happen after an expression.
-       * In expressions like this:
-       *            a /= b; c /= d;
-       * things between slashes is NOT a regex literal.
-       * The switch below catches all cases where division happens.
-       */
-      switch (prev_tok) {
-        case TOK_CLOSE_CURLY:
-        case TOK_CLOSE_PAREN:
-        case TOK_CLOSE_BRACKET:
-        case TOK_IDENTIFIER:
-        case TOK_NUMBER:
-          return punct1(s, src_end, '=', TOK_DIV_ASSIGN, TOK_DIV);
-        default:
-          /* Not a division - this is a regex. Scan until closing slash */
-          for (p++; p < src_end && *p != '\0' && *p != '\n'; p++) {
-            if (*p == '\\') {
-              /* Skip escape sequence */
-              p++;
-            } else if (*p == '/') {
-              /* This is a closing slash */
-              p++;
-              /* Skip regex flags */
-              while (*p == 'g' || *p == 'i' || *p == 'm') {
-                p++;
-              }
-              *s = p;
-              return TOK_REGEX_LITERAL;
-            }
-          }
-          break;
-      }
-      return punct1(s, src_end, '=', TOK_DIV_ASSIGN, TOK_DIV);
-    case '^':
-      return punct1(s, src_end, '=', TOK_XOR_ASSIGN, TOK_XOR);
-
-    case '+':
-      return punct3(s, src_end, '+', TOK_PLUS_PLUS, '=', TOK_PLUS_ASSIGN,
-                    TOK_PLUS);
-    case '-':
-      return punct3(s, src_end, '-', TOK_MINUS_MINUS, '=', TOK_MINUS_ASSIGN,
-                    TOK_MINUS);
-    case '&':
-      return punct3(s, src_end, '&', TOK_LOGICAL_AND, '=', TOK_AND_ASSIGN,
-                    TOK_AND);
-    case '|':
-      return punct3(s, src_end, '|', TOK_LOGICAL_OR, '=', TOK_OR_ASSIGN,
-                    TOK_OR);
-
-    case '<':
-      if (*s + 1 < src_end && s[0][1] == '=') {
-        (*s) += 2;
-        return TOK_LE;
-      }
-      return punct2(s, src_end, '<', TOK_LSHIFT, '=', TOK_LSHIFT_ASSIGN,
-                    TOK_LT);
-    case '>':
-      if (*s + 1 < src_end && s[0][1] == '=') {
-        (*s) += 2;
-        return TOK_GE;
-      }
-      if (*s + 3 < src_end && s[0][1] == '>' && s[0][2] == '>' &&
-          s[0][3] == '=') {
-        (*s) += 4;
-        return TOK_URSHIFT_ASSIGN;
-      }
-      if (*s + 2 < src_end && s[0][1] == '>' && s[0][2] == '>') {
-        (*s) += 3;
-        return TOK_URSHIFT;
-      }
-      return punct2(s, src_end, '>', TOK_RSHIFT, '=', TOK_RSHIFT_ASSIGN,
-                    TOK_GT);
-
-    case '{':
-      (*s)++;
-      return TOK_OPEN_CURLY;
-    case '}':
-      (*s)++;
-      return TOK_CLOSE_CURLY;
-    case '(':
-      (*s)++;
-      return TOK_OPEN_PAREN;
-    case ')':
-      (*s)++;
-      return TOK_CLOSE_PAREN;
-    case '[':
-      (*s)++;
-      return TOK_OPEN_BRACKET;
-    case ']':
-      (*s)++;
-      return TOK_CLOSE_BRACKET;
-    case '.':
-      switch (*(*s + 1)) {
-        /* Numbers */
-        case '0':
-        case '1':
-        case '2':
-        case '3':
-        case '4':
-        case '5':
-        case '6':
-        case '7':
-        case '8':
-        case '9':
-          parse_number(p, s, n);
-          return TOK_NUMBER;
-      }
-      (*s)++;
-      return TOK_DOT;
-    case ';':
-      (*s)++;
-      return TOK_SEMICOLON;
-    case ':':
-      (*s)++;
-      return TOK_COLON;
-    case '?':
-      (*s)++;
-      return TOK_QUESTION;
-    case '~':
-      (*s)++;
-      return TOK_TILDA;
-    case ',':
-      (*s)++;
-      return TOK_COMMA;
-
-    default: {
-      /* Handle unicode variables */
-      Rune r;
-      if (chartorune(&r, *s) > 1 && isalpharune(r)) {
-        ident(s, src_end);
-        return TOK_IDENTIFIER;
-      }
-      return TOK_END_OF_INPUT;
-    }
-  }
-}
-
-#ifdef TEST_RUN
-int main(void) {
-  const char *src =
-      "for (var fo++ = -1; /= <= 1.17; x<<) { == <<=, 'x')} "
-      "Infinity %=x<<=2";
-  const char *src_end = src + strlen(src);
-  enum v7_tok tok;
-  double num;
-  const char *p = src;
-
-  skip_to_next_tok(&src, src_end);
-  while ((tok = get_tok(&src, src_end, &num)) != TOK_END_OF_INPUT) {
-    printf("%d [%.*s]\n", tok, (int) (src - p), p);
-    skip_to_next_tok(&src, src_end);
-    p = src;
-  }
-  printf("%d [%.*s]\n", tok, (int) (src - p), p);
-
-  return 0;
-}
-#endif
-
-#endif /* V7_NO_COMPILER */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/ast.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/cs_strtod.h" */
-/* Amalgamated: #include "common/mbuf.h" */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/varint.h" */
-/* Amalgamated: #include "v7/src/ast.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "common/str_util.h" */
-
-#if !defined(V7_NO_COMPILER)
-
-#ifdef V7_LARGE_AST
-typedef uint32_t ast_skip_t;
-#else
-typedef uint16_t ast_skip_t;
-#define AST_SKIP_MAX UINT16_MAX
-#endif
-
-#ifndef V7_DISABLE_AST_TAG_NAMES
-#define AST_ENTRY(name, has_varint, has_inlined, num_skips, num_subtrees) \
-  { (name), (has_varint), (has_inlined), (num_skips), (num_subtrees) }
-#else
-#define AST_ENTRY(name, has_varint, has_inlined, num_skips, num_subtrees) \
-  { (has_varint), (has_inlined), (num_skips), (num_subtrees) }
-#endif
-
-/*
- * The structure of AST nodes cannot be described in portable ANSI C,
- * since they are variable length and packed (unaligned).
- *
- * Here each node's body is described with a pseudo-C structure notation.
- * The pseudo type `child` represents a variable length byte sequence
- * representing a fully serialized child node.
- *
- * `child body[]` represents a sequence of such subtrees.
- *
- * Pseudo-labels, such as `end:` represent the targets of skip fields
- * with the same name (e.g. `ast_skip_t end`).
- *
- * Skips allow skipping a subtree or sequence of subtrees.
- *
- * Sequences of subtrees (i.e. `child []`) have to be terminated by a skip:
- * they don't have a termination tag; all nodes whose position is before the
- * skip are part of the sequence.
- *
- * Skips are encoded as network-byte-order 16-bit offsets counted from the
- * first byte of the node body (i.e. not counting the tag itself).
- * This currently limits the the maximum size of a function body to 64k.
- *
- * Notes:
- *
- * - Some nodes contain skips just for performance or because it simplifies
- * the implementation of the interpreter. For example, technically, the FOR
- * node doesn't need the `body` skip in order to be correctly traversed.
- * However, being able to quickly skip the `iter` expression is useful
- * also because it allows the interpreter to avoid traversing the expression
- * subtree without evaluating it, just in order to find the next subtree.
- *
- * - The name `skip` was chosen because `offset` was too overloaded in general
- * and label` is part of our domain model (i.e. JS has a label AST node type).
- *
- *
- * So, each node has a mandatory field: *tag* (see `enum ast_tag`), and a
- * number of optional fields. Whether the node has one or another optional
- * field is determined by the *node descriptor*: `struct ast_node_def`. For
- * each node type (i.e. for each element of `enum ast_tag`) there is a
- * corresponding descriptor: see `ast_node_defs`.
- *
- * Optional fields are:
- *
- * - *varint*: a varint-encoded number. At the moment, this field is only used
- *   together with the next field: inlined data, and a varint number determines
- *   the inlined data length.
- * - *inlined data*: a node-specific data. Size of it is determined by the
- *   previous field: varint.
- * - *skips*: as explained above, these are integer offsets, encoded in
- *   big-endian. The number of skips is determined by the node descriptor
- *   (`struct ast_node_def`). The size of each skip is either 16 or 32 bits,
- *   depending on whether the macro `V7_LARGE_AST` is set. The order of skips
- *   is determined by the `enum ast_which_skip`. See examples below for
- *   clarity.
- * - *subtrees*: child nodes. Some nodes have fixed number of child nodes; in
- *   this case, the descriptor has non-zero field `num_subtrees`.  Otherwise,
- *   `num_subtrees` is zero, and consumer handles child nodes one by one, until
- *   the end of the node is reached (end of the node is determined by the `end`
- *   skip)
- *
- *
- * Examples:
- *
- * Let's start from the very easy example script: "300;"
- *
- * Tree looks as follows:
- *
- *    $ ./v7 -e "300;" -t
- *      SCRIPT
- *        /- [...] -/
- *        NUM 300
- *
- * Binary data is:
- *
- *    $ ./v7 -e "300;" -b | od -A n -t x1
- *    56 07 41 53 54 56 31 30 00 01 00 09 00 00 13 03
- *    33 30 30
- *
- * Let's break it down and examine:
- *
- *    - 56 07 41 53 54 56 31 30 00
- *        Just a format prefix:
- *        Null-terminated string: `"V\007ASTV10"` (see `BIN_AST_SIGNATURE`)
- *    - 01
- *        AST tag: `AST_SCRIPT`. As you see in `ast_node_defs` below, node of
- *        this type has neither *varint* nor *inlined data* fields, but it has
- *        2 skips: `end` and `next`. `end` is a skip to the end of the current
- *        node (`SCRIPT`), and `next` will be explained below.
- *
- *        The size of each skip depends on whether `V7_LARGE_AST` is defined.
- *        If it is, then size is 32 bit, otherwise it's 16 bit. In this
- *        example, we have 16-bit skips.
- *
- *        The order of skips is determined by the `enum ast_which_skip`. If you
- *        check, you'll see that `AST_END_SKIP` is 0, and `AST_VAR_NEXT_SKIP`
- *        is 1. So, `end` skip fill be the first, and `next` will be the second:
- *    - 00 09
- *        `end` skip: 9 bytes. It's the size of the whole `SCRIPT` data. So, if
- *        we have an index of the `ASC_SCRIPT` tag, we can just add this skip
- *        (9) to this index, and therefore skip over the whole node.
- *    - 00 00
- *        `next` skip. `next` actually means "next variable node": since
- *        variables are hoisted in JavaScript, when the interpreter starts
- *        executing a top-level code or any function, it needs to get a list of
- *        all defined variables. The `SCRIPT` node has a "skip" to the first
- *        `var` or `function` declaration, which, in turn, has a "skip" to the
- *        next one, etc. If there is no next `var` declaration, then 0 is
- *        stored.
- *
- *        In our super-simple script, we have no `var` neither `function`
- *        declarations, so, this skip is 0.
- *
- *        Now, the body of our SCRIPT node goes, which contains child nodes:
- *
- *    - 13
- *        AST tag: `AST_NUM`. Look at the `ast_node_defs`, and we'll see that
- *        nodes of this type don't have any skips, but they do have the varint
- *        field and the inlined data. Here we go:
- *    - 03
- *        Varint value: 3
- *    - 33 30 30
- *        UTF-8 string "300"
- *
- * ---------------
- *
- * The next example is a bit more interesting:
- *
- *    var foo,
- *        bar = 1;
- *    foo = 3;
- *    var baz = 4;
- *
- * Tree:
- *
- *    $ ./v7 -e 'var foo, bar=1; foo=3; var baz = 4;' -t
- *    SCRIPT
- *      /- [...] -/
- *      VAR
- *        /- [...] -/
- *        VAR_DECL foo
- *          NOP
- *        VAR_DECL bar
- *          NUM 1
- *      ASSIGN
- *        IDENT foo
- *        NUM 3
- *      VAR
- *        /- [...] -/
- *        VAR_DECL baz
- *          NUM 4
- *
- * Binary:
- *
- *    $ ./v7 -e 'var foo, bar=1; foo=3; var baz = 4;' -b | od -A n -t x1
- *    56 07 41 53 54 56 31 30 00 01 00 2d 00 05 02 00
- *    12 00 1c 03 03 66 6f 6f 00 03 03 62 61 72 13 01
- *    31 07 14 03 66 6f 6f 13 01 33 02 00 0c 00 00 03
- *    03 62 61 7a 13 01 34
- *
- * Break it down:
- *
- *    - 56 07 41 53 54 56 31 30 00
- *        `"V\007ASTV10"`
- *    - 01:       AST tag: `AST_SCRIPT`
- *    - 00 2d:    `end` skip: 0x2d = 45 bytes
- *    - 00 05:    `next` skip: an offset from `AST_SCRIPT` byte to the first
- *                `var` declaration.
- *
- *        Now, body of the SCRIPT node begins, which contains child nodes,
- *        and the first node is the var declaration `var foo, bar=1;`:
- *
- *        SCRIPT node body: {{{
- *    - 02:       AST tag: `AST_VAR`
- *    - 00 12:    `end` skip: 18 bytes from tag byte to the end of current node
- *    - 00 1c:    `next` skip: 28 bytes from tag byte to the next `var` node
- *
- *        The VAR node contains arbitrary number of child nodes, so, consumer
- *        takes advantage of the `end` skip.
- *
- *        VAR node body: {{{
- *    - 03:       AST tag: `AST_VAR_DECL`
- *    - 03:       Varint value: 3 (the length of the inlined data: a variable
- *name)
- *    - 66 6f 6f: UTF-8 string: "foo"
- *    - 00:       AST tag: `AST_NOP`
- *                Since we haven't provided any value to store into `foo`, NOP
- *                without any additional data is stored in AST.
- *
- *    - 03:       AST tag: `AST_VAR_DECL`
- *    - 03:       Varint value: 3 (the length of the inlined data: a variable
- *name)
- *    - 62 61 72: UTF-8 string: "bar"
- *    - 13:       AST tag: `AST_NUM`
- *    - 01:       Varint value: 1
- *    - 31:       UTF-8 string "1"
- *        VAR body end }}}
- *
- *    - 07:       AST tag: `AST_ASSIGN`
- *
- *        The ASSIGN node has fixed number of subrees: 2 (lvalue and rvalue),
- *        so there's no `end` skip.
- *
- *        ASSIGN node body: {{{
- *    - 14:       AST tag: `AST_IDENT`
- *    - 03:       Varint value: 3
- *    - 66 6f 6f: UTF-8 string: "foo"
- *
- *    - 13:       AST tag: `AST_NUM`
- *    - 01:       Varint value: 1
- *    - 33:       UTF-8 string: "3"
- *        ASSIGN body end }}}
- *
- *    - 02:       AST tag: `AST_VAR`
- *    - 00 0c:    `end` skip: 12 bytes from tag byte to the end of current node
- *    - 00 00:    `next` skip: no more `var` nodes
- *
- *        VAR node body: {{{
- *    - 03:       AST tag: `AST_VAR_DECL`
- *    - 03:       Varint value: 3 (the length of the inlined data: a variable
- *name)
- *    - 62 61 7a: UTF-8 string: "baz"
- *    - 13:       AST tag: `AST_NUM`
- *    - 01:       Varint value: 1
- *    - 34:       UTF-8 string "4"
- *        VAR body end }}}
- *        SCRIPT body end }}}
- *
- * --------------------------
- */
-
-const struct ast_node_def ast_node_defs[] = {
-    AST_ENTRY("NOP", 0, 0, 0, 0), /* struct {} */
-
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   ast_skip_t first_var;
-     *   child body[];
-     * end:
-     * }
-     */
-    AST_ENTRY("SCRIPT", 0, 0, 2, 0),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   ast_skip_t next;
-     *   child decls[];
-     * end:
-     * }
-     */
-    AST_ENTRY("VAR", 0, 0, 2, 0),
-    /*
-     * struct {
-     *   varint len;
-     *   char name[len];
-     *   child expr;
-     * }
-     */
-    AST_ENTRY("VAR_DECL", 1, 1, 0, 1),
-    /*
-     * struct {
-     *   varint len;
-     *   char name[len];
-     *   child expr;
-     * }
-     */
-    AST_ENTRY("FUNC_DECL", 1, 1, 0, 1),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   ast_skip_t end_true;
-     *   child cond;
-     *   child iftrue[];
-     * end_true:
-     *   child iffalse[];
-     * end:
-     * }
-     */
-    AST_ENTRY("IF", 0, 0, 2, 1),
-    /*
-     * TODO(mkm) distinguish function expressions
-     * from function statements.
-     * Function statements behave like vars and need a
-     * next field for hoisting.
-     * We can also ignore the name for function expressions
-     * if it's only needed for debugging.
-     *
-     * struct {
-     *   ast_skip_t end;
-     *   ast_skip_t first_var;
-     *   ast_skip_t body;
-     *   child name;
-     *   child params[];
-     * body:
-     *   child body[];
-     * end:
-     * }
-     */
-    AST_ENTRY("FUNC", 0, 0, 3, 1),
-    AST_ENTRY("ASSIGN", 0, 0, 0, 2),         /* struct { child left, right; } */
-    AST_ENTRY("REM_ASSIGN", 0, 0, 0, 2),     /* struct { child left, right; } */
-    AST_ENTRY("MUL_ASSIGN", 0, 0, 0, 2),     /* struct { child left, right; } */
-    AST_ENTRY("DIV_ASSIGN", 0, 0, 0, 2),     /* struct { child left, right; } */
-    AST_ENTRY("XOR_ASSIGN", 0, 0, 0, 2),     /* struct { child left, right; } */
-    AST_ENTRY("PLUS_ASSIGN", 0, 0, 0, 2),    /* struct { child left, right; } */
-    AST_ENTRY("MINUS_ASSIGN", 0, 0, 0, 2),   /* struct { child left, right; } */
-    AST_ENTRY("OR_ASSIGN", 0, 0, 0, 2),      /* struct { child left, right; } */
-    AST_ENTRY("AND_ASSIGN", 0, 0, 0, 2),     /* struct { child left, right; } */
-    AST_ENTRY("LSHIFT_ASSIGN", 0, 0, 0, 2),  /* struct { child left, right; } */
-    AST_ENTRY("RSHIFT_ASSIGN", 0, 0, 0, 2),  /* struct { child left, right; } */
-    AST_ENTRY("URSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
-    AST_ENTRY("NUM", 1, 1, 0, 0),    /* struct { varint len, char s[len]; } */
-    AST_ENTRY("IDENT", 1, 1, 0, 0),  /* struct { varint len, char s[len]; } */
-    AST_ENTRY("STRING", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */
-    AST_ENTRY("REGEX", 1, 1, 0, 0),  /* struct { varint len, char s[len]; } */
-    AST_ENTRY("LABEL", 1, 1, 0, 0),  /* struct { varint len, char s[len]; } */
-
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   child body[];
-     * end:
-     * }
-     */
-    AST_ENTRY("SEQ", 0, 0, 1, 0),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   child cond;
-     *   child body[];
-     * end:
-     * }
-     */
-    AST_ENTRY("WHILE", 0, 0, 1, 1),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   ast_skip_t cond;
-     *   child body[];
-     * cond:
-     *   child cond;
-     * end:
-     * }
-     */
-    AST_ENTRY("DOWHILE", 0, 0, 2, 0),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   ast_skip_t body;
-     *   child init;
-     *   child cond;
-     *   child iter;
-     * body:
-     *   child body[];
-     * end:
-     * }
-     */
-    AST_ENTRY("FOR", 0, 0, 2, 3),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   ast_skip_t dummy; // allows to quickly promote a for to a for in
-     *   child var;
-     *   child expr;
-     *   child dummy;
-     *   child body[];
-     * end:
-     * }
-     */
-    AST_ENTRY("FOR_IN", 0, 0, 2, 3),
-    AST_ENTRY("COND", 0, 0, 0, 3), /* struct { child cond, iftrue, iffalse; } */
-    AST_ENTRY("DEBUGGER", 0, 0, 0, 0), /* struct {} */
-    AST_ENTRY("BREAK", 0, 0, 0, 0),    /* struct {} */
-
-    /*
-     * struct {
-     *   child label; // TODO(mkm): inline
-     * }
-     */
-    AST_ENTRY("LAB_BREAK", 0, 0, 0, 1),
-    AST_ENTRY("CONTINUE", 0, 0, 0, 0), /* struct {} */
-
-    /*
-     * struct {
-     *   child label; // TODO(mkm): inline
-     * }
-     */
-    AST_ENTRY("LAB_CONTINUE", 0, 0, 0, 1),
-    AST_ENTRY("RETURN", 0, 0, 0, 0),     /* struct {} */
-    AST_ENTRY("VAL_RETURN", 0, 0, 0, 1), /* struct { child expr; } */
-    AST_ENTRY("THROW", 0, 0, 0, 1),      /* struct { child expr; } */
-
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   ast_skip_t catch;
-     *   ast_skip_t finally;
-     *   child try[];
-     * catch:
-     *   child var; // TODO(mkm): inline
-     *   child catch[];
-     * finally:
-     *   child finally[];
-     * end:
-     * }
-     */
-    AST_ENTRY("TRY", 0, 0, 3, 1),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   ast_skip_t def;
-     *   child expr;
-     *   child cases[];
-     * def:
-     *   child default?; // optional
-     * end:
-     * }
-     */
-    AST_ENTRY("SWITCH", 0, 0, 2, 1),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   child val;
-     *   child stmts[];
-     * end:
-     * }
-     */
-    AST_ENTRY("CASE", 0, 0, 1, 1),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   child stmts[];
-     * end:
-     * }
-     */
-    AST_ENTRY("DEFAULT", 0, 0, 1, 0),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   child expr;
-     *   child body[];
-     * end:
-     * }
-     */
-    AST_ENTRY("WITH", 0, 0, 1, 1),
-    AST_ENTRY("LOG_OR", 0, 0, 0, 2),      /* struct { child left, right; } */
-    AST_ENTRY("LOG_AND", 0, 0, 0, 2),     /* struct { child left, right; } */
-    AST_ENTRY("OR", 0, 0, 0, 2),          /* struct { child left, right; } */
-    AST_ENTRY("XOR", 0, 0, 0, 2),         /* struct { child left, right; } */
-    AST_ENTRY("AND", 0, 0, 0, 2),         /* struct { child left, right; } */
-    AST_ENTRY("EQ", 0, 0, 0, 2),          /* struct { child left, right; } */
-    AST_ENTRY("EQ_EQ", 0, 0, 0, 2),       /* struct { child left, right; } */
-    AST_ENTRY("NE", 0, 0, 0, 2),          /* struct { child left, right; } */
-    AST_ENTRY("NE_NE", 0, 0, 0, 2),       /* struct { child left, right; } */
-    AST_ENTRY("LE", 0, 0, 0, 2),          /* struct { child left, right; } */
-    AST_ENTRY("LT", 0, 0, 0, 2),          /* struct { child left, right; } */
-    AST_ENTRY("GE", 0, 0, 0, 2),          /* struct { child left, right; } */
-    AST_ENTRY("GT", 0, 0, 0, 2),          /* struct { child left, right; } */
-    AST_ENTRY("IN", 0, 0, 0, 2),          /* struct { child left, right; } */
-    AST_ENTRY("INSTANCEOF", 0, 0, 0, 2),  /* struct { child left, right; } */
-    AST_ENTRY("LSHIFT", 0, 0, 0, 2),      /* struct { child left, right; } */
-    AST_ENTRY("RSHIFT", 0, 0, 0, 2),      /* struct { child left, right; } */
-    AST_ENTRY("URSHIFT", 0, 0, 0, 2),     /* struct { child left, right; } */
-    AST_ENTRY("ADD", 0, 0, 0, 2),         /* struct { child left, right; } */
-    AST_ENTRY("SUB", 0, 0, 0, 2),         /* struct { child left, right; } */
-    AST_ENTRY("REM", 0, 0, 0, 2),         /* struct { child left, right; } */
-    AST_ENTRY("MUL", 0, 0, 0, 2),         /* struct { child left, right; } */
-    AST_ENTRY("DIV", 0, 0, 0, 2),         /* struct { child left, right; } */
-    AST_ENTRY("POS", 0, 0, 0, 1),         /* struct { child expr; } */
-    AST_ENTRY("NEG", 0, 0, 0, 1),         /* struct { child expr; } */
-    AST_ENTRY("NOT", 0, 0, 0, 1),         /* struct { child expr; } */
-    AST_ENTRY("LOGICAL_NOT", 0, 0, 0, 1), /* struct { child expr; } */
-    AST_ENTRY("VOID", 0, 0, 0, 1),        /* struct { child expr; } */
-    AST_ENTRY("DELETE", 0, 0, 0, 1),      /* struct { child expr; } */
-    AST_ENTRY("TYPEOF", 0, 0, 0, 1),      /* struct { child expr; } */
-    AST_ENTRY("PREINC", 0, 0, 0, 1),      /* struct { child expr; } */
-    AST_ENTRY("PREDEC", 0, 0, 0, 1),      /* struct { child expr; } */
-    AST_ENTRY("POSTINC", 0, 0, 0, 1),     /* struct { child expr; } */
-    AST_ENTRY("POSTDEC", 0, 0, 0, 1),     /* struct { child expr; } */
-
-    /*
-     * struct {
-     *   varint len;
-     *   char ident[len];
-     *   child expr;
-     * }
-     */
-    AST_ENTRY("MEMBER", 1, 1, 0, 1),
-    /*
-     * struct {
-     *   child expr;
-     *   child index;
-     * }
-     */
-    AST_ENTRY("INDEX", 0, 0, 0, 2),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   child expr;
-     *   child args[];
-     * end:
-     * }
-     */
-    AST_ENTRY("CALL", 0, 0, 1, 1),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   child expr;
-     *   child args[];
-     * end:
-     * }
-     */
-    AST_ENTRY("NEW", 0, 0, 1, 1),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   child elements[];
-     * end:
-     * }
-     */
-    AST_ENTRY("ARRAY", 0, 0, 1, 0),
-    /*
-     * struct {
-     *   ast_skip_t end;
-     *   child props[];
-     * end:
-     * }
-     */
-    AST_ENTRY("OBJECT", 0, 0, 1, 0),
-    /*
-     * struct {
-     *   varint len;
-     *   char name[len];
-     *   child expr;
-     * }
-     */
-    AST_ENTRY("PROP", 1, 1, 0, 1),
-    /*
-     * struct {
-     *   child func;
-     * }
-     */
-    AST_ENTRY("GETTER", 0, 0, 0, 1),
-    /*
-     * struct {
-     *   child func;
-     * end:
-     * }
-     */
-    AST_ENTRY("SETTER", 0, 0, 0, 1),
-    AST_ENTRY("THIS", 0, 0, 0, 0),       /* struct {} */
-    AST_ENTRY("TRUE", 0, 0, 0, 0),       /* struct {} */
-    AST_ENTRY("FALSE", 0, 0, 0, 0),      /* struct {} */
-    AST_ENTRY("NULL", 0, 0, 0, 0),       /* struct {} */
-    AST_ENTRY("UNDEF", 0, 0, 0, 0),      /* struct {} */
-    AST_ENTRY("USE_STRICT", 0, 0, 0, 0), /* struct {} */
-};
-
-/*
- * A flag which is used to mark node's tag byte if the node has line number
- * data encoded (varint after skips). See `ast_get_line_no()`.
- */
-#define AST_TAG_LINENO_PRESENT 0x80
-
-V7_STATIC_ASSERT(AST_MAX_TAG < 256, ast_tag_should_fit_in_char);
-V7_STATIC_ASSERT(AST_MAX_TAG == ARRAY_SIZE(ast_node_defs), bad_node_defs);
-V7_STATIC_ASSERT(AST_MAX_TAG <= AST_TAG_LINENO_PRESENT, bad_AST_LINE_NO);
-
-#if V7_ENABLE_FOOTPRINT_REPORT
-const size_t ast_node_defs_size = sizeof(ast_node_defs);
-const size_t ast_node_defs_count = ARRAY_SIZE(ast_node_defs);
-#endif
-
-/*
- * Converts a given byte `t` (which should be read from the AST data buffer)
- * into `enum ast_tag`. This function is needed because tag might be marked
- * with the `AST_TAG_LINENO_PRESENT` flag; the returned tag is always unmarked,
- * and if the flag was indeed set, `lineno_present` is set to 1; otherwise
- * it is set to 0.
- *
- * `lineno_present` is allowed to be NULL, if the caller doesn't care of the
- * line number presence.
- */
-static enum ast_tag uint8_to_tag(uint8_t t, uint8_t *lineno_present) {
-  if (t & AST_TAG_LINENO_PRESENT) {
-    t &= ~AST_TAG_LINENO_PRESENT;
-    if (lineno_present != NULL) {
-      *lineno_present = 1;
-    }
-  } else if (lineno_present != NULL) {
-    *lineno_present = 0;
-  }
-  return (enum ast_tag) t;
-}
-
-V7_PRIVATE ast_off_t
-ast_insert_node(struct ast *a, ast_off_t pos, enum ast_tag tag) {
-  uint8_t t = (uint8_t) tag;
-  const struct ast_node_def *d = &ast_node_defs[tag];
-  ast_off_t cur = pos;
-
-  assert(tag < AST_MAX_TAG);
-
-  mbuf_insert(&a->mbuf, cur, (char *) &t, sizeof(t));
-  cur += sizeof(t);
-
-  mbuf_insert(&a->mbuf, cur, NULL, sizeof(ast_skip_t) * d->num_skips);
-  cur += sizeof(ast_skip_t) * d->num_skips;
-
-  if (d->num_skips) {
-    ast_set_skip(a, pos + 1, AST_END_SKIP);
-  }
-
-  return pos + 1;
-}
-
-V7_PRIVATE void ast_modify_tag(struct ast *a, ast_off_t tag_off,
-                               enum ast_tag tag) {
-  a->mbuf.buf[tag_off] = tag | (a->mbuf.buf[tag_off] & 0x80);
-}
-
-#ifndef V7_DISABLE_LINE_NUMBERS
-V7_PRIVATE void ast_add_line_no(struct ast *a, ast_off_t tag_off, int line_no) {
-  ast_off_t ln_off = tag_off + 1 /* tag byte */;
-  int llen = calc_llen(line_no);
-
-  ast_move_to_inlined_data(a, &ln_off);
-  mbuf_insert(&a->mbuf, ln_off, NULL, llen);
-  encode_varint(line_no, (unsigned char *) (a->mbuf.buf + ln_off));
-
-  assert(a->mbuf.buf[tag_off] < AST_MAX_TAG);
-  a->mbuf.buf[tag_off] |= AST_TAG_LINENO_PRESENT;
-}
-#endif
-
-V7_PRIVATE ast_off_t
-ast_set_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip) {
-  return ast_modify_skip(a, pos, a->mbuf.len, skip);
-}
-
-V7_PRIVATE ast_off_t ast_modify_skip(struct ast *a, ast_off_t pos,
-                                     ast_off_t where,
-                                     enum ast_which_skip skip) {
-  uint8_t *p = (uint8_t *) a->mbuf.buf + pos + skip * sizeof(ast_skip_t);
-  ast_skip_t delta = where - pos;
-#ifndef NDEBUG
-  enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + pos - 1), NULL);
-  const struct ast_node_def *def = &ast_node_defs[tag];
-#endif
-  assert(pos <= where);
-
-#ifndef V7_LARGE_AST
-  /* the value of delta overflowed, therefore the ast is not useable */
-  if (where - pos > AST_SKIP_MAX) {
-    a->has_overflow = 1;
-  }
-#endif
-
-  /* assertion, to be optimizable out */
-  assert((int) skip < def->num_skips);
-
-#ifdef V7_LARGE_AST
-  p[0] = delta >> 24;
-  p[1] = delta >> 16 & 0xff;
-  p[2] = delta >> 8 & 0xff;
-  p[3] = delta & 0xff;
-#else
-  p[0] = delta >> 8;
-  p[1] = delta & 0xff;
-#endif
-  return where;
-}
-
-V7_PRIVATE ast_off_t
-ast_get_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip) {
-  uint8_t *p;
-  assert(pos + skip * sizeof(ast_skip_t) < a->mbuf.len);
-
-  p = (uint8_t *) a->mbuf.buf + pos + skip * sizeof(ast_skip_t);
-#ifdef V7_LARGE_AST
-  return pos + (p[3] | p[2] << 8 | p[1] << 16 | p[0] << 24);
-#else
-  return pos + (p[1] | p[0] << 8);
-#endif
-}
-
-V7_PRIVATE enum ast_tag ast_fetch_tag(struct ast *a, ast_off_t *ppos) {
-  enum ast_tag ret;
-  assert(*ppos < a->mbuf.len);
-
-  ret = uint8_to_tag(*(a->mbuf.buf + (*ppos)++), NULL);
-
-  return ret;
-}
-
-V7_PRIVATE void ast_move_to_children(struct ast *a, ast_off_t *ppos) {
-  enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + *ppos - 1), NULL);
-  const struct ast_node_def *def = &ast_node_defs[tag];
-  assert(*ppos - 1 < a->mbuf.len);
-
-  ast_move_to_inlined_data(a, ppos);
-
-  /* skip varint + inline data, if present */
-  if (def->has_varint) {
-    int llen;
-    size_t slen = decode_varint((unsigned char *) a->mbuf.buf + *ppos, &llen);
-    *ppos += llen;
-    if (def->has_inlined) {
-      *ppos += slen;
-    }
-  }
-}
-
-V7_PRIVATE ast_off_t ast_insert_inlined_node(struct ast *a, ast_off_t pos,
-                                             enum ast_tag tag, const char *name,
-                                             size_t len) {
-  const struct ast_node_def *d = &ast_node_defs[tag];
-
-  ast_off_t offset = ast_insert_node(a, pos, tag);
-
-  assert(d->has_inlined);
-
-  embed_string(&a->mbuf, offset + sizeof(ast_skip_t) * d->num_skips, name, len,
-               EMBSTR_UNESCAPE);
-
-  return offset;
-}
-
-V7_PRIVATE int ast_get_line_no(struct ast *a, ast_off_t pos) {
-  /*
-   * by default we'll return 0, meaning that the AST node does not contain line
-   * number data
-   */
-  int ret = 0;
-
-#ifndef V7_DISABLE_LINE_NUMBERS
-  uint8_t lineno_present;
-  enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + pos - 1), &lineno_present);
-
-  if (lineno_present) {
-    /* line number is present, so, let's decode it */
-    int llen;
-
-    /* skip skips */
-    pos += ast_node_defs[tag].num_skips * sizeof(ast_skip_t);
-
-    /* get line number */
-    ret = decode_varint((unsigned char *) a->mbuf.buf + pos, &llen);
-  }
-#else
-  (void) a;
-  (void) pos;
-#endif
-
-  return ret;
-}
-
-V7_PRIVATE void ast_move_to_inlined_data(struct ast *a, ast_off_t *ppos) {
-  uint8_t lineno_present = 0;
-  enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + *ppos - 1), &lineno_present);
-  const struct ast_node_def *def = &ast_node_defs[tag];
-  assert(*ppos - 1 < a->mbuf.len);
-
-  /* skip skips */
-  *ppos += def->num_skips * sizeof(ast_skip_t);
-
-  /* skip line_no, if present */
-  if (lineno_present) {
-    int llen;
-    int line_no = decode_varint((unsigned char *) a->mbuf.buf + *ppos, &llen);
-    *ppos += llen;
-
-    (void) line_no;
-  }
-}
-
-V7_PRIVATE char *ast_get_inlined_data(struct ast *a, ast_off_t pos, size_t *n) {
-  int llen;
-  assert(pos < a->mbuf.len);
-
-  ast_move_to_inlined_data(a, &pos);
-
-  *n = decode_varint((unsigned char *) a->mbuf.buf + pos, &llen);
-  return a->mbuf.buf + pos + llen;
-}
-
-V7_PRIVATE double ast_get_num(struct ast *a, ast_off_t pos) {
-  double ret;
-  char *str;
-  size_t str_len;
-  char buf[12];
-  char *p = buf;
-  str = ast_get_inlined_data(a, pos, &str_len);
-  assert(str + str_len <= a->mbuf.buf + a->mbuf.len);
-
-  if (str_len > sizeof(buf) - 1) {
-    p = (char *) malloc(str_len + 1);
-  }
-  strncpy(p, str, str_len);
-  p[str_len] = '\0';
-  ret = cs_strtod(p, NULL);
-  if (p != buf) free(p);
-  return ret;
-}
-
-#ifndef NO_LIBC
-static void comment_at_depth(FILE *fp, const char *fmt, int depth, ...) {
-  int i;
-  STATIC char buf[256];
-  va_list ap;
-  va_start(ap, depth);
-
-  c_vsnprintf(buf, sizeof(buf), fmt, ap);
-
-  for (i = 0; i < depth; i++) {
-    fprintf(fp, "  ");
-  }
-  fprintf(fp, "/* [%s] */\n", buf);
-}
-#endif
-
-V7_PRIVATE void ast_skip_tree(struct ast *a, ast_off_t *ppos) {
-  enum ast_tag tag = ast_fetch_tag(a, ppos);
-  const struct ast_node_def *def = &ast_node_defs[tag];
-  ast_off_t skips = *ppos;
-  int i;
-  ast_move_to_children(a, ppos);
-
-  for (i = 0; i < def->num_subtrees; i++) {
-    ast_skip_tree(a, ppos);
-  }
-
-  if (def->num_skips > AST_END_SKIP) {
-    ast_off_t end = ast_get_skip(a, skips, AST_END_SKIP);
-
-    while (*ppos < end) {
-      ast_skip_tree(a, ppos);
-    }
-  }
-}
-
-#ifndef NO_LIBC
-V7_PRIVATE void ast_dump_tree(FILE *fp, struct ast *a, ast_off_t *ppos,
-                              int depth) {
-  enum ast_tag tag = ast_fetch_tag(a, ppos);
-  const struct ast_node_def *def = &ast_node_defs[tag];
-  ast_off_t skips = *ppos;
-  size_t slen;
-  int i, llen;
-
-  for (i = 0; i < depth; i++) {
-    fprintf(fp, "  ");
-  }
-
-#ifndef V7_DISABLE_AST_TAG_NAMES
-  fprintf(fp, "%s", def->name);
-#else
-  fprintf(fp, "TAG_%d", tag);
-#endif
-
-  if (def->has_inlined) {
-    ast_off_t pos_tmp = *ppos;
-    ast_move_to_inlined_data(a, &pos_tmp);
-
-    slen = decode_varint((unsigned char *) a->mbuf.buf + pos_tmp, &llen);
-    fprintf(fp, " %.*s\n", (int) slen, a->mbuf.buf + pos_tmp + llen);
-  } else {
-    fprintf(fp, "\n");
-  }
-
-  ast_move_to_children(a, ppos);
-
-  for (i = 0; i < def->num_subtrees; i++) {
-    ast_dump_tree(fp, a, ppos, depth + 1);
-  }
-
-  if (ast_node_defs[tag].num_skips) {
-    /*
-     * first skip always encodes end of the last children sequence.
-     * so unless we care how the subtree sequences are grouped together
-     * (and we currently don't) we can just read until the end of that skip.
-     */
-    ast_off_t end = ast_get_skip(a, skips, AST_END_SKIP);
-
-    comment_at_depth(fp, "...", depth + 1);
-    while (*ppos < end) {
-      int s;
-      for (s = ast_node_defs[tag].num_skips - 1; s > 0; s--) {
-        if (*ppos == ast_get_skip(a, skips, (enum ast_which_skip) s)) {
-          comment_at_depth(fp, "%d ->", depth + 1, s);
-          break;
-        }
-      }
-      ast_dump_tree(fp, a, ppos, depth + 1);
-    }
-  }
-}
-#endif
-
-V7_PRIVATE void ast_init(struct ast *ast, size_t len) {
-  mbuf_init(&ast->mbuf, len);
-  ast->refcnt = 0;
-  ast->has_overflow = 0;
-}
-
-V7_PRIVATE void ast_optimize(struct ast *ast) {
-  /*
-   * leave one trailing byte so that literals can be
-   * null terminated on the fly.
-   */
-  mbuf_resize(&ast->mbuf, ast->mbuf.len + 1);
-}
-
-V7_PRIVATE void ast_free(struct ast *ast) {
-  mbuf_free(&ast->mbuf);
-  ast->refcnt = 0;
-  ast->has_overflow = 0;
-}
-
-V7_PRIVATE void release_ast(struct v7 *v7, struct ast *a) {
-  (void) v7;
-
-  if (a->refcnt != 0) a->refcnt--;
-
-  if (a->refcnt == 0) {
-#if V7_ENABLE__Memory__stats
-    v7->function_arena_ast_size -= a->mbuf.size;
-#endif
-    ast_free(a);
-    free(a);
-  }
-}
-
-#endif /* V7_NO_COMPILER */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/bcode.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/bcode.h" */
-/* Amalgamated: #include "v7/src/varint.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/gc.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/regexp.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-/* Amalgamated: #include "v7/src/shdata.h" */
-
-/*
- * TODO(dfrank): implement `bcode_serialize_*` more generically, so that they
- * can write to buffer instead of a `FILE`. Then, remove a need for mmap here.
- */
-#if CS_PLATFORM == CS_P_UNIX
-#include <sys/mman.h>
-#endif
-
-#if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE)
-/* clang-format off */
-static const char *op_names[] = {
-  "DROP",
-  "DUP",
-  "2DUP",
-  "SWAP",
-  "STASH",
-  "UNSTASH",
-  "SWAP_DROP",
-  "PUSH_UNDEFINED",
-  "PUSH_NULL",
-  "PUSH_THIS",
-  "PUSH_TRUE",
-  "PUSH_FALSE",
-  "PUSH_ZERO",
-  "PUSH_ONE",
-  "PUSH_LIT",
-  "NOT",
-  "LOGICAL_NOT",
-  "NEG",
-  "POS",
-  "ADD",
-  "SUB",
-  "REM",
-  "MUL",
-  "DIV",
-  "LSHIFT",
-  "RSHIFT",
-  "URSHIFT",
-  "OR",
-  "XOR",
-  "AND",
-  "EQ_EQ",
-  "EQ",
-  "NE",
-  "NE_NE",
-  "LT",
-  "LE",
-  "GT",
-  "GE",
-  "INSTANCEOF",
-  "TYPEOF",
-  "IN",
-  "GET",
-  "SET",
-  "SET_VAR",
-  "GET_VAR",
-  "SAFE_GET_VAR",
-  "JMP",
-  "JMP_TRUE",
-  "JMP_FALSE",
-  "JMP_TRUE_DROP",
-  "JMP_IF_CONTINUE",
-  "CREATE_OBJ",
-  "CREATE_ARR",
-  "PUSH_PROP_ITER_CTX",
-  "NEXT_PROP",
-  "FUNC_LIT",
-  "CALL",
-  "NEW",
-  "CHECK_CALL",
-  "RET",
-  "DELETE",
-  "DELETE_VAR",
-  "TRY_PUSH_CATCH",
-  "TRY_PUSH_FINALLY",
-  "TRY_PUSH_LOOP",
-  "TRY_PUSH_SWITCH",
-  "TRY_POP",
-  "AFTER_FINALLY",
-  "THROW",
-  "BREAK",
-  "CONTINUE",
-  "ENTER_CATCH",
-  "EXIT_CATCH",
-};
-/* clang-format on */
-
-V7_STATIC_ASSERT(OP_MAX == ARRAY_SIZE(op_names), bad_op_names);
-V7_STATIC_ASSERT(OP_MAX <= _OP_LINE_NO, bad_OP_LINE_NO);
-#endif
-
-static void bcode_serialize_func(struct v7 *v7, struct bcode *bcode, FILE *out);
-
-static size_t bcode_ops_append(struct bcode_builder *bbuilder, const void *buf,
-                               size_t len) {
-  size_t ret;
-#if V7_ENABLE__Memory__stats
-  bbuilder->v7->bcode_ops_size -= bbuilder->ops.len;
-#endif
-  ret = mbuf_append(&bbuilder->ops, buf, len);
-#if V7_ENABLE__Memory__stats
-  bbuilder->v7->bcode_ops_size += bbuilder->ops.len;
-#endif
-  return ret;
-}
-
-/*
- * Initialize bcode builder. The `bcode` should be already initialized by the
- * caller, and should be empty (i.e. should not own any ops, literals, etc)
- *
- * TODO(dfrank) : probably make `bcode_builder_init()` to initialize `bcode`
- * as well
- */
-V7_PRIVATE void bcode_builder_init(struct v7 *v7,
-                                   struct bcode_builder *bbuilder,
-                                   struct bcode *bcode) {
-  memset(bbuilder, 0x00, sizeof(*bbuilder));
-  bbuilder->v7 = v7;
-  bbuilder->bcode = bcode;
-
-  mbuf_init(&bbuilder->ops, 0);
-  mbuf_init(&bbuilder->lit, 0);
-}
-
-/*
- * Finalize bcode builder: propagate data to the bcode and transfer the
- * ownership from builder to bcode
- */
-V7_PRIVATE void bcode_builder_finalize(struct bcode_builder *bbuilder) {
-  mbuf_trim(&bbuilder->ops);
-  bbuilder->bcode->ops.p = bbuilder->ops.buf;
-  bbuilder->bcode->ops.len = bbuilder->ops.len;
-  mbuf_init(&bbuilder->ops, 0);
-
-  mbuf_trim(&bbuilder->lit);
-  bbuilder->bcode->lit.p = bbuilder->lit.buf;
-  bbuilder->bcode->lit.len = bbuilder->lit.len;
-  mbuf_init(&bbuilder->lit, 0);
-
-  memset(bbuilder, 0x00, sizeof(*bbuilder));
-}
-
-#if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE)
-V7_PRIVATE void dump_op(struct v7 *v7, FILE *f, struct bcode *bcode,
-                        char **ops) {
-  char *p = *ops;
-
-  assert(*p < OP_MAX);
-  fprintf(f, "%zu: %s", (size_t)(p - bcode->ops.p), op_names[(uint8_t) *p]);
-  switch (*p) {
-    case OP_PUSH_LIT:
-    case OP_SAFE_GET_VAR:
-    case OP_GET_VAR:
-    case OP_SET_VAR: {
-      size_t idx = bcode_get_varint(&p);
-      fprintf(f, "(%lu): ", (unsigned long) idx);
-      v7_fprint(f, v7, ((val_t *) bcode->lit.p)[idx]);
-      break;
-    }
-    case OP_CALL:
-    case OP_NEW:
-      p++;
-      fprintf(f, "(%d)", *p);
-      break;
-    case OP_JMP:
-    case OP_JMP_FALSE:
-    case OP_JMP_TRUE:
-    case OP_JMP_TRUE_DROP:
-    case OP_JMP_IF_CONTINUE:
-    case OP_TRY_PUSH_CATCH:
-    case OP_TRY_PUSH_FINALLY:
-    case OP_TRY_PUSH_LOOP:
-    case OP_TRY_PUSH_SWITCH: {
-      bcode_off_t target;
-      p++;
-      memcpy(&target, p, sizeof(target));
-      fprintf(f, "(%lu)", (unsigned long) target);
-      p += sizeof(target) - 1;
-      break;
-    }
-    default:
-      break;
-  }
-  fprintf(f, "\n");
-  *ops = p;
-}
-#endif
-
-#ifdef V7_BCODE_DUMP
-V7_PRIVATE void dump_bcode(struct v7 *v7, FILE *f, struct bcode *bcode) {
-  char *p = bcode_end_names(bcode->ops.p, bcode->names_cnt);
-  char *end = bcode->ops.p + bcode->ops.len;
-  for (; p < end; p++) {
-    dump_op(v7, f, bcode, &p);
-  }
-}
-#endif
-
-V7_PRIVATE void bcode_init(struct bcode *bcode, uint8_t strict_mode,
-                           void *filename, uint8_t filename_in_rom) {
-  memset(bcode, 0x00, sizeof(*bcode));
-  bcode->refcnt = 0;
-  bcode->args_cnt = 0;
-  bcode->strict_mode = strict_mode;
-#ifndef V7_DISABLE_FILENAMES
-  bcode->filename = filename;
-  bcode->filename_in_rom = filename_in_rom;
-#else
-  (void) filename;
-  (void) filename_in_rom;
-#endif
-}
-
-V7_PRIVATE void bcode_free(struct v7 *v7, struct bcode *bcode) {
-  (void) v7;
-#if V7_ENABLE__Memory__stats
-  if (!bcode->ops_in_rom) {
-    v7->bcode_ops_size -= bcode->ops.len;
-  }
-
-  v7->bcode_lit_total_size -= bcode->lit.len;
-  if (bcode->deserialized) {
-    v7->bcode_lit_deser_size -= bcode->lit.len;
-  }
-#endif
-
-  if (!bcode->ops_in_rom) {
-    free(bcode->ops.p);
-  }
-  memset(&bcode->ops, 0x00, sizeof(bcode->ops));
-
-  free(bcode->lit.p);
-  memset(&bcode->lit, 0x00, sizeof(bcode->lit));
-
-#ifndef V7_DISABLE_FILENAMES
-  if (!bcode->filename_in_rom && bcode->filename != NULL) {
-    shdata_release((struct shdata *) bcode->filename);
-    bcode->filename = NULL;
-  }
-#endif
-
-  bcode->refcnt = 0;
-}
-
-V7_PRIVATE void retain_bcode(struct v7 *v7, struct bcode *b) {
-  (void) v7;
-  if (!b->frozen) {
-    b->refcnt++;
-  }
-}
-
-V7_PRIVATE void release_bcode(struct v7 *v7, struct bcode *b) {
-  (void) v7;
-  if (b->frozen) return;
-
-  assert(b->refcnt > 0);
-  if (b->refcnt != 0) b->refcnt--;
-
-  if (b->refcnt == 0) {
-    bcode_free(v7, b);
-    free(b);
-  }
-}
-
-#ifndef V7_DISABLE_FILENAMES
-V7_PRIVATE const char *bcode_get_filename(struct bcode *bcode) {
-  const char *ret = NULL;
-  if (bcode->filename_in_rom) {
-    ret = (const char *) bcode->filename;
-  } else if (bcode->filename != NULL) {
-    ret = (const char *) shdata_get_payload((struct shdata *) bcode->filename);
-  }
-  return ret;
-}
-#endif
-
-V7_PRIVATE void bcode_copy_filename_from(struct bcode *dst, struct bcode *src) {
-#ifndef V7_DISABLE_FILENAMES
-  dst->filename_in_rom = src->filename_in_rom;
-  dst->filename = src->filename;
-
-  if (src->filename != NULL && !src->filename_in_rom) {
-    shdata_retain((struct shdata *) dst->filename);
-  }
-#else
-  (void) dst;
-  (void) src;
-#endif
-}
-
-V7_PRIVATE void bcode_op(struct bcode_builder *bbuilder, uint8_t op) {
-  bcode_ops_append(bbuilder, &op, 1);
-}
-
-#ifndef V7_DISABLE_LINE_NUMBERS
-V7_PRIVATE void bcode_append_lineno(struct bcode_builder *bbuilder,
-                                    int line_no) {
-  int offset = bbuilder->ops.len;
-  bcode_add_varint(bbuilder, (line_no << 1) | 1);
-  bbuilder->ops.buf[offset] = msb_lsb_swap(bbuilder->ops.buf[offset]);
-  assert(bbuilder->ops.buf[offset] & _OP_LINE_NO);
-}
-#endif
-
-/*
- * Appends varint-encoded integer to the `ops` mbuf
- */
-V7_PRIVATE void bcode_add_varint(struct bcode_builder *bbuilder, size_t value) {
-  int k = calc_llen(value); /* Calculate how many bytes length takes */
-  int offset = bbuilder->ops.len;
-
-  /* Allocate buffer */
-  bcode_ops_append(bbuilder, NULL, k);
-
-  /* Write value */
-  encode_varint(value, (unsigned char *) bbuilder->ops.buf + offset);
-}
-
-V7_PRIVATE size_t bcode_get_varint(char **ops) {
-  size_t ret = 0;
-  int len = 0;
-  (*ops)++;
-  ret = decode_varint((unsigned char *) *ops, &len);
-  *ops += len - 1;
-  return ret;
-}
-
-static int bcode_is_inline_string(struct v7 *v7, val_t val) {
-  uint64_t tag = val & V7_TAG_MASK;
-  if (v7->is_precompiling && v7_is_string(val)) {
-    return 1;
-  }
-  return tag == V7_TAG_STRING_I || tag == V7_TAG_STRING_5;
-}
-
-static int bcode_is_inline_func(struct v7 *v7, val_t val) {
-  return (v7->is_precompiling && is_js_function(val));
-}
-
-static int bcode_is_inline_regexp(struct v7 *v7, val_t val) {
-  return (v7->is_precompiling && v7_is_regexp(v7, val));
-}
-
-V7_PRIVATE lit_t bcode_add_lit(struct bcode_builder *bbuilder, val_t val) {
-  lit_t lit;
-  memset(&lit, 0, sizeof(lit));
-
-  if (bcode_is_inline_string(bbuilder->v7, val) ||
-      bcode_is_inline_func(bbuilder->v7, val) || v7_is_number(val) ||
-      bcode_is_inline_regexp(bbuilder->v7, val)) {
-    /* literal should be inlined (it's `bcode_op_lit()` who does this) */
-    lit.mode = LIT_MODE__INLINED;
-    lit.v.inline_val = val;
-  } else {
-    /* literal will now be added to the literal table */
-    lit.mode = LIT_MODE__TABLE;
-    lit.v.lit_idx = bbuilder->lit.len / sizeof(val);
-
-#if V7_ENABLE__Memory__stats
-    bbuilder->v7->bcode_lit_total_size -= bbuilder->lit.len;
-    if (bbuilder->bcode->deserialized) {
-      bbuilder->v7->bcode_lit_deser_size -= bbuilder->lit.len;
-    }
-#endif
-
-    mbuf_append(&bbuilder->lit, &val, sizeof(val));
-
-    /*
-     * immediately propagate current lit buffer to the bcode, so that GC will
-     * be aware of it
-     */
-    bbuilder->bcode->lit.p = bbuilder->lit.buf;
-    bbuilder->bcode->lit.len = bbuilder->lit.len;
-
-#if V7_ENABLE__Memory__stats
-    bbuilder->v7->bcode_lit_total_size += bbuilder->lit.len;
-    if (bbuilder->bcode->deserialized) {
-      bbuilder->v7->bcode_lit_deser_size += bbuilder->lit.len;
-    }
-#endif
-  }
-  return lit;
-}
-
-#if 0
-V7_PRIVATE v7_val_t bcode_get_lit(struct bcode *bcode, size_t idx) {
-  val_t ret;
-  memcpy(&ret, bcode->lit.p + (size_t) idx * sizeof(ret), sizeof(ret));
-  return ret;
-}
-#endif
-
-static const char *bcode_deserialize_func(struct v7 *v7, struct bcode *bcode,
-                                          const char *data);
-
-V7_PRIVATE v7_val_t
-bcode_decode_lit(struct v7 *v7, struct bcode *bcode, char **ops) {
-  struct v7_vec *vec = &bcode->lit;
-  size_t idx = bcode_get_varint(ops);
-  switch (idx) {
-    case BCODE_INLINE_STRING_TYPE_TAG: {
-      val_t res;
-      size_t len = bcode_get_varint(ops);
-      res = v7_mk_string(
-          v7, (const char *) *ops + 1 /*skip BCODE_INLINE_STRING_TYPE_TAG*/,
-          len, !bcode->ops_in_rom);
-      *ops += len + 1;
-      return res;
-    }
-    case BCODE_INLINE_NUMBER_TYPE_TAG: {
-      val_t res;
-      memcpy(&res, *ops + 1 /*skip BCODE_INLINE_NUMBER_TYPE_TAG*/, sizeof(res));
-      *ops += sizeof(res);
-      return res;
-    }
-    case BCODE_INLINE_FUNC_TYPE_TAG: {
-      /*
-       * Create half-done function: without scope but _with_ prototype. Scope
-       * will be set by `bcode_instantiate_function()`.
-       *
-       * The fact that the prototype is already set will make
-       * `bcode_instantiate_function()` just set scope on this function,
-       * instead of creating a new one.
-       */
-      val_t res = mk_js_function(v7, NULL, v7_mk_object(v7));
-
-      /* Create bcode in this half-done function */
-      struct v7_js_function *func = get_js_function_struct(res);
-
-      func->bcode = (struct bcode *) calloc(1, sizeof(*func->bcode));
-      bcode_init(func->bcode, bcode->strict_mode, NULL /* will be set below */,
-                 0);
-      bcode_copy_filename_from(func->bcode, bcode);
-      retain_bcode(v7, func->bcode);
-
-      /* deserialize the function's bcode from `ops` */
-      *ops = (char *) bcode_deserialize_func(
-          v7, func->bcode, *ops + 1 /*skip BCODE_INLINE_FUNC_TYPE_TAG*/);
-
-      /* decrement *ops, because it will be incremented by `eval_bcode` soon */
-      *ops -= 1;
-
-      return res;
-    }
-    case BCODE_INLINE_REGEXP_TYPE_TAG: {
-#if V7_ENABLE__RegExp
-      enum v7_err rcode = V7_OK;
-      val_t res;
-      size_t len_src, len_flags;
-      char *buf_src, *buf_flags;
-
-      len_src = bcode_get_varint(ops);
-      buf_src = *ops + 1;
-      *ops += len_src + 1 /* nul term */;
-
-      len_flags = bcode_get_varint(ops);
-      buf_flags = *ops + 1;
-      *ops += len_flags + 1 /* nul term */;
-
-      rcode = v7_mk_regexp(v7, buf_src, len_src, buf_flags, len_flags, &res);
-      assert(rcode == V7_OK);
-      (void) rcode;
-
-      return res;
-#else
-      fprintf(stderr, "Firmware is built without -DV7_ENABLE__RegExp\n");
-      abort();
-#endif
-    }
-    default:
-      return ((val_t *) vec->p)[idx - BCODE_MAX_INLINE_TYPE_TAG];
-  }
-}
-
-V7_PRIVATE void bcode_op_lit(struct bcode_builder *bbuilder, enum opcode op,
-                             lit_t lit) {
-  bcode_op(bbuilder, op);
-
-  switch (lit.mode) {
-    case LIT_MODE__TABLE:
-      bcode_add_varint(bbuilder, lit.v.lit_idx + BCODE_MAX_INLINE_TYPE_TAG);
-      break;
-
-    case LIT_MODE__INLINED:
-      if (v7_is_string(lit.v.inline_val)) {
-        size_t len;
-        const char *s = v7_get_string(bbuilder->v7, &lit.v.inline_val, &len);
-        bcode_add_varint(bbuilder, BCODE_INLINE_STRING_TYPE_TAG);
-        bcode_add_varint(bbuilder, len);
-        bcode_ops_append(bbuilder, s, len + 1 /* nul term */);
-      } else if (v7_is_number(lit.v.inline_val)) {
-        bcode_add_varint(bbuilder, BCODE_INLINE_NUMBER_TYPE_TAG);
-        /*
-         * TODO(dfrank): we can save some memory by storing string
-         * representation of a number here, instead of wasting 8 bytes for each
-         * number.
-         *
-         * Alternatively, we can add more tags for integers, like
-         * `BCODE_INLINE_S08_TYPE_TAG`, `BCODE_INLINE_S16_TYPE_TAG`, etc, since
-         * integers are the most common numbers for sure.
-         */
-        bcode_ops_append(bbuilder, &lit.v.inline_val, sizeof(lit.v.inline_val));
-      } else if (is_js_function(lit.v.inline_val)) {
-/*
- * TODO(dfrank): implement `bcode_serialize_*` more generically, so
- * that they can write to buffer instead of a `FILE`. Then, remove this
- * workaround with `CS_PLATFORM == CS_P_UNIX`, `tmpfile()`, etc.
- */
-#if CS_PLATFORM == CS_P_UNIX
-        struct v7_js_function *func;
-        FILE *fp = tmpfile();
-        long len = 0;
-        char *p;
-
-        func = get_js_function_struct(lit.v.inline_val);
-
-        /* we inline functions if only we're precompiling */
-        assert(bbuilder->v7->is_precompiling);
-
-        bcode_add_varint(bbuilder, BCODE_INLINE_FUNC_TYPE_TAG);
-        bcode_serialize_func(bbuilder->v7, func->bcode, fp);
-
-        fflush(fp);
-
-        len = ftell(fp);
-
-        p = (char *) mmap(NULL, len, PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
-
-        bcode_ops_append(bbuilder, p, len);
-
-        fclose(fp);
-#endif
-      } else if (v7_is_regexp(bbuilder->v7, lit.v.inline_val)) {
-#if V7_ENABLE__RegExp
-        struct v7_regexp *rp =
-            v7_get_regexp_struct(bbuilder->v7, lit.v.inline_val);
-        bcode_add_varint(bbuilder, BCODE_INLINE_REGEXP_TYPE_TAG);
-
-        /* append regexp source */
-        {
-          size_t len;
-          const char *buf =
-              v7_get_string(bbuilder->v7, &rp->regexp_string, &len);
-          bcode_add_varint(bbuilder, len);
-          bcode_ops_append(bbuilder, buf, len + 1 /* nul term */);
-        }
-
-        /* append regexp flags */
-        {
-          char buf[_V7_REGEXP_MAX_FLAGS_LEN + 1 /* nul term */];
-          size_t len = get_regexp_flags_str(bbuilder->v7, rp, buf);
-          bcode_add_varint(bbuilder, len);
-          bcode_ops_append(bbuilder, buf, len + 1 /* nul term */);
-        }
-#else
-        fprintf(stderr, "Firmware is built without -DV7_ENABLE__RegExp\n");
-        abort();
-#endif
-      } else {
-        /* invalid type of inlined value */
-        abort();
-      }
-      break;
-
-    default:
-      /* invalid literal mode */
-      abort();
-      break;
-  }
-}
-
-V7_PRIVATE void bcode_push_lit(struct bcode_builder *bbuilder, lit_t lit) {
-  bcode_op_lit(bbuilder, OP_PUSH_LIT, lit);
-}
-
-WARN_UNUSED_RESULT
-    /*V7_PRIVATE*/ enum v7_err
-    bcode_add_name(struct bcode_builder *bbuilder, const char *p, size_t len,
-                   size_t *idx) {
-  enum v7_err rcode = V7_OK;
-  int llen;
-  size_t ops_index;
-
-  /*
-   * if name length is not provided, assume it's null-terminated and calculate
-   * it
-   */
-  if (len == ~((size_t) 0)) {
-    len = strlen(p);
-  }
-
-  /* index at which to put name. If not provided, we'll append at the end */
-  if (idx != NULL) {
-    ops_index = *idx;
-  } else {
-    ops_index = bbuilder->ops.len;
-  }
-
-  /* calculate how much varint len will take */
-  llen = calc_llen(len);
-
-  /* reserve space in `ops` buffer */
-  mbuf_insert(&bbuilder->ops, ops_index, NULL, llen + len + 1 /*null-term*/);
-
-  {
-    char *ops = bbuilder->ops.buf + ops_index;
-
-    /* put varint len */
-    ops += encode_varint(len, (unsigned char *) ops);
-
-    /* put string */
-    memcpy(ops, p, len);
-    ops += len;
-
-    /* null-terminate */
-    *ops++ = 0x00;
-
-    if (idx != NULL) {
-      *idx = ops - bbuilder->ops.buf;
-    }
-  }
-
-  /* maintain total number of names */
-  if (bbuilder->bcode->names_cnt < V7_NAMES_CNT_MAX) {
-    bbuilder->bcode->names_cnt++;
-  } else {
-    rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "Too many local variables");
-  }
-
-  return rcode;
-}
-
-/*V7_PRIVATE*/ char *bcode_end_names(char *ops, size_t names_cnt) {
-  while (names_cnt--) {
-    ops = bcode_next_name(ops, NULL, NULL);
-  }
-  return ops;
-}
-
-V7_PRIVATE char *bcode_next_name(char *ops, char **pname, size_t *plen) {
-  size_t len;
-  int llen;
-
-  len = decode_varint((unsigned char *) ops, &llen);
-
-  ops += llen;
-
-  if (pname != NULL) {
-    *pname = ops;
-  }
-
-  if (plen != NULL) {
-    *plen = len;
-  }
-
-  ops += len + 1 /*null-terminator*/;
-  return ops;
-}
-
-V7_PRIVATE char *bcode_next_name_v(struct v7 *v7, struct bcode *bcode,
-                                   char *ops, val_t *res) {
-  char *name;
-  size_t len;
-
-  ops = bcode_next_name(ops, &name, &len);
-
-  /*
-   * If `ops` is in RAM, we create owned string, since the string may outlive
-   * bcode. Otherwise (`ops` is in ROM), we create foreign string.
-   */
-  *res = v7_mk_string(v7, name, len, !bcode->ops_in_rom);
-
-  return ops;
-}
-
-V7_PRIVATE bcode_off_t bcode_pos(struct bcode_builder *bbuilder) {
-  return bbuilder->ops.len;
-}
-
-/*
- * Appends a branch target and returns its location.
- * This location can be updated with bcode_patch_target.
- * To be issued following a JMP_* bytecode
- */
-V7_PRIVATE bcode_off_t bcode_add_target(struct bcode_builder *bbuilder) {
-  bcode_off_t pos = bcode_pos(bbuilder);
-  bcode_off_t zero = 0;
-  bcode_ops_append(bbuilder, &zero, sizeof(bcode_off_t));
-  return pos;
-}
-
-/*
- * Appends an op requiring a branch target. See bcode_add_target.
- *
- * This function is used only internally, but used in a complicated mix of
- * configurations, hence the commented V7_PRIVATE
- */
-/*V7_PRIVATE*/ bcode_off_t bcode_op_target(struct bcode_builder *bbuilder,
-                                           uint8_t op) {
-  bcode_op(bbuilder, op);
-  return bcode_add_target(bbuilder);
-}
-
-/*V7_PRIVATE*/ void bcode_patch_target(struct bcode_builder *bbuilder,
-                                       bcode_off_t label, bcode_off_t target) {
-  memcpy(bbuilder->ops.buf + label, &target, sizeof(target));
-}
-
-/*V7_PRIVATE*/ void bcode_serialize(struct v7 *v7, struct bcode *bcode,
-                                    FILE *out) {
-  (void) v7;
-  (void) bcode;
-
-  fwrite(BIN_BCODE_SIGNATURE, sizeof(BIN_BCODE_SIGNATURE), 1, out);
-  bcode_serialize_func(v7, bcode, out);
-}
-
-static void bcode_serialize_varint(int n, FILE *out) {
-  unsigned char buf[8];
-  int k = calc_llen(n);
-  encode_varint(n, buf);
-  fwrite(buf, k, 1, out);
-}
-
-static void bcode_serialize_func(struct v7 *v7, struct bcode *bcode,
-                                 FILE *out) {
-  struct v7_vec *vec;
-  (void) v7;
-
-  /*
-   * All literals should be inlined into `ops`, so we expect literals table
-   * to be empty here
-   */
-  assert(bcode->lit.len == 0);
-
-  /* args_cnt */
-  bcode_serialize_varint(bcode->args_cnt, out);
-
-  /* names_cnt */
-  bcode_serialize_varint(bcode->names_cnt, out);
-
-  /* func_name_present */
-  bcode_serialize_varint(bcode->func_name_present, out);
-
-  /*
-   * bcode:
-   * <varint> // opcodes length
-   * <opcode>*
-   */
-  vec = &bcode->ops;
-  bcode_serialize_varint(vec->len, out);
-  fwrite(vec->p, vec->len, 1, out);
-}
-
-static size_t bcode_deserialize_varint(const char **data) {
-  size_t ret = 0;
-  int len = 0;
-  ret = decode_varint((const unsigned char *) (*data), &len);
-  *data += len;
-  return ret;
-}
-
-static const char *bcode_deserialize_func(struct v7 *v7, struct bcode *bcode,
-                                          const char *data) {
-  size_t size;
-  struct bcode_builder bbuilder;
-
-  bcode_builder_init(v7, &bbuilder, bcode);
-
-  /*
-   * before deserializing, set the corresponding flag, so that metrics will be
-   * updated accordingly
-   */
-  bcode->deserialized = 1;
-
-  /*
-   * In serialized functions, all literals are inlined into `ops`, so we don't
-   * deserialize them here in any way
-   */
-
-  /* get number of args */
-  bcode->args_cnt = bcode_deserialize_varint(&data);
-
-  /* get number of names */
-  bcode->names_cnt = bcode_deserialize_varint(&data);
-
-  /* get whether the function name is present in `names` */
-  bcode->func_name_present = bcode_deserialize_varint(&data);
-
-  /* get opcode size */
-  size = bcode_deserialize_varint(&data);
-
-  bbuilder.ops.buf = (char *) data;
-  bbuilder.ops.size = size;
-  bbuilder.ops.len = size;
-
-  bcode->ops_in_rom = 1;
-
-  data += size;
-
-  bcode_builder_finalize(&bbuilder);
-  return data;
-}
-
-V7_PRIVATE void bcode_deserialize(struct v7 *v7, struct bcode *bcode,
-                                  const char *data) {
-  data = bcode_deserialize_func(v7, bcode, data);
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/eval.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/str_util.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/eval.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/gc.h" */
-/* Amalgamated: #include "v7/src/compiler.h" */
-/* Amalgamated: #include "v7/src/cyg_profile.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-/* Amalgamated: #include "v7/src/shdata.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/varint.h" */
-
-/*
- * Bcode offsets in "try stack" are stored in JS numbers, i.e.  in `double`s.
- * Apart from the offset itself, we also need some additional data:
- *
- * - type of the block that offset represents (`catch`, `finally`, `switch`,
- *   or some loop)
- * - size of the stack when the block is created (needed when throwing, since
- *   if exception is thrown from the middle of the expression, the stack may
- *   have any arbitrary length)
- *
- * We bake all this data into integer part of the double (53 bits) :
- *
- * - 32 bits: bcode offset
- * - 3 bits: "tag": the type of the block
- * - 16 bits: stack size
- */
-
-/*
- * Widths of data parts
- */
-#define LBLOCK_OFFSET_WIDTH 32
-#define LBLOCK_TAG_WIDTH 3
-#define LBLOCK_STACK_SIZE_WIDTH 16
-
-/*
- * Shifts of data parts
- */
-#define LBLOCK_OFFSET_SHIFT (0)
-#define LBLOCK_TAG_SHIFT (LBLOCK_OFFSET_SHIFT + LBLOCK_OFFSET_WIDTH)
-#define LBLOCK_STACK_SIZE_SHIFT (LBLOCK_TAG_SHIFT + LBLOCK_TAG_WIDTH)
-#define LBLOCK_TOTAL_WIDTH (LBLOCK_STACK_SIZE_SHIFT + LBLOCK_STACK_SIZE_WIDTH)
-
-/*
- * Masks of data parts
- */
-#define LBLOCK_OFFSET_MASK \
-  ((int64_t)(((int64_t) 1 << LBLOCK_OFFSET_WIDTH) - 1) << LBLOCK_OFFSET_SHIFT)
-#define LBLOCK_TAG_MASK \
-  ((int64_t)(((int64_t) 1 << LBLOCK_TAG_WIDTH) - 1) << LBLOCK_TAG_SHIFT)
-#define LBLOCK_STACK_SIZE_MASK                             \
-  ((int64_t)(((int64_t) 1 << LBLOCK_STACK_SIZE_WIDTH) - 1) \
-   << LBLOCK_STACK_SIZE_SHIFT)
-
-/*
- * Self-check: make sure all the data can fit into double's mantissa
- */
-#if (LBLOCK_TOTAL_WIDTH > 53)
-#error lblock width is too large, it can't fit into double's mantissa
-#endif
-
-/*
- * Tags that are used for bcode offsets in "try stack"
- */
-#define LBLOCK_TAG_CATCH ((int64_t) 0x01 << LBLOCK_TAG_SHIFT)
-#define LBLOCK_TAG_FINALLY ((int64_t) 0x02 << LBLOCK_TAG_SHIFT)
-#define LBLOCK_TAG_LOOP ((int64_t) 0x03 << LBLOCK_TAG_SHIFT)
-#define LBLOCK_TAG_SWITCH ((int64_t) 0x04 << LBLOCK_TAG_SHIFT)
-
-/*
- * Yields 32-bit bcode offset value
- */
-#define LBLOCK_OFFSET(v) \
-  ((bcode_off_t)(((v) &LBLOCK_OFFSET_MASK) >> LBLOCK_OFFSET_SHIFT))
-
-/*
- * Yields tag value (unshifted, to be compared with macros like
- * `LBLOCK_TAG_CATCH`, etc)
- */
-#define LBLOCK_TAG(v) ((v) &LBLOCK_TAG_MASK)
-
-/*
- * Yields stack size
- */
-#define LBLOCK_STACK_SIZE(v) \
-  (((v) &LBLOCK_STACK_SIZE_MASK) >> LBLOCK_STACK_SIZE_SHIFT)
-
-/*
- * Yields `int64_t` value to be stored as a JavaScript number
- */
-#define LBLOCK_ITEM_CREATE(offset, tag, stack_size) \
-  ((int64_t)(offset) | (tag) |                      \
-   (((int64_t)(stack_size)) << LBLOCK_STACK_SIZE_SHIFT))
-
-/*
- * make sure `bcode_off_t` is just 32-bit, so that it can fit in double
- * with 3-bit tag
- */
-V7_STATIC_ASSERT((sizeof(bcode_off_t) * 8) == LBLOCK_OFFSET_WIDTH,
-                 wrong_size_of_bcode_off_t);
-
-#define PUSH(v) stack_push(&v7->stack, v)
-#define POP() stack_pop(&v7->stack)
-#define TOS() stack_tos(&v7->stack)
-#define SP() stack_sp(&v7->stack)
-
-/*
- * Local-to-function block types that we might want to consider when unwinding
- * stack for whatever reason. see `unwind_local_blocks_stack()`.
- */
-enum local_block {
-  LOCAL_BLOCK_NONE = (0),
-  LOCAL_BLOCK_CATCH = (1 << 0),
-  LOCAL_BLOCK_FINALLY = (1 << 1),
-  LOCAL_BLOCK_LOOP = (1 << 2),
-  LOCAL_BLOCK_SWITCH = (1 << 3),
-};
-
-/*
- * Like `V7_TRY()`, but to be used inside `eval_bcode()` only: you should
- * wrap all calls to cfunctions into `BTRY()` instead of `V7_TRY()`.
- *
- * If the provided function returns something other than `V7_OK`, this macro
- * calls `bcode_perform_throw`, which performs bcode stack unwinding.
- */
-#define BTRY(call)                                                            \
-  do {                                                                        \
-    enum v7_err _e = call;                                                    \
-    (void) _you_should_use_BTRY_in_eval_bcode_only;                           \
-    if (_e != V7_OK) {                                                        \
-      V7_TRY(bcode_perform_throw(v7, &r, 0 /*don't take value from stack*/)); \
-      goto op_done;                                                           \
-    }                                                                         \
-  } while (0)
-
-V7_PRIVATE void stack_push(struct mbuf *s, val_t v) {
-  mbuf_append(s, &v, sizeof(v));
-}
-
-V7_PRIVATE val_t stack_pop(struct mbuf *s) {
-  assert(s->len >= sizeof(val_t));
-  s->len -= sizeof(val_t);
-  return *(val_t *) (s->buf + s->len);
-}
-
-V7_PRIVATE val_t stack_tos(struct mbuf *s) {
-  assert(s->len >= sizeof(val_t));
-  return *(val_t *) (s->buf + s->len - sizeof(val_t));
-}
-
-#ifdef V7_BCODE_TRACE_STACK
-V7_PRIVATE val_t stack_at(struct mbuf *s, size_t idx) {
-  assert(s->len >= sizeof(val_t) * idx);
-  return *(val_t *) (s->buf + s->len - sizeof(val_t) - idx * sizeof(val_t));
-}
-#endif
-
-V7_PRIVATE int stack_sp(struct mbuf *s) {
-  return s->len / sizeof(val_t);
-}
-
-/*
- * Delete a property with name `name`, `len` from an object `obj`. If the
- * object does not contain own property with the given `name`, moves to `obj`'s
- * prototype, and so on.
- *
- * If the property is eventually found, it is deleted, and `0` is returned.
- * Otherwise, `-1` is returned.
- *
- * If `len` is -1/MAXUINT/~0, then `name` must be 0-terminated.
- *
- * See `v7_del()` as well.
- */
-static int del_property_deep(struct v7 *v7, val_t obj, const char *name,
-                             size_t len) {
-  if (!v7_is_object(obj)) {
-    return -1;
-  }
-  for (; obj != V7_NULL; obj = v7_get_proto(v7, obj)) {
-    int del_res;
-    if ((del_res = v7_del(v7, obj, name, len)) != -1) {
-      return del_res;
-    }
-  }
-  return -1;
-}
-
-/* Visual studio 2012+ has signbit() */
-#if defined(_MSC_VER) && _MSC_VER < 1700
-static int signbit(double x) {
-  double s = _copysign(1, x);
-  return s < 0;
-}
-#endif
-
-static double b_int_bin_op(enum opcode op, double a, double b) {
-  int32_t ia = isnan(a) || isinf(a) ? 0 : (int32_t)(int64_t) a;
-  int32_t ib = isnan(b) || isinf(b) ? 0 : (int32_t)(int64_t) b;
-
-  switch (op) {
-    case OP_LSHIFT:
-      return (int32_t)((uint32_t) ia << ((uint32_t) ib & 31));
-    case OP_RSHIFT:
-      return ia >> ((uint32_t) ib & 31);
-    case OP_URSHIFT:
-      return (uint32_t) ia >> ((uint32_t) ib & 31);
-    case OP_OR:
-      return ia | ib;
-    case OP_XOR:
-      return ia ^ ib;
-    case OP_AND:
-      return ia & ib;
-    default:
-      assert(0);
-  }
-  return 0;
-}
-
-static double b_num_bin_op(enum opcode op, double a, double b) {
-  /*
-   * For certain operations, the result is always NaN if either of arguments
-   * is NaN
-   */
-  switch (op) {
-    case OP_ADD:
-    case OP_SUB:
-    case OP_MUL:
-    case OP_DIV:
-    case OP_REM:
-      if (isnan(a) || isnan(b)) {
-        return NAN;
-      }
-      break;
-    default:
-      break;
-  }
-
-  switch (op) {
-    case OP_ADD: /* simple fixed width nodes with no payload */
-      return a + b;
-    case OP_SUB:
-      return a - b;
-    case OP_REM:
-      if (b == 0 || isnan(b) || isnan(a) || isinf(b) || isinf(a)) {
-        return NAN;
-      }
-      return (int) a % (int) b;
-    case OP_MUL:
-      return a * b;
-    case OP_DIV:
-      if (b == 0) {
-        if (a == 0) return NAN;
-        return (!signbit(a) == !signbit(b)) ? INFINITY : -INFINITY;
-      }
-      return a / b;
-    case OP_LSHIFT:
-    case OP_RSHIFT:
-    case OP_URSHIFT:
-    case OP_OR:
-    case OP_XOR:
-    case OP_AND:
-      return b_int_bin_op(op, a, b);
-    default:
-      assert(0);
-  }
-  return 0;
-}
-
-static int b_bool_bin_op(enum opcode op, double a, double b) {
-#ifdef V7_BROKEN_NAN
-  if (isnan(a) || isnan(b)) return op == OP_NE || op == OP_NE_NE;
-#endif
-
-  switch (op) {
-    case OP_EQ:
-    case OP_EQ_EQ:
-      return a == b;
-    case OP_NE:
-    case OP_NE_NE:
-      return a != b;
-    case OP_LT:
-      return a < b;
-    case OP_LE:
-      return a <= b;
-    case OP_GT:
-      return a > b;
-    case OP_GE:
-      return a >= b;
-    default:
-      assert(0);
-  }
-  return 0;
-}
-
-static bcode_off_t bcode_get_target(char **ops) {
-  bcode_off_t target;
-  (*ops)++;
-  memcpy(&target, *ops, sizeof(target));
-  *ops += sizeof(target) - 1;
-  return target;
-}
-
-struct bcode_registers {
-  /*
-   * TODO(dfrank): make it contain `struct v7_call_frame_bcode *`
-   * and use `bcode_ops` in-place, or probably drop the `bcode_registers`
-   * whatsoever
-   */
-  struct bcode *bcode;
-  char *ops;
-  char *end;
-  unsigned int need_inc_ops : 1;
-};
-
-/*
- * If returning from function implicitly, then set return value to `undefined`.
- *
- * And if function was called as a constructor, then make sure returned
- * value is an object.
- */
-static void bcode_adjust_retval(struct v7 *v7, uint8_t is_explicit_return) {
-  if (!is_explicit_return) {
-    /* returning implicitly: set return value to `undefined` */
-    POP();
-    PUSH(V7_UNDEFINED);
-  }
-
-  if (v7->call_stack->is_constructor && !v7_is_object(TOS())) {
-    /* constructor is going to return non-object: replace it with `this` */
-    POP();
-    PUSH(v7_get_this(v7));
-  }
-}
-
-static void bcode_restore_registers(struct v7 *v7, struct bcode *bcode,
-                                    struct bcode_registers *r) {
-  r->bcode = bcode;
-  r->ops = bcode->ops.p;
-  r->end = r->ops + bcode->ops.len;
-
-  (void) v7;
-}
-
-V7_PRIVATE struct v7_call_frame_base *find_call_frame(struct v7 *v7,
-                                                      uint8_t type_mask) {
-  struct v7_call_frame_base *ret = v7->call_stack;
-
-  while (ret != NULL && !(ret->type_mask & type_mask)) {
-    ret = ret->prev;
-  }
-
-  return ret;
-}
-
-static struct v7_call_frame_private *find_call_frame_private(struct v7 *v7) {
-  return (struct v7_call_frame_private *) find_call_frame(
-      v7, V7_CALL_FRAME_MASK_PRIVATE);
-}
-
-static struct v7_call_frame_bcode *find_call_frame_bcode(struct v7 *v7) {
-  return (struct v7_call_frame_bcode *) find_call_frame(
-      v7, V7_CALL_FRAME_MASK_BCODE);
-}
-
-#if 0
-static struct v7_call_frame_cfunc *find_call_frame_cfunc(struct v7 *v7) {
-  return (struct v7_call_frame_cfunc *) find_call_frame(
-      v7, V7_CALL_FRAME_MASK_CFUNC);
-}
-#endif
-
-static struct v7_call_frame_base *create_call_frame(struct v7 *v7,
-                                                    size_t size) {
-  struct v7_call_frame_base *call_frame_base = NULL;
-
-  call_frame_base = (struct v7_call_frame_base *) calloc(1, size);
-
-  /* save previous call frame */
-  call_frame_base->prev = v7->call_stack;
-
-  /* by default, inherit line_no from the previous frame */
-  if (v7->call_stack != NULL) {
-    call_frame_base->line_no = v7->call_stack->line_no;
-  }
-
-  return call_frame_base;
-}
-
-static void init_call_frame_private(struct v7 *v7,
-                                    struct v7_call_frame_private *call_frame,
-                                    val_t scope) {
-  /* make a snapshot of the current state */
-  {
-    struct v7_call_frame_private *cf = find_call_frame_private(v7);
-    if (cf != NULL) {
-      cf->stack_size = v7->stack.len;
-    }
-  }
-
-  /* set a type flag */
-  call_frame->base.type_mask |= V7_CALL_FRAME_MASK_PRIVATE;
-
-  /* fill the new frame with data */
-  call_frame->vals.scope = scope;
-  /* `try_stack` will be lazily created in `eval_try_push()`*/
-  call_frame->vals.try_stack = V7_UNDEFINED;
-}
-
-static void init_call_frame_bcode(struct v7 *v7,
-                                  struct v7_call_frame_bcode *call_frame,
-                                  char *prev_bcode_ops, struct bcode *bcode,
-                                  val_t this_obj, val_t scope,
-                                  uint8_t is_constructor) {
-  init_call_frame_private(v7, &call_frame->base, scope);
-
-  /* make a snapshot of the current state */
-  {
-    struct v7_call_frame_bcode *cf = find_call_frame_bcode(v7);
-    if (cf != NULL) {
-      cf->bcode_ops = prev_bcode_ops;
-
-      /* remember thrown value */
-      cf->vals.thrown_error = v7->vals.thrown_error;
-      cf->base.base.is_thrown = v7->is_thrown;
-    }
-  }
-
-  /* set a type flag */
-  call_frame->base.base.type_mask |= V7_CALL_FRAME_MASK_BCODE;
-
-  /* fill the new frame with data */
-  call_frame->bcode = bcode;
-  call_frame->vals.this_obj = this_obj;
-  call_frame->base.base.is_constructor = is_constructor;
-}
-
-/*
- * Create new bcode call frame object and fill it with data
- */
-static void append_call_frame_bcode(struct v7 *v7, char *prev_bcode_ops,
-                                    struct bcode *bcode, val_t this_obj,
-                                    val_t scope, uint8_t is_constructor) {
-  struct v7_call_frame_bcode *call_frame =
-      (struct v7_call_frame_bcode *) create_call_frame(v7, sizeof(*call_frame));
-
-  init_call_frame_bcode(v7, call_frame, prev_bcode_ops, bcode, this_obj, scope,
-                        is_constructor);
-
-  v7->call_stack = &call_frame->base.base;
-}
-
-static void append_call_frame_private(struct v7 *v7, val_t scope) {
-  struct v7_call_frame_private *call_frame =
-      (struct v7_call_frame_private *) create_call_frame(v7,
-                                                         sizeof(*call_frame));
-  init_call_frame_private(v7, call_frame, scope);
-
-  v7->call_stack = &call_frame->base;
-}
-
-static void append_call_frame_cfunc(struct v7 *v7, val_t this_obj,
-                                    v7_cfunction_t *cfunc) {
-  struct v7_call_frame_cfunc *call_frame =
-      (struct v7_call_frame_cfunc *) create_call_frame(v7, sizeof(*call_frame));
-
-  /* set a type flag */
-  call_frame->base.type_mask |= V7_CALL_FRAME_MASK_CFUNC;
-
-  /* fill the new frame with data */
-  call_frame->cfunc = cfunc;
-  call_frame->vals.this_obj = this_obj;
-
-  v7->call_stack = &call_frame->base;
-}
-
-/*
- * The caller's bcode object is needed because we have to restore literals
- * and `end` registers.
- *
- * TODO(mkm): put this state on a return stack
- *
- * Caller of bcode_perform_call is responsible for owning `call_frame`
- */
-static enum v7_err bcode_perform_call(struct v7 *v7, v7_val_t scope_frame,
-                                      struct v7_js_function *func,
-                                      struct bcode_registers *r,
-                                      val_t this_object, char *ops,
-                                      uint8_t is_constructor) {
-  /* new scope_frame will inherit from the function's scope */
-  obj_prototype_set(v7, get_object_struct(scope_frame), &func->scope->base);
-
-  /* create new `call_frame` which will replace `v7->call_stack` */
-  append_call_frame_bcode(v7, r->ops + 1, func->bcode, this_object, scope_frame,
-                          is_constructor);
-
-  bcode_restore_registers(v7, func->bcode, r);
-
-  /* adjust `ops` since names were already read from it */
-  r->ops = ops;
-
-  /* `ops` already points to the needed instruction, no need to increment it */
-  r->need_inc_ops = 0;
-
-  return V7_OK;
-}
-
-/*
- * Apply data from the "private" call frame, typically after some other frame
- * was just unwound.
- *
- * The `call_frame` may actually be `NULL`, if the top frame was unwound.
- */
-static void apply_frame_private(struct v7 *v7,
-                                struct v7_call_frame_private *call_frame) {
-  /*
-   * Adjust data stack length (restore saved).
-   *
-   * If `call_frame` is NULL, it means that the last call frame was just
-   * unwound, and hence the data stack size should be 0.
-   */
-  size_t stack_size = (call_frame != NULL ? call_frame->stack_size : 0);
-  assert(stack_size <= v7->stack.len);
-  v7->stack.len = stack_size;
-}
-
-/*
- * Apply data from the "bcode" call frame, typically after some other frame
- * was just unwound.
- *
- * The `call_frame` may actually be `NULL`, if the top frame was unwound; but
- * in this case, `r` must be `NULL` too, by design. See inline comment below.
- */
-static void apply_frame_bcode(struct v7 *v7,
-                              struct v7_call_frame_bcode *call_frame,
-                              struct bcode_registers *r) {
-  if (r != NULL) {
-    /*
-     * Note: if `r` is non-NULL, then `call_frame` should be non-NULL as well,
-     * by design. If this invariant is violated, it means that
-     * `unwind_stack_1level()` is misused.
-     */
-    assert(call_frame != NULL);
-
-    bcode_restore_registers(v7, call_frame->bcode, r);
-    r->ops = call_frame->bcode_ops;
-
-    /*
-     * restore thrown value if only there's no new thrown value
-     * (otherwise, the new one overrides the previous one)
-     */
-    if (!v7->is_thrown) {
-      v7->vals.thrown_error = call_frame->vals.thrown_error;
-      v7->is_thrown = call_frame->base.base.is_thrown;
-    }
-  }
-}
-
-/*
- * Unwinds `call_stack` by 1 frame.
- *
- * Returns the type of the unwound frame
- */
-static v7_call_frame_mask_t unwind_stack_1level(struct v7 *v7,
-                                                struct bcode_registers *r) {
-  v7_call_frame_mask_t type_mask;
-#ifdef V7_BCODE_TRACE
-  fprintf(stderr, "unwinding stack by 1 level\n");
-#endif
-
-  type_mask = v7->call_stack->type_mask;
-
-  /* drop the top frame */
-  {
-    struct v7_call_frame_base *tmp = v7->call_stack;
-    v7->call_stack = v7->call_stack->prev;
-    free(tmp);
-  }
-
-  /*
-   * depending on the unwound frame type, apply data from the top call frame(s)
-   * which are still alive (if any)
-   */
-
-  if (type_mask & V7_CALL_FRAME_MASK_PRIVATE) {
-    apply_frame_private(v7, find_call_frame_private(v7));
-  }
-
-  if (type_mask & V7_CALL_FRAME_MASK_BCODE) {
-    apply_frame_bcode(v7, find_call_frame_bcode(v7), r);
-  }
-
-  if (type_mask & V7_CALL_FRAME_MASK_CFUNC) {
-    /* Nothing to do here at the moment */
-  }
-
-  return type_mask;
-}
-
-/*
- * Unwinds local "try stack" (i.e. local-to-current-function stack of nested
- * `try` blocks), looking for local-to-function blocks.
- *
- * Block types of interest are specified with `wanted_blocks_mask`: it's a
- * bitmask of `enum local_block` values.
- *
- * Only blocks of specified types will be considered, others will be dropped.
- *
- * If `restore_stack_size` is non-zero, the `v7->stack.len` will be restored
- * to the value saved when the block was created. This is useful when throwing,
- * since if we throw from the middle of the expression, the stack could have
- * any size. But you probably shouldn't set this flag when breaking and
- * returning, since it may hide real bugs in the opcode.
- *
- * Returns id of the block type that control was transferred into, or
- * `LOCAL_BLOCK_NONE` if no appropriate block was found. Note: returned value
- * contains at most 1 block bit; it can't contain multiple bits.
- */
-static enum local_block unwind_local_blocks_stack(
-    struct v7 *v7, struct bcode_registers *r, unsigned int wanted_blocks_mask,
-    uint8_t restore_stack_size) {
-  val_t arr = V7_UNDEFINED;
-  struct gc_tmp_frame tf = new_tmp_frame(v7);
-  enum local_block found_block = LOCAL_BLOCK_NONE;
-  unsigned long length;
-
-  tmp_stack_push(&tf, &arr);
-
-  arr = find_call_frame_private(v7)->vals.try_stack;
-  if (v7_is_array(v7, arr)) {
-    /*
-     * pop latest element from "try stack", loop until we need to transfer
-     * control there
-     */
-    while ((length = v7_array_length(v7, arr)) > 0) {
-      /* get latest offset from the "try stack" */
-      int64_t offset = v7_get_double(v7, v7_array_get(v7, arr, length - 1));
-      enum local_block cur_block = LOCAL_BLOCK_NONE;
-
-      /* get id of the current block type */
-      switch (LBLOCK_TAG(offset)) {
-        case LBLOCK_TAG_CATCH:
-          cur_block = LOCAL_BLOCK_CATCH;
-          break;
-        case LBLOCK_TAG_FINALLY:
-          cur_block = LOCAL_BLOCK_FINALLY;
-          break;
-        case LBLOCK_TAG_LOOP:
-          cur_block = LOCAL_BLOCK_LOOP;
-          break;
-        case LBLOCK_TAG_SWITCH:
-          cur_block = LOCAL_BLOCK_SWITCH;
-          break;
-        default:
-          assert(0);
-          break;
-      }
-
-      if (cur_block & wanted_blocks_mask) {
-        /* need to transfer control to this offset */
-        r->ops = r->bcode->ops.p + LBLOCK_OFFSET(offset);
-#ifdef V7_BCODE_TRACE
-        fprintf(stderr, "transferring to block #%d: %u\n", (int) cur_block,
-                (unsigned int) LBLOCK_OFFSET(offset));
-#endif
-        found_block = cur_block;
-        /* if needed, restore stack size to the saved value */
-        if (restore_stack_size) {
-          v7->stack.len = LBLOCK_STACK_SIZE(offset);
-        }
-        break;
-      } else {
-#ifdef V7_BCODE_TRACE
-        fprintf(stderr, "skipped block #%d: %u\n", (int) cur_block,
-                (unsigned int) LBLOCK_OFFSET(offset));
-#endif
-        /*
-         * since we don't need to control transfer there, just pop
-         * it from the "try stack"
-         */
-        v7_array_del(v7, arr, length - 1);
-      }
-    }
-  }
-
-  tmp_frame_cleanup(&tf);
-  return found_block;
-}
-
-/*
- * Perform break, if there is a `finally` block in effect, transfer
- * control there.
- */
-static void bcode_perform_break(struct v7 *v7, struct bcode_registers *r) {
-  enum local_block found;
-  unsigned int mask;
-  v7->is_breaking = 0;
-  if (v7->is_continuing) {
-    mask = LOCAL_BLOCK_LOOP;
-  } else {
-    mask = LOCAL_BLOCK_LOOP | LOCAL_BLOCK_SWITCH;
-  }
-
-  /*
-   * Keep unwinding until we find local block of interest. We should not
-   * encounter any "function" frames; only "private" frames are allowed.
-   */
-  for (;;) {
-    /*
-     * Try to unwind local "try stack", considering only `finally` and `break`.
-     */
-    found = unwind_local_blocks_stack(v7, r, mask | LOCAL_BLOCK_FINALLY, 0);
-    if (found == LOCAL_BLOCK_NONE) {
-      /*
-       * no blocks found: this may happen if only the `break` or `continue` has
-       * occurred inside "private" frame. So, unwind this frame, make sure it
-       * is indeed a "private" frame, and keep unwinding local blocks.
-       */
-      v7_call_frame_mask_t frame_type_mask = unwind_stack_1level(v7, r);
-      assert(frame_type_mask == V7_CALL_FRAME_MASK_PRIVATE);
-      (void) frame_type_mask;
-    } else {
-      /* found some block to transfer control into, stop unwinding */
-      break;
-    }
-  }
-
-  /*
-   * upon exit of a finally block we'll reenter here if is_breaking is true.
-   * See OP_AFTER_FINALLY.
-   */
-  if (found == LOCAL_BLOCK_FINALLY) {
-    v7->is_breaking = 1;
-  }
-
-  /* `ops` already points to the needed instruction, no need to increment it */
-  r->need_inc_ops = 0;
-}
-
-/*
- * Perform return, but if there is a `finally` block in effect, transfer
- * control there.
- *
- * If `take_retval` is non-zero, value to return will be popped from stack
- * (and saved into `v7->vals.returned_value`), otherwise, it won't ae affected.
- */
-static enum v7_err bcode_perform_return(struct v7 *v7,
-                                        struct bcode_registers *r,
-                                        int take_retval) {
-  /*
-   * We should either take retval from the stack, or some value should already
-   * de pending to return
-   */
-  assert(take_retval || v7->is_returned);
-
-  if (take_retval) {
-    /* taking return value from stack */
-    v7->vals.returned_value = POP();
-    v7->is_returned = 1;
-
-    /*
-     * returning (say, from `finally`) dismisses any errors that are eeing
-     * thrown at the moment as well
-     */
-    v7->is_thrown = 0;
-    v7->vals.thrown_error = V7_UNDEFINED;
-  }
-
-  /*
-   * Keep unwinding until we unwound "function" frame, or found some `finally`
-   * block.
-   */
-  for (;;) {
-    /* Try to unwind local "try stack", considering only `finally` blocks */
-    if (unwind_local_blocks_stack(v7, r, (LOCAL_BLOCK_FINALLY), 0) ==
-        LOCAL_BLOCK_NONE) {
-      /*
-       * no `finally` blocks were found, so, unwind stack by 1 level, and see
-       * if it's a "function" frame. If not, will keep unwinding.
-       */
-      if (unwind_stack_1level(v7, r) & V7_CALL_FRAME_MASK_BCODE) {
-        /*
-         * unwound frame is a "function" frame, so, push returned value to
-         * stack, and stop unwinding
-         */
-        PUSH(v7->vals.returned_value);
-        v7->is_returned = 0;
-        v7->vals.returned_value = V7_UNDEFINED;
-
-        break;
-      }
-    } else {
-      /* found `finally` block, so, stop unwinding */
-      break;
-    }
-  }
-
-  /* `ops` already points to the needed instruction, no need to increment it */
-  r->need_inc_ops = 0;
-
-  return V7_OK;
-}
-
-/*
- * Perform throw inside `eval_bcode()`.
- *
- * If `take_thrown_value` is non-zero, value to return will be popped from
- * stack (and saved into `v7->vals.thrown_error`), otherwise, it won't be
- * affected.
- *
- * Returns `V7_OK` if thrown exception was caught, `V7_EXEC_EXCEPTION`
- * otherwise (in this case, evaluation of current script must be stopped)
- *
- * When calling this function from `eval_rcode()`, you should wrap this call
- * into the `V7_TRY()` macro.
- */
-static enum v7_err bcode_perform_throw(struct v7 *v7, struct bcode_registers *r,
-                                       int take_thrown_value) {
-  enum v7_err rcode = V7_OK;
-  enum local_block found;
-
-  assert(take_thrown_value || v7->is_thrown);
-
-  if (take_thrown_value) {
-    v7->vals.thrown_error = POP();
-    v7->is_thrown = 1;
-
-    /* Throwing dismisses any pending return values */
-    v7->is_returned = 0;
-    v7->vals.returned_value = V7_UNDEFINED;
-  }
-
-  while ((found = unwind_local_blocks_stack(
-              v7, r, (LOCAL_BLOCK_CATCH | LOCAL_BLOCK_FINALLY), 1)) ==
-         LOCAL_BLOCK_NONE) {
-    if (v7->call_stack != v7->bottom_call_frame) {
-#ifdef V7_BCODE_TRACE
-      fprintf(stderr, "not at the bottom of the stack, going to unwind..\n");
-#endif
-      /* not reached bottom of the stack yet, keep unwinding */
-      unwind_stack_1level(v7, r);
-    } else {
-/* reached stack bottom: uncaught exception */
-#ifdef V7_BCODE_TRACE
-      fprintf(stderr, "reached stack bottom: uncaught exception\n");
-#endif
-      rcode = V7_EXEC_EXCEPTION;
-      break;
-    }
-  }
-
-  if (found == LOCAL_BLOCK_CATCH) {
-    /*
-     * we're going to enter `catch` block, so, populate TOS with the thrown
-     * value, and clear it in v7 context.
-     */
-    PUSH(v7->vals.thrown_error);
-    v7->is_thrown = 0;
-    v7->vals.thrown_error = V7_UNDEFINED;
-  }
-
-  /* `ops` already points to the needed instruction, no need to increment it */
-  r->need_inc_ops = 0;
-
-  return rcode;
-}
-
-/*
- * Throws reference error from `eval_bcode()`. Always wrap a call to this
- * function into `V7_TRY()`.
- */
-static enum v7_err bcode_throw_reference_error(struct v7 *v7,
-                                               struct bcode_registers *r,
-                                               val_t var_name) {
-  enum v7_err rcode = V7_OK;
-  const char *s;
-  size_t name_len;
-
-  assert(v7_is_string(var_name));
-  s = v7_get_string(v7, &var_name, &name_len);
-
-  rcode = v7_throwf(v7, REFERENCE_ERROR, "[%.*s] is not defined",
-                    (int) name_len, s);
-  (void) rcode;
-  return bcode_perform_throw(v7, r, 0);
-}
-
-/*
- * Takes a half-done function (either from literal table or deserialized from
- * `ops` inlined data), and returns a ready-to-use function.
- *
- * The actual behaviour depends on whether the half-done function has
- * `prototype` defined. If there's no prototype (i.e. it's `undefined`), then
- * the new function is created, with bcode from a given one. If, however,
- * the prototype is defined, it means that the function was just deserialized
- * from `ops`, so we only need to set `scope` on it.
- *
- * Assumes `func` is owned by the caller.
- */
-static val_t bcode_instantiate_function(struct v7 *v7, val_t func) {
-  val_t res;
-  struct v7_generic_object *scope;
-  struct v7_js_function *f;
-  assert(is_js_function(func));
-  f = get_js_function_struct(func);
-
-  scope = get_generic_object_struct(get_scope(v7));
-
-  if (v7_is_undefined(v7_get(v7, func, "prototype", 9))) {
-    /*
-     * Function's `prototype` is `undefined`: it means that the function is
-     * created by the compiler and is stored in the literal table. We have to
-     * create completely new function
-     */
-    struct v7_js_function *rf;
-
-    res = mk_js_function(v7, scope, v7_mk_object(v7));
-
-    /* Copy and retain bcode */
-    rf = get_js_function_struct(res);
-    rf->bcode = f->bcode;
-    retain_bcode(v7, rf->bcode);
-  } else {
-    /*
-     * Function's `prototype` is NOT `undefined`: it means that the function is
-     * deserialized from inline `ops` data, and we just need to set scope on
-     * it.
-     */
-    res = func;
-    f->scope = scope;
-  }
-
-  return res;
-}
-
-/**
- * Call C function `func` with given `this_object` and array of arguments
- * `args`. `func` should be a C function pointer, not C function object.
- */
-static enum v7_err call_cfunction(struct v7 *v7, val_t func, val_t this_object,
-                                  val_t args, uint8_t is_constructor,
-                                  val_t *res) {
-  enum v7_err rcode = V7_OK;
-  uint8_t saved_inhibit_gc = v7->inhibit_gc;
-  val_t saved_arguments = v7->vals.arguments;
-  struct gc_tmp_frame tf = new_tmp_frame(v7);
-  v7_cfunction_t *cfunc = get_cfunction_ptr(v7, func);
-
-  *res = V7_UNDEFINED;
-
-  tmp_stack_push(&tf, &saved_arguments);
-
-  append_call_frame_cfunc(v7, this_object, cfunc);
-
-  /*
-   * prepare cfunction environment
-   */
-  v7->inhibit_gc = 1;
-  v7->vals.arguments = args;
-
-  /* call C function */
-  rcode = cfunc(v7, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (is_constructor && !v7_is_object(*res)) {
-    /* constructor returned non-object: replace it with `this` */
-    *res = v7_get_this(v7);
-  }
-
-clean:
-  v7->vals.arguments = saved_arguments;
-  v7->inhibit_gc = saved_inhibit_gc;
-
-  unwind_stack_1level(v7, NULL);
-
-  tmp_frame_cleanup(&tf);
-  return rcode;
-}
-
-/*
- * Evaluate `OP_TRY_PUSH_CATCH` or `OP_TRY_PUSH_FINALLY`: Take an offset (from
- * the parameter of opcode) and push it onto "try stack"
- */
-static void eval_try_push(struct v7 *v7, enum opcode op,
-                          struct bcode_registers *r) {
-  val_t arr = V7_UNDEFINED;
-  struct gc_tmp_frame tf = new_tmp_frame(v7);
-  bcode_off_t target;
-  int64_t offset_tag = 0;
-
-  tmp_stack_push(&tf, &arr);
-
-  /* make sure "try stack" array exists */
-  arr = find_call_frame_private(v7)->vals.try_stack;
-  if (!v7_is_array(v7, arr)) {
-    arr = v7_mk_dense_array(v7);
-    find_call_frame_private(v7)->vals.try_stack = arr;
-  }
-
-  /*
-   * push the target address at the end of the "try stack" array
-   */
-  switch (op) {
-    case OP_TRY_PUSH_CATCH:
-      offset_tag = LBLOCK_TAG_CATCH;
-      break;
-    case OP_TRY_PUSH_FINALLY:
-      offset_tag = LBLOCK_TAG_FINALLY;
-      break;
-    case OP_TRY_PUSH_LOOP:
-      offset_tag = LBLOCK_TAG_LOOP;
-      break;
-    case OP_TRY_PUSH_SWITCH:
-      offset_tag = LBLOCK_TAG_SWITCH;
-      break;
-    default:
-      assert(0);
-      break;
-  }
-  target = bcode_get_target(&r->ops);
-  v7_array_push(v7, arr, v7_mk_number(v7, LBLOCK_ITEM_CREATE(target, offset_tag,
-                                                             v7->stack.len)));
-
-  tmp_frame_cleanup(&tf);
-}
-
-/*
- * Evaluate `OP_TRY_POP`: just pop latest item from "try stack", ignoring it
- */
-static enum v7_err eval_try_pop(struct v7 *v7) {
-  enum v7_err rcode = V7_OK;
-  val_t arr = V7_UNDEFINED;
-  unsigned long length;
-  struct gc_tmp_frame tf = new_tmp_frame(v7);
-
-  tmp_stack_push(&tf, &arr);
-
-  /* get "try stack" array, which must be defined and must not be emtpy */
-  arr = find_call_frame_private(v7)->vals.try_stack;
-  if (!v7_is_array(v7, arr)) {
-    rcode = v7_throwf(v7, "Error", "TRY_POP when try_stack is not an array");
-    V7_TRY(V7_INTERNAL_ERROR);
-  }
-
-  length = v7_array_length(v7, arr);
-  if (length == 0) {
-    rcode = v7_throwf(v7, "Error", "TRY_POP when try_stack is empty");
-    V7_TRY(V7_INTERNAL_ERROR);
-  }
-
-  /* delete the latest element of this array */
-  v7_array_del(v7, arr, length - 1);
-
-clean:
-  tmp_frame_cleanup(&tf);
-  return rcode;
-}
-
-static void own_bcode(struct v7 *v7, struct bcode *p) {
-  mbuf_append(&v7->act_bcodes, &p, sizeof(p));
-}
-
-static void disown_bcode(struct v7 *v7, struct bcode *p) {
-#ifndef NDEBUG
-  struct bcode **vp =
-      (struct bcode **) (v7->act_bcodes.buf + v7->act_bcodes.len - sizeof(p));
-
-  /* given `p` should be the last item */
-  assert(*vp == p);
-#endif
-  v7->act_bcodes.len -= sizeof(p);
-}
-
-/* Keeps track of last evaluated bcodes in order to improve error reporting */
-static void push_bcode_history(struct v7 *v7, enum opcode op) {
-  size_t i;
-
-  if (op == OP_CHECK_CALL || op == OP_CALL || op == OP_NEW) return;
-
-  for (i = ARRAY_SIZE(v7->last_ops) - 1; i > 0; i--) {
-    v7->last_ops[i] = v7->last_ops[i - 1];
-  }
-  v7->last_ops[0] = op;
-}
-
-#ifndef V7_DISABLE_CALL_ERROR_CONTEXT
-static void reset_last_name(struct v7 *v7) {
-  v7->vals.last_name[0] = V7_UNDEFINED;
-  v7->vals.last_name[1] = V7_UNDEFINED;
-}
-#else
-static void reset_last_name(struct v7 *v7) {
-  /* should be inlined out */
-  (void) v7;
-}
-#endif
-
-static void prop_iter_ctx_dtor(struct v7 *v7, void *ud) {
-  struct prop_iter_ctx *ctx = (struct prop_iter_ctx *) ud;
-  v7_destruct_prop_iter_ctx(v7, ctx);
-  free(ctx);
-}
-
-/*
- * Evaluates given `bcode`. If `reset_line_no` is non-zero, the line number
- * is initially reset to 1; otherwise, it is inherited from the previous call
- * frame.
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err eval_bcode(struct v7 *v7, struct bcode *bcode,
-                                  val_t this_object, uint8_t reset_line_no,
-                                  val_t *_res) {
-  struct bcode_registers r;
-  enum v7_err rcode = V7_OK;
-  struct v7_call_frame_base *saved_bottom_call_frame = v7->bottom_call_frame;
-
-  /*
-   * Dummy variable just to enforce that `BTRY()` macro is used only inside the
-   * `eval_bcode()` function
-   */
-  uint8_t _you_should_use_BTRY_in_eval_bcode_only = 0;
-
-  char buf[512];
-
-  val_t res = V7_UNDEFINED, v1 = V7_UNDEFINED, v2 = V7_UNDEFINED,
-        v3 = V7_UNDEFINED, v4 = V7_UNDEFINED, scope_frame = V7_UNDEFINED;
-  struct gc_tmp_frame tf = new_tmp_frame(v7);
-
-  append_call_frame_bcode(v7, NULL, bcode, this_object, get_scope(v7), 0);
-
-  if (reset_line_no) {
-    v7->call_stack->line_no = 1;
-  }
-
-  /*
-   * Set current call stack as the "bottom" call stack, so that bcode evaluator
-   * will exit when it reaches this "bottom"
-   */
-  v7->bottom_call_frame = v7->call_stack;
-
-  bcode_restore_registers(v7, bcode, &r);
-
-  tmp_stack_push(&tf, &res);
-  tmp_stack_push(&tf, &v1);
-  tmp_stack_push(&tf, &v2);
-  tmp_stack_push(&tf, &v3);
-  tmp_stack_push(&tf, &v4);
-  tmp_stack_push(&tf, &scope_frame);
-
-  /*
-   * populate local variables on current scope, making them undeletable
-   * (since they're defined with `var`)
-   */
-  {
-    size_t i;
-    for (i = 0; i < bcode->names_cnt; ++i) {
-      r.ops = bcode_next_name_v(v7, bcode, r.ops, &v1);
-
-      /* set undeletable property on current scope */
-      V7_TRY(def_property_v(v7, get_scope(v7), v1, V7_DESC_CONFIGURABLE(0),
-                            V7_UNDEFINED, 1 /*as_assign*/, NULL));
-    }
-  }
-
-restart:
-  while (r.ops < r.end && rcode == V7_OK) {
-    enum opcode op = (enum opcode) * r.ops;
-
-#ifndef V7_DISABLE_LINE_NUMBERS
-    if ((uint8_t) op >= _OP_LINE_NO) {
-      unsigned char buf[sizeof(size_t)];
-      int len;
-      size_t max_llen = sizeof(buf);
-
-      /* ASAN doesn't like out of bound reads */
-      if (r.ops + max_llen > r.end) {
-        max_llen = r.end - r.ops;
-      }
-
-      /*
-       * before we decode varint, we'll have to swap MSB and LSB, but we can't
-       * do it in place since we're decoding from constant memory, so, we also
-       * have to copy the data to the temp buffer first. 4 bytes should be
-       * enough for everyone's line number.
-       */
-      memcpy(buf, r.ops, max_llen);
-      buf[0] = msb_lsb_swap(buf[0]);
-
-      v7->call_stack->line_no = decode_varint(buf, &len) >> 1;
-      assert((size_t) len <= sizeof(buf));
-      r.ops += len;
-
-      continue;
-    }
-#endif
-
-    push_bcode_history(v7, op);
-
-    if (v7->need_gc) {
-      if (maybe_gc(v7)) {
-        v7->need_gc = 0;
-      }
-    }
-
-    r.need_inc_ops = 1;
-#ifdef V7_BCODE_TRACE
-    {
-      char *dops = r.ops;
-      fprintf(stderr, "eval ");
-      dump_op(v7, stderr, r.bcode, &dops);
-    }
-#endif
-
-    switch (op) {
-      case OP_DROP:
-        POP();
-        break;
-      case OP_DUP:
-        v1 = POP();
-        PUSH(v1);
-        PUSH(v1);
-        break;
-      case OP_2DUP:
-        v2 = POP();
-        v1 = POP();
-        PUSH(v1);
-        PUSH(v2);
-        PUSH(v1);
-        PUSH(v2);
-        break;
-      case OP_SWAP:
-        v1 = POP();
-        v2 = POP();
-        PUSH(v1);
-        PUSH(v2);
-        break;
-      case OP_STASH:
-        assert(!v7->is_stashed);
-        v7->vals.stash = TOS();
-        v7->is_stashed = 1;
-        break;
-      case OP_UNSTASH:
-        assert(v7->is_stashed);
-        POP();
-        PUSH(v7->vals.stash);
-        v7->vals.stash = V7_UNDEFINED;
-        v7->is_stashed = 0;
-        break;
-
-      case OP_SWAP_DROP:
-        v1 = POP();
-        POP();
-        PUSH(v1);
-        break;
-
-      case OP_PUSH_UNDEFINED:
-        PUSH(V7_UNDEFINED);
-        break;
-      case OP_PUSH_NULL:
-        PUSH(V7_NULL);
-        break;
-      case OP_PUSH_THIS:
-        PUSH(v7_get_this(v7));
-        reset_last_name(v7);
-        break;
-      case OP_PUSH_TRUE:
-        PUSH(v7_mk_boolean(v7, 1));
-        reset_last_name(v7);
-        break;
-      case OP_PUSH_FALSE:
-        PUSH(v7_mk_boolean(v7, 0));
-        reset_last_name(v7);
-        break;
-      case OP_PUSH_ZERO:
-        PUSH(v7_mk_number(v7, 0));
-        reset_last_name(v7);
-        break;
-      case OP_PUSH_ONE:
-        PUSH(v7_mk_number(v7, 1));
-        reset_last_name(v7);
-        break;
-      case OP_PUSH_LIT: {
-        PUSH(bcode_decode_lit(v7, r.bcode, &r.ops));
-#ifndef V7_DISABLE_CALL_ERROR_CONTEXT
-        /* name tracking */
-        if (!v7_is_string(TOS())) {
-          reset_last_name(v7);
-        }
-#endif
-        break;
-      }
-      case OP_LOGICAL_NOT:
-        v1 = POP();
-        PUSH(v7_mk_boolean(v7, !v7_is_truthy(v7, v1)));
-        break;
-      case OP_NOT: {
-        v1 = POP();
-        BTRY(to_number_v(v7, v1, &v1));
-        PUSH(v7_mk_number(v7, ~(int32_t) v7_get_double(v7, v1)));
-        break;
-      }
-      case OP_NEG: {
-        v1 = POP();
-        BTRY(to_number_v(v7, v1, &v1));
-        PUSH(v7_mk_number(v7, -v7_get_double(v7, v1)));
-        break;
-      }
-      case OP_POS: {
-        v1 = POP();
-        BTRY(to_number_v(v7, v1, &v1));
-        PUSH(v1);
-        break;
-      }
-      case OP_ADD: {
-        v2 = POP();
-        v1 = POP();
-
-        /*
-         * If either operand is an object, convert both of them to primitives
-         */
-        if (v7_is_object(v1) || v7_is_object(v2)) {
-          BTRY(to_primitive(v7, v1, V7_TO_PRIMITIVE_HINT_AUTO, &v1));
-          BTRY(to_primitive(v7, v2, V7_TO_PRIMITIVE_HINT_AUTO, &v2));
-        }
-
-        if (v7_is_string(v1) || v7_is_string(v2)) {
-          /* Convert both operands to strings, and concatenate */
-
-          BTRY(primitive_to_str(v7, v1, &v1, NULL, 0, NULL));
-          BTRY(primitive_to_str(v7, v2, &v2, NULL, 0, NULL));
-
-          PUSH(s_concat(v7, v1, v2));
-        } else {
-          /* Convert both operands to numbers, and sum */
-
-          BTRY(primitive_to_number(v7, v1, &v1));
-          BTRY(primitive_to_number(v7, v2, &v2));
-
-          PUSH(v7_mk_number(v7, b_num_bin_op(op, v7_get_double(v7, v1),
-                                             v7_get_double(v7, v2))));
-        }
-        break;
-      }
-      case OP_SUB:
-      case OP_REM:
-      case OP_MUL:
-      case OP_DIV:
-      case OP_LSHIFT:
-      case OP_RSHIFT:
-      case OP_URSHIFT:
-      case OP_OR:
-      case OP_XOR:
-      case OP_AND: {
-        v2 = POP();
-        v1 = POP();
-
-        BTRY(to_number_v(v7, v1, &v1));
-        BTRY(to_number_v(v7, v2, &v2));
-
-        PUSH(v7_mk_number(v7, b_num_bin_op(op, v7_get_double(v7, v1),
-                                           v7_get_double(v7, v2))));
-        break;
-      }
-      case OP_EQ_EQ: {
-        v2 = POP();
-        v1 = POP();
-        if (v7_is_string(v1) && v7_is_string(v2)) {
-          res = v7_mk_boolean(v7, s_cmp(v7, v1, v2) == 0);
-        } else if (v1 == v2 && v1 == V7_TAG_NAN) {
-          res = v7_mk_boolean(v7, 0);
-        } else {
-          res = v7_mk_boolean(v7, v1 == v2);
-        }
-        PUSH(res);
-        break;
-      }
-      case OP_NE_NE: {
-        v2 = POP();
-        v1 = POP();
-        if (v7_is_string(v1) && v7_is_string(v2)) {
-          res = v7_mk_boolean(v7, s_cmp(v7, v1, v2) != 0);
-        } else if (v1 == v2 && v1 == V7_TAG_NAN) {
-          res = v7_mk_boolean(v7, 1);
-        } else {
-          res = v7_mk_boolean(v7, v1 != v2);
-        }
-        PUSH(res);
-        break;
-      }
-      case OP_EQ:
-      case OP_NE: {
-        v2 = POP();
-        v1 = POP();
-        /*
-         * TODO(dfrank) : it's not really correct. Fix it accordingly to
-         * the p. 4.9 of The Definitive Guide (page 71)
-         */
-        if (((v7_is_object(v1) || v7_is_object(v2)) && v1 == v2)) {
-          res = v7_mk_boolean(v7, op == OP_EQ);
-          PUSH(res);
-          break;
-        } else if (v7_is_undefined(v1) || v7_is_null(v1)) {
-          res = v7_mk_boolean(
-              v7, (op != OP_EQ) ^ (v7_is_undefined(v2) || v7_is_null(v2)));
-          PUSH(res);
-          break;
-        } else if (v7_is_undefined(v2) || v7_is_null(v2)) {
-          res = v7_mk_boolean(
-              v7, (op != OP_EQ) ^ (v7_is_undefined(v1) || v7_is_null(v1)));
-          PUSH(res);
-          break;
-        }
-
-        if (v7_is_string(v1) && v7_is_string(v2)) {
-          int cmp = s_cmp(v7, v1, v2);
-          switch (op) {
-            case OP_EQ:
-              res = v7_mk_boolean(v7, cmp == 0);
-              break;
-            case OP_NE:
-              res = v7_mk_boolean(v7, cmp != 0);
-              break;
-            default:
-              /* should never be here */
-              assert(0);
-          }
-        } else {
-          /* Convert both operands to numbers */
-
-          BTRY(to_number_v(v7, v1, &v1));
-          BTRY(to_number_v(v7, v2, &v2));
-
-          res = v7_mk_boolean(v7, b_bool_bin_op(op, v7_get_double(v7, v1),
-                                                v7_get_double(v7, v2)));
-        }
-        PUSH(res);
-        break;
-      }
-      case OP_LT:
-      case OP_LE:
-      case OP_GT:
-      case OP_GE: {
-        v2 = POP();
-        v1 = POP();
-        BTRY(to_primitive(v7, v1, V7_TO_PRIMITIVE_HINT_NUMBER, &v1));
-        BTRY(to_primitive(v7, v2, V7_TO_PRIMITIVE_HINT_NUMBER, &v2));
-
-        if (v7_is_string(v1) && v7_is_string(v2)) {
-          int cmp = s_cmp(v7, v1, v2);
-          switch (op) {
-            case OP_LT:
-              res = v7_mk_boolean(v7, cmp < 0);
-              break;
-            case OP_LE:
-              res = v7_mk_boolean(v7, cmp <= 0);
-              break;
-            case OP_GT:
-              res = v7_mk_boolean(v7, cmp > 0);
-              break;
-            case OP_GE:
-              res = v7_mk_boolean(v7, cmp >= 0);
-              break;
-            default:
-              /* should never be here */
-              assert(0);
-          }
-        } else {
-          /* Convert both operands to numbers */
-
-          BTRY(to_number_v(v7, v1, &v1));
-          BTRY(to_number_v(v7, v2, &v2));
-
-          res = v7_mk_boolean(v7, b_bool_bin_op(op, v7_get_double(v7, v1),
-                                                v7_get_double(v7, v2)));
-        }
-        PUSH(res);
-        break;
-      }
-      case OP_INSTANCEOF: {
-        v2 = POP();
-        v1 = POP();
-        if (!v7_is_callable(v7, v2)) {
-          BTRY(v7_throwf(v7, TYPE_ERROR,
-                         "Expecting a function in instanceof check"));
-          goto op_done;
-        } else {
-          PUSH(v7_mk_boolean(
-              v7, is_prototype_of(v7, v1, v7_get(v7, v2, "prototype", 9))));
-        }
-        break;
-      }
-      case OP_TYPEOF:
-        v1 = POP();
-        switch (val_type(v7, v1)) {
-          case V7_TYPE_NUMBER:
-            res = v7_mk_string(v7, "number", 6, 1);
-            break;
-          case V7_TYPE_STRING:
-            res = v7_mk_string(v7, "string", 6, 1);
-            break;
-          case V7_TYPE_BOOLEAN:
-            res = v7_mk_string(v7, "boolean", 7, 1);
-            break;
-          case V7_TYPE_FUNCTION_OBJECT:
-          case V7_TYPE_CFUNCTION_OBJECT:
-          case V7_TYPE_CFUNCTION:
-            res = v7_mk_string(v7, "function", 8, 1);
-            break;
-          case V7_TYPE_UNDEFINED:
-            res = v7_mk_string(v7, "undefined", 9, 1);
-            break;
-          default:
-            res = v7_mk_string(v7, "object", 6, 1);
-            break;
-        }
-        PUSH(res);
-        break;
-      case OP_IN: {
-        struct v7_property *prop = NULL;
-        v2 = POP();
-        v1 = POP();
-        BTRY(to_string(v7, v1, NULL, buf, sizeof(buf), NULL));
-        prop = v7_get_property(v7, v2, buf, ~0);
-        PUSH(v7_mk_boolean(v7, prop != NULL));
-      } break;
-      case OP_GET:
-        v2 = POP();
-        v1 = POP();
-        BTRY(v7_get_throwing_v(v7, v1, v2, &v3));
-        PUSH(v3);
-#ifndef V7_DISABLE_CALL_ERROR_CONTEXT
-        v7->vals.last_name[1] = v7->vals.last_name[0];
-        v7->vals.last_name[0] = v2;
-#endif
-        break;
-      case OP_SET: {
-        v3 = POP();
-        v2 = POP();
-        v1 = POP();
-
-        /* convert name to string, if it's not already */
-        BTRY(to_string(v7, v2, &v2, NULL, 0, NULL));
-
-        /* set value */
-        BTRY(set_property_v(v7, v1, v2, v3, NULL));
-
-        PUSH(v3);
-        break;
-      }
-      case OP_GET_VAR:
-      case OP_SAFE_GET_VAR: {
-        struct v7_property *p = NULL;
-        assert(r.ops < r.end - 1);
-        v1 = bcode_decode_lit(v7, r.bcode, &r.ops);
-        BTRY(v7_get_property_v(v7, get_scope(v7), v1, &p));
-        if (p == NULL) {
-          if (op == OP_SAFE_GET_VAR) {
-            PUSH(V7_UNDEFINED);
-          } else {
-            /* variable does not exist: Reference Error */
-            V7_TRY(bcode_throw_reference_error(v7, &r, v1));
-            goto op_done;
-          }
-          break;
-        } else {
-          BTRY(v7_property_value(v7, get_scope(v7), p, &v2));
-          PUSH(v2);
-        }
-#ifndef V7_DISABLE_CALL_ERROR_CONTEXT
-        v7->vals.last_name[0] = v1;
-        v7->vals.last_name[1] = V7_UNDEFINED;
-#endif
-        break;
-      }
-      case OP_SET_VAR: {
-        struct v7_property *prop;
-        v3 = POP();
-        v2 = bcode_decode_lit(v7, r.bcode, &r.ops);
-        v1 = get_scope(v7);
-
-        BTRY(to_string(v7, v2, NULL, buf, sizeof(buf), NULL));
-        prop = v7_get_property(v7, v1, buf, strlen(buf));
-        if (prop != NULL) {
-          /* Property already exists: update its value */
-          /*
-           * TODO(dfrank): currently we can't use `def_property_v()` here,
-           * because if the property was already found somewhere in the
-           * prototype chain, then it should be updated, instead of creating a
-           * new one on the top of the scope.
-           *
-           * Probably we need to make `def_property_v()` more generic and
-           * use it here; or split `def_property_v()` into smaller pieces and
-           * use one of them here.
-           */
-          if (!(prop->attributes & V7_PROPERTY_NON_WRITABLE)) {
-            prop->value = v3;
-          }
-        } else if (!r.bcode->strict_mode) {
-          /*
-           * Property does not exist: since we're not in strict mode, let's
-           * create new property at Global Object
-           */
-          BTRY(set_property_v(v7, v7_get_global(v7), v2, v3, NULL));
-        } else {
-          /*
-           * In strict mode, throw reference error instead of polluting Global
-           * Object
-           */
-          V7_TRY(bcode_throw_reference_error(v7, &r, v2));
-          goto op_done;
-        }
-        PUSH(v3);
-        break;
-      }
-      case OP_JMP: {
-        bcode_off_t target = bcode_get_target(&r.ops);
-        r.ops = r.bcode->ops.p + target - 1;
-        break;
-      }
-      case OP_JMP_FALSE: {
-        bcode_off_t target = bcode_get_target(&r.ops);
-        v1 = POP();
-        if (!v7_is_truthy(v7, v1)) {
-          r.ops = r.bcode->ops.p + target - 1;
-        }
-        break;
-      }
-      case OP_JMP_TRUE: {
-        bcode_off_t target = bcode_get_target(&r.ops);
-        v1 = POP();
-        if (v7_is_truthy(v7, v1)) {
-          r.ops = r.bcode->ops.p + target - 1;
-        }
-        break;
-      }
-      case OP_JMP_TRUE_DROP: {
-        bcode_off_t target = bcode_get_target(&r.ops);
-        v1 = POP();
-        if (v7_is_truthy(v7, v1)) {
-          r.ops = r.bcode->ops.p + target - 1;
-          v1 = POP();
-          POP();
-          PUSH(v1);
-        }
-        break;
-      }
-      case OP_JMP_IF_CONTINUE: {
-        bcode_off_t target = bcode_get_target(&r.ops);
-        if (v7->is_continuing) {
-          r.ops = r.bcode->ops.p + target - 1;
-        }
-        v7->is_continuing = 0;
-        break;
-      }
-      case OP_CREATE_OBJ:
-        PUSH(v7_mk_object(v7));
-        break;
-      case OP_CREATE_ARR:
-        PUSH(v7_mk_array(v7));
-        break;
-      case OP_PUSH_PROP_ITER_CTX: {
-        struct prop_iter_ctx *ctx =
-            (struct prop_iter_ctx *) calloc(1, sizeof(*ctx));
-        BTRY(init_prop_iter_ctx(v7, TOS(), 1, ctx));
-        v1 = v7_mk_object(v7);
-        v7_set_user_data(v7, v1, ctx);
-        v7_set_destructor_cb(v7, v1, prop_iter_ctx_dtor);
-        PUSH(v1);
-        break;
-      }
-      case OP_NEXT_PROP: {
-        struct prop_iter_ctx *ctx = NULL;
-        int ok = 0;
-        v1 = POP(); /* ctx */
-        v2 = POP(); /* object */
-
-        ctx = (struct prop_iter_ctx *) v7_get_user_data(v7, v1);
-
-        if (v7_is_object(v2)) {
-          v7_prop_attr_t attrs;
-
-          do {
-            /* iterate properties until we find a non-hidden enumerable one */
-            do {
-              BTRY(next_prop(v7, ctx, &res, NULL, &attrs, &ok));
-            } while (ok && (attrs & (_V7_PROPERTY_HIDDEN |
-                                     V7_PROPERTY_NON_ENUMERABLE)));
-
-            if (!ok) {
-              /* no more properties in this object: proceed to the prototype */
-              v2 = v7_get_proto(v7, v2);
-              if (get_generic_object_struct(v2) != NULL) {
-                /*
-                 * the prototype is a generic object, so, init the context for
-                 * props iteration
-                 */
-                v7_destruct_prop_iter_ctx(v7, ctx);
-                BTRY(init_prop_iter_ctx(v7, v2, 1, ctx));
-              } else {
-                /*
-                 * we can't iterate the prototype's props, so, just stop
-                 * iteration.
-                 */
-                ctx = NULL;
-              }
-            }
-          } while (!ok && ctx != NULL);
-        } else {
-          /*
-           * Not an object: reset the context.
-           */
-          ctx = NULL;
-        }
-
-        if (ctx == NULL) {
-          PUSH(v7_mk_boolean(v7, 0));
-
-          /*
-           * We could leave the context unfreed, and let the
-           * `prop_iter_ctx_dtor()` free it when the v1 will be GC-d, but
-           * let's do that earlier.
-           */
-          ctx = (struct prop_iter_ctx *) v7_get_user_data(v7, v1);
-          v7_destruct_prop_iter_ctx(v7, ctx);
-          free(ctx);
-          v7_set_user_data(v7, v1, NULL);
-          v7_set_destructor_cb(v7, v1, NULL);
-        } else {
-          PUSH(v2);
-          PUSH(v1);
-          PUSH(res);
-          PUSH(v7_mk_boolean(v7, 1));
-        }
-        break;
-      }
-      case OP_FUNC_LIT: {
-        v1 = POP();
-        v2 = bcode_instantiate_function(v7, v1);
-        PUSH(v2);
-        break;
-      }
-      case OP_CHECK_CALL:
-        v1 = TOS();
-        if (!v7_is_callable(v7, v1)) {
-          int arity = 0;
-          enum v7_err ignore;
-/* tried to call non-function object: throw a TypeError */
-
-#ifndef V7_DISABLE_CALL_ERROR_CONTEXT
-          /*
-           * try to provide some useful context for the error message
-           * using a good-enough heuristics
-           * but defer actual throw when process the incriminated call
-           * in order to evaluate the arguments as required by the spec.
-           */
-          if (v7->last_ops[0] == OP_GET_VAR) {
-            arity = 1;
-          } else if (v7->last_ops[0] == OP_GET &&
-                     v7->last_ops[1] == OP_PUSH_LIT) {
-            /*
-             * OP_PUSH_LIT is used to both push property names for OP_GET
-             * and for pushing actual literals. During PUSH_LIT push lit
-             * evaluation we reset the last name variable in case the literal
-             * is not a string, such as in `[].foo()`.
-             * Unfortunately it doesn't handle `"foo".bar()`; could be
-             * solved by adding another bytecode for property literals but
-             * probably it doesn't matter much.
-             */
-            if (v7_is_undefined(v7->vals.last_name[1])) {
-              arity = 1;
-            } else {
-              arity = 2;
-            }
-          }
-#endif
-
-          switch (arity) {
-            case 0:
-              ignore = v7_throwf(v7, TYPE_ERROR, "value is not a function");
-              break;
-#ifndef V7_DISABLE_CALL_ERROR_CONTEXT
-
-            case 1:
-              ignore = v7_throwf(v7, TYPE_ERROR, "%s is not a function",
-                                 v7_get_cstring(v7, &v7->vals.last_name[0]));
-              break;
-            case 2:
-              ignore = v7_throwf(v7, TYPE_ERROR, "%s.%s is not a function",
-                                 v7_get_cstring(v7, &v7->vals.last_name[1]),
-                                 v7_get_cstring(v7, &v7->vals.last_name[0]));
-              break;
-#endif
-          };
-
-          v7->vals.call_check_ex = v7->vals.thrown_error;
-          v7_clear_thrown_value(v7);
-          (void) ignore;
-        }
-        break;
-      case OP_CALL:
-      case OP_NEW: {
-        /* Naive implementation pending stack frame redesign */
-        int args = (int) *(++r.ops);
-        uint8_t is_constructor = (op == OP_NEW);
-
-        if (SP() < (args + 1 /*func*/ + 1 /*this*/)) {
-          BTRY(v7_throwf(v7, INTERNAL_ERROR, "stack underflow"));
-          goto op_done;
-        } else {
-          v2 = v7_mk_dense_array(v7);
-          while (args > 0) {
-            BTRY(v7_array_set_throwing(v7, v2, --args, POP(), NULL));
-          }
-          /* pop function to call */
-          v1 = POP();
-
-          /* pop `this` */
-          v3 = POP();
-
-          /*
-           * adjust `this` if the function is called with the constructor
-           * invocation pattern
-           */
-          if (is_constructor) {
-            /*
-             * The function is invoked as a constructor: we ignore `this`
-             * value popped from stack, create new object and set prototype.
-             */
-
-            /*
-             * get "prototype" property from the constructor function,
-             * and make sure it's an object
-             */
-            v4 = v7_get(v7, v1 /*func*/, "prototype", 9);
-            if (!v7_is_object(v4)) {
-              /* TODO(dfrank): box primitive value */
-              BTRY(v7_throwf(
-                  v7, TYPE_ERROR,
-                  "Cannot set a primitive value as object prototype"));
-              goto op_done;
-            } else if (is_cfunction_lite(v4)) {
-              /*
-               * TODO(dfrank): maybe add support for a cfunction pointer to be
-               * a prototype
-               */
-              BTRY(v7_throwf(v7, TYPE_ERROR,
-                             "Not implemented: cfunction as a prototype"));
-              goto op_done;
-            }
-
-            /* create an object with given prototype */
-            v3 = mk_object(v7, v4 /*prototype*/);
-            v4 = V7_UNDEFINED;
-          }
-
-          if (!v7_is_callable(v7, v1)) {
-            /* tried to call non-function object: throw a TypeError */
-            BTRY(v7_throw(v7, v7->vals.call_check_ex));
-            goto op_done;
-          } else if (is_cfunction_lite(v1) || is_cfunction_obj(v7, v1)) {
-            /* call cfunction */
-
-            /*
-             * In "function invocation pattern", the `this` value popped from
-             * stack is an `undefined`. And in non-strict mode, we should change
-             * it to global object.
-             */
-            if (!is_constructor && !r.bcode->strict_mode &&
-                v7_is_undefined(v3)) {
-              v3 = v7->vals.global_object;
-            }
-
-            BTRY(call_cfunction(v7, v1 /*func*/, v3 /*this*/, v2 /*args*/,
-                                is_constructor, &v4));
-
-            /* push value returned from C function to bcode stack */
-            PUSH(v4);
-
-          } else {
-            char *ops;
-            struct v7_js_function *func = get_js_function_struct(v1);
-
-            /*
-             * In "function invocation pattern", the `this` value popped from
-             * stack is an `undefined`. And in non-strict mode, we should change
-             * it to global object.
-             */
-            if (!is_constructor && !func->bcode->strict_mode &&
-                v7_is_undefined(v3)) {
-              v3 = v7->vals.global_object;
-            }
-
-            scope_frame = v7_mk_object(v7);
-
-            /*
-             * Before actual opcodes, `ops` contains one or more
-             * null-terminated strings: first of all, the function name (if the
-             * function is anonymous, it's an empty string).
-             *
-             * Then, argument names follow. We know number of arguments, so, we
-             * know how many names to take.
-             *
-             * And then, local variable names follow. We know total number of
-             * strings (`names_cnt`), so, again, we know how many names to
-             * take.
-             */
-
-            ops = func->bcode->ops.p;
-
-            /* populate function itself */
-            ops = bcode_next_name_v(v7, func->bcode, ops, &v4);
-            BTRY(def_property_v(v7, scope_frame, v4, V7_DESC_CONFIGURABLE(0),
-                                v1, 0 /*not assign*/, NULL));
-
-            /* populate arguments */
-            {
-              int arg_num;
-              for (arg_num = 0; arg_num < func->bcode->args_cnt; ++arg_num) {
-                ops = bcode_next_name_v(v7, func->bcode, ops, &v4);
-                BTRY(def_property_v(
-                    v7, scope_frame, v4, V7_DESC_CONFIGURABLE(0),
-                    v7_array_get(v7, v2, arg_num), 0 /*not assign*/, NULL));
-              }
-            }
-
-            /* populate `arguments` object */
-
-            /*
-             * TODO(dfrank): it's actually much more complicated than that:
-             * it's not an array, it's an array-like object. More, in
-             * non-strict mode, elements of `arguments` object are just aliases
-             * for actual arguments, so this one:
-             *
-             *   `(function(a){arguments[0]=2; return a;})(1);`
-             *
-             * should yield 2. Currently, it yields 1.
-             */
-            v7_def(v7, scope_frame, "arguments", 9, V7_DESC_CONFIGURABLE(0),
-                   v2);
-
-            /* populate local variables */
-            {
-              uint8_t loc_num;
-              uint8_t loc_cnt = func->bcode->names_cnt - func->bcode->args_cnt -
-                                1 /*func name*/;
-              for (loc_num = 0; loc_num < loc_cnt; ++loc_num) {
-                ops = bcode_next_name_v(v7, func->bcode, ops, &v4);
-                BTRY(def_property_v(v7, scope_frame, v4,
-                                    V7_DESC_CONFIGURABLE(0), V7_UNDEFINED,
-                                    0 /*not assign*/, NULL));
-              }
-            }
-
-            /* transfer control to the function */
-            V7_TRY(bcode_perform_call(v7, scope_frame, func, &r, v3 /*this*/,
-                                      ops, is_constructor));
-
-            scope_frame = V7_UNDEFINED;
-          }
-        }
-        break;
-      }
-      case OP_RET:
-        bcode_adjust_retval(v7, 1 /*explicit return*/);
-        V7_TRY(bcode_perform_return(v7, &r, 1 /*take value from stack*/));
-        break;
-      case OP_DELETE:
-      case OP_DELETE_VAR: {
-        size_t name_len;
-        struct v7_property *prop;
-
-        res = v7_mk_boolean(v7, 1);
-
-        /* pop property name to delete */
-        v2 = POP();
-
-        if (op == OP_DELETE) {
-          /* pop object to delete the property from */
-          v1 = POP();
-        } else {
-          /* use scope as an object to delete the property from */
-          v1 = get_scope(v7);
-        }
-
-        if (!v7_is_object(v1)) {
-          /*
-           * the "object" to delete a property from is not actually an object
-           * (at least this can happen with cfunction pointers), will just
-           * return `true`
-           */
-          goto delete_clean;
-        }
-
-        BTRY(to_string(v7, v2, NULL, buf, sizeof(buf), &name_len));
-
-        prop = v7_get_property(v7, v1, buf, name_len);
-        if (prop == NULL) {
-          /* not found a property; will just return `true` */
-          goto delete_clean;
-        }
-
-        /* found needed property */
-
-        if (prop->attributes & V7_PROPERTY_NON_CONFIGURABLE) {
-          /*
-           * this property is undeletable. In non-strict mode, we just
-           * return `false`; otherwise, we throw.
-           */
-          if (!r.bcode->strict_mode) {
-            res = v7_mk_boolean(v7, 0);
-          } else {
-            BTRY(v7_throwf(v7, TYPE_ERROR, "Cannot delete property '%s'", buf));
-            goto op_done;
-          }
-        } else {
-          /*
-           * delete property: when we operate on the current scope, we should
-           * walk the prototype chain when deleting property.
-           *
-           * But when we operate on a "real" object, we should delete own
-           * properties only.
-           */
-          if (op == OP_DELETE) {
-            v7_del(v7, v1, buf, name_len);
-          } else {
-            del_property_deep(v7, v1, buf, name_len);
-          }
-        }
-
-      delete_clean:
-        PUSH(res);
-        break;
-      }
-      case OP_TRY_PUSH_CATCH:
-      case OP_TRY_PUSH_FINALLY:
-      case OP_TRY_PUSH_LOOP:
-      case OP_TRY_PUSH_SWITCH:
-        eval_try_push(v7, op, &r);
-        break;
-      case OP_TRY_POP:
-        V7_TRY(eval_try_pop(v7));
-        break;
-      case OP_AFTER_FINALLY:
-        /*
-         * exited from `finally` block: if some value is currently being
-         * returned, continue returning it.
-         *
-         * Likewise, if some value is currently being thrown, continue
-         * unwinding stack.
-         */
-        if (v7->is_thrown) {
-          V7_TRY(
-              bcode_perform_throw(v7, &r, 0 /*don't take value from stack*/));
-          goto op_done;
-        } else if (v7->is_returned) {
-          V7_TRY(
-              bcode_perform_return(v7, &r, 0 /*don't take value from stack*/));
-          break;
-        } else if (v7->is_breaking) {
-          bcode_perform_break(v7, &r);
-        }
-        break;
-      case OP_THROW:
-        V7_TRY(bcode_perform_throw(v7, &r, 1 /*take thrown value*/));
-        goto op_done;
-      case OP_BREAK:
-        bcode_perform_break(v7, &r);
-        break;
-      case OP_CONTINUE:
-        v7->is_continuing = 1;
-        bcode_perform_break(v7, &r);
-        break;
-      case OP_ENTER_CATCH: {
-        /* pop thrown value from stack */
-        v1 = POP();
-        /* get the name of the thrown value */
-        v2 = bcode_decode_lit(v7, r.bcode, &r.ops);
-
-        /*
-         * create a new stack frame (a "private" one), and set exception
-         * property on it
-         */
-        scope_frame = v7_mk_object(v7);
-        BTRY(set_property_v(v7, scope_frame, v2, v1, NULL));
-
-        /* Push this "private" frame on the call stack */
-
-        /* new scope_frame will inherit from the current scope */
-
-        obj_prototype_set(v7, get_object_struct(scope_frame),
-                          get_object_struct(get_scope(v7)));
-
-        /*
-         * Create new `call_frame` which will replace `v7->call_stack`.
-         */
-        append_call_frame_private(v7, scope_frame);
-
-        break;
-      }
-      case OP_EXIT_CATCH: {
-        v7_call_frame_mask_t frame_type_mask;
-        /* unwind 1 frame */
-        frame_type_mask = unwind_stack_1level(v7, &r);
-        /* make sure the unwound frame is a "private" frame */
-        assert(frame_type_mask == V7_CALL_FRAME_MASK_PRIVATE);
-#if defined(NDEBUG)
-        (void) frame_type_mask;
-#endif
-        break;
-      }
-      default:
-        BTRY(v7_throwf(v7, INTERNAL_ERROR, "Unknown opcode: %d", (int) op));
-        goto op_done;
-    }
-
-  op_done:
-#ifdef V7_BCODE_TRACE
-    /* print current stack state */
-    {
-      char buf[40];
-      char *str = v7_stringify(v7, TOS(), buf, sizeof(buf), V7_STRINGIFY_DEBUG);
-      fprintf(stderr, "        stack size: %u, TOS: '%s'\n",
-              (unsigned int) (v7->stack.len / sizeof(val_t)), str);
-      if (str != buf) {
-        free(str);
-      }
-
-#ifdef V7_BCODE_TRACE_STACK
-      {
-        size_t i;
-        for (i = 0; i < (v7->stack.len / sizeof(val_t)); i++) {
-          char *str = v7_stringify(v7, stack_at(&v7->stack, i), buf,
-                                   sizeof(buf), V7_STRINGIFY_DEBUG);
-
-          fprintf(stderr, "        #: '%s'\n", str);
-
-          if (str != buf) {
-            free(str);
-          }
-        }
-      }
-#endif
-    }
-#endif
-    if (r.need_inc_ops) {
-      r.ops++;
-    }
-  }
-
-  /* implicit return */
-  if (v7->call_stack != v7->bottom_call_frame) {
-#ifdef V7_BCODE_TRACE
-    fprintf(stderr, "return implicitly\n");
-#endif
-    bcode_adjust_retval(v7, 0 /*implicit return*/);
-    V7_TRY(bcode_perform_return(v7, &r, 1));
-    goto restart;
-  } else {
-#ifdef V7_BCODE_TRACE
-    const char *s = (get_scope(v7) != v7->vals.global_object)
-                        ? "not global object"
-                        : "global object";
-    fprintf(stderr, "reached bottom_call_frame (%s)\n", s);
-#endif
-  }
-
-clean:
-
-  if (rcode == V7_OK) {
-/*
- * bcode evaluated successfully. Make sure try stack is empty.
- * (data stack will be checked below, in `clean`)
- */
-#ifndef NDEBUG
-    {
-      unsigned long try_stack_len =
-          v7_array_length(v7, find_call_frame_private(v7)->vals.try_stack);
-      if (try_stack_len != 0) {
-        fprintf(stderr, "try_stack_len=%lu, should be 0\n", try_stack_len);
-      }
-      assert(try_stack_len == 0);
-    }
-#endif
-
-    /* get the value returned from the evaluated script */
-    *_res = POP();
-  }
-
-  assert(v7->bottom_call_frame == v7->call_stack);
-  unwind_stack_1level(v7, NULL);
-
-  v7->bottom_call_frame = saved_bottom_call_frame;
-
-  tmp_frame_cleanup(&tf);
-  return rcode;
-}
-
-/*
- * TODO(dfrank) this function is probably too overloaded: it handles both
- * `v7_exec` and `v7_apply`. Read below why it's written this way, but it's
- * probably a good idea to factor out common functionality in some other
- * function.
- *
- * If `src` is not `NULL`, then we behave in favour of `v7_exec`: parse,
- * compile, and evaluate the script. The `func` and `args` are ignored.
- *
- * If, however, `src` is `NULL`, then we behave in favour of `v7_apply`: we
- * call the provided `func` with `args`. But unlike interpreter, we can't just
- * call the provided function: we need to setup environment for this call.
- *
- * Currently, we just quickly generate the "wrapper" bcode for the function.
- * This wrapper bcode looks like this:
- *
- *    OP_PUSH_UNDEFINED
- *    OP_PUSH_LIT       # push this
- *    OP_PUSH_LIT       # push function
- *    OP_PUSH_LIT       # push arg1
- *    OP_PUSH_LIT       # push arg2
- *    ...
- *    OP_PUSH_LIT       # push argN
- *    OP_CALL(N)        # call function with N arguments
- *    OP_SWAP_DROP
- *
- * and then, bcode evaluator proceeds with this code.
- *
- * In fact, both cases (eval or apply) are quite similar: we should prepare
- * environment for the bcode evaluation in exactly the same way, and the only
- * different part is where we get the bcode from. This is why that
- * functionality is baked in the single function, but it would be good to make
- * it suck less.
- */
-V7_PRIVATE enum v7_err b_exec(struct v7 *v7, const char *src, size_t src_len,
-                              const char *filename, val_t func, val_t args,
-                              val_t this_object, int is_json, int fr,
-                              uint8_t is_constructor, val_t *res) {
-#if defined(V7_BCODE_TRACE_SRC)
-  fprintf(stderr, "src:'%s'\n", src);
-#endif
-
-/* TODO(mkm): use GC pool */
-#if !defined(V7_NO_COMPILER)
-  struct ast *a = (struct ast *) malloc(sizeof(struct ast));
-#endif
-  size_t saved_stack_len = v7->stack.len;
-  enum v7_err rcode = V7_OK;
-  val_t _res = V7_UNDEFINED;
-  struct gc_tmp_frame tf = new_tmp_frame(v7);
-  struct bcode *bcode = NULL;
-#if defined(V7_ENABLE_STACK_TRACKING)
-  struct stack_track_ctx stack_track_ctx;
-#endif
-  struct {
-    unsigned noopt : 1;
-    unsigned line_no_reset : 1;
-  } flags = {0, 0};
-
-  (void) filename;
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-  v7_stack_track_start(v7, &stack_track_ctx);
-#endif
-
-  tmp_stack_push(&tf, &func);
-  tmp_stack_push(&tf, &args);
-  tmp_stack_push(&tf, &this_object);
-  tmp_stack_push(&tf, &_res);
-
-  /* init new bcode */
-  bcode = (struct bcode *) calloc(1, sizeof(*bcode));
-
-  bcode_init(bcode,
-#ifndef V7_FORCE_STRICT_MODE
-             0,
-#else
-             1,
-#endif
-#ifndef V7_DISABLE_FILENAMES
-             filename ? shdata_create_from_string(filename) : NULL,
-#else
-             NULL,
-#endif
-             0 /*filename not in ROM*/
-             );
-
-  retain_bcode(v7, bcode);
-  own_bcode(v7, bcode);
-
-#if !defined(V7_NO_COMPILER)
-  ast_init(a, 0);
-  a->refcnt = 1;
-#endif
-
-  if (src != NULL) {
-    /* Caller provided some source code, so, handle it somehow */
-
-    flags.line_no_reset = 1;
-
-    if (src_len >= sizeof(BIN_BCODE_SIGNATURE) &&
-        strncmp(BIN_BCODE_SIGNATURE, src, sizeof(BIN_BCODE_SIGNATURE)) == 0) {
-      /* we have a serialized bcode */
-
-      bcode_deserialize(v7, bcode, src + sizeof(BIN_BCODE_SIGNATURE));
-
-/*
- * Currently, we only support serialized bcode that is stored in some
- * mmapped memory. Otherwise, we don't yet have any mechanism to free
- * this memory at the appropriate time.
- */
-
-/*
- * TODO(dfrank): currently, we remove this assert, and introduce memory
- * leak. We need to support that properly.
- */
-#if 0
-      assert(fr == 0);
-#else
-      if (fr) {
-        fr = 0;
-      }
-#endif
-    } else {
-/* Maybe regular JavaScript source or binary AST data */
-#if !defined(V7_NO_COMPILER)
-
-      if (src_len >= sizeof(BIN_AST_SIGNATURE) &&
-          strncmp(BIN_AST_SIGNATURE, src, sizeof(BIN_AST_SIGNATURE)) == 0) {
-        /* we have binary AST data */
-
-        if (fr == 0) {
-          /* Unmanaged memory, usually rom or mmapped flash */
-          mbuf_free(&a->mbuf);
-          a->mbuf.buf = (char *) (src + sizeof(BIN_AST_SIGNATURE));
-          a->mbuf.size = a->mbuf.len = src_len - sizeof(BIN_AST_SIGNATURE);
-          a->refcnt++; /* prevent freeing */
-          flags.noopt = 1;
-        } else {
-          mbuf_append(&a->mbuf, src + sizeof(BIN_AST_SIGNATURE),
-                      src_len - sizeof(BIN_AST_SIGNATURE));
-        }
-      } else {
-        /* we have regular JavaScript source, so, parse it */
-        V7_TRY(parse(v7, a, src, src_len, is_json));
-      }
-
-      /* we now have binary AST, let's compile it */
-
-      if (!flags.noopt) {
-        ast_optimize(a);
-      }
-#if V7_ENABLE__Memory__stats
-      v7->function_arena_ast_size += a->mbuf.size;
-#endif
-
-      if (v7_is_undefined(this_object)) {
-        this_object = v7->vals.global_object;
-      }
-
-      if (!is_json) {
-        V7_TRY(compile_script(v7, a, bcode));
-      } else {
-        ast_off_t pos = 0;
-        V7_TRY(compile_expr(v7, a, &pos, bcode));
-      }
-#else  /* V7_NO_COMPILER */
-      (void) is_json;
-      /* Parsing JavaScript code is disabled */
-      rcode = v7_throwf(v7, SYNTAX_ERROR,
-                        "Parsing JS code is disabled by V7_NO_COMPILER");
-      V7_THROW(V7_SYNTAX_ERROR);
-#endif /* V7_NO_COMPILER */
-    }
-
-  } else if (is_js_function(func)) {
-    /*
-     * Caller did not provide source code, so, assume we should call
-     * provided function. Here, we prepare "wrapper" bcode.
-     */
-
-    struct bcode_builder bbuilder;
-    lit_t lit;
-    int args_cnt = v7_array_length(v7, args);
-
-    bcode_builder_init(v7, &bbuilder, bcode);
-
-    bcode_op(&bbuilder, OP_PUSH_UNDEFINED);
-
-    /* push `this` */
-    lit = bcode_add_lit(&bbuilder, this_object);
-    bcode_push_lit(&bbuilder, lit);
-
-    /* push func literal */
-    lit = bcode_add_lit(&bbuilder, func);
-    bcode_push_lit(&bbuilder, lit);
-
-    /* push args */
-    {
-      int i;
-      for (i = 0; i < args_cnt; i++) {
-        lit = bcode_add_lit(&bbuilder, v7_array_get(v7, args, i));
-        bcode_push_lit(&bbuilder, lit);
-      }
-    }
-
-    bcode_op(&bbuilder, OP_CALL);
-    /* TODO(dfrank): check if args <= 0x7f */
-    bcode_op(&bbuilder, (uint8_t) args_cnt);
-
-    bcode_op(&bbuilder, OP_SWAP_DROP);
-
-    bcode_builder_finalize(&bbuilder);
-  } else if (is_cfunction_lite(func) || is_cfunction_obj(v7, func)) {
-    /* call cfunction */
-
-    V7_TRY(call_cfunction(v7, func, this_object, args, is_constructor, &_res));
-
-    goto clean;
-  } else {
-    /* value is not a function */
-    V7_TRY(v7_throwf(v7, TYPE_ERROR, "value is not a function"));
-  }
-
-/* We now have bcode to evaluate; proceed to it */
-
-#if !defined(V7_NO_COMPILER)
-  /*
-   * Before we evaluate bcode, we can safely release AST since it's not needed
-   * anymore. Note that there's no leak here: if we `goto clean` from somewhere
-   * above, we'll anyway release the AST under `clean` as well.
-   */
-  release_ast(v7, a);
-  a = NULL;
-#endif /* V7_NO_COMPILER */
-
-  /* Evaluate bcode */
-  V7_TRY(eval_bcode(v7, bcode, this_object, flags.line_no_reset, &_res));
-
-clean:
-
-  /* free `src` if needed */
-  /*
-   * TODO(dfrank) : free it above, just after parsing, and make sure you use
-   * V7_TRY2() with custom label instead of V7_TRY()
-   */
-  if (src != NULL && fr) {
-    free((void *) src);
-  }
-
-  /* disown and release current bcode */
-  disown_bcode(v7, bcode);
-  release_bcode(v7, bcode);
-  bcode = NULL;
-
-  if (rcode != V7_OK) {
-    /* some exception happened. */
-    _res = v7->vals.thrown_error;
-
-    /*
-     * if this is a top-level bcode, clear thrown error from the v7 context
-     *
-     * TODO(dfrank): do we really need to do this?
-     *
-     * If we don't clear the error, then we should clear it manually after each
-     * call to v7_exec() or friends; otherwise, all the following calls will
-     * see this error.
-     *
-     * On the other hand, user would still need to clear the error if he calls
-     * v7_exec() from some cfunction. So, currently, sometimes we don't need
-     * to clear the error, and sometimes we do, which is confusing.
-     */
-    if (v7->act_bcodes.len == 0) {
-      v7->vals.thrown_error = V7_UNDEFINED;
-      v7->is_thrown = 0;
-    }
-  }
-
-  /*
-   * Data stack should have the same length as it was before evaluating script.
-   */
-  if (v7->stack.len != saved_stack_len) {
-    fprintf(stderr, "len=%d, saved=%d\n", (int) v7->stack.len,
-            (int) saved_stack_len);
-  }
-  assert(v7->stack.len == saved_stack_len);
-
-#if !defined(V7_NO_COMPILER)
-  /*
-   * release AST if needed (normally, it's already released above, before
-   * bcode evaluation)
-   */
-  if (a != NULL) {
-    release_ast(v7, a);
-    a = NULL;
-  }
-#endif /* V7_NO_COMPILER */
-
-  if (is_constructor && !v7_is_object(_res)) {
-    /* constructor returned non-object: replace it with `this` */
-    _res = v7_get_this(v7);
-  }
-
-  /* Provide the caller with the result, if asked to do so */
-  if (res != NULL) {
-    *res = _res;
-  }
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-  {
-    int diff = v7_stack_track_end(v7, &stack_track_ctx);
-    if (diff > v7->stack_stat[V7_STACK_STAT_EXEC]) {
-      v7->stack_stat[V7_STACK_STAT_EXEC] = diff;
-    }
-  }
-#endif
-
-  tmp_frame_cleanup(&tf);
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err b_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
-                               v7_val_t args, uint8_t is_constructor,
-                               v7_val_t *res) {
-  return b_exec(v7, NULL, 0, NULL, func, args, this_obj, 0, 0, is_constructor,
-                res);
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/core.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/builtin/builtin.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "v7/src/slre.h" */
-/* Amalgamated: #include "v7/src/bcode.h" */
-/* Amalgamated: #include "v7/src/stdlib.h" */
-/* Amalgamated: #include "v7/src/gc.h" */
-/* Amalgamated: #include "v7/src/heapusage.h" */
-/* Amalgamated: #include "v7/src/eval.h" */
-
-#ifdef V7_THAW
-extern struct v7_vals *fr_vals;
-#endif
-
-#ifdef HAS_V7_INFINITY
-double _v7_infinity;
-#endif
-
-#ifdef HAS_V7_NAN
-double _v7_nan;
-#endif
-
-#if defined(V7_CYG_PROFILE_ON)
-struct v7 *v7_head = NULL;
-#endif
-
-static void generic_object_destructor(struct v7 *v7, void *ptr) {
-  struct v7_generic_object *o = (struct v7_generic_object *) ptr;
-  struct v7_property *p;
-  struct mbuf *abuf;
-
-  /* TODO(mkm): make regexp use user data API */
-  p = v7_get_own_property2(v7, v7_object_to_value(&o->base), "", 0,
-                           _V7_PROPERTY_HIDDEN);
-
-#if V7_ENABLE__RegExp
-  if (p != NULL && (p->value & V7_TAG_MASK) == V7_TAG_REGEXP) {
-    struct v7_regexp *rp = (struct v7_regexp *) get_ptr(p->value);
-    v7_disown(v7, &rp->regexp_string);
-    slre_free(rp->compiled_regexp);
-    free(rp);
-  }
-#endif
-
-  if (o->base.attributes & V7_OBJ_DENSE_ARRAY) {
-    if (p != NULL &&
-        ((abuf = (struct mbuf *) v7_get_ptr(v7, p->value)) != NULL)) {
-      mbuf_free(abuf);
-      free(abuf);
-    }
-  }
-
-  if (o->base.attributes & V7_OBJ_HAS_DESTRUCTOR) {
-    struct v7_property *p;
-    for (p = o->base.properties; p != NULL; p = p->next) {
-      if (p->attributes & _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR) {
-        if (v7_is_foreign(p->name)) {
-          v7_destructor_cb_t *cb =
-              (v7_destructor_cb_t *) v7_get_ptr(v7, p->name);
-          cb(v7, v7_get_ptr(v7, p->value));
-        }
-        break;
-      }
-    }
-  }
-
-#if defined(V7_ENABLE_ENTITY_IDS)
-  o->base.entity_id_base = V7_ENTITY_ID_PART_NONE;
-  o->base.entity_id_spec = V7_ENTITY_ID_PART_NONE;
-#endif
-}
-
-static void function_destructor(struct v7 *v7, void *ptr) {
-  struct v7_js_function *f = (struct v7_js_function *) ptr;
-  (void) v7;
-  if (f == NULL) return;
-
-  if (f->bcode != NULL) {
-    release_bcode(v7, f->bcode);
-  }
-
-#if defined(V7_ENABLE_ENTITY_IDS)
-  f->base.entity_id_base = V7_ENTITY_ID_PART_NONE;
-  f->base.entity_id_spec = V7_ENTITY_ID_PART_NONE;
-#endif
-}
-
-#if defined(V7_ENABLE_ENTITY_IDS)
-static void property_destructor(struct v7 *v7, void *ptr) {
-  struct v7_property *p = (struct v7_property *) ptr;
-  (void) v7;
-  if (p == NULL) return;
-
-  p->entity_id = V7_ENTITY_ID_NONE;
-}
-#endif
-
-struct v7 *v7_create(void) {
-  struct v7_create_opts opts;
-  memset(&opts, 0, sizeof(opts));
-  return v7_create_opt(opts);
-}
-
-struct v7 *v7_create_opt(struct v7_create_opts opts) {
-  struct v7 *v7 = NULL;
-  char z = 0;
-
-#if defined(HAS_V7_INFINITY) || defined(HAS_V7_NAN)
-  double zero = 0.0;
-#endif
-
-#ifdef HAS_V7_INFINITY
-  _v7_infinity = 1.0 / zero;
-#endif
-#ifdef HAS_V7_NAN
-  _v7_nan = zero / zero;
-#endif
-
-  if (opts.object_arena_size == 0) opts.object_arena_size = 200;
-  if (opts.function_arena_size == 0) opts.function_arena_size = 100;
-  if (opts.property_arena_size == 0) opts.property_arena_size = 400;
-
-  if ((v7 = (struct v7 *) calloc(1, sizeof(*v7))) != NULL) {
-#ifdef V7_STACK_SIZE
-    v7->sp_limit = (void *) ((uintptr_t) opts.c_stack_base - (V7_STACK_SIZE));
-    v7->sp_lwm = opts.c_stack_base;
-#ifdef V7_STACK_GUARD_MIN_SIZE
-    v7_sp_limit = v7->sp_limit;
-#endif
-#endif
-
-#if defined(V7_CYG_PROFILE_ON)
-    v7->next_v7 = v7_head;
-    v7_head = v7;
-#endif
-
-#ifndef V7_DISABLE_STR_ALLOC_SEQ
-    v7->gc_next_asn = 0;
-    v7->gc_min_asn = 0;
-#endif
-
-    v7->cur_dense_prop =
-        (struct v7_property *) calloc(1, sizeof(struct v7_property));
-    gc_arena_init(&v7->generic_object_arena, sizeof(struct v7_generic_object),
-                  opts.object_arena_size, 10, "object");
-    v7->generic_object_arena.destructor = generic_object_destructor;
-    gc_arena_init(&v7->function_arena, sizeof(struct v7_js_function),
-                  opts.function_arena_size, 10, "function");
-    v7->function_arena.destructor = function_destructor;
-    gc_arena_init(&v7->property_arena, sizeof(struct v7_property),
-                  opts.property_arena_size, 10, "property");
-#if defined(V7_ENABLE_ENTITY_IDS)
-    v7->property_arena.destructor = property_destructor;
-#endif
-
-    /*
-     * The compacting GC exploits the null terminator of the previous
-     * string as marker.
-     */
-    mbuf_append(&v7->owned_strings, &z, 1);
-
-    v7->inhibit_gc = 1;
-    v7->vals.thrown_error = V7_UNDEFINED;
-
-    v7->call_stack = NULL;
-    v7->bottom_call_frame = NULL;
-
-#if defined(V7_THAW) && !defined(V7_FREEZE_NOT_READONLY)
-    {
-      struct v7_generic_object *obj;
-      v7->vals = *fr_vals;
-      v7->vals.global_object = v7_mk_object(v7);
-
-      /*
-       * The global object has to be mutable.
-       */
-      obj = get_generic_object_struct(v7->vals.global_object);
-      *obj = *get_generic_object_struct(fr_vals->global_object);
-      obj->base.attributes &= ~(V7_OBJ_NOT_EXTENSIBLE | V7_OBJ_OFF_HEAP);
-      v7_set(v7, v7->vals.global_object, "global", 6, v7->vals.global_object);
-    }
-#else
-    init_stdlib(v7);
-    init_file(v7);
-    init_crypto(v7);
-    init_socket(v7);
-#endif
-
-    v7->inhibit_gc = 0;
-  }
-
-  return v7;
-}
-
-val_t v7_get_global(struct v7 *v7) {
-  return v7->vals.global_object;
-}
-
-void v7_destroy(struct v7 *v7) {
-  if (v7 == NULL) return;
-  gc_arena_destroy(v7, &v7->generic_object_arena);
-  gc_arena_destroy(v7, &v7->function_arena);
-  gc_arena_destroy(v7, &v7->property_arena);
-
-  mbuf_free(&v7->owned_strings);
-  mbuf_free(&v7->owned_values);
-  mbuf_free(&v7->foreign_strings);
-  mbuf_free(&v7->json_visited_stack);
-  mbuf_free(&v7->tmp_stack);
-  mbuf_free(&v7->act_bcodes);
-  mbuf_free(&v7->stack);
-
-#if defined(V7_CYG_PROFILE_ON)
-  /* delete this v7 */
-  {
-    struct v7 *v, **prevp = &v7_head;
-    for (v = v7_head; v != NULL; prevp = &v->next_v7, v = v->next_v7) {
-      if (v == v7) {
-        *prevp = v->next_v7;
-        break;
-      }
-    }
-  }
-#endif
-
-  free(v7->cur_dense_prop);
-  free(v7);
-}
-
-v7_val_t v7_get_this(struct v7 *v7) {
-  /*
-   * By default, when there's no active call frame, will return Global Object
-   */
-  v7_val_t ret = v7->vals.global_object;
-
-  struct v7_call_frame_base *call_frame =
-      find_call_frame(v7, V7_CALL_FRAME_MASK_BCODE | V7_CALL_FRAME_MASK_CFUNC);
-
-  if (call_frame != NULL) {
-    if (call_frame->type_mask & V7_CALL_FRAME_MASK_BCODE) {
-      ret = ((struct v7_call_frame_bcode *) call_frame)->vals.this_obj;
-    } else if (call_frame->type_mask & V7_CALL_FRAME_MASK_CFUNC) {
-      ret = ((struct v7_call_frame_cfunc *) call_frame)->vals.this_obj;
-    } else {
-      assert(0);
-    }
-  }
-
-  return ret;
-}
-
-V7_PRIVATE v7_val_t get_scope(struct v7 *v7) {
-  struct v7_call_frame_private *call_frame =
-      (struct v7_call_frame_private *) find_call_frame(
-          v7, V7_CALL_FRAME_MASK_PRIVATE);
-
-  if (call_frame != NULL) {
-    return call_frame->vals.scope;
-  } else {
-    /* No active call frame, return global object */
-    return v7->vals.global_object;
-  }
-}
-
-V7_PRIVATE uint8_t is_strict_mode(struct v7 *v7) {
-  struct v7_call_frame_bcode *call_frame =
-      (struct v7_call_frame_bcode *) find_call_frame(v7,
-                                                     V7_CALL_FRAME_MASK_BCODE);
-
-  if (call_frame != NULL) {
-    return call_frame->bcode->strict_mode;
-  } else {
-    /* No active call frame, assume no strict mode */
-    return 0;
-  }
-}
-
-v7_val_t v7_get_arguments(struct v7 *v7) {
-  return v7->vals.arguments;
-}
-
-v7_val_t v7_arg(struct v7 *v7, unsigned long n) {
-  return v7_array_get(v7, v7->vals.arguments, n);
-}
-
-unsigned long v7_argc(struct v7 *v7) {
-  return v7_array_length(v7, v7->vals.arguments);
-}
-
-void v7_own(struct v7 *v7, v7_val_t *v) {
-  heapusage_dont_count(1);
-  mbuf_append(&v7->owned_values, &v, sizeof(v));
-  heapusage_dont_count(0);
-}
-
-int v7_disown(struct v7 *v7, v7_val_t *v) {
-  v7_val_t **vp =
-      (v7_val_t **) (v7->owned_values.buf + v7->owned_values.len - sizeof(v));
-
-  for (; (char *) vp >= v7->owned_values.buf; vp--) {
-    if (*vp == v) {
-      *vp = *(v7_val_t **) (v7->owned_values.buf + v7->owned_values.len -
-                            sizeof(v));
-      v7->owned_values.len -= sizeof(v);
-      return 1;
-    }
-  }
-
-  return 0;
-}
-
-void v7_set_gc_enabled(struct v7 *v7, int enabled) {
-  v7->inhibit_gc = !enabled;
-}
-
-void v7_interrupt(struct v7 *v7) {
-  v7->interrupted = 1;
-}
-
-const char *v7_get_parser_error(struct v7 *v7) {
-  return v7->error_msg;
-}
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-
-int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what) {
-  assert(what < V7_STACK_STATS_CNT);
-  return v7->stack_stat[what];
-}
-
-void v7_stack_stat_clean(struct v7 *v7) {
-  memset(v7->stack_stat, 0x00, sizeof(v7->stack_stat));
-}
-
-#endif /* V7_ENABLE_STACK_TRACKING */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/primitive.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-
-/* Number {{{ */
-
-NOINSTR static v7_val_t mk_number(double v) {
-  val_t res;
-  /* not every NaN is a JS NaN */
-  if (isnan(v)) {
-    res = V7_TAG_NAN;
-  } else {
-    union {
-      double d;
-      val_t r;
-    } u;
-    u.d = v;
-    res = u.r;
-  }
-  return res;
-}
-
-NOINSTR static double get_double(val_t v) {
-  union {
-    double d;
-    val_t v;
-  } u;
-  u.v = v;
-  /* Due to NaN packing, any non-numeric value is already a valid NaN value */
-  return u.d;
-}
-
-NOINSTR static v7_val_t mk_boolean(int v) {
-  return (!!v) | V7_TAG_BOOLEAN;
-}
-
-NOINSTR static int get_bool(val_t v) {
-  if (v7_is_boolean(v)) {
-    return v & 1;
-  } else {
-    return 0;
-  }
-}
-
-NOINSTR v7_val_t v7_mk_number(struct v7 *v7, double v) {
-  (void) v7;
-  return mk_number(v);
-}
-
-NOINSTR double v7_get_double(struct v7 *v7, v7_val_t v) {
-  (void) v7;
-  return get_double(v);
-}
-
-NOINSTR int v7_get_int(struct v7 *v7, v7_val_t v) {
-  (void) v7;
-  return (int) get_double(v);
-}
-
-int v7_is_number(val_t v) {
-  return v == V7_TAG_NAN || !isnan(get_double(v));
-}
-
-V7_PRIVATE int is_finite(struct v7 *v7, val_t v) {
-  return v7_is_number(v) && v != V7_TAG_NAN && !isinf(v7_get_double(v7, v));
-}
-
-/* }}} Number */
-
-/* Boolean {{{ */
-
-NOINSTR v7_val_t v7_mk_boolean(struct v7 *v7, int v) {
-  (void) v7;
-  return mk_boolean(v);
-}
-
-NOINSTR int v7_get_bool(struct v7 *v7, val_t v) {
-  (void) v7;
-  return get_bool(v);
-}
-
-int v7_is_boolean(val_t v) {
-  return (v & V7_TAG_MASK) == V7_TAG_BOOLEAN;
-}
-
-/* }}} Boolean */
-
-/* null {{{ */
-
-NOINSTR v7_val_t v7_mk_null(void) {
-  return V7_NULL;
-}
-
-int v7_is_null(val_t v) {
-  return v == V7_NULL;
-}
-
-/* }}} null */
-
-/* undefined {{{ */
-
-NOINSTR v7_val_t v7_mk_undefined(void) {
-  return V7_UNDEFINED;
-}
-
-int v7_is_undefined(val_t v) {
-  return v == V7_UNDEFINED;
-}
-
-/* }}} undefined */
-
-/* Foreign {{{ */
-
-V7_PRIVATE val_t pointer_to_value(void *p) {
-  uint64_t n = ((uint64_t)(uintptr_t) p);
-
-  assert((n & V7_TAG_MASK) == 0 || (n & V7_TAG_MASK) == (~0 & V7_TAG_MASK));
-  return n & ~V7_TAG_MASK;
-}
-
-V7_PRIVATE void *get_ptr(val_t v) {
-  return (void *) (uintptr_t)(v & 0xFFFFFFFFFFFFUL);
-}
-
-NOINSTR void *v7_get_ptr(struct v7 *v7, val_t v) {
-  (void) v7;
-  if (!v7_is_foreign(v)) {
-    return NULL;
-  }
-  return get_ptr(v);
-}
-
-NOINSTR v7_val_t v7_mk_foreign(struct v7 *v7, void *p) {
-  (void) v7;
-  return pointer_to_value(p) | V7_TAG_FOREIGN;
-}
-
-int v7_is_foreign(val_t v) {
-  return (v & V7_TAG_MASK) == V7_TAG_FOREIGN;
-}
-
-/* }}} Foreign */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/function.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/gc.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-
-static val_t js_function_to_value(struct v7_js_function *o) {
-  return pointer_to_value(o) | V7_TAG_FUNCTION;
-}
-
-V7_PRIVATE struct v7_js_function *get_js_function_struct(val_t v) {
-  struct v7_js_function *ret = NULL;
-  assert(is_js_function(v));
-  ret = (struct v7_js_function *) get_ptr(v);
-#if defined(V7_ENABLE_ENTITY_IDS)
-  if (ret->base.entity_id_spec != V7_ENTITY_ID_PART_JS_FUNC) {
-    fprintf(stderr, "entity_id: not a function!\n");
-    abort();
-  } else if (ret->base.entity_id_base != V7_ENTITY_ID_PART_OBJ) {
-    fprintf(stderr, "entity_id: not an object!\n");
-    abort();
-  }
-#endif
-  return ret;
-}
-
-V7_PRIVATE
-val_t mk_js_function(struct v7 *v7, struct v7_generic_object *scope,
-                     val_t proto) {
-  struct v7_js_function *f;
-  val_t fval = V7_NULL;
-  struct gc_tmp_frame tf = new_tmp_frame(v7);
-  tmp_stack_push(&tf, &proto);
-  tmp_stack_push(&tf, &fval);
-
-  f = new_function(v7);
-
-  if (f == NULL) {
-    /* fval is left `null` */
-    goto cleanup;
-  }
-
-#if defined(V7_ENABLE_ENTITY_IDS)
-  f->base.entity_id_base = V7_ENTITY_ID_PART_OBJ;
-  f->base.entity_id_spec = V7_ENTITY_ID_PART_JS_FUNC;
-#endif
-
-  fval = js_function_to_value(f);
-
-  f->base.properties = NULL;
-  f->scope = scope;
-
-  /*
-   * Before setting a `V7_OBJ_FUNCTION` flag, make sure we don't have
-   * `V7_OBJ_DENSE_ARRAY` flag set
-   */
-  assert(!(f->base.attributes & V7_OBJ_DENSE_ARRAY));
-  f->base.attributes |= V7_OBJ_FUNCTION;
-
-  /* TODO(mkm): lazily create these properties on first access */
-  if (v7_is_object(proto)) {
-    v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), fval);
-    v7_def(v7, fval, "prototype", 9,
-           V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0), proto);
-  }
-
-cleanup:
-  tmp_frame_cleanup(&tf);
-  return fval;
-}
-
-V7_PRIVATE int is_js_function(val_t v) {
-  return (v & V7_TAG_MASK) == V7_TAG_FUNCTION;
-}
-
-V7_PRIVATE
-v7_val_t mk_cfunction_obj(struct v7 *v7, v7_cfunction_t *f, int num_args) {
-  val_t obj = mk_object(v7, v7->vals.function_prototype);
-  struct gc_tmp_frame tf = new_tmp_frame(v7);
-  tmp_stack_push(&tf, &obj);
-  v7_def(v7, obj, "", 0, _V7_DESC_HIDDEN(1), v7_mk_cfunction(f));
-  if (num_args >= 0) {
-    v7_def(v7, obj, "length", 6, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) |
-                                  V7_DESC_CONFIGURABLE(0)),
-           v7_mk_number(v7, num_args));
-  }
-  tmp_frame_cleanup(&tf);
-  return obj;
-}
-
-V7_PRIVATE v7_val_t mk_cfunction_obj_with_proto(struct v7 *v7,
-                                                v7_cfunction_t *f, int num_args,
-                                                v7_val_t proto) {
-  struct gc_tmp_frame tf = new_tmp_frame(v7);
-  v7_val_t res = mk_cfunction_obj(v7, f, num_args);
-
-  tmp_stack_push(&tf, &res);
-
-  v7_def(v7, res, "prototype", 9, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) |
-                                   V7_DESC_CONFIGURABLE(0)),
-         proto);
-  v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), res);
-  tmp_frame_cleanup(&tf);
-  return res;
-}
-
-V7_PRIVATE v7_val_t mk_cfunction_lite(v7_cfunction_t *f) {
-  union {
-    void *p;
-    v7_cfunction_t *f;
-  } u;
-  u.f = f;
-  return pointer_to_value(u.p) | V7_TAG_CFUNCTION;
-}
-
-V7_PRIVATE v7_cfunction_t *get_cfunction_ptr(struct v7 *v7, val_t v) {
-  v7_cfunction_t *ret = NULL;
-
-  if (is_cfunction_lite(v)) {
-    /* Implementation is identical to get_ptr but is separate since
-     * object pointers are not directly convertible to function pointers
-     * according to ISO C and generates a warning in -Wpedantic mode. */
-    ret = (v7_cfunction_t *) (uintptr_t)(v & 0xFFFFFFFFFFFFUL);
-  } else {
-    /* maybe cfunction object */
-
-    /* extract the hidden property from a cfunction_object */
-    struct v7_property *p;
-    p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
-    if (p != NULL) {
-      /* yes, it's cfunction object. Extract cfunction pointer from it */
-      ret = get_cfunction_ptr(v7, p->value);
-    }
-  }
-
-  return ret;
-}
-
-V7_PRIVATE int is_cfunction_lite(val_t v) {
-  return (v & V7_TAG_MASK) == V7_TAG_CFUNCTION;
-}
-
-V7_PRIVATE int is_cfunction_obj(struct v7 *v7, val_t v) {
-  int ret = 0;
-  if (v7_is_object(v)) {
-    /* extract the hidden property from a cfunction_object */
-    struct v7_property *p;
-    p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
-    if (p != NULL) {
-      v = p->value;
-    }
-
-    ret = is_cfunction_lite(v);
-  }
-  return ret;
-}
-
-v7_val_t v7_mk_function(struct v7 *v7, v7_cfunction_t *f) {
-  return mk_cfunction_obj(v7, f, -1);
-}
-
-v7_val_t v7_mk_function_with_proto(struct v7 *v7, v7_cfunction_t *f,
-                                   v7_val_t proto) {
-  return mk_cfunction_obj_with_proto(v7, f, ~0, proto);
-}
-
-v7_val_t v7_mk_cfunction(v7_cfunction_t *f) {
-  return mk_cfunction_lite(f);
-}
-
-int v7_is_callable(struct v7 *v7, val_t v) {
-  return is_js_function(v) || is_cfunction_lite(v) || is_cfunction_obj(v7, v);
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/exec.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* osdep.h must be included before `cs_file.h` TODO(dfrank) : fix this */
-/* Amalgamated: #include "common/cs_file.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/eval.h" */
-/* Amalgamated: #include "v7/src/exec.h" */
-/* Amalgamated: #include "v7/src/ast.h" */
-/* Amalgamated: #include "v7/src/compiler.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-
-enum v7_err v7_exec(struct v7 *v7, const char *js_code, v7_val_t *res) {
-  return b_exec(v7, js_code, strlen(js_code), NULL, V7_UNDEFINED, V7_UNDEFINED,
-                V7_UNDEFINED, 0, 0, 0, res);
-}
-
-enum v7_err v7_exec_opt(struct v7 *v7, const char *js_code,
-                        const struct v7_exec_opts *opts, v7_val_t *res) {
-  return b_exec(v7, js_code, strlen(js_code), opts->filename, V7_UNDEFINED,
-                V7_UNDEFINED,
-                (opts->this_obj == 0 ? V7_UNDEFINED : opts->this_obj),
-                opts->is_json, 0, 0, res);
-}
-
-enum v7_err v7_parse_json(struct v7 *v7, const char *str, v7_val_t *res) {
-  return b_exec(v7, str, strlen(str), NULL, V7_UNDEFINED, V7_UNDEFINED,
-                V7_UNDEFINED, 1, 0, 0, res);
-}
-
-#ifndef V7_NO_FS
-static enum v7_err exec_file(struct v7 *v7, const char *path, val_t *res,
-                             int is_json) {
-  enum v7_err rcode = V7_OK;
-  char *p;
-  size_t file_size;
-  char *(*rd)(const char *, size_t *);
-
-  rd = cs_read_file;
-#ifdef V7_MMAP_EXEC
-  rd = cs_mmap_file;
-#ifdef V7_MMAP_EXEC_ONLY
-#define I_STRINGIFY(x) #x
-#define I_STRINGIFY2(x) I_STRINGIFY(x)
-
-  /* use mmap only for .js files */
-  if (strlen(path) <= 3 || strcmp(path + strlen(path) - 3, ".js") != 0) {
-    rd = cs_read_file;
-  }
-#endif
-#endif
-
-  if ((p = rd(path, &file_size)) == NULL) {
-    rcode = v7_throwf(v7, SYNTAX_ERROR, "cannot open [%s]", path);
-    /*
-     * In order to maintain compat with existing API, we should save the
-     * current exception value into `*res`
-     *
-     * TODO(dfrank): probably change API: clients can use
-     *`v7_get_thrown_value()` now.
-     */
-    if (res != NULL) *res = v7_get_thrown_value(v7, NULL);
-    goto clean;
-  } else {
-#ifndef V7_MMAP_EXEC
-    int fr = 1;
-#else
-    int fr = 0;
-#endif
-    rcode = b_exec(v7, p, file_size, path, V7_UNDEFINED, V7_UNDEFINED,
-                   V7_UNDEFINED, is_json, fr, 0, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-clean:
-  return rcode;
-}
-
-enum v7_err v7_exec_file(struct v7 *v7, const char *path, val_t *res) {
-  return exec_file(v7, path, res, 0);
-}
-
-enum v7_err v7_parse_json_file(struct v7 *v7, const char *path, v7_val_t *res) {
-  return exec_file(v7, path, res, 1);
-}
-#endif /* V7_NO_FS */
-
-enum v7_err v7_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
-                     v7_val_t args, v7_val_t *res) {
-  return b_apply(v7, func, this_obj, args, 0, res);
-}
-
-#ifndef NO_LIBC
-#if !defined(V7_NO_COMPILER)
-enum v7_err _v7_compile(const char *src, size_t js_code_size, int binary,
-                        int use_bcode, FILE *fp) {
-  struct ast ast;
-  struct v7 *v7 = v7_create();
-  ast_off_t pos = 0;
-  enum v7_err err;
-
-  v7->is_precompiling = 1;
-
-  ast_init(&ast, 0);
-  err = parse(v7, &ast, src, js_code_size, 0);
-  if (err == V7_OK) {
-    if (use_bcode) {
-      struct bcode bcode;
-      /*
-       * We don't set filename here, because the bcode will be just serialized
-       * and then freed. We don't currently serialize filename. If we ever do,
-       * we'll have to make `_v7_compile()` to also take a filename argument,
-       * and use it here.
-       */
-      bcode_init(&bcode, 0, NULL, 0);
-      err = compile_script(v7, &ast, &bcode);
-      if (err != V7_OK) {
-        goto cleanup_bcode;
-      }
-
-      if (binary) {
-        bcode_serialize(v7, &bcode, fp);
-      } else {
-#ifdef V7_BCODE_DUMP
-        dump_bcode(v7, fp, &bcode);
-#else
-        fprintf(stderr, "build flag V7_BCODE_DUMP not enabled\n");
-#endif
-      }
-    cleanup_bcode:
-      bcode_free(v7, &bcode);
-    } else {
-      if (binary) {
-        fwrite(BIN_AST_SIGNATURE, sizeof(BIN_AST_SIGNATURE), 1, fp);
-        fwrite(ast.mbuf.buf, ast.mbuf.len, 1, fp);
-      } else {
-        ast_dump_tree(fp, &ast, &pos, 0);
-      }
-    }
-  }
-
-  ast_free(&ast);
-  v7_destroy(v7);
-  return err;
-}
-
-enum v7_err v7_compile(const char *src, int binary, int use_bcode, FILE *fp) {
-  return _v7_compile(src, strlen(src), binary, use_bcode, fp);
-}
-#endif /* V7_NO_COMPILER */
-#endif
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/util.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "v7/src/eval.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/std_proxy.h" */
-
-void v7_print(struct v7 *v7, v7_val_t v) {
-  v7_fprint(stdout, v7, v);
-}
-
-void v7_fprint(FILE *f, struct v7 *v7, val_t v) {
-  char buf[16];
-  char *s = v7_stringify(v7, v, buf, sizeof(buf), V7_STRINGIFY_DEBUG);
-  fprintf(f, "%s", s);
-  if (buf != s) free(s);
-}
-
-void v7_println(struct v7 *v7, v7_val_t v) {
-  v7_fprintln(stdout, v7, v);
-}
-
-void v7_fprintln(FILE *f, struct v7 *v7, val_t v) {
-  v7_fprint(f, v7, v);
-  fprintf(f, ENDL);
-}
-
-void v7_fprint_stack_trace(FILE *f, struct v7 *v7, val_t e) {
-  size_t s;
-  val_t strace_v = v7_get(v7, e, "stack", ~0);
-  const char *strace = NULL;
-  if (v7_is_string(strace_v)) {
-    strace = v7_get_string(v7, &strace_v, &s);
-    fprintf(f, "%s\n", strace);
-  }
-}
-
-void v7_print_error(FILE *f, struct v7 *v7, const char *ctx, val_t e) {
-  /* TODO(mkm): figure out if this is an error object and which kind */
-  v7_val_t msg;
-  if (v7_is_undefined(e)) {
-    fprintf(f, "undefined error [%s]\n ", ctx);
-    return;
-  }
-  msg = v7_get(v7, e, "message", ~0);
-  if (v7_is_undefined(msg)) {
-    msg = e;
-  }
-  fprintf(f, "Exec error [%s]: ", ctx);
-  v7_fprintln(f, v7, msg);
-  v7_fprint_stack_trace(f, v7, e);
-}
-
-#if V7_ENABLE__Proxy
-
-v7_val_t v7_mk_proxy(struct v7 *v7, v7_val_t target,
-                     const v7_proxy_hnd_t *handler) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t res = V7_UNDEFINED;
-  v7_val_t args = V7_UNDEFINED;
-  v7_val_t handler_v = V7_UNDEFINED;
-
-  v7_own(v7, &res);
-  v7_own(v7, &args);
-  v7_own(v7, &handler_v);
-  v7_own(v7, &target);
-
-  /* if target is not an object, create one */
-  if (!v7_is_object(target)) {
-    target = v7_mk_object(v7);
-  }
-
-  /* prepare handler object with necessary properties */
-  handler_v = v7_mk_object(v7);
-  if (handler->get != NULL) {
-    set_cfunc_prop(v7, handler_v, "get", handler->get);
-  }
-  if (handler->set != NULL) {
-    set_cfunc_prop(v7, handler_v, "set", handler->set);
-  }
-  if (handler->own_keys != NULL) {
-    set_cfunc_prop(v7, handler_v, "ownKeys", handler->own_keys);
-  }
-  if (handler->get_own_prop_desc != NULL) {
-    v7_def(v7, handler_v, "_gpdc", ~0, V7_DESC_ENUMERABLE(0),
-           v7_mk_foreign(v7, (void *) handler->get_own_prop_desc));
-  }
-
-  /* prepare args */
-  args = v7_mk_dense_array(v7);
-  v7_array_set(v7, args, 0, target);
-  v7_array_set(v7, args, 1, handler_v);
-
-  /* call Proxy constructor */
-  V7_TRY(b_apply(v7, v7_get(v7, v7->vals.global_object, "Proxy", ~0),
-                 v7_mk_object(v7), args, 1 /* as ctor */, &res));
-
-clean:
-  if (rcode != V7_OK) {
-    fprintf(stderr, "error during v7_mk_proxy()");
-    res = V7_UNDEFINED;
-  }
-
-  v7_disown(v7, &target);
-  v7_disown(v7, &handler_v);
-  v7_disown(v7, &args);
-  v7_disown(v7, &res);
-  return res;
-}
-
-#endif /* V7_ENABLE__Proxy */
-
-V7_PRIVATE enum v7_type val_type(struct v7 *v7, val_t v) {
-  int tag;
-  if (v7_is_number(v)) {
-    return V7_TYPE_NUMBER;
-  }
-  tag = (v & V7_TAG_MASK) >> 48;
-  switch (tag) {
-    case V7_TAG_FOREIGN >> 48:
-      if (v7_is_null(v)) {
-        return V7_TYPE_NULL;
-      }
-      return V7_TYPE_FOREIGN;
-    case V7_TAG_UNDEFINED >> 48:
-      return V7_TYPE_UNDEFINED;
-    case V7_TAG_OBJECT >> 48:
-      if (v7_get_proto(v7, v) == v7->vals.array_prototype) {
-        return V7_TYPE_ARRAY_OBJECT;
-      } else if (v7_get_proto(v7, v) == v7->vals.boolean_prototype) {
-        return V7_TYPE_BOOLEAN_OBJECT;
-      } else if (v7_get_proto(v7, v) == v7->vals.string_prototype) {
-        return V7_TYPE_STRING_OBJECT;
-      } else if (v7_get_proto(v7, v) == v7->vals.number_prototype) {
-        return V7_TYPE_NUMBER_OBJECT;
-      } else if (v7_get_proto(v7, v) == v7->vals.function_prototype) {
-        return V7_TYPE_CFUNCTION_OBJECT;
-      } else if (v7_get_proto(v7, v) == v7->vals.date_prototype) {
-        return V7_TYPE_DATE_OBJECT;
-      } else {
-        return V7_TYPE_GENERIC_OBJECT;
-      }
-    case V7_TAG_STRING_I >> 48:
-    case V7_TAG_STRING_O >> 48:
-    case V7_TAG_STRING_F >> 48:
-    case V7_TAG_STRING_D >> 48:
-    case V7_TAG_STRING_5 >> 48:
-      return V7_TYPE_STRING;
-    case V7_TAG_BOOLEAN >> 48:
-      return V7_TYPE_BOOLEAN;
-    case V7_TAG_FUNCTION >> 48:
-      return V7_TYPE_FUNCTION_OBJECT;
-    case V7_TAG_CFUNCTION >> 48:
-      return V7_TYPE_CFUNCTION;
-    case V7_TAG_REGEXP >> 48:
-      return V7_TYPE_REGEXP_OBJECT;
-    default:
-      abort();
-      return V7_TYPE_UNDEFINED;
-  }
-}
-
-#ifndef V7_DISABLE_LINE_NUMBERS
-V7_PRIVATE uint8_t msb_lsb_swap(uint8_t b) {
-  if ((b & 0x01) != (b >> 7)) {
-    b ^= 0x81;
-  }
-  return b;
-}
-#endif
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/string.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/utf.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/varint.h" */
-/* Amalgamated: #include "v7/src/gc.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/slre.h" */
-/* Amalgamated: #include "v7/src/heapusage.h" */
-
-/* TODO(lsm): NaN payload location depends on endianness, make crossplatform */
-#define GET_VAL_NAN_PAYLOAD(v) ((char *) &(v))
-
-/*
- * Dictionary of read-only strings with length > 5.
- * NOTE(lsm): must be sorted lexicographically, because
- * v_find_string_in_dictionary performs binary search over this list.
- */
-/* clang-format off */
-static const struct v7_vec_const v_dictionary_strings[] = {
-    V7_VEC(" is not a function"),
-    V7_VEC("Boolean"),
-    V7_VEC("Crypto"),
-    V7_VEC("EvalError"),
-    V7_VEC("Function"),
-    V7_VEC("Infinity"),
-    V7_VEC("InternalError"),
-    V7_VEC("LOG10E"),
-    V7_VEC("MAX_VALUE"),
-    V7_VEC("MIN_VALUE"),
-    V7_VEC("NEGATIVE_INFINITY"),
-    V7_VEC("Number"),
-    V7_VEC("Object"),
-    V7_VEC("POSITIVE_INFINITY"),
-    V7_VEC("RangeError"),
-    V7_VEC("ReferenceError"),
-    V7_VEC("RegExp"),
-    V7_VEC("SQRT1_2"),
-    V7_VEC("Socket"),
-    V7_VEC("String"),
-    V7_VEC("SyntaxError"),
-    V7_VEC("TypeError"),
-    V7_VEC("UBJSON"),
-    V7_VEC("_modcache"),
-    V7_VEC("accept"),
-    V7_VEC("arguments"),
-    V7_VEC("base64_decode"),
-    V7_VEC("base64_encode"),
-    V7_VEC("boolean"),
-    V7_VEC("charAt"),
-    V7_VEC("charCodeAt"),
-    V7_VEC("concat"),
-    V7_VEC("configurable"),
-    V7_VEC("connect"),
-    V7_VEC("constructor"),
-    V7_VEC("create"),
-    V7_VEC("defineProperties"),
-    V7_VEC("defineProperty"),
-    V7_VEC("every"),
-    V7_VEC("exists"),
-    V7_VEC("exports"),
-    V7_VEC("filter"),
-    V7_VEC("forEach"),
-    V7_VEC("fromCharCode"),
-    V7_VEC("function"),
-    V7_VEC("getDate"),
-    V7_VEC("getDay"),
-    V7_VEC("getFullYear"),
-    V7_VEC("getHours"),
-    V7_VEC("getMilliseconds"),
-    V7_VEC("getMinutes"),
-    V7_VEC("getMonth"),
-    V7_VEC("getOwnPropertyDescriptor"),
-    V7_VEC("getOwnPropertyNames"),
-    V7_VEC("getPrototypeOf"),
-    V7_VEC("getSeconds"),
-    V7_VEC("getTime"),
-    V7_VEC("getTimezoneOffset"),
-    V7_VEC("getUTCDate"),
-    V7_VEC("getUTCDay"),
-    V7_VEC("getUTCFullYear"),
-    V7_VEC("getUTCHours"),
-    V7_VEC("getUTCMilliseconds"),
-    V7_VEC("getUTCMinutes"),
-    V7_VEC("getUTCMonth"),
-    V7_VEC("getUTCSeconds"),
-    V7_VEC("global"),
-    V7_VEC("hasOwnProperty"),
-    V7_VEC("ignoreCase"),
-    V7_VEC("indexOf"),
-    V7_VEC("isArray"),
-    V7_VEC("isExtensible"),
-    V7_VEC("isFinite"),
-    V7_VEC("isPrototypeOf"),
-    V7_VEC("lastIndex"),
-    V7_VEC("lastIndexOf"),
-    V7_VEC("length"),
-    V7_VEC("listen"),
-    V7_VEC("loadJSON"),
-    V7_VEC("localeCompare"),
-    V7_VEC("md5_hex"),
-    V7_VEC("module"),
-    V7_VEC("multiline"),
-    V7_VEC("number"),
-    V7_VEC("parseFloat"),
-    V7_VEC("parseInt"),
-    V7_VEC("preventExtensions"),
-    V7_VEC("propertyIsEnumerable"),
-    V7_VEC("prototype"),
-    V7_VEC("random"),
-    V7_VEC("recvAll"),
-    V7_VEC("reduce"),
-    V7_VEC("remove"),
-    V7_VEC("rename"),
-    V7_VEC("render"),
-    V7_VEC("replace"),
-    V7_VEC("require"),
-    V7_VEC("reverse"),
-    V7_VEC("search"),
-    V7_VEC("setDate"),
-    V7_VEC("setFullYear"),
-    V7_VEC("setHours"),
-    V7_VEC("setMilliseconds"),
-    V7_VEC("setMinutes"),
-    V7_VEC("setMonth"),
-    V7_VEC("setSeconds"),
-    V7_VEC("setTime"),
-    V7_VEC("setUTCDate"),
-    V7_VEC("setUTCFullYear"),
-    V7_VEC("setUTCHours"),
-    V7_VEC("setUTCMilliseconds"),
-    V7_VEC("setUTCMinutes"),
-    V7_VEC("setUTCMonth"),
-    V7_VEC("setUTCSeconds"),
-    V7_VEC("sha1_hex"),
-    V7_VEC("source"),
-    V7_VEC("splice"),
-    V7_VEC("string"),
-    V7_VEC("stringify"),
-    V7_VEC("substr"),
-    V7_VEC("substring"),
-    V7_VEC("toDateString"),
-    V7_VEC("toExponential"),
-    V7_VEC("toFixed"),
-    V7_VEC("toISOString"),
-    V7_VEC("toJSON"),
-    V7_VEC("toLocaleDateString"),
-    V7_VEC("toLocaleLowerCase"),
-    V7_VEC("toLocaleString"),
-    V7_VEC("toLocaleTimeString"),
-    V7_VEC("toLocaleUpperCase"),
-    V7_VEC("toLowerCase"),
-    V7_VEC("toPrecision"),
-    V7_VEC("toString"),
-    V7_VEC("toTimeString"),
-    V7_VEC("toUTCString"),
-    V7_VEC("toUpperCase"),
-    V7_VEC("valueOf"),
-    V7_VEC("writable"),
-};
-/* clang-format on */
-
-int nextesc(const char **p); /* from SLRE */
-V7_PRIVATE size_t unescape(const char *s, size_t len, char *to) {
-  const char *end = s + len;
-  size_t n = 0;
-  char tmp[4];
-  Rune r;
-
-  while (s < end) {
-    s += chartorune(&r, s);
-    if (r == '\\' && s < end) {
-      switch (*s) {
-        case '"':
-          s++, r = '"';
-          break;
-        case '\'':
-          s++, r = '\'';
-          break;
-        case '\n':
-          s++, r = '\n';
-          break;
-        default: {
-          const char *tmp_s = s;
-          int i = nextesc(&s);
-          switch (i) {
-            case -SLRE_INVALID_ESC_CHAR:
-              r = '\\';
-              s = tmp_s;
-              n += runetochar(to == NULL ? tmp : to + n, &r);
-              s += chartorune(&r, s);
-              break;
-            case -SLRE_INVALID_HEX_DIGIT:
-            default:
-              r = i;
-          }
-        }
-      }
-    }
-    n += runetochar(to == NULL ? tmp : to + n, &r);
-  }
-
-  return n;
-}
-
-static int v_find_string_in_dictionary(const char *s, size_t len) {
-  size_t start = 0, end = ARRAY_SIZE(v_dictionary_strings);
-
-  while (s != NULL && start < end) {
-    size_t mid = start + (end - start) / 2;
-    const struct v7_vec_const *v = &v_dictionary_strings[mid];
-    size_t min_len = len < v->len ? len : v->len;
-    int comparison_result = memcmp(s, v->p, min_len);
-    if (comparison_result == 0) {
-      comparison_result = len - v->len;
-    }
-    if (comparison_result < 0) {
-      end = mid;
-    } else if (comparison_result > 0) {
-      start = mid + 1;
-    } else {
-      return mid;
-    }
-  }
-  return -1;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err v7_char_code_at(struct v7 *v7, val_t obj, val_t arg,
-                                       double *res) {
-  enum v7_err rcode = V7_OK;
-  size_t n;
-  val_t s = V7_UNDEFINED;
-  const char *p = NULL;
-  double at = v7_get_double(v7, arg);
-
-  *res = 0;
-
-  rcode = to_string(v7, obj, &s, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  p = v7_get_string(v7, &s, &n);
-
-  n = utfnlen(p, n);
-  if (v7_is_number(arg) && at >= 0 && at < n) {
-    Rune r = 0;
-    p = utfnshift(p, at);
-    chartorune(&r, (char *) p);
-    *res = r;
-    goto clean;
-  } else {
-    *res = NAN;
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-V7_PRIVATE int s_cmp(struct v7 *v7, val_t a, val_t b) {
-  size_t a_len, b_len;
-  const char *a_ptr, *b_ptr;
-
-  a_ptr = v7_get_string(v7, &a, &a_len);
-  b_ptr = v7_get_string(v7, &b, &b_len);
-
-  if (a_len == b_len) {
-    return memcmp(a_ptr, b_ptr, a_len);
-  }
-  if (a_len > b_len) {
-    return 1;
-  } else if (a_len < b_len) {
-    return -1;
-  } else {
-    return 0;
-  }
-}
-
-V7_PRIVATE val_t s_concat(struct v7 *v7, val_t a, val_t b) {
-  size_t a_len, b_len, res_len;
-  const char *a_ptr, *b_ptr, *res_ptr;
-  val_t res;
-
-  /* Find out lengths of both srtings */
-  a_ptr = v7_get_string(v7, &a, &a_len);
-  b_ptr = v7_get_string(v7, &b, &b_len);
-
-  /* Create an placeholder string */
-  res = v7_mk_string(v7, NULL, a_len + b_len, 1);
-
-  /* v7_mk_string() may have reallocated mbuf - revalidate pointers */
-  a_ptr = v7_get_string(v7, &a, &a_len);
-  b_ptr = v7_get_string(v7, &b, &b_len);
-
-  /* Copy strings into the placeholder */
-  res_ptr = v7_get_string(v7, &res, &res_len);
-  memcpy((char *) res_ptr, a_ptr, a_len);
-  memcpy((char *) res_ptr + a_len, b_ptr, b_len);
-
-  return res;
-}
-
-V7_PRIVATE unsigned long cstr_to_ulong(const char *s, size_t len, int *ok) {
-  char *e;
-  unsigned long res = strtoul(s, &e, 10);
-  *ok = (e == s + len) && len != 0;
-  return res;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err str_to_ulong(struct v7 *v7, val_t v, int *ok,
-                                    unsigned long *res) {
-  enum v7_err rcode = V7_OK;
-  char buf[100];
-  size_t len = 0;
-
-  V7_TRY(to_string(v7, v, NULL, buf, sizeof(buf), &len));
-
-  *res = cstr_to_ulong(buf, len, ok);
-
-clean:
-  return rcode;
-}
-
-/* Insert a string into mbuf at specified offset */
-V7_PRIVATE void embed_string(struct mbuf *m, size_t offset, const char *p,
-                             size_t len, uint8_t /*enum embstr_flags*/ flags) {
-  char *old_base = m->buf;
-  uint8_t p_backed_by_mbuf = p >= old_base && p < old_base + m->len;
-  size_t n = (flags & EMBSTR_UNESCAPE) ? unescape(p, len, NULL) : len;
-
-  /* Calculate how many bytes length takes */
-  int k = calc_llen(n);
-
-  /* total length: varing length + string len + zero-term */
-  size_t tot_len = k + n + !!(flags & EMBSTR_ZERO_TERM);
-
-  /* Allocate buffer */
-  heapusage_dont_count(1);
-  mbuf_insert(m, offset, NULL, tot_len);
-  heapusage_dont_count(0);
-
-  /* Fixup p if it was relocated by mbuf_insert() above */
-  if (p_backed_by_mbuf) {
-    p += m->buf - old_base;
-  }
-
-  /* Write length */
-  encode_varint(n, (unsigned char *) m->buf + offset);
-
-  /* Write string */
-  if (p != 0) {
-    if (flags & EMBSTR_UNESCAPE) {
-      unescape(p, len, m->buf + offset + k);
-    } else {
-      memcpy(m->buf + offset + k, p, len);
-    }
-  }
-
-  /* add NULL-terminator if needed */
-  if (flags & EMBSTR_ZERO_TERM) {
-    m->buf[offset + tot_len - 1] = '\0';
-  }
-}
-
-/* Create a string */
-v7_val_t v7_mk_string(struct v7 *v7, const char *p, size_t len, int copy) {
-  struct mbuf *m = copy ? &v7->owned_strings : &v7->foreign_strings;
-  val_t offset = m->len, tag = V7_TAG_STRING_F;
-  int dict_index;
-
-#ifdef V7_GC_AFTER_STRING_ALLOC
-  v7->need_gc = 1;
-#endif
-
-  if (len == ~((size_t) 0)) len = strlen(p);
-
-  if (len <= 4) {
-    char *s = GET_VAL_NAN_PAYLOAD(offset) + 1;
-    offset = 0;
-    if (p != 0) {
-      memcpy(s, p, len);
-    }
-    s[-1] = len;
-    tag = V7_TAG_STRING_I;
-  } else if (len == 5) {
-    char *s = GET_VAL_NAN_PAYLOAD(offset);
-    offset = 0;
-    if (p != 0) {
-      memcpy(s, p, len);
-    }
-    tag = V7_TAG_STRING_5;
-  } else if ((dict_index = v_find_string_in_dictionary(p, len)) >= 0) {
-    offset = 0;
-    GET_VAL_NAN_PAYLOAD(offset)[0] = dict_index;
-    tag = V7_TAG_STRING_D;
-  } else if (copy) {
-    compute_need_gc(v7);
-
-    /*
-     * Before embedding new string, check if the reallocation is needed.  If
-     * so, perform the reallocation by calling `mbuf_resize` manually, since we
-     * need to preallocate some extra space (`_V7_STRING_BUF_RESERVE`)
-     */
-    if ((m->len + len) > m->size) {
-      heapusage_dont_count(1);
-      mbuf_resize(m, m->len + len + _V7_STRING_BUF_RESERVE);
-      heapusage_dont_count(0);
-    }
-    embed_string(m, m->len, p, len, EMBSTR_ZERO_TERM);
-    tag = V7_TAG_STRING_O;
-#ifndef V7_DISABLE_STR_ALLOC_SEQ
-    /* TODO(imax): panic if offset >= 2^32. */
-    offset |= ((val_t) gc_next_allocation_seqn(v7, p, len)) << 32;
-#endif
-  } else {
-    /* foreign string */
-    if (sizeof(void *) <= 4 && len <= UINT16_MAX) {
-      /* small foreign strings can fit length and ptr in the val_t */
-      offset = (uint64_t) len << 32 | (uint64_t)(uintptr_t) p;
-    } else {
-      /* bigger strings need indirection that uses ram */
-      size_t pos = m->len;
-      int llen = calc_llen(len);
-
-      /* allocate space for len and ptr */
-      heapusage_dont_count(1);
-      mbuf_insert(m, pos, NULL, llen + sizeof(p));
-      heapusage_dont_count(0);
-
-      encode_varint(len, (uint8_t *) (m->buf + pos));
-      memcpy(m->buf + pos + llen, &p, sizeof(p));
-    }
-    tag = V7_TAG_STRING_F;
-  }
-
-  /* NOTE(lsm): don't use pointer_to_value, 32-bit ptrs will truncate */
-  return (offset & ~V7_TAG_MASK) | tag;
-}
-
-int v7_is_string(val_t v) {
-  uint64_t t = v & V7_TAG_MASK;
-  return t == V7_TAG_STRING_I || t == V7_TAG_STRING_F || t == V7_TAG_STRING_O ||
-         t == V7_TAG_STRING_5 || t == V7_TAG_STRING_D;
-}
-
-/* Get a pointer to string and string length. */
-const char *v7_get_string(struct v7 *v7, val_t *v, size_t *sizep) {
-  uint64_t tag = v[0] & V7_TAG_MASK;
-  const char *p = NULL;
-  int llen;
-  size_t size = 0;
-
-  if (!v7_is_string(*v)) {
-    goto clean;
-  }
-
-  if (tag == V7_TAG_STRING_I) {
-    p = GET_VAL_NAN_PAYLOAD(*v) + 1;
-    size = p[-1];
-  } else if (tag == V7_TAG_STRING_5) {
-    p = GET_VAL_NAN_PAYLOAD(*v);
-    size = 5;
-  } else if (tag == V7_TAG_STRING_D) {
-    int index = ((unsigned char *) GET_VAL_NAN_PAYLOAD(*v))[0];
-    size = v_dictionary_strings[index].len;
-    p = v_dictionary_strings[index].p;
-  } else if (tag == V7_TAG_STRING_O) {
-    size_t offset = (size_t) gc_string_val_to_offset(*v);
-    char *s = v7->owned_strings.buf + offset;
-
-#ifndef V7_DISABLE_STR_ALLOC_SEQ
-    gc_check_valid_allocation_seqn(v7, (*v >> 32) & 0xFFFF);
-#endif
-
-    size = decode_varint((uint8_t *) s, &llen);
-    p = s + llen;
-  } else if (tag == V7_TAG_STRING_F) {
-    /*
-     * short foreign strings on <=32-bit machines can be encoded in a compact
-     * form:
-     *
-     *     7         6        5        4        3        2        1        0
-     *  11111111|1111tttt|llllllll|llllllll|ssssssss|ssssssss|ssssssss|ssssssss
-     *
-     * Strings longer than 2^26 will be indireceted through the foreign_strings
-     * mbuf.
-     *
-     * We don't use a different tag to represent those two cases. Instead, all
-     * foreign strings represented with the help of the foreign_strings mbuf
-     * will have the upper 16-bits of the payload set to zero. This allows us to
-     * represent up to 477 million foreign strings longer than 64k.
-     */
-    uint16_t len = (*v >> 32) & 0xFFFF;
-    if (sizeof(void *) <= 4 && len != 0) {
-      size = (size_t) len;
-      p = (const char *) (uintptr_t) *v;
-    } else {
-      size_t offset = (size_t) gc_string_val_to_offset(*v);
-      char *s = v7->foreign_strings.buf + offset;
-
-      size = decode_varint((uint8_t *) s, &llen);
-      memcpy(&p, s + llen, sizeof(p));
-    }
-  } else {
-    assert(0);
-  }
-
-clean:
-  if (sizep != NULL) {
-    *sizep = size;
-  }
-  return p;
-}
-
-const char *v7_get_cstring(struct v7 *v7, v7_val_t *value) {
-  size_t size;
-  const char *s = v7_get_string(v7, value, &size);
-  if (s == NULL) return NULL;
-  if (s[size] != 0 || strlen(s) != size) {
-    return NULL;
-  }
-  return s;
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/array.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/str_util.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-/* like c_snprintf but returns `size` if write is truncated */
-static int v_sprintf_s(char *buf, size_t size, const char *fmt, ...) {
-  size_t n;
-  va_list ap;
-  va_start(ap, fmt);
-  n = c_vsnprintf(buf, size, fmt, ap);
-  if (n > size) {
-    return size;
-  }
-  return n;
-}
-
-v7_val_t v7_mk_array(struct v7 *v7) {
-  val_t a = mk_object(v7, v7->vals.array_prototype);
-#if 0
-  v7_def(v7, a, "", 0, _V7_DESC_HIDDEN(1), V7_NULL);
-#endif
-  return a;
-}
-
-int v7_is_array(struct v7 *v7, val_t v) {
-  return v7_is_generic_object(v) &&
-         is_prototype_of(v7, v, v7->vals.array_prototype);
-}
-
-/*
- * Dense arrays are backed by mbuf. Currently the array can only grow by
- * appending (i.e. setting an element whose index == array.length)
- *
- * TODO(mkm): automatically promote dense arrays to normal objects
- *            when they are used as sparse arrays or to store arbitrary keys
- *            (perhaps a hybrid approach)
- * TODO(mkm): small sparsness doesn't have to promote the array,
- *            we can just fill empty slots with a tag. In JS missing array
- *            indices are subtly different from indices with an undefined value
- *            (key iteration).
- * TODO(mkm): change the interpreter so it can set elements in dense arrays
- */
-V7_PRIVATE val_t v7_mk_dense_array(struct v7 *v7) {
-  val_t a = v7_mk_array(v7);
-#ifdef V7_ENABLE_DENSE_ARRAYS
-  v7_own(v7, &a);
-  v7_def(v7, a, "", 0, _V7_DESC_HIDDEN(1), V7_NULL);
-
-  /*
-   * Before setting a `V7_OBJ_DENSE_ARRAY` flag, make sure we don't have
-   * `V7_OBJ_FUNCTION` flag set
-   */
-  assert(!(get_object_struct(a)->attributes & V7_OBJ_FUNCTION));
-  get_object_struct(a)->attributes |= V7_OBJ_DENSE_ARRAY;
-
-  v7_disown(v7, &a);
-#endif
-  return a;
-}
-
-/* TODO_V7_ERR */
-val_t v7_array_get(struct v7 *v7, val_t arr, unsigned long index) {
-  return v7_array_get2(v7, arr, index, NULL);
-}
-
-/* TODO_V7_ERR */
-val_t v7_array_get2(struct v7 *v7, val_t arr, unsigned long index, int *has) {
-  enum v7_err rcode = V7_OK;
-  val_t res;
-
-  if (has != NULL) {
-    *has = 0;
-  }
-  if (v7_is_object(arr)) {
-    if (get_object_struct(arr)->attributes & V7_OBJ_DENSE_ARRAY) {
-      struct v7_property *p =
-          v7_get_own_property2(v7, arr, "", 0, _V7_PROPERTY_HIDDEN);
-      struct mbuf *abuf = NULL;
-      unsigned long len;
-      if (p != NULL) {
-        abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
-      }
-      if (abuf == NULL) {
-        res = V7_UNDEFINED;
-        goto clean;
-      }
-      len = abuf->len / sizeof(val_t);
-      if (index >= len) {
-        res = V7_UNDEFINED;
-        goto clean;
-      } else {
-        memcpy(&res, abuf->buf + index * sizeof(val_t), sizeof(val_t));
-        if (has != NULL && res != V7_TAG_NOVALUE) *has = 1;
-        if (res == V7_TAG_NOVALUE) {
-          res = V7_UNDEFINED;
-        }
-        goto clean;
-      }
-    } else {
-      struct v7_property *p;
-      char buf[20];
-      int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
-      p = v7_get_property(v7, arr, buf, n);
-      if (has != NULL && p != NULL) *has = 1;
-      V7_TRY(v7_property_value(v7, arr, p, &res));
-      goto clean;
-    }
-  } else {
-    res = V7_UNDEFINED;
-    goto clean;
-  }
-
-clean:
-  (void) rcode;
-  return res;
-}
-
-#if V7_ENABLE_DENSE_ARRAYS
-
-/* Create V7 strings for integers such as array indices */
-static val_t ulong_to_str(struct v7 *v7, unsigned long n) {
-  char buf[100];
-  int len;
-  len = c_snprintf(buf, sizeof(buf), "%lu", n);
-  return v7_mk_string(v7, buf, len, 1);
-}
-
-/*
- * Pack 15-bit length and 15 bit index, leaving 2 bits for tag. the LSB has to
- * be set to distinguish it from a prop pointer.
- * In alternative we just fetch the length from obj at each call to v7_next_prop
- * and just stuff the index here (e.g. on 8/16-bit platforms).
- * TODO(mkm): conditional for 16-bit platforms
- */
-#define PACK_ITER(len, idx) \
-  ((struct v7_property *) ((len) << 17 | (idx) << 1 | 1))
-
-#define UNPACK_ITER_LEN(p) (((uintptr_t) p) >> 17)
-#define UNPACK_ITER_IDX(p) ((((uintptr_t) p) >> 1) & 0x7FFF)
-#define IS_PACKED_ITER(p) ((uintptr_t) p & 1)
-
-void *v7_next_prop(struct v7 *v7, val_t obj, void *h, val_t *name, val_t *val,
-                   v7_prop_attr_t *attrs) {
-  struct v7_property *p = (struct v7_property *) h;
-
-  if (get_object_struct(obj)->attributes & V7_OBJ_DENSE_ARRAY) {
-    /* This is a dense array. Find backing mbuf and fetch values from there */
-    struct v7_property *hp =
-        v7_get_own_property2(v7, obj, "", 0, _V7_PROPERTY_HIDDEN);
-    struct mbuf *abuf = NULL;
-    unsigned long len, idx;
-    if (hp != NULL) {
-      abuf = (struct mbuf *) v7_get_ptr(v7, hp->value);
-    }
-    if (abuf == NULL) return NULL;
-    len = abuf->len / sizeof(val_t);
-    if (len == 0) return NULL;
-    idx = (p == NULL) ? 0 : UNPACK_ITER_IDX(p) + 1;
-    p = (idx == len) ? get_object_struct(obj)->properties : PACK_ITER(len, idx);
-    if (val != NULL) *val = ((val_t *) abuf->buf)[idx];
-    if (attrs != NULL) *attrs = 0;
-    if (name != NULL) {
-      char buf[20];
-      int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
-      *name = v7_mk_string(v7, buf, n, 1);
-    }
-  } else {
-    /* Ordinary object */
-    p = (p == NULL) ? get_object_struct(obj)->properties : p->next;
-    if (p != NULL) {
-      if (name != NULL) *name = p->name;
-      if (val != NULL) *val = p->value;
-      if (attrs != NULL) *attrs = p->attributes;
-    }
-  }
-
-  return p;
-}
-
-V7_PRIVATE val_t
-v7_iter_get_value(struct v7 *v7, val_t obj, struct v7_property *p) {
-  return IS_PACKED_ITER(p) ? v7_array_get(v7, obj, UNPACK_ITER_IDX(p))
-                           : p->value;
-}
-
-V7_PRIVATE val_t v7_iter_get_name(struct v7 *v7, struct v7_property *p) {
-  return IS_PACKED_ITER(p) ? ulong_to_str(v7, UNPACK_ITER_IDX(p)) : p->name;
-}
-
-V7_PRIVATE uint8_t v7_iter_get_attrs(struct v7_property *p) {
-  return IS_PACKED_ITER(p) ? 0 : p->attributes;
-}
-
-/* return array index as number or undefined. works with iterators */
-V7_PRIVATE enum v7_err v7_iter_get_index(struct v7 *v7, struct v7_property *p,
-                                         val_t *res) {
-  enum v7_err rcode = V7_OK;
-  int ok;
-  unsigned long res;
-  if (IS_PACKED_ITER(p)) {
-    *res = v7_mk_number(v7, UNPACK_ITER_IDX(p));
-    goto clean;
-  }
-  V7_TRY(str_to_ulong(v7, p->name, &ok, &res));
-  if (!ok || res >= UINT32_MAX) {
-    goto clean;
-  }
-  *res = v7_mk_number(v7, res);
-  goto clean;
-
-clean:
-  return rcode;
-}
-#endif
-
-/* TODO_V7_ERR */
-unsigned long v7_array_length(struct v7 *v7, val_t v) {
-  enum v7_err rcode = V7_OK;
-  struct v7_property *p;
-  unsigned long len = 0;
-
-  if (!v7_is_object(v)) {
-    len = 0;
-    goto clean;
-  }
-
-#if V7_ENABLE_DENSE_ARRAYS
-  if (get_object_struct(v)->attributes & V7_OBJ_DENSE_ARRAY) {
-    struct v7_property *p =
-        v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
-    struct mbuf *abuf;
-    if (p == NULL) {
-      len = 0;
-      goto clean;
-    }
-    abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
-    if (abuf == NULL) {
-      len = 0;
-      goto clean;
-    }
-    len = abuf->len / sizeof(val_t);
-    goto clean;
-  }
-#endif
-
-  for (p = get_object_struct(v)->properties; p != NULL; p = p->next) {
-    int ok = 0;
-    unsigned long n = 0;
-    V7_TRY(str_to_ulong(v7, p->name, &ok, &n));
-    if (ok && n >= len && n < UINT32_MAX) {
-      len = n + 1;
-    }
-  }
-
-clean:
-  (void) rcode;
-  return len;
-}
-
-int v7_array_set(struct v7 *v7, val_t arr, unsigned long index, val_t v) {
-  enum v7_err rcode = V7_OK;
-  uint8_t saved_is_thrown = 0;
-  val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
-  int ret = -1;
-
-  rcode = v7_array_set_throwing(v7, arr, index, v, &ret);
-  if (rcode != V7_OK) {
-    rcode = V7_OK;
-    if (saved_is_thrown) {
-      rcode = v7_throw(v7, saved_thrown);
-    } else {
-      v7_clear_thrown_value(v7);
-    }
-    ret = -1;
-  }
-
-  return ret;
-}
-
-enum v7_err v7_array_set_throwing(struct v7 *v7, val_t arr, unsigned long index,
-                                  val_t v, int *res) {
-  enum v7_err rcode = V7_OK;
-  int ires = -1;
-
-  if (v7_is_object(arr)) {
-    if (get_object_struct(arr)->attributes & V7_OBJ_DENSE_ARRAY) {
-      struct v7_property *p =
-          v7_get_own_property2(v7, arr, "", 0, _V7_PROPERTY_HIDDEN);
-      struct mbuf *abuf;
-      unsigned long len;
-      assert(p != NULL);
-      abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
-
-      if (get_object_struct(arr)->attributes & V7_OBJ_NOT_EXTENSIBLE) {
-        if (is_strict_mode(v7)) {
-          rcode = v7_throwf(v7, TYPE_ERROR, "Object is not extensible");
-          goto clean;
-        }
-
-        goto clean;
-      }
-
-      if (abuf == NULL) {
-        abuf = (struct mbuf *) malloc(sizeof(*abuf));
-        mbuf_init(abuf, sizeof(val_t) * (index + 1));
-        p->value = v7_mk_foreign(v7, abuf);
-      }
-      len = abuf->len / sizeof(val_t);
-      /* TODO(mkm): possibly promote to sparse array */
-      if (index > len) {
-        unsigned long i;
-        val_t s = V7_TAG_NOVALUE;
-        for (i = len; i < index; i++) {
-          mbuf_append(abuf, (char *) &s, sizeof(val_t));
-        }
-        len = index;
-      }
-
-      if (index == len) {
-        mbuf_append(abuf, (char *) &v, sizeof(val_t));
-      } else {
-        memcpy(abuf->buf + index * sizeof(val_t), &v, sizeof(val_t));
-      }
-    } else {
-      char buf[20];
-      int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
-      {
-        struct v7_property *tmp = NULL;
-        rcode = set_property(v7, arr, buf, n, v, &tmp);
-        ires = (tmp == NULL) ? -1 : 0;
-      }
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-    }
-  }
-
-clean:
-  if (res != NULL) {
-    *res = ires;
-  }
-  return rcode;
-}
-
-void v7_array_del(struct v7 *v7, val_t arr, unsigned long index) {
-  char buf[20];
-  int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
-  v7_del(v7, arr, buf, n);
-}
-
-int v7_array_push(struct v7 *v7, v7_val_t arr, v7_val_t v) {
-  return v7_array_set(v7, arr, v7_array_length(v7, arr), v);
-}
-
-WARN_UNUSED_RESULT
-enum v7_err v7_array_push_throwing(struct v7 *v7, v7_val_t arr, v7_val_t v,
-                                   int *res) {
-  return v7_array_set_throwing(v7, arr, v7_array_length(v7, arr), v, res);
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/object.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/gc.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "v7/src/eval.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/std_proxy.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-
-/*
- * Default property attributes (see `v7_prop_attr_t`)
- */
-#define V7_DEFAULT_PROPERTY_ATTRS 0
-
-V7_PRIVATE val_t mk_object(struct v7 *v7, val_t prototype) {
-  struct v7_generic_object *o = new_generic_object(v7);
-  if (o == NULL) {
-    return V7_NULL;
-  }
-  (void) v7;
-#if defined(V7_ENABLE_ENTITY_IDS)
-  o->base.entity_id_base = V7_ENTITY_ID_PART_OBJ;
-  o->base.entity_id_spec = V7_ENTITY_ID_PART_GEN_OBJ;
-#endif
-  o->base.properties = NULL;
-  obj_prototype_set(v7, &o->base, get_object_struct(prototype));
-  return v7_object_to_value(&o->base);
-}
-
-v7_val_t v7_mk_object(struct v7 *v7) {
-  return mk_object(v7, v7->vals.object_prototype);
-}
-
-V7_PRIVATE val_t v7_object_to_value(struct v7_object *o) {
-  if (o == NULL) {
-    return V7_NULL;
-  } else if (o->attributes & V7_OBJ_FUNCTION) {
-    return pointer_to_value(o) | V7_TAG_FUNCTION;
-  } else {
-    return pointer_to_value(o) | V7_TAG_OBJECT;
-  }
-}
-
-V7_PRIVATE struct v7_generic_object *get_generic_object_struct(val_t v) {
-  struct v7_generic_object *ret = NULL;
-  if (v7_is_null(v)) {
-    ret = NULL;
-  } else {
-    assert(v7_is_generic_object(v));
-    ret = (struct v7_generic_object *) get_ptr(v);
-#if defined(V7_ENABLE_ENTITY_IDS)
-    if (ret->base.entity_id_base != V7_ENTITY_ID_PART_OBJ) {
-      fprintf(stderr, "not a generic object!\n");
-      abort();
-    } else if (ret->base.entity_id_spec != V7_ENTITY_ID_PART_GEN_OBJ) {
-      fprintf(stderr, "not an object (but is a generic object)!\n");
-      abort();
-    }
-#endif
-  }
-  return ret;
-}
-
-V7_PRIVATE struct v7_object *get_object_struct(val_t v) {
-  struct v7_object *ret = NULL;
-  if (v7_is_null(v)) {
-    ret = NULL;
-  } else {
-    assert(v7_is_object(v));
-    ret = (struct v7_object *) get_ptr(v);
-#if defined(V7_ENABLE_ENTITY_IDS)
-    if (ret->entity_id_base != V7_ENTITY_ID_PART_OBJ) {
-      fprintf(stderr, "not an object!\n");
-      abort();
-    }
-#endif
-  }
-  return ret;
-}
-
-int v7_is_object(val_t v) {
-  return (v & V7_TAG_MASK) == V7_TAG_OBJECT ||
-         (v & V7_TAG_MASK) == V7_TAG_FUNCTION;
-}
-
-V7_PRIVATE int v7_is_generic_object(val_t v) {
-  return (v & V7_TAG_MASK) == V7_TAG_OBJECT;
-}
-
-/* Object properties {{{ */
-
-V7_PRIVATE struct v7_property *v7_mk_property(struct v7 *v7) {
-  struct v7_property *p = new_property(v7);
-#if defined(V7_ENABLE_ENTITY_IDS)
-  p->entity_id = V7_ENTITY_ID_PROP;
-#endif
-  p->next = NULL;
-  p->name = V7_UNDEFINED;
-  p->value = V7_UNDEFINED;
-  p->attributes = 0;
-  return p;
-}
-
-V7_PRIVATE struct v7_property *v7_get_own_property2(struct v7 *v7, val_t obj,
-                                                    const char *name,
-                                                    size_t len,
-                                                    v7_prop_attr_t attrs) {
-  struct v7_property *p;
-  struct v7_object *o;
-  val_t ss;
-  if (!v7_is_object(obj)) {
-    return NULL;
-  }
-  if (len == (size_t) ~0) {
-    len = strlen(name);
-  }
-
-  o = get_object_struct(obj);
-  /*
-   * len check is needed to allow getting the mbuf from the hidden property.
-   * TODO(mkm): however hidden properties cannot be safely represented with
-   * a zero length string anyway, so this will change.
-   */
-  if (o->attributes & V7_OBJ_DENSE_ARRAY && len > 0) {
-    int ok, has;
-    unsigned long i = cstr_to_ulong(name, len, &ok);
-    if (ok) {
-      v7->cur_dense_prop->value = v7_array_get2(v7, obj, i, &has);
-      return has ? v7->cur_dense_prop : NULL;
-    }
-  }
-
-  if (len <= 5) {
-    ss = v7_mk_string(v7, name, len, 1);
-    for (p = o->properties; p != NULL; p = p->next) {
-#if defined(V7_ENABLE_ENTITY_IDS)
-      if (p->entity_id != V7_ENTITY_ID_PROP) {
-        fprintf(stderr, "not a prop!=0x%x\n", p->entity_id);
-        abort();
-      }
-#endif
-      if (p->name == ss && (attrs == 0 || (p->attributes & attrs))) {
-        return p;
-      }
-    }
-  } else {
-    for (p = o->properties; p != NULL; p = p->next) {
-      size_t n;
-      const char *s = v7_get_string(v7, &p->name, &n);
-#if defined(V7_ENABLE_ENTITY_IDS)
-      if (p->entity_id != V7_ENTITY_ID_PROP) {
-        fprintf(stderr, "not a prop!=0x%x\n", p->entity_id);
-        abort();
-      }
-#endif
-      if (n == len && strncmp(s, name, len) == 0 &&
-          (attrs == 0 || (p->attributes & attrs))) {
-        return p;
-      }
-    }
-  }
-  return NULL;
-}
-
-V7_PRIVATE struct v7_property *v7_get_own_property(struct v7 *v7, val_t obj,
-                                                   const char *name,
-                                                   size_t len) {
-  return v7_get_own_property2(v7, obj, name, len, 0);
-}
-
-V7_PRIVATE struct v7_property *v7_get_property(struct v7 *v7, val_t obj,
-                                               const char *name, size_t len) {
-  if (!v7_is_object(obj)) {
-    return NULL;
-  }
-  for (; obj != V7_NULL; obj = v7_get_proto(v7, obj)) {
-    struct v7_property *prop;
-    if ((prop = v7_get_own_property(v7, obj, name, len)) != NULL) {
-      return prop;
-    }
-  }
-  return NULL;
-}
-
-V7_PRIVATE enum v7_err v7_get_property_v(struct v7 *v7, val_t obj,
-                                         v7_val_t name,
-                                         struct v7_property **res) {
-  enum v7_err rcode = V7_OK;
-  size_t name_len;
-  STATIC char buf[8];
-  const char *s = buf;
-  uint8_t fr = 0;
-
-  if (v7_is_string(name)) {
-    s = v7_get_string(v7, &name, &name_len);
-  } else {
-    char *stmp;
-    V7_TRY(v7_stringify_throwing(v7, name, buf, sizeof(buf),
-                                 V7_STRINGIFY_DEFAULT, &stmp));
-    s = stmp;
-    if (s != buf) {
-      fr = 1;
-    }
-    name_len = strlen(s);
-  }
-
-  *res = v7_get_property(v7, obj, s, name_len);
-
-clean:
-  if (fr) {
-    free((void *) s);
-  }
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-enum v7_err v7_get_throwing(struct v7 *v7, val_t obj, const char *name,
-                            size_t name_len, val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t v = obj;
-
-  v7_own(v7, &v);
-
-  if (name_len == (size_t) ~0) {
-    name_len = strlen(name);
-  }
-
-  if (v7_is_string(obj)) {
-    v = v7->vals.string_prototype;
-  } else if (v7_is_number(obj)) {
-    v = v7->vals.number_prototype;
-  } else if (v7_is_boolean(obj)) {
-    v = v7->vals.boolean_prototype;
-  } else if (v7_is_undefined(obj)) {
-    rcode =
-        v7_throwf(v7, TYPE_ERROR, "cannot read property '%.*s' of undefined",
-                  (int) name_len, name);
-    goto clean;
-  } else if (v7_is_null(obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "cannot read property '%.*s' of null",
-                      (int) name_len, name);
-    goto clean;
-  } else if (is_cfunction_lite(obj)) {
-    v = v7->vals.function_prototype;
-  }
-
-#if V7_ENABLE__Proxy
-  {
-    struct v7_object *o = NULL;
-    if (v7_is_object(obj)) {
-      o = get_object_struct(obj);
-    }
-
-    if (o != NULL && (o->attributes & V7_OBJ_PROXY) &&
-        !is_special_proxy_name(name, name_len)) {
-      /* we need to access the target object through a proxy */
-
-      val_t target_v = V7_UNDEFINED;
-      val_t handler_v = V7_UNDEFINED;
-      val_t name_v = V7_UNDEFINED;
-      val_t get_v = V7_UNDEFINED;
-      val_t get_args_v = V7_UNDEFINED;
-
-      /*
-       * we need to create a copy of the name, because the given `name` might
-       * be returned by v7_get_string(), and any object creation might
-       * invalidate this pointer. Below, we're going to create some objects.
-       *
-       * It would probably be cleaner to always create a copy before calling
-       * v7_get_throwing if the name was returned by v7_get_string(), but that
-       * would cause additional pressure on the heap, so let's not do that
-       */
-      char *name_copy = (char *) calloc(1, name_len + 1 /* null-term */);
-      memcpy(name_copy, name, name_len);
-
-      v7_own(v7, &target_v);
-      v7_own(v7, &handler_v);
-      v7_own(v7, &name_v);
-      v7_own(v7, &get_v);
-      v7_own(v7, &get_args_v);
-
-      V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, &target_v),
-              clean_proxy);
-      V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, &handler_v),
-              clean_proxy);
-      V7_TRY2(v7_get_throwing(v7, handler_v, "get", ~0, &get_v), clean_proxy);
-
-      if (v7_is_callable(v7, get_v)) {
-        /* The `get` callback is actually callable, so, use it */
-
-        /* prepare arguments for the callback */
-        get_args_v = v7_mk_dense_array(v7);
-        /*
-         * TODO(dfrank): don't copy string in case we already have val_t (we
-         * need some generic function which will take both `const char *` and
-         * val_t)
-         */
-        v7_array_set(v7, get_args_v, 0, target_v);
-        v7_array_set(v7, get_args_v, 1,
-                     v7_mk_string(v7, name_copy, name_len, 1));
-
-        /* call `get` callback */
-        V7_TRY2(b_apply(v7, get_v, V7_UNDEFINED, get_args_v, 0, res),
-                clean_proxy);
-      } else {
-        /*
-         * there's no `get` callback: then, get property from the target object
-         * (not from the proxy object)
-         */
-        V7_TRY2(v7_get_throwing(v7, target_v, name_copy, name_len, res),
-                clean_proxy);
-      }
-
-    clean_proxy:
-
-      free(name_copy);
-
-      v7_disown(v7, &get_args_v);
-      v7_disown(v7, &get_v);
-      v7_disown(v7, &name_v);
-      v7_disown(v7, &handler_v);
-      v7_disown(v7, &target_v);
-      goto clean;
-    }
-  }
-#endif
-
-  /* regular (non-proxy) property access */
-  V7_TRY(
-      v7_property_value(v7, obj, v7_get_property(v7, v, name, name_len), res));
-
-clean:
-  v7_disown(v7, &v);
-  return rcode;
-}
-
-v7_val_t v7_get(struct v7 *v7, val_t obj, const char *name, size_t name_len) {
-  enum v7_err rcode = V7_OK;
-  uint8_t saved_is_thrown = 0;
-  val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
-  v7_val_t ret = V7_UNDEFINED;
-
-  rcode = v7_get_throwing(v7, obj, name, name_len, &ret);
-  if (rcode != V7_OK) {
-    rcode = V7_OK;
-    if (saved_is_thrown) {
-      rcode = v7_throw(v7, saved_thrown);
-    } else {
-      v7_clear_thrown_value(v7);
-    }
-    ret = V7_UNDEFINED;
-  }
-
-  return ret;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err v7_get_throwing_v(struct v7 *v7, v7_val_t obj,
-                                         v7_val_t name, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  size_t name_len;
-  STATIC char buf[8];
-  const char *s = buf;
-  uint8_t fr = 0;
-
-  /* subscripting strings */
-  if (v7_is_string(obj)) {
-    char ch;
-    double dch = 0;
-
-    rcode = v7_char_code_at(v7, obj, name, &dch);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    if (!isnan(dch)) {
-      ch = dch;
-      *res = v7_mk_string(v7, &ch, 1, 1);
-      goto clean;
-    }
-  }
-
-  if (v7_is_string(name)) {
-    s = v7_get_string(v7, &name, &name_len);
-  } else {
-    char *stmp;
-    V7_TRY(v7_stringify_throwing(v7, name, buf, sizeof(buf),
-                                 V7_STRINGIFY_DEFAULT, &stmp));
-    s = stmp;
-    if (s != buf) {
-      fr = 1;
-    }
-    name_len = strlen(s);
-  }
-  V7_TRY(v7_get_throwing(v7, obj, s, name_len, res));
-
-clean:
-  if (fr) {
-    free((void *) s);
-  }
-  return rcode;
-}
-
-V7_PRIVATE void v7_destroy_property(struct v7_property **p) {
-  *p = NULL;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err v7_invoke_setter(struct v7 *v7, struct v7_property *prop,
-                                        val_t obj, val_t val) {
-  enum v7_err rcode = V7_OK;
-  val_t setter = prop->value, args;
-  v7_own(v7, &val);
-  args = v7_mk_dense_array(v7);
-  v7_own(v7, &args);
-  if (prop->attributes & V7_PROPERTY_GETTER) {
-    setter = v7_array_get(v7, prop->value, 1);
-  }
-  v7_array_set(v7, args, 0, val);
-  v7_disown(v7, &args);
-  v7_disown(v7, &val);
-  {
-    val_t val = V7_UNDEFINED;
-    V7_TRY(b_apply(v7, setter, obj, args, 0, &val));
-  }
-
-clean:
-  return rcode;
-}
-
-static v7_prop_attr_t apply_attrs_desc(v7_prop_attr_desc_t attrs_desc,
-                                       v7_prop_attr_t old_attrs) {
-  v7_prop_attr_t ret = old_attrs;
-  if (old_attrs & V7_PROPERTY_NON_CONFIGURABLE) {
-    /*
-     * The property is non-configurable: we can only change it from being
-     * writable to non-writable
-     */
-
-    if ((attrs_desc >> _V7_DESC_SHIFT) & V7_PROPERTY_NON_WRITABLE &&
-        (attrs_desc & V7_PROPERTY_NON_WRITABLE)) {
-      ret |= V7_PROPERTY_NON_WRITABLE;
-    }
-
-  } else {
-    /* The property is configurable: we can change any attributes */
-    ret = (old_attrs & ~(attrs_desc >> _V7_DESC_SHIFT)) |
-          (attrs_desc & _V7_DESC_MASK);
-  }
-
-  return ret;
-}
-
-int v7_def(struct v7 *v7, val_t obj, const char *name, size_t len,
-           v7_prop_attr_desc_t attrs_desc, v7_val_t val) {
-  enum v7_err rcode = V7_OK;
-  uint8_t saved_is_thrown = 0;
-  val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
-  int ret = -1;
-
-  {
-    struct v7_property *tmp = NULL;
-    rcode = def_property(v7, obj, name, len, attrs_desc, val, 0 /*not assign*/,
-                         &tmp);
-    ret = (tmp == NULL) ? -1 : 0;
-  }
-
-  if (rcode != V7_OK) {
-    rcode = V7_OK;
-    if (saved_is_thrown) {
-      rcode = v7_throw(v7, saved_thrown);
-    } else {
-      v7_clear_thrown_value(v7);
-    }
-    ret = -1;
-  }
-
-  return ret;
-}
-
-int v7_set(struct v7 *v7, val_t obj, const char *name, size_t len,
-           v7_val_t val) {
-  enum v7_err rcode = V7_OK;
-  uint8_t saved_is_thrown = 0;
-  val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
-  int ret = -1;
-
-  {
-    struct v7_property *tmp = NULL;
-    rcode = set_property(v7, obj, name, len, val, &tmp);
-    ret = (tmp == NULL) ? -1 : 0;
-  }
-
-  if (rcode != V7_OK) {
-    rcode = V7_OK;
-    if (saved_is_thrown) {
-      rcode = v7_throw(v7, saved_thrown);
-    } else {
-      v7_clear_thrown_value(v7);
-    }
-    ret = -1;
-  }
-
-  return ret;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err set_property_v(struct v7 *v7, val_t obj, val_t name,
-                                      val_t val, struct v7_property **res) {
-  return def_property_v(v7, obj, name, 0, val, 1 /*as_assign*/, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err set_property(struct v7 *v7, val_t obj, const char *name,
-                                    size_t len, v7_val_t val,
-                                    struct v7_property **res) {
-  return def_property(v7, obj, name, len, 0, val, 1 /*as_assign*/, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err def_property_v(struct v7 *v7, val_t obj, val_t name,
-                                      v7_prop_attr_desc_t attrs_desc, val_t val,
-                                      uint8_t as_assign,
-                                      struct v7_property **res) {
-  enum v7_err rcode = V7_OK;
-  struct v7_property *prop = NULL;
-  size_t len;
-  const char *n = v7_get_string(v7, &name, &len);
-
-  v7_own(v7, &name);
-  v7_own(v7, &val);
-
-  if (!v7_is_object(obj)) {
-    prop = NULL;
-    goto clean;
-  }
-
-#if V7_ENABLE__Proxy
-  if ((get_object_struct(obj)->attributes & V7_OBJ_PROXY) &&
-      !is_special_proxy_name(n, len)) {
-    /* we need to access the target object through a proxy */
-
-    val_t target_v = V7_UNDEFINED;
-    val_t handler_v = V7_UNDEFINED;
-    val_t set_v = V7_UNDEFINED;
-    val_t set_args_v = V7_UNDEFINED;
-
-    v7_own(v7, &target_v);
-    v7_own(v7, &handler_v);
-    v7_own(v7, &set_v);
-    v7_own(v7, &set_args_v);
-
-    V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, &target_v),
-            clean_proxy);
-    V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, &handler_v),
-            clean_proxy);
-    /*
-     * We'll consult "set" property in case of the plain assignment only;
-     * Object.defineProperty() has its own trap `defineProperty` which is not
-     * yet implemented in v7
-     */
-    if (as_assign) {
-      V7_TRY2(v7_get_throwing(v7, handler_v, "set", ~0, &set_v), clean_proxy);
-    }
-
-    if (v7_is_callable(v7, set_v)) {
-      /* The `set` callback is actually callable, so, use it */
-
-      /* prepare arguments for the callback */
-      set_args_v = v7_mk_dense_array(v7);
-      /*
-       * TODO(dfrank): don't copy string in case we already have val_t
-       * (we need some generic function which will take both const char * and
-       * val_t for that)
-       */
-      v7_array_set(v7, set_args_v, 0, target_v);
-      v7_array_set(v7, set_args_v, 1, name);
-      v7_array_set(v7, set_args_v, 2, val);
-
-      /* call `set` callback */
-      V7_TRY2(b_apply(v7, set_v, V7_UNDEFINED, set_args_v, 0, &val),
-              clean_proxy);
-
-      /* in strict mode, we should throw if trap returned falsy value */
-      if (is_strict_mode(v7) && !v7_is_truthy(v7, val)) {
-        V7_THROW2(
-            v7_throwf(v7, TYPE_ERROR, "Trap returned falsy for property '%s'",
-                      v7_get_string(v7, &name, NULL)),
-            clean_proxy);
-      }
-
-    } else {
-      /*
-       * there's no `set` callback: then, set property on the target object
-       * (not on the proxy object)
-       */
-      V7_TRY2(
-          def_property_v(v7, target_v, name, attrs_desc, val, as_assign, res),
-          clean_proxy);
-    }
-
-  clean_proxy:
-    v7_disown(v7, &set_args_v);
-    v7_disown(v7, &set_v);
-    v7_disown(v7, &handler_v);
-    v7_disown(v7, &target_v);
-    goto clean;
-  }
-#endif
-
-  /* regular (non-proxy) property access */
-  prop = v7_get_own_property(v7, obj, n, len);
-  if (prop == NULL) {
-    /*
-     * The own property with given `name` doesn't exist yet: try to create it,
-     * set requested `name` and `attributes`, and append to the object's
-     * properties
-     */
-
-    /* make sure the object is extensible */
-    if (get_object_struct(obj)->attributes & V7_OBJ_NOT_EXTENSIBLE) {
-      /*
-       * We should throw if we use `Object.defineProperty`, or if we're in
-       * strict mode.
-       */
-      if (is_strict_mode(v7) || !as_assign) {
-        V7_THROW(v7_throwf(v7, TYPE_ERROR, "Object is not extensible"));
-      }
-      prop = NULL;
-      goto clean;
-    }
-
-    if ((prop = v7_mk_property(v7)) == NULL) {
-      prop = NULL; /* LCOV_EXCL_LINE */
-      goto clean;
-    }
-    prop->name = name;
-    prop->value = val;
-    prop->attributes = apply_attrs_desc(attrs_desc, V7_DEFAULT_PROPERTY_ATTRS);
-
-    prop->next = get_object_struct(obj)->properties;
-    get_object_struct(obj)->properties = prop;
-    goto clean;
-  } else {
-    /* Property already exists */
-
-    if (prop->attributes & V7_PROPERTY_NON_WRITABLE) {
-      /* The property is read-only */
-
-      if (as_assign) {
-        /* Plain assignment: in strict mode throw, otherwise ignore */
-        if (is_strict_mode(v7)) {
-          V7_THROW(
-              v7_throwf(v7, TYPE_ERROR, "Cannot assign to read-only property"));
-        } else {
-          prop = NULL;
-          goto clean;
-        }
-      } else if (prop->attributes & V7_PROPERTY_NON_CONFIGURABLE) {
-        /*
-         * Use `Object.defineProperty` semantic, and the property is
-         * non-configurable: if no value is provided, or if new value is equal
-         * to the existing one, then just fall through to change attributes;
-         * otherwise, throw.
-         */
-
-        if (!(attrs_desc & V7_DESC_PRESERVE_VALUE)) {
-          uint8_t equal = 0;
-          if (v7_is_string(val) && v7_is_string(prop->value)) {
-            equal = (s_cmp(v7, val, prop->value) == 0);
-          } else {
-            equal = (val == prop->value);
-          }
-
-          if (!equal) {
-            /* Values are not equal: should throw */
-            V7_THROW(v7_throwf(v7, TYPE_ERROR,
-                               "Cannot redefine read-only property"));
-          } else {
-            /*
-             * Values are equal. Will fall through so that attributes might
-             * change.
-             */
-          }
-        } else {
-          /*
-           * No value is provided. Will fall through so that attributes might
-           * change.
-           */
-        }
-      } else {
-        /*
-         * Use `Object.defineProperty` semantic, and the property is
-         * configurable: will fall through and assign new value, effectively
-         * ignoring non-writable flag. This is the same as making a property
-         * writable, then assigning a new value, and making a property
-         * non-writable again.
-         */
-      }
-    } else if (prop->attributes & V7_PROPERTY_SETTER) {
-      /* Invoke setter */
-      V7_TRY(v7_invoke_setter(v7, prop, obj, val));
-      prop = NULL;
-      goto clean;
-    }
-
-    /* Set value and apply attrs delta */
-    if (!(attrs_desc & V7_DESC_PRESERVE_VALUE)) {
-      prop->value = val;
-    }
-    prop->attributes = apply_attrs_desc(attrs_desc, prop->attributes);
-  }
-
-clean:
-
-  if (res != NULL) {
-    *res = prop;
-  }
-
-  v7_disown(v7, &val);
-  v7_disown(v7, &name);
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err def_property(struct v7 *v7, val_t obj, const char *name,
-                                    size_t len, v7_prop_attr_desc_t attrs_desc,
-                                    v7_val_t val, uint8_t as_assign,
-                                    struct v7_property **res) {
-  enum v7_err rcode = V7_OK;
-  val_t name_val = V7_UNDEFINED;
-
-  v7_own(v7, &obj);
-  v7_own(v7, &val);
-  v7_own(v7, &name_val);
-
-  if (len == (size_t) ~0) {
-    len = strlen(name);
-  }
-
-  name_val = v7_mk_string(v7, name, len, 1);
-  V7_TRY(def_property_v(v7, obj, name_val, attrs_desc, val, as_assign, res));
-
-clean:
-  v7_disown(v7, &name_val);
-  v7_disown(v7, &val);
-  v7_disown(v7, &obj);
-
-  return rcode;
-}
-
-V7_PRIVATE int set_method(struct v7 *v7, v7_val_t obj, const char *name,
-                          v7_cfunction_t *func, int num_args) {
-  return v7_def(v7, obj, name, strlen(name), V7_DESC_ENUMERABLE(0),
-                mk_cfunction_obj(v7, func, num_args));
-}
-
-int v7_set_method(struct v7 *v7, v7_val_t obj, const char *name,
-                  v7_cfunction_t *func) {
-  return set_method(v7, obj, name, func, ~0);
-}
-
-V7_PRIVATE int set_cfunc_prop(struct v7 *v7, val_t o, const char *name,
-                              v7_cfunction_t *f) {
-  return v7_def(v7, o, name, strlen(name), V7_DESC_ENUMERABLE(0),
-                v7_mk_cfunction(f));
-}
-
-/*
- * See comments in `object_public.h`
- */
-int v7_del(struct v7 *v7, val_t obj, const char *name, size_t len) {
-  struct v7_property *prop, *prev;
-
-  if (!v7_is_object(obj)) {
-    return -1;
-  }
-  if (len == (size_t) ~0) {
-    len = strlen(name);
-  }
-  for (prev = NULL, prop = get_object_struct(obj)->properties; prop != NULL;
-       prev = prop, prop = prop->next) {
-    size_t n;
-    const char *s = v7_get_string(v7, &prop->name, &n);
-    if (n == len && strncmp(s, name, len) == 0) {
-      if (prev) {
-        prev->next = prop->next;
-      } else {
-        get_object_struct(obj)->properties = prop->next;
-      }
-      v7_destroy_property(&prop);
-      return 0;
-    }
-  }
-  return -1;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err v7_property_value(struct v7 *v7, val_t obj,
-                                         struct v7_property *p, val_t *res) {
-  enum v7_err rcode = V7_OK;
-  if (p == NULL) {
-    *res = V7_UNDEFINED;
-    goto clean;
-  }
-  if (p->attributes & V7_PROPERTY_GETTER) {
-    val_t getter = p->value;
-    if (p->attributes & V7_PROPERTY_SETTER) {
-      getter = v7_array_get(v7, p->value, 0);
-    }
-    {
-      V7_TRY(b_apply(v7, getter, obj, V7_UNDEFINED, 0, res));
-      goto clean;
-    }
-  }
-
-  *res = p->value;
-  goto clean;
-
-clean:
-  return rcode;
-}
-
-enum v7_err v7_init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
-                                  struct prop_iter_ctx *ctx) {
-  return init_prop_iter_ctx(v7, obj, 1 /*proxy-transparent*/, ctx);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
-                                          int proxy_transp,
-                                          struct prop_iter_ctx *ctx) {
-  enum v7_err rcode = V7_OK;
-
-  v7_own(v7, &obj);
-
-  memset(ctx, 0x00, sizeof(*ctx));
-
-  if (v7_is_object(obj)) {
-#if V7_ENABLE__Proxy
-    if (proxy_transp && get_object_struct(obj)->attributes & V7_OBJ_PROXY) {
-      v7_val_t ownKeys_v = V7_UNDEFINED;
-      v7_val_t args_v = V7_UNDEFINED;
-
-      v7_own(v7, &ownKeys_v);
-      v7_own(v7, &args_v);
-
-      ctx->proxy_ctx =
-          (struct prop_iter_proxy_ctx *) calloc(1, sizeof(*ctx->proxy_ctx));
-
-      ctx->proxy_ctx->target_obj = V7_UNDEFINED;
-      ctx->proxy_ctx->handler_obj = V7_UNDEFINED;
-      ctx->proxy_ctx->own_keys = V7_UNDEFINED;
-      ctx->proxy_ctx->get_own_prop_desc = V7_UNDEFINED;
-
-      v7_own(v7, &ctx->proxy_ctx->target_obj);
-      v7_own(v7, &ctx->proxy_ctx->handler_obj);
-      v7_own(v7, &ctx->proxy_ctx->own_keys);
-      v7_own(v7, &ctx->proxy_ctx->get_own_prop_desc);
-
-      V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0,
-                              &ctx->proxy_ctx->target_obj),
-              clean_proxy);
-      V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0,
-                              &ctx->proxy_ctx->handler_obj),
-              clean_proxy);
-
-      V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, "ownKeys", ~0,
-                              &ownKeys_v),
-              clean_proxy);
-
-      if (v7_is_callable(v7, ownKeys_v)) {
-        /* prepare arguments for the ownKeys callback */
-        args_v = v7_mk_dense_array(v7);
-        v7_array_set(v7, args_v, 0, ctx->proxy_ctx->target_obj);
-
-        /* call `ownKeys` callback, and save the result in context */
-        V7_TRY2(b_apply(v7, ownKeys_v, V7_UNDEFINED, args_v, 0,
-                        &ctx->proxy_ctx->own_keys),
-                clean_proxy);
-
-        ctx->proxy_ctx->has_own_keys = 1;
-        ctx->proxy_ctx->own_key_idx = 0;
-
-      } else {
-        /*
-         * No ownKeys callback, so we'll iterate real properties of the target
-         * object
-         */
-
-        /*
-         * TODO(dfrank): add support for the target object which is a proxy as
-         * well
-         */
-        ctx->cur_prop =
-            get_object_struct(ctx->proxy_ctx->target_obj)->properties;
-      }
-
-      V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, "_gpdc", ~0,
-                              &ctx->proxy_ctx->get_own_prop_desc),
-              clean_proxy);
-      if (v7_is_foreign(ctx->proxy_ctx->get_own_prop_desc)) {
-        /*
-         * C callback for getting property descriptor is provided: will use it
-         */
-        ctx->proxy_ctx->has_get_own_prop_desc = 1;
-        ctx->proxy_ctx->has_get_own_prop_desc_C = 1;
-      } else {
-        /*
-         * No C callback for getting property descriptor is provided, let's
-         * check if there is a JS one..
-         */
-        V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj,
-                                "getOwnPropertyDescriptor", ~0,
-                                &ctx->proxy_ctx->get_own_prop_desc),
-                clean_proxy);
-
-        if (v7_is_callable(v7, ctx->proxy_ctx->get_own_prop_desc)) {
-          /* Yes there is, we'll use it */
-          ctx->proxy_ctx->has_get_own_prop_desc = 1;
-        }
-      }
-
-    clean_proxy:
-      v7_disown(v7, &args_v);
-      v7_disown(v7, &ownKeys_v);
-
-      if (rcode != V7_OK) {
-        /* something went wrong, so, disown values in the context and free it */
-        v7_disown(v7, &ctx->proxy_ctx->get_own_prop_desc);
-        v7_disown(v7, &ctx->proxy_ctx->own_keys);
-        v7_disown(v7, &ctx->proxy_ctx->handler_obj);
-        v7_disown(v7, &ctx->proxy_ctx->target_obj);
-
-        free(ctx->proxy_ctx);
-        ctx->proxy_ctx = NULL;
-
-        goto clean;
-      }
-    } else {
-#else
-    (void) proxy_transp;
-#endif
-
-      /* Object is not a proxy: we'll iterate real properties */
-      ctx->cur_prop = get_object_struct(obj)->properties;
-
-#if V7_ENABLE__Proxy
-    }
-#endif
-  }
-
-#if V7_ENABLE__Proxy
-clean:
-#endif
-  v7_disown(v7, &obj);
-  if (rcode == V7_OK) {
-    ctx->init = 1;
-  }
-  return rcode;
-}
-
-void v7_destruct_prop_iter_ctx(struct v7 *v7, struct prop_iter_ctx *ctx) {
-  if (ctx->init) {
-#if V7_ENABLE__Proxy
-    if (ctx->proxy_ctx != NULL) {
-      v7_disown(v7, &ctx->proxy_ctx->target_obj);
-      v7_disown(v7, &ctx->proxy_ctx->handler_obj);
-      v7_disown(v7, &ctx->proxy_ctx->own_keys);
-      v7_disown(v7, &ctx->proxy_ctx->get_own_prop_desc);
-    }
-    free(ctx->proxy_ctx);
-    ctx->proxy_ctx = NULL;
-#else
-    (void) v7;
-#endif
-    ctx->init = 0;
-  }
-}
-
-int v7_next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, v7_val_t *name,
-                 v7_val_t *value, v7_prop_attr_t *attrs) {
-  int ok = 0;
-  if (next_prop(v7, ctx, name, value, attrs, &ok) != V7_OK) {
-    fprintf(stderr, "next_prop failed\n");
-    ok = 0;
-  }
-  return ok;
-}
-
-#if V7_ENABLE__Proxy
-WARN_UNUSED_RESULT
-static enum v7_err get_custom_prop_desc(struct v7 *v7, v7_val_t name,
-                                        struct prop_iter_ctx *ctx,
-                                        struct v7_property *res_prop, int *ok) {
-  enum v7_err rcode = V7_OK;
-
-  v7_val_t args_v = V7_UNDEFINED;
-  v7_val_t desc_v = V7_UNDEFINED;
-  v7_val_t tmpflag_v = V7_UNDEFINED;
-
-  v7_own(v7, &name);
-  v7_own(v7, &args_v);
-  v7_own(v7, &desc_v);
-  v7_own(v7, &tmpflag_v);
-
-  *ok = 0;
-
-  if (ctx->proxy_ctx->has_get_own_prop_desc_C) {
-    /*
-     * There is a C callback which should fill the property descriptor
-     * structure, see `v7_get_own_prop_desc_cb_t`
-     */
-    v7_get_own_prop_desc_cb_t *cb = NULL;
-    memset(res_prop, 0, sizeof(*res_prop));
-    cb = (v7_get_own_prop_desc_cb_t *) v7_get_ptr(
-        v7, ctx->proxy_ctx->get_own_prop_desc);
-
-    res_prop->attributes = 0;
-    res_prop->value = V7_UNDEFINED;
-
-    *ok = !!cb(v7, ctx->proxy_ctx->target_obj, name, &res_prop->attributes,
-               &res_prop->value);
-  } else {
-    /* prepare arguments for the getOwnPropertyDescriptor callback */
-    args_v = v7_mk_dense_array(v7);
-    v7_array_set(v7, args_v, 0, ctx->proxy_ctx->target_obj);
-    v7_array_set(v7, args_v, 1, name);
-
-    /* call getOwnPropertyDescriptor callback */
-    V7_TRY(b_apply(v7, ctx->proxy_ctx->get_own_prop_desc, V7_UNDEFINED, args_v,
-                   0, &desc_v));
-
-    if (v7_is_object(desc_v)) {
-      res_prop->attributes = 0;
-
-      V7_TRY(v7_get_throwing(v7, desc_v, "writable", ~0, &tmpflag_v));
-      if (!v7_is_truthy(v7, tmpflag_v)) {
-        res_prop->attributes |= V7_PROPERTY_NON_WRITABLE;
-      }
-
-      V7_TRY(v7_get_throwing(v7, desc_v, "configurable", ~0, &tmpflag_v));
-      if (!v7_is_truthy(v7, tmpflag_v)) {
-        res_prop->attributes |= V7_PROPERTY_NON_CONFIGURABLE;
-      }
-
-      V7_TRY(v7_get_throwing(v7, desc_v, "enumerable", ~0, &tmpflag_v));
-      if (!v7_is_truthy(v7, tmpflag_v)) {
-        res_prop->attributes |= V7_PROPERTY_NON_ENUMERABLE;
-      }
-
-      V7_TRY(v7_get_throwing(v7, desc_v, "value", ~0, &res_prop->value));
-
-      *ok = 1;
-    }
-  }
-
-  /* We always set the name in the property descriptor to the actual name */
-  res_prop->name = name;
-
-clean:
-  v7_disown(v7, &tmpflag_v);
-  v7_disown(v7, &desc_v);
-  v7_disown(v7, &args_v);
-  v7_disown(v7, &name);
-
-  return rcode;
-}
-#endif
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err next_prop(struct v7 *v7, struct prop_iter_ctx *ctx,
-                                 v7_val_t *name, v7_val_t *value,
-                                 v7_prop_attr_t *attrs, int *ok) {
-  enum v7_err rcode = V7_OK;
-  struct v7_property p;
-
-  (void) v7;
-
-  memset(&p, 0, sizeof(p));
-  p.name = V7_UNDEFINED;
-  p.value = V7_UNDEFINED;
-
-  v7_own(v7, &p.name);
-  v7_own(v7, &p.value);
-
-  assert(ctx->init);
-
-  *ok = 0;
-
-#if V7_ENABLE__Proxy
-  if (ctx->proxy_ctx == NULL || !ctx->proxy_ctx->has_own_keys) {
-    /*
-     * No `ownKeys` callback, so we'll iterate real properties of the object
-     * (either the given object or, if it's a proxy, the proxy's target object)
-     */
-
-    if (ctx->cur_prop != NULL) {
-      if (ctx->proxy_ctx == NULL || !ctx->proxy_ctx->has_get_own_prop_desc) {
-        /*
-         * There is no `getOwnPropertyDescriptor` callback, so, use the current
-         * real property
-         */
-        memcpy(&p, ctx->cur_prop, sizeof(p));
-        *ok = 1;
-      } else {
-        /*
-         * There is a `getOwnPropertyDescriptor` callback, so call it for the
-         * name of the current real property
-         */
-        V7_TRY(get_custom_prop_desc(v7, ctx->cur_prop->name, ctx, &p, ok));
-      }
-
-      ctx->cur_prop = ctx->cur_prop->next;
-    }
-  } else {
-    /* We have custom own keys */
-    v7_val_t cur_key = V7_UNDEFINED;
-    size_t len = v7_array_length(v7, ctx->proxy_ctx->own_keys);
-
-    v7_own(v7, &cur_key);
-
-    /*
-     * Iterate through the custom own keys until we can get the proper property
-     * descriptor for the given key
-     */
-    while (!*ok && (size_t) ctx->proxy_ctx->own_key_idx < len) {
-      cur_key = v7_array_get(v7, ctx->proxy_ctx->own_keys,
-                             ctx->proxy_ctx->own_key_idx);
-      ctx->proxy_ctx->own_key_idx++;
-
-      if (ctx->proxy_ctx->has_get_own_prop_desc) {
-        /*
-         * There is a `getOwnPropertyDescriptor` callback, so, call it for the
-         * current custom key and get all descriptor data from the object
-         * returned. The `ok` variable will be updated appropriately (it will
-         * be 0 if the callback did not return a proper descriptor)
-         */
-        V7_TRY2(get_custom_prop_desc(v7, cur_key, ctx, &p, ok), clean_custom);
-      } else {
-        /*
-         * There is no `getOwnPropertyDescriptor` callback, so, try to get
-         * real property with the name equal to the current key
-         */
-        size_t len = 0;
-        const char *name = v7_get_string(v7, &cur_key, &len);
-
-        struct v7_property *real_prop =
-            v7_get_own_property(v7, ctx->proxy_ctx->target_obj, name, len);
-        if (real_prop != NULL) {
-          /* Property exists, so use data from its descriptor */
-          memcpy(&p, real_prop, sizeof(p));
-          *ok = 1;
-        }
-      }
-    }
-  clean_custom:
-    v7_disown(v7, &cur_key);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-#else
-  /*
-   * Proxy is disabled: just get the next property
-   */
-  if (ctx->cur_prop != NULL) {
-    memcpy(&p, ctx->cur_prop, sizeof(p));
-    *ok = 1;
-    ctx->cur_prop = ctx->cur_prop->next;
-  }
-#endif
-
-  /* If we have a valid property descriptor, use data from it */
-  if (*ok) {
-    if (name != NULL) *name = p.name;
-    if (value != NULL) *value = p.value;
-    if (attrs != NULL) *attrs = p.attributes;
-  }
-
-#if V7_ENABLE__Proxy
-clean:
-#endif
-  v7_disown(v7, &p.value);
-  v7_disown(v7, &p.name);
-  return rcode;
-}
-
-/* }}} Object properties */
-
-/* Object prototypes {{{ */
-
-V7_PRIVATE int obj_prototype_set(struct v7 *v7, struct v7_object *obj,
-                                 struct v7_object *proto) {
-  int ret = -1;
-  (void) v7;
-
-  if (obj->attributes & V7_OBJ_FUNCTION) {
-    ret = -1;
-  } else {
-    ((struct v7_generic_object *) obj)->prototype = proto;
-    ret = 0;
-  }
-
-  return ret;
-}
-
-V7_PRIVATE struct v7_object *obj_prototype(struct v7 *v7,
-                                           struct v7_object *obj) {
-  if (obj->attributes & V7_OBJ_FUNCTION) {
-    return get_object_struct(v7->vals.function_prototype);
-  } else {
-    return ((struct v7_generic_object *) obj)->prototype;
-  }
-}
-
-V7_PRIVATE int is_prototype_of(struct v7 *v7, val_t o, val_t p) {
-  if (!v7_is_object(o) || !v7_is_object(p)) {
-    return 0;
-  }
-
-  /* walk the prototype chain */
-  for (; !v7_is_null(o); o = v7_get_proto(v7, o)) {
-    if (v7_get_proto(v7, o) == p) {
-      return 1;
-    }
-  }
-  return 0;
-}
-
-int v7_is_instanceof(struct v7 *v7, val_t o, const char *c) {
-  return v7_is_instanceof_v(v7, o, v7_get(v7, v7->vals.global_object, c, ~0));
-}
-
-int v7_is_instanceof_v(struct v7 *v7, val_t o, val_t c) {
-  return is_prototype_of(v7, o, v7_get(v7, c, "prototype", 9));
-}
-
-v7_val_t v7_set_proto(struct v7 *v7, v7_val_t obj, v7_val_t proto) {
-  if (v7_is_generic_object(obj)) {
-    v7_val_t old_proto =
-        v7_object_to_value(obj_prototype(v7, get_object_struct(obj)));
-    obj_prototype_set(v7, get_object_struct(obj), get_object_struct(proto));
-    return old_proto;
-  } else {
-    return V7_UNDEFINED;
-  }
-}
-
-val_t v7_get_proto(struct v7 *v7, val_t obj) {
-  /*
-   * NOTE: we don't use v7_is_callable() here, because it involves walking
-   * through the object's properties, which may be expensive. And it's done
-   * anyway for cfunction objects as it would for any other generic objects by
-   * the call to `obj_prototype()`.
-   *
-   * Since this function is called quite often (at least, GC walks the
-   * prototype chain), it's better to just handle cfunction objects as generic
-   * objects.
-   */
-  if (is_js_function(obj) || is_cfunction_lite(obj)) {
-    return v7->vals.function_prototype;
-  }
-  return v7_object_to_value(obj_prototype(v7, get_object_struct(obj)));
-}
-
-V7_PRIVATE struct v7_property *get_user_data_property(v7_val_t obj) {
-  struct v7_property *p;
-  struct v7_object *o;
-  if (!v7_is_object(obj)) return NULL;
-  o = get_object_struct(obj);
-
-  for (p = o->properties; p != NULL; p = p->next) {
-    if (p->attributes & _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR) {
-      return p;
-    }
-  }
-
-  return NULL;
-}
-
-/*
- * Returns the user data property structure associated with obj, or NULL if
- * `obj` is not an object.
- */
-static struct v7_property *get_or_create_user_data_property(struct v7 *v7,
-                                                            v7_val_t obj) {
-  struct v7_property *p = get_user_data_property(obj);
-  struct v7_object *o;
-
-  if (p != NULL) return p;
-
-  if (!v7_is_object(obj)) return NULL;
-  o = get_object_struct(obj);
-  v7_own(v7, &obj);
-  p = v7_mk_property(v7);
-  v7_disown(v7, &obj);
-
-  p->attributes |= _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR | _V7_PROPERTY_HIDDEN;
-
-  p->next = o->properties;
-  o->properties = p;
-
-  return p;
-}
-
-void v7_set_user_data(struct v7 *v7, v7_val_t obj, void *ud) {
-  struct v7_property *p = get_or_create_user_data_property(v7, obj);
-  if (p == NULL) return;
-  p->value = v7_mk_foreign(v7, ud);
-}
-
-void *v7_get_user_data(struct v7 *v7, v7_val_t obj) {
-  struct v7_property *p = get_user_data_property(obj);
-  (void) v7;
-  if (p == NULL) return NULL;
-  return v7_get_ptr(v7, p->value);
-}
-
-void v7_set_destructor_cb(struct v7 *v7, v7_val_t obj, v7_destructor_cb_t *d) {
-  struct v7_property *p = get_or_create_user_data_property(v7, obj);
-  struct v7_object *o;
-  union {
-    void *v;
-    v7_destructor_cb_t *f;
-  } fu;
-
-  if (p == NULL) return;
-
-  o = get_object_struct(obj);
-  if (d != NULL) {
-    o->attributes |= V7_OBJ_HAS_DESTRUCTOR;
-    fu.f = d;
-    p->name = v7_mk_foreign(v7, fu.v);
-  } else {
-    o->attributes &= ~V7_OBJ_HAS_DESTRUCTOR;
-    p->name = V7_UNDEFINED;
-  }
-}
-
-/* }}} Object prototypes */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/regexp.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/regexp.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/slre.h" */
-
-#if V7_ENABLE__RegExp
-enum v7_err v7_mk_regexp(struct v7 *v7, const char *re, size_t re_len,
-                         const char *flags, size_t flags_len, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  struct slre_prog *p = NULL;
-  struct v7_regexp *rp;
-
-  if (re_len == ~((size_t) 0)) re_len = strlen(re);
-
-  if (slre_compile(re, re_len, flags, flags_len, &p, 1) != SLRE_OK ||
-      p == NULL) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Invalid regex");
-    goto clean;
-  } else {
-    *res = mk_object(v7, v7->vals.regexp_prototype);
-    rp = (struct v7_regexp *) malloc(sizeof(*rp));
-    rp->regexp_string = v7_mk_string(v7, re, re_len, 1);
-    v7_own(v7, &rp->regexp_string);
-    rp->compiled_regexp = p;
-    rp->lastIndex = 0;
-
-    v7_def(v7, *res, "", 0, _V7_DESC_HIDDEN(1),
-           pointer_to_value(rp) | V7_TAG_REGEXP);
-  }
-
-clean:
-  return rcode;
-}
-
-V7_PRIVATE struct v7_regexp *v7_get_regexp_struct(struct v7 *v7, val_t v) {
-  struct v7_property *p;
-  int is = v7_is_regexp(v7, v);
-  (void) is;
-  assert(is == 1);
-  /* TODO(mkm): make regexp use user data API */
-  p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
-  assert(p != NULL);
-  return (struct v7_regexp *) get_ptr(p->value);
-}
-
-int v7_is_regexp(struct v7 *v7, val_t v) {
-  struct v7_property *p;
-  if (!v7_is_generic_object(v)) return 0;
-  /* TODO(mkm): make regexp use user data API */
-  p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
-  if (p == NULL) return 0;
-  return (p->value & V7_TAG_MASK) == V7_TAG_REGEXP;
-}
-
-V7_PRIVATE size_t
-get_regexp_flags_str(struct v7 *v7, struct v7_regexp *rp, char *buf) {
-  int re_flags = slre_get_flags(rp->compiled_regexp);
-  size_t n = 0;
-
-  (void) v7;
-  if (re_flags & SLRE_FLAG_G) buf[n++] = 'g';
-  if (re_flags & SLRE_FLAG_I) buf[n++] = 'i';
-  if (re_flags & SLRE_FLAG_M) buf[n++] = 'm';
-
-  assert(n <= _V7_REGEXP_MAX_FLAGS_LEN);
-
-  return n;
-}
-
-#else /* V7_ENABLE__RegExp */
-
-/*
- * Dummy implementation when RegExp support is disabled: just return 0
- */
-int v7_is_regexp(struct v7 *v7, val_t v) {
-  (void) v7;
-  (void) v;
-  return 0;
-}
-
-#endif /* V7_ENABLE__RegExp */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/exceptions.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/str_util.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/eval.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-
-enum v7_err v7_throw(struct v7 *v7, v7_val_t val) {
-  v7->vals.thrown_error = val;
-  v7->is_thrown = 1;
-  return V7_EXEC_EXCEPTION;
-}
-
-void v7_clear_thrown_value(struct v7 *v7) {
-  v7->vals.thrown_error = V7_UNDEFINED;
-  v7->is_thrown = 0;
-}
-
-enum v7_err v7_throwf(struct v7 *v7, const char *typ, const char *err_fmt,
-                      ...) {
-  /* TODO(dfrank) : get rid of v7->error_msg, allocate mem right here */
-  enum v7_err rcode = V7_OK;
-  va_list ap;
-  val_t e = V7_UNDEFINED;
-  va_start(ap, err_fmt);
-  c_vsnprintf(v7->error_msg, sizeof(v7->error_msg), err_fmt, ap);
-  va_end(ap);
-
-  v7_own(v7, &e);
-  rcode = create_exception(v7, typ, v7->error_msg, &e);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = v7_throw(v7, e);
-
-clean:
-  v7_disown(v7, &e);
-  return rcode;
-}
-
-enum v7_err v7_rethrow(struct v7 *v7) {
-  assert(v7->is_thrown);
-#ifdef NDEBUG
-  (void) v7;
-#endif
-  return V7_EXEC_EXCEPTION;
-}
-
-v7_val_t v7_get_thrown_value(struct v7 *v7, uint8_t *is_thrown) {
-  if (is_thrown != NULL) {
-    *is_thrown = v7->is_thrown;
-  }
-  return v7->vals.thrown_error;
-}
-
-/*
- * Create an instance of the exception with type `typ` (see `TYPE_ERROR`,
- * `SYNTAX_ERROR`, etc) and message `msg`.
- */
-V7_PRIVATE enum v7_err create_exception(struct v7 *v7, const char *typ,
-                                        const char *msg, val_t *res) {
-  enum v7_err rcode = V7_OK;
-  uint8_t saved_creating_exception = v7->creating_exception;
-  val_t ctor_args = V7_UNDEFINED, ctor_func = V7_UNDEFINED;
-#if 0
-  assert(v7_is_undefined(v7->vals.thrown_error));
-#endif
-
-  *res = V7_UNDEFINED;
-
-  v7_own(v7, &ctor_args);
-  v7_own(v7, &ctor_func);
-
-  if (v7->creating_exception) {
-#ifndef NO_LIBC
-    fprintf(stderr, "Exception creation throws an exception %s: %s\n", typ,
-            msg);
-#endif
-  } else {
-    v7->creating_exception = 1;
-
-    /* Prepare arguments for the `Error` constructor */
-    ctor_args = v7_mk_dense_array(v7);
-    v7_array_set(v7, ctor_args, 0, v7_mk_string(v7, msg, strlen(msg), 1));
-
-    /* Get constructor for the given error `typ` */
-    ctor_func = v7_get(v7, v7->vals.global_object, typ, ~0);
-    if (v7_is_undefined(ctor_func)) {
-      fprintf(stderr, "cannot find exception %s\n", typ);
-    }
-
-    /* Create an error object, with prototype from constructor function */
-    *res = mk_object(v7, v7_get(v7, ctor_func, "prototype", 9));
-
-    /*
-     * Finally, call the error constructor, passing an error object as `this`
-     */
-    V7_TRY(b_apply(v7, ctor_func, *res, ctor_args, 0, NULL));
-  }
-
-clean:
-  v7->creating_exception = saved_creating_exception;
-
-  v7_disown(v7, &ctor_func);
-  v7_disown(v7, &ctor_args);
-
-  return rcode;
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/conversion.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/cs_strtod.h" */
-/* Amalgamated: #include "common/str_util.h" */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/eval.h" */
-/* Amalgamated: #include "v7/src/gc.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-
-static void save_val(struct v7 *v7, const char *str, size_t str_len,
-                     val_t *dst_v, char *dst, size_t dst_size, int wanted_len,
-                     size_t *res_wanted_len) {
-  if (dst_v != NULL) {
-    *dst_v = v7_mk_string(v7, str, str_len, 1);
-  }
-
-  if (dst != NULL && dst_size > 0) {
-    size_t size = str_len + 1 /*null-term*/;
-    if (size > dst_size) {
-      size = dst_size;
-    }
-    memcpy(dst, str, size);
-
-    /* make sure we have null-term */
-    dst[dst_size - 1] = '\0';
-  }
-
-  if (res_wanted_len != NULL) {
-    *res_wanted_len = (wanted_len >= 0) ? (size_t) wanted_len : str_len;
-  }
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err primitive_to_str(struct v7 *v7, val_t v, val_t *res,
-                                        char *buf, size_t buf_size,
-                                        size_t *res_len) {
-  enum v7_err rcode = V7_OK;
-  char tmp_buf[25];
-  double num;
-  size_t wanted_len;
-
-  assert(!v7_is_object(v));
-
-  memset(tmp_buf, 0x00, sizeof(tmp_buf));
-
-  v7_own(v7, &v);
-
-  switch (val_type(v7, v)) {
-    case V7_TYPE_STRING: {
-      /* if `res` provided, set it to source value */
-      if (res != NULL) {
-        *res = v;
-      }
-
-      /* if buf provided, copy string data there */
-      if (buf != NULL && buf_size > 0) {
-        size_t size;
-        const char *str = v7_get_string(v7, &v, &size);
-        size += 1 /*null-term*/;
-
-        if (size > buf_size) {
-          size = buf_size;
-        }
-
-        memcpy(buf, str, size);
-
-        /* make sure we have a null-term */
-        buf[buf_size - 1] = '\0';
-      }
-
-      if (res_len != NULL) {
-        v7_get_string(v7, &v, res_len);
-      }
-
-      goto clean;
-    }
-    case V7_TYPE_NULL:
-      strncpy(tmp_buf, "null", sizeof(tmp_buf) - 1);
-      save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
-      goto clean;
-    case V7_TYPE_UNDEFINED:
-      strncpy(tmp_buf, "undefined", sizeof(tmp_buf) - 1);
-      save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
-      goto clean;
-    case V7_TYPE_BOOLEAN:
-      if (v7_get_bool(v7, v)) {
-        strncpy(tmp_buf, "true", sizeof(tmp_buf) - 1);
-        save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
-        goto clean;
-      } else {
-        strncpy(tmp_buf, "false", sizeof(tmp_buf) - 1);
-        save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
-        goto clean;
-      }
-    case V7_TYPE_NUMBER:
-      if (v == V7_TAG_NAN) {
-        strncpy(tmp_buf, "NaN", sizeof(tmp_buf) - 1);
-        save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
-        goto clean;
-      }
-      num = v7_get_double(v7, v);
-      if (isinf(num)) {
-        if (num < 0.0) {
-          strncpy(tmp_buf, "-Infinity", sizeof(tmp_buf) - 1);
-        } else {
-          strncpy(tmp_buf, "Infinity", sizeof(tmp_buf) - 1);
-        }
-        save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
-        goto clean;
-      }
-      {
-        const char *fmt = num > 1e10 ? "%.21g" : "%.10g";
-        wanted_len = snprintf(tmp_buf, sizeof(tmp_buf), fmt, num);
-        save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
-                 res_len);
-        goto clean;
-      }
-    case V7_TYPE_CFUNCTION:
-#ifdef V7_UNIT_TEST
-      wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "cfunc_xxxxxx");
-      save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
-               res_len);
-      goto clean;
-#else
-      wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "cfunc_%p", get_ptr(v));
-      save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
-               res_len);
-      goto clean;
-#endif
-    case V7_TYPE_FOREIGN:
-      wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "[foreign_%p]",
-                              v7_get_ptr(v7, v));
-      save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
-               res_len);
-      goto clean;
-    default:
-      abort();
-  }
-
-clean:
-
-  v7_disown(v7, &v);
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err primitive_to_number(struct v7 *v7, val_t v, val_t *res) {
-  enum v7_err rcode = V7_OK;
-
-  assert(!v7_is_object(v));
-
-  *res = v;
-
-  if (v7_is_number(*res)) {
-    goto clean;
-  }
-
-  if (v7_is_undefined(*res)) {
-    *res = V7_TAG_NAN;
-    goto clean;
-  }
-
-  if (v7_is_null(*res)) {
-    *res = v7_mk_number(v7, 0.0);
-    goto clean;
-  }
-
-  if (v7_is_boolean(*res)) {
-    *res = v7_mk_number(v7, !!v7_get_bool(v7, v));
-    goto clean;
-  }
-
-  if (is_cfunction_lite(*res)) {
-    *res = v7_mk_number(v7, 0.0);
-    goto clean;
-  }
-
-  if (v7_is_string(*res)) {
-    double d;
-    size_t n;
-    char *e, *s = (char *) v7_get_string(v7, res, &n);
-    if (n != 0) {
-      d = cs_strtod(s, &e);
-      if (e - n != s) {
-        d = NAN;
-      }
-    } else {
-      /* empty string: convert to 0 */
-      d = 0.0;
-    }
-    *res = v7_mk_number(v7, d);
-    goto clean;
-  }
-
-  assert(0);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-enum v7_err to_primitive(struct v7 *v7, val_t v, enum to_primitive_hint hint,
-                         val_t *res) {
-  enum v7_err rcode = V7_OK;
-  enum v7_err (*p_func)(struct v7 *v7, val_t v, val_t *res);
-
-  v7_own(v7, &v);
-
-  *res = v;
-
-  /*
-   * If given value is an object, try to convert it to string by calling first
-   * preferred function (`toString()` or `valueOf()`, depending on the `hint`
-   * argument)
-   */
-  if (v7_is_object(*res)) {
-    /* Handle special case for Date object */
-    if (hint == V7_TO_PRIMITIVE_HINT_AUTO) {
-      hint = (v7_get_proto(v7, *res) == v7->vals.date_prototype)
-                 ? V7_TO_PRIMITIVE_HINT_STRING
-                 : V7_TO_PRIMITIVE_HINT_NUMBER;
-    }
-
-    p_func =
-        (hint == V7_TO_PRIMITIVE_HINT_NUMBER) ? obj_value_of : obj_to_string;
-    rcode = p_func(v7, *res, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    /*
-     * If returned value is still an object, get original argument value
-     */
-    if (v7_is_object(*res)) {
-      *res = v;
-    }
-  }
-
-  /*
-   * If the value is still an object, try to call second function (`valueOf()`
-   * or `toString()`)
-   */
-  if (v7_is_object(*res)) {
-    p_func =
-        (hint == V7_TO_PRIMITIVE_HINT_NUMBER) ? obj_to_string : obj_value_of;
-    rcode = p_func(v7, *res, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-  /*
-   * If the value is still an object, then throw.
-   */
-  if (v7_is_object(*res)) {
-    rcode =
-        v7_throwf(v7, TYPE_ERROR, "Cannot convert object to primitive value");
-    goto clean;
-  }
-
-clean:
-  v7_disown(v7, &v);
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err to_string(struct v7 *v7, val_t v, val_t *res, char *buf,
-                                 size_t buf_size, size_t *res_len) {
-  enum v7_err rcode = V7_OK;
-
-  v7_own(v7, &v);
-
-  /*
-   * Convert value to primitive if needed, calling `toString()` first
-   */
-  V7_TRY(to_primitive(v7, v, V7_TO_PRIMITIVE_HINT_STRING, &v));
-
-  /*
-   * Now, we're guaranteed to have a primitive here. Convert it to string.
-   */
-  V7_TRY(primitive_to_str(v7, v, res, buf, buf_size, res_len));
-
-clean:
-  v7_disown(v7, &v);
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err to_number_v(struct v7 *v7, val_t v, val_t *res) {
-  enum v7_err rcode = V7_OK;
-
-  *res = v;
-
-  /*
-   * Convert value to primitive if needed, calling `valueOf()` first
-   */
-  rcode = to_primitive(v7, *res, V7_TO_PRIMITIVE_HINT_NUMBER, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  /*
-   * Now, we're guaranteed to have a primitive here. Convert it to number.
-   */
-  rcode = primitive_to_number(v7, *res, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err to_long(struct v7 *v7, val_t v, long default_value,
-                               long *res) {
-  enum v7_err rcode = V7_OK;
-  double d;
-
-  /* if value is `undefined`, just return `default_value` */
-  if (v7_is_undefined(v)) {
-    *res = default_value;
-    goto clean;
-  }
-
-  /* Try to convert value to number */
-  rcode = to_number_v(v7, v, &v);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  /*
-   * Conversion to number succeeded, so, convert it to long
-   */
-
-  d = v7_get_double(v7, v);
-  /* We want to return LONG_MAX if d is positive Inf, thus d < 0 check */
-  if (isnan(d) || (isinf(d) && d < 0)) {
-    *res = 0;
-    goto clean;
-  } else if (d > LONG_MAX) {
-    *res = LONG_MAX;
-    goto clean;
-  }
-  *res = (long) d;
-  goto clean;
-
-clean:
-  return rcode;
-}
-
-V7_PRIVATE enum v7_err obj_value_of(struct v7 *v7, val_t v, val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t func_valueOf = V7_UNDEFINED;
-
-  v7_own(v7, &func_valueOf);
-  v7_own(v7, &v);
-
-  /*
-   * TODO(dfrank): use `assert(v7_is_object(v))` instead, like `obj_to_string()`
-   * does, and fix all callers to ensure it's an object before calling.
-   *
-   * Or, conversely, make `obj_to_string()` to accept objects.
-   */
-  if (!v7_is_object(v)) {
-    *res = v;
-    goto clean;
-  }
-
-  V7_TRY(v7_get_throwing(v7, v, "valueOf", 7, &func_valueOf));
-
-  if (v7_is_callable(v7, func_valueOf)) {
-    V7_TRY(b_apply(v7, func_valueOf, v, V7_UNDEFINED, 0, res));
-  }
-
-clean:
-  if (rcode != V7_OK) {
-    *res = v;
-  }
-
-  v7_disown(v7, &v);
-  v7_disown(v7, &func_valueOf);
-
-  return rcode;
-}
-
-/*
- * Caller should ensure that `v` is an object
- */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err obj_to_string(struct v7 *v7, val_t v, val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t to_string_func = V7_UNDEFINED;
-
-  /* Caller should ensure that `v` is an object */
-  assert(v7_is_object(v));
-
-  v7_own(v7, &to_string_func);
-  v7_own(v7, &v);
-
-  /*
-   * If `toString` is callable, then call it; otherwise, just return source
-   * value
-   */
-  V7_TRY(v7_get_throwing(v7, v, "toString", 8, &to_string_func));
-  if (v7_is_callable(v7, to_string_func)) {
-    V7_TRY(b_apply(v7, to_string_func, v, V7_UNDEFINED, 0, res));
-  } else {
-    *res = v;
-  }
-
-clean:
-  v7_disown(v7, &v);
-  v7_disown(v7, &to_string_func);
-
-  return rcode;
-}
-
-static const char *hex_digits = "0123456789abcdef";
-static char *append_hex(char *buf, char *limit, uint8_t c) {
-  if (buf < limit) *buf++ = 'u';
-  if (buf < limit) *buf++ = '0';
-  if (buf < limit) *buf++ = '0';
-  if (buf < limit) *buf++ = hex_digits[(int) ((c >> 4) % 0xf)];
-  if (buf < limit) *buf++ = hex_digits[(int) (c & 0xf)];
-  return buf;
-}
-
-/*
- * Appends quoted s to buf. Any double quote contained in s will be escaped.
- * Returns the number of characters that would have been added,
- * like snprintf.
- * If size is zero it doesn't output anything but keeps counting.
- */
-static int snquote(char *buf, size_t size, const char *s, size_t len) {
-  char *limit = buf + size - 1;
-  const char *end;
-  /*
-   * String single character escape sequence:
-   * http://www.ecma-international.org/ecma-262/6.0/index.html#table-34
-   *
-   * 0x8 -> \b
-   * 0x9 -> \t
-   * 0xa -> \n
-   * 0xb -> \v
-   * 0xc -> \f
-   * 0xd -> \r
-   */
-  const char *specials = "btnvfr";
-  size_t i = 0;
-
-  i++;
-  if (buf < limit) *buf++ = '"';
-
-  for (end = s + len; s < end; s++) {
-    if (*s == '"' || *s == '\\') {
-      i++;
-      if (buf < limit) *buf++ = '\\';
-    } else if (*s >= '\b' && *s <= '\r') {
-      i += 2;
-      if (buf < limit) *buf++ = '\\';
-      if (buf < limit) *buf++ = specials[*s - '\b'];
-      continue;
-    } else if ((unsigned char) *s < '\b' || (*s > '\r' && *s < ' ')) {
-      i += 6 /* \uXXXX */;
-      if (buf < limit) *buf++ = '\\';
-      buf = append_hex(buf, limit, (uint8_t) *s);
-      continue;
-    }
-    i++;
-    if (buf < limit) *buf++ = *s;
-  }
-
-  i++;
-  if (buf < limit) *buf++ = '"';
-
-  if (size != 0) {
-    *buf = '\0';
-  }
-  return i;
-}
-
-/*
- * Returns whether the value of given type should be skipped when generating
- * JSON output
- */
-static int should_skip_for_json(enum v7_type type) {
-  int ret;
-  switch (type) {
-    /* All permitted values */
-    case V7_TYPE_NULL:
-    case V7_TYPE_BOOLEAN:
-    case V7_TYPE_BOOLEAN_OBJECT:
-    case V7_TYPE_NUMBER:
-    case V7_TYPE_NUMBER_OBJECT:
-    case V7_TYPE_STRING:
-    case V7_TYPE_STRING_OBJECT:
-    case V7_TYPE_GENERIC_OBJECT:
-    case V7_TYPE_ARRAY_OBJECT:
-    case V7_TYPE_DATE_OBJECT:
-    case V7_TYPE_REGEXP_OBJECT:
-    case V7_TYPE_ERROR_OBJECT:
-      ret = 0;
-      break;
-    default:
-      ret = 1;
-      break;
-  }
-  return ret;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err to_json_or_debug(struct v7 *v7, val_t v, char *buf,
-                                        size_t size, size_t *res_len,
-                                        uint8_t is_debug) {
-  val_t el;
-  char *vp;
-  enum v7_err rcode = V7_OK;
-  size_t len = 0;
-  struct gc_tmp_frame tf = new_tmp_frame(v7);
-
-  tmp_stack_push(&tf, &v);
-  tmp_stack_push(&tf, &el);
-  /*
-   * TODO(dfrank) : also push all `v7_val_t`s that are declared below
-   */
-
-  if (size > 0) *buf = '\0';
-
-  if (!is_debug && should_skip_for_json(val_type(v7, v))) {
-    goto clean;
-  }
-
-  for (vp = v7->json_visited_stack.buf;
-       vp < v7->json_visited_stack.buf + v7->json_visited_stack.len;
-       vp += sizeof(val_t)) {
-    if (*(val_t *) vp == v) {
-      strncpy(buf, "[Circular]", size);
-      len = 10;
-      goto clean;
-    }
-  }
-
-  switch (val_type(v7, v)) {
-    case V7_TYPE_NULL:
-    case V7_TYPE_BOOLEAN:
-    case V7_TYPE_NUMBER:
-    case V7_TYPE_UNDEFINED:
-    case V7_TYPE_CFUNCTION:
-    case V7_TYPE_FOREIGN:
-      /* For those types, regular `primitive_to_str()` works */
-      V7_TRY(primitive_to_str(v7, v, NULL, buf, size, &len));
-      goto clean;
-
-    case V7_TYPE_STRING: {
-      /*
-       * For strings we can't just use `primitive_to_str()`, because we need
-       * quoted value
-       */
-      size_t n;
-      const char *str = v7_get_string(v7, &v, &n);
-      len = snquote(buf, size, str, n);
-      goto clean;
-    }
-
-    case V7_TYPE_DATE_OBJECT: {
-      v7_val_t func = V7_UNDEFINED, val = V7_UNDEFINED;
-      V7_TRY(v7_get_throwing(v7, v, "toString", 8, &func));
-#if V7_ENABLE__Date__toJSON
-      if (!is_debug) {
-        V7_TRY(v7_get_throwing(v7, v, "toJSON", 6, &func));
-      }
-#endif
-      V7_TRY(b_apply(v7, func, v, V7_UNDEFINED, 0, &val));
-      V7_TRY(to_json_or_debug(v7, val, buf, size, &len, is_debug));
-      goto clean;
-    }
-    case V7_TYPE_GENERIC_OBJECT:
-    case V7_TYPE_BOOLEAN_OBJECT:
-    case V7_TYPE_STRING_OBJECT:
-    case V7_TYPE_NUMBER_OBJECT:
-    case V7_TYPE_REGEXP_OBJECT:
-    case V7_TYPE_ERROR_OBJECT: {
-      /* TODO(imax): make it return the desired size of the buffer */
-      char *b = buf;
-      v7_val_t name = V7_UNDEFINED, val = V7_UNDEFINED;
-      v7_prop_attr_t attrs = 0;
-      const char *pname;
-      size_t nlen;
-      int ok = 0;
-      struct prop_iter_ctx ctx;
-      memset(&ctx, 0, sizeof(ctx));
-
-      mbuf_append(&v7->json_visited_stack, (char *) &v, sizeof(v));
-      b += c_snprintf(b, BUF_LEFT(size, b - buf), "{");
-      V7_TRY2(init_prop_iter_ctx(v7, v, 1 /*proxy-transparent*/, &ctx),
-              clean_iter);
-      while (1) {
-        size_t n;
-        const char *s;
-        V7_TRY2(next_prop(v7, &ctx, &name, &val, &attrs, &ok), clean_iter);
-        if (!ok) {
-          break;
-        } else if (attrs & (_V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE)) {
-          continue;
-        }
-        pname = v7_get_string(v7, &name, &nlen);
-        V7_TRY(v7_get_throwing(v7, v, pname, nlen, &val));
-        if (!is_debug && should_skip_for_json(val_type(v7, val))) {
-          continue;
-        }
-        if (b - buf != 1) { /* Not the first property to be printed */
-          b += c_snprintf(b, BUF_LEFT(size, b - buf), ",");
-        }
-        s = v7_get_string(v7, &name, &n);
-        b += c_snprintf(b, BUF_LEFT(size, b - buf), "\"%.*s\":", (int) n, s);
-        {
-          size_t tmp = 0;
-          V7_TRY2(to_json_or_debug(v7, val, b, BUF_LEFT(size, b - buf), &tmp,
-                                   is_debug),
-                  clean_iter);
-          b += tmp;
-        }
-      }
-      b += c_snprintf(b, BUF_LEFT(size, b - buf), "}");
-      v7->json_visited_stack.len -= sizeof(v);
-
-    clean_iter:
-      v7_destruct_prop_iter_ctx(v7, &ctx);
-
-      len = b - buf;
-      goto clean;
-    }
-    case V7_TYPE_ARRAY_OBJECT: {
-      int has;
-      char *b = buf;
-      size_t i, alen = v7_array_length(v7, v);
-      mbuf_append(&v7->json_visited_stack, (char *) &v, sizeof(v));
-      b += c_snprintf(b, BUF_LEFT(size, b - buf), "[");
-      for (i = 0; i < alen; i++) {
-        el = v7_array_get2(v7, v, i, &has);
-        if (has) {
-          size_t tmp = 0;
-          if (!is_debug && should_skip_for_json(val_type(v7, el))) {
-            b += c_snprintf(b, BUF_LEFT(size, b - buf), "null");
-          } else {
-            V7_TRY(to_json_or_debug(v7, el, b, BUF_LEFT(size, b - buf), &tmp,
-                                    is_debug));
-          }
-          b += tmp;
-        }
-        if (i != alen - 1) {
-          b += c_snprintf(b, BUF_LEFT(size, b - buf), ",");
-        }
-      }
-      b += c_snprintf(b, BUF_LEFT(size, b - buf), "]");
-      v7->json_visited_stack.len -= sizeof(v);
-      len = b - buf;
-      goto clean;
-    }
-    case V7_TYPE_CFUNCTION_OBJECT:
-      V7_TRY(obj_value_of(v7, v, &v));
-      len = c_snprintf(buf, size, "Function cfunc_%p", get_ptr(v));
-      goto clean;
-    case V7_TYPE_FUNCTION_OBJECT:
-      V7_TRY(to_string(v7, v, NULL, buf, size, &len));
-      goto clean;
-
-    case V7_TYPE_MAX_OBJECT_TYPE:
-    case V7_NUM_TYPES:
-      abort();
-  }
-
-  abort();
-
-  len = 0; /* for compilers that don't know about abort() */
-  goto clean;
-
-clean:
-  if (rcode != V7_OK) {
-    len = 0;
-  }
-  if (res_len != NULL) {
-    *res_len = len;
-  }
-  tmp_frame_cleanup(&tf);
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE val_t to_boolean_v(struct v7 *v7, val_t v) {
-  size_t len;
-  int is_truthy;
-
-  is_truthy = ((v7_is_boolean(v) && v7_get_bool(v7, v)) ||
-               (v7_is_number(v) && v7_get_double(v7, v) != 0.0) ||
-               (v7_is_string(v) && v7_get_string(v7, &v, &len) && len > 0) ||
-               (v7_is_object(v))) &&
-              v != V7_TAG_NAN;
-
-  return v7_mk_boolean(v7, is_truthy);
-}
-
-/*
- * v7_stringify allocates a new buffer if value representation doesn't fit into
- * buf. Caller is responsible for freeing that buffer.
- */
-char *v7_stringify(struct v7 *v7, val_t v, char *buf, size_t size,
-                   enum v7_stringify_mode mode) {
-  enum v7_err rcode = V7_OK;
-  uint8_t saved_is_thrown = 0;
-  val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
-  char *ret = NULL;
-
-  rcode = v7_stringify_throwing(v7, v, buf, size, mode, &ret);
-  if (rcode != V7_OK) {
-    rcode = V7_OK;
-    if (saved_is_thrown) {
-      rcode = v7_throw(v7, saved_thrown);
-    } else {
-      v7_clear_thrown_value(v7);
-    }
-
-    buf[0] = '\0';
-    ret = buf;
-  }
-
-  return ret;
-}
-
-enum v7_err v7_stringify_throwing(struct v7 *v7, val_t v, char *buf,
-                                  size_t size, enum v7_stringify_mode mode,
-                                  char **res) {
-  enum v7_err rcode = V7_OK;
-  char *p = buf;
-  size_t len;
-
-  switch (mode) {
-    case V7_STRINGIFY_DEFAULT:
-      V7_TRY(to_string(v7, v, NULL, buf, size, &len));
-      break;
-
-    case V7_STRINGIFY_JSON:
-      V7_TRY(to_json_or_debug(v7, v, buf, size, &len, 0));
-      break;
-
-    case V7_STRINGIFY_DEBUG:
-      V7_TRY(to_json_or_debug(v7, v, buf, size, &len, 1));
-      break;
-  }
-
-  /* fit null terminating byte */
-  if (len >= size) {
-    /* Buffer is not large enough. Allocate a bigger one */
-    p = (char *) malloc(len + 1);
-    V7_TRY(v7_stringify_throwing(v7, v, p, len + 1, mode, res));
-    assert(*res == p);
-    goto clean;
-  } else {
-    *res = p;
-    goto clean;
-  }
-
-clean:
-  /*
-   * If we're going to throw, and we allocated a buffer, then free it.
-   * But if we don't throw, then the caller will free it.
-   */
-  if (rcode != V7_OK && p != buf) {
-    free(p);
-  }
-  return rcode;
-}
-
-int v7_is_truthy(struct v7 *v7, val_t v) {
-  return v7_get_bool(v7, to_boolean_v(v7, v));
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/shdata.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/shdata.h" */
-
-#if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
-V7_PRIVATE struct shdata *shdata_create(const void *payload, size_t size) {
-  struct shdata *ret =
-      (struct shdata *) calloc(1, sizeof(struct shdata) + size);
-  shdata_retain(ret);
-  if (payload != NULL) {
-    memcpy((char *) shdata_get_payload(ret), (char *) payload, size);
-  }
-  return ret;
-}
-
-V7_PRIVATE struct shdata *shdata_create_from_string(const char *src) {
-  return shdata_create(src, strlen(src) + 1 /*null-term*/);
-}
-
-V7_PRIVATE void shdata_retain(struct shdata *p) {
-  p->refcnt++;
-  assert(p->refcnt > 0);
-}
-
-V7_PRIVATE void shdata_release(struct shdata *p) {
-  assert(p->refcnt > 0);
-  p->refcnt--;
-  if (p->refcnt == 0) {
-    free(p);
-  }
-}
-
-V7_PRIVATE void *shdata_get_payload(struct shdata *p) {
-  return (char *) p + sizeof(*p);
-}
-#endif
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/gc.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/bcode.h" */
-/* Amalgamated: #include "v7/src/varint.h" */
-/* Amalgamated: #include "v7/src/gc.h" */
-/* Amalgamated: #include "v7/src/freeze.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/heapusage.h" */
-
-#include <stdio.h>
-
-#ifdef V7_STACK_GUARD_MIN_SIZE
-void *v7_sp_limit = NULL;
-#endif
-
-void gc_mark_string(struct v7 *, val_t *);
-
-static struct gc_block *gc_new_block(struct gc_arena *a, size_t size);
-static void gc_free_block(struct gc_block *b);
-static void gc_mark_mbuf_pt(struct v7 *v7, const struct mbuf *mbuf);
-static void gc_mark_mbuf_val(struct v7 *v7, const struct mbuf *mbuf);
-static void gc_mark_vec_val(struct v7 *v7, const struct v7_vec *vec);
-
-V7_PRIVATE struct v7_generic_object *new_generic_object(struct v7 *v7) {
-  return (struct v7_generic_object *) gc_alloc_cell(v7,
-                                                    &v7->generic_object_arena);
-}
-
-V7_PRIVATE struct v7_property *new_property(struct v7 *v7) {
-  return (struct v7_property *) gc_alloc_cell(v7, &v7->property_arena);
-}
-
-V7_PRIVATE struct v7_js_function *new_function(struct v7 *v7) {
-  return (struct v7_js_function *) gc_alloc_cell(v7, &v7->function_arena);
-}
-
-V7_PRIVATE struct gc_tmp_frame new_tmp_frame(struct v7 *v7) {
-  struct gc_tmp_frame frame;
-  frame.v7 = v7;
-  frame.pos = v7->tmp_stack.len;
-  return frame;
-}
-
-V7_PRIVATE void tmp_frame_cleanup(struct gc_tmp_frame *tf) {
-  tf->v7->tmp_stack.len = tf->pos;
-}
-
-/*
- * TODO(mkm): perhaps it's safer to keep val_t in the temporary
- * roots stack, instead of keeping val_t*, in order to be better
- * able to debug the relocating GC.
- */
-V7_PRIVATE void tmp_stack_push(struct gc_tmp_frame *tf, val_t *vp) {
-  mbuf_append(&tf->v7->tmp_stack, (char *) &vp, sizeof(val_t *));
-}
-
-/* Initializes a new arena. */
-V7_PRIVATE void gc_arena_init(struct gc_arena *a, size_t cell_size,
-                              size_t initial_size, size_t size_increment,
-                              const char *name) {
-  assert(cell_size >= sizeof(uintptr_t));
-
-  memset(a, 0, sizeof(*a));
-  a->cell_size = cell_size;
-  a->name = name;
-  a->size_increment = size_increment;
-  a->blocks = gc_new_block(a, initial_size);
-}
-
-V7_PRIVATE void gc_arena_destroy(struct v7 *v7, struct gc_arena *a) {
-  struct gc_block *b;
-
-  if (a->blocks != NULL) {
-    gc_sweep(v7, a, 0);
-    for (b = a->blocks; b != NULL;) {
-      struct gc_block *tmp;
-      tmp = b;
-      b = b->next;
-      gc_free_block(tmp);
-    }
-  }
-}
-
-static void gc_free_block(struct gc_block *b) {
-  free(b->base);
-  free(b);
-}
-
-static struct gc_block *gc_new_block(struct gc_arena *a, size_t size) {
-  struct gc_cell *cur;
-  struct gc_block *b;
-
-  heapusage_dont_count(1);
-  b = (struct gc_block *) calloc(1, sizeof(*b));
-  heapusage_dont_count(0);
-  if (b == NULL) abort();
-
-  b->size = size;
-  heapusage_dont_count(1);
-  b->base = (struct gc_cell *) calloc(a->cell_size, b->size);
-  heapusage_dont_count(0);
-  if (b->base == NULL) abort();
-
-  for (cur = GC_CELL_OP(a, b->base, +, 0);
-       cur < GC_CELL_OP(a, b->base, +, b->size);
-       cur = GC_CELL_OP(a, cur, +, 1)) {
-    cur->head.link = a->free;
-    a->free = cur;
-  }
-
-  return b;
-}
-
-V7_PRIVATE void *gc_alloc_cell(struct v7 *v7, struct gc_arena *a) {
-#if V7_MALLOC_GC
-  struct gc_cell *r;
-  maybe_gc(v7);
-  heapusage_dont_count(1);
-  r = (struct gc_cell *) calloc(1, a->cell_size);
-  heapusage_dont_count(0);
-  mbuf_append(&v7->malloc_trace, &r, sizeof(r));
-  return r;
-#else
-  struct gc_cell *r;
-  if (a->free == NULL) {
-    if (!maybe_gc(v7)) {
-      /* GC is inhibited, so, schedule invocation for later */
-      v7->need_gc = 1;
-    }
-
-    if (a->free == NULL) {
-      struct gc_block *b = gc_new_block(a, a->size_increment);
-      b->next = a->blocks;
-      a->blocks = b;
-    }
-  }
-  r = a->free;
-
-  UNMARK(r);
-
-  a->free = r->head.link;
-
-#if V7_ENABLE__Memory__stats
-  a->allocations++;
-  a->alive++;
-#endif
-
-  /*
-   * TODO(mkm): minor opt possible since most of the fields
-   * are overwritten downstream, but not worth the yak shave time
-   * when fields are added to GC-able structures */
-  memset(r, 0, a->cell_size);
-  return (void *) r;
-#endif
-}
-
-#ifdef V7_MALLOC_GC
-/*
- * Scans trough the memory blocks registered in the malloc trace.
- * Free the unmarked ones and reset the mark on the rest.
- */
-void gc_sweep_malloc(struct v7 *v7) {
-  struct gc_cell **cur;
-  for (cur = (struct gc_cell **) v7->malloc_trace.buf;
-       cur < (struct gc_cell **) (v7->malloc_trace.buf + v7->malloc_trace.len);
-       cur++) {
-    if (*cur == NULL) continue;
-
-    if (MARKED(*cur)) {
-      UNMARK(*cur);
-    } else {
-      free(*cur);
-      /* TODO(mkm): compact malloc trace buffer */
-      *cur = NULL;
-    }
-  }
-}
-#endif
-
-/*
- * Scans the arena and add all unmarked cells to the free list.
- *
- * Empty blocks get deallocated. The head of the free list will contais cells
- * from the last (oldest) block. Cells will thus be allocated in block order.
- */
-void gc_sweep(struct v7 *v7, struct gc_arena *a, size_t start) {
-  struct gc_block *b;
-  struct gc_cell *cur;
-  struct gc_block **prevp = &a->blocks;
-#if V7_ENABLE__Memory__stats
-  a->alive = 0;
-#endif
-
-  /*
-   * Before we sweep, we should mark all free cells in a way that is
-   * distinguishable from marked used cells.
-   */
-  {
-    struct gc_cell *next;
-    for (cur = a->free; cur != NULL; cur = next) {
-      next = cur->head.link;
-      MARK_FREE(cur);
-    }
-  }
-
-  /*
-   * We'll rebuild the whole `free` list, so initially we just reset it
-   */
-  a->free = NULL;
-
-  for (b = a->blocks; b != NULL;) {
-    size_t freed_in_block = 0;
-    /*
-     * if it turns out that this block is 100% garbage
-     * we can release the whole block, but the addition
-     * of it's cells to the free list has to be undone.
-     */
-    struct gc_cell *prev_free = a->free;
-
-    for (cur = GC_CELL_OP(a, b->base, +, start);
-         cur < GC_CELL_OP(a, b->base, +, b->size);
-         cur = GC_CELL_OP(a, cur, +, 1)) {
-      if (MARKED(cur)) {
-        /* The cell is used and marked  */
-        UNMARK(cur);
-#if V7_ENABLE__Memory__stats
-        a->alive++;
-#endif
-      } else {
-        /*
-         * The cell is either:
-         * - free
-         * - garbage that's about to be freed
-         */
-
-        if (MARKED_FREE(cur)) {
-          /* The cell is free, so, just unmark it */
-          UNMARK_FREE(cur);
-        } else {
-          /*
-           * The cell is used and should be freed: call the destructor and
-           * reset the memory
-           */
-          if (a->destructor != NULL) {
-            a->destructor(v7, cur);
-          }
-          memset(cur, 0, a->cell_size);
-        }
-
-        /* Add this cell to the `free` list */
-        cur->head.link = a->free;
-        a->free = cur;
-        freed_in_block++;
-#if V7_ENABLE__Memory__stats
-        a->garbage++;
-#endif
-      }
-    }
-
-    /*
-     * don't free the initial block, which is at the tail
-     * because it has a special size aimed at reducing waste
-     * and simplifying initial startup. TODO(mkm): improve
-     * */
-    if (b->next != NULL && freed_in_block == b->size) {
-      *prevp = b->next;
-      gc_free_block(b);
-      b = *prevp;
-      a->free = prev_free;
-    } else {
-      prevp = &b->next;
-      b = b->next;
-    }
-  }
-}
-
-/*
- * dense arrays contain only one property pointing to an mbuf with array values.
- */
-V7_PRIVATE void gc_mark_dense_array(struct v7 *v7,
-                                    struct v7_generic_object *obj) {
-  val_t v;
-  struct mbuf *mbuf;
-  val_t *vp;
-
-#if 0
-  /* TODO(mkm): use this when dense array promotion is implemented */
-  v = obj->properties->value;
-#else
-  v = v7_get(v7, v7_object_to_value(&obj->base), "", 0);
-#endif
-
-  mbuf = (struct mbuf *) v7_get_ptr(v7, v);
-
-  /* function scope pointer is aliased to the object's prototype pointer */
-  gc_mark(v7, v7_object_to_value(obj_prototype(v7, &obj->base)));
-  MARK(obj);
-
-  if (mbuf == NULL) return;
-  for (vp = (val_t *) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; vp++) {
-    gc_mark(v7, *vp);
-    gc_mark_string(v7, vp);
-  }
-  UNMARK(obj);
-}
-
-V7_PRIVATE void gc_mark(struct v7 *v7, val_t v) {
-  struct v7_object *obj_base;
-  struct v7_property *prop;
-  struct v7_property *next;
-
-  if (!v7_is_object(v)) {
-    return;
-  }
-  obj_base = get_object_struct(v);
-
-  /*
-   * we ignore objects that are not managed by V7 heap, such as frozen
-   * objects, especially when on flash.
-   */
-  if (obj_base->attributes & V7_OBJ_OFF_HEAP) {
-    return;
-  }
-
-  /*
-   * we treat all object like things like objects but they might be functions,
-   * gc_gheck_val checks the appropriate arena per actual value type.
-   */
-  if (!gc_check_val(v7, v)) {
-    abort();
-  }
-
-  if (MARKED(obj_base)) return;
-
-#ifdef V7_FREEZE
-  if (v7->freeze_file != NULL) {
-    freeze_obj(v7, v7->freeze_file, v);
-  }
-#endif
-
-  if (obj_base->attributes & V7_OBJ_DENSE_ARRAY) {
-    struct v7_generic_object *obj = get_generic_object_struct(v);
-    gc_mark_dense_array(v7, obj);
-  }
-
-  /* mark object itself, and its properties */
-  for ((prop = obj_base->properties), MARK(obj_base); prop != NULL;
-       prop = next) {
-    if (prop->attributes & _V7_PROPERTY_OFF_HEAP) {
-      break;
-    }
-
-    if (!gc_check_ptr(&v7->property_arena, prop)) {
-      abort();
-    }
-
-#ifdef V7_FREEZE
-    if (v7->freeze_file != NULL) {
-      freeze_prop(v7, v7->freeze_file, prop);
-    }
-#endif
-
-    gc_mark_string(v7, &prop->value);
-    gc_mark_string(v7, &prop->name);
-    gc_mark(v7, prop->value);
-
-    next = prop->next;
-    MARK(prop);
-  }
-
-  /* mark object's prototype */
-  gc_mark(v7, v7_get_proto(v7, v));
-
-  if (is_js_function(v)) {
-    struct v7_js_function *func = get_js_function_struct(v);
-
-    /* mark function's scope */
-    gc_mark(v7, v7_object_to_value(&func->scope->base));
-
-    if (func->bcode != NULL) {
-      gc_mark_vec_val(v7, &func->bcode->lit);
-    }
-  }
-}
-
-#if V7_ENABLE__Memory__stats
-
-V7_PRIVATE size_t gc_arena_size(struct gc_arena *a) {
-  size_t size = 0;
-  struct gc_block *b;
-  for (b = a->blocks; b != NULL; b = b->next) {
-    size += b->size;
-  }
-  return size;
-}
-
-/*
- * TODO(dfrank): move to core
- */
-int v7_heap_stat(struct v7 *v7, enum v7_heap_stat_what what) {
-  switch (what) {
-    case V7_HEAP_STAT_HEAP_SIZE:
-      return gc_arena_size(&v7->generic_object_arena) *
-                 v7->generic_object_arena.cell_size +
-             gc_arena_size(&v7->function_arena) * v7->function_arena.cell_size +
-             gc_arena_size(&v7->property_arena) * v7->property_arena.cell_size;
-    case V7_HEAP_STAT_HEAP_USED:
-      return v7->generic_object_arena.alive *
-                 v7->generic_object_arena.cell_size +
-             v7->function_arena.alive * v7->function_arena.cell_size +
-             v7->property_arena.alive * v7->property_arena.cell_size;
-    case V7_HEAP_STAT_STRING_HEAP_RESERVED:
-      return v7->owned_strings.size;
-    case V7_HEAP_STAT_STRING_HEAP_USED:
-      return v7->owned_strings.len;
-    case V7_HEAP_STAT_OBJ_HEAP_MAX:
-      return gc_arena_size(&v7->generic_object_arena);
-    case V7_HEAP_STAT_OBJ_HEAP_FREE:
-      return gc_arena_size(&v7->generic_object_arena) -
-             v7->generic_object_arena.alive;
-    case V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE:
-      return v7->generic_object_arena.cell_size;
-    case V7_HEAP_STAT_FUNC_HEAP_MAX:
-      return gc_arena_size(&v7->function_arena);
-    case V7_HEAP_STAT_FUNC_HEAP_FREE:
-      return gc_arena_size(&v7->function_arena) - v7->function_arena.alive;
-    case V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE:
-      return v7->function_arena.cell_size;
-    case V7_HEAP_STAT_PROP_HEAP_MAX:
-      return gc_arena_size(&v7->property_arena);
-    case V7_HEAP_STAT_PROP_HEAP_FREE:
-      return gc_arena_size(&v7->property_arena) - v7->property_arena.alive;
-    case V7_HEAP_STAT_PROP_HEAP_CELL_SIZE:
-      return v7->property_arena.cell_size;
-    case V7_HEAP_STAT_FUNC_AST_SIZE:
-      return v7->function_arena_ast_size;
-    case V7_HEAP_STAT_BCODE_OPS_SIZE:
-      return v7->bcode_ops_size;
-    case V7_HEAP_STAT_BCODE_LIT_TOTAL_SIZE:
-      return v7->bcode_lit_total_size;
-    case V7_HEAP_STAT_BCODE_LIT_DESER_SIZE:
-      return v7->bcode_lit_deser_size;
-    case V7_HEAP_STAT_FUNC_OWNED:
-      return v7->owned_values.len / sizeof(val_t *);
-    case V7_HEAP_STAT_FUNC_OWNED_MAX:
-      return v7->owned_values.size / sizeof(val_t *);
-  }
-
-  return -1;
-}
-#endif
-
-V7_PRIVATE void gc_dump_arena_stats(const char *msg, struct gc_arena *a) {
-  (void) msg;
-  (void) a;
-#ifndef NO_LIBC
-#if V7_ENABLE__Memory__stats
-  if (a->verbose) {
-    fprintf(stderr, "%s: total allocations %lu, max %lu, alive %lu\n", msg,
-            (long unsigned int) a->allocations,
-            (long unsigned int) gc_arena_size(a), (long unsigned int) a->alive);
-  }
-#endif
-#endif
-}
-
-V7_PRIVATE uint64_t gc_string_val_to_offset(val_t v) {
-  return (((uint64_t)(uintptr_t) get_ptr(v)) & ~V7_TAG_MASK)
-#ifndef V7_DISABLE_STR_ALLOC_SEQ
-         & 0xFFFFFFFF
-#endif
-      ;
-}
-
-V7_PRIVATE val_t gc_string_val_from_offset(uint64_t s) {
-  return s | V7_TAG_STRING_O;
-}
-
-#ifndef V7_DISABLE_STR_ALLOC_SEQ
-
-static uint16_t next_asn(struct v7 *v7) {
-  if (v7->gc_next_asn == 0xFFFF) {
-    /* Wrap around explicitly. */
-    v7->gc_next_asn = 0;
-    return 0xFFFF;
-  }
-  return v7->gc_next_asn++;
-}
-
-uint16_t gc_next_allocation_seqn(struct v7 *v7, const char *str, size_t len) {
-  uint16_t asn = next_asn(v7);
-  (void) str;
-  (void) len;
-#ifdef V7_GC_VERBOSE
-  /*
-   * ESP SDK printf cannot cope with null strings
-   * as created by s_concat.
-   */
-  if (str == NULL) {
-    fprintf(stderr, "GC ASN %d: <nil>\n", asn);
-  } else {
-    fprintf(stderr, "GC ASN %d: \"%.*s\"\n", asn, (int) len, str);
-  }
-#endif
-#ifdef V7_GC_PANIC_ON_ASN
-  if (asn == (V7_GC_PANIC_ON_ASN)) {
-    abort();
-  }
-#endif
-  return asn;
-}
-
-int gc_is_valid_allocation_seqn(struct v7 *v7, uint16_t n) {
-  /*
-   * This functions attempts to handle integer wraparound in a naive way and
-   * will give false positives when more than 65536 strings are allocated
-   * between GC runs.
-   */
-  int r = (n >= v7->gc_min_asn && n < v7->gc_next_asn) ||
-          (v7->gc_min_asn > v7->gc_next_asn &&
-           (n >= v7->gc_min_asn || n < v7->gc_next_asn));
-  if (!r) {
-    fprintf(stderr, "GC ASN %d is not in [%d,%d)\n", n, v7->gc_min_asn,
-            v7->gc_next_asn);
-  }
-  return r;
-}
-
-void gc_check_valid_allocation_seqn(struct v7 *v7, uint16_t n) {
-  if (!gc_is_valid_allocation_seqn(v7, n)) {
-/*
- * TODO(dfrank) throw exception if V7_GC_ASN_PANIC is not defined.
- */
-#if 0 && !defined(V7_GC_ASN_PANIC)
-    throw_exception(v7, INTERNAL_ERROR, "Invalid ASN: %d", (int) n);
-#else
-    fprintf(stderr, "Invalid ASN: %d\n", (int) n);
-    abort();
-#endif
-  }
-}
-
-#endif /* V7_DISABLE_STR_ALLOC_SEQ */
-
-/* Mark a string value */
-void gc_mark_string(struct v7 *v7, val_t *v) {
-  val_t h, tmp = 0;
-  char *s;
-
-  /* clang-format off */
-
-  /*
-   * If a value points to an unmarked string we shall:
-   *  1. save the first 6 bytes of the string
-   *     since we need to be able to distinguish real values from
-   *     the saved first 6 bytes of the string, we need to tag the chunk
-   *     as V7_TAG_STRING_C
-   *  2. encode value's address (v) into the first 6 bytes of the string.
-   *  3. put the saved 8 bytes (tag + chunk) back into the value.
-   *  4. mark the string by putting '\1' in the NUL terminator of the previous
-   *     string chunk.
-   *
-   * If a value points to an already marked string we shall:
-   *     (0, <6 bytes of a pointer to a val_t>), hence we have to skip
-   *     the first byte. We tag the value pointer as a V7_TAG_FOREIGN
-   *     so that it won't be followed during recursive mark.
-   *
-   *  ... the rest is the same
-   *
-   *  Note: 64-bit pointers can be represented with 48-bits
-   */
-
-  /* clang-format on */
-
-  if ((*v & V7_TAG_MASK) != V7_TAG_STRING_O) {
-    return;
-  }
-
-#ifdef V7_FREEZE
-  if (v7->freeze_file != NULL) {
-    return;
-  }
-#endif
-
-#ifdef V7_GC_VERBOSE
-  {
-    uint16_t asn = (*v >> 32) & 0xFFFF;
-    size_t size;
-    fprintf(stderr, "GC marking ASN %d: '%s'\n", asn,
-            v7_get_string(v7, v, &size));
-  }
-#endif
-
-#ifndef V7_DISABLE_STR_ALLOC_SEQ
-  gc_check_valid_allocation_seqn(v7, (*v >> 32) & 0xFFFF);
-#endif
-
-  s = v7->owned_strings.buf + gc_string_val_to_offset(*v);
-  assert(s < v7->owned_strings.buf + v7->owned_strings.len);
-  if (s[-1] == '\0') {
-    memcpy(&tmp, s, sizeof(tmp) - 2);
-    tmp |= V7_TAG_STRING_C;
-  } else {
-    memcpy(&tmp, s, sizeof(tmp) - 2);
-    tmp |= V7_TAG_FOREIGN;
-  }
-
-  h = (val_t)(uintptr_t) v;
-  s[-1] = 1;
-  memcpy(s, &h, sizeof(h) - 2);
-  memcpy(v, &tmp, sizeof(tmp));
-}
-
-void gc_compact_strings(struct v7 *v7) {
-  char *p = v7->owned_strings.buf + 1;
-  uint64_t h, next, head = 1;
-  int len, llen;
-
-#ifndef V7_DISABLE_STR_ALLOC_SEQ
-  v7->gc_min_asn = v7->gc_next_asn;
-#endif
-  while (p < v7->owned_strings.buf + v7->owned_strings.len) {
-    if (p[-1] == '\1') {
-#ifndef V7_DISABLE_STR_ALLOC_SEQ
-      /* Not using gc_next_allocation_seqn() as we don't have full string. */
-      uint16_t asn = next_asn(v7);
-#endif
-      /* relocate and update ptrs */
-      h = 0;
-      memcpy(&h, p, sizeof(h) - 2);
-
-      /*
-       * relocate pointers until we find the tail.
-       * The tail is marked with V7_TAG_STRING_C,
-       * while val_t link pointers are tagged with V7_TAG_FOREIGN
-       */
-      for (; (h & V7_TAG_MASK) != V7_TAG_STRING_C; h = next) {
-        h &= ~V7_TAG_MASK;
-        memcpy(&next, (char *) (uintptr_t) h, sizeof(h));
-
-        *(val_t *) (uintptr_t) h = gc_string_val_from_offset(head)
-#ifndef V7_DISABLE_STR_ALLOC_SEQ
-                                   | ((val_t) asn << 32)
-#endif
-            ;
-      }
-      h &= ~V7_TAG_MASK;
-
-      /*
-       * the tail contains the first 6 bytes we stole from
-       * the actual string.
-       */
-      len = decode_varint((unsigned char *) &h, &llen);
-      len += llen + 1;
-
-      /*
-       * restore the saved 6 bytes
-       * TODO(mkm): think about endianness
-       */
-      memcpy(p, &h, sizeof(h) - 2);
-
-      /*
-       * and relocate the string data by packing it to the left.
-       */
-      memmove(v7->owned_strings.buf + head, p, len);
-      v7->owned_strings.buf[head - 1] = 0x0;
-#if defined(V7_GC_VERBOSE) && !defined(V7_DISABLE_STR_ALLOC_SEQ)
-      fprintf(stderr, "GC updated ASN %d: \"%.*s\"\n", asn, len - llen - 1,
-              v7->owned_strings.buf + head + llen);
-#endif
-      p += len;
-      head += len;
-    } else {
-      len = decode_varint((unsigned char *) p, &llen);
-      len += llen + 1;
-
-      p += len;
-    }
-  }
-
-#if defined(V7_GC_VERBOSE) && !defined(V7_DISABLE_STR_ALLOC_SEQ)
-  fprintf(stderr, "GC valid ASN range: [%d,%d)\n", v7->gc_min_asn,
-          v7->gc_next_asn);
-#endif
-
-  v7->owned_strings.len = head;
-}
-
-void gc_dump_owned_strings(struct v7 *v7) {
-  size_t i;
-  for (i = 0; i < v7->owned_strings.len; i++) {
-    if (isprint((unsigned char) v7->owned_strings.buf[i])) {
-      fputc(v7->owned_strings.buf[i], stderr);
-    } else {
-      fputc('.', stderr);
-    }
-  }
-  fputc('\n', stderr);
-}
-
-/*
- * builting on gcc, tried out by redefining it.
- * Using null pointer as base can trigger undefined behavior, hence
- * a portable workaround that involves a valid yet dummy pointer.
- * It's meant to be used as a contant expression.
- */
-#ifndef offsetof
-#define offsetof(st, m) (((ptrdiff_t)(&((st *) 32)->m)) - 32)
-#endif
-
-V7_PRIVATE void compute_need_gc(struct v7 *v7) {
-  struct mbuf *m = &v7->owned_strings;
-  if ((double) m->len / (double) m->size > 0.9) {
-    v7->need_gc = 1;
-  }
-  /* TODO(mkm): check free heap */
-}
-
-V7_PRIVATE int maybe_gc(struct v7 *v7) {
-  if (!v7->inhibit_gc) {
-    v7_gc(v7, 0);
-    return 1;
-  }
-  return 0;
-}
-#if defined(V7_GC_VERBOSE)
-static int gc_pass = 0;
-#endif
-
-/*
- * mark an array of `val_t` values (*not pointers* to them)
- */
-static void gc_mark_val_array(struct v7 *v7, val_t *vals, size_t len) {
-  val_t *vp;
-  for (vp = vals; vp < vals + len; vp++) {
-    gc_mark(v7, *vp);
-    gc_mark_string(v7, vp);
-  }
-}
-
-/*
- * mark an mbuf containing *pointers* to `val_t` values
- */
-static void gc_mark_mbuf_pt(struct v7 *v7, const struct mbuf *mbuf) {
-  val_t **vp;
-  for (vp = (val_t **) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; vp++) {
-    gc_mark(v7, **vp);
-    gc_mark_string(v7, *vp);
-  }
-}
-
-/*
- * mark an mbuf containing `val_t` values (*not pointers* to them)
- */
-static void gc_mark_mbuf_val(struct v7 *v7, const struct mbuf *mbuf) {
-  gc_mark_val_array(v7, (val_t *) mbuf->buf, mbuf->len / sizeof(val_t));
-}
-
-/*
- * mark a vector containing `val_t` values (*not pointers* to them)
- */
-static void gc_mark_vec_val(struct v7 *v7, const struct v7_vec *vec) {
-  gc_mark_val_array(v7, (val_t *) vec->p, vec->len / sizeof(val_t));
-}
-
-/*
- * mark an mbuf containing foreign pointers to `struct bcode`
- */
-static void gc_mark_mbuf_bcode_pt(struct v7 *v7, const struct mbuf *mbuf) {
-  struct bcode **vp;
-  for (vp = (struct bcode **) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len;
-       vp++) {
-    gc_mark_vec_val(v7, &(*vp)->lit);
-  }
-}
-
-static void gc_mark_call_stack_private(
-    struct v7 *v7, struct v7_call_frame_private *call_stack) {
-  gc_mark_val_array(v7, (val_t *) &call_stack->vals,
-                    sizeof(call_stack->vals) / sizeof(val_t));
-}
-
-static void gc_mark_call_stack_cfunc(struct v7 *v7,
-                                     struct v7_call_frame_cfunc *call_stack) {
-  gc_mark_val_array(v7, (val_t *) &call_stack->vals,
-                    sizeof(call_stack->vals) / sizeof(val_t));
-}
-
-static void gc_mark_call_stack_bcode(struct v7 *v7,
-                                     struct v7_call_frame_bcode *call_stack) {
-  gc_mark_val_array(v7, (val_t *) &call_stack->vals,
-                    sizeof(call_stack->vals) / sizeof(val_t));
-}
-
-/*
- * mark `struct v7_call_frame` and all its back-linked frames
- */
-static void gc_mark_call_stack(struct v7 *v7,
-                               struct v7_call_frame_base *call_stack) {
-  while (call_stack != NULL) {
-    if (call_stack->type_mask & V7_CALL_FRAME_MASK_BCODE) {
-      gc_mark_call_stack_bcode(v7, (struct v7_call_frame_bcode *) call_stack);
-    }
-
-    if (call_stack->type_mask & V7_CALL_FRAME_MASK_PRIVATE) {
-      gc_mark_call_stack_private(v7,
-                                 (struct v7_call_frame_private *) call_stack);
-    }
-
-    if (call_stack->type_mask & V7_CALL_FRAME_MASK_CFUNC) {
-      gc_mark_call_stack_cfunc(v7, (struct v7_call_frame_cfunc *) call_stack);
-    }
-
-    call_stack = call_stack->prev;
-  }
-}
-
-/* Perform garbage collection */
-void v7_gc(struct v7 *v7, int full) {
-#ifdef V7_DISABLE_GC
-  (void) v7;
-  (void) full;
-  return;
-#else
-
-#if defined(V7_GC_VERBOSE)
-  fprintf(stderr, "V7 GC pass %d\n", ++gc_pass);
-#endif
-
-  gc_dump_arena_stats("Before GC objects", &v7->generic_object_arena);
-  gc_dump_arena_stats("Before GC functions", &v7->function_arena);
-  gc_dump_arena_stats("Before GC properties", &v7->property_arena);
-
-  gc_mark_call_stack(v7, v7->call_stack);
-
-  gc_mark_val_array(v7, (val_t *) &v7->vals, sizeof(v7->vals) / sizeof(val_t));
-  /* mark all items on bcode stack */
-  gc_mark_mbuf_val(v7, &v7->stack);
-
-  /* mark literals and names of all the active bcodes */
-  gc_mark_mbuf_bcode_pt(v7, &v7->act_bcodes);
-
-  gc_mark_mbuf_pt(v7, &v7->tmp_stack);
-  gc_mark_mbuf_pt(v7, &v7->owned_values);
-
-  gc_compact_strings(v7);
-
-#ifdef V7_MALLOC_GC
-  gc_sweep_malloc(v7);
-#else
-  gc_sweep(v7, &v7->generic_object_arena, 0);
-  gc_sweep(v7, &v7->function_arena, 0);
-  gc_sweep(v7, &v7->property_arena, 0);
-#endif
-
-  gc_dump_arena_stats("After GC objects", &v7->generic_object_arena);
-  gc_dump_arena_stats("After GC functions", &v7->function_arena);
-  gc_dump_arena_stats("After GC properties", &v7->property_arena);
-
-  if (full) {
-    /*
-     * In case of full GC, we also resize strings buffer, but we still leave
-     * some extra space (at most, `_V7_STRING_BUF_RESERVE`) in order to avoid
-     * frequent reallocations
-     */
-    size_t trimmed_size = v7->owned_strings.len + _V7_STRING_BUF_RESERVE;
-    if (trimmed_size < v7->owned_strings.size) {
-      heapusage_dont_count(1);
-      mbuf_resize(&v7->owned_strings, trimmed_size);
-      heapusage_dont_count(0);
-    }
-  }
-#endif /* V7_DISABLE_GC */
-}
-
-V7_PRIVATE int gc_check_val(struct v7 *v7, val_t v) {
-  if (is_js_function(v)) {
-    return gc_check_ptr(&v7->function_arena, get_js_function_struct(v));
-  } else if (v7_is_object(v)) {
-    return gc_check_ptr(&v7->generic_object_arena, get_object_struct(v));
-  }
-  return 1;
-}
-
-V7_PRIVATE int gc_check_ptr(const struct gc_arena *a, const void *ptr) {
-#ifdef V7_MALLOC_GC
-  (void) a;
-  (void) ptr;
-  return 1;
-#else
-  const struct gc_cell *p = (const struct gc_cell *) ptr;
-  struct gc_block *b;
-  for (b = a->blocks; b != NULL; b = b->next) {
-    if (p >= b->base && p < GC_CELL_OP(a, b->base, +, b->size)) {
-      return 1;
-    }
-  }
-  return 0;
-#endif
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/freeze.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-/* Amalgamated: #include "v7/src/freeze.h" */
-/* Amalgamated: #include "v7/src/bcode.h" */
-/* Amalgamated: #include "v7/src/gc.h" */
-/* Amalgamated: #include "common/base64.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-
-#include <stdio.h>
-
-#ifdef V7_FREEZE
-
-V7_PRIVATE void freeze(struct v7 *v7, char *filename) {
-  size_t i;
-
-  v7->freeze_file = fopen(filename, "w");
-  assert(v7->freeze_file != NULL);
-
-#ifndef V7_FREEZE_NOT_READONLY
-  /*
-   * We have to remove `global` from the global object since
-   * when thawing global will actually be a new mutable object
-   * living on the heap.
-   */
-  v7_del(v7, v7->vals.global_object, "global", 6);
-#endif
-
-  for (i = 0; i < sizeof(v7->vals) / sizeof(val_t); i++) {
-    val_t v = ((val_t *) &v7->vals)[i];
-    fprintf(v7->freeze_file,
-            "{\"type\":\"global\", \"idx\":%zu, \"value\":\"%p\"}\n", i,
-            (void *) (v7_is_object(v) ? get_object_struct(v) : 0x0));
-  }
-
-  /*
-   * since v7->freeze_file is not NULL this will cause freeze_obj and
-   * freeze_prop to be called for each reachable object and property.
-   */
-  v7_gc(v7, 1);
-  assert(v7->stack.len == 0);
-
-  fclose(v7->freeze_file);
-  v7->freeze_file = NULL;
-}
-
-static char *freeze_vec(struct v7_vec *vec) {
-  char *res = (char *) malloc(512 + vec->len);
-  res[0] = '"';
-  cs_base64_encode((const unsigned char *) vec->p, vec->len, &res[1]);
-  strcat(res, "\"");
-  return res;
-}
-
-V7_PRIVATE void freeze_obj(struct v7 *v7, FILE *f, v7_val_t v) {
-  struct v7_object *obj_base = get_object_struct(v);
-  unsigned int attrs = V7_OBJ_OFF_HEAP;
-
-#ifndef V7_FREEZE_NOT_READONLY
-  attrs |= V7_OBJ_NOT_EXTENSIBLE;
-#endif
-
-  if (is_js_function(v)) {
-    struct v7_js_function *func = get_js_function_struct(v);
-    struct bcode *bcode = func->bcode;
-    char *jops = freeze_vec(&bcode->ops);
-    int i;
-
-    fprintf(f,
-            "{\"type\":\"func\", \"addr\":\"%p\", \"props\":\"%p\", "
-            "\"attrs\":%d, \"scope\":\"%p\", \"bcode\":\"%p\""
-#if defined(V7_ENABLE_ENTITY_IDS)
-            ", \"entity_id_base\":%d, \"entity_id_spec\":\"%d\" "
-#endif
-            "}\n",
-            (void *) obj_base,
-            (void *) ((uintptr_t) obj_base->properties & ~0x1),
-            obj_base->attributes | attrs, (void *) func->scope, (void *) bcode
-#if defined(V7_ENABLE_ENTITY_IDS)
-            ,
-            obj_base->entity_id_base, obj_base->entity_id_spec
-#endif
-            );
-    fprintf(f,
-            "{\"type\":\"bcode\", \"addr\":\"%p\", \"args_cnt\":%d, "
-            "\"names_cnt\":%d, "
-            "\"strict_mode\": %d, \"func_name_present\": %d, \"ops\":%s, "
-            "\"lit\": [",
-            (void *) bcode, bcode->args_cnt, bcode->names_cnt,
-            bcode->strict_mode, bcode->func_name_present, jops);
-
-    for (i = 0; (size_t) i < bcode->lit.len / sizeof(val_t); i++) {
-      val_t v = ((val_t *) bcode->lit.p)[i];
-      const char *str;
-
-      if (((v & V7_TAG_MASK) == V7_TAG_STRING_O ||
-           (v & V7_TAG_MASK) == V7_TAG_STRING_F) &&
-          (str = v7_get_cstring(v7, &v)) != NULL) {
-        fprintf(f, "{\"str\": \"%s\"}", str);
-      } else {
-        fprintf(f, "{\"val\": \"0x%" INT64_X_FMT "\"}", v);
-      }
-      if ((size_t) i != bcode->lit.len / sizeof(val_t) - 1) {
-        fprintf(f, ",");
-      }
-    }
-
-    fprintf(f, "]}\n");
-    free(jops);
-  } else {
-    struct v7_generic_object *gob = get_generic_object_struct(v);
-    fprintf(f,
-            "{\"type\":\"obj\", \"addr\":\"%p\", \"props\":\"%p\", "
-            "\"attrs\":%d, \"proto\":\"%p\""
-#if defined(V7_ENABLE_ENTITY_IDS)
-            ", \"entity_id_base\":%d, \"entity_id_spec\":\"%d\" "
-#endif
-            "}\n",
-            (void *) obj_base,
-            (void *) ((uintptr_t) obj_base->properties & ~0x1),
-            obj_base->attributes | attrs, (void *) gob->prototype
-#if defined(V7_ENABLE_ENTITY_IDS)
-            ,
-            obj_base->entity_id_base, obj_base->entity_id_spec
-#endif
-            );
-  }
-}
-
-V7_PRIVATE void freeze_prop(struct v7 *v7, FILE *f, struct v7_property *prop) {
-  unsigned int attrs = _V7_PROPERTY_OFF_HEAP;
-#ifndef V7_FREEZE_NOT_READONLY
-  attrs |= V7_PROPERTY_NON_WRITABLE | V7_PROPERTY_NON_CONFIGURABLE;
-#endif
-
-  fprintf(f,
-          "{\"type\":\"prop\","
-          " \"addr\":\"%p\","
-          " \"next\":\"%p\","
-          " \"attrs\":%d,"
-          " \"name\":\"0x%" INT64_X_FMT
-          "\","
-          " \"value_type\":%d,"
-          " \"value\":\"0x%" INT64_X_FMT
-          "\","
-          " \"name_str\":\"%s\""
-#if defined(V7_ENABLE_ENTITY_IDS)
-          ", \"entity_id\":\"%d\""
-#endif
-          "}\n",
-          (void *) prop, (void *) prop->next, prop->attributes | attrs,
-          prop->name, val_type(v7, prop->value), prop->value,
-          v7_get_cstring(v7, &prop->name)
-#if defined(V7_ENABLE_ENTITY_IDS)
-              ,
-          prop->entity_id
-#endif
-          );
-}
-
-#endif
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/parser.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/coroutine.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/parser.h" */
-/* Amalgamated: #include "v7/src/tokenizer.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/ast.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/cyg_profile.h" */
-
-#if !defined(V7_NO_COMPILER)
-
-#define ACCEPT(t) (((v7)->cur_tok == (t)) ? next_tok((v7)), 1 : 0)
-
-#define EXPECT(t)                            \
-  do {                                       \
-    if ((v7)->cur_tok != (t)) {              \
-      CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); \
-    }                                        \
-    next_tok(v7);                            \
-  } while (0)
-
-#define PARSE_WITH_OPT_ARG(tag, arg_tag, arg_parser, label) \
-  do {                                                      \
-    if (end_of_statement(v7) == V7_OK) {                    \
-      add_node(v7, a, (tag));                               \
-    } else {                                                \
-      add_node(v7, a, (arg_tag));                           \
-      arg_parser(label);                                    \
-    }                                                       \
-  } while (0)
-
-#define N (CR_ARG_RET_PT()->arg)
-
-/*
- * User functions
- * (as well as other in-function entry points)
- */
-enum my_fid {
-  fid_none = CR_FID__NONE,
-
-  /* parse_script function */
-  fid_parse_script = CR_FID__USER,
-  fid_p_script_1,
-  fid_p_script_2,
-  fid_p_script_3,
-  fid_p_script_4,
-
-  /* parse_use_strict function */
-  fid_parse_use_strict,
-
-  /* parse_body function */
-  fid_parse_body,
-  fid_p_body_1,
-  fid_p_body_2,
-
-  /* parse_statement function */
-  fid_parse_statement,
-  fid_p_stat_1,
-  fid_p_stat_2,
-  fid_p_stat_3,
-  fid_p_stat_4,
-  fid_p_stat_5,
-  fid_p_stat_6,
-  fid_p_stat_7,
-  fid_p_stat_8,
-  fid_p_stat_9,
-  fid_p_stat_10,
-  fid_p_stat_11,
-  fid_p_stat_12,
-  fid_p_stat_13,
-  fid_p_stat_14,
-
-  /* parse_expression function */
-  fid_parse_expression,
-  fid_p_expr_1,
-
-  /* parse_assign function */
-  fid_parse_assign,
-  fid_p_assign_1,
-
-  /* parse_binary function */
-  fid_parse_binary,
-  fid_p_binary_1,
-  fid_p_binary_2,
-  fid_p_binary_3,
-  fid_p_binary_4,
-  fid_p_binary_5,
-  fid_p_binary_6,
-
-  /* parse_prefix function */
-  fid_parse_prefix,
-  fid_p_prefix_1,
-
-  /* parse_postfix function */
-  fid_parse_postfix,
-  fid_p_postfix_1,
-
-  /* parse_callexpr function */
-  fid_parse_callexpr,
-  fid_p_callexpr_1,
-  fid_p_callexpr_2,
-  fid_p_callexpr_3,
-
-  /* parse_newexpr function */
-  fid_parse_newexpr,
-  fid_p_newexpr_1,
-  fid_p_newexpr_2,
-  fid_p_newexpr_3,
-  fid_p_newexpr_4,
-
-  /* parse_terminal function */
-  fid_parse_terminal,
-  fid_p_terminal_1,
-  fid_p_terminal_2,
-  fid_p_terminal_3,
-  fid_p_terminal_4,
-
-  /* parse_block function */
-  fid_parse_block,
-  fid_p_block_1,
-
-  /* parse_if function */
-  fid_parse_if,
-  fid_p_if_1,
-  fid_p_if_2,
-  fid_p_if_3,
-
-  /* parse_while function */
-  fid_parse_while,
-  fid_p_while_1,
-  fid_p_while_2,
-
-  /* parse_ident function */
-  fid_parse_ident,
-
-  /* parse_ident_allow_reserved_words function */
-  fid_parse_ident_allow_reserved_words,
-  fid_p_ident_arw_1,
-
-  /* parse_funcdecl function */
-  fid_parse_funcdecl,
-  fid_p_funcdecl_1,
-  fid_p_funcdecl_2,
-  fid_p_funcdecl_3,
-  fid_p_funcdecl_4,
-  fid_p_funcdecl_5,
-  fid_p_funcdecl_6,
-  fid_p_funcdecl_7,
-  fid_p_funcdecl_8,
-  fid_p_funcdecl_9,
-
-  /* parse_arglist function */
-  fid_parse_arglist,
-  fid_p_arglist_1,
-
-  /* parse_member function */
-  fid_parse_member,
-  fid_p_member_1,
-
-  /* parse_memberexpr function */
-  fid_parse_memberexpr,
-  fid_p_memberexpr_1,
-  fid_p_memberexpr_2,
-
-  /* parse_var function */
-  fid_parse_var,
-  fid_p_var_1,
-
-  /* parse_prop function */
-  fid_parse_prop,
-#ifdef V7_ENABLE_JS_GETTERS
-  fid_p_prop_1_getter,
-#endif
-  fid_p_prop_2,
-#ifdef V7_ENABLE_JS_SETTERS
-  fid_p_prop_3_setter,
-#endif
-  fid_p_prop_4,
-
-  /* parse_dowhile function */
-  fid_parse_dowhile,
-  fid_p_dowhile_1,
-  fid_p_dowhile_2,
-
-  /* parse_for function */
-  fid_parse_for,
-  fid_p_for_1,
-  fid_p_for_2,
-  fid_p_for_3,
-  fid_p_for_4,
-  fid_p_for_5,
-  fid_p_for_6,
-
-  /* parse_try function */
-  fid_parse_try,
-  fid_p_try_1,
-  fid_p_try_2,
-  fid_p_try_3,
-  fid_p_try_4,
-
-  /* parse_switch function */
-  fid_parse_switch,
-  fid_p_switch_1,
-  fid_p_switch_2,
-  fid_p_switch_3,
-  fid_p_switch_4,
-
-  /* parse_with function */
-  fid_parse_with,
-  fid_p_with_1,
-  fid_p_with_2,
-
-  MY_FID_CNT
-};
-
-/*
- * User exception IDs. The first one should have value `CR_EXC_ID__USER`
- */
-enum parser_exc_id {
-  PARSER_EXC_ID__NONE = CR_EXC_ID__NONE,
-  PARSER_EXC_ID__SYNTAX_ERROR = CR_EXC_ID__USER,
-};
-
-/* structures with locals and args {{{ */
-
-/* parse_script {{{ */
-
-/* parse_script's arguments */
-#if 0
-typedef struct fid_parse_script_arg {
-} fid_parse_script_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_script_arg_t;
-#endif
-
-/* parse_script's data on stack */
-typedef struct fid_parse_script_locals {
-#if 0
-  struct fid_parse_script_arg arg;
-#endif
-
-  ast_off_t start;
-  ast_off_t outer_last_var_node;
-  int saved_in_strict;
-} fid_parse_script_locals_t;
-
-/* }}} */
-
-/* parse_use_strict {{{ */
-/* parse_use_strict's arguments */
-#if 0
-typedef struct fid_parse_use_strict_arg {
-} fid_parse_use_strict_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_use_strict_arg_t;
-#endif
-
-/* parse_use_strict's data on stack */
-#if 0
-typedef struct fid_parse_use_strict_locals {
-  struct fid_parse_use_strict_arg arg;
-} fid_parse_use_strict_locals_t;
-#else
-typedef cr_zero_size_type_t fid_parse_use_strict_locals_t;
-#endif
-
-#define CALL_PARSE_USE_STRICT(_label)      \
-  do {                                     \
-    CR_CALL(fid_parse_use_strict, _label); \
-  } while (0)
-
-/* }}} */
-
-/* parse_body {{{ */
-/* parse_body's arguments */
-typedef struct fid_parse_body_arg { enum v7_tok end; } fid_parse_body_arg_t;
-
-/* parse_body's data on stack */
-typedef struct fid_parse_body_locals {
-  struct fid_parse_body_arg arg;
-
-  ast_off_t start;
-} fid_parse_body_locals_t;
-
-#define CALL_PARSE_BODY(_end, _label) \
-  do {                                \
-    N.fid_parse_body.end = (_end);    \
-    CR_CALL(fid_parse_body, _label);  \
-  } while (0)
-/* }}} */
-
-/* parse_statement {{{ */
-/* parse_statement's arguments */
-#if 0
-typedef struct fid_parse_statement_arg {
-} fid_parse_statement_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_statement_arg_t;
-#endif
-
-/* parse_statement's data on stack */
-#if 0
-typedef struct fid_parse_statement_locals {
-  struct fid_parse_statement_arg arg;
-} fid_parse_statement_locals_t;
-#else
-typedef cr_zero_size_type_t fid_parse_statement_locals_t;
-#endif
-
-#define CALL_PARSE_STATEMENT(_label)      \
-  do {                                    \
-    CR_CALL(fid_parse_statement, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_expression {{{ */
-/* parse_expression's arguments */
-#if 0
-typedef struct fid_parse_expression_arg {
-} fid_parse_expression_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_expression_arg_t;
-#endif
-
-/* parse_expression's data on stack */
-typedef struct fid_parse_expression_locals {
-#if 0
-  struct fid_parse_expression_arg arg;
-#endif
-
-  ast_off_t pos;
-  int group;
-} fid_parse_expression_locals_t;
-
-#define CALL_PARSE_EXPRESSION(_label)      \
-  do {                                     \
-    CR_CALL(fid_parse_expression, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_assign {{{ */
-/* parse_assign's arguments */
-#if 0
-typedef struct fid_parse_assign_arg {
-} fid_parse_assign_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_assign_arg_t;
-#endif
-
-/* parse_assign's data on stack */
-#if 0
-typedef struct fid_parse_assign_locals {
-  struct fid_parse_assign_arg arg;
-} fid_parse_assign_locals_t;
-#else
-typedef cr_zero_size_type_t fid_parse_assign_locals_t;
-#endif
-
-#define CALL_PARSE_ASSIGN(_label)      \
-  do {                                 \
-    CR_CALL(fid_parse_assign, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_binary {{{ */
-/* parse_binary's arguments */
-typedef struct fid_parse_binary_arg {
-  ast_off_t pos;
-  uint8_t min_level;
-} fid_parse_binary_arg_t;
-
-/* parse_binary's data on stack */
-typedef struct fid_parse_binary_locals {
-  struct fid_parse_binary_arg arg;
-
-  uint8_t i;
-  /* during iteration, it becomes negative, so should be signed */
-  int8_t level;
-  uint8_t /*enum v7_tok*/ tok;
-  uint8_t /*enum ast_tag*/ ast;
-  ast_off_t saved_mbuf_len;
-} fid_parse_binary_locals_t;
-
-#define CALL_PARSE_BINARY(_level, _pos, _label) \
-  do {                                          \
-    N.fid_parse_binary.min_level = (_level);    \
-    N.fid_parse_binary.pos = (_pos);            \
-    CR_CALL(fid_parse_binary, _label);          \
-  } while (0)
-/* }}} */
-
-/* parse_prefix {{{ */
-/* parse_prefix's arguments */
-#if 0
-typedef struct fid_parse_prefix_arg {
-} fid_parse_prefix_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_prefix_arg_t;
-#endif
-
-/* parse_prefix's data on stack */
-#if 0
-typedef struct fid_parse_prefix_locals {
-  struct fid_parse_prefix_arg arg;
-} fid_parse_prefix_locals_t;
-#else
-typedef cr_zero_size_type_t fid_parse_prefix_locals_t;
-#endif
-
-#define CALL_PARSE_PREFIX(_label)      \
-  do {                                 \
-    CR_CALL(fid_parse_prefix, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_postfix {{{ */
-/* parse_postfix's arguments */
-#if 0
-typedef struct fid_parse_postfix_arg {
-} fid_parse_postfix_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_postfix_arg_t;
-#endif
-
-/* parse_postfix's data on stack */
-typedef struct fid_parse_postfix_locals {
-#if 0
-  struct fid_parse_postfix_arg arg;
-#endif
-
-  ast_off_t pos;
-} fid_parse_postfix_locals_t;
-
-#define CALL_PARSE_POSTFIX(_label)      \
-  do {                                  \
-    CR_CALL(fid_parse_postfix, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_callexpr {{{ */
-/* parse_callexpr's arguments */
-#if 0
-typedef struct fid_parse_callexpr_arg {
-} fid_parse_callexpr_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_callexpr_arg_t;
-#endif
-
-/* parse_callexpr's data on stack */
-typedef struct fid_parse_callexpr_locals {
-#if 0
-  struct fid_parse_callexpr_arg arg;
-#endif
-
-  ast_off_t pos;
-} fid_parse_callexpr_locals_t;
-
-#define CALL_PARSE_CALLEXPR(_label)      \
-  do {                                   \
-    CR_CALL(fid_parse_callexpr, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_newexpr {{{ */
-/* parse_newexpr's arguments */
-#if 0
-typedef struct fid_parse_newexpr_arg {
-} fid_parse_newexpr_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_newexpr_arg_t;
-#endif
-
-/* parse_newexpr's data on stack */
-typedef struct fid_parse_newexpr_locals {
-#if 0
-  struct fid_parse_newexpr_arg arg;
-#endif
-
-  ast_off_t start;
-} fid_parse_newexpr_locals_t;
-
-#define CALL_PARSE_NEWEXPR(_label)      \
-  do {                                  \
-    CR_CALL(fid_parse_newexpr, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_terminal {{{ */
-/* parse_terminal's arguments */
-#if 0
-typedef struct fid_parse_terminal_arg {
-} fid_parse_terminal_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_terminal_arg_t;
-#endif
-
-/* parse_terminal's data on stack */
-typedef struct fid_parse_terminal_locals {
-#if 0
-  struct fid_parse_terminal_arg arg;
-#endif
-
-  ast_off_t start;
-} fid_parse_terminal_locals_t;
-
-#define CALL_PARSE_TERMINAL(_label)      \
-  do {                                   \
-    CR_CALL(fid_parse_terminal, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_block {{{ */
-/* parse_block's arguments */
-#if 0
-typedef struct fid_parse_block_arg {
-} fid_parse_block_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_block_arg_t;
-#endif
-
-/* parse_block's data on stack */
-#if 0
-typedef struct fid_parse_block_locals {
-  struct fid_parse_block_arg arg;
-} fid_parse_block_locals_t;
-#else
-typedef cr_zero_size_type_t fid_parse_block_locals_t;
-#endif
-
-#define CALL_PARSE_BLOCK(_label)      \
-  do {                                \
-    CR_CALL(fid_parse_block, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_if {{{ */
-/* parse_if's arguments */
-#if 0
-typedef struct fid_parse_if_arg {
-} fid_parse_if_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_if_arg_t;
-#endif
-
-/* parse_if's data on stack */
-typedef struct fid_parse_if_locals {
-#if 0
-  struct fid_parse_if_arg arg;
-#endif
-
-  ast_off_t start;
-} fid_parse_if_locals_t;
-
-#define CALL_PARSE_IF(_label)      \
-  do {                             \
-    CR_CALL(fid_parse_if, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_while {{{ */
-/* parse_while's arguments */
-#if 0
-typedef struct fid_parse_while_arg {
-} fid_parse_while_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_while_arg_t;
-#endif
-
-/* parse_while's data on stack */
-typedef struct fid_parse_while_locals {
-#if 0
-  struct fid_parse_while_arg arg;
-#endif
-
-  ast_off_t start;
-  uint8_t saved_in_loop;
-} fid_parse_while_locals_t;
-
-#define CALL_PARSE_WHILE(_label)      \
-  do {                                \
-    CR_CALL(fid_parse_while, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_ident {{{ */
-/* parse_ident's arguments */
-#if 0
-typedef struct fid_parse_ident_arg {
-} fid_parse_ident_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_ident_arg_t;
-#endif
-
-/* parse_ident's data on stack */
-#if 0
-typedef struct fid_parse_ident_locals {
-  struct fid_parse_ident_arg arg;
-} fid_parse_ident_locals_t;
-#else
-typedef cr_zero_size_type_t fid_parse_ident_locals_t;
-#endif
-
-#define CALL_PARSE_IDENT(_label)      \
-  do {                                \
-    CR_CALL(fid_parse_ident, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_ident_allow_reserved_words {{{ */
-/* parse_ident_allow_reserved_words's arguments */
-#if 0
-typedef struct fid_parse_ident_allow_reserved_words_arg {
-} fid_parse_ident_allow_reserved_words_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_ident_allow_reserved_words_arg_t;
-#endif
-
-/* parse_ident_allow_reserved_words's data on stack */
-#if 0
-typedef struct fid_parse_ident_allow_reserved_words_locals {
-  struct fid_parse_ident_allow_reserved_words_arg arg;
-} fid_parse_ident_allow_reserved_words_locals_t;
-#else
-typedef cr_zero_size_type_t fid_parse_ident_allow_reserved_words_locals_t;
-#endif
-
-#define CALL_PARSE_IDENT_ALLOW_RESERVED_WORDS(_label)      \
-  do {                                                     \
-    CR_CALL(fid_parse_ident_allow_reserved_words, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_funcdecl {{{ */
-/* parse_funcdecl's arguments */
-typedef struct fid_parse_funcdecl_arg {
-  uint8_t require_named;
-  uint8_t reserved_name;
-} fid_parse_funcdecl_arg_t;
-
-/* parse_funcdecl's data on stack */
-typedef struct fid_parse_funcdecl_locals {
-  struct fid_parse_funcdecl_arg arg;
-
-  ast_off_t start;
-  ast_off_t outer_last_var_node;
-  uint8_t saved_in_function;
-  uint8_t saved_in_strict;
-} fid_parse_funcdecl_locals_t;
-
-#define CALL_PARSE_FUNCDECL(_require_named, _reserved_name, _label) \
-  do {                                                              \
-    N.fid_parse_funcdecl.require_named = (_require_named);          \
-    N.fid_parse_funcdecl.reserved_name = (_reserved_name);          \
-    CR_CALL(fid_parse_funcdecl, _label);                            \
-  } while (0)
-/* }}} */
-
-/* parse_arglist {{{ */
-/* parse_arglist's arguments */
-#if 0
-typedef struct fid_parse_arglist_arg {
-} fid_parse_arglist_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_arglist_arg_t;
-#endif
-
-/* parse_arglist's data on stack */
-#if 0
-typedef struct fid_parse_arglist_locals {
-  struct fid_parse_arglist_arg arg;
-} fid_parse_arglist_locals_t;
-#else
-typedef cr_zero_size_type_t fid_parse_arglist_locals_t;
-#endif
-
-#define CALL_PARSE_ARGLIST(_label)      \
-  do {                                  \
-    CR_CALL(fid_parse_arglist, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_member {{{ */
-/* parse_member's arguments */
-typedef struct fid_parse_member_arg { ast_off_t pos; } fid_parse_member_arg_t;
-
-/* parse_member's data on stack */
-typedef struct fid_parse_member_locals {
-  struct fid_parse_member_arg arg;
-} fid_parse_member_locals_t;
-
-#define CALL_PARSE_MEMBER(_pos, _label) \
-  do {                                  \
-    N.fid_parse_member.pos = (_pos);    \
-    CR_CALL(fid_parse_member, _label);  \
-  } while (0)
-/* }}} */
-
-/* parse_memberexpr {{{ */
-/* parse_memberexpr's arguments */
-#if 0
-typedef struct fid_parse_memberexpr_arg {
-} fid_parse_memberexpr_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_memberexpr_arg_t;
-#endif
-
-/* parse_memberexpr's data on stack */
-typedef struct fid_parse_memberexpr_locals {
-#if 0
-  struct fid_parse_memberexpr_arg arg;
-#endif
-
-  ast_off_t pos;
-} fid_parse_memberexpr_locals_t;
-
-#define CALL_PARSE_MEMBEREXPR(_label)      \
-  do {                                     \
-    CR_CALL(fid_parse_memberexpr, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_var {{{ */
-/* parse_var's arguments */
-#if 0
-typedef struct fid_parse_var_arg {
-} fid_parse_var_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_var_arg_t;
-#endif
-
-/* parse_var's data on stack */
-typedef struct fid_parse_var_locals {
-#if 0
-  struct fid_parse_var_arg arg;
-#endif
-
-  ast_off_t start;
-} fid_parse_var_locals_t;
-
-#define CALL_PARSE_VAR(_label)      \
-  do {                              \
-    CR_CALL(fid_parse_var, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_prop {{{ */
-/* parse_prop's arguments */
-#if 0
-typedef struct fid_parse_prop_arg {
-} fid_parse_prop_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_prop_arg_t;
-#endif
-
-/* parse_prop's data on stack */
-#if 0
-typedef struct fid_parse_prop_locals {
-  struct fid_parse_prop_arg arg;
-} fid_parse_prop_locals_t;
-#else
-typedef cr_zero_size_type_t fid_parse_prop_locals_t;
-#endif
-
-#define CALL_PARSE_PROP(_label)      \
-  do {                               \
-    CR_CALL(fid_parse_prop, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_dowhile {{{ */
-/* parse_dowhile's arguments */
-#if 0
-typedef struct fid_parse_dowhile_arg {
-} fid_parse_dowhile_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_dowhile_arg_t;
-#endif
-
-/* parse_dowhile's data on stack */
-typedef struct fid_parse_dowhile_locals {
-#if 0
-  struct fid_parse_dowhile_arg arg;
-#endif
-
-  ast_off_t start;
-  uint8_t saved_in_loop;
-} fid_parse_dowhile_locals_t;
-
-#define CALL_PARSE_DOWHILE(_label)      \
-  do {                                  \
-    CR_CALL(fid_parse_dowhile, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_for {{{ */
-/* parse_for's arguments */
-#if 0
-typedef struct fid_parse_for_arg {
-} fid_parse_for_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_for_arg_t;
-#endif
-
-/* parse_for's data on stack */
-typedef struct fid_parse_for_locals {
-#if 0
-  struct fid_parse_for_arg arg;
-#endif
-
-  ast_off_t start;
-  uint8_t saved_in_loop;
-} fid_parse_for_locals_t;
-
-#define CALL_PARSE_FOR(_label)      \
-  do {                              \
-    CR_CALL(fid_parse_for, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_try {{{ */
-/* parse_try's arguments */
-#if 0
-typedef struct fid_parse_try_arg {
-} fid_parse_try_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_try_arg_t;
-#endif
-
-/* parse_try's data on stack */
-typedef struct fid_parse_try_locals {
-#if 0
-  struct fid_parse_try_arg arg;
-#endif
-
-  ast_off_t start;
-  uint8_t catch_or_finally;
-} fid_parse_try_locals_t;
-
-#define CALL_PARSE_TRY(_label)      \
-  do {                              \
-    CR_CALL(fid_parse_try, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_switch {{{ */
-/* parse_switch's arguments */
-#if 0
-typedef struct fid_parse_switch_arg {
-} fid_parse_switch_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_switch_arg_t;
-#endif
-
-/* parse_switch's data on stack */
-typedef struct fid_parse_switch_locals {
-#if 0
-  struct fid_parse_switch_arg arg;
-#endif
-
-  ast_off_t start;
-  int saved_in_switch;
-  ast_off_t case_start;
-} fid_parse_switch_locals_t;
-
-#define CALL_PARSE_SWITCH(_label)      \
-  do {                                 \
-    CR_CALL(fid_parse_switch, _label); \
-  } while (0)
-/* }}} */
-
-/* parse_with {{{ */
-/* parse_with's arguments */
-#if 0
-typedef struct fid_parse_with_arg {
-} fid_parse_with_arg_t;
-#else
-typedef cr_zero_size_type_t fid_parse_with_arg_t;
-#endif
-
-/* parse_with's data on stack */
-typedef struct fid_parse_with_locals {
-#if 0
-  struct fid_parse_with_arg arg;
-#endif
-
-  ast_off_t start;
-} fid_parse_with_locals_t;
-
-#define CALL_PARSE_WITH(_label)      \
-  do {                               \
-    CR_CALL(fid_parse_with, _label); \
-  } while (0)
-/* }}} */
-
-/* }}} */
-
-/*
- * Array of "function" descriptors. Each descriptor contains just a size
- * of "function"'s locals.
- */
-static const struct cr_func_desc _fid_descrs[MY_FID_CNT] = {
-
-    /* fid_none */
-    {0},
-
-    /* fid_parse_script ----------------------------------------- */
-    /* fid_parse_script */
-    {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
-    /* fid_p_script_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
-    /* fid_p_script_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
-    /* fid_p_script_3 */
-    {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
-    /* fid_p_script_4 */
-    {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
-
-    /* fid_parse_use_strict ----------------------------------------- */
-    /* fid_parse_use_strict */
-    {CR_LOCALS_SIZEOF(fid_parse_use_strict_locals_t)},
-
-    /* fid_parse_body ----------------------------------------- */
-    /* fid_parse_body */
-    {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)},
-    /* fid_p_body_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)},
-    /* fid_p_body_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)},
-
-    /* fid_parse_statement ----------------------------------------- */
-    /* fid_parse_statement */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_3 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_4 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_5 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_6 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_7 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_8 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_9 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_10 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_11 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_12 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_13 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-    /* fid_p_stat_14 */
-    {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
-
-    /* fid_parse_expression ----------------------------------------- */
-    /* fid_parse_expression */
-    {CR_LOCALS_SIZEOF(fid_parse_expression_locals_t)},
-    /* fid_p_expr_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_expression_locals_t)},
-
-    /* fid_parse_assign ----------------------------------------- */
-    /* fid_parse_assign */
-    {CR_LOCALS_SIZEOF(fid_parse_assign_locals_t)},
-    /* fid_p_assign_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_assign_locals_t)},
-
-    /* fid_parse_binary ----------------------------------------- */
-    /* fid_parse_binary */
-    {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
-    /* fid_p_binary_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
-    /* fid_p_binary_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
-    /* fid_p_binary_3 */
-    {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
-    /* fid_p_binary_4 */
-    {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
-    /* fid_p_binary_5 */
-    {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
-    /* fid_p_binary_6 */
-    {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
-
-    /* fid_parse_prefix ----------------------------------------- */
-    /* fid_parse_prefix */
-    {CR_LOCALS_SIZEOF(fid_parse_prefix_locals_t)},
-    /* fid_p_prefix_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_prefix_locals_t)},
-
-    /* fid_parse_postfix ----------------------------------------- */
-    /* fid_parse_postfix */
-    {CR_LOCALS_SIZEOF(fid_parse_postfix_locals_t)},
-    /* fid_p_postfix_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_postfix_locals_t)},
-
-    /* fid_parse_callexpr ----------------------------------------- */
-    /* fid_parse_callexpr */
-    {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
-    /* fid_p_callexpr_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
-    /* fid_p_callexpr_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
-    /* fid_p_callexpr_3 */
-    {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
-
-    /* fid_parse_newexpr ----------------------------------------- */
-    /* fid_parse_newexpr */
-    {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
-    /* fid_p_newexpr_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
-    /* fid_p_newexpr_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
-    /* fid_p_newexpr_3 */
-    {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
-    /* fid_p_newexpr_4 */
-    {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
-
-    /* fid_parse_terminal ----------------------------------------- */
-    /* fid_parse_terminal */
-    {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
-    /* fid_p_terminal_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
-    /* fid_p_terminal_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
-    /* fid_p_terminal_3 */
-    {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
-    /* fid_p_terminal_4 */
-    {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
-
-    /* fid_parse_block ----------------------------------------- */
-    /* fid_parse_block */
-    {CR_LOCALS_SIZEOF(fid_parse_block_locals_t)},
-    /* fid_p_block_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_block_locals_t)},
-
-    /* fid_parse_if ----------------------------------------- */
-    /* fid_parse_if */
-    {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
-    /* fid_p_if_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
-    /* fid_p_if_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
-    /* fid_p_if_3 */
-    {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
-
-    /* fid_parse_while ----------------------------------------- */
-    /* fid_parse_while */
-    {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)},
-    /* fid_p_while_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)},
-    /* fid_p_while_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)},
-
-    /* fid_parse_ident ----------------------------------------- */
-    /* fid_parse_ident */
-    {CR_LOCALS_SIZEOF(fid_parse_ident_locals_t)},
-
-    /* fid_parse_ident_allow_reserved_words -------------------- */
-    /* fid_parse_ident_allow_reserved_words */
-    {CR_LOCALS_SIZEOF(fid_parse_ident_allow_reserved_words_locals_t)},
-    /* fid_p_ident_allow_reserved_words_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_ident_allow_reserved_words_locals_t)},
-
-    /* fid_parse_funcdecl ----------------------------------------- */
-    /* fid_parse_funcdecl */
-    {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
-    /* fid_p_funcdecl_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
-    /* fid_p_funcdecl_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
-    /* fid_p_funcdecl_3 */
-    {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
-    /* fid_p_funcdecl_4 */
-    {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
-    /* fid_p_funcdecl_5 */
-    {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
-    /* fid_p_funcdecl_6 */
-    {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
-    /* fid_p_funcdecl_7 */
-    {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
-    /* fid_p_funcdecl_8 */
-    {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
-    /* fid_p_funcdecl_9 */
-    {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
-
-    /* fid_parse_arglist ----------------------------------------- */
-    /* fid_parse_arglist */
-    {CR_LOCALS_SIZEOF(fid_parse_arglist_locals_t)},
-    /* fid_p_arglist_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_arglist_locals_t)},
-
-    /* fid_parse_member ----------------------------------------- */
-    /* fid_parse_member */
-    {CR_LOCALS_SIZEOF(fid_parse_member_locals_t)},
-    /* fid_p_member_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_member_locals_t)},
-
-    /* fid_parse_memberexpr ----------------------------------------- */
-    /* fid_parse_memberexpr */
-    {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)},
-    /* fid_p_memberexpr_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)},
-    /* fid_p_memberexpr_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)},
-
-    /* fid_parse_var ----------------------------------------- */
-    /* fid_parse_var */
-    {CR_LOCALS_SIZEOF(fid_parse_var_locals_t)},
-    /* fid_p_var_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_var_locals_t)},
-
-    /* fid_parse_prop ----------------------------------------- */
-    /* fid_parse_prop */
-    {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
-#ifdef V7_ENABLE_JS_GETTERS
-    /* fid_p_prop_1_getter */
-    {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
-#endif
-    /* fid_p_prop_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
-#ifdef V7_ENABLE_JS_SETTERS
-    /* fid_p_prop_3_setter */
-    {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
-#endif
-    /* fid_p_prop_4 */
-    {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
-
-    /* fid_parse_dowhile ----------------------------------------- */
-    /* fid_parse_dowhile */
-    {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)},
-    /* fid_p_dowhile_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)},
-    /* fid_p_dowhile_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)},
-
-    /* fid_parse_for ----------------------------------------- */
-    /* fid_parse_for */
-    {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
-    /* fid_p_for_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
-    /* fid_p_for_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
-    /* fid_p_for_3 */
-    {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
-    /* fid_p_for_4 */
-    {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
-    /* fid_p_for_5 */
-    {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
-    /* fid_p_for_6 */
-    {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
-
-    /* fid_parse_try ----------------------------------------- */
-    /* fid_parse_try */
-    {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
-    /* fid_p_try_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
-    /* fid_p_try_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
-    /* fid_p_try_3 */
-    {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
-    /* fid_p_try_4 */
-    {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
-
-    /* fid_parse_switch ----------------------------------------- */
-    /* fid_parse_switch */
-    {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
-    /* fid_p_switch_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
-    /* fid_p_switch_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
-    /* fid_p_switch_3 */
-    {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
-    /* fid_p_switch_4 */
-    {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
-
-    /* fid_parse_with ----------------------------------------- */
-    /* fid_parse_with */
-    {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)},
-    /* fid_p_with_1 */
-    {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)},
-    /* fid_p_with_2 */
-    {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)},
-
-};
-
-/*
- * Union of arguments and return values for all existing "functions".
- *
- * Used as an accumulator when we call function, return from function,
- * yield, or resume.
- */
-union user_arg_ret {
-  /* arguments to the next function */
-  union {
-#if 0
-    fid_parse_script_arg_t fid_parse_script;
-    fid_parse_use_strict_arg_t fid_parse_use_strict;
-    fid_parse_statement_arg_t fid_parse_statement;
-    fid_parse_expression_arg_t fid_parse_expression;
-    fid_parse_assign_arg_t fid_parse_assign;
-    fid_parse_prefix_arg_t fid_parse_prefix;
-    fid_parse_postfix_arg_t fid_parse_postfix;
-    fid_parse_callexpr_arg_t fid_parse_callexpr;
-    fid_parse_newexpr_arg_t fid_parse_newexpr;
-    fid_parse_terminal_arg_t fid_parse_terminal;
-    fid_parse_block_arg_t fid_parse_block;
-    fid_parse_if_arg_t fid_parse_if;
-    fid_parse_while_arg_t fid_parse_while;
-    fid_parse_ident_arg_t fid_parse_ident;
-    fid_parse_ident_allow_reserved_words_arg_t
-      fid_parse_ident_allow_reserved_words;
-    fid_parse_arglist_arg_t fid_parse_arglist;
-    fid_parse_memberexpr_arg_t fid_parse_memberexpr;
-    fid_parse_var_arg_t fid_parse_var;
-    fid_parse_prop_arg_t fid_parse_prop;
-    fid_parse_dowhile_arg_t fid_parse_dowhile;
-    fid_parse_for_arg_t fid_parse_for;
-    fid_parse_try_arg_t fid_parse_try;
-    fid_parse_switch_arg_t fid_parse_switch;
-    fid_parse_with_arg_t fid_parse_with;
-#endif
-    fid_parse_body_arg_t fid_parse_body;
-    fid_parse_binary_arg_t fid_parse_binary;
-    fid_parse_funcdecl_arg_t fid_parse_funcdecl;
-    fid_parse_member_arg_t fid_parse_member;
-  } arg;
-
-  /* value returned from function */
-  /*
-     union {
-     } ret;
-     */
-};
-
-static enum v7_tok next_tok(struct v7 *v7) {
-  int prev_line_no = v7->pstate.prev_line_no;
-  v7->pstate.prev_line_no = v7->pstate.line_no;
-  v7->pstate.line_no += skip_to_next_tok(&v7->pstate.pc, v7->pstate.src_end);
-  v7->after_newline = prev_line_no != v7->pstate.line_no;
-  v7->tok = v7->pstate.pc;
-  v7->cur_tok = get_tok(&v7->pstate.pc, v7->pstate.src_end, &v7->cur_tok_dbl,
-                        v7->cur_tok);
-  v7->tok_len = v7->pstate.pc - v7->tok;
-  v7->pstate.line_no += skip_to_next_tok(&v7->pstate.pc, v7->pstate.src_end);
-  return v7->cur_tok;
-}
-
-#ifndef V7_DISABLE_LINE_NUMBERS
-/*
- * Assumes `offset` points to the byte right after a tag
- */
-static void insert_line_no_if_changed(struct v7 *v7, struct ast *a,
-                                      ast_off_t offset) {
-  if (v7->pstate.prev_line_no != v7->line_no) {
-    v7->line_no = v7->pstate.prev_line_no;
-    ast_add_line_no(a, offset - 1, v7->line_no);
-  } else {
-#if V7_AST_FORCE_LINE_NUMBERS
-    /*
-     * This mode is needed for debug only: to make sure AST consumers correctly
-     * consume all nodes with line numbers data encoded
-     */
-    ast_add_line_no(a, offset - 1, 0);
-#endif
-  }
-}
-#else
-static void insert_line_no_if_changed(struct v7 *v7, struct ast *a,
-                                      ast_off_t offset) {
-  (void) v7;
-  (void) a;
-  (void) offset;
-}
-#endif
-
-static ast_off_t insert_node(struct v7 *v7, struct ast *a, ast_off_t start,
-                             enum ast_tag tag) {
-  ast_off_t ret = ast_insert_node(a, start, tag);
-  insert_line_no_if_changed(v7, a, ret);
-  return ret;
-}
-
-static ast_off_t add_node(struct v7 *v7, struct ast *a, enum ast_tag tag) {
-  return insert_node(v7, a, a->mbuf.len, tag);
-}
-
-static ast_off_t insert_inlined_node(struct v7 *v7, struct ast *a,
-                                     ast_off_t start, enum ast_tag tag,
-                                     const char *name, size_t len) {
-  ast_off_t ret = ast_insert_inlined_node(a, start, tag, name, len);
-  insert_line_no_if_changed(v7, a, ret);
-  return ret;
-}
-
-static ast_off_t add_inlined_node(struct v7 *v7, struct ast *a,
-                                  enum ast_tag tag, const char *name,
-                                  size_t len) {
-  return insert_inlined_node(v7, a, a->mbuf.len, tag, name, len);
-}
-
-static unsigned long get_column(const char *code, const char *pos) {
-  const char *p = pos;
-  while (p > code && *p != '\n') {
-    p--;
-  }
-  return p == code ? pos - p : pos - (p + 1);
-}
-
-static enum v7_err end_of_statement(struct v7 *v7) {
-  if (v7->cur_tok == TOK_SEMICOLON || v7->cur_tok == TOK_END_OF_INPUT ||
-      v7->cur_tok == TOK_CLOSE_CURLY || v7->after_newline) {
-    return V7_OK;
-  }
-  return V7_SYNTAX_ERROR;
-}
-
-static enum v7_tok lookahead(const struct v7 *v7) {
-  const char *s = v7->pstate.pc;
-  double d;
-  return get_tok(&s, v7->pstate.src_end, &d, v7->cur_tok);
-}
-
-static int parse_optional(struct v7 *v7, struct ast *a,
-                          enum v7_tok terminator) {
-  if (v7->cur_tok != terminator) {
-    return 1;
-  }
-  add_node(v7, a, AST_NOP);
-  return 0;
-}
-
-/*
- * On ESP8266 'levels' declaration have to be outside of 'parse_binary'
- * in order to prevent reboot on return from this function
- * TODO(alashkin): understand why
- */
-#define NONE \
-  { (enum v7_tok) 0, (enum v7_tok) 0, (enum ast_tag) 0 }
-
-static const struct {
-  int len, left_to_right;
-  struct {
-    enum v7_tok start_tok, end_tok;
-    enum ast_tag start_ast;
-  } parts[2];
-} levels[] = {
-    {1, 0, {{TOK_ASSIGN, TOK_URSHIFT_ASSIGN, AST_ASSIGN}, NONE}},
-    {1, 0, {{TOK_QUESTION, TOK_QUESTION, AST_COND}, NONE}},
-    {1, 1, {{TOK_LOGICAL_OR, TOK_LOGICAL_OR, AST_LOGICAL_OR}, NONE}},
-    {1, 1, {{TOK_LOGICAL_AND, TOK_LOGICAL_AND, AST_LOGICAL_AND}, NONE}},
-    {1, 1, {{TOK_OR, TOK_OR, AST_OR}, NONE}},
-    {1, 1, {{TOK_XOR, TOK_XOR, AST_XOR}, NONE}},
-    {1, 1, {{TOK_AND, TOK_AND, AST_AND}, NONE}},
-    {1, 1, {{TOK_EQ, TOK_NE_NE, AST_EQ}, NONE}},
-    {2, 1, {{TOK_LE, TOK_GT, AST_LE}, {TOK_IN, TOK_INSTANCEOF, AST_IN}}},
-    {1, 1, {{TOK_LSHIFT, TOK_URSHIFT, AST_LSHIFT}, NONE}},
-    {1, 1, {{TOK_PLUS, TOK_MINUS, AST_ADD}, NONE}},
-    {1, 1, {{TOK_REM, TOK_DIV, AST_REM}, NONE}}};
-
-enum cr_status parser_cr_exec(struct cr_ctx *p_ctx, struct v7 *v7,
-                              struct ast *a) {
-  enum cr_status rc = CR_RES__OK;
-
-_cr_iter_begin:
-
-  rc = cr_on_iter_begin(p_ctx);
-  if (rc != CR_RES__OK) {
-    return rc;
-  }
-
-  /*
-   * dispatcher switch: depending on the fid, jump to the corresponding label
-   */
-  switch ((enum my_fid) CR_CURR_FUNC()) {
-    CR_DEFINE_ENTRY_POINT(fid_none);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_script);
-    CR_DEFINE_ENTRY_POINT(fid_p_script_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_script_2);
-    CR_DEFINE_ENTRY_POINT(fid_p_script_3);
-    CR_DEFINE_ENTRY_POINT(fid_p_script_4);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_use_strict);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_body);
-    CR_DEFINE_ENTRY_POINT(fid_p_body_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_body_2);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_statement);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_2);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_3);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_4);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_5);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_6);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_7);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_8);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_9);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_10);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_11);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_12);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_13);
-    CR_DEFINE_ENTRY_POINT(fid_p_stat_14);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_expression);
-    CR_DEFINE_ENTRY_POINT(fid_p_expr_1);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_assign);
-    CR_DEFINE_ENTRY_POINT(fid_p_assign_1);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_binary);
-    CR_DEFINE_ENTRY_POINT(fid_p_binary_2);
-    CR_DEFINE_ENTRY_POINT(fid_p_binary_3);
-    CR_DEFINE_ENTRY_POINT(fid_p_binary_4);
-    CR_DEFINE_ENTRY_POINT(fid_p_binary_5);
-    CR_DEFINE_ENTRY_POINT(fid_p_binary_6);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_prefix);
-    CR_DEFINE_ENTRY_POINT(fid_p_prefix_1);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_postfix);
-    CR_DEFINE_ENTRY_POINT(fid_p_postfix_1);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_callexpr);
-    CR_DEFINE_ENTRY_POINT(fid_p_callexpr_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_callexpr_2);
-    CR_DEFINE_ENTRY_POINT(fid_p_callexpr_3);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_newexpr);
-    CR_DEFINE_ENTRY_POINT(fid_p_newexpr_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_newexpr_2);
-    CR_DEFINE_ENTRY_POINT(fid_p_newexpr_3);
-    CR_DEFINE_ENTRY_POINT(fid_p_newexpr_4);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_terminal);
-    CR_DEFINE_ENTRY_POINT(fid_p_terminal_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_terminal_2);
-    CR_DEFINE_ENTRY_POINT(fid_p_terminal_3);
-    CR_DEFINE_ENTRY_POINT(fid_p_terminal_4);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_block);
-    CR_DEFINE_ENTRY_POINT(fid_p_block_1);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_if);
-    CR_DEFINE_ENTRY_POINT(fid_p_if_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_if_2);
-    CR_DEFINE_ENTRY_POINT(fid_p_if_3);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_while);
-    CR_DEFINE_ENTRY_POINT(fid_p_while_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_while_2);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_ident);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_ident_allow_reserved_words);
-    CR_DEFINE_ENTRY_POINT(fid_p_ident_arw_1);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_funcdecl);
-    CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_2);
-    CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_3);
-    CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_4);
-    CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_5);
-    CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_6);
-    CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_7);
-    CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_8);
-    CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_9);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_arglist);
-    CR_DEFINE_ENTRY_POINT(fid_p_arglist_1);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_member);
-    CR_DEFINE_ENTRY_POINT(fid_p_member_1);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_memberexpr);
-    CR_DEFINE_ENTRY_POINT(fid_p_memberexpr_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_memberexpr_2);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_var);
-    CR_DEFINE_ENTRY_POINT(fid_p_var_1);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_prop);
-#ifdef V7_ENABLE_JS_GETTERS
-    CR_DEFINE_ENTRY_POINT(fid_p_prop_1_getter);
-#endif
-    CR_DEFINE_ENTRY_POINT(fid_p_prop_2);
-#ifdef V7_ENABLE_JS_SETTERS
-    CR_DEFINE_ENTRY_POINT(fid_p_prop_3_setter);
-#endif
-    CR_DEFINE_ENTRY_POINT(fid_p_prop_4);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_dowhile);
-    CR_DEFINE_ENTRY_POINT(fid_p_dowhile_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_dowhile_2);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_for);
-    CR_DEFINE_ENTRY_POINT(fid_p_for_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_for_2);
-    CR_DEFINE_ENTRY_POINT(fid_p_for_3);
-    CR_DEFINE_ENTRY_POINT(fid_p_for_4);
-    CR_DEFINE_ENTRY_POINT(fid_p_for_5);
-    CR_DEFINE_ENTRY_POINT(fid_p_for_6);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_try);
-    CR_DEFINE_ENTRY_POINT(fid_p_try_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_try_2);
-    CR_DEFINE_ENTRY_POINT(fid_p_try_3);
-    CR_DEFINE_ENTRY_POINT(fid_p_try_4);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_switch);
-    CR_DEFINE_ENTRY_POINT(fid_p_switch_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_switch_2);
-    CR_DEFINE_ENTRY_POINT(fid_p_switch_3);
-    CR_DEFINE_ENTRY_POINT(fid_p_switch_4);
-
-    CR_DEFINE_ENTRY_POINT(fid_parse_with);
-    CR_DEFINE_ENTRY_POINT(fid_p_with_1);
-    CR_DEFINE_ENTRY_POINT(fid_p_with_2);
-
-    default:
-      /* should never be here */
-      printf("fatal: wrong func id: %d", CR_CURR_FUNC());
-      break;
-  };
-
-/* static enum v7_err parse_script(struct v7 *v7, struct ast *a) */
-fid_parse_script :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_script_locals_t)
-{
-  L->start = add_node(v7, a, AST_SCRIPT);
-  L->outer_last_var_node = v7->last_var_node;
-  L->saved_in_strict = v7->pstate.in_strict;
-
-  v7->last_var_node = L->start;
-  ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
-
-  CR_TRY(fid_p_script_1);
-  {
-    CALL_PARSE_USE_STRICT(fid_p_script_3);
-    v7->pstate.in_strict = 1;
-  }
-  CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_script_1, fid_p_script_2);
-  CR_ENDCATCH(fid_p_script_2);
-
-  CALL_PARSE_BODY(TOK_END_OF_INPUT, fid_p_script_4);
-  ast_set_skip(a, L->start, AST_END_SKIP);
-  v7->pstate.in_strict = L->saved_in_strict;
-  v7->last_var_node = L->outer_last_var_node;
-
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_use_strict(struct v7 *v7, struct ast *a) */
-fid_parse_use_strict :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_use_strict_locals_t)
-{
-  if (v7->cur_tok == TOK_STRING_LITERAL &&
-      (strncmp(v7->tok, "\"use strict\"", v7->tok_len) == 0 ||
-       strncmp(v7->tok, "'use strict'", v7->tok_len) == 0)) {
-    next_tok(v7);
-    add_node(v7, a, AST_USE_STRICT);
-    CR_RETURN_VOID();
-  } else {
-    CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-  }
-}
-
-/*
- * static enum v7_err parse_body(struct v7 *v7, struct ast *a,
- *                               enum v7_tok end)
- */
-fid_parse_body :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_body_locals_t)
-{
-  while (v7->cur_tok != L->arg.end) {
-    if (ACCEPT(TOK_FUNCTION)) {
-      if (v7->cur_tok != TOK_IDENTIFIER) {
-        CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-      }
-      L->start = add_node(v7, a, AST_VAR);
-      ast_modify_skip(a, v7->last_var_node, L->start, AST_FUNC_FIRST_VAR_SKIP);
-      /* zero out var node pointer */
-      ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
-      v7->last_var_node = L->start;
-      add_inlined_node(v7, a, AST_FUNC_DECL, v7->tok, v7->tok_len);
-
-      CALL_PARSE_FUNCDECL(1, 0, fid_p_body_1);
-      ast_set_skip(a, L->start, AST_END_SKIP);
-    } else {
-      CALL_PARSE_STATEMENT(fid_p_body_2);
-    }
-  }
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_statement(struct v7 *v7, struct ast *a) */
-fid_parse_statement :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_statement_locals_t)
-{
-  switch (v7->cur_tok) {
-    case TOK_SEMICOLON:
-      next_tok(v7);
-      /* empty statement */
-      CR_RETURN_VOID();
-    case TOK_OPEN_CURLY: /* block */
-      CALL_PARSE_BLOCK(fid_p_stat_3);
-      /* returning because no semicolon required */
-      CR_RETURN_VOID();
-    case TOK_IF:
-      next_tok(v7);
-      CALL_PARSE_IF(fid_p_stat_4);
-      CR_RETURN_VOID();
-    case TOK_WHILE:
-      next_tok(v7);
-      CALL_PARSE_WHILE(fid_p_stat_5);
-      CR_RETURN_VOID();
-    case TOK_DO:
-      next_tok(v7);
-      CALL_PARSE_DOWHILE(fid_p_stat_10);
-      CR_RETURN_VOID();
-    case TOK_FOR:
-      next_tok(v7);
-      CALL_PARSE_FOR(fid_p_stat_11);
-      CR_RETURN_VOID();
-    case TOK_TRY:
-      next_tok(v7);
-      CALL_PARSE_TRY(fid_p_stat_12);
-      CR_RETURN_VOID();
-    case TOK_SWITCH:
-      next_tok(v7);
-      CALL_PARSE_SWITCH(fid_p_stat_13);
-      CR_RETURN_VOID();
-    case TOK_WITH:
-      next_tok(v7);
-      CALL_PARSE_WITH(fid_p_stat_14);
-      CR_RETURN_VOID();
-    case TOK_BREAK:
-      if (!(v7->pstate.in_loop || v7->pstate.in_switch)) {
-        CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-      }
-      next_tok(v7);
-      PARSE_WITH_OPT_ARG(AST_BREAK, AST_LABELED_BREAK, CALL_PARSE_IDENT,
-                         fid_p_stat_7);
-      break;
-    case TOK_CONTINUE:
-      if (!v7->pstate.in_loop) {
-        CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-      }
-      next_tok(v7);
-      PARSE_WITH_OPT_ARG(AST_CONTINUE, AST_LABELED_CONTINUE, CALL_PARSE_IDENT,
-                         fid_p_stat_8);
-      break;
-    case TOK_RETURN:
-      if (!v7->pstate.in_function) {
-        CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-      }
-      next_tok(v7);
-      PARSE_WITH_OPT_ARG(AST_RETURN, AST_VALUE_RETURN, CALL_PARSE_EXPRESSION,
-                         fid_p_stat_6);
-      break;
-    case TOK_THROW:
-      next_tok(v7);
-      add_node(v7, a, AST_THROW);
-      CALL_PARSE_EXPRESSION(fid_p_stat_2);
-      break;
-    case TOK_DEBUGGER:
-      next_tok(v7);
-      add_node(v7, a, AST_DEBUGGER);
-      break;
-    case TOK_VAR:
-      next_tok(v7);
-      CALL_PARSE_VAR(fid_p_stat_9);
-      break;
-    case TOK_IDENTIFIER:
-      if (lookahead(v7) == TOK_COLON) {
-        add_inlined_node(v7, a, AST_LABEL, v7->tok, v7->tok_len);
-        next_tok(v7);
-        EXPECT(TOK_COLON);
-        CR_RETURN_VOID();
-      }
-    /* fall through */
-    default:
-      CALL_PARSE_EXPRESSION(fid_p_stat_1);
-      break;
-  }
-
-  if (end_of_statement(v7) != V7_OK) {
-    CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-  }
-  ACCEPT(TOK_SEMICOLON); /* swallow optional semicolon */
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_expression(struct v7 *v7, struct ast *a) */
-fid_parse_expression :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_expression_locals_t)
-{
-  L->pos = a->mbuf.len;
-  L->group = 0;
-  while (1) {
-    CALL_PARSE_ASSIGN(fid_p_expr_1);
-    if (ACCEPT(TOK_COMMA)) {
-      L->group = 1;
-    } else {
-      break;
-    }
-  }
-  if (L->group) {
-    insert_node(v7, a, L->pos, AST_SEQ);
-  }
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_assign(struct v7 *v7, struct ast *a) */
-fid_parse_assign :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_assign_locals_t)
-{
-  CALL_PARSE_BINARY(0, a->mbuf.len, fid_p_assign_1);
-  CR_RETURN_VOID();
-}
-
-/*
- * static enum v7_err parse_binary(struct v7 *v7, struct ast *a, int level,
- *                                 ast_off_t pos)
- */
-#if 1
-fid_parse_binary :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_binary_locals_t)
-{
-/*
- * Note: we use macro CUR_POS instead of a local variable, since this
- * function is called really a lot, so, each byte on stack frame counts.
- *
- * It will work a bit slower of course, but slowness is not a problem
- */
-#define CUR_POS ((L->level > L->arg.min_level) ? L->saved_mbuf_len : L->arg.pos)
-  L->saved_mbuf_len = a->mbuf.len;
-
-  CALL_PARSE_PREFIX(fid_p_binary_6);
-
-  for (L->level = (int) ARRAY_SIZE(levels) - 1; L->level >= L->arg.min_level;
-       L->level--) {
-    for (L->i = 0; L->i < levels[L->level].len; L->i++) {
-      L->tok = levels[L->level].parts[L->i].start_tok;
-      L->ast = levels[L->level].parts[L->i].start_ast;
-      do {
-        if (v7->pstate.inhibit_in && L->tok == TOK_IN) {
-          continue;
-        }
-
-        /*
-         * Ternary operator sits in the middle of the binary operator
-         * precedence chain. Deal with it as an exception and don't break
-         * the chain.
-         */
-        if (L->tok == TOK_QUESTION && v7->cur_tok == TOK_QUESTION) {
-          next_tok(v7);
-          CALL_PARSE_ASSIGN(fid_p_binary_2);
-          EXPECT(TOK_COLON);
-          CALL_PARSE_ASSIGN(fid_p_binary_3);
-          insert_node(v7, a, CUR_POS, AST_COND);
-          CR_RETURN_VOID();
-        } else if (ACCEPT(L->tok)) {
-          if (levels[L->level].left_to_right) {
-            insert_node(v7, a, CUR_POS, (enum ast_tag) L->ast);
-            CALL_PARSE_BINARY(L->level, CUR_POS, fid_p_binary_4);
-          } else {
-            CALL_PARSE_BINARY(L->level, a->mbuf.len, fid_p_binary_5);
-            insert_node(v7, a, CUR_POS, (enum ast_tag) L->ast);
-          }
-        }
-      } while (L->ast = (enum ast_tag)(L->ast + 1),
-               L->tok < levels[L->level].parts[L->i].end_tok &&
-                   (L->tok = (enum v7_tok)(L->tok + 1)));
-    }
-  }
-
-  CR_RETURN_VOID();
-#undef CUR_POS
-}
-#endif
-
-/* enum v7_err parse_prefix(struct v7 *v7, struct ast *a) */
-fid_parse_prefix :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_prefix_locals_t)
-{
-  for (;;) {
-    switch (v7->cur_tok) {
-      case TOK_PLUS:
-        next_tok(v7);
-        add_node(v7, a, AST_POSITIVE);
-        break;
-      case TOK_MINUS:
-        next_tok(v7);
-        add_node(v7, a, AST_NEGATIVE);
-        break;
-      case TOK_PLUS_PLUS:
-        next_tok(v7);
-        add_node(v7, a, AST_PREINC);
-        break;
-      case TOK_MINUS_MINUS:
-        next_tok(v7);
-        add_node(v7, a, AST_PREDEC);
-        break;
-      case TOK_TILDA:
-        next_tok(v7);
-        add_node(v7, a, AST_NOT);
-        break;
-      case TOK_NOT:
-        next_tok(v7);
-        add_node(v7, a, AST_LOGICAL_NOT);
-        break;
-      case TOK_VOID:
-        next_tok(v7);
-        add_node(v7, a, AST_VOID);
-        break;
-      case TOK_DELETE:
-        next_tok(v7);
-        add_node(v7, a, AST_DELETE);
-        break;
-      case TOK_TYPEOF:
-        next_tok(v7);
-        add_node(v7, a, AST_TYPEOF);
-        break;
-      default:
-        CALL_PARSE_POSTFIX(fid_p_prefix_1);
-        CR_RETURN_VOID();
-    }
-  }
-}
-
-/* static enum v7_err parse_postfix(struct v7 *v7, struct ast *a) */
-fid_parse_postfix :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_postfix_locals_t)
-{
-  L->pos = a->mbuf.len;
-  CALL_PARSE_CALLEXPR(fid_p_postfix_1);
-
-  if (v7->after_newline) {
-    CR_RETURN_VOID();
-  }
-  switch (v7->cur_tok) {
-    case TOK_PLUS_PLUS:
-      next_tok(v7);
-      insert_node(v7, a, L->pos, AST_POSTINC);
-      break;
-    case TOK_MINUS_MINUS:
-      next_tok(v7);
-      insert_node(v7, a, L->pos, AST_POSTDEC);
-      break;
-    default:
-      break; /* nothing */
-  }
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_callexpr(struct v7 *v7, struct ast *a) */
-fid_parse_callexpr :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_callexpr_locals_t)
-{
-  L->pos = a->mbuf.len;
-  CALL_PARSE_NEWEXPR(fid_p_callexpr_1);
-
-  for (;;) {
-    switch (v7->cur_tok) {
-      case TOK_DOT:
-      case TOK_OPEN_BRACKET:
-        CALL_PARSE_MEMBER(L->pos, fid_p_callexpr_3);
-        break;
-      case TOK_OPEN_PAREN:
-        next_tok(v7);
-        CALL_PARSE_ARGLIST(fid_p_callexpr_2);
-        EXPECT(TOK_CLOSE_PAREN);
-        insert_node(v7, a, L->pos, AST_CALL);
-        break;
-      default:
-        CR_RETURN_VOID();
-    }
-  }
-}
-
-/* static enum v7_err parse_newexpr(struct v7 *v7, struct ast *a) */
-fid_parse_newexpr :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_newexpr_locals_t)
-{
-  switch (v7->cur_tok) {
-    case TOK_NEW:
-      next_tok(v7);
-      L->start = add_node(v7, a, AST_NEW);
-      CALL_PARSE_MEMBEREXPR(fid_p_newexpr_3);
-      if (ACCEPT(TOK_OPEN_PAREN)) {
-        CALL_PARSE_ARGLIST(fid_p_newexpr_4);
-        EXPECT(TOK_CLOSE_PAREN);
-      }
-      ast_set_skip(a, L->start, AST_END_SKIP);
-      break;
-    case TOK_FUNCTION:
-      next_tok(v7);
-      CALL_PARSE_FUNCDECL(0, 0, fid_p_newexpr_2);
-      break;
-    default:
-      CALL_PARSE_TERMINAL(fid_p_newexpr_1);
-      break;
-  }
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_terminal(struct v7 *v7, struct ast *a) */
-fid_parse_terminal :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_terminal_locals_t)
-{
-  switch (v7->cur_tok) {
-    case TOK_OPEN_PAREN:
-      next_tok(v7);
-      CALL_PARSE_EXPRESSION(fid_p_terminal_1);
-      EXPECT(TOK_CLOSE_PAREN);
-      break;
-    case TOK_OPEN_BRACKET:
-      next_tok(v7);
-      L->start = add_node(v7, a, AST_ARRAY);
-      while (v7->cur_tok != TOK_CLOSE_BRACKET) {
-        if (v7->cur_tok == TOK_COMMA) {
-          /* Array literals allow missing elements, e.g. [,,1,] */
-          add_node(v7, a, AST_NOP);
-        } else {
-          CALL_PARSE_ASSIGN(fid_p_terminal_2);
-        }
-        ACCEPT(TOK_COMMA);
-      }
-      EXPECT(TOK_CLOSE_BRACKET);
-      ast_set_skip(a, L->start, AST_END_SKIP);
-      break;
-    case TOK_OPEN_CURLY:
-      next_tok(v7);
-      L->start = add_node(v7, a, AST_OBJECT);
-      if (v7->cur_tok != TOK_CLOSE_CURLY) {
-        do {
-          if (v7->cur_tok == TOK_CLOSE_CURLY) {
-            break;
-          }
-          CALL_PARSE_PROP(fid_p_terminal_3);
-        } while (ACCEPT(TOK_COMMA));
-      }
-      EXPECT(TOK_CLOSE_CURLY);
-      ast_set_skip(a, L->start, AST_END_SKIP);
-      break;
-    case TOK_THIS:
-      next_tok(v7);
-      add_node(v7, a, AST_THIS);
-      break;
-    case TOK_TRUE:
-      next_tok(v7);
-      add_node(v7, a, AST_TRUE);
-      break;
-    case TOK_FALSE:
-      next_tok(v7);
-      add_node(v7, a, AST_FALSE);
-      break;
-    case TOK_NULL:
-      next_tok(v7);
-      add_node(v7, a, AST_NULL);
-      break;
-    case TOK_STRING_LITERAL:
-      add_inlined_node(v7, a, AST_STRING, v7->tok + 1, v7->tok_len - 2);
-      next_tok(v7);
-      break;
-    case TOK_NUMBER:
-      add_inlined_node(v7, a, AST_NUM, v7->tok, v7->tok_len);
-      next_tok(v7);
-      break;
-    case TOK_REGEX_LITERAL:
-      add_inlined_node(v7, a, AST_REGEX, v7->tok, v7->tok_len);
-      next_tok(v7);
-      break;
-    case TOK_IDENTIFIER:
-      if (v7->tok_len == 9 && strncmp(v7->tok, "undefined", v7->tok_len) == 0) {
-        add_node(v7, a, AST_UNDEFINED);
-        next_tok(v7);
-        break;
-      }
-    /* fall through */
-    default:
-      CALL_PARSE_IDENT(fid_p_terminal_4);
-  }
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_block(struct v7 *v7, struct ast *a) */
-fid_parse_block :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_block_locals_t)
-{
-  EXPECT(TOK_OPEN_CURLY);
-  CALL_PARSE_BODY(TOK_CLOSE_CURLY, fid_p_block_1);
-  EXPECT(TOK_CLOSE_CURLY);
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_if(struct v7 *v7, struct ast *a) */
-fid_parse_if :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_if_locals_t)
-{
-  L->start = add_node(v7, a, AST_IF);
-  EXPECT(TOK_OPEN_PAREN);
-  CALL_PARSE_EXPRESSION(fid_p_if_1);
-  EXPECT(TOK_CLOSE_PAREN);
-  CALL_PARSE_STATEMENT(fid_p_if_2);
-  ast_set_skip(a, L->start, AST_END_IF_TRUE_SKIP);
-  if (ACCEPT(TOK_ELSE)) {
-    CALL_PARSE_STATEMENT(fid_p_if_3);
-  }
-  ast_set_skip(a, L->start, AST_END_SKIP);
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_while(struct v7 *v7, struct ast *a) */
-fid_parse_while :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_while_locals_t)
-{
-  L->start = add_node(v7, a, AST_WHILE);
-  L->saved_in_loop = v7->pstate.in_loop;
-  EXPECT(TOK_OPEN_PAREN);
-  CALL_PARSE_EXPRESSION(fid_p_while_1);
-  EXPECT(TOK_CLOSE_PAREN);
-  v7->pstate.in_loop = 1;
-  CALL_PARSE_STATEMENT(fid_p_while_2);
-  ast_set_skip(a, L->start, AST_END_SKIP);
-  v7->pstate.in_loop = L->saved_in_loop;
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_ident(struct v7 *v7, struct ast *a) */
-fid_parse_ident :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_ident_locals_t)
-{
-  if (v7->cur_tok == TOK_IDENTIFIER) {
-    add_inlined_node(v7, a, AST_IDENT, v7->tok, v7->tok_len);
-    next_tok(v7);
-    CR_RETURN_VOID();
-  }
-  CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-}
-
-/*
- * static enum v7_err parse_ident_allow_reserved_words(struct v7 *v7,
- *                                                     struct ast *a)
- *
- */
-fid_parse_ident_allow_reserved_words :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_ident_allow_reserved_words_locals_t)
-{
-  /* Allow reserved words as property names. */
-  if (is_reserved_word_token(v7->cur_tok)) {
-    add_inlined_node(v7, a, AST_IDENT, v7->tok, v7->tok_len);
-    next_tok(v7);
-  } else {
-    CALL_PARSE_IDENT(fid_p_ident_arw_1);
-  }
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_funcdecl(struct v7 *, struct ast *, int, int) */
-fid_parse_funcdecl :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_funcdecl_locals_t)
-{
-  L->start = add_node(v7, a, AST_FUNC);
-  L->outer_last_var_node = v7->last_var_node;
-  L->saved_in_function = v7->pstate.in_function;
-  L->saved_in_strict = v7->pstate.in_strict;
-
-  v7->last_var_node = L->start;
-  ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
-
-  CR_TRY(fid_p_funcdecl_2);
-  {
-    if (L->arg.reserved_name) {
-      CALL_PARSE_IDENT_ALLOW_RESERVED_WORDS(fid_p_funcdecl_1);
-    } else {
-      CALL_PARSE_IDENT(fid_p_funcdecl_9);
-    }
-  }
-  CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_funcdecl_2, fid_p_funcdecl_3);
-  {
-    if (L->arg.require_named) {
-      /* function name is required, so, rethrow SYNTAX ERROR */
-      CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-    } else {
-      /* it's ok not to have a function name, just insert NOP */
-      add_node(v7, a, AST_NOP);
-    }
-  }
-  CR_ENDCATCH(fid_p_funcdecl_3);
-
-  EXPECT(TOK_OPEN_PAREN);
-  CALL_PARSE_ARGLIST(fid_p_funcdecl_4);
-  EXPECT(TOK_CLOSE_PAREN);
-  ast_set_skip(a, L->start, AST_FUNC_BODY_SKIP);
-  v7->pstate.in_function = 1;
-  EXPECT(TOK_OPEN_CURLY);
-
-  CR_TRY(fid_p_funcdecl_5);
-  {
-    CALL_PARSE_USE_STRICT(fid_p_funcdecl_7);
-    v7->pstate.in_strict = 1;
-  }
-  CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_funcdecl_5, fid_p_funcdecl_6);
-  CR_ENDCATCH(fid_p_funcdecl_6);
-
-  CALL_PARSE_BODY(TOK_CLOSE_CURLY, fid_p_funcdecl_8);
-  EXPECT(TOK_CLOSE_CURLY);
-  v7->pstate.in_strict = L->saved_in_strict;
-  v7->pstate.in_function = L->saved_in_function;
-  ast_set_skip(a, L->start, AST_END_SKIP);
-  v7->last_var_node = L->outer_last_var_node;
-
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_arglist(struct v7 *v7, struct ast *a) */
-fid_parse_arglist :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_arglist_locals_t)
-{
-  if (v7->cur_tok != TOK_CLOSE_PAREN) {
-    do {
-      CALL_PARSE_ASSIGN(fid_p_arglist_1);
-    } while (ACCEPT(TOK_COMMA));
-  }
-  CR_RETURN_VOID();
-}
-
-/*
- * static enum v7_err parse_member(struct v7 *v7, struct ast *a, ast_off_t pos)
- */
-fid_parse_member :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_member_locals_t)
-{
-  switch (v7->cur_tok) {
-    case TOK_DOT:
-      next_tok(v7);
-      /* Allow reserved words as member identifiers */
-      if (is_reserved_word_token(v7->cur_tok) ||
-          v7->cur_tok == TOK_IDENTIFIER) {
-        insert_inlined_node(v7, a, L->arg.pos, AST_MEMBER, v7->tok,
-                            v7->tok_len);
-        next_tok(v7);
-      } else {
-        CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-      }
-      break;
-    case TOK_OPEN_BRACKET:
-      next_tok(v7);
-      CALL_PARSE_EXPRESSION(fid_p_member_1);
-      EXPECT(TOK_CLOSE_BRACKET);
-      insert_node(v7, a, L->arg.pos, AST_INDEX);
-      break;
-    default:
-      CR_RETURN_VOID();
-  }
-  /* not necessary, but let it be anyway */
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_memberexpr(struct v7 *v7, struct ast *a) */
-fid_parse_memberexpr :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_memberexpr_locals_t)
-{
-  L->pos = a->mbuf.len;
-  CALL_PARSE_NEWEXPR(fid_p_memberexpr_1);
-
-  for (;;) {
-    switch (v7->cur_tok) {
-      case TOK_DOT:
-      case TOK_OPEN_BRACKET:
-        CALL_PARSE_MEMBER(L->pos, fid_p_memberexpr_2);
-        break;
-      default:
-        CR_RETURN_VOID();
-    }
-  }
-}
-
-/* static enum v7_err parse_var(struct v7 *v7, struct ast *a) */
-fid_parse_var :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_var_locals_t)
-{
-  L->start = add_node(v7, a, AST_VAR);
-  ast_modify_skip(a, v7->last_var_node, L->start, AST_FUNC_FIRST_VAR_SKIP);
-  /* zero out var node pointer */
-  ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
-  v7->last_var_node = L->start;
-  do {
-    add_inlined_node(v7, a, AST_VAR_DECL, v7->tok, v7->tok_len);
-    EXPECT(TOK_IDENTIFIER);
-    if (ACCEPT(TOK_ASSIGN)) {
-      CALL_PARSE_ASSIGN(fid_p_var_1);
-    } else {
-      add_node(v7, a, AST_NOP);
-    }
-  } while (ACCEPT(TOK_COMMA));
-  ast_set_skip(a, L->start, AST_END_SKIP);
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_prop(struct v7 *v7, struct ast *a) */
-fid_parse_prop :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_prop_locals_t)
-{
-#ifdef V7_ENABLE_JS_GETTERS
-  if (v7->cur_tok == TOK_IDENTIFIER && v7->tok_len == 3 &&
-      strncmp(v7->tok, "get", v7->tok_len) == 0 && lookahead(v7) != TOK_COLON) {
-    next_tok(v7);
-    add_node(v7, a, AST_GETTER);
-    CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_1_getter);
-  } else
-#endif
-      if (v7->cur_tok == TOK_IDENTIFIER && lookahead(v7) == TOK_OPEN_PAREN) {
-    /* ecmascript 6 feature */
-    CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_2);
-#ifdef V7_ENABLE_JS_SETTERS
-  } else if (v7->cur_tok == TOK_IDENTIFIER && v7->tok_len == 3 &&
-             strncmp(v7->tok, "set", v7->tok_len) == 0 &&
-             lookahead(v7) != TOK_COLON) {
-    next_tok(v7);
-    add_node(v7, a, AST_SETTER);
-    CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_3_setter);
-#endif
-  } else {
-    /* Allow reserved words as property names. */
-    if (is_reserved_word_token(v7->cur_tok) || v7->cur_tok == TOK_IDENTIFIER ||
-        v7->cur_tok == TOK_NUMBER) {
-      add_inlined_node(v7, a, AST_PROP, v7->tok, v7->tok_len);
-    } else if (v7->cur_tok == TOK_STRING_LITERAL) {
-      add_inlined_node(v7, a, AST_PROP, v7->tok + 1, v7->tok_len - 2);
-    } else {
-      CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-    }
-    next_tok(v7);
-    EXPECT(TOK_COLON);
-    CALL_PARSE_ASSIGN(fid_p_prop_4);
-  }
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_dowhile(struct v7 *v7, struct ast *a) */
-fid_parse_dowhile :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_dowhile_locals_t)
-{
-  L->start = add_node(v7, a, AST_DOWHILE);
-  L->saved_in_loop = v7->pstate.in_loop;
-
-  v7->pstate.in_loop = 1;
-  CALL_PARSE_STATEMENT(fid_p_dowhile_1);
-  v7->pstate.in_loop = L->saved_in_loop;
-  ast_set_skip(a, L->start, AST_DO_WHILE_COND_SKIP);
-  EXPECT(TOK_WHILE);
-  EXPECT(TOK_OPEN_PAREN);
-  CALL_PARSE_EXPRESSION(fid_p_dowhile_2);
-  EXPECT(TOK_CLOSE_PAREN);
-  ast_set_skip(a, L->start, AST_END_SKIP);
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_for(struct v7 *v7, struct ast *a) */
-fid_parse_for :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_for_locals_t)
-{
-  /* TODO(mkm): for of, for each in */
-  /*
-  ast_off_t start;
-  int saved_in_loop;
-  */
-
-  L->start = add_node(v7, a, AST_FOR);
-  L->saved_in_loop = v7->pstate.in_loop;
-
-  EXPECT(TOK_OPEN_PAREN);
-
-  if (parse_optional(v7, a, TOK_SEMICOLON)) {
-    /*
-     * TODO(mkm): make this reentrant otherwise this pearl won't parse:
-     * for((function(){return 1 in o.a ? o : x})().a in [1,2,3])
-     */
-    v7->pstate.inhibit_in = 1;
-    if (ACCEPT(TOK_VAR)) {
-      CALL_PARSE_VAR(fid_p_for_1);
-    } else {
-      CALL_PARSE_EXPRESSION(fid_p_for_2);
-    }
-    v7->pstate.inhibit_in = 0;
-
-    if (ACCEPT(TOK_IN)) {
-      CALL_PARSE_EXPRESSION(fid_p_for_3);
-      add_node(v7, a, AST_NOP);
-      /*
-       * Assumes that for and for in have the same AST format which is
-       * suboptimal but avoids the need of fixing up the var offset chain.
-       * TODO(mkm) improve this
-       */
-      ast_modify_tag(a, L->start - 1, AST_FOR_IN);
-      goto for_loop_body;
-    }
-  }
-
-  EXPECT(TOK_SEMICOLON);
-  if (parse_optional(v7, a, TOK_SEMICOLON)) {
-    CALL_PARSE_EXPRESSION(fid_p_for_4);
-  }
-  EXPECT(TOK_SEMICOLON);
-  if (parse_optional(v7, a, TOK_CLOSE_PAREN)) {
-    CALL_PARSE_EXPRESSION(fid_p_for_5);
-  }
-
-for_loop_body:
-  EXPECT(TOK_CLOSE_PAREN);
-  ast_set_skip(a, L->start, AST_FOR_BODY_SKIP);
-  v7->pstate.in_loop = 1;
-  CALL_PARSE_STATEMENT(fid_p_for_6);
-  v7->pstate.in_loop = L->saved_in_loop;
-  ast_set_skip(a, L->start, AST_END_SKIP);
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_try(struct v7 *v7, struct ast *a) */
-fid_parse_try :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_try_locals_t)
-{
-  L->start = add_node(v7, a, AST_TRY);
-  L->catch_or_finally = 0;
-  CALL_PARSE_BLOCK(fid_p_try_1);
-  ast_set_skip(a, L->start, AST_TRY_CATCH_SKIP);
-  if (ACCEPT(TOK_CATCH)) {
-    L->catch_or_finally = 1;
-    EXPECT(TOK_OPEN_PAREN);
-    CALL_PARSE_IDENT(fid_p_try_2);
-    EXPECT(TOK_CLOSE_PAREN);
-    CALL_PARSE_BLOCK(fid_p_try_3);
-  }
-  ast_set_skip(a, L->start, AST_TRY_FINALLY_SKIP);
-  if (ACCEPT(TOK_FINALLY)) {
-    L->catch_or_finally = 1;
-    CALL_PARSE_BLOCK(fid_p_try_4);
-  }
-  ast_set_skip(a, L->start, AST_END_SKIP);
-
-  /* make sure `catch` and `finally` aren't both missing */
-  if (!L->catch_or_finally) {
-    CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-  }
-
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_switch(struct v7 *v7, struct ast *a) */
-fid_parse_switch :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_switch_locals_t)
-{
-  L->start = add_node(v7, a, AST_SWITCH);
-  L->saved_in_switch = v7->pstate.in_switch;
-
-  ast_set_skip(a, L->start, AST_SWITCH_DEFAULT_SKIP); /* clear out */
-  EXPECT(TOK_OPEN_PAREN);
-  CALL_PARSE_EXPRESSION(fid_p_switch_1);
-  EXPECT(TOK_CLOSE_PAREN);
-  EXPECT(TOK_OPEN_CURLY);
-  v7->pstate.in_switch = 1;
-  while (v7->cur_tok != TOK_CLOSE_CURLY) {
-    switch (v7->cur_tok) {
-      case TOK_CASE:
-        next_tok(v7);
-        L->case_start = add_node(v7, a, AST_CASE);
-        CALL_PARSE_EXPRESSION(fid_p_switch_2);
-        EXPECT(TOK_COLON);
-        while (v7->cur_tok != TOK_CASE && v7->cur_tok != TOK_DEFAULT &&
-               v7->cur_tok != TOK_CLOSE_CURLY) {
-          CALL_PARSE_STATEMENT(fid_p_switch_3);
-        }
-        ast_set_skip(a, L->case_start, AST_END_SKIP);
-        break;
-      case TOK_DEFAULT:
-        next_tok(v7);
-        EXPECT(TOK_COLON);
-        ast_set_skip(a, L->start, AST_SWITCH_DEFAULT_SKIP);
-        L->case_start = add_node(v7, a, AST_DEFAULT);
-        while (v7->cur_tok != TOK_CASE && v7->cur_tok != TOK_DEFAULT &&
-               v7->cur_tok != TOK_CLOSE_CURLY) {
-          CALL_PARSE_STATEMENT(fid_p_switch_4);
-        }
-        ast_set_skip(a, L->case_start, AST_END_SKIP);
-        break;
-      default:
-        CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-    }
-  }
-  EXPECT(TOK_CLOSE_CURLY);
-  ast_set_skip(a, L->start, AST_END_SKIP);
-  v7->pstate.in_switch = L->saved_in_switch;
-  CR_RETURN_VOID();
-}
-
-/* static enum v7_err parse_with(struct v7 *v7, struct ast *a) */
-fid_parse_with :
-#undef L
-#define L CR_CUR_LOCALS_PT(fid_parse_with_locals_t)
-{
-  L->start = add_node(v7, a, AST_WITH);
-  if (v7->pstate.in_strict) {
-    CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
-  }
-  EXPECT(TOK_OPEN_PAREN);
-  CALL_PARSE_EXPRESSION(fid_p_with_1);
-  EXPECT(TOK_CLOSE_PAREN);
-  CALL_PARSE_STATEMENT(fid_p_with_2);
-  ast_set_skip(a, L->start, AST_END_SKIP);
-  CR_RETURN_VOID();
-}
-
-fid_none:
-  /* stack is empty, so we're done; return */
-  return rc;
-}
-
-V7_PRIVATE enum v7_err parse(struct v7 *v7, struct ast *a, const char *src,
-                             size_t src_len, int is_json) {
-  enum v7_err rcode;
-  const char *error_msg = NULL;
-  const char *p;
-  struct cr_ctx cr_ctx;
-  union user_arg_ret arg_retval;
-  enum cr_status rc;
-#if defined(V7_ENABLE_STACK_TRACKING)
-  struct stack_track_ctx stack_track_ctx;
-#endif
-  int saved_line_no = v7->line_no;
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-  v7_stack_track_start(v7, &stack_track_ctx);
-#endif
-
-  v7->pstate.source_code = v7->pstate.pc = src;
-  v7->pstate.src_end = src + src_len;
-  v7->pstate.file_name = "<stdin>";
-  v7->pstate.line_no = 1;
-  v7->pstate.in_function = 0;
-  v7->pstate.in_loop = 0;
-  v7->pstate.in_switch = 0;
-
-  /*
-   * TODO(dfrank): `v7->parser.line_no` vs `v7->line_no` is confusing.  probaby
-   * we need to refactor it.
-   *
-   * See comment for v7->line_no in core.h for some details.
-   */
-  v7->line_no = 1;
-
-  next_tok(v7);
-  /*
-   * setup initial state for "after newline" tracking.
-   * next_tok will consume our token and position the current line
-   * position at the beginning of the next token.
-   * While processing the first token, both the leading and the
-   * trailing newlines will be counted and thus it will create a spurious
-   * "after newline" condition at the end of the first token
-   * regardless if there is actually a newline after it.
-   */
-  for (p = src; isspace((int) *p); p++) {
-    if (*p == '\n') {
-      v7->pstate.prev_line_no++;
-    }
-  }
-
-  /* init cr context */
-  cr_context_init(&cr_ctx, &arg_retval, sizeof(arg_retval), _fid_descrs);
-
-  /* prepare first function call: fid_mul_sum */
-  if (is_json) {
-    CR_FIRST_CALL_PREPARE_C(&cr_ctx, fid_parse_terminal);
-  } else {
-    CR_FIRST_CALL_PREPARE_C(&cr_ctx, fid_parse_script);
-  }
-
-  /* proceed to coroutine execution */
-  rc = parser_cr_exec(&cr_ctx, v7, a);
-
-  /* set `rcode` depending on coroutine state */
-  switch (rc) {
-    case CR_RES__OK:
-      rcode = V7_OK;
-      break;
-    case CR_RES__ERR_UNCAUGHT_EXCEPTION:
-      switch ((enum parser_exc_id) CR_THROWN_C(&cr_ctx)) {
-        case PARSER_EXC_ID__SYNTAX_ERROR:
-          rcode = V7_SYNTAX_ERROR;
-          error_msg = "Syntax error";
-          break;
-
-        default:
-          rcode = V7_INTERNAL_ERROR;
-          error_msg = "Internal error: no exception id set";
-          break;
-      }
-      break;
-    default:
-      rcode = V7_INTERNAL_ERROR;
-      error_msg = "Internal error: unexpected parser coroutine return code";
-      break;
-  }
-
-#if defined(V7_TRACK_MAX_PARSER_STACK_SIZE)
-  /* remember how much stack space was consumed */
-
-  if (v7->parser_stack_data_max_size < cr_ctx.stack_data.size) {
-    v7->parser_stack_data_max_size = cr_ctx.stack_data.size;
-#ifndef NO_LIBC
-    printf("parser_stack_data_max_size=%u\n",
-           (unsigned int) v7->parser_stack_data_max_size);
-#endif
-  }
-
-  if (v7->parser_stack_ret_max_size < cr_ctx.stack_ret.size) {
-    v7->parser_stack_ret_max_size = cr_ctx.stack_ret.size;
-#ifndef NO_LIBC
-    printf("parser_stack_ret_max_size=%u\n",
-           (unsigned int) v7->parser_stack_ret_max_size);
-#endif
-  }
-
-#if defined(CR_TRACK_MAX_STACK_LEN)
-  if (v7->parser_stack_data_max_len < cr_ctx.stack_data_max_len) {
-    v7->parser_stack_data_max_len = cr_ctx.stack_data_max_len;
-#ifndef NO_LIBC
-    printf("parser_stack_data_max_len=%u\n",
-           (unsigned int) v7->parser_stack_data_max_len);
-#endif
-  }
-
-  if (v7->parser_stack_ret_max_len < cr_ctx.stack_ret_max_len) {
-    v7->parser_stack_ret_max_len = cr_ctx.stack_ret_max_len;
-#ifndef NO_LIBC
-    printf("parser_stack_ret_max_len=%u\n",
-           (unsigned int) v7->parser_stack_ret_max_len);
-#endif
-  }
-#endif
-
-#endif
-
-  /* free resources occupied by context (at least, "stack" arrays) */
-  cr_context_free(&cr_ctx);
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-  {
-    int diff = v7_stack_track_end(v7, &stack_track_ctx);
-    if (diff > v7->stack_stat[V7_STACK_STAT_PARSER]) {
-      v7->stack_stat[V7_STACK_STAT_PARSER] = diff;
-    }
-  }
-#endif
-
-  /* Check if AST was overflown */
-  if (a->has_overflow) {
-    rcode = v7_throwf(v7, SYNTAX_ERROR,
-                      "Script too large (try V7_LARGE_AST build option)");
-    V7_THROW(V7_AST_TOO_LARGE);
-  }
-
-  if (rcode == V7_OK && v7->cur_tok != TOK_END_OF_INPUT) {
-    rcode = V7_SYNTAX_ERROR;
-    error_msg = "Syntax error";
-  }
-
-  if (rcode != V7_OK) {
-    unsigned long col = get_column(v7->pstate.source_code, v7->tok);
-    int line_len = 0;
-
-    assert(error_msg != NULL);
-
-    for (p = v7->tok - col; p < v7->pstate.src_end && *p != '\0' && *p != '\n';
-         p++) {
-      line_len++;
-    }
-
-    /* fixup line number: line_no points to the beginning of the next token */
-    for (; p < v7->pstate.pc; p++) {
-      if (*p == '\n') {
-        v7->pstate.line_no--;
-      }
-    }
-
-    /*
-     * We already have a proper `rcode`, that's why we discard returned value
-     * of `v7_throwf()`, which is always `V7_EXEC_EXCEPTION`.
-     *
-     * TODO(dfrank): probably get rid of distinct error types, and use just
-     * `V7_JS_EXCEPTION`. However it would be good to have a way to get exact
-     * error type, so probably error object should contain some property with
-     * error code, but it would make exceptions even more expensive, etc, etc.
-     */
-    {
-      enum v7_err _tmp;
-      _tmp = v7_throwf(v7, SYNTAX_ERROR, "%s at line %d col %lu:\n%.*s\n%*s^",
-                       error_msg, v7->pstate.line_no, col, line_len,
-                       v7->tok - col, (int) col - 1, "");
-      (void) _tmp;
-    }
-    V7_THROW(rcode);
-  }
-
-clean:
-  v7->line_no = saved_line_no;
-  return rcode;
-}
-
-#endif /* V7_NO_COMPILER */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/compiler.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/compiler.h" */
-/* Amalgamated: #include "v7/src/std_error.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/regexp.h" */
-
-#if !defined(V7_NO_COMPILER)
-
-/*
- * The bytecode compiler takes an AST as input and produces one or more
- * bcode structure as output.
- *
- * Each script or function body is compiled into it's own bcode structure.
- *
- * Each bcode stream produces a new value on the stack, i.e. its overall
- * stack diagram is: `( -- a)`
- *
- * This value will be then popped by the function caller or by v7_exec in case
- * of scripts.
- *
- * In JS, the value of a script is the value of the last statement.
- * A script with no statement has an `undefined` value.
- * Functions instead require an explicit return value, so this matters only
- * for `v7_exec` and JS `eval`.
- *
- * Since an empty script has an undefined value, and each script has to
- * yield a value, the script/function prologue consists of a PUSH_UNDEFINED.
- *
- * Each statement will be compiled to push a value on the stack.
- * When a statement begins evaluating, the current TOS is thus either
- * the value of the previous statement or `undefined` in case of the first
- * statement.
- *
- * Every statement of a given script/function body always evaluates at the same
- * stack depth.
- *
- * In order to achieve that, after a statement is compiled out, a SWAP_DROP
- * opcode is emitted, that drops the value of the previous statement (or the
- * initial `undefined`). Dropping the value after the next statement is
- * evaluated and not before has allows us to correctly implement exception
- * behaviour and the break statement.
- *
- * Compound statements are constructs such as `if`/`while`/`for`/`try`. These
- * constructs contain a body consisting of a possibly empty statement list.
- *
- * Unlike normal statements, compound statements don't produce a value
- * themselves. Their value is either the value of their last executed statement
- * in their body, or the previous statement in case their body is empty or not
- * evaluated at all.
- *
- * An example is:
- *
- * [source,js]
- * ----
- * try {
- *   42;
- *   someUnexistingVariable;
- * } catch(e) {
- *   while(true) {}
- *     if(true) {
- *     }
- *     if(false) {
- *       2;
- *     }
- *     break;
- *   }
- * }
- * ----
- */
-
-static const enum ast_tag assign_ast_map[] = {
-    AST_REM, AST_MUL, AST_DIV,    AST_XOR,    AST_ADD,    AST_SUB,
-    AST_OR,  AST_AND, AST_LSHIFT, AST_RSHIFT, AST_URSHIFT};
-
-#ifdef V7_BCODE_DUMP
-extern void dump_bcode(struct v7 *v7, FILE *f, struct bcode *bcode);
-#endif
-
-V7_PRIVATE enum v7_err compile_expr_builder(struct bcode_builder *bbuilder,
-                                            struct ast *a, ast_off_t *ppos);
-
-V7_PRIVATE enum v7_err compile_function(struct v7 *v7, struct ast *a,
-                                        ast_off_t *ppos, struct bcode *bcode);
-
-V7_PRIVATE enum v7_err binary_op(struct bcode_builder *bbuilder,
-                                 enum ast_tag tag) {
-  uint8_t op;
-  enum v7_err rcode = V7_OK;
-  struct v7 *v7 = bbuilder->v7;
-
-  switch (tag) {
-    case AST_ADD:
-      op = OP_ADD;
-      break;
-    case AST_SUB:
-      op = OP_SUB;
-      break;
-    case AST_REM:
-      op = OP_REM;
-      break;
-    case AST_MUL:
-      op = OP_MUL;
-      break;
-    case AST_DIV:
-      op = OP_DIV;
-      break;
-    case AST_LSHIFT:
-      op = OP_LSHIFT;
-      break;
-    case AST_RSHIFT:
-      op = OP_RSHIFT;
-      break;
-    case AST_URSHIFT:
-      op = OP_URSHIFT;
-      break;
-    case AST_OR:
-      op = OP_OR;
-      break;
-    case AST_XOR:
-      op = OP_XOR;
-      break;
-    case AST_AND:
-      op = OP_AND;
-      break;
-    case AST_EQ_EQ:
-      op = OP_EQ_EQ;
-      break;
-    case AST_EQ:
-      op = OP_EQ;
-      break;
-    case AST_NE:
-      op = OP_NE;
-      break;
-    case AST_NE_NE:
-      op = OP_NE_NE;
-      break;
-    case AST_LT:
-      op = OP_LT;
-      break;
-    case AST_LE:
-      op = OP_LE;
-      break;
-    case AST_GT:
-      op = OP_GT;
-      break;
-    case AST_GE:
-      op = OP_GE;
-      break;
-    case AST_INSTANCEOF:
-      op = OP_INSTANCEOF;
-      break;
-    default:
-      rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "unknown binary ast node");
-      V7_THROW(V7_SYNTAX_ERROR);
-  }
-  bcode_op(bbuilder, op);
-clean:
-  return rcode;
-}
-
-V7_PRIVATE enum v7_err compile_binary(struct bcode_builder *bbuilder,
-                                      struct ast *a, ast_off_t *ppos,
-                                      enum ast_tag tag) {
-  enum v7_err rcode = V7_OK;
-  struct v7 *v7 = bbuilder->v7;
-  V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-  V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-
-  V7_TRY(binary_op(bbuilder, tag));
-clean:
-  return rcode;
-}
-
-/*
- * `pos` should be an offset of the byte right after a tag
- */
-static lit_t string_lit(struct bcode_builder *bbuilder, struct ast *a,
-                        ast_off_t pos) {
-  size_t i = 0, name_len;
-  val_t v = V7_UNDEFINED;
-  struct mbuf *m = &bbuilder->lit;
-  char *name = ast_get_inlined_data(a, pos, &name_len);
-
-/* temp disabled because of short lits */
-#if 0
-  for (i = 0; i < m->len / sizeof(val_t); i++) {
-    v = ((val_t *) m->buf)[i];
-    if (v7_is_string(v)) {
-      size_t l;
-      const char *s = v7_get_string(bbuilder->v7, &v, &l);
-      if (name_len == l && memcmp(name, s, name_len) == 0) {
-        lit_t res;
-        memset(&res, 0, sizeof(res));
-        res.idx = i + bcode_max_inline_type_tag;
-        return res;
-      }
-    }
-  }
-#else
-  (void) i;
-  (void) v;
-  (void) m;
-#endif
-  return bcode_add_lit(bbuilder, v7_mk_string(bbuilder->v7, name, name_len, 1));
-}
-
-#if V7_ENABLE__RegExp
-WARN_UNUSED_RESULT
-static enum v7_err regexp_lit(struct bcode_builder *bbuilder, struct ast *a,
-                              ast_off_t pos, lit_t *res) {
-  enum v7_err rcode = V7_OK;
-  size_t name_len;
-  char *p;
-  char *name = ast_get_inlined_data(a, pos, &name_len);
-  val_t tmp = V7_UNDEFINED;
-  struct v7 *v7 = bbuilder->v7;
-
-  for (p = name + name_len - 1; *p != '/';) p--;
-
-  V7_TRY(v7_mk_regexp(bbuilder->v7, name + 1, p - (name + 1), p + 1,
-                      (name + name_len) - p - 1, &tmp));
-
-  *res = bcode_add_lit(bbuilder, tmp);
-
-clean:
-  return rcode;
-}
-#endif
-
-#ifndef V7_DISABLE_LINE_NUMBERS
-static void append_lineno_if_changed(struct v7 *v7,
-                                     struct bcode_builder *bbuilder,
-                                     int line_no) {
-  (void) v7;
-  if (line_no != 0 && line_no != v7->line_no) {
-    v7->line_no = line_no;
-    bcode_append_lineno(bbuilder, line_no);
-  }
-}
-#else
-static void append_lineno_if_changed(struct v7 *v7,
-                                     struct bcode_builder *bbuilder,
-                                     int line_no) {
-  (void) v7;
-  (void) bbuilder;
-  (void) line_no;
-}
-#endif
-
-static enum ast_tag fetch_tag(struct v7 *v7, struct bcode_builder *bbuilder,
-                              struct ast *a, ast_off_t *ppos,
-                              ast_off_t *ppos_after_tag) {
-  enum ast_tag ret = ast_fetch_tag(a, ppos);
-  int line_no = ast_get_line_no(a, *ppos);
-  append_lineno_if_changed(v7, bbuilder, line_no);
-  if (ppos_after_tag != NULL) {
-    *ppos_after_tag = *ppos;
-  }
-  ast_move_to_children(a, ppos);
-  return ret;
-}
-
-/*
- * a++ and a-- need to ignore the updated value.
- *
- * Call this before updating the lhs.
- */
-static void fixup_post_op(struct bcode_builder *bbuilder, enum ast_tag tag) {
-  if (tag == AST_POSTINC || tag == AST_POSTDEC) {
-    bcode_op(bbuilder, OP_UNSTASH);
-  }
-}
-
-/*
- * evaluate rhs expression.
- * ++a and a++ are equivalent to a+=1
- */
-static enum v7_err eval_assign_rhs(struct bcode_builder *bbuilder,
-                                   struct ast *a, ast_off_t *ppos,
-                                   enum ast_tag tag) {
-  enum v7_err rcode = V7_OK;
-  struct v7 *v7 = bbuilder->v7;
-
-  /* a++ and a-- need to preserve initial value. */
-  if (tag == AST_POSTINC || tag == AST_POSTDEC) {
-    bcode_op(bbuilder, OP_STASH);
-  }
-  if (tag >= AST_PREINC && tag <= AST_POSTDEC) {
-    bcode_op(bbuilder, OP_PUSH_ONE);
-  } else {
-    V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-  }
-
-  switch (tag) {
-    case AST_PREINC:
-    case AST_POSTINC:
-      bcode_op(bbuilder, OP_ADD);
-      break;
-    case AST_PREDEC:
-    case AST_POSTDEC:
-      bcode_op(bbuilder, OP_SUB);
-      break;
-    case AST_ASSIGN:
-      /* no operation */
-      break;
-    default:
-      binary_op(bbuilder, assign_ast_map[tag - AST_ASSIGN - 1]);
-  }
-
-clean:
-  return rcode;
-}
-
-static enum v7_err compile_assign(struct bcode_builder *bbuilder, struct ast *a,
-                                  ast_off_t *ppos, enum ast_tag tag) {
-  lit_t lit;
-  enum ast_tag ntag;
-  enum v7_err rcode = V7_OK;
-  struct v7 *v7 = bbuilder->v7;
-  ast_off_t pos_after_tag;
-
-  ntag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-
-  switch (ntag) {
-    case AST_IDENT:
-      lit = string_lit(bbuilder, a, pos_after_tag);
-      if (tag != AST_ASSIGN) {
-        bcode_op_lit(bbuilder, OP_GET_VAR, lit);
-      }
-
-      V7_TRY(eval_assign_rhs(bbuilder, a, ppos, tag));
-      bcode_op_lit(bbuilder, OP_SET_VAR, lit);
-
-      fixup_post_op(bbuilder, tag);
-      break;
-    case AST_MEMBER:
-    case AST_INDEX:
-      switch (ntag) {
-        case AST_MEMBER:
-          lit = string_lit(bbuilder, a, pos_after_tag);
-          V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-          bcode_push_lit(bbuilder, lit);
-          break;
-        case AST_INDEX:
-          V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-          V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-          break;
-        default:
-          /* unreachable, compilers are dumb */
-          V7_THROW(V7_SYNTAX_ERROR);
-      }
-      if (tag != AST_ASSIGN) {
-        bcode_op(bbuilder, OP_2DUP);
-        bcode_op(bbuilder, OP_GET);
-      }
-
-      V7_TRY(eval_assign_rhs(bbuilder, a, ppos, tag));
-      bcode_op(bbuilder, OP_SET);
-
-      fixup_post_op(bbuilder, tag);
-      break;
-    default:
-      /* We end up here on expressions like `1 = 2;`, it's a ReferenceError */
-      rcode = v7_throwf(bbuilder->v7, REFERENCE_ERROR, "unexpected ast node");
-      V7_THROW(V7_SYNTAX_ERROR);
-  }
-clean:
-  return rcode;
-}
-
-/*
- * Walks through all declarations (`var` and `function`) in the current scope,
- * and adds names of all of them to `bcode->ops`. Additionally, `function`
- * declarations are compiled right here, since they're hoisted in JS.
- */
-static enum v7_err compile_local_vars(struct bcode_builder *bbuilder,
-                                      struct ast *a, ast_off_t start,
-                                      ast_off_t fvar) {
-  ast_off_t next, fvar_end;
-  char *name;
-  size_t name_len;
-  lit_t lit;
-  enum v7_err rcode = V7_OK;
-  struct v7 *v7 = bbuilder->v7;
-  size_t names_end = 0;
-  ast_off_t pos_after_tag;
-
-  /* calculate `names_end`: offset at which names in `bcode->ops` end */
-  names_end =
-      (size_t)(bcode_end_names(bbuilder->ops.buf, bbuilder->bcode->names_cnt) -
-               bbuilder->ops.buf);
-
-  if (fvar != start) {
-    /* iterate all `AST_VAR`s in the current scope */
-    do {
-      V7_CHECK_INTERNAL(fetch_tag(v7, bbuilder, a, &fvar, &pos_after_tag) ==
-                        AST_VAR);
-
-      next = ast_get_skip(a, pos_after_tag, AST_VAR_NEXT_SKIP);
-      if (next == pos_after_tag) {
-        next = 0;
-      }
-
-      fvar_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-
-      /*
-       * iterate all `AST_VAR_DECL`s and `AST_FUNC_DECL`s in the current
-       * `AST_VAR`
-       */
-      while (fvar < fvar_end) {
-        enum ast_tag tag = fetch_tag(v7, bbuilder, a, &fvar, &pos_after_tag);
-        V7_CHECK_INTERNAL(tag == AST_VAR_DECL || tag == AST_FUNC_DECL);
-        name = ast_get_inlined_data(a, pos_after_tag, &name_len);
-        if (tag == AST_VAR_DECL) {
-          /*
-           * it's a `var` declaration, so, skip the value for now, it'll be set
-           * to `undefined` initially
-           */
-          ast_skip_tree(a, &fvar);
-        } else {
-          /*
-           * tag is an AST_FUNC_DECL: since functions in JS are hoisted,
-           * we compile it and put `OP_SET_VAR` directly here
-           */
-          lit = string_lit(bbuilder, a, pos_after_tag);
-          V7_TRY(compile_expr_builder(bbuilder, a, &fvar));
-          bcode_op_lit(bbuilder, OP_SET_VAR, lit);
-
-          /* function declarations are stack-neutral */
-          bcode_op(bbuilder, OP_DROP);
-          /*
-           * Note: the `is_stack_neutral` flag will be set by `compile_stmt`
-           * later, when it encounters `AST_FUNC_DECL` again.
-           */
-        }
-        V7_TRY(bcode_add_name(bbuilder, name, name_len, &names_end));
-      }
-
-      if (next > 0) {
-        fvar = next - 1;
-      }
-
-    } while (next != 0);
-  }
-
-clean:
-  return rcode;
-}
-
-/*
- * Just like `compile_expr_builder`, but it takes additional argument:
- *`for_call`.
- * If it's non-zero, the stack is additionally populated with `this` value
- * for call.
- *
- * If there is a refinement (a dot, or a subscript), then it'll be the
- * appropriate object. Otherwise, it's `undefined`.
- *
- * In non-strict mode, `undefined` will be changed to Global Object at runtime,
- * see `OP_CALL` handling in `eval_bcode()`.
- */
-V7_PRIVATE enum v7_err compile_expr_ext(struct bcode_builder *bbuilder,
-                                        struct ast *a, ast_off_t *ppos,
-                                        uint8_t for_call) {
-  enum v7_err rcode = V7_OK;
-  struct v7 *v7 = bbuilder->v7;
-  ast_off_t pos_after_tag;
-  enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-
-  switch (tag) {
-    case AST_MEMBER: {
-      lit_t lit = string_lit(bbuilder, a, pos_after_tag);
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      if (for_call) {
-        /* current TOS will be used as `this` */
-        bcode_op(bbuilder, OP_DUP);
-      }
-      bcode_push_lit(bbuilder, lit);
-      bcode_op(bbuilder, OP_GET);
-      break;
-    }
-
-    case AST_INDEX:
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      if (for_call) {
-        /* current TOS will be used as `this` */
-        bcode_op(bbuilder, OP_DUP);
-      }
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_GET);
-      break;
-
-    default:
-      if (for_call) {
-        /*
-         * `this` will be an `undefined` (but it may change to Global Object
-         * at runtime)
-         */
-        bcode_op(bbuilder, OP_PUSH_UNDEFINED);
-      }
-      *ppos = pos_after_tag - 1;
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      break;
-  }
-
-clean:
-  return rcode;
-}
-
-V7_PRIVATE enum v7_err compile_delete(struct bcode_builder *bbuilder,
-                                      struct ast *a, ast_off_t *ppos) {
-  enum v7_err rcode = V7_OK;
-  struct v7 *v7 = bbuilder->v7;
-  ast_off_t pos_after_tag;
-  enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-
-  switch (tag) {
-    case AST_MEMBER: {
-      /* Delete a specified property of an object */
-      lit_t lit = string_lit(bbuilder, a, pos_after_tag);
-      /* put an object to delete property from */
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      /* put a property name */
-      bcode_push_lit(bbuilder, lit);
-      bcode_op(bbuilder, OP_DELETE);
-      break;
-    }
-
-    case AST_INDEX:
-      /* Delete a specified property of an object */
-      /* put an object to delete property from */
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      /* put a property name */
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_DELETE);
-      break;
-
-    case AST_IDENT:
-      /* Delete the scope variable (or throw an error if strict mode) */
-      if (!bbuilder->bcode->strict_mode) {
-        /* put a property name */
-        bcode_push_lit(bbuilder, string_lit(bbuilder, a, pos_after_tag));
-        bcode_op(bbuilder, OP_DELETE_VAR);
-      } else {
-        rcode =
-            v7_throwf(bbuilder->v7, SYNTAX_ERROR,
-                      "Delete of an unqualified identifier in strict mode.");
-        V7_THROW(V7_SYNTAX_ERROR);
-      }
-      break;
-
-    case AST_UNDEFINED:
-      /*
-       * `undefined` should actually be an undeletable property of the Global
-       * Object, so, trying to delete it just yields `false`
-       */
-      bcode_op(bbuilder, OP_PUSH_FALSE);
-      break;
-
-    default:
-      /*
-       * For all other cases, we evaluate the expression given to `delete`
-       * for side effects, then drop the result, and yield `true`
-       */
-      *ppos = pos_after_tag - 1;
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_DROP);
-      bcode_op(bbuilder, OP_PUSH_TRUE);
-      break;
-  }
-
-clean:
-  return rcode;
-}
-
-V7_PRIVATE enum v7_err compile_expr_builder(struct bcode_builder *bbuilder,
-                                            struct ast *a, ast_off_t *ppos) {
-  enum v7_err rcode = V7_OK;
-  struct v7 *v7 = bbuilder->v7;
-  ast_off_t pos_after_tag;
-  enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-
-  switch (tag) {
-    case AST_ADD:
-    case AST_SUB:
-    case AST_REM:
-    case AST_MUL:
-    case AST_DIV:
-    case AST_LSHIFT:
-    case AST_RSHIFT:
-    case AST_URSHIFT:
-    case AST_OR:
-    case AST_XOR:
-    case AST_AND:
-    case AST_EQ_EQ:
-    case AST_EQ:
-    case AST_NE:
-    case AST_NE_NE:
-    case AST_LT:
-    case AST_LE:
-    case AST_GT:
-    case AST_GE:
-    case AST_INSTANCEOF:
-      V7_TRY(compile_binary(bbuilder, a, ppos, tag));
-      break;
-    case AST_LOGICAL_NOT:
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_LOGICAL_NOT);
-      break;
-    case AST_NOT:
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_NOT);
-      break;
-    case AST_POSITIVE:
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_POS);
-      break;
-    case AST_NEGATIVE:
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_NEG);
-      break;
-    case AST_IDENT:
-      bcode_op_lit(bbuilder, OP_GET_VAR,
-                   string_lit(bbuilder, a, pos_after_tag));
-      break;
-    case AST_MEMBER:
-    case AST_INDEX:
-      /*
-       * These two are handled by the "extended" version of this function,
-       * since we may need to put `this` value on stack, for "method pattern
-       * invocation".
-       *
-       * First of all, restore starting AST position, and then call extended
-       * function.
-       */
-      *ppos = pos_after_tag - 1;
-      V7_TRY(compile_expr_ext(bbuilder, a, ppos, 0 /*not for call*/));
-      break;
-    case AST_IN:
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_IN);
-      break;
-    case AST_TYPEOF: {
-      ast_off_t lookahead = *ppos;
-      tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
-      if (tag == AST_IDENT) {
-        *ppos = lookahead;
-        bcode_op_lit(bbuilder, OP_SAFE_GET_VAR,
-                     string_lit(bbuilder, a, pos_after_tag));
-      } else {
-        V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      }
-      bcode_op(bbuilder, OP_TYPEOF);
-      break;
-    }
-    case AST_ASSIGN:
-    case AST_PREINC:
-    case AST_PREDEC:
-    case AST_POSTINC:
-    case AST_POSTDEC:
-    case AST_REM_ASSIGN:
-    case AST_MUL_ASSIGN:
-    case AST_DIV_ASSIGN:
-    case AST_XOR_ASSIGN:
-    case AST_PLUS_ASSIGN:
-    case AST_MINUS_ASSIGN:
-    case AST_OR_ASSIGN:
-    case AST_AND_ASSIGN:
-    case AST_LSHIFT_ASSIGN:
-    case AST_RSHIFT_ASSIGN:
-    case AST_URSHIFT_ASSIGN:
-      V7_TRY(compile_assign(bbuilder, a, ppos, tag));
-      break;
-    case AST_COND: {
-      /*
-      * A ? B : C
-      *
-      * ->
-      *
-      *   <A>
-      *   JMP_FALSE false
-      *   <B>
-      *   JMP end
-      * false:
-      *   <C>
-      * end:
-      *
-      */
-      bcode_off_t false_label, end_label;
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      false_label = bcode_op_target(bbuilder, OP_JMP_FALSE);
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      end_label = bcode_op_target(bbuilder, OP_JMP);
-      bcode_patch_target(bbuilder, false_label, bcode_pos(bbuilder));
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
-      break;
-    }
-    case AST_LOGICAL_OR:
-    case AST_LOGICAL_AND: {
-      /*
-       * A && B
-       *
-       * ->
-       *
-       *   <A>
-       *   JMP_FALSE end
-       *   POP
-       *   <B>
-       * end:
-       *
-       */
-      bcode_off_t end_label;
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_DUP);
-      end_label = bcode_op_target(
-          bbuilder, tag == AST_LOGICAL_AND ? OP_JMP_FALSE : OP_JMP_TRUE);
-      bcode_op(bbuilder, OP_DROP);
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
-      break;
-    }
-    /*
-     * A, B, C
-     *
-     * ->
-     *
-     * <A>
-     * DROP
-     * <B>
-     * DROP
-     * <C>
-     */
-    case AST_SEQ: {
-      ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-      while (*ppos < end) {
-        V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-        if (*ppos < end) {
-          bcode_op(bbuilder, OP_DROP);
-        }
-      }
-      break;
-    }
-    case AST_CALL:
-    case AST_NEW: {
-      /*
-       * f()
-       *
-       * ->
-       *
-       *  PUSH_UNDEFINED (value for `this`)
-       *  GET_VAR "f"
-       *  CHECK_CALL
-       *  CALL 0 args
-       *
-       * ---------------
-       *
-       * f(a, b)
-       *
-       * ->
-       *
-       *  PUSH_UNDEFINED (value for `this`)
-       *  GET_VAR "f"
-       *  CHECK_CALL
-       *  GET_VAR "a"
-       *  GET_VAR "b"
-       *  CALL 2 args
-       *
-       * ---------------
-       *
-       * o.f(a, b)
-       *
-       * ->
-       *
-       *  GET_VAR "o" (so that `this` will be an `o`)
-       *  DUP         (we'll also need `o` for GET below, so, duplicate it)
-       *  PUSH_LIT "f"
-       *  GET         (get property "f" of the object "o")
-       *  CHECK_CALL
-       *  GET_VAR "a"
-       *  GET_VAR "b"
-       *  CALL 2 args
-       *
-       */
-      int args;
-      ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-
-      V7_TRY(compile_expr_ext(bbuilder, a, ppos, 1 /*for call*/));
-      bcode_op(bbuilder, OP_CHECK_CALL);
-      for (args = 0; *ppos < end; args++) {
-        V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      }
-      bcode_op(bbuilder, (tag == AST_CALL ? OP_CALL : OP_NEW));
-      if (args > 0x7f) {
-        rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "too many arguments");
-        V7_THROW(V7_SYNTAX_ERROR);
-      }
-      bcode_op(bbuilder, (uint8_t) args);
-      break;
-    }
-    case AST_DELETE: {
-      V7_TRY(compile_delete(bbuilder, a, ppos));
-      break;
-    }
-    case AST_OBJECT: {
-      /*
-       * {a:<B>, ...}
-       *
-       * ->
-       *
-       *   CREATE_OBJ
-       *   DUP
-       *   PUSH_LIT "a"
-       *   <B>
-       *   SET
-       *   POP
-       *   ...
-       */
-
-      /*
-       * Literal indices of property names of current object literal.
-       * Needed for strict mode: we need to keep track of the added
-       * properties, since duplicates are not allowed
-       */
-      struct mbuf cur_literals;
-      lit_t lit;
-      ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-      mbuf_init(&cur_literals, 0);
-
-      bcode_op(bbuilder, OP_CREATE_OBJ);
-      while (*ppos < end) {
-        tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-        switch (tag) {
-          case AST_PROP:
-            bcode_op(bbuilder, OP_DUP);
-            lit = string_lit(bbuilder, a, pos_after_tag);
-
-/* disabled because we broke get_lit */
-#if 0
-            if (bbuilder->bcode->strict_mode) {
-              /*
-               * In strict mode, check for duplicate property names in
-               * object literals
-               */
-              char *plit;
-              for (plit = (char *) cur_literals.buf;
-                   (char *) plit < cur_literals.buf + cur_literals.len;
-                   plit++) {
-                const char *str1, *str2;
-                size_t size1, size2;
-                v7_val_t val1, val2;
-
-                val1 = bcode_get_lit(bbuilder->bcode, lit);
-                str1 = v7_get_string(bbuilder->v7, &val1, &size1);
-
-                val2 = bcode_get_lit(bbuilder->bcode, *plit);
-                str2 = v7_get_string(bbuilder->v7, &val2, &size2);
-
-                if (size1 == size2 && memcmp(str1, str2, size1) == 0) {
-                  /* found already existing property of the same name */
-                  rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR,
-                                    "duplicate data property in object literal "
-                                    "is not allowed in strict mode");
-                  V7_THROW2(V7_SYNTAX_ERROR, ast_object_clean);
-                }
-              }
-              mbuf_append(&cur_literals, &lit, sizeof(lit));
-            }
-#endif
-            bcode_push_lit(bbuilder, lit);
-            V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-            bcode_op(bbuilder, OP_SET);
-            bcode_op(bbuilder, OP_DROP);
-            break;
-          default:
-            rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented");
-            V7_THROW2(V7_SYNTAX_ERROR, ast_object_clean);
-        }
-      }
-
-    ast_object_clean:
-      mbuf_free(&cur_literals);
-      if (rcode != V7_OK) {
-        V7_THROW(rcode);
-      }
-      break;
-    }
-    case AST_ARRAY: {
-      /*
-       * [<A>,,<B>,...]
-       *
-       * ->
-       *
-       *   CREATE_ARR
-       *   PUSH_ZERO
-       *
-       *   2DUP
-       *   <A>
-       *   SET
-       *   POP
-       *   PUSH_ONE
-       *   ADD
-       *
-       *   PUSH_ONE
-       *   ADD
-       *
-       *   2DUP
-       *   <B>
-       *   ...
-       *   POP // tmp index
-       *
-       * TODO(mkm): optimize this out. we can have more compact array push
-       * that uses a special marker value for missing array elements
-       * (which are not the same as undefined btw)
-       */
-      ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-      bcode_op(bbuilder, OP_CREATE_ARR);
-      bcode_op(bbuilder, OP_PUSH_ZERO);
-      while (*ppos < end) {
-        ast_off_t lookahead = *ppos;
-        tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
-        if (tag != AST_NOP) {
-          bcode_op(bbuilder, OP_2DUP);
-          V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-          bcode_op(bbuilder, OP_SET);
-          bcode_op(bbuilder, OP_DROP);
-        } else {
-          *ppos = lookahead; /* skip nop */
-        }
-        bcode_op(bbuilder, OP_PUSH_ONE);
-        bcode_op(bbuilder, OP_ADD);
-      }
-      bcode_op(bbuilder, OP_DROP);
-      break;
-    }
-    case AST_FUNC: {
-      lit_t flit;
-
-      /*
-       * Create half-done function: without scope and prototype. The real
-       * function will be created from this one during bcode evaluation: see
-       * `bcode_instantiate_function()`.
-       */
-      val_t funv = mk_js_function(bbuilder->v7, NULL, V7_UNDEFINED);
-
-      /* Create bcode in this half-done function */
-      struct v7_js_function *func = get_js_function_struct(funv);
-      func->bcode = (struct bcode *) calloc(1, sizeof(*bbuilder->bcode));
-      bcode_init(func->bcode, bbuilder->bcode->strict_mode,
-                 NULL /* will be set below */, 0);
-      bcode_copy_filename_from(func->bcode, bbuilder->bcode);
-      retain_bcode(bbuilder->v7, func->bcode);
-      flit = bcode_add_lit(bbuilder, funv);
-
-      *ppos = pos_after_tag - 1;
-      V7_TRY(compile_function(v7, a, ppos, func->bcode));
-      bcode_push_lit(bbuilder, flit);
-      bcode_op(bbuilder, OP_FUNC_LIT);
-      break;
-    }
-    case AST_THIS:
-      bcode_op(bbuilder, OP_PUSH_THIS);
-      break;
-    case AST_VOID:
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_DROP);
-      bcode_op(bbuilder, OP_PUSH_UNDEFINED);
-      break;
-    case AST_NULL:
-      bcode_op(bbuilder, OP_PUSH_NULL);
-      break;
-    case AST_NOP:
-    case AST_UNDEFINED:
-      bcode_op(bbuilder, OP_PUSH_UNDEFINED);
-      break;
-    case AST_TRUE:
-      bcode_op(bbuilder, OP_PUSH_TRUE);
-      break;
-    case AST_FALSE:
-      bcode_op(bbuilder, OP_PUSH_FALSE);
-      break;
-    case AST_NUM: {
-      double dv = ast_get_num(a, pos_after_tag);
-      if (dv == 0) {
-        bcode_op(bbuilder, OP_PUSH_ZERO);
-      } else if (dv == 1) {
-        bcode_op(bbuilder, OP_PUSH_ONE);
-      } else {
-        bcode_push_lit(bbuilder, bcode_add_lit(bbuilder, v7_mk_number(v7, dv)));
-      }
-      break;
-    }
-    case AST_STRING:
-      bcode_push_lit(bbuilder, string_lit(bbuilder, a, pos_after_tag));
-      break;
-    case AST_REGEX:
-#if V7_ENABLE__RegExp
-    {
-      lit_t tmp;
-      rcode = regexp_lit(bbuilder, a, pos_after_tag, &tmp);
-      if (rcode != V7_OK) {
-        rcode = V7_SYNTAX_ERROR;
-        goto clean;
-      }
-
-      bcode_push_lit(bbuilder, tmp);
-      break;
-    }
-#else
-      rcode =
-          v7_throwf(bbuilder->v7, SYNTAX_ERROR, "Regexp support is disabled");
-      V7_THROW(V7_SYNTAX_ERROR);
-#endif
-    case AST_LABEL:
-    case AST_LABELED_BREAK:
-    case AST_LABELED_CONTINUE:
-      /* TODO(dfrank): implement */
-      rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented");
-      V7_THROW(V7_SYNTAX_ERROR);
-    case AST_WITH:
-      rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented");
-      V7_THROW(V7_SYNTAX_ERROR);
-    default:
-      /*
-       * We end up here if the AST is broken.
-       *
-       * It might be appropriate to return `V7_INTERNAL_ERROR` here, but since
-       * we might receive AST from network or something, we just interpret
-       * it as SyntaxError.
-       */
-      rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "unknown ast node %d",
-                        (int) tag);
-      V7_THROW(V7_SYNTAX_ERROR);
-  }
-clean:
-  return rcode;
-}
-
-V7_PRIVATE enum v7_err compile_stmt(struct bcode_builder *bbuilder,
-                                    struct ast *a, ast_off_t *ppos);
-
-V7_PRIVATE enum v7_err compile_stmts(struct bcode_builder *bbuilder,
-                                     struct ast *a, ast_off_t *ppos,
-                                     ast_off_t end) {
-  enum v7_err rcode = V7_OK;
-  struct v7 *v7 = bbuilder->v7;
-
-  while (*ppos < end) {
-    V7_TRY(compile_stmt(bbuilder, a, ppos));
-    if (!bbuilder->v7->is_stack_neutral) {
-      bcode_op(bbuilder, OP_SWAP_DROP);
-    } else {
-      bbuilder->v7->is_stack_neutral = 0;
-    }
-  }
-clean:
-  return rcode;
-}
-
-V7_PRIVATE enum v7_err compile_stmt(struct bcode_builder *bbuilder,
-                                    struct ast *a, ast_off_t *ppos) {
-  ast_off_t end;
-  enum ast_tag tag;
-  ast_off_t cond, pos_after_tag;
-  bcode_off_t body_target, body_label, cond_label;
-  struct mbuf case_labels;
-  enum v7_err rcode = V7_OK;
-  struct v7 *v7 = bbuilder->v7;
-
-  tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-
-  mbuf_init(&case_labels, 0);
-
-  switch (tag) {
-    /*
-     * if(E) {
-     *   BT...
-     * } else {
-     *   BF...
-     * }
-     *
-     * ->
-     *
-     *   <E>
-     *   JMP_FALSE body
-     *   <BT>
-     *   JMP end
-     * body:
-     *   <BF>
-     * end:
-     *
-     * If else clause is omitted, it will emit output equivalent to:
-     *
-     * if(E) {BT} else undefined;
-     */
-    case AST_IF: {
-      ast_off_t if_false;
-      bcode_off_t end_label, if_false_label;
-      end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-      if_false = ast_get_skip(a, pos_after_tag, AST_END_IF_TRUE_SKIP);
-
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      if_false_label = bcode_op_target(bbuilder, OP_JMP_FALSE);
-
-      /* body if true */
-      V7_TRY(compile_stmts(bbuilder, a, ppos, if_false));
-
-      if (if_false != end) {
-        /* `else` branch is present */
-        end_label = bcode_op_target(bbuilder, OP_JMP);
-
-        /* will jump here if `false` */
-        bcode_patch_target(bbuilder, if_false_label, bcode_pos(bbuilder));
-
-        /* body if false */
-        V7_TRY(compile_stmts(bbuilder, a, ppos, end));
-
-        bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
-      } else {
-        /*
-         * `else` branch is not present: just remember where we should
-         * jump in case of `false`
-         */
-        bcode_patch_target(bbuilder, if_false_label, bcode_pos(bbuilder));
-      }
-
-      bbuilder->v7->is_stack_neutral = 1;
-      break;
-    }
-    /*
-     * while(C) {
-     *   B...
-     * }
-     *
-     * ->
-     *
-     *   TRY_PUSH_LOOP end
-     *   JMP cond
-     * body:
-     *   <B>
-     * cond:
-     *   <C>
-     *   JMP_TRUE body
-     * end:
-     *   JMP_IF_CONTINUE cond
-     *   TRY_POP
-     *
-     */
-    case AST_WHILE: {
-      bcode_off_t end_label, continue_label, continue_target;
-
-      end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-      cond = *ppos;
-      ast_skip_tree(a, ppos);
-
-      end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
-
-      /*
-       * Condition check is at the end of the loop, this layout
-       * reduces the number of jumps in the steady state.
-       */
-      cond_label = bcode_op_target(bbuilder, OP_JMP);
-      body_target = bcode_pos(bbuilder);
-
-      V7_TRY(compile_stmts(bbuilder, a, ppos, end));
-
-      continue_target = bcode_pos(bbuilder);
-      bcode_patch_target(bbuilder, cond_label, continue_target);
-
-      V7_TRY(compile_expr_builder(bbuilder, a, &cond));
-      body_label = bcode_op_target(bbuilder, OP_JMP_TRUE);
-      bcode_patch_target(bbuilder, body_label, body_target);
-
-      bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
-      continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
-      bcode_patch_target(bbuilder, continue_label, continue_target);
-      bcode_op(bbuilder, OP_TRY_POP);
-
-      bbuilder->v7->is_stack_neutral = 1;
-      break;
-    }
-    case AST_BREAK:
-      bcode_op(bbuilder, OP_BREAK);
-      break;
-    case AST_CONTINUE:
-      bcode_op(bbuilder, OP_CONTINUE);
-      break;
-    /*
-     * Frame objects (`v7->vals.call_stack`) contain one more hidden property:
-     * `____t`, which is an array of offsets in bcode. Each element of the array
-     * is an offset of either `catch` or `finally` block (distinguished by the
-     * tag: `OFFSET_TAG_CATCH` or `OFFSET_TAG_FINALLY`). Let's call this array
-     * as a "try stack". When evaluator enters new `try` block, it adds
-     * appropriate offset(s) at the top of "try stack", and when we unwind the
-     * stack, we can "pop" offsets from "try stack" at each level.
-     *
-     * try {
-     *   TRY_B
-     * } catch (e) {
-     *   CATCH_B
-     * } finally {
-     *   FIN_B
-     * }
-     *
-     * ->
-     *    OP_TRY_PUSH_FINALLY finally
-     *    OP_TRY_PUSH_CATCH catch
-     *    <TRY_B>
-     *    OP_TRY_POP
-     *    JMP finally
-     *  catch:
-     *    OP_TRY_POP
-     *    OP_ENTER_CATCH <e>
-     *    <CATCH_B>
-     *    OP_EXIT_CATCH
-     *  finally:
-     *    OP_TRY_POP
-     *    <FIN_B>
-     *    OP_AFTER_FINALLY
-     *
-     * ---------------
-     *
-     * try {
-     *   TRY_B
-     * } catch (e) {
-     *   CATCH_B
-     * }
-     *
-     * ->
-     *    OP_TRY_PUSH_CATCH catch
-     *    <TRY_B>
-     *    OP_TRY_POP
-     *    JMP end
-     *  catch:
-     *    OP_TRY_POP
-     *    OP_ENTER_CATCH <e>
-     *    <CATCH_B>
-     *    OP_EXIT_CATCH
-     *  end:
-     *
-     * ---------------
-     *
-     * try {
-     *   TRY_B
-     * } finally {
-     *   FIN_B
-     * }
-     *
-     * ->
-     *    OP_TRY_PUSH_FINALLY finally
-     *    <TRY_B>
-     *  finally:
-     *    OP_TRY_POP
-     *    <FIN_B>
-     *    OP_AFTER_FINALLY
-     */
-    case AST_TRY: {
-      ast_off_t acatch, afinally;
-      bcode_off_t finally_label, catch_label;
-
-      end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-      acatch = ast_get_skip(a, pos_after_tag, AST_TRY_CATCH_SKIP);
-      afinally = ast_get_skip(a, pos_after_tag, AST_TRY_FINALLY_SKIP);
-
-      if (afinally != end) {
-        /* `finally` clause is present: push its offset */
-        finally_label = bcode_op_target(bbuilder, OP_TRY_PUSH_FINALLY);
-      }
-
-      if (acatch != afinally) {
-        /* `catch` clause is present: push its offset */
-        catch_label = bcode_op_target(bbuilder, OP_TRY_PUSH_CATCH);
-      }
-
-      /* compile statements of `try` block */
-      V7_TRY(compile_stmts(bbuilder, a, ppos, acatch));
-
-      if (acatch != afinally) {
-        /* `catch` clause is present: compile it */
-        bcode_off_t after_catch_label;
-
-        /*
-         * pop offset pushed by OP_TRY_PUSH_CATCH, and jump over the `catch`
-         * block
-         */
-        bcode_op(bbuilder, OP_TRY_POP);
-        after_catch_label = bcode_op_target(bbuilder, OP_JMP);
-
-        /* --- catch --- */
-
-        /* in case of exception in the `try` block above, we'll get here */
-        bcode_patch_target(bbuilder, catch_label, bcode_pos(bbuilder));
-
-        /* pop offset pushed by OP_TRY_PUSH_CATCH */
-        bcode_op(bbuilder, OP_TRY_POP);
-
-        /*
-         * retrieve identifier where to store thrown error, and make sure
-         * it is actually an indentifier (AST_IDENT)
-         */
-        tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-        V7_CHECK(tag == AST_IDENT, V7_SYNTAX_ERROR);
-
-        /*
-         * when we enter `catch` block, the TOS contains thrown value.
-         * We should create private frame for the `catch` clause, and populate
-         * a variable with the thrown value there.
-         * The `OP_ENTER_CATCH` opcode does just that.
-         */
-        bcode_op_lit(bbuilder, OP_ENTER_CATCH,
-                     string_lit(bbuilder, a, pos_after_tag));
-
-        /*
-         * compile statements until the end of `catch` clause
-         * (`afinally` points to the end of the `catch` clause independently
-         * of whether the `finally` clause is present)
-         */
-        V7_TRY(compile_stmts(bbuilder, a, ppos, afinally));
-
-        /* pop private frame */
-        bcode_op(bbuilder, OP_EXIT_CATCH);
-
-        bcode_patch_target(bbuilder, after_catch_label, bcode_pos(bbuilder));
-      }
-
-      if (afinally != end) {
-        /* `finally` clause is present: compile it */
-
-        /* --- finally --- */
-
-        /* after the `try` block above executes, we'll get here */
-        bcode_patch_target(bbuilder, finally_label, bcode_pos(bbuilder));
-
-        /* pop offset pushed by OP_TRY_PUSH_FINALLY */
-        bcode_op(bbuilder, OP_TRY_POP);
-
-        /* compile statements until the end of `finally` clause */
-        V7_TRY(compile_stmts(bbuilder, a, ppos, end));
-
-        bcode_op(bbuilder, OP_AFTER_FINALLY);
-      }
-
-      bbuilder->v7->is_stack_neutral = 1;
-      break;
-    }
-
-    case AST_THROW: {
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_THROW);
-      break;
-    }
-
-    /*
-     * switch(E) {
-     * default:
-     *   D...
-     * case C1:
-     *   B1...
-     * case C2:
-     *   B2...
-     * }
-     *
-     * ->
-     *
-     *   TRY_PUSH_SWITCH end
-     *   <E>
-     *   DUP
-     *   <C1>
-     *   EQ
-     *   JMP_TRUE_DROP l1
-     *   DUP
-     *   <C2>
-     *   EQ
-     *   JMP_TRUE_DROP l2
-     *   DROP
-     *   JMP dfl
-     *
-     * dfl:
-     *   <D>
-     *
-     * l1:
-     *   <B1>
-     *
-     * l2:
-     *   <B2>
-     *
-     * end:
-     *   TRY_POP
-     *
-     * If the default case is missing we treat it as if had an empty body and
-     * placed in last position (i.e. `dfl` label is replaced with `end`).
-     *
-     * Before emitting a case/default block (except the first one) we have to
-     * drop the TOS resulting from evaluating the last expression
-     */
-    case AST_SWITCH: {
-      bcode_off_t dfl_label, end_label;
-      ast_off_t case_end, case_start;
-      enum ast_tag case_tag;
-      int i, has_default = 0, cases = 0;
-
-      end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-
-      end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_SWITCH);
-
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-
-      case_start = *ppos;
-      /* first pass: evaluate case expression and generate jump table */
-      while (*ppos < end) {
-        case_tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-        assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
-
-        case_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-
-        switch (case_tag) {
-          case AST_DEFAULT:
-            /* default jump table entry must be the last one */
-            break;
-          case AST_CASE: {
-            bcode_off_t case_label;
-            bcode_op(bbuilder, OP_DUP);
-            V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-            bcode_op(bbuilder, OP_EQ);
-            case_label = bcode_op_target(bbuilder, OP_JMP_TRUE_DROP);
-            cases++;
-            mbuf_append(&case_labels, &case_label, sizeof(case_label));
-            break;
-          }
-          default:
-            assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
-        }
-        *ppos = case_end;
-      }
-
-      /* jmp table epilogue: unconditional jump to default case */
-      bcode_op(bbuilder, OP_DROP);
-      dfl_label = bcode_op_target(bbuilder, OP_JMP);
-
-      *ppos = case_start;
-      /* second pass: emit case bodies and patch jump table */
-
-      for (i = 0; *ppos < end;) {
-        case_tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-        assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
-        assert(i <= cases);
-
-        case_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-
-        switch (case_tag) {
-          case AST_DEFAULT:
-            has_default = 1;
-            bcode_patch_target(bbuilder, dfl_label, bcode_pos(bbuilder));
-            V7_TRY(compile_stmts(bbuilder, a, ppos, case_end));
-            break;
-          case AST_CASE: {
-            bcode_off_t case_label = ((bcode_off_t *) case_labels.buf)[i++];
-            bcode_patch_target(bbuilder, case_label, bcode_pos(bbuilder));
-            ast_skip_tree(a, ppos);
-            V7_TRY(compile_stmts(bbuilder, a, ppos, case_end));
-            break;
-          }
-          default:
-            assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
-        }
-
-        *ppos = case_end;
-      }
-      mbuf_free(&case_labels);
-
-      if (!has_default) {
-        bcode_patch_target(bbuilder, dfl_label, bcode_pos(bbuilder));
-      }
-
-      bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
-      bcode_op(bbuilder, OP_TRY_POP);
-
-      bbuilder->v7->is_stack_neutral = 1;
-      break;
-    }
-    /*
-     * for(INIT,COND,IT) {
-     *   B...
-     * }
-     *
-     * ->
-     *
-     *   <INIT>
-     *   DROP
-     *   TRY_PUSH_LOOP end
-     *   JMP cond
-     * body:
-     *   <B>
-     * next:
-     *   <IT>
-     *   DROP
-     * cond:
-     *   <COND>
-     *   JMP_TRUE body
-     * end:
-     *   JMP_IF_CONTINUE next
-     *   TRY_POP
-     *
-     */
-    case AST_FOR: {
-      ast_off_t iter, body, lookahead;
-      bcode_off_t end_label, continue_label, continue_target;
-      end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-      body = ast_get_skip(a, pos_after_tag, AST_FOR_BODY_SKIP);
-
-      lookahead = *ppos;
-      tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
-      /*
-       * Support for `var` declaration in INIT
-       */
-      if (tag == AST_VAR) {
-        ast_off_t fvar_end;
-        lit_t lit;
-
-        *ppos = lookahead;
-        fvar_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-
-        /*
-         * Iterate through all vars in the given `var` declaration: they are
-         * just like assigments here
-         */
-        while (*ppos < fvar_end) {
-          tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-          /* Only var declarations are allowed (not function declarations) */
-          V7_CHECK_INTERNAL(tag == AST_VAR_DECL);
-          lit = string_lit(bbuilder, a, pos_after_tag);
-          V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-
-          /* Just like an assigment */
-          bcode_op_lit(bbuilder, OP_SET_VAR, lit);
-
-          /* INIT is stack-neutral */
-          bcode_op(bbuilder, OP_DROP);
-        }
-      } else {
-        /* normal expression in INIT (not `var` declaration) */
-        V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-        /* INIT is stack-neutral */
-        bcode_op(bbuilder, OP_DROP);
-      }
-      cond = *ppos;
-      ast_skip_tree(a, ppos);
-      iter = *ppos;
-      *ppos = body;
-
-      end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
-      cond_label = bcode_op_target(bbuilder, OP_JMP);
-      body_target = bcode_pos(bbuilder);
-      V7_TRY(compile_stmts(bbuilder, a, ppos, end));
-
-      continue_target = bcode_pos(bbuilder);
-
-      V7_TRY(compile_expr_builder(bbuilder, a, &iter));
-      bcode_op(bbuilder, OP_DROP);
-
-      bcode_patch_target(bbuilder, cond_label, bcode_pos(bbuilder));
-
-      /*
-       * Handle for(INIT;;ITER)
-       */
-      lookahead = cond;
-      tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
-      if (tag == AST_NOP) {
-        bcode_op(bbuilder, OP_JMP);
-      } else {
-        V7_TRY(compile_expr_builder(bbuilder, a, &cond));
-        bcode_op(bbuilder, OP_JMP_TRUE);
-      }
-      body_label = bcode_add_target(bbuilder);
-      bcode_patch_target(bbuilder, body_label, body_target);
-      bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
-
-      continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
-      bcode_patch_target(bbuilder, continue_label, continue_target);
-
-      bcode_op(bbuilder, OP_TRY_POP);
-
-      bbuilder->v7->is_stack_neutral = 1;
-      break;
-    }
-    /*
-     * for(I in O) {
-     *   B...
-     * }
-     *
-     * ->
-     *
-     *   DUP
-     *   <O>
-     *   SWAP
-     *   STASH
-     *   DROP
-     *   PUSH_PROP_ITER_CTX   # push initial iteration context
-     *   TRY_PUSH_LOOP brend
-     * loop:
-     *   NEXT_PROP
-     *   JMP_FALSE end
-     *   SET_VAR <I>
-     *   UNSTASH
-     *   <B>
-     * next:
-     *   STASH
-     *   DROP
-     *   JMP loop
-     * end:
-     *   UNSTASH
-     *   JMP try_pop:
-     * brend:
-     *              # got here after a `break` or `continue` from a loop body:
-     *   JMP_IF_CONTINUE next
-     *
-     *              # we're not going to `continue`, so, need to remove an
-     *              # extra stuff that was needed for the NEXT_PROP
-     *
-     *   SWAP_DROP  # drop iteration context
-     *   SWAP_DROP  # drop <O>
-     *   SWAP_DROP  # drop the value preceding the loop
-     * try_pop:
-     *   TRY_POP
-     *
-     */
-    case AST_FOR_IN: {
-      lit_t lit;
-      bcode_off_t loop_label, loop_target, end_label, brend_label,
-          continue_label, pop_label, continue_target;
-      ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-
-      tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-      /* TODO(mkm) accept any l-value */
-      if (tag == AST_VAR) {
-        tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-        V7_CHECK_INTERNAL(tag == AST_VAR_DECL);
-        lit = string_lit(bbuilder, a, pos_after_tag);
-        ast_skip_tree(a, ppos);
-      } else {
-        V7_CHECK_INTERNAL(tag == AST_IDENT);
-        lit = string_lit(bbuilder, a, pos_after_tag);
-      }
-
-      /*
-       * preserve previous statement value.
-       * We need to feed the previous value into the stash
-       * because it's required for the loop steady state.
-       *
-       * The stash register is required to simplify the steady state stack
-       * management, in particular the removal of value in 3rd position in case
-       * a of not taken exit.
-       *
-       * TODO(mkm): consider having a stash OP that moves a value to the stash
-       * register instead of copying it. The current behaviour has been
-       * optimized for the `assign` use case which seems more common.
-       */
-      bcode_op(bbuilder, OP_DUP);
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_SWAP);
-      bcode_op(bbuilder, OP_STASH);
-      bcode_op(bbuilder, OP_DROP);
-
-      /*
-       * OP_NEXT_PROP needs the iteration context, let's push the initial one.
-       */
-      bcode_op(bbuilder, OP_PUSH_PROP_ITER_CTX);
-
-      brend_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
-
-      /* loop: */
-      loop_target = bcode_pos(bbuilder);
-
-      /*
-       * The loop stead state begins with the following stack layout:
-       * `( S:v o h )`
-       */
-
-      bcode_op(bbuilder, OP_NEXT_PROP);
-      end_label = bcode_op_target(bbuilder, OP_JMP_FALSE);
-      bcode_op_lit(bbuilder, OP_SET_VAR, lit);
-
-      /*
-       * The stash register contains the value of the previous statement,
-       * being it the statement before the for..in statement or
-       * the previous iteration. We move it to the data stack. It will
-       * be replaced by the values of the body statements as usual.
-       */
-      bcode_op(bbuilder, OP_UNSTASH);
-
-      /*
-       * This node is always a NOP, for compatibility
-       * with the layout of the AST_FOR node.
-       */
-      ast_skip_tree(a, ppos);
-
-      V7_TRY(compile_stmts(bbuilder, a, ppos, end));
-
-      continue_target = bcode_pos(bbuilder);
-
-      /*
-       * Save the last body statement. If next evaluation of NEXT_PROP returns
-       * false, we'll unstash it.
-       */
-      bcode_op(bbuilder, OP_STASH);
-      bcode_op(bbuilder, OP_DROP);
-
-      loop_label = bcode_op_target(bbuilder, OP_JMP);
-      bcode_patch_target(bbuilder, loop_label, loop_target);
-
-      /* end: */
-      bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
-      bcode_op(bbuilder, OP_UNSTASH);
-
-      pop_label = bcode_op_target(bbuilder, OP_JMP);
-
-      /* brend: */
-      bcode_patch_target(bbuilder, brend_label, bcode_pos(bbuilder));
-
-      continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
-      bcode_patch_target(bbuilder, continue_label, continue_target);
-
-      bcode_op(bbuilder, OP_SWAP_DROP);
-      bcode_op(bbuilder, OP_SWAP_DROP);
-      bcode_op(bbuilder, OP_SWAP_DROP);
-
-      /* try_pop: */
-      bcode_patch_target(bbuilder, pop_label, bcode_pos(bbuilder));
-
-      bcode_op(bbuilder, OP_TRY_POP);
-
-      bbuilder->v7->is_stack_neutral = 1;
-      break;
-    }
-    /*
-     * do {
-     *   B...
-     * } while(COND);
-     *
-     * ->
-     *
-     *   TRY_PUSH_LOOP end
-     * body:
-     *   <B>
-     * cond:
-     *   <COND>
-     *   JMP_TRUE body
-     * end:
-     *   JMP_IF_CONTINUE cond
-     *   TRY_POP
-     *
-     */
-    case AST_DOWHILE: {
-      bcode_off_t end_label, continue_label, continue_target;
-      end = ast_get_skip(a, pos_after_tag, AST_DO_WHILE_COND_SKIP);
-      end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
-      body_target = bcode_pos(bbuilder);
-      V7_TRY(compile_stmts(bbuilder, a, ppos, end));
-
-      continue_target = bcode_pos(bbuilder);
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      body_label = bcode_op_target(bbuilder, OP_JMP_TRUE);
-      bcode_patch_target(bbuilder, body_label, body_target);
-
-      bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
-      continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
-      bcode_patch_target(bbuilder, continue_label, continue_target);
-      bcode_op(bbuilder, OP_TRY_POP);
-
-      bbuilder->v7->is_stack_neutral = 1;
-      break;
-    }
-    case AST_VAR: {
-      /*
-       * Var decls are hoisted when the function frame is created. Vars
-       * declared inside a `with` or `catch` block belong to the function
-       * lexical scope, and although those clauses create an inner frame
-       * no new variables should be created in it. A var decl thus
-       * behaves as a normal assignment at runtime.
-       */
-      lit_t lit;
-      end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-      while (*ppos < end) {
-        tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
-        if (tag == AST_FUNC_DECL) {
-          /*
-           * function declarations are already set during hoisting (see
-           * `compile_local_vars()`), so, skip it.
-           *
-           * Plus, they are stack-neutral, so don't forget to set
-           * `is_stack_neutral`.
-           */
-          ast_skip_tree(a, ppos);
-          bbuilder->v7->is_stack_neutral = 1;
-        } else {
-          /*
-           * compile `var` declaration: basically it looks similar to an
-           * assignment, but it differs from an assignment is that it's
-           * stack-neutral: `1; var a = 5;` yields `1`, not `5`.
-           */
-          V7_CHECK_INTERNAL(tag == AST_VAR_DECL);
-          lit = string_lit(bbuilder, a, pos_after_tag);
-          V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-          bcode_op_lit(bbuilder, OP_SET_VAR, lit);
-
-          /* `var` declaration is stack-neutral */
-          bcode_op(bbuilder, OP_DROP);
-          bbuilder->v7->is_stack_neutral = 1;
-        }
-      }
-      break;
-    }
-    case AST_RETURN:
-      bcode_op(bbuilder, OP_PUSH_UNDEFINED);
-      bcode_op(bbuilder, OP_RET);
-      break;
-    case AST_VALUE_RETURN:
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-      bcode_op(bbuilder, OP_RET);
-      break;
-    default:
-      *ppos = pos_after_tag - 1;
-      V7_TRY(compile_expr_builder(bbuilder, a, ppos));
-  }
-
-clean:
-  mbuf_free(&case_labels);
-  return rcode;
-}
-
-static enum v7_err compile_body(struct bcode_builder *bbuilder, struct ast *a,
-                                ast_off_t start, ast_off_t end, ast_off_t body,
-                                ast_off_t fvar, ast_off_t *ppos) {
-  enum v7_err rcode = V7_OK;
-  struct v7 *v7 = bbuilder->v7;
-
-#ifndef V7_FORCE_STRICT_MODE
-  /* check 'use strict' */
-  if (*ppos < end) {
-    ast_off_t tmp_pos = body;
-    if (fetch_tag(v7, bbuilder, a, &tmp_pos, NULL) == AST_USE_STRICT) {
-      bbuilder->bcode->strict_mode = 1;
-      /* move `body` offset, effectively removing `AST_USE_STRICT` from it */
-      body = tmp_pos;
-    }
-  }
-#endif
-
-  /* put initial value for the function body execution */
-  bcode_op(bbuilder, OP_PUSH_UNDEFINED);
-
-  /*
-   * populate `bcode->ops` with function's local variable names. Note that we
-   * should do this *after* `OP_PUSH_UNDEFINED`, since `compile_local_vars`
-   * emits code that assigns the hoisted functions to local variables, and
-   * those statements assume that the stack contains `undefined`.
-   */
-  V7_TRY(compile_local_vars(bbuilder, a, start, fvar));
-
-  /* compile body */
-  *ppos = body;
-  V7_TRY(compile_stmts(bbuilder, a, ppos, end));
-
-clean:
-  return rcode;
-}
-
-/*
- * Compiles a given script and populates a bcode structure.
- * The AST must start with an AST_SCRIPT node.
- */
-V7_PRIVATE enum v7_err compile_script(struct v7 *v7, struct ast *a,
-                                      struct bcode *bcode) {
-  ast_off_t pos_after_tag, end, fvar, pos = 0;
-  int saved_line_no = v7->line_no;
-  enum v7_err rcode = V7_OK;
-  struct bcode_builder bbuilder;
-  enum ast_tag tag;
-
-  bcode_builder_init(v7, &bbuilder, bcode);
-  v7->line_no = 1;
-
-  tag = fetch_tag(v7, &bbuilder, a, &pos, &pos_after_tag);
-
-  /* first tag should always be AST_SCRIPT */
-  assert(tag == AST_SCRIPT);
-  (void) tag;
-
-  end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-  fvar = ast_get_skip(a, pos_after_tag, AST_FUNC_FIRST_VAR_SKIP) - 1;
-
-  V7_TRY(compile_body(&bbuilder, a, pos_after_tag - 1, end, pos /* body */,
-                      fvar, &pos));
-
-clean:
-
-  bcode_builder_finalize(&bbuilder);
-
-#ifdef V7_BCODE_DUMP
-  if (rcode == V7_OK) {
-    fprintf(stderr, "--- script ---\n");
-    dump_bcode(v7, stderr, bcode);
-  }
-#endif
-
-  v7->line_no = saved_line_no;
-
-  return rcode;
-}
-
-/*
- * Compiles a given function and populates a bcode structure.
- * The AST must contain an AST_FUNC node at offset ast_off.
- */
-V7_PRIVATE enum v7_err compile_function(struct v7 *v7, struct ast *a,
-                                        ast_off_t *ppos, struct bcode *bcode) {
-  ast_off_t pos_after_tag, start, end, body, fvar;
-  const char *name;
-  size_t name_len;
-  size_t args_cnt;
-  enum v7_err rcode = V7_OK;
-  struct bcode_builder bbuilder;
-  enum ast_tag tag;
-  size_t names_end = 0;
-  bcode_builder_init(v7, &bbuilder, bcode);
-  tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag);
-  start = pos_after_tag - 1;
-
-  (void) tag;
-  assert(tag == AST_FUNC);
-  end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
-  body = ast_get_skip(a, pos_after_tag, AST_FUNC_BODY_SKIP);
-  fvar = ast_get_skip(a, pos_after_tag, AST_FUNC_FIRST_VAR_SKIP) - 1;
-
-  /* retrieve function name */
-  tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag);
-  if (tag == AST_IDENT) {
-    /* function name is provided */
-    name = ast_get_inlined_data(a, pos_after_tag, &name_len);
-    V7_TRY(bcode_add_name(&bbuilder, name, name_len, &names_end));
-  } else {
-    /* no name: anonymous function */
-    V7_TRY(bcode_add_name(&bbuilder, "", 0, &names_end));
-  }
-
-  /* retrieve function's argument names */
-  for (args_cnt = 0; *ppos < body; args_cnt++) {
-    if (args_cnt > V7_ARGS_CNT_MAX) {
-      /* too many arguments */
-      rcode = v7_throwf(v7, SYNTAX_ERROR, "Too many arguments");
-      V7_THROW(V7_SYNTAX_ERROR);
-    }
-
-    tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag);
-    /*
-     * TODO(dfrank): it's not actually an internal error, we get here if
-     * we compile e.g. the following: (function(1){})
-     */
-    V7_CHECK_INTERNAL(tag == AST_IDENT);
-    name = ast_get_inlined_data(a, pos_after_tag, &name_len);
-    V7_TRY(bcode_add_name(&bbuilder, name, name_len, &names_end));
-  }
-
-  bcode->args_cnt = args_cnt;
-  bcode->func_name_present = 1;
-
-  V7_TRY(compile_body(&bbuilder, a, start, end, body, fvar, ppos));
-
-clean:
-  bcode_builder_finalize(&bbuilder);
-
-#ifdef V7_BCODE_DUMP
-  if (rcode == V7_OK) {
-    fprintf(stderr, "--- function ---\n");
-    dump_bcode(v7, stderr, bcode);
-  }
-#endif
-
-  return rcode;
-}
-
-V7_PRIVATE enum v7_err compile_expr(struct v7 *v7, struct ast *a,
-                                    ast_off_t *ppos, struct bcode *bcode) {
-  enum v7_err rcode = V7_OK;
-  struct bcode_builder bbuilder;
-  int saved_line_no = v7->line_no;
-
-  bcode_builder_init(v7, &bbuilder, bcode);
-  v7->line_no = 1;
-
-  rcode = compile_expr_builder(&bbuilder, a, ppos);
-
-  bcode_builder_finalize(&bbuilder);
-  v7->line_no = saved_line_no;
-  return rcode;
-}
-
-#endif /* V7_NO_COMPILER */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/stdlib.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/cs_strtod.h" */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/stdlib.h" */
-/* Amalgamated: #include "v7/src/std_array.h" */
-/* Amalgamated: #include "v7/src/std_boolean.h" */
-/* Amalgamated: #include "v7/src/std_date.h" */
-/* Amalgamated: #include "v7/src/std_error.h" */
-/* Amalgamated: #include "v7/src/std_function.h" */
-/* Amalgamated: #include "v7/src/std_json.h" */
-/* Amalgamated: #include "v7/src/std_math.h" */
-/* Amalgamated: #include "v7/src/std_number.h" */
-/* Amalgamated: #include "v7/src/std_object.h" */
-/* Amalgamated: #include "v7/src/std_regex.h" */
-/* Amalgamated: #include "v7/src/std_string.h" */
-/* Amalgamated: #include "v7/src/std_proxy.h" */
-/* Amalgamated: #include "v7/src/js_stdlib.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-/* Amalgamated: #include "v7/src/exec.h" */
-
-#ifdef NO_LIBC
-void print_str(const char *str);
-#endif
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Std_print(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  int i, num_args = v7_argc(v7);
-  val_t v;
-
-  (void) res;
-
-  for (i = 0; i < num_args; i++) {
-    v = v7_arg(v7, i);
-    if (v7_is_string(v)) {
-      size_t n;
-      const char *s = v7_get_string(v7, &v, &n);
-      printf("%.*s", (int) n, s);
-    } else {
-      v7_print(v7, v);
-    }
-    printf(" ");
-  }
-  printf(ENDL);
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err std_eval(struct v7 *v7, v7_val_t arg, val_t this_obj,
-                                int is_json, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  char buf[100], *p = buf;
-  struct v7_exec_opts opts;
-  memset(&opts, 0x00, sizeof(opts));
-  opts.filename = "Eval'd code";
-
-  if (arg != V7_UNDEFINED) {
-    size_t len;
-    rcode = to_string(v7, arg, NULL, buf, sizeof(buf), &len);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    /* Fit null terminating byte and quotes */
-    if (len >= sizeof(buf) - 2) {
-      /* Buffer is not large enough. Allocate a bigger one */
-      p = (char *) malloc(len + 3);
-      rcode = to_string(v7, arg, NULL, p, len + 2, NULL);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-    }
-
-    v7_set_gc_enabled(v7, 1);
-    if (is_json) {
-      opts.is_json = 1;
-    } else {
-      opts.this_obj = this_obj;
-    }
-    rcode = v7_exec_opt(v7, p, &opts, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-clean:
-  if (p != buf) {
-    free(p);
-  }
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Std_eval(struct v7 *v7, v7_val_t *res) {
-  val_t this_obj = v7_get_this(v7);
-  v7_val_t arg = v7_arg(v7, 0);
-  return std_eval(v7, arg, this_obj, 0, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Std_parseInt(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = V7_UNDEFINED;
-  v7_val_t arg1 = V7_UNDEFINED;
-  long sign = 1, base, n;
-  char buf[20], *p = buf, *end;
-
-  *res = V7_TAG_NAN;
-
-  arg0 = v7_arg(v7, 0);
-  arg1 = v7_arg(v7, 1);
-
-  rcode = to_string(v7, arg0, &arg0, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = to_number_v(v7, arg1, &arg1);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (is_finite(v7, arg1)) {
-    base = v7_get_double(v7, arg1);
-  } else {
-    base = 0;
-  }
-
-  if (base == 0) {
-    base = 10;
-  }
-
-  if (base < 2 || base > 36) {
-    *res = V7_TAG_NAN;
-    goto clean;
-  }
-
-  {
-    size_t str_len;
-    p = (char *) v7_get_string(v7, &arg0, &str_len);
-  }
-
-  /* Strip leading whitespaces */
-  while (*p != '\0' && isspace(*(unsigned char *) p)) {
-    p++;
-  }
-
-  if (*p == '+') {
-    sign = 1;
-    p++;
-  } else if (*p == '-') {
-    sign = -1;
-    p++;
-  }
-
-  if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
-    base = 16;
-    p += 2;
-  }
-
-  n = strtol(p, &end, base);
-
-  *res = (p == end) ? V7_TAG_NAN : v7_mk_number(v7, n * sign);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Std_parseFloat(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = V7_UNDEFINED;
-  char buf[20], *p = buf, *end;
-  double result;
-
-  rcode = to_primitive(v7, v7_arg(v7, 0), V7_TO_PRIMITIVE_HINT_NUMBER, &arg0);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (v7_is_string(arg0)) {
-    size_t str_len;
-    p = (char *) v7_get_string(v7, &arg0, &str_len);
-  } else {
-    rcode = to_string(v7, arg0, NULL, buf, sizeof(buf), NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-    buf[sizeof(buf) - 1] = '\0';
-  }
-
-  while (*p != '\0' && isspace(*(unsigned char *) p)) {
-    p++;
-  }
-
-  result = cs_strtod(p, &end);
-
-  *res = (p == end) ? V7_TAG_NAN : v7_mk_number(v7, result);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Std_isNaN(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = V7_TAG_NAN;
-  rcode = to_number_v(v7, v7_arg(v7, 0), &arg0);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  *res = v7_mk_boolean(v7, isnan(v7_get_double(v7, arg0)));
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Std_isFinite(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t arg0 = V7_TAG_NAN;
-
-  rcode = to_number_v(v7, v7_arg(v7, 0), &arg0);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  *res = v7_mk_boolean(v7, is_finite(v7, arg0));
-
-clean:
-  return rcode;
-}
-
-#ifndef NO_LIBC
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Std_exit(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  long exit_code;
-
-  (void) res;
-
-  rcode = to_long(v7, v7_arg(v7, 0), 0, &exit_code);
-  if (rcode != V7_OK) {
-    /* `to_long` has thrown, so, will return 1 */
-    exit_code = 1;
-  }
-  exit(exit_code);
-
-  return rcode;
-}
-#endif
-
-/*
- * Initialize standard library.
- *
- * This function is used only internally, but used in a complicated mix of
- * configurations, hence the commented V7_PRIVATE
- */
-/*V7_PRIVATE*/ void init_stdlib(struct v7 *v7) {
-  v7_prop_attr_desc_t attr_internal =
-      (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0));
-
-  /*
-   * Ensure the first call to v7_mk_value will use a null proto:
-   * {}.__proto__.__proto__ == null
-   */
-  v7->vals.object_prototype = mk_object(v7, V7_NULL);
-  v7->vals.array_prototype = v7_mk_object(v7);
-  v7->vals.boolean_prototype = v7_mk_object(v7);
-  v7->vals.string_prototype = v7_mk_object(v7);
-  v7->vals.regexp_prototype = v7_mk_object(v7);
-  v7->vals.number_prototype = v7_mk_object(v7);
-  v7->vals.error_prototype = v7_mk_object(v7);
-  v7->vals.global_object = v7_mk_object(v7);
-  v7->vals.date_prototype = v7_mk_object(v7);
-  v7->vals.function_prototype = v7_mk_object(v7);
-  v7->vals.proxy_prototype = v7_mk_object(v7);
-
-  set_method(v7, v7->vals.global_object, "eval", Std_eval, 1);
-  set_method(v7, v7->vals.global_object, "print", Std_print, 1);
-#ifndef NO_LIBC
-  set_method(v7, v7->vals.global_object, "exit", Std_exit, 1);
-#endif
-  set_method(v7, v7->vals.global_object, "parseInt", Std_parseInt, 2);
-  set_method(v7, v7->vals.global_object, "parseFloat", Std_parseFloat, 1);
-  set_method(v7, v7->vals.global_object, "isNaN", Std_isNaN, 1);
-  set_method(v7, v7->vals.global_object, "isFinite", Std_isFinite, 1);
-
-  v7_def(v7, v7->vals.global_object, "Infinity", 8, attr_internal,
-         v7_mk_number(v7, INFINITY));
-  v7_set(v7, v7->vals.global_object, "global", 6, v7->vals.global_object);
-
-  init_object(v7);
-  init_array(v7);
-  init_error(v7);
-  init_boolean(v7);
-#if V7_ENABLE__Math
-  init_math(v7);
-#endif
-  init_string(v7);
-#if V7_ENABLE__RegExp
-  init_regex(v7);
-#endif
-  init_number(v7);
-  init_json(v7);
-#if V7_ENABLE__Date
-  init_date(v7);
-#endif
-  init_function(v7);
-  init_js_stdlib(v7);
-
-#if V7_ENABLE__Proxy
-  init_proxy(v7);
-#endif
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/js_stdlib.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* clang-format off */
-/* because clang-format would break JS code, e.g. === converted to == = ... */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/exec.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-
-#define STRINGIFY(x) #x
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-static const char js_array_indexOf[] = STRINGIFY(
-    Object.defineProperty(Array.prototype, "indexOf", {
-      writable:true,
-      configurable: true,
-      value: function(a, x) {
-        var i; var r = -1; var b = +x;
-        if (!b || b < 0) b = 0;
-        for (i in this) if (i >= b && (r < 0 || i < r) && this[i] === a) r = +i;
-        return r;
-    }}););
-
-static const char js_array_lastIndexOf[] = STRINGIFY(
-    Object.defineProperty(Array.prototype, "lastIndexOf", {
-      writable:true,
-      configurable: true,
-      value: function(a, x) {
-        var i; var r = -1; var b = +x;
-        if (isNaN(b) || b < 0 || b >= this.length) b = this.length - 1;
-        for (i in this) if (i <= b && (r < 0 || i > r) && this[i] === a) r = +i;
-        return r;
-    }}););
-
-#if V7_ENABLE__Array__reduce
-static const char js_array_reduce[] = STRINGIFY(
-    Object.defineProperty(Array.prototype, "reduce", {
-      writable:true,
-      configurable: true,
-      value: function(a, b) {
-        var f = 0;
-        if (typeof(a) != "function") {
-          throw new TypeError(a + " is not a function");
-        }
-        for (var k in this) {
-          if (k > this.length) break;
-          if (f == 0 && b === undefined) {
-            b = this[k];
-            f = 1;
-          } else {
-            b = a(b, this[k], k, this);
-          }
-        }
-        return b;
-    }}););
-#endif
-
-static const char js_array_pop[] = STRINGIFY(
-    Object.defineProperty(Array.prototype, "pop", {
-      writable:true,
-      configurable: true,
-      value: function() {
-      var i = this.length - 1;
-        return this.splice(i, 1)[0];
-    }}););
-
-static const char js_array_shift[] = STRINGIFY(
-    Object.defineProperty(Array.prototype, "shift", {
-      writable:true,
-      configurable: true,
-      value: function() {
-        return this.splice(0, 1)[0];
-    }}););
-
-#if V7_ENABLE__Function__call
-static const char js_function_call[] = STRINGIFY(
-    Object.defineProperty(Function.prototype, "call", {
-      writable:true,
-      configurable: true,
-      value: function() {
-        var t = arguments.splice(0, 1)[0];
-        return this.apply(t, arguments);
-    }}););
-#endif
-
-#if V7_ENABLE__Function__bind
-static const char js_function_bind[] = STRINGIFY(
-    Object.defineProperty(Function.prototype, "bind", {
-      writable:true,
-      configurable: true,
-      value: function(t) {
-        var f = this;
-        return function() {
-          return f.apply(t, arguments);
-        };
-    }}););
-#endif
-
-#if V7_ENABLE__Blob
-static const char js_Blob[] = STRINGIFY(
-    function Blob(a) {
-      this.a = a;
-    });
-#endif
-
-static const char * const js_functions[] = {
-#if V7_ENABLE__Blob
-  js_Blob,
-#endif
-#if V7_ENABLE__Function__call
-  js_function_call,
-#endif
-#if V7_ENABLE__Function__bind
-  js_function_bind,
-#endif
-#if V7_ENABLE__Array__reduce
-  js_array_reduce,
-#endif
-  js_array_indexOf,
-  js_array_lastIndexOf,
-  js_array_pop,
-  js_array_shift
-};
-
- V7_PRIVATE void init_js_stdlib(struct v7 *v7) {
-  val_t res;
-  int i;
-
-  for(i = 0; i < (int) ARRAY_SIZE(js_functions); i++) {
-    if (v7_exec(v7, js_functions[i], &res) != V7_OK) {
-      fprintf(stderr, "ex: %s:\n", js_functions[i]);
-      v7_fprintln(stderr, v7, res);
-    }
-  }
-
-  /* TODO(lsm): re-enable in a separate PR */
-#if 0
-  v7_exec(v7, &res, STRINGIFY(
-    Array.prototype.unshift = function() {
-      var a = new Array(0, 0);
-      Array.prototype.push.apply(a, arguments);
-      Array.prototype.splice.apply(this, a);
-      return this.length;
-    };));
-#endif
-}
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/slre.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- *
- * This software is dual-licensed: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. For the terms of this
- * license, see <http://www.gnu.org/licenses/>.
- *
- * You are free to use this software under the terms of the GNU General
- * Public License, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * Alternatively, you can license this software under a commercial
- * license, as set out in <https://www.cesanta.com/license>.
- */
-
-/* Amalgamated: #include "v7/src/v7_features.h" */
-
-#include <setjmp.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifndef NO_LIBC
-#include <ctype.h>
-#endif
-
-/* Amalgamated: #include "common/utf.h" */
-/* Amalgamated: #include "v7/src/slre.h" */
-
-/* Limitations */
-#define SLRE_MAX_RANGES 32
-#define SLRE_MAX_SETS 16
-#define SLRE_MAX_REP 0xFFFF
-
-#define SLRE_MALLOC malloc
-#define SLRE_FREE free
-#define SLRE_THROW(e, err_code) longjmp((e)->jmp_buf, (err_code))
-
-static int hex(int c) {
-  if (c >= '0' && c <= '9') return c - '0';
-  if (c >= 'a' && c <= 'f') return c - 'a' + 10;
-  if (c >= 'A' && c <= 'F') return c - 'A' + 10;
-  return -SLRE_INVALID_HEX_DIGIT;
-}
-
-int nextesc(const char **p) {
-  const unsigned char *s = (unsigned char *) (*p)++;
-  switch (*s) {
-    case 0:
-      return -SLRE_UNTERM_ESC_SEQ;
-    case 'c':
-      ++*p;
-      return *s & 31;
-    case 'b':
-      return '\b';
-    case 't':
-      return '\t';
-    case 'n':
-      return '\n';
-    case 'v':
-      return '\v';
-    case 'f':
-      return '\f';
-    case 'r':
-      return '\r';
-    case '\\':
-      return '\\';
-    case 'u':
-      if (isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) &&
-          isxdigit(s[4])) {
-        (*p) += 4;
-        return hex(s[1]) << 12 | hex(s[2]) << 8 | hex(s[3]) << 4 | hex(s[4]);
-      }
-      return -SLRE_INVALID_HEX_DIGIT;
-    case 'x':
-      if (isxdigit(s[1]) && isxdigit(s[2])) {
-        (*p) += 2;
-        return (hex(s[1]) << 4) | hex(s[2]);
-      }
-      return -SLRE_INVALID_HEX_DIGIT;
-    default:
-      return -SLRE_INVALID_ESC_CHAR;
-  }
-}
-
-#if V7_ENABLE__RegExp
-
-/* Parser Information */
-struct slre_node {
-  unsigned char type;
-  union {
-    Rune c;                /* character */
-    struct slre_class *cp; /* class pointer */
-    struct {
-      struct slre_node *x;
-      union {
-        struct slre_node *y;
-        unsigned char n;
-        struct {
-          unsigned char ng; /* not greedy flag */
-          unsigned short min;
-          unsigned short max;
-        } rp;
-      } y;
-    } xy;
-  } par;
-};
-
-struct slre_range {
-  unsigned short s, e;
-};
-
-/* character class, each pair of rune's defines a range */
-struct slre_class {
-  struct slre_range *end;
-  struct slre_range spans[SLRE_MAX_RANGES];
-};
-
-struct slre_instruction {
-  unsigned char opcode;
-  union {
-    unsigned char n;
-    Rune c;                /* character */
-    struct slre_class *cp; /* class pointer */
-    struct {
-      struct slre_instruction *x;
-      union {
-        struct {
-          unsigned short min;
-          unsigned short max;
-        } rp;
-        struct slre_instruction *y;
-      } y;
-    } xy;
-  } par;
-};
-
-struct slre_prog {
-  struct slre_instruction *start, *end;
-  unsigned int num_captures;
-  int flags;
-  struct slre_class charset[SLRE_MAX_SETS];
-};
-
-struct slre_env {
-  int is_regex;
-  const char *src;
-  const char *src_end;
-  Rune curr_rune;
-
-  struct slre_prog *prog;
-  struct slre_node *pstart, *pend;
-
-  struct slre_node *caps[SLRE_MAX_CAPS];
-  unsigned int num_captures;
-  unsigned int sets_num;
-
-  int lookahead;
-  struct slre_class *curr_set;
-  int min_rep, max_rep;
-
-#if defined(__cplusplus)
-  ::jmp_buf jmp_buf;
-#else
-  jmp_buf jmp_buf;
-#endif
-};
-
-struct slre_thread {
-  struct slre_thread *prev;
-  struct slre_instruction *pc;
-  const char *start;
-  struct slre_loot loot;
-};
-
-enum slre_opcode {
-  I_END = 10, /* Terminate: match found */
-  I_ANY,
-  P_ANY = I_ANY, /* Any character except newline, . */
-  I_ANYNL,       /* Any character including newline, . */
-  I_BOL,
-  P_BOL = I_BOL, /* Beginning of line, ^ */
-  I_CH,
-  P_CH = I_CH,
-  I_EOL,
-  P_EOL = I_EOL, /* End of line, $ */
-  I_EOS,
-  P_EOS = I_EOS, /* End of string, \0 */
-  I_JUMP,
-  I_LA,
-  P_LA = I_LA,
-  I_LA_N,
-  P_LA_N = I_LA_N,
-  I_LBRA,
-  P_BRA = I_LBRA, /* Left bracket, ( */
-  I_REF,
-  P_REF = I_REF,
-  I_REP,
-  P_REP = I_REP,
-  I_REP_INI,
-  I_RBRA, /* Right bracket, ) */
-  I_SET,
-  P_SET = I_SET, /* Character set, [] */
-  I_SET_N,
-  P_SET_N = I_SET_N, /* Negated character set, [] */
-  I_SPLIT,
-  I_WORD,
-  P_WORD = I_WORD,
-  I_WORD_N,
-  P_WORD_N = I_WORD_N,
-  P_ALT, /* Alternation, | */
-  P_CAT, /* Concatentation, implicit operator */
-  L_CH = 256,
-  L_COUNT,  /* {M,N} */
-  L_EOS,    /* End of string, \0 */
-  L_LA,     /* "(?=" lookahead */
-  L_LA_CAP, /* "(?:" lookahead, capture */
-  L_LA_N,   /* "(?!" negative lookahead */
-  L_REF,    /* "\1" back-reference */
-  L_CHSET,  /* character set */
-  L_SET_N,  /* negative character set */
-  L_WORD,   /* "\b" word boundary */
-  L_WORD_N  /* "\B" non-word boundary */
-};
-
-static signed char dec(int c) {
-  if (isdigitrune(c)) return c - '0';
-  return SLRE_INVALID_DEC_DIGIT;
-}
-
-static unsigned char re_dec_digit(struct slre_env *e, int c) {
-  signed char ret = dec(c);
-  if (ret < 0) {
-    SLRE_THROW(e, SLRE_INVALID_DEC_DIGIT);
-  }
-  return ret;
-}
-
-static int re_nextc(Rune *r, const char **src, const char *src_end) {
-  *r = 0;
-  if (*src >= src_end) return 0;
-  *src += chartorune(r, *src);
-  if (*r == '\\') {
-    const char *tmp_s = *src;
-    int i = nextesc(src);
-    switch (i) {
-      case -SLRE_INVALID_ESC_CHAR:
-        *r = '\\';
-        *src = tmp_s;
-        *src += chartorune(r, *src);
-        break;
-      case -SLRE_INVALID_HEX_DIGIT:
-      default:
-        *r = i;
-    }
-    return 1;
-  }
-  return 0;
-}
-
-static int re_nextc_raw(Rune *r, const char **src, const char *src_end) {
-  *r = 0;
-  if (*src >= src_end) return 0;
-  *src += chartorune(r, *src);
-  return 0;
-}
-
-static int re_nextc_env(struct slre_env *e) {
-  return re_nextc(&e->curr_rune, &e->src, e->src_end);
-}
-
-static void re_nchset(struct slre_env *e) {
-  if (e->sets_num >= nelem(e->prog->charset)) {
-    SLRE_THROW(e, SLRE_TOO_MANY_CHARSETS);
-  }
-  e->curr_set = e->prog->charset + e->sets_num++;
-  e->curr_set->end = e->curr_set->spans;
-}
-
-static void re_rng2set(struct slre_env *e, Rune start, Rune end) {
-  if (start > end) {
-    SLRE_THROW(e, SLRE_INV_CHARSET_RANGE);
-  }
-  if (e->curr_set->end + 2 == e->curr_set->spans + nelem(e->curr_set->spans)) {
-    SLRE_THROW(e, SLRE_CHARSET_TOO_LARGE);
-  }
-  e->curr_set->end->s = start;
-  e->curr_set->end->e = end;
-  e->curr_set->end++;
-}
-
-#define re_char2set(e, c) re_rng2set(e, c, c)
-
-#define re_d_2set(e) re_rng2set(e, '0', '9')
-
-static void re_D_2set(struct slre_env *e) {
-  re_rng2set(e, 0, '0' - 1);
-  re_rng2set(e, '9' + 1, 0xFFFF);
-}
-
-static void re_s_2set(struct slre_env *e) {
-  re_char2set(e, 0x9);
-  re_rng2set(e, 0xA, 0xD);
-  re_char2set(e, 0x20);
-  re_char2set(e, 0xA0);
-  re_rng2set(e, 0x2028, 0x2029);
-  re_char2set(e, 0xFEFF);
-}
-
-static void re_S_2set(struct slre_env *e) {
-  re_rng2set(e, 0, 0x9 - 1);
-  re_rng2set(e, 0xD + 1, 0x20 - 1);
-  re_rng2set(e, 0x20 + 1, 0xA0 - 1);
-  re_rng2set(e, 0xA0 + 1, 0x2028 - 1);
-  re_rng2set(e, 0x2029 + 1, 0xFEFF - 1);
-  re_rng2set(e, 0xFEFF + 1, 0xFFFF);
-}
-
-static void re_w_2set(struct slre_env *e) {
-  re_d_2set(e);
-  re_rng2set(e, 'A', 'Z');
-  re_char2set(e, '_');
-  re_rng2set(e, 'a', 'z');
-}
-
-static void re_W_2set(struct slre_env *e) {
-  re_rng2set(e, 0, '0' - 1);
-  re_rng2set(e, '9' + 1, 'A' - 1);
-  re_rng2set(e, 'Z' + 1, '_' - 1);
-  re_rng2set(e, '_' + 1, 'a' - 1);
-  re_rng2set(e, 'z' + 1, 0xFFFF);
-}
-
-static unsigned char re_endofcount(Rune c) {
-  switch (c) {
-    case ',':
-    case '}':
-      return 1;
-  }
-  return 0;
-}
-
-static void re_ex_num_overfl(struct slre_env *e) {
-  SLRE_THROW(e, SLRE_NUM_OVERFLOW);
-}
-
-static enum slre_opcode re_countrep(struct slre_env *e) {
-  e->min_rep = 0;
-  while (e->src < e->src_end && !re_endofcount(e->curr_rune = *e->src++)) {
-    e->min_rep = e->min_rep * 10 + re_dec_digit(e, e->curr_rune);
-    if (e->min_rep >= SLRE_MAX_REP) re_ex_num_overfl(e);
-  }
-
-  if (e->curr_rune != ',') {
-    e->max_rep = e->min_rep;
-    return L_COUNT;
-  }
-  e->max_rep = 0;
-  while (e->src < e->src_end && (e->curr_rune = *e->src++) != '}') {
-    e->max_rep = e->max_rep * 10 + re_dec_digit(e, e->curr_rune);
-    if (e->max_rep >= SLRE_MAX_REP) re_ex_num_overfl(e);
-  }
-  if (!e->max_rep) {
-    e->max_rep = SLRE_MAX_REP;
-    return L_COUNT;
-  }
-
-  return L_COUNT;
-}
-
-static enum slre_opcode re_lexset(struct slre_env *e) {
-  Rune ch = 0;
-  unsigned char esc, ch_fl = 0, dash_fl = 0;
-  enum slre_opcode type = L_CHSET;
-
-  re_nchset(e);
-
-  esc = re_nextc_env(e);
-  if (!esc && e->curr_rune == '^') {
-    type = L_SET_N;
-    esc = re_nextc_env(e);
-  }
-
-  for (; esc || e->curr_rune != ']'; esc = re_nextc_env(e)) {
-    if (!e->curr_rune) {
-      SLRE_THROW(e, SLRE_MALFORMED_CHARSET);
-    }
-    if (esc) {
-      if (strchr("DdSsWw", e->curr_rune)) {
-        if (ch_fl) {
-          re_char2set(e, ch);
-          if (dash_fl) re_char2set(e, '-');
-        }
-        switch (e->curr_rune) {
-          case 'D':
-            re_D_2set(e);
-            break;
-          case 'd':
-            re_d_2set(e);
-            break;
-          case 'S':
-            re_S_2set(e);
-            break;
-          case 's':
-            re_s_2set(e);
-            break;
-          case 'W':
-            re_W_2set(e);
-            break;
-          case 'w':
-            re_w_2set(e);
-            break;
-        }
-        ch_fl = dash_fl = 0;
-        continue;
-      }
-      switch (e->curr_rune) {
-        default:
-          /* case '-':
-          case '\\':
-          case '.':
-          case '/':
-          case ']':
-          case '|': */
-          break;
-        case '0':
-          e->curr_rune = 0;
-          break;
-        case 'b':
-          e->curr_rune = '\b';
-          break;
-          /* default:
-            SLRE_THROW(e->catch_point, e->err_msg,
-            SLRE_INVALID_ESC_CHAR); */
-      }
-    } else {
-      if (e->curr_rune == '-') {
-        if (ch_fl) {
-          if (dash_fl) {
-            re_rng2set(e, ch, '-');
-            ch_fl = dash_fl = 0;
-          } else
-            dash_fl = 1;
-        } else {
-          ch = '-';
-          ch_fl = 1;
-        }
-        continue;
-      }
-    }
-    if (ch_fl) {
-      if (dash_fl) {
-        re_rng2set(e, ch, e->curr_rune);
-        ch_fl = dash_fl = 0;
-      } else {
-        re_char2set(e, ch);
-        ch = e->curr_rune;
-      }
-    } else {
-      ch = e->curr_rune;
-      ch_fl = 1;
-    }
-  }
-  if (ch_fl) {
-    re_char2set(e, ch);
-    if (dash_fl) re_char2set(e, '-');
-  }
-  return type;
-}
-
-static int re_lexer(struct slre_env *e) {
-  if (re_nextc_env(e)) {
-    switch (e->curr_rune) {
-      case '0':
-        e->curr_rune = 0;
-        return L_EOS;
-      case 'b':
-        return L_WORD;
-      case 'B':
-        return L_WORD_N;
-      case 'd':
-        re_nchset(e);
-        re_d_2set(e);
-        return L_CHSET;
-      case 'D':
-        re_nchset(e);
-        re_d_2set(e);
-        return L_SET_N;
-      case 's':
-        re_nchset(e);
-        re_s_2set(e);
-        return L_CHSET;
-      case 'S':
-        re_nchset(e);
-        re_s_2set(e);
-        return L_SET_N;
-      case 'w':
-        re_nchset(e);
-        re_w_2set(e);
-        return L_CHSET;
-      case 'W':
-        re_nchset(e);
-        re_w_2set(e);
-        return L_SET_N;
-    }
-    if (isdigitrune(e->curr_rune)) {
-      e->curr_rune -= '0';
-      if (isdigitrune(*e->src))
-        e->curr_rune = e->curr_rune * 10 + *e->src++ - '0';
-      return L_REF;
-    }
-    return L_CH;
-  }
-
-  if (e->is_regex) {
-    switch (e->curr_rune) {
-      case 0:
-        return 0;
-      case '$':
-      case ')':
-      case '*':
-      case '+':
-      case '.':
-      case '?':
-      case '^':
-      case '|':
-        return e->curr_rune;
-      case '{':
-        return re_countrep(e);
-      case '[':
-        return re_lexset(e);
-      case '(':
-        if (e->src[0] == '?') switch (e->src[1]) {
-            case '=':
-              e->src += 2;
-              return L_LA;
-            case ':':
-              e->src += 2;
-              return L_LA_CAP;
-            case '!':
-              e->src += 2;
-              return L_LA_N;
-          }
-        return '(';
-    }
-  } else if (e->curr_rune == 0) {
-    return 0;
-  }
-
-  return L_CH;
-}
-
-#define RE_NEXT(env) (env)->lookahead = re_lexer(env)
-#define RE_ACCEPT(env, t) ((env)->lookahead == (t) ? RE_NEXT(env), 1 : 0)
-
-static struct slre_node *re_nnode(struct slre_env *e, int type) {
-  memset(e->pend, 0, sizeof(struct slre_node));
-  e->pend->type = type;
-  return e->pend++;
-}
-
-static unsigned char re_isemptynd(struct slre_node *nd) {
-  if (!nd) return 1;
-  switch (nd->type) {
-    default:
-      return 1;
-    case P_ANY:
-    case P_CH:
-    case P_SET:
-    case P_SET_N:
-      return 0;
-    case P_BRA:
-    case P_REF:
-      return re_isemptynd(nd->par.xy.x);
-    case P_CAT:
-      return re_isemptynd(nd->par.xy.x) && re_isemptynd(nd->par.xy.y.y);
-    case P_ALT:
-      return re_isemptynd(nd->par.xy.x) || re_isemptynd(nd->par.xy.y.y);
-    case P_REP:
-      return re_isemptynd(nd->par.xy.x) || !nd->par.xy.y.rp.min;
-  }
-}
-
-static struct slre_node *re_nrep(struct slre_env *e, struct slre_node *nd,
-                                 int ng, unsigned short min,
-                                 unsigned short max) {
-  struct slre_node *rep = re_nnode(e, P_REP);
-  if (max == SLRE_MAX_REP && re_isemptynd(nd)) {
-    SLRE_THROW(e, SLRE_INF_LOOP_M_EMP_STR);
-  }
-  rep->par.xy.y.rp.ng = ng;
-  rep->par.xy.y.rp.min = min;
-  rep->par.xy.y.rp.max = max;
-  rep->par.xy.x = nd;
-  return rep;
-}
-
-static struct slre_node *re_parser(struct slre_env *e);
-
-static struct slre_node *re_parse_la(struct slre_env *e) {
-  struct slre_node *nd;
-  int min, max;
-  switch (e->lookahead) {
-    case '^':
-      RE_NEXT(e);
-      return re_nnode(e, P_BOL);
-    case '$':
-      RE_NEXT(e);
-      return re_nnode(e, P_EOL);
-    case L_EOS:
-      RE_NEXT(e);
-      return re_nnode(e, P_EOS);
-    case L_WORD:
-      RE_NEXT(e);
-      return re_nnode(e, P_WORD);
-    case L_WORD_N:
-      RE_NEXT(e);
-      return re_nnode(e, P_WORD_N);
-  }
-
-  switch (e->lookahead) {
-    case L_CH:
-      nd = re_nnode(e, P_CH);
-      nd->par.c = e->curr_rune;
-      RE_NEXT(e);
-      break;
-    case L_CHSET:
-      nd = re_nnode(e, P_SET);
-      nd->par.cp = e->curr_set;
-      RE_NEXT(e);
-      break;
-    case L_SET_N:
-      nd = re_nnode(e, P_SET_N);
-      nd->par.cp = e->curr_set;
-      RE_NEXT(e);
-      break;
-    case L_REF:
-      nd = re_nnode(e, P_REF);
-      if (!e->curr_rune || e->curr_rune > e->num_captures ||
-          !e->caps[e->curr_rune]) {
-        SLRE_THROW(e, SLRE_INVALID_BACK_REFERENCE);
-      }
-      nd->par.xy.y.n = e->curr_rune;
-      nd->par.xy.x = e->caps[e->curr_rune];
-      RE_NEXT(e);
-      break;
-    case '.':
-      RE_NEXT(e);
-      nd = re_nnode(e, P_ANY);
-      break;
-    case '(':
-      RE_NEXT(e);
-      nd = re_nnode(e, P_BRA);
-      if (e->num_captures == SLRE_MAX_CAPS) {
-        SLRE_THROW(e, SLRE_TOO_MANY_CAPTURES);
-      }
-      nd->par.xy.y.n = e->num_captures++;
-      nd->par.xy.x = re_parser(e);
-      e->caps[nd->par.xy.y.n] = nd;
-      if (!RE_ACCEPT(e, ')')) {
-        SLRE_THROW(e, SLRE_UNMATCH_LBR);
-      }
-      break;
-    case L_LA:
-      RE_NEXT(e);
-      nd = re_nnode(e, P_LA);
-      nd->par.xy.x = re_parser(e);
-      if (!RE_ACCEPT(e, ')')) {
-        SLRE_THROW(e, SLRE_UNMATCH_LBR);
-      }
-      break;
-    case L_LA_CAP:
-      RE_NEXT(e);
-      nd = re_parser(e);
-      if (!RE_ACCEPT(e, ')')) {
-        SLRE_THROW(e, SLRE_UNMATCH_LBR);
-      }
-      break;
-    case L_LA_N:
-      RE_NEXT(e);
-      nd = re_nnode(e, P_LA_N);
-      nd->par.xy.x = re_parser(e);
-      if (!RE_ACCEPT(e, ')')) {
-        SLRE_THROW(e, SLRE_UNMATCH_LBR);
-      }
-      break;
-    default:
-      SLRE_THROW(e, SLRE_SYNTAX_ERROR);
-  }
-
-  switch (e->lookahead) {
-    case '*':
-      RE_NEXT(e);
-      return re_nrep(e, nd, RE_ACCEPT(e, '?'), 0, SLRE_MAX_REP);
-    case '+':
-      RE_NEXT(e);
-      return re_nrep(e, nd, RE_ACCEPT(e, '?'), 1, SLRE_MAX_REP);
-    case '?':
-      RE_NEXT(e);
-      return re_nrep(e, nd, RE_ACCEPT(e, '?'), 0, 1);
-    case L_COUNT:
-      min = e->min_rep, max = e->max_rep;
-      RE_NEXT(e);
-      if (max < min) {
-        SLRE_THROW(e, SLRE_INVALID_QUANTIFIER);
-      }
-      return re_nrep(e, nd, RE_ACCEPT(e, '?'), min, max);
-  }
-  return nd;
-}
-
-static unsigned char re_endofcat(Rune c, int is_regex) {
-  switch (c) {
-    case 0:
-      return 1;
-    case '|':
-    case ')':
-      if (is_regex) return 1;
-  }
-  return 0;
-}
-
-static struct slre_node *re_parser(struct slre_env *e) {
-  struct slre_node *alt = NULL, *cat, *nd;
-  if (!re_endofcat(e->lookahead, e->is_regex)) {
-    cat = re_parse_la(e);
-    while (!re_endofcat(e->lookahead, e->is_regex)) {
-      nd = cat;
-      cat = re_nnode(e, P_CAT);
-      cat->par.xy.x = nd;
-      cat->par.xy.y.y = re_parse_la(e);
-    }
-    alt = cat;
-  }
-  if (e->lookahead == '|') {
-    RE_NEXT(e);
-    nd = alt;
-    alt = re_nnode(e, P_ALT);
-    alt->par.xy.x = nd;
-    alt->par.xy.y.y = re_parser(e);
-  }
-  return alt;
-}
-
-static unsigned int re_nodelen(struct slre_node *nd) {
-  unsigned int n = 0;
-  if (!nd) return 0;
-  switch (nd->type) {
-    case P_ALT:
-      n = 2;
-    case P_CAT:
-      return re_nodelen(nd->par.xy.x) + re_nodelen(nd->par.xy.y.y) + n;
-    case P_BRA:
-    case P_LA:
-    case P_LA_N:
-      return re_nodelen(nd->par.xy.x) + 2;
-    case P_REP:
-      n = nd->par.xy.y.rp.max - nd->par.xy.y.rp.min;
-      switch (nd->par.xy.y.rp.min) {
-        case 0:
-          if (!n) return 0;
-          if (nd->par.xy.y.rp.max >= SLRE_MAX_REP)
-            return re_nodelen(nd->par.xy.x) + 2;
-        case 1:
-          if (!n) return re_nodelen(nd->par.xy.x);
-          if (nd->par.xy.y.rp.max >= SLRE_MAX_REP)
-            return re_nodelen(nd->par.xy.x) + 1;
-        default:
-          n = 4;
-          if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) n++;
-          return re_nodelen(nd->par.xy.x) + n;
-      }
-    default:
-      return 1;
-  }
-}
-
-static struct slre_instruction *re_newinst(struct slre_prog *prog, int opcode) {
-  memset(prog->end, 0, sizeof(struct slre_instruction));
-  prog->end->opcode = opcode;
-  return prog->end++;
-}
-
-static void re_compile(struct slre_env *e, struct slre_node *nd) {
-  struct slre_instruction *inst, *split, *jump, *rep;
-  unsigned int n;
-
-  if (!nd) return;
-
-  switch (nd->type) {
-    case P_ALT:
-      split = re_newinst(e->prog, I_SPLIT);
-      re_compile(e, nd->par.xy.x);
-      jump = re_newinst(e->prog, I_JUMP);
-      re_compile(e, nd->par.xy.y.y);
-      split->par.xy.x = split + 1;
-      split->par.xy.y.y = jump + 1;
-      jump->par.xy.x = e->prog->end;
-      break;
-
-    case P_ANY:
-      re_newinst(e->prog, I_ANY);
-      break;
-
-    case P_BOL:
-      re_newinst(e->prog, I_BOL);
-      break;
-
-    case P_BRA:
-      inst = re_newinst(e->prog, I_LBRA);
-      inst->par.n = nd->par.xy.y.n;
-      re_compile(e, nd->par.xy.x);
-      inst = re_newinst(e->prog, I_RBRA);
-      inst->par.n = nd->par.xy.y.n;
-      break;
-
-    case P_CAT:
-      re_compile(e, nd->par.xy.x);
-      re_compile(e, nd->par.xy.y.y);
-      break;
-
-    case P_CH:
-      inst = re_newinst(e->prog, I_CH);
-      inst->par.c = nd->par.c;
-      break;
-
-    case P_EOL:
-      re_newinst(e->prog, I_EOL);
-      break;
-
-    case P_EOS:
-      re_newinst(e->prog, I_EOS);
-      break;
-
-    case P_LA:
-      split = re_newinst(e->prog, I_LA);
-      re_compile(e, nd->par.xy.x);
-      re_newinst(e->prog, I_END);
-      split->par.xy.x = split + 1;
-      split->par.xy.y.y = e->prog->end;
-      break;
-    case P_LA_N:
-      split = re_newinst(e->prog, I_LA_N);
-      re_compile(e, nd->par.xy.x);
-      re_newinst(e->prog, I_END);
-      split->par.xy.x = split + 1;
-      split->par.xy.y.y = e->prog->end;
-      break;
-
-    case P_REF:
-      inst = re_newinst(e->prog, I_REF);
-      inst->par.n = nd->par.xy.y.n;
-      break;
-
-    case P_REP:
-      n = nd->par.xy.y.rp.max - nd->par.xy.y.rp.min;
-      switch (nd->par.xy.y.rp.min) {
-        case 0:
-          if (!n) break;
-          if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) {
-            split = re_newinst(e->prog, I_SPLIT);
-            re_compile(e, nd->par.xy.x);
-            jump = re_newinst(e->prog, I_JUMP);
-            jump->par.xy.x = split;
-            split->par.xy.x = split + 1;
-            split->par.xy.y.y = e->prog->end;
-            if (nd->par.xy.y.rp.ng) {
-              split->par.xy.y.y = split + 1;
-              split->par.xy.x = e->prog->end;
-            }
-            break;
-          }
-        case 1:
-          if (!n) {
-            re_compile(e, nd->par.xy.x);
-            break;
-          }
-          if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) {
-            inst = e->prog->end;
-            re_compile(e, nd->par.xy.x);
-            split = re_newinst(e->prog, I_SPLIT);
-            split->par.xy.x = inst;
-            split->par.xy.y.y = e->prog->end;
-            if (nd->par.xy.y.rp.ng) {
-              split->par.xy.y.y = inst;
-              split->par.xy.x = e->prog->end;
-            }
-            break;
-          }
-        default:
-          inst = re_newinst(e->prog, I_REP_INI);
-          inst->par.xy.y.rp.min = nd->par.xy.y.rp.min;
-          inst->par.xy.y.rp.max = n;
-          rep = re_newinst(e->prog, I_REP);
-          split = re_newinst(e->prog, I_SPLIT);
-          re_compile(e, nd->par.xy.x);
-          jump = re_newinst(e->prog, I_JUMP);
-          jump->par.xy.x = rep;
-          rep->par.xy.x = e->prog->end;
-          split->par.xy.x = split + 1;
-          split->par.xy.y.y = e->prog->end;
-          if (nd->par.xy.y.rp.ng) {
-            split->par.xy.y.y = split + 1;
-            split->par.xy.x = e->prog->end;
-          }
-          if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) {
-            inst = split + 1;
-            split = re_newinst(e->prog, I_SPLIT);
-            split->par.xy.x = inst;
-            split->par.xy.y.y = e->prog->end;
-            if (nd->par.xy.y.rp.ng) {
-              split->par.xy.y.y = inst;
-              split->par.xy.x = e->prog->end;
-            }
-            break;
-          }
-          break;
-      }
-      break;
-
-    case P_SET:
-      inst = re_newinst(e->prog, I_SET);
-      inst->par.cp = nd->par.cp;
-      break;
-    case P_SET_N:
-      inst = re_newinst(e->prog, I_SET_N);
-      inst->par.cp = nd->par.cp;
-      break;
-
-    case P_WORD:
-      re_newinst(e->prog, I_WORD);
-      break;
-    case P_WORD_N:
-      re_newinst(e->prog, I_WORD_N);
-      break;
-  }
-}
-
-#ifdef RE_TEST
-static void print_set(struct slre_class *cp) {
-  struct slre_range *p;
-  for (p = cp->spans; p < cp->end; p++) {
-    printf("%s", p == cp->spans ? "'" : ",'");
-    printf(
-        p->s >= 32 && p->s < 127 ? "%c" : (p->s < 256 ? "\\x%02X" : "\\u%04X"),
-        p->s);
-    if (p->s != p->e) {
-      printf(p->e >= 32 && p->e < 127 ? "-%c"
-                                      : (p->e < 256 ? "-\\x%02X" : "-\\u%04X"),
-             p->e);
-    }
-    printf("'");
-  }
-  printf("]");
-}
-
-static void node_print(struct slre_node *nd) {
-  if (!nd) {
-    printf("Empty");
-    return;
-  }
-  switch (nd->type) {
-    case P_ALT:
-      printf("{");
-      node_print(nd->par.xy.x);
-      printf(" | ");
-      node_print(nd->par.xy.y.y);
-      printf("}");
-      break;
-    case P_ANY:
-      printf(".");
-      break;
-    case P_BOL:
-      printf("^");
-      break;
-    case P_BRA:
-      node_print(nd->par.xy.x);
-      printf(")");
-      break;
-    case P_CAT:
-      printf("{");
-      node_print(nd->par.xy.x);
-      printf(" & ");
-      node_print(nd->par.xy.y.y);
-      printf("}");
-      break;
-    case P_CH:
-      printf(nd->par.c >= 32 && nd->par.c < 127 ? "'%c'" : "'\\u%04X'",
-             nd->par.c);
-      break;
-    case P_EOL:
-      printf("$");
-      break;
-    case P_EOS:
-      printf("\\0");
-      break;
-    case P_LA:
-      printf("LA(");
-      node_print(nd->par.xy.x);
-      printf(")");
-      break;
-    case P_LA_N:
-      printf("LA_N(");
-      node_print(nd->par.xy.x);
-      printf(")");
-      break;
-    case P_REF:
-      printf("\\%d", nd->par.xy.y.n);
-      break;
-    case P_REP:
-      node_print(nd->par.xy.x);
-      printf(nd->par.xy.y.rp.ng ? "{%d,%d}?" : "{%d,%d}", nd->par.xy.y.rp.min,
-             nd->par.xy.y.rp.max);
-      break;
-    case P_SET:
-      printf("[");
-      print_set(nd->par.cp);
-      break;
-    case P_SET_N:
-      printf("[^");
-      print_set(nd->par.cp);
-      break;
-    case P_WORD:
-      printf("\\b");
-      break;
-    case P_WORD_N:
-      printf("\\B");
-      break;
-  }
-}
-
-static void program_print(struct slre_prog *prog) {
-  struct slre_instruction *inst;
-  for (inst = prog->start; inst < prog->end; ++inst) {
-    printf("%3d: ", inst - prog->start);
-    switch (inst->opcode) {
-      case I_END:
-        puts("end");
-        break;
-      case I_ANY:
-        puts(".");
-        break;
-      case I_ANYNL:
-        puts(". | '\\r' | '\\n'");
-        break;
-      case I_BOL:
-        puts("^");
-        break;
-      case I_CH:
-        printf(
-            inst->par.c >= 32 && inst->par.c < 127 ? "'%c'\n" : "'\\u%04X'\n",
-            inst->par.c);
-        break;
-      case I_EOL:
-        puts("$");
-        break;
-      case I_EOS:
-        puts("\\0");
-        break;
-      case I_JUMP:
-        printf("-->%d\n", inst->par.xy.x - prog->start);
-        break;
-      case I_LA:
-        printf("la %d %d\n", inst->par.xy.x - prog->start,
-               inst->par.xy.y.y - prog->start);
-        break;
-      case I_LA_N:
-        printf("la_n %d %d\n", inst->par.xy.x - prog->start,
-               inst->par.xy.y.y - prog->start);
-        break;
-      case I_LBRA:
-        printf("( %d\n", inst->par.n);
-        break;
-      case I_RBRA:
-        printf(") %d\n", inst->par.n);
-        break;
-      case I_SPLIT:
-        printf("-->%d | -->%d\n", inst->par.xy.x - prog->start,
-               inst->par.xy.y.y - prog->start);
-        break;
-      case I_REF:
-        printf("\\%d\n", inst->par.n);
-        break;
-      case I_REP:
-        printf("repeat -->%d\n", inst->par.xy.x - prog->start);
-        break;
-      case I_REP_INI:
-        printf("init_rep %d %d\n", inst->par.xy.y.rp.min,
-               inst->par.xy.y.rp.min + inst->par.xy.y.rp.max);
-        break;
-      case I_SET:
-        printf("[");
-        print_set(inst->par.cp);
-        puts("");
-        break;
-      case I_SET_N:
-        printf("[^");
-        print_set(inst->par.cp);
-        puts("");
-        break;
-      case I_WORD:
-        puts("\\w");
-        break;
-      case I_WORD_N:
-        puts("\\W");
-        break;
-    }
-  }
-}
-#endif
-
-int slre_compile(const char *pat, size_t pat_len, const char *flags,
-                 volatile size_t fl_len, struct slre_prog **pr, int is_regex) {
-  struct slre_env e;
-  struct slre_node *nd;
-  struct slre_instruction *split, *jump;
-  int err_code;
-
-  e.is_regex = is_regex;
-  e.prog = (struct slre_prog *) SLRE_MALLOC(sizeof(struct slre_prog));
-  e.pstart = e.pend =
-      (struct slre_node *) SLRE_MALLOC(sizeof(struct slre_node) * pat_len * 2);
-  e.prog->flags = is_regex ? SLRE_FLAG_RE : 0;
-
-  if ((err_code = setjmp(e.jmp_buf)) != SLRE_OK) {
-    SLRE_FREE(e.pstart);
-    SLRE_FREE(e.prog);
-    return err_code;
-  }
-
-  while (fl_len--) {
-    switch (flags[fl_len]) {
-      case 'g':
-        e.prog->flags |= SLRE_FLAG_G;
-        break;
-      case 'i':
-        e.prog->flags |= SLRE_FLAG_I;
-        break;
-      case 'm':
-        e.prog->flags |= SLRE_FLAG_M;
-        break;
-    }
-  }
-
-  e.src = pat;
-  e.src_end = pat + pat_len;
-  e.sets_num = 0;
-  e.num_captures = 1;
-  /*e.flags = flags;*/
-  memset(e.caps, 0, sizeof(e.caps));
-
-  RE_NEXT(&e);
-  nd = re_parser(&e);
-  if (e.lookahead == ')') {
-    SLRE_THROW(&e, SLRE_UNMATCH_RBR);
-  }
-  if (e.lookahead != 0) {
-    SLRE_THROW(&e, SLRE_SYNTAX_ERROR);
-  }
-
-  e.prog->num_captures = e.num_captures;
-  e.prog->start = e.prog->end = (struct slre_instruction *) SLRE_MALLOC(
-      (re_nodelen(nd) + 6) * sizeof(struct slre_instruction));
-
-  split = re_newinst(e.prog, I_SPLIT);
-  split->par.xy.x = split + 3;
-  split->par.xy.y.y = split + 1;
-  re_newinst(e.prog, I_ANYNL);
-  jump = re_newinst(e.prog, I_JUMP);
-  jump->par.xy.x = split;
-  re_newinst(e.prog, I_LBRA);
-  re_compile(&e, nd);
-  re_newinst(e.prog, I_RBRA);
-  re_newinst(e.prog, I_END);
-
-#ifdef RE_TEST
-  node_print(nd);
-  putchar('\n');
-  program_print(e.prog);
-#endif
-
-  SLRE_FREE(e.pstart);
-
-  if (pr != NULL) {
-    *pr = e.prog;
-  } else {
-    slre_free(e.prog);
-  }
-
-  return err_code;
-}
-
-void slre_free(struct slre_prog *prog) {
-  if (prog) {
-    SLRE_FREE(prog->start);
-    SLRE_FREE(prog);
-  }
-}
-
-static struct slre_thread *re_newthread(struct slre_thread *t,
-                                        struct slre_instruction *pc,
-                                        const char *start,
-                                        struct slre_loot *loot) {
-  struct slre_thread *new_thread =
-      (struct slre_thread *) SLRE_MALLOC(sizeof(struct slre_thread));
-  if (new_thread != NULL) new_thread->prev = t;
-  t->pc = pc;
-  t->start = start;
-  t->loot = *loot;
-  return new_thread;
-}
-
-static struct slre_thread *get_prev_thread(struct slre_thread *t) {
-  struct slre_thread *tmp_thr = t->prev;
-  SLRE_FREE(t);
-  return tmp_thr;
-}
-
-static void free_threads(struct slre_thread *t) {
-  while (t->prev != NULL) t = get_prev_thread(t);
-}
-
-static unsigned char re_match(struct slre_instruction *pc, const char *current,
-                              const char *end, const char *bol,
-                              unsigned int flags, struct slre_loot *loot) {
-  struct slre_loot sub, tmpsub;
-  Rune c, r;
-  struct slre_range *p;
-  size_t i;
-  struct slre_thread thread, *curr_thread, *tmp_thr;
-
-  /* queue initial thread */
-  thread.prev = NULL;
-  curr_thread = re_newthread(&thread, pc, current, loot);
-
-  /* run threads in stack order */
-  do {
-    curr_thread = get_prev_thread(curr_thread);
-    pc = curr_thread->pc;
-    current = curr_thread->start;
-    sub = curr_thread->loot;
-    for (;;) {
-      switch (pc->opcode) {
-        case I_END:
-          memcpy(loot->caps, sub.caps, sizeof loot->caps);
-          free_threads(curr_thread);
-          return 1;
-        case I_ANY:
-        case I_ANYNL:
-          if (current < end) {
-            current += chartorune(&c, current);
-            if (c && !(pc->opcode == I_ANY && isnewline(c))) break;
-          }
-          goto no_match;
-
-        case I_BOL:
-          if (current == bol) break;
-          if ((flags & SLRE_FLAG_M) && isnewline(current[-1])) break;
-          goto no_match;
-        case I_CH:
-          if (current < end) {
-            current += chartorune(&c, current);
-            if (c &&
-                (c == pc->par.c || ((flags & SLRE_FLAG_I) &&
-                                    tolowerrune(c) == tolowerrune(pc->par.c))))
-              break;
-          }
-          goto no_match;
-        case I_EOL:
-          if (current >= end) break;
-          if ((flags & SLRE_FLAG_M) && isnewline(*current)) break;
-          goto no_match;
-        case I_EOS:
-          if (current >= end) break;
-          goto no_match;
-
-        case I_JUMP:
-          pc = pc->par.xy.x;
-          continue;
-
-        case I_LA:
-          if (re_match(pc->par.xy.x, current, end, bol, flags, &sub)) {
-            pc = pc->par.xy.y.y;
-            continue;
-          }
-          goto no_match;
-        case I_LA_N:
-          tmpsub = sub;
-          if (!re_match(pc->par.xy.x, current, end, bol, flags, &tmpsub)) {
-            pc = pc->par.xy.y.y;
-            continue;
-          }
-          goto no_match;
-
-        case I_LBRA:
-          sub.caps[pc->par.n].start = current;
-          break;
-
-        case I_REF:
-          i = sub.caps[pc->par.n].end - sub.caps[pc->par.n].start;
-          if (flags & SLRE_FLAG_I) {
-            int num = i;
-            const char *s = current, *p = sub.caps[pc->par.n].start;
-            Rune rr;
-            for (; num && *s && *p; num--) {
-              s += chartorune(&r, s);
-              p += chartorune(&rr, p);
-              if (tolowerrune(r) != tolowerrune(rr)) break;
-            }
-            if (num) goto no_match;
-          } else if (strncmp(current, sub.caps[pc->par.n].start, i)) {
-            goto no_match;
-          }
-          if (i > 0) current += i;
-          break;
-
-        case I_REP:
-          if (pc->par.xy.y.rp.min) {
-            pc->par.xy.y.rp.min--;
-            pc++;
-          } else if (!pc->par.xy.y.rp.max--) {
-            pc = pc->par.xy.x;
-            continue;
-          }
-          break;
-
-        case I_REP_INI:
-          (pc + 1)->par.xy.y.rp.min = pc->par.xy.y.rp.min;
-          (pc + 1)->par.xy.y.rp.max = pc->par.xy.y.rp.max;
-          break;
-
-        case I_RBRA:
-          sub.caps[pc->par.n].end = current;
-          break;
-
-        case I_SET:
-        case I_SET_N:
-          if (current >= end) goto no_match;
-          current += chartorune(&c, current);
-          if (!c) goto no_match;
-
-          i = 1;
-          for (p = pc->par.cp->spans; i && p < pc->par.cp->end; p++)
-            if (flags & SLRE_FLAG_I) {
-              for (r = p->s; r <= p->e; ++r)
-                if (tolowerrune(c) == tolowerrune(r)) {
-                  i = 0;
-                  break;
-                }
-            } else if (p->s <= c && c <= p->e)
-              i = 0;
-
-          if (pc->opcode == I_SET) i = !i;
-          if (i) break;
-          goto no_match;
-
-        case I_SPLIT:
-          tmp_thr = curr_thread;
-          curr_thread =
-              re_newthread(curr_thread, pc->par.xy.y.y, current, &sub);
-          if (curr_thread == NULL) {
-            fprintf(stderr, "re_match: no memory for thread!\n");
-            free_threads(tmp_thr);
-            return 0;
-          }
-          pc = pc->par.xy.x;
-          continue;
-
-        case I_WORD:
-        case I_WORD_N:
-          i = (current > bol && iswordchar(current[-1]));
-          if (iswordchar(current[0])) i = !i;
-          if (pc->opcode == I_WORD_N) i = !i;
-          if (i) break;
-        /* goto no_match; */
-
-        default:
-          goto no_match;
-      }
-      pc++;
-    }
-  no_match:
-    ;
-  } while (curr_thread->prev != NULL);
-  return 0;
-}
-
-int slre_exec(struct slre_prog *prog, int flag_g, const char *start,
-              const char *end, struct slre_loot *loot) {
-  struct slre_loot tmpsub;
-  const char *st = start;
-
-  if (!loot) loot = &tmpsub;
-  memset(loot, 0, sizeof(*loot));
-
-  if (!flag_g) {
-    loot->num_captures = prog->num_captures;
-    return !re_match(prog->start, start, end, start, prog->flags, loot);
-  }
-
-  while (re_match(prog->start, st, end, start, prog->flags, &tmpsub)) {
-    unsigned int i;
-    st = tmpsub.caps[0].end;
-    for (i = 0; i < prog->num_captures; i++) {
-      struct slre_cap *l = &loot->caps[loot->num_captures + i];
-      struct slre_cap *s = &tmpsub.caps[i];
-      l->start = s->start;
-      l->end = s->end;
-    }
-    loot->num_captures += prog->num_captures;
-  }
-  return !loot->num_captures;
-}
-
-int slre_replace(struct slre_loot *loot, const char *src, size_t src_len,
-                 const char *rstr, size_t rstr_len, struct slre_loot *dstsub) {
-  int size = 0, n;
-  Rune curr_rune;
-  const char *const rstr_end = rstr + rstr_len;
-
-  memset(dstsub, 0, sizeof(*dstsub));
-  while (rstr < rstr_end && !(n = re_nextc_raw(&curr_rune, &rstr, rstr_end)) &&
-         curr_rune) {
-    int sz;
-    if (n < 0) return n;
-    if (curr_rune == '$') {
-      n = re_nextc(&curr_rune, &rstr, rstr_end);
-      if (n < 0) return n;
-      switch (curr_rune) {
-        case '&':
-          sz = loot->caps[0].end - loot->caps[0].start;
-          size += sz;
-          dstsub->caps[dstsub->num_captures++] = loot->caps[0];
-          break;
-        case '0':
-        case '1':
-        case '2':
-        case '3':
-        case '4':
-        case '5':
-        case '6':
-        case '7':
-        case '8':
-        case '9': {
-          int sbn = dec(curr_rune);
-          if (0 == sbn && rstr[0] && isdigitrune(rstr[0])) {
-            n = re_nextc(&curr_rune, &rstr, rstr_end);
-            if (n < 0) return n;
-            sz = dec(curr_rune);
-            sbn = sbn * 10 + sz;
-          }
-          if (sbn >= loot->num_captures) break;
-          sz = loot->caps[sbn].end - loot->caps[sbn].start;
-          size += sz;
-          dstsub->caps[dstsub->num_captures++] = loot->caps[sbn];
-          break;
-        }
-        case '`':
-          sz = loot->caps[0].start - src;
-          size += sz;
-          dstsub->caps[dstsub->num_captures].start = src;
-          dstsub->caps[dstsub->num_captures++].end = loot->caps[0].start;
-          break;
-        case '\'':
-          sz = src + src_len - loot->caps[0].end;
-          size += sz;
-          dstsub->caps[dstsub->num_captures].start = loot->caps[0].end;
-          dstsub->caps[dstsub->num_captures++].end = loot->caps[0].end + sz;
-          break;
-        case '$':
-          size++;
-          dstsub->caps[dstsub->num_captures].start = rstr - 1;
-          dstsub->caps[dstsub->num_captures++].end = rstr;
-          break;
-        default:
-          return SLRE_BAD_CHAR_AFTER_USD;
-      }
-    } else {
-      char tmps[300], *d = tmps;
-      size += (sz = runetochar(d, &curr_rune));
-      if (!dstsub->num_captures ||
-          dstsub->caps[dstsub->num_captures - 1].end != rstr - sz) {
-        dstsub->caps[dstsub->num_captures].start = rstr - sz;
-        dstsub->caps[dstsub->num_captures++].end = rstr;
-      } else
-        dstsub->caps[dstsub->num_captures - 1].end = rstr;
-    }
-  }
-  return size;
-}
-
-int slre_match(const char *re, size_t re_len, const char *flags, size_t fl_len,
-               const char *str, size_t str_len, struct slre_loot *loot) {
-  struct slre_prog *prog = NULL;
-  int res;
-
-  if ((res = slre_compile(re, re_len, flags, fl_len, &prog, 1)) == SLRE_OK) {
-    res = slre_exec(prog, prog->flags & SLRE_FLAG_G, str, str + str_len, loot);
-    slre_free(prog);
-  }
-
-  return res;
-}
-
-int slre_get_flags(struct slre_prog *crp) {
-  return crp->flags;
-}
-
-#ifdef SLRE_TEST
-
-#include <errno.h>
-
-static const char *err_code_to_str(int err_code) {
-  static const char *ar[] = {
-      "no error", "invalid decimal digit", "invalid hex digit",
-      "invalid escape character", "invalid unterminated escape sequence",
-      "syntax error", "unmatched left parenthesis",
-      "unmatched right parenthesis", "numeric overflow",
-      "infinite loop empty string", "too many charsets",
-      "invalid charset range", "charset is too large", "malformed charset",
-      "invalid back reference", "too many captures", "invalid quantifier",
-      "bad character after $"};
-
-  typedef char static_assertion_err_codes_out_of_sync
-      [2 * !!(((sizeof(ar) / sizeof(ar[0])) == SLRE_BAD_CHAR_AFTER_USD + 1)) -
-       1];
-
-  return err_code >= 0 && err_code < (int) (sizeof(ar) / sizeof(ar[0]))
-             ? ar[err_code]
-             : "invalid error code";
-}
-
-#define RE_TEST_STR_SIZE 2000
-
-static unsigned get_flags(const char *ch) {
-  unsigned int flags = 0;
-
-  while (*ch != '\0') {
-    switch (*ch) {
-      case 'g':
-        flags |= SLRE_FLAG_G;
-        break;
-      case 'i':
-        flags |= SLRE_FLAG_I;
-        break;
-      case 'm':
-        flags |= SLRE_FLAG_M;
-        break;
-      case 'r':
-        flags |= SLRE_FLAG_RE;
-        break;
-      default:
-        return flags;
-    }
-    ch++;
-  }
-  return flags;
-}
-
-static void show_usage_and_exit(char *argv[]) {
-  fprintf(stderr, "Usage: %s [OPTIONS]\n", argv[0]);
-  fprintf(stderr, "%s\n", "OPTIONS:");
-  fprintf(stderr, "%s\n", "  -p <regex_pattern>     Regex pattern");
-  fprintf(stderr, "%s\n", "  -o <regex_flags>       Combination of g,i,m");
-  fprintf(stderr, "%s\n", "  -s <string>            String to match");
-  fprintf(stderr, "%s\n", "  -f <file_name>         Match lines from file");
-  fprintf(stderr, "%s\n", "  -n <cap_no>            Show given capture");
-  fprintf(stderr, "%s\n", "  -r <replace_str>       Replace given capture");
-  fprintf(stderr, "%s\n", "  -v                     Show verbose stats");
-  exit(1);
-}
-
-static int process_line(struct slre_prog *pr, const char *flags,
-                        const char *line, const char *cap_no,
-                        const char *replace, const char *verbose) {
-  struct slre_loot loot;
-  unsigned int fl = flags == NULL ? 0 : get_flags(flags);
-  int i, n = cap_no == NULL ? -1 : atoi(cap_no), err_code = 0;
-  struct slre_cap *cap = &loot.caps[n];
-
-  err_code =
-      slre_exec(pr, pr->flags & SLRE_FLAG_G, line, line + strlen(line), &loot);
-  if (err_code == SLRE_OK) {
-    if (n >= 0 && n < loot.num_captures && replace != NULL) {
-      struct slre_cap *cap = &loot.caps[n];
-      printf("%.*s", (int) (cap->start - line), line);
-      printf("%s", replace);
-      printf("%.*s", (int) ((line + strlen(line)) - cap->end), cap->end);
-    } else if (n >= 0 && n < loot.num_captures) {
-      printf("%.*s\n", (int) (cap->end - cap->start), cap->start);
-    }
-
-    if (verbose != NULL) {
-      fprintf(stderr, "%s\n", "Captures:");
-      for (i = 0; i < loot.num_captures; i++) {
-        fprintf(stderr, "%d [%.*s]\n", i,
-                (int) (loot.caps[i].end - loot.caps[i].start),
-                loot.caps[i].start);
-      }
-    }
-  }
-
-  return err_code;
-}
-
-int main(int argc, char **argv) {
-  const char *str = NULL, *pattern = NULL, *replace = NULL;
-  const char *flags = "", *file_name = NULL, *cap_no = NULL, *verbose = NULL;
-  struct slre_prog *pr = NULL;
-  int i, err_code = 0;
-
-  /* Execute inline code */
-  for (i = 1; i < argc; i++) {
-    if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) {
-      pattern = argv[++i];
-    } else if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) {
-      flags = argv[++i];
-    } else if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) {
-      str = argv[++i];
-    } else if (strcmp(argv[i], "-f") == 0 && i + 1 < argc) {
-      file_name = argv[++i];
-    } else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) {
-      cap_no = argv[++i];
-    } else if (strcmp(argv[i], "-r") == 0 && i + 1 < argc) {
-      replace = argv[++i];
-    } else if (strcmp(argv[i], "-v") == 0) {
-      verbose = "";
-    } else if (strcmp(argv[i], "-h") == 0) {
-      show_usage_and_exit(argv);
-    } else {
-      show_usage_and_exit(argv);
-    }
-  }
-
-  if (pattern == NULL) {
-    fprintf(stderr, "%s\n", "-p option is mandatory");
-    exit(1);
-  } else if ((err_code = slre_compile(pattern, strlen(pattern), flags,
-                                      strlen(flags), &pr, 1)) != SLRE_OK) {
-    fprintf(stderr, "slre_compile(%s): %s\n", argv[0],
-            err_code_to_str(err_code));
-    exit(1);
-  } else if (str != NULL) {
-    err_code = process_line(pr, flags, str, cap_no, replace, verbose);
-  } else if (file_name != NULL) {
-    FILE *fp = strcmp(file_name, "-") == 0 ? stdin : fopen(file_name, "rb");
-    char line[20 * 1024];
-    if (fp == NULL) {
-      fprintf(stderr, "Cannot open %s: %s\n", file_name, strerror(errno));
-      exit(1);
-    } else {
-      /* Return success if at least one line matches */
-      err_code = 1;
-      while (fgets(line, sizeof(line), fp) != NULL) {
-        if (process_line(pr, flags, line, cap_no, replace, verbose) ==
-            SLRE_OK) {
-          err_code = 0;
-        }
-      }
-      fclose(fp); /* If fp == stdin, it is safe to close, too */
-    }
-  } else {
-    fprintf(stderr, "%s\n", "Please specify one of -s or -f options");
-    exit(1);
-  }
-  slre_free(pr);
-
-  return err_code;
-}
-#endif /* SLRE_TEST */
-
-#endif /* V7_ENABLE__RegExp */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/heapusage.c"
-#endif
-/*
- * Copyright (c) 2014-2016 Cesanta Software Limited
- * All rights reserved
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-
-#if defined(V7_HEAPUSAGE_ENABLE)
-
-/*
- * A flag that is set by GC before allocating its buffers, so we can
- * distinguish these buffers from other allocations
- */
-volatile int heap_dont_count = 0;
-
-extern void *__real_malloc(size_t size);
-extern void *__real_calloc(size_t num, size_t size);
-extern void *__real_realloc(void *p, size_t size);
-extern void __real_free(void *p);
-
-/* TODO(dfrank): make it dynamically allocated from heap */
-#define CELLS_CNT (1024 * 32)
-
-typedef struct cell {
-  void *p;
-  unsigned dont_count : 1;
-  unsigned size : 31;
-} cell_t;
-
-typedef struct alloc_registry {
-  size_t used_cells_cnt;
-  size_t allocated_size;
-  size_t real_used_cells_cnt;
-  size_t real_allocated_size;
-  cell_t cells[CELLS_CNT];
-} alloc_registry_t;
-
-static alloc_registry_t registry = {0};
-
-/*
- * Make a record about an allocated buffer `p` of size `size`
- */
-static void cell_allocated(void *p, size_t size) {
-  int i;
-  int cell_num = -1;
-
-  if (p != NULL && size != 0) {
-    /* TODO(dfrank): make it dynamically allocated from heap */
-    assert(registry.real_used_cells_cnt < CELLS_CNT);
-
-    for (i = 0; i < CELLS_CNT; ++i) {
-      if (registry.cells[i].p == NULL) {
-        cell_num = i;
-        break;
-      }
-    }
-
-    assert(cell_num != -1);
-
-    registry.cells[cell_num].p = p;
-    registry.cells[cell_num].size = size;
-    registry.cells[cell_num].dont_count = !!heap_dont_count;
-
-    registry.real_allocated_size += size;
-    registry.real_used_cells_cnt += 1;
-
-    if (!heap_dont_count) {
-      registry.allocated_size += size;
-      registry.used_cells_cnt += 1;
-    }
-
-#if 0
-    printf("alloc=0x%lx, size=%lu, total=%lu\n", (unsigned long)p, size,
-        registry.allocated_size);
-#endif
-  }
-}
-
-/*
- * Delete a record about an allocated buffer `p`. If our registry does not
- * contain anything about the given pointer, the call is ignored. We can't
- * generate an error because shared libraries still use unwrapped heap
- * functions, so we can face "unknown" pointers.
- */
-static void cell_freed(void *p) {
-  int i;
-  int cell_num = -1;
-
-  if (p != NULL) {
-    assert(registry.real_used_cells_cnt > 0);
-
-    for (i = 0; i < CELLS_CNT; ++i) {
-      if (registry.cells[i].p == p) {
-        cell_num = i;
-        break;
-      }
-    }
-
-    /*
-     * NOTE: it would be nice to have `assert(cell_num != -1);`, but
-     * unfortunately not all allocations are wrapped: shared libraries will
-     * still use unwrapped mallocs, so we might get unknown pointers here.
-     */
-
-    if (cell_num != -1) {
-      registry.real_allocated_size -= registry.cells[cell_num].size;
-      registry.real_used_cells_cnt -= 1;
-
-      if (!registry.cells[cell_num].dont_count) {
-        registry.allocated_size -= registry.cells[cell_num].size;
-        registry.used_cells_cnt -= 1;
-      }
-
-      registry.cells[cell_num].p = NULL;
-      registry.cells[cell_num].size = 0;
-      registry.cells[cell_num].dont_count = 0;
-
-#if 0
-      printf("free=0x%lx, total=%lu\n", (unsigned long)p, registry.allocated_size);
-#endif
-    }
-  }
-}
-
-/*
- * Wrappers of the standard heap functions
- */
-
-void *__wrap_malloc(size_t size) {
-  void *ret = __real_malloc(size);
-  cell_allocated(ret, size);
-  return ret;
-}
-
-void *__wrap_calloc(size_t num, size_t size) {
-  void *ret = __real_calloc(num, size);
-  cell_allocated(ret, num * size);
-  return ret;
-}
-
-void *__wrap_realloc(void *p, size_t size) {
-  void *ret;
-  cell_freed(p);
-  ret = __real_realloc(p, size);
-  cell_allocated(ret, size);
-  return ret;
-}
-
-void __wrap_free(void *p) {
-  __real_free(p);
-  cell_freed(p);
-}
-
-/*
- * Small API to get some stats, see header file for details
- */
-
-size_t heapusage_alloc_size(void) {
-  return registry.allocated_size;
-}
-
-size_t heapusage_allocs_cnt(void) {
-  return registry.used_cells_cnt;
-}
-
-#endif /* V7_HEAPUSAGE_ENABLE */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/cyg_profile.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * This file contains GCC/clang instrumentation callbacks. The actual
- * code in these callbacks depends on enabled features.
- *
- * Currently, the code from different subsystems is embedded right into
- * callbacks for performance reasons. It would be probably more elegant
- * to have subsystem-specific functions that will be called from these
- * callbacks, but since the callbacks are called really a lot (on each v7
- * function call), I decided it's better to inline the code right here.
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/cyg_profile.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-
-#if defined(V7_CYG_PROFILE_ON)
-
-#if defined(V7_ENABLE_CALL_TRACE)
-
-#define CALL_TRACE_SIZE 32
-
-typedef struct {
-  uint16_t size;
-  uint16_t missed_cnt;
-  void *addresses[CALL_TRACE_SIZE];
-} call_trace_t;
-
-static call_trace_t call_trace = {0};
-
-NOINSTR
-void call_trace_print(const char *prefix, const char *suffix, size_t skip_cnt,
-                      size_t max_cnt) {
-  int i;
-  if (call_trace.missed_cnt > 0) {
-    fprintf(stderr, "missed calls! (%d) ", (int) call_trace.missed_cnt);
-  }
-  if (prefix != NULL) {
-    fprintf(stderr, "%s", prefix);
-  }
-  for (i = (int) call_trace.size - 1 - skip_cnt; i >= 0; i--) {
-    fprintf(stderr, " %lx", (unsigned long) call_trace.addresses[i]);
-    if (max_cnt > 0) {
-      if (--max_cnt == 0) {
-        break;
-      }
-    }
-  }
-  if (suffix != NULL) {
-    fprintf(stderr, "%s", suffix);
-  }
-  fprintf(stderr, "\n");
-}
-
-#endif
-
-#ifndef IRAM
-#define IRAM
-#endif
-
-#ifndef NOINSTR
-#define NOINSTR __attribute__((no_instrument_function))
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-IRAM NOINSTR void __cyg_profile_func_enter(void *this_fn, void *call_site);
-
-IRAM NOINSTR void __cyg_profile_func_exit(void *this_fn, void *call_site);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-IRAM void __cyg_profile_func_enter(void *this_fn, void *call_site) {
-#if defined(V7_STACK_GUARD_MIN_SIZE)
-  {
-    static int profile_enter = 0;
-    void *fp = __builtin_frame_address(0);
-
-    (void) call_site;
-
-    if (profile_enter || v7_sp_limit == NULL) return;
-
-    profile_enter++;
-    if (v7_head != NULL && fp < v7_head->sp_lwm) v7_head->sp_lwm = fp;
-
-    if (((int) fp - (int) v7_sp_limit) < V7_STACK_GUARD_MIN_SIZE) {
-      printf("fun %p sp %p limit %p left %d\n", this_fn, fp, v7_sp_limit,
-             (int) fp - (int) v7_sp_limit);
-      abort();
-    }
-    profile_enter--;
-  }
-#endif
-
-#if defined(V7_ENABLE_GC_CHECK)
-  {
-    (void) this_fn;
-    (void) call_site;
-  }
-#endif
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-  {
-    struct v7 *v7;
-    struct stack_track_ctx *ctx;
-    void *fp = __builtin_frame_address(1);
-
-    (void) this_fn;
-    (void) call_site;
-
-    /*
-     * TODO(dfrank): it actually won't work for multiple instances of v7 running
-     * in parallel threads. We need to know the exact v7 instance for which
-     * current function is called, but so far I failed to find a way to do this.
-     */
-    for (v7 = v7_head; v7 != NULL; v7 = v7->next_v7) {
-      for (ctx = v7->stack_track_ctx; ctx != NULL; ctx = ctx->next) {
-        /* commented because it fails on legal code compiled with -O3 */
-        /*assert(fp <= ctx->start);*/
-
-        if (fp < ctx->max) {
-          ctx->max = fp;
-        }
-      }
-    }
-  }
-#endif
-
-#if defined(V7_ENABLE_CALL_TRACE)
-  if (call_trace.size < CALL_TRACE_SIZE) {
-    call_trace.addresses[call_trace.size] = this_fn;
-    call_trace.size++;
-  } else {
-    call_trace.missed_cnt++;
-  }
-#endif
-}
-
-IRAM void __cyg_profile_func_exit(void *this_fn, void *call_site) {
-#if defined(V7_STACK_GUARD_MIN_SIZE)
-  {
-    (void) this_fn;
-    (void) call_site;
-  }
-#endif
-
-#if defined(V7_ENABLE_GC_CHECK)
-  {
-    struct v7 *v7;
-    void *fp = __builtin_frame_address(1);
-
-    (void) this_fn;
-    (void) call_site;
-
-    for (v7 = v7_head; v7 != NULL; v7 = v7->next_v7) {
-      v7_val_t **vp;
-      if (v7->owned_values.buf == NULL) continue;
-      vp = (v7_val_t **) (v7->owned_values.buf + v7->owned_values.len -
-                          sizeof(v7_val_t *));
-
-      for (; (char *) vp >= v7->owned_values.buf; vp--) {
-        /*
-         * Check if a variable belongs to a dead stack frame.
-         * Addresses lower than the parent frame belong to the
-         * stack frame of the function about to return.
-         * But the heap also usually below the stack and
-         * we don't know the end of the stack. But this hook
-         * is called at each function return, so we have
-         * to check only up to the maximum stack frame size,
-         * let's arbitrarily but reasonably set that at 8k.
-         */
-        if ((void *) *vp <= fp && (void *) *vp > (fp + 8196)) {
-          fprintf(stderr, "Found owned variable after return\n");
-          abort();
-        }
-      }
-    }
-  }
-#endif
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-  {
-    (void) this_fn;
-    (void) call_site;
-  }
-#endif
-
-#if defined(V7_ENABLE_CALL_TRACE)
-  if (call_trace.missed_cnt > 0) {
-    call_trace.missed_cnt--;
-  } else if (call_trace.size > 0) {
-    if (call_trace.addresses[call_trace.size - 1] != this_fn) {
-      abort();
-    }
-    call_trace.size--;
-  } else {
-    /*
-     * We may get here if calls to `__cyg_profile_func_exit()` and
-     * `__cyg_profile_func_enter()` are unbalanced.
-     *
-     * TODO(dfrank) understand, why in the beginning of the program execution
-     * we get here. I was sure this should be impossible.
-     */
-    /* abort(); */
-  }
-#endif
-}
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-
-void v7_stack_track_start(struct v7 *v7, struct stack_track_ctx *ctx) {
-  /* insert new context at the head of the list */
-  ctx->next = v7->stack_track_ctx;
-  v7->stack_track_ctx = ctx;
-
-  /* init both `max` and `start` to the current frame pointer */
-  ctx->max = ctx->start = __builtin_frame_address(0);
-}
-
-int v7_stack_track_end(struct v7 *v7, struct stack_track_ctx *ctx) {
-  int diff;
-
-  /* this function can be called only for the head context */
-  assert(v7->stack_track_ctx == ctx);
-
-  diff = (int) ((char *) ctx->start - (char *) ctx->max);
-
-  /* remove context from the linked list */
-  v7->stack_track_ctx = ctx->next;
-
-  return (int) diff;
-}
-
-#endif /* V7_ENABLE_STACK_TRACKING */
-#endif /* V7_CYG_PROFILE_ON */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_object.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/str_util.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/std_object.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/regexp.h" */
-/* Amalgamated: #include "v7/src/exec.h" */
-
-#if V7_ENABLE__Object__getPrototypeOf
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_getPrototypeOf(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t arg = v7_arg(v7, 0);
-
-  if (!v7_is_object(arg)) {
-    rcode =
-        v7_throwf(v7, TYPE_ERROR, "Object.getPrototypeOf called on non-object");
-    goto clean;
-  }
-  *res = v7_get_proto(v7, arg);
-
-clean:
-  return rcode;
-}
-#endif
-
-#if V7_ENABLE__Object__isPrototypeOf
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_isPrototypeOf(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t obj = v7_arg(v7, 0);
-  val_t proto = v7_get_this(v7);
-
-  *res = v7_mk_boolean(v7, is_prototype_of(v7, obj, proto));
-
-  return rcode;
-}
-#endif
-
-#if V7_ENABLE__Object__getOwnPropertyNames || V7_ENABLE__Object__keys
-/*
- * Hack to ensure that the iteration order of the keys array is consistent
- * with the iteration order if properties in `for in`
- * This will be obsoleted when arrays will have a special object type.
- */
-static void _Obj_append_reverse(struct v7 *v7, struct v7_property *p, val_t res,
-                                int i, v7_prop_attr_t ignore_flags) {
-  while (p && p->attributes & ignore_flags) p = p->next;
-  if (p == NULL) return;
-  if (p->next) _Obj_append_reverse(v7, p->next, res, i + 1, ignore_flags);
-
-  v7_array_set(v7, res, i, p->name);
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err _Obj_ownKeys(struct v7 *v7, unsigned int ignore_flags,
-                                val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t obj = v7_arg(v7, 0);
-
-  *res = v7_mk_dense_array(v7);
-
-  if (!v7_is_object(obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Object.keys called on non-object");
-    goto clean;
-  }
-
-  _Obj_append_reverse(v7, get_object_struct(obj)->properties, *res, 0,
-                      ignore_flags);
-
-clean:
-  return rcode;
-}
-#endif
-
-#if V7_ENABLE__Object__hasOwnProperty ||       \
-    V7_ENABLE__Object__propertyIsEnumerable || \
-    V7_ENABLE__Object__getOwnPropertyDescriptor
-static enum v7_err _Obj_getOwnProperty(struct v7 *v7, val_t obj, val_t name,
-                                       struct v7_property **res) {
-  enum v7_err rcode = V7_OK;
-  char name_buf[512];
-  size_t name_len;
-
-  rcode = to_string(v7, name, NULL, name_buf, sizeof(name_buf), &name_len);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  *res = v7_get_own_property(v7, obj, name_buf, name_len);
-
-clean:
-  return rcode;
-}
-#endif
-
-#if V7_ENABLE__Object__keys
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_keys(struct v7 *v7, v7_val_t *res) {
-  return _Obj_ownKeys(v7, _V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE,
-                      res);
-}
-#endif
-
-#if V7_ENABLE__Object__getOwnPropertyNames
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_getOwnPropertyNames(struct v7 *v7, v7_val_t *res) {
-  return _Obj_ownKeys(v7, _V7_PROPERTY_HIDDEN, res);
-}
-#endif
-
-#if V7_ENABLE__Object__getOwnPropertyDescriptor
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_getOwnPropertyDescriptor(struct v7 *v7,
-                                                    v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  struct v7_property *prop;
-  val_t obj = v7_arg(v7, 0);
-  val_t name = v7_arg(v7, 1);
-  val_t desc;
-
-  rcode = _Obj_getOwnProperty(v7, obj, name, &prop);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (prop == NULL) {
-    goto clean;
-  }
-
-  desc = v7_mk_object(v7);
-  v7_set(v7, desc, "value", 5, prop->value);
-  v7_set(v7, desc, "writable", 8,
-         v7_mk_boolean(v7, !(prop->attributes & V7_PROPERTY_NON_WRITABLE)));
-  v7_set(v7, desc, "enumerable", 10,
-         v7_mk_boolean(v7, !(prop->attributes & (_V7_PROPERTY_HIDDEN |
-                                                 V7_PROPERTY_NON_ENUMERABLE))));
-  v7_set(v7, desc, "configurable", 12,
-         v7_mk_boolean(v7, !(prop->attributes & V7_PROPERTY_NON_CONFIGURABLE)));
-
-  *res = desc;
-
-clean:
-  return rcode;
-}
-#endif
-
-WARN_UNUSED_RESULT
-static enum v7_err o_set_attr(struct v7 *v7, val_t desc, const char *name,
-                              size_t n, v7_prop_attr_desc_t *pattrs_delta,
-                              v7_prop_attr_desc_t flag_true,
-                              v7_prop_attr_desc_t flag_false) {
-  enum v7_err rcode = V7_OK;
-
-  val_t v = V7_UNDEFINED;
-  rcode = v7_get_throwing(v7, desc, name, n, &v);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (v7_is_truthy(v7, v)) {
-    *pattrs_delta |= flag_true;
-  } else {
-    *pattrs_delta |= flag_false;
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err _Obj_defineProperty(struct v7 *v7, val_t obj,
-                                       const char *name, int name_len,
-                                       val_t desc, val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t val = V7_UNDEFINED;
-  v7_prop_attr_desc_t attrs_desc = 0;
-
-  /*
-   * get provided value, or set `V7_DESC_PRESERVE_VALUE` flag if no value is
-   * provided at all
-   */
-  {
-    struct v7_property *prop = v7_get_property(v7, desc, "value", 5);
-    if (prop == NULL) {
-      /* no value is provided */
-      attrs_desc |= V7_DESC_PRESERVE_VALUE;
-    } else {
-      /* value is provided: use it */
-      rcode = v7_property_value(v7, desc, prop, &val);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-    }
-  }
-
-  /* Examine given properties, and set appropriate flags for `def_property` */
-
-  rcode = o_set_attr(v7, desc, "enumerable", 10, &attrs_desc,
-                     V7_DESC_ENUMERABLE(1), V7_DESC_ENUMERABLE(0));
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = o_set_attr(v7, desc, "writable", 8, &attrs_desc, V7_DESC_WRITABLE(1),
-                     V7_DESC_WRITABLE(0));
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = o_set_attr(v7, desc, "configurable", 12, &attrs_desc,
-                     V7_DESC_CONFIGURABLE(1), V7_DESC_CONFIGURABLE(0));
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  /* TODO(dfrank) : add getter/setter support */
-
-  /* Finally, do the job on defining the property */
-  rcode = def_property(v7, obj, name, name_len, attrs_desc, val,
-                       0 /*not assign*/, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  *res = obj;
-  goto clean;
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_defineProperty(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t obj = v7_arg(v7, 0);
-  val_t name = v7_arg(v7, 1);
-  val_t desc = v7_arg(v7, 2);
-  char name_buf[512];
-  size_t name_len;
-
-  if (!v7_is_object(obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "object expected");
-    goto clean;
-  }
-
-  rcode = to_string(v7, name, NULL, name_buf, sizeof(name_buf), &name_len);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = _Obj_defineProperty(v7, obj, name_buf, name_len, desc, res);
-  goto clean;
-
-clean:
-  return rcode;
-}
-
-#if V7_ENABLE__Object__create || V7_ENABLE__Object__defineProperties
-WARN_UNUSED_RESULT
-static enum v7_err o_define_props(struct v7 *v7, val_t obj, val_t descs,
-                                  val_t *res) {
-  enum v7_err rcode = V7_OK;
-  struct v7_property *p;
-
-  if (!v7_is_object(descs)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "object expected");
-    goto clean;
-  }
-
-  for (p = get_object_struct(descs)->properties; p; p = p->next) {
-    size_t n;
-    const char *s = v7_get_string(v7, &p->name, &n);
-    if (p->attributes & (_V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE)) {
-      continue;
-    }
-    rcode = _Obj_defineProperty(v7, obj, s, n, p->value, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-clean:
-  return rcode;
-}
-#endif
-
-#if V7_ENABLE__Object__defineProperties
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_defineProperties(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t descs = V7_UNDEFINED;
-
-  *res = v7_arg(v7, 0);
-  descs = v7_arg(v7, 1);
-  rcode = o_define_props(v7, *res, descs, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-#endif
-
-#if V7_ENABLE__Object__create
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_create(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t proto = v7_arg(v7, 0);
-  val_t descs = v7_arg(v7, 1);
-  if (!v7_is_null(proto) && !v7_is_object(proto)) {
-    rcode = v7_throwf(v7, TYPE_ERROR,
-                      "Object prototype may only be an Object or null");
-    goto clean;
-  }
-  *res = mk_object(v7, proto);
-  if (v7_is_object(descs)) {
-    rcode = o_define_props(v7, *res, descs, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-clean:
-  return rcode;
-}
-#endif
-
-#if V7_ENABLE__Object__propertyIsEnumerable
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_propertyIsEnumerable(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  struct v7_property *prop;
-  val_t name = v7_arg(v7, 0);
-
-  rcode = _Obj_getOwnProperty(v7, this_obj, name, &prop);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (prop == NULL) {
-    *res = v7_mk_boolean(v7, 0);
-  } else {
-    *res =
-        v7_mk_boolean(v7, !(prop->attributes & (_V7_PROPERTY_HIDDEN |
-                                                V7_PROPERTY_NON_ENUMERABLE)));
-  }
-
-  goto clean;
-
-clean:
-  return rcode;
-}
-#endif
-
-#if V7_ENABLE__Object__hasOwnProperty
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_hasOwnProperty(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t name = v7_arg(v7, 0);
-  struct v7_property *ptmp = NULL;
-
-  rcode = _Obj_getOwnProperty(v7, this_obj, name, &ptmp);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  *res = v7_mk_boolean(v7, ptmp != NULL);
-  goto clean;
-
-clean:
-  return rcode;
-}
-#endif
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_valueOf(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  struct v7_property *p;
-
-  *res = this_obj;
-
-  if (v7_is_regexp(v7, this_obj)) {
-    /* res is `this_obj` */
-    goto clean;
-  }
-
-  p = v7_get_own_property2(v7, this_obj, "", 0, _V7_PROPERTY_HIDDEN);
-  if (p != NULL) {
-    *res = p->value;
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_toString(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t ctor, name, this_obj = v7_get_this(v7);
-  char buf[20];
-  const char *str = "Object";
-  size_t name_len = ~0;
-
-  if (v7_is_undefined(this_obj)) {
-    str = "Undefined";
-  } else if (v7_is_null(this_obj)) {
-    str = "Null";
-  } else if (v7_is_number(this_obj)) {
-    str = "Number";
-  } else if (v7_is_boolean(this_obj)) {
-    str = "Boolean";
-  } else if (v7_is_string(this_obj)) {
-    str = "String";
-  } else if (v7_is_callable(v7, this_obj)) {
-    str = "Function";
-  } else {
-    rcode = v7_get_throwing(v7, this_obj, "constructor", ~0, &ctor);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    if (!v7_is_undefined(ctor)) {
-      rcode = v7_get_throwing(v7, ctor, "name", ~0, &name);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-
-      if (!v7_is_undefined(name)) {
-        size_t tmp_len;
-        const char *tmp_str;
-        tmp_str = v7_get_string(v7, &name, &tmp_len);
-        /*
-         * objects constructed with an anonymous constructor are represented as
-         * Object, ch11/11.1/11.1.1/S11.1.1_A4.2.js
-         */
-        if (tmp_len > 0) {
-          str = tmp_str;
-          name_len = tmp_len;
-        }
-      }
-    }
-  }
-
-  if (name_len == (size_t) ~0) {
-    name_len = strlen(str);
-  }
-
-  c_snprintf(buf, sizeof(buf), "[object %.*s]", (int) name_len, str);
-  *res = v7_mk_string(v7, buf, strlen(buf), 1);
-
-clean:
-  return rcode;
-}
-
-#if V7_ENABLE__Object__preventExtensions
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_preventExtensions(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t arg = v7_arg(v7, 0);
-  if (!v7_is_object(arg)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Object expected");
-    goto clean;
-  }
-  get_object_struct(arg)->attributes |= V7_OBJ_NOT_EXTENSIBLE;
-  *res = arg;
-
-clean:
-  return rcode;
-}
-#endif
-
-#if V7_ENABLE__Object__isExtensible
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_isExtensible(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t arg = v7_arg(v7, 0);
-
-  if (!v7_is_object(arg)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Object expected");
-    goto clean;
-  }
-
-  *res = v7_mk_boolean(
-      v7, !(get_object_struct(arg)->attributes & V7_OBJ_NOT_EXTENSIBLE));
-
-clean:
-  return rcode;
-}
-#endif
-
-#if V7_ENABLE__Object__isFrozen || V7_ENABLE__Object__isSealed
-static enum v7_err is_rigid(struct v7 *v7, v7_val_t *res, int is_frozen) {
-  enum v7_err rcode = V7_OK;
-  int ok = 0;
-  val_t arg = v7_arg(v7, 0);
-
-  if (!v7_is_object(arg)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Object expected");
-    goto clean;
-  }
-
-  *res = v7_mk_boolean(v7, 0);
-
-  if (get_object_struct(arg)->attributes & V7_OBJ_NOT_EXTENSIBLE) {
-    v7_prop_attr_t attrs = 0;
-    struct prop_iter_ctx ctx;
-    memset(&ctx, 0, sizeof(ctx));
-    V7_TRY2(init_prop_iter_ctx(v7, arg, 1, &ctx), clean_iter);
-    while (1) {
-      V7_TRY2(next_prop(v7, &ctx, NULL, NULL, &attrs, &ok), clean_iter);
-      if (!ok) {
-        break;
-      }
-      if (!(attrs & V7_PROPERTY_NON_CONFIGURABLE)) {
-        goto clean_iter;
-      }
-      if (is_frozen) {
-        if (!(attrs & V7_PROPERTY_SETTER) &&
-            !(attrs & V7_PROPERTY_NON_WRITABLE)) {
-          goto clean_iter;
-        }
-      }
-    }
-
-    *res = v7_mk_boolean(v7, 1);
-
-  clean_iter:
-    v7_destruct_prop_iter_ctx(v7, &ctx);
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-#endif
-
-#if V7_ENABLE__Object__isSealed
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_isSealed(struct v7 *v7, v7_val_t *res) {
-  return is_rigid(v7, res, 0 /* is_frozen */);
-}
-#endif
-
-#if V7_ENABLE__Object__isFrozen
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Obj_isFrozen(struct v7 *v7, v7_val_t *res) {
-  return is_rigid(v7, res, 1 /* is_frozen */);
-}
-#endif
-
-static const char js_function_Object[] =
-    "function Object(v) {"
-    "if (typeof v === 'boolean') return new Boolean(v);"
-    "if (typeof v === 'number') return new Number(v);"
-    "if (typeof v === 'string') return new String(v);"
-    "if (typeof v === 'date') return new Date(v);"
-    "}";
-
-V7_PRIVATE void init_object(struct v7 *v7) {
-  enum v7_err rcode = V7_OK;
-  val_t object, v;
-  /* TODO(mkm): initialize global object without requiring a parser */
-  rcode = v7_exec(v7, js_function_Object, &v);
-  assert(rcode == V7_OK);
-#if defined(NDEBUG)
-  (void) rcode;
-#endif
-
-  object = v7_get(v7, v7->vals.global_object, "Object", 6);
-  v7_set(v7, object, "prototype", 9, v7->vals.object_prototype);
-  v7_def(v7, v7->vals.object_prototype, "constructor", 11,
-         V7_DESC_ENUMERABLE(0), object);
-
-  set_method(v7, v7->vals.object_prototype, "toString", Obj_toString, 0);
-#if V7_ENABLE__Object__getPrototypeOf
-  set_cfunc_prop(v7, object, "getPrototypeOf", Obj_getPrototypeOf);
-#endif
-#if V7_ENABLE__Object__getOwnPropertyDescriptor
-  set_cfunc_prop(v7, object, "getOwnPropertyDescriptor",
-                 Obj_getOwnPropertyDescriptor);
-#endif
-
-  /* defineProperty is currently required to perform stdlib initialization */
-  set_method(v7, object, "defineProperty", Obj_defineProperty, 3);
-
-#if V7_ENABLE__Object__defineProperties
-  set_cfunc_prop(v7, object, "defineProperties", Obj_defineProperties);
-#endif
-#if V7_ENABLE__Object__create
-  set_cfunc_prop(v7, object, "create", Obj_create);
-#endif
-#if V7_ENABLE__Object__keys
-  set_cfunc_prop(v7, object, "keys", Obj_keys);
-#endif
-#if V7_ENABLE__Object__getOwnPropertyNames
-  set_cfunc_prop(v7, object, "getOwnPropertyNames", Obj_getOwnPropertyNames);
-#endif
-#if V7_ENABLE__Object__preventExtensions
-  set_method(v7, object, "preventExtensions", Obj_preventExtensions, 1);
-#endif
-#if V7_ENABLE__Object__isExtensible
-  set_method(v7, object, "isExtensible", Obj_isExtensible, 1);
-#endif
-#if V7_ENABLE__Object__isSealed
-  set_method(v7, object, "isSealed", Obj_isSealed, 1);
-#endif
-#if V7_ENABLE__Object__isFrozen
-  set_method(v7, object, "isFrozen", Obj_isFrozen, 1);
-#endif
-
-#if V7_ENABLE__Object__propertyIsEnumerable
-  set_cfunc_prop(v7, v7->vals.object_prototype, "propertyIsEnumerable",
-                 Obj_propertyIsEnumerable);
-#endif
-#if V7_ENABLE__Object__hasOwnProperty
-  set_cfunc_prop(v7, v7->vals.object_prototype, "hasOwnProperty",
-                 Obj_hasOwnProperty);
-#endif
-#if V7_ENABLE__Object__isPrototypeOf
-  set_cfunc_prop(v7, v7->vals.object_prototype, "isPrototypeOf",
-                 Obj_isPrototypeOf);
-#endif
-  set_cfunc_prop(v7, v7->vals.object_prototype, "valueOf", Obj_valueOf);
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_error.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/std_error.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/bcode.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-
-/*
- * TODO(dfrank): make the top of v7->call_frame to represent the current
- * frame, and thus get rid of the `CUR_LINENO()`
- */
-#ifndef V7_DISABLE_LINE_NUMBERS
-#define CALLFRAME_LINENO(call_frame) ((call_frame)->line_no)
-#define CUR_LINENO() (v7->line_no)
-#else
-#define CALLFRAME_LINENO(call_frame) 0
-#define CUR_LINENO() 0
-#endif
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Error_ctor(struct v7 *v7, v7_val_t *res);
-
-#if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
-static int printf_stack_line(char *p, size_t len, struct bcode *bcode,
-                             int line_no, const char *leading) {
-  int ret;
-  const char *fn = bcode_get_filename(bcode);
-  if (fn == NULL) {
-    fn = "<no filename>";
-  }
-
-  if (bcode->func_name_present) {
-    /* this is a function's bcode: let's show the function's name as well */
-    char *funcname;
-
-    /*
-     * read first name from the bcode ops, which is the function name,
-     * since `func_name_present` is set
-     */
-    bcode_next_name(bcode->ops.p, &funcname, NULL);
-
-    /* Check if it's an anonymous function */
-    if (funcname[0] == '\0') {
-      funcname = (char *) "<anonymous>";
-    }
-    ret =
-        snprintf(p, len, "%s    at %s (%s:%d)", leading, funcname, fn, line_no);
-  } else {
-    /* it's a file's bcode: show only filename and line number */
-    ret = snprintf(p, len, "%s    at %s:%d", leading, fn, line_no);
-  }
-  return ret;
-}
-
-static int printf_stack_line_cfunc(char *p, size_t len, v7_cfunction_t *cfunc,
-                                   const char *leading) {
-  int ret = 0;
-
-#if !defined(V7_FILENAMES_SUPPRESS_CFUNC_ADDR)
-  int name_len =
-      snprintf(NULL, 0, "cfunc_%p", (void *) cfunc) + 1 /*null-term*/;
-  char *buf = (char *) malloc(name_len);
-
-  snprintf(buf, name_len, "cfunc_%p", (void *) cfunc);
-#else
-  /*
-   * We need this mode only for ecma test reporting, so that the
-   * report is not different from one run to another
-   */
-  char *buf = (char *) "cfunc";
-  (void) cfunc;
-#endif
-
-  ret = snprintf(p, len, "%s    at %s", leading, buf);
-
-#if !defined(V7_FILENAMES_SUPPRESS_CFUNC_ADDR)
-  free(buf);
-#endif
-
-  return ret;
-}
-
-static int print_stack_trace(char *p, size_t len,
-                             struct v7_call_frame_base *call_frame) {
-  char *p_cur = p;
-  int total_len = 0;
-
-  assert(call_frame->type_mask == V7_CALL_FRAME_MASK_CFUNC &&
-         ((struct v7_call_frame_cfunc *) call_frame)->cfunc == Error_ctor);
-  call_frame = call_frame->prev;
-
-  while (call_frame != NULL) {
-    int cur_len = 0;
-    const char *leading = (total_len ? "\n" : "");
-    size_t line_len = len - (p_cur - p);
-
-    if (call_frame->type_mask & V7_CALL_FRAME_MASK_BCODE) {
-      struct bcode *bcode = ((struct v7_call_frame_bcode *) call_frame)->bcode;
-      if (bcode != NULL) {
-        cur_len = printf_stack_line(p_cur, line_len, bcode,
-                                    CALLFRAME_LINENO(call_frame), leading);
-      }
-    } else if (call_frame->type_mask & V7_CALL_FRAME_MASK_CFUNC) {
-      cur_len = printf_stack_line_cfunc(
-          p_cur, line_len, ((struct v7_call_frame_cfunc *) call_frame)->cfunc,
-          leading);
-    }
-
-    total_len += cur_len;
-    if (p_cur != NULL) {
-      p_cur += cur_len;
-    }
-
-    call_frame = call_frame->prev;
-
-#if !(V7_ENABLE__StackTrace)
-    break;
-#endif
-  }
-
-  return total_len;
-}
-#endif
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Error_ctor(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t arg0 = v7_arg(v7, 0);
-
-  if (v7_is_object(this_obj) && this_obj != v7->vals.global_object) {
-    *res = this_obj;
-  } else {
-    *res = mk_object(v7, v7->vals.error_prototype);
-  }
-  /* TODO(mkm): set non enumerable but provide toString method */
-  v7_set(v7, *res, "message", 7, arg0);
-
-#if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
-  /* Save the stack trace */
-  {
-    size_t len = 0;
-    val_t st_v = V7_UNDEFINED;
-
-    v7_own(v7, &st_v);
-
-    len = print_stack_trace(NULL, 0, v7->call_stack);
-
-    if (len > 0) {
-      /* Now, create a placeholder for string */
-      st_v = v7_mk_string(v7, NULL, len, 1);
-      len += 1 /*null-term*/;
-
-      /* And fill it with actual data */
-      print_stack_trace((char *) v7_get_string(v7, &st_v, NULL), len,
-                        v7->call_stack);
-
-      v7_set(v7, *res, "stack", ~0, st_v);
-    }
-
-    v7_disown(v7, &st_v);
-  }
-#endif
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Error_toString(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t prefix, msg = v7_get(v7, this_obj, "message", ~0);
-
-  if (!v7_is_string(msg)) {
-    *res = v7_mk_string(v7, "Error", ~0, 1);
-    goto clean;
-  }
-
-  prefix = v7_mk_string(v7, "Error: ", ~0, 1);
-  *res = s_concat(v7, prefix, msg);
-  goto clean;
-
-clean:
-  return rcode;
-}
-
-static const char *const error_names[] = {TYPE_ERROR,      SYNTAX_ERROR,
-                                          REFERENCE_ERROR, INTERNAL_ERROR,
-                                          RANGE_ERROR,     EVAL_ERROR};
-
-V7_STATIC_ASSERT(ARRAY_SIZE(error_names) == ERROR_CTOR_MAX,
-                 error_name_count_mismatch);
-
-V7_PRIVATE void init_error(struct v7 *v7) {
-  val_t error;
-  size_t i;
-
-  error =
-      mk_cfunction_obj_with_proto(v7, Error_ctor, 1, v7->vals.error_prototype);
-  v7_def(v7, v7->vals.global_object, "Error", 5, V7_DESC_ENUMERABLE(0), error);
-  set_method(v7, v7->vals.error_prototype, "toString", Error_toString, 0);
-
-  for (i = 0; i < ARRAY_SIZE(error_names); i++) {
-    error = mk_cfunction_obj_with_proto(
-        v7, Error_ctor, 1, mk_object(v7, v7->vals.error_prototype));
-    v7_def(v7, v7->vals.global_object, error_names[i], strlen(error_names[i]),
-           V7_DESC_ENUMERABLE(0), error);
-    v7->vals.error_objects[i] = error;
-  }
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_number.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/std_object.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Number_ctor(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t arg0 = v7_argc(v7) == 0 ? v7_mk_number(v7, 0.0) : v7_arg(v7, 0);
-
-  if (v7_is_number(arg0)) {
-    *res = arg0;
-  } else {
-    rcode = to_number_v(v7, arg0, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-  if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
-    obj_prototype_set(v7, get_object_struct(this_obj),
-                      get_object_struct(v7->vals.number_prototype));
-    v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
-
-    /*
-     * implicitly returning `this`: `call_cfunction()` in bcode.c will do
-     * that for us
-     */
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err n_to_str(struct v7 *v7, const char *format, val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t arg0 = v7_arg(v7, 0);
-  int len, digits = 0;
-  char fmt[10], buf[100];
-
-  rcode = to_number_v(v7, arg0, &arg0);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (v7_get_double(v7, arg0) > 0) {
-    digits = (int) v7_get_double(v7, arg0);
-  }
-
-  /*
-   * NOTE: we don't own `arg0` and `this_obj`, since this function is called
-   * from cfunctions only, and GC is inhibited during these calls
-   */
-
-  rcode = obj_value_of(v7, this_obj, &this_obj);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  snprintf(fmt, sizeof(fmt), format, digits);
-  len = snprintf(buf, sizeof(buf), fmt, v7_get_double(v7, this_obj));
-
-  *res = v7_mk_string(v7, buf, len, 1);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Number_toFixed(struct v7 *v7, v7_val_t *res) {
-  return n_to_str(v7, "%%.%dlf", res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Number_toExp(struct v7 *v7, v7_val_t *res) {
-  return n_to_str(v7, "%%.%de", res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Number_toPrecision(struct v7 *v7, v7_val_t *res) {
-  return Number_toExp(v7, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Number_valueOf(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-
-  if (!v7_is_number(this_obj) &&
-      (v7_is_object(this_obj) &&
-       v7_get_proto(v7, this_obj) != v7->vals.number_prototype)) {
-    rcode =
-        v7_throwf(v7, TYPE_ERROR, "Number.valueOf called on non-number object");
-    goto clean;
-  }
-
-  rcode = Obj_valueOf(v7, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-/*
- * Converts a 64 bit signed integer into a string of a given base.
- * Requires space for 65 bytes (64 bit + null terminator) in the result buffer
- */
-static char *cs_itoa(int64_t value, char *result, int base) {
-  char *ptr = result, *ptr1 = result, tmp_char;
-  int64_t tmp_value;
-  int64_t sign = value < 0 ? -1 : 1;
-  const char *base36 = "0123456789abcdefghijklmnopqrstuvwxyz";
-
-  if (base < 2 || base > 36) {
-    *result = '\0';
-    return result;
-  }
-
-  /* let's think positive */
-  value = value * sign;
-  do {
-    tmp_value = value;
-    value /= base;
-    *ptr++ = base36[tmp_value - value * base];
-  } while (value);
-
-  /* sign */
-  if (sign < 0) *ptr++ = '-';
-  *ptr-- = '\0';
-  while (ptr1 < ptr) {
-    tmp_char = *ptr;
-    *ptr-- = *ptr1;
-    *ptr1++ = tmp_char;
-  }
-  return result;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Number_toString(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t radixv = v7_arg(v7, 0);
-  char buf[65];
-  double d, radix;
-
-  if (this_obj == v7->vals.number_prototype) {
-    *res = v7_mk_string(v7, "0", 1, 1);
-    goto clean;
-  }
-
-  /* Make sure this function was called on Number instance */
-  if (!v7_is_number(this_obj) &&
-      !(v7_is_generic_object(this_obj) &&
-        is_prototype_of(v7, this_obj, v7->vals.number_prototype))) {
-    rcode = v7_throwf(v7, TYPE_ERROR,
-                      "Number.toString called on non-number object");
-    goto clean;
-  }
-
-  /* Get number primitive */
-  rcode = to_number_v(v7, this_obj, &this_obj);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  /* Get radix if provided, or 10 otherwise */
-  if (!v7_is_undefined(radixv)) {
-    rcode = to_number_v(v7, radixv, &radixv);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-    radix = v7_get_double(v7, radixv);
-  } else {
-    radix = 10.0;
-  }
-
-  d = v7_get_double(v7, this_obj);
-  if (!isnan(d) && (int64_t) d == d && radix >= 2) {
-    cs_itoa(d, buf, radix);
-    *res = v7_mk_string(v7, buf, strlen(buf), 1);
-  } else {
-    rcode = to_string(v7, this_obj, res, NULL, 0, NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err n_isNaN(struct v7 *v7, v7_val_t *res) {
-  val_t arg0 = v7_arg(v7, 0);
-  *res = v7_mk_boolean(v7, !v7_is_number(arg0) || arg0 == V7_TAG_NAN);
-  return V7_OK;
-}
-
-V7_PRIVATE void init_number(struct v7 *v7) {
-  v7_prop_attr_desc_t attrs_desc =
-      (V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0));
-  val_t num = mk_cfunction_obj_with_proto(v7, Number_ctor, 1,
-                                          v7->vals.number_prototype);
-
-  v7_def(v7, v7->vals.global_object, "Number", 6, V7_DESC_ENUMERABLE(0), num);
-
-  set_cfunc_prop(v7, v7->vals.number_prototype, "toFixed", Number_toFixed);
-  set_cfunc_prop(v7, v7->vals.number_prototype, "toPrecision",
-                 Number_toPrecision);
-  set_cfunc_prop(v7, v7->vals.number_prototype, "toExponential", Number_toExp);
-  set_cfunc_prop(v7, v7->vals.number_prototype, "valueOf", Number_valueOf);
-  set_cfunc_prop(v7, v7->vals.number_prototype, "toString", Number_toString);
-
-  v7_def(v7, num, "MAX_VALUE", 9, attrs_desc,
-         v7_mk_number(v7, 1.7976931348623157e+308));
-  v7_def(v7, num, "MIN_VALUE", 9, attrs_desc, v7_mk_number(v7, 5e-324));
-#if V7_ENABLE__NUMBER__NEGATIVE_INFINITY
-  v7_def(v7, num, "NEGATIVE_INFINITY", 17, attrs_desc,
-         v7_mk_number(v7, -INFINITY));
-#endif
-#if V7_ENABLE__NUMBER__POSITIVE_INFINITY
-  v7_def(v7, num, "POSITIVE_INFINITY", 17, attrs_desc,
-         v7_mk_number(v7, INFINITY));
-#endif
-  v7_def(v7, num, "NaN", 3, attrs_desc, V7_TAG_NAN);
-
-  v7_def(v7, v7->vals.global_object, "NaN", 3, attrs_desc, V7_TAG_NAN);
-  v7_def(v7, v7->vals.global_object, "isNaN", 5, V7_DESC_ENUMERABLE(0),
-         v7_mk_cfunction(n_isNaN));
-}
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_json.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/stdlib.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-#if defined(V7_ALT_JSON_PARSE)
-extern enum v7_err v7_alt_json_parse(struct v7 *v7, v7_val_t json_string,
-                                     v7_val_t *res);
-#endif
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Json_stringify(struct v7 *v7, v7_val_t *res) {
-  val_t arg0 = v7_arg(v7, 0);
-  char buf[100], *p = v7_to_json(v7, arg0, buf, sizeof(buf));
-  *res = v7_mk_string(v7, p, strlen(p), 1);
-
-  if (p != buf) free(p);
-  return V7_OK;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Json_parse(struct v7 *v7, v7_val_t *res) {
-  v7_val_t arg = v7_arg(v7, 0);
-  enum v7_err rcode = V7_OK;
-#if defined(V7_ALT_JSON_PARSE)
-  rcode = v7_alt_json_parse(v7, arg, res);
-#else
-  rcode = std_eval(v7, arg, V7_UNDEFINED, 1, res);
-#endif
-  return rcode;
-}
-
-V7_PRIVATE void init_json(struct v7 *v7) {
-  val_t o = v7_mk_object(v7);
-  set_method(v7, o, "stringify", Json_stringify, 1);
-  set_method(v7, o, "parse", Json_parse, 1);
-  v7_def(v7, v7->vals.global_object, "JSON", 4, V7_DESC_ENUMERABLE(0), o);
-}
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_array.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/str_util.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/gc.h" */
-/* Amalgamated: #include "v7/src/eval.h" */
-/* Amalgamated: #include "v7/src/std_string.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-struct a_sort_data {
-  val_t sort_func;
-};
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_ctor(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  unsigned long i, len;
-
-  (void) v7;
-  *res = v7_mk_array(v7);
-  /*
-   * The interpreter passes dense array to C functions.
-   * However dense array implementation is not yet complete
-   * so we don't want to propagate them at each call to Array()
-   */
-  len = v7_argc(v7);
-  for (i = 0; i < len; i++) {
-    rcode = v7_array_set_throwing(v7, *res, i, v7_arg(v7, i), NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_push(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  int i, len = v7_argc(v7);
-
-  *res = V7_UNDEFINED;
-
-  for (i = 0; i < len; i++) {
-    *res = v7_arg(v7, i);
-    rcode = v7_array_push_throwing(v7, v7_get_this(v7), *res, NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-/*
- * TODO(dfrank) : we need to implement `length` as a real property, and here
- * we need to set new length and return it (even if the object is not an
- * array)
- */
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_get_length(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  long len = 0;
-
-  if (is_prototype_of(v7, this_obj, v7->vals.array_prototype)) {
-    len = v7_array_length(v7, this_obj);
-  }
-  *res = v7_mk_number(v7, len);
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_set_length(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t arg0 = v7_arg(v7, 0);
-  val_t this_obj = v7_get_this(v7);
-  long new_len = 0;
-
-  rcode = to_long(v7, v7_arg(v7, 0), -1, &new_len);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (!v7_is_object(this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
-    goto clean;
-  } else if (new_len < 0 ||
-             (v7_is_number(arg0) && (isnan(v7_get_double(v7, arg0)) ||
-                                     isinf(v7_get_double(v7, arg0))))) {
-    rcode = v7_throwf(v7, RANGE_ERROR, "Invalid array length");
-    goto clean;
-  } else {
-    struct v7_property **p, **next;
-    long index, max_index = -1;
-
-    /* Remove all items with an index higher than new_len */
-    for (p = &get_object_struct(this_obj)->properties; *p != NULL; p = next) {
-      size_t n;
-      const char *s = v7_get_string(v7, &p[0]->name, &n);
-      next = &p[0]->next;
-      index = strtol(s, NULL, 10);
-      if (index >= new_len) {
-        v7_destroy_property(p);
-        *p = *next;
-        next = p;
-      } else if (index > max_index) {
-        max_index = index;
-      }
-    }
-
-    /* If we have to expand, insert an item with appropriate index */
-    if (new_len > 0 && max_index < new_len - 1) {
-      char buf[40];
-      c_snprintf(buf, sizeof(buf), "%ld", new_len - 1);
-      v7_set(v7, this_obj, buf, strlen(buf), V7_UNDEFINED);
-    }
-  }
-
-  *res = v7_mk_number(v7, new_len);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err a_cmp(struct v7 *v7, void *user_data, const void *pa,
-                         const void *pb, int *res) {
-  enum v7_err rcode = V7_OK;
-  struct a_sort_data *sort_data = (struct a_sort_data *) user_data;
-  val_t a = *(val_t *) pa, b = *(val_t *) pb, func = sort_data->sort_func;
-
-  if (v7_is_callable(v7, func)) {
-    int saved_inhibit_gc = v7->inhibit_gc;
-    val_t vres = V7_UNDEFINED, args = v7_mk_dense_array(v7);
-    v7_array_push(v7, args, a);
-    v7_array_push(v7, args, b);
-    v7->inhibit_gc = 0;
-    rcode = b_apply(v7, func, V7_UNDEFINED, args, 0, &vres);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-    v7->inhibit_gc = saved_inhibit_gc;
-    *res = (int) -v7_get_double(v7, vres);
-    goto clean;
-  } else {
-    char sa[100], sb[100];
-
-    rcode = to_string(v7, a, NULL, sa, sizeof(sa), NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    rcode = to_string(v7, b, NULL, sb, sizeof(sb), NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    sa[sizeof(sa) - 1] = sb[sizeof(sb) - 1] = '\0';
-    *res = strcmp(sb, sa);
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err a_partition(struct v7 *v7, val_t *a, int l, int r,
-                               void *user_data, int *res) {
-  enum v7_err rcode = V7_OK;
-  val_t t, pivot = a[l];
-  int i = l, j = r + 1;
-
-  for (;;) {
-    while (1) {
-      ++i;
-
-      if (i <= r) {
-        int tmp = 0;
-        rcode = a_cmp(v7, user_data, &a[i], &pivot, &tmp);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-
-        if (tmp > 0) {
-          break;
-        }
-      } else {
-        break;
-      }
-    }
-    while (1) {
-      int tmp = 0;
-      --j;
-
-      rcode = a_cmp(v7, user_data, &a[j], &pivot, &tmp);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-
-      if (tmp <= 0) {
-        break;
-      }
-    }
-    if (i >= j) break;
-    t = a[i];
-    a[i] = a[j];
-    a[j] = t;
-  }
-  t = a[l];
-  a[l] = a[j];
-  a[j] = t;
-
-  *res = j;
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err a_qsort(struct v7 *v7, val_t *a, int l, int r,
-                           void *user_data) {
-  enum v7_err rcode = V7_OK;
-  if (l < r) {
-    int j = 0;
-    rcode = a_partition(v7, a, l, r, user_data, &j);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    rcode = a_qsort(v7, a, l, j - 1, user_data);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    rcode = a_qsort(v7, a, j + 1, r, user_data);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err a_sort(struct v7 *v7,
-                          enum v7_err (*sorting_func)(struct v7 *v7, void *,
-                                                      const void *,
-                                                      const void *, int *res),
-                          v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  int i = 0, len = 0;
-  val_t *arr = NULL;
-  val_t arg0 = v7_arg(v7, 0);
-
-  *res = v7_get_this(v7);
-  len = v7_array_length(v7, *res);
-
-  if (!v7_is_object(*res)) {
-    goto clean;
-  }
-
-  arr = (val_t *) malloc(len * sizeof(arr[0]));
-
-  assert(*res != v7->vals.global_object);
-
-  for (i = 0; i < len; i++) {
-    arr[i] = v7_array_get(v7, *res, i);
-  }
-
-  /* TODO(dfrank): sorting_func isn't actually used! something is wrong here */
-  if (sorting_func != NULL) {
-    struct a_sort_data sort_data;
-    sort_data.sort_func = arg0;
-    rcode = a_qsort(v7, arr, 0, len - 1, &sort_data);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-  for (i = 0; i < len; i++) {
-    v7_array_set(v7, *res, i, arr[len - (i + 1)]);
-  }
-
-clean:
-  if (arr != NULL) {
-    free(arr);
-  }
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_sort(struct v7 *v7, v7_val_t *res) {
-  return a_sort(v7, a_cmp, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_reverse(struct v7 *v7, v7_val_t *res) {
-  return a_sort(v7, NULL, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_join(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t arg0 = v7_arg(v7, 0);
-  size_t sep_size = 0;
-  const char *sep = NULL;
-
-  *res = V7_UNDEFINED;
-
-  /* Get pointer to the separator string */
-  if (!v7_is_string(arg0)) {
-    /* If no separator is provided, use comma */
-    arg0 = v7_mk_string(v7, ",", 1, 1);
-  }
-  sep = v7_get_string(v7, &arg0, &sep_size);
-
-  /* Do the actual join */
-  if (is_prototype_of(v7, this_obj, v7->vals.array_prototype)) {
-    struct mbuf m;
-    char buf[100], *p;
-    long i, n, num_elems = v7_array_length(v7, this_obj);
-
-    mbuf_init(&m, 0);
-
-    for (i = 0; i < num_elems; i++) {
-      /* Append separator */
-      if (i > 0) {
-        mbuf_append(&m, sep, sep_size);
-      }
-
-      /* Append next item from an array */
-      p = buf;
-      {
-        size_t tmp;
-        rcode = to_string(v7, v7_array_get(v7, this_obj, i), NULL, buf,
-                          sizeof(buf), &tmp);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-        n = tmp;
-      }
-      if (n > (long) sizeof(buf)) {
-        p = (char *) malloc(n + 1);
-        rcode = to_string(v7, v7_array_get(v7, this_obj, i), NULL, p, n, NULL);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-      }
-      mbuf_append(&m, p, n);
-      if (p != buf) {
-        free(p);
-      }
-    }
-
-    /* mbuf contains concatenated string now. Copy it to the result. */
-    *res = v7_mk_string(v7, m.buf, m.len, 1);
-    mbuf_free(&m);
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_toString(struct v7 *v7, v7_val_t *res) {
-  return Array_join(v7, res);
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err a_splice(struct v7 *v7, int mutate, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  long i, len = v7_array_length(v7, this_obj);
-  long num_args = v7_argc(v7);
-  long elems_to_insert = num_args > 2 ? num_args - 2 : 0;
-  long arg0, arg1;
-
-  if (!v7_is_object(this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR,
-                      "Array.splice or Array.slice called on non-object value");
-    goto clean;
-  }
-
-  *res = v7_mk_dense_array(v7);
-
-  rcode = to_long(v7, v7_arg(v7, 0), 0, &arg0);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = to_long(v7, v7_arg(v7, 1), len, &arg1);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  /* Bounds check */
-  if (!mutate && len <= 0) {
-    goto clean;
-  }
-  if (arg0 < 0) arg0 = len + arg0;
-  if (arg0 < 0) arg0 = 0;
-  if (arg0 > len) arg0 = len;
-  if (mutate) {
-    if (arg1 < 0) arg1 = 0;
-    arg1 += arg0;
-  } else if (arg1 < 0) {
-    arg1 = len + arg1;
-  }
-
-  /* Create return value - slice */
-  for (i = arg0; i < arg1 && i < len; i++) {
-    rcode =
-        v7_array_push_throwing(v7, *res, v7_array_get(v7, this_obj, i), NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-  if (mutate && get_object_struct(this_obj)->attributes & V7_OBJ_DENSE_ARRAY) {
-    /*
-     * dense arrays are spliced by memmoving leaving the trailing
-     * space allocated for future appends.
-     * TODO(mkm): figure out if trimming is better
-     */
-    struct v7_property *p =
-        v7_get_own_property2(v7, this_obj, "", 0, _V7_PROPERTY_HIDDEN);
-    struct mbuf *abuf;
-    if (p == NULL) {
-      goto clean;
-    }
-    abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
-    if (abuf == NULL) {
-      goto clean;
-    }
-
-    memmove(abuf->buf + arg0 * sizeof(val_t), abuf->buf + arg1 * sizeof(val_t),
-            (len - arg1) * sizeof(val_t));
-    abuf->len -= (arg1 - arg0) * sizeof(val_t);
-  } else if (mutate) {
-    /* If splicing, modify this_obj array: remove spliced sub-array */
-    struct v7_property **p, **next;
-    long i;
-
-    for (p = &get_object_struct(this_obj)->properties; *p != NULL; p = next) {
-      size_t n;
-      const char *s = v7_get_string(v7, &p[0]->name, &n);
-      next = &p[0]->next;
-      i = strtol(s, NULL, 10);
-      if (i >= arg0 && i < arg1) {
-        /* Remove items from spliced sub-array */
-        v7_destroy_property(p);
-        *p = *next;
-        next = p;
-      } else if (i >= arg1) {
-        /* Modify indices of the elements past sub-array */
-        char key[20];
-        size_t n = c_snprintf(key, sizeof(key), "%ld",
-                              i - (arg1 - arg0) + elems_to_insert);
-        p[0]->name = v7_mk_string(v7, key, n, 1);
-      }
-    }
-
-    /* Insert optional extra elements */
-    for (i = 2; i < num_args; i++) {
-      char key[20];
-      size_t n = c_snprintf(key, sizeof(key), "%ld", arg0 + i - 2);
-      rcode = set_property(v7, this_obj, key, n, v7_arg(v7, i), NULL);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-    }
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_slice(struct v7 *v7, v7_val_t *res) {
-  return a_splice(v7, 0, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_splice(struct v7 *v7, v7_val_t *res) {
-  return a_splice(v7, 1, res);
-}
-
-static void a_prep1(struct v7 *v7, val_t t, val_t *a0, val_t *a1) {
-  *a0 = v7_arg(v7, 0);
-  *a1 = v7_arg(v7, 1);
-  if (v7_is_undefined(*a1)) {
-    *a1 = t;
-  }
-}
-
-/*
- * Call callback function `cb`, passing `this_obj` as `this`, with the
- * following arguments:
- *
- *   cb(v, n, this_obj);
- *
- */
-WARN_UNUSED_RESULT
-static enum v7_err a_prep2(struct v7 *v7, val_t cb, val_t v, val_t n,
-                           val_t this_obj, val_t *res) {
-  enum v7_err rcode = V7_OK;
-  int saved_inhibit_gc = v7->inhibit_gc;
-  val_t args = v7_mk_dense_array(v7);
-
-  *res = v7_mk_dense_array(v7);
-
-  v7_own(v7, &args);
-
-  v7_array_push(v7, args, v);
-  v7_array_push(v7, args, n);
-  v7_array_push(v7, args, this_obj);
-
-  v7->inhibit_gc = 0;
-  rcode = b_apply(v7, cb, this_obj, args, 0, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-clean:
-  v7->inhibit_gc = saved_inhibit_gc;
-  v7_disown(v7, &args);
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_forEach(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t v = V7_UNDEFINED, cb = v7_arg(v7, 0);
-  unsigned long len, i;
-  int has;
-  /* a_prep2 uninhibits GC when calling cb */
-  struct gc_tmp_frame vf = new_tmp_frame(v7);
-
-  if (!v7_is_object(this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
-    goto clean;
-  }
-
-  if (!v7_is_callable(v7, cb)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Function expected");
-    goto clean;
-  }
-
-  tmp_stack_push(&vf, &v);
-
-  len = v7_array_length(v7, this_obj);
-  for (i = 0; i < len; i++) {
-    v = v7_array_get2(v7, this_obj, i, &has);
-    if (!has) continue;
-
-    rcode = a_prep2(v7, cb, v, v7_mk_number(v7, i), this_obj, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-clean:
-  tmp_frame_cleanup(&vf);
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_map(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t arg0, arg1, el, v;
-  unsigned long len, i;
-  int has;
-  /* a_prep2 uninhibits GC when calling cb */
-  struct gc_tmp_frame vf = new_tmp_frame(v7);
-
-  if (!v7_is_object(this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
-    goto clean;
-  } else {
-    a_prep1(v7, this_obj, &arg0, &arg1);
-    *res = v7_mk_dense_array(v7);
-    len = v7_array_length(v7, this_obj);
-
-    tmp_stack_push(&vf, &arg0);
-    tmp_stack_push(&vf, &arg1);
-    tmp_stack_push(&vf, &v);
-
-    for (i = 0; i < len; i++) {
-      v = v7_array_get2(v7, this_obj, i, &has);
-      if (!has) continue;
-      rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-
-      rcode = v7_array_set_throwing(v7, *res, i, el, NULL);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-    }
-  }
-
-clean:
-  tmp_frame_cleanup(&vf);
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_every(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t arg0, arg1, el, v;
-  unsigned long i, len;
-  int has;
-  /* a_prep2 uninhibits GC when calling cb */
-  struct gc_tmp_frame vf = new_tmp_frame(v7);
-
-  *res = v7_mk_boolean(v7, 0);
-
-  if (!v7_is_object(this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
-    goto clean;
-  } else {
-    a_prep1(v7, this_obj, &arg0, &arg1);
-
-    tmp_stack_push(&vf, &arg0);
-    tmp_stack_push(&vf, &arg1);
-    tmp_stack_push(&vf, &v);
-
-    len = v7_array_length(v7, this_obj);
-    for (i = 0; i < len; i++) {
-      v = v7_array_get2(v7, this_obj, i, &has);
-      if (!has) continue;
-      rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-      if (!v7_is_truthy(v7, el)) {
-        *res = v7_mk_boolean(v7, 0);
-        goto clean;
-      }
-    }
-  }
-
-  *res = v7_mk_boolean(v7, 1);
-
-clean:
-  tmp_frame_cleanup(&vf);
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_some(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t arg0, arg1, el, v;
-  unsigned long i, len;
-  int has;
-  /* a_prep2 uninhibits GC when calling cb */
-  struct gc_tmp_frame vf = new_tmp_frame(v7);
-
-  *res = v7_mk_boolean(v7, 1);
-
-  if (!v7_is_object(this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
-    goto clean;
-  } else {
-    a_prep1(v7, this_obj, &arg0, &arg1);
-
-    tmp_stack_push(&vf, &arg0);
-    tmp_stack_push(&vf, &arg1);
-    tmp_stack_push(&vf, &v);
-
-    len = v7_array_length(v7, this_obj);
-    for (i = 0; i < len; i++) {
-      v = v7_array_get2(v7, this_obj, i, &has);
-      if (!has) continue;
-      rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-      if (v7_is_truthy(v7, el)) {
-        *res = v7_mk_boolean(v7, 1);
-        goto clean;
-      }
-    }
-  }
-
-  *res = v7_mk_boolean(v7, 0);
-
-clean:
-  tmp_frame_cleanup(&vf);
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_filter(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t arg0, arg1, el, v;
-  unsigned long len, i;
-  int has;
-  /* a_prep2 uninhibits GC when calling cb */
-  struct gc_tmp_frame vf = new_tmp_frame(v7);
-
-  if (!v7_is_object(this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
-    goto clean;
-  } else {
-    a_prep1(v7, this_obj, &arg0, &arg1);
-    *res = v7_mk_dense_array(v7);
-    len = v7_array_length(v7, this_obj);
-
-    tmp_stack_push(&vf, &arg0);
-    tmp_stack_push(&vf, &arg1);
-    tmp_stack_push(&vf, &v);
-
-    for (i = 0; i < len; i++) {
-      v = v7_array_get2(v7, this_obj, i, &has);
-      if (!has) continue;
-      rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-      if (v7_is_truthy(v7, el)) {
-        rcode = v7_array_push_throwing(v7, *res, v, NULL);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-      }
-    }
-  }
-
-clean:
-  tmp_frame_cleanup(&vf);
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_concat(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  size_t i, j, len;
-  val_t saved_args;
-
-  if (!v7_is_array(v7, this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
-    goto clean;
-  }
-
-  len = v7_argc(v7);
-
-  /*
-   * reuse a_splice but override it's arguments. a_splice
-   * internally uses a lot of helpers that fetch arguments
-   * from the v7 context.
-   * TODO(mkm): we need a better helper call another cfunction
-   * from a cfunction.
-   */
-  saved_args = v7->vals.arguments;
-  v7->vals.arguments = V7_UNDEFINED;
-  rcode = a_splice(v7, 1, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-  v7->vals.arguments = saved_args;
-
-  for (i = 0; i < len; i++) {
-    val_t a = v7_arg(v7, i);
-    if (!v7_is_array(v7, a)) {
-      rcode = v7_array_push_throwing(v7, *res, a, NULL);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-    } else {
-      size_t alen = v7_array_length(v7, a);
-      for (j = 0; j < alen; j++) {
-        rcode = v7_array_push_throwing(v7, *res, v7_array_get(v7, a, j), NULL);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-      }
-    }
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Array_isArray(struct v7 *v7, v7_val_t *res) {
-  val_t arg0 = v7_arg(v7, 0);
-  *res = v7_mk_boolean(v7, v7_is_array(v7, arg0));
-  return V7_OK;
-}
-
-V7_PRIVATE void init_array(struct v7 *v7) {
-  val_t ctor = mk_cfunction_obj(v7, Array_ctor, 1);
-  val_t length = v7_mk_dense_array(v7);
-
-  v7_set(v7, ctor, "prototype", 9, v7->vals.array_prototype);
-  set_method(v7, ctor, "isArray", Array_isArray, 1);
-  v7_set(v7, v7->vals.global_object, "Array", 5, ctor);
-  v7_def(v7, v7->vals.array_prototype, "constructor", ~0, _V7_DESC_HIDDEN(1),
-         ctor);
-  v7_set(v7, ctor, "name", 4, v7_mk_string(v7, "Array", ~0, 1));
-
-  set_method(v7, v7->vals.array_prototype, "concat", Array_concat, 1);
-  set_method(v7, v7->vals.array_prototype, "every", Array_every, 1);
-  set_method(v7, v7->vals.array_prototype, "filter", Array_filter, 1);
-  set_method(v7, v7->vals.array_prototype, "forEach", Array_forEach, 1);
-  set_method(v7, v7->vals.array_prototype, "join", Array_join, 1);
-  set_method(v7, v7->vals.array_prototype, "map", Array_map, 1);
-  set_method(v7, v7->vals.array_prototype, "push", Array_push, 1);
-  set_method(v7, v7->vals.array_prototype, "reverse", Array_reverse, 0);
-  set_method(v7, v7->vals.array_prototype, "slice", Array_slice, 2);
-  set_method(v7, v7->vals.array_prototype, "some", Array_some, 1);
-  set_method(v7, v7->vals.array_prototype, "sort", Array_sort, 1);
-  set_method(v7, v7->vals.array_prototype, "splice", Array_splice, 2);
-  set_method(v7, v7->vals.array_prototype, "toString", Array_toString, 0);
-
-  v7_array_set(v7, length, 0, v7_mk_cfunction(Array_get_length));
-  v7_array_set(v7, length, 1, v7_mk_cfunction(Array_set_length));
-  v7_def(v7, v7->vals.array_prototype, "length", 6,
-         V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1) | V7_DESC_SETTER(1), length);
-}
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_boolean.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/std_object.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Boolean_ctor(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-
-  *res = to_boolean_v(v7, v7_arg(v7, 0));
-
-  if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
-    /* called as "new Boolean(...)" */
-    obj_prototype_set(v7, get_object_struct(this_obj),
-                      get_object_struct(v7->vals.boolean_prototype));
-    v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
-
-    /*
-     * implicitly returning `this`: `call_cfunction()` in bcode.c will do
-     * that for us
-     */
-  }
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Boolean_valueOf(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  if (!v7_is_boolean(this_obj) &&
-      (v7_is_object(this_obj) &&
-       v7_get_proto(v7, this_obj) != v7->vals.boolean_prototype)) {
-    rcode = v7_throwf(v7, TYPE_ERROR,
-                      "Boolean.valueOf called on non-boolean object");
-    goto clean;
-  }
-
-  rcode = Obj_valueOf(v7, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Boolean_toString(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-
-  *res = V7_UNDEFINED;
-
-  if (this_obj == v7->vals.boolean_prototype) {
-    *res = v7_mk_string(v7, "false", 5, 1);
-    goto clean;
-  }
-
-  if (!v7_is_boolean(this_obj) &&
-      !(v7_is_generic_object(this_obj) &&
-        is_prototype_of(v7, this_obj, v7->vals.boolean_prototype))) {
-    rcode = v7_throwf(v7, TYPE_ERROR,
-                      "Boolean.toString called on non-boolean object");
-    goto clean;
-  }
-
-  rcode = obj_value_of(v7, this_obj, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = primitive_to_str(v7, *res, res, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-V7_PRIVATE void init_boolean(struct v7 *v7) {
-  val_t ctor = mk_cfunction_obj_with_proto(v7, Boolean_ctor, 1,
-                                           v7->vals.boolean_prototype);
-  v7_set(v7, v7->vals.global_object, "Boolean", 7, ctor);
-
-  set_cfunc_prop(v7, v7->vals.boolean_prototype, "valueOf", Boolean_valueOf);
-  set_cfunc_prop(v7, v7->vals.boolean_prototype, "toString", Boolean_toString);
-}
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_math.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-
-#if V7_ENABLE__Math
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-#ifdef __WATCOM__
-int matherr(struct _exception *exc) {
-  if (exc->type == DOMAIN) {
-    exc->retval = NAN;
-    return 0;
-  }
-}
-#endif
-
-#if V7_ENABLE__Math__abs || V7_ENABLE__Math__acos || V7_ENABLE__Math__asin ||  \
-    V7_ENABLE__Math__atan || V7_ENABLE__Math__ceil || V7_ENABLE__Math__cos ||  \
-    V7_ENABLE__Math__exp || V7_ENABLE__Math__floor || V7_ENABLE__Math__log ||  \
-    V7_ENABLE__Math__round || V7_ENABLE__Math__sin || V7_ENABLE__Math__sqrt || \
-    V7_ENABLE__Math__tan
-WARN_UNUSED_RESULT
-static enum v7_err m_one_arg(struct v7 *v7, double (*f)(double), val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t arg0 = v7_arg(v7, 0);
-  double d0 = v7_get_double(v7, arg0);
-#ifdef V7_BROKEN_NAN
-  if (isnan(d0)) {
-    *res = V7_TAG_NAN;
-    goto clean;
-  }
-#endif
-  *res = v7_mk_number(v7, f(d0));
-  goto clean;
-
-clean:
-  return rcode;
-}
-#endif /* V7_ENABLE__Math__* */
-
-#if V7_ENABLE__Math__pow || V7_ENABLE__Math__atan2
-WARN_UNUSED_RESULT
-static enum v7_err m_two_arg(struct v7 *v7, double (*f)(double, double),
-                             val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t arg0 = v7_arg(v7, 0);
-  val_t arg1 = v7_arg(v7, 1);
-  double d0 = v7_get_double(v7, arg0);
-  double d1 = v7_get_double(v7, arg1);
-#ifdef V7_BROKEN_NAN
-  /* pow(NaN,0) == 1, doesn't fix atan2, but who cares */
-  if (isnan(d1)) {
-    *res = V7_TAG_NAN;
-    goto clean;
-  }
-#endif
-  *res = v7_mk_number(v7, f(d0, d1));
-  goto clean;
-
-clean:
-  return rcode;
-}
-#endif /* V7_ENABLE__Math__pow || V7_ENABLE__Math__atan2 */
-
-#define DEFINE_WRAPPER(name, func)                                   \
-  WARN_UNUSED_RESULT                                                 \
-  V7_PRIVATE enum v7_err Math_##name(struct v7 *v7, v7_val_t *res) { \
-    return func(v7, name, res);                                      \
-  }
-
-/* Visual studio 2012+ has round() */
-#if V7_ENABLE__Math__round && \
-    ((defined(V7_WINDOWS) && _MSC_VER < 1700) || defined(__WATCOM__))
-static double round(double n) {
-  return n;
-}
-#endif
-
-#if V7_ENABLE__Math__abs
-DEFINE_WRAPPER(fabs, m_one_arg)
-#endif
-#if V7_ENABLE__Math__acos
-DEFINE_WRAPPER(acos, m_one_arg)
-#endif
-#if V7_ENABLE__Math__asin
-DEFINE_WRAPPER(asin, m_one_arg)
-#endif
-#if V7_ENABLE__Math__atan
-DEFINE_WRAPPER(atan, m_one_arg)
-#endif
-#if V7_ENABLE__Math__atan2
-DEFINE_WRAPPER(atan2, m_two_arg)
-#endif
-#if V7_ENABLE__Math__ceil
-DEFINE_WRAPPER(ceil, m_one_arg)
-#endif
-#if V7_ENABLE__Math__cos
-DEFINE_WRAPPER(cos, m_one_arg)
-#endif
-#if V7_ENABLE__Math__exp
-DEFINE_WRAPPER(exp, m_one_arg)
-#endif
-#if V7_ENABLE__Math__floor
-DEFINE_WRAPPER(floor, m_one_arg)
-#endif
-#if V7_ENABLE__Math__log
-DEFINE_WRAPPER(log, m_one_arg)
-#endif
-#if V7_ENABLE__Math__pow
-DEFINE_WRAPPER(pow, m_two_arg)
-#endif
-#if V7_ENABLE__Math__round
-DEFINE_WRAPPER(round, m_one_arg)
-#endif
-#if V7_ENABLE__Math__sin
-DEFINE_WRAPPER(sin, m_one_arg)
-#endif
-#if V7_ENABLE__Math__sqrt
-DEFINE_WRAPPER(sqrt, m_one_arg)
-#endif
-#if V7_ENABLE__Math__tan
-DEFINE_WRAPPER(tan, m_one_arg)
-#endif
-
-#if V7_ENABLE__Math__random
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Math_random(struct v7 *v7, v7_val_t *res) {
-  (void) v7;
-  *res = v7_mk_number(v7, (double) rand() / RAND_MAX);
-  return V7_OK;
-}
-#endif /* V7_ENABLE__Math__random */
-
-#if V7_ENABLE__Math__min || V7_ENABLE__Math__max
-WARN_UNUSED_RESULT
-static enum v7_err min_max(struct v7 *v7, int is_min, val_t *res) {
-  enum v7_err rcode = V7_OK;
-  double dres = NAN;
-  int i, len = v7_argc(v7);
-
-  for (i = 0; i < len; i++) {
-    double v = v7_get_double(v7, v7_arg(v7, i));
-    if (isnan(dres) || (is_min && v < dres) || (!is_min && v > dres)) {
-      dres = v;
-    }
-  }
-
-  *res = v7_mk_number(v7, dres);
-
-  return rcode;
-}
-#endif /* V7_ENABLE__Math__min || V7_ENABLE__Math__max */
-
-#if V7_ENABLE__Math__min
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Math_min(struct v7 *v7, v7_val_t *res) {
-  return min_max(v7, 1, res);
-}
-#endif
-
-#if V7_ENABLE__Math__max
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Math_max(struct v7 *v7, v7_val_t *res) {
-  return min_max(v7, 0, res);
-}
-#endif
-
-V7_PRIVATE void init_math(struct v7 *v7) {
-  val_t math = v7_mk_object(v7);
-
-#if V7_ENABLE__Math__abs
-  set_cfunc_prop(v7, math, "abs", Math_fabs);
-#endif
-#if V7_ENABLE__Math__acos
-  set_cfunc_prop(v7, math, "acos", Math_acos);
-#endif
-#if V7_ENABLE__Math__asin
-  set_cfunc_prop(v7, math, "asin", Math_asin);
-#endif
-#if V7_ENABLE__Math__atan
-  set_cfunc_prop(v7, math, "atan", Math_atan);
-#endif
-#if V7_ENABLE__Math__atan2
-  set_cfunc_prop(v7, math, "atan2", Math_atan2);
-#endif
-#if V7_ENABLE__Math__ceil
-  set_cfunc_prop(v7, math, "ceil", Math_ceil);
-#endif
-#if V7_ENABLE__Math__cos
-  set_cfunc_prop(v7, math, "cos", Math_cos);
-#endif
-#if V7_ENABLE__Math__exp
-  set_cfunc_prop(v7, math, "exp", Math_exp);
-#endif
-#if V7_ENABLE__Math__floor
-  set_cfunc_prop(v7, math, "floor", Math_floor);
-#endif
-#if V7_ENABLE__Math__log
-  set_cfunc_prop(v7, math, "log", Math_log);
-#endif
-#if V7_ENABLE__Math__max
-  set_cfunc_prop(v7, math, "max", Math_max);
-#endif
-#if V7_ENABLE__Math__min
-  set_cfunc_prop(v7, math, "min", Math_min);
-#endif
-#if V7_ENABLE__Math__pow
-  set_cfunc_prop(v7, math, "pow", Math_pow);
-#endif
-#if V7_ENABLE__Math__random
-  /* Incorporate our pointer into the RNG.
-   * If srand() has not been called before, this will provide some randomness.
-   * If it has, it will hopefully not make things worse.
-   */
-  srand(rand() ^ ((uintptr_t) v7));
-  set_cfunc_prop(v7, math, "random", Math_random);
-#endif
-#if V7_ENABLE__Math__round
-  set_cfunc_prop(v7, math, "round", Math_round);
-#endif
-#if V7_ENABLE__Math__sin
-  set_cfunc_prop(v7, math, "sin", Math_sin);
-#endif
-#if V7_ENABLE__Math__sqrt
-  set_cfunc_prop(v7, math, "sqrt", Math_sqrt);
-#endif
-#if V7_ENABLE__Math__tan
-  set_cfunc_prop(v7, math, "tan", Math_tan);
-#endif
-
-#if V7_ENABLE__Math__constants
-  v7_set(v7, math, "E", 1, v7_mk_number(v7, M_E));
-  v7_set(v7, math, "PI", 2, v7_mk_number(v7, M_PI));
-  v7_set(v7, math, "LN2", 3, v7_mk_number(v7, M_LN2));
-  v7_set(v7, math, "LN10", 4, v7_mk_number(v7, M_LN10));
-  v7_set(v7, math, "LOG2E", 5, v7_mk_number(v7, M_LOG2E));
-  v7_set(v7, math, "LOG10E", 6, v7_mk_number(v7, M_LOG10E));
-  v7_set(v7, math, "SQRT1_2", 7, v7_mk_number(v7, M_SQRT1_2));
-  v7_set(v7, math, "SQRT2", 5, v7_mk_number(v7, M_SQRT2));
-#endif
-
-  v7_set(v7, v7->vals.global_object, "Math", 4, math);
-}
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_ENABLE__Math */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_string.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/utf.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/std_string.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/slre.h" */
-/* Amalgamated: #include "v7/src/std_regex.h" */
-/* Amalgamated: #include "v7/src/std_object.h" */
-/* Amalgamated: #include "v7/src/eval.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/regexp.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-
-/* Substring implementations: RegExp-based and String-based {{{ */
-
-/*
- * Substring context: currently, used in Str_split() only, but will probably
- * be used in Str_replace() and other functions as well.
- *
- * Needed to provide different implementation for RegExp or String arguments,
- * keeping common parts reusable.
- */
-struct _str_split_ctx {
-  /* implementation-specific data */
-  union {
-#if V7_ENABLE__RegExp
-    struct {
-      struct slre_prog *prog;
-      struct slre_loot loot;
-    } regexp;
-#endif
-
-    struct {
-      val_t sep;
-    } string;
-  } impl;
-
-  struct v7 *v7;
-
-  /* start and end of previous match (set by `p_exec()`) */
-  const char *match_start;
-  const char *match_end;
-
-  /* pointers to implementation functions */
-
-  /*
-   * Initialize context
-   */
-  void (*p_init)(struct _str_split_ctx *ctx, struct v7 *v7, val_t sep);
-
-  /*
-   * Look for the next match, set `match_start` and `match_end` to appropriate
-   * values.
-   *
-   * Returns 0 if match found, 1 otherwise (in accordance with `slre_exec()`)
-   */
-  int (*p_exec)(struct _str_split_ctx *ctx, const char *start, const char *end);
-
-#if V7_ENABLE__RegExp
-  /*
-   * Add captured data to resulting array (for RegExp-based implementation only)
-   *
-   * Returns updated `elem` value
-   */
-  long (*p_add_caps)(struct _str_split_ctx *ctx, val_t res, long elem,
-                     long limit);
-#endif
-};
-
-#if V7_ENABLE__RegExp
-/* RegExp-based implementation of `p_init` in `struct _str_split_ctx` */
-static void subs_regexp_init(struct _str_split_ctx *ctx, struct v7 *v7,
-                             val_t sep) {
-  ctx->v7 = v7;
-  ctx->impl.regexp.prog = v7_get_regexp_struct(v7, sep)->compiled_regexp;
-}
-
-/* RegExp-based implementation of `p_exec` in `struct _str_split_ctx` */
-static int subs_regexp_exec(struct _str_split_ctx *ctx, const char *start,
-                            const char *end) {
-  int ret =
-      slre_exec(ctx->impl.regexp.prog, 0, start, end, &ctx->impl.regexp.loot);
-
-  ctx->match_start = ctx->impl.regexp.loot.caps[0].start;
-  ctx->match_end = ctx->impl.regexp.loot.caps[0].end;
-
-  return ret;
-}
-
-/* RegExp-based implementation of `p_add_caps` in `struct _str_split_ctx` */
-static long subs_regexp_split_add_caps(struct _str_split_ctx *ctx, val_t res,
-                                       long elem, long limit) {
-  int i;
-  for (i = 1; i < ctx->impl.regexp.loot.num_captures && elem < limit; i++) {
-    size_t cap_len =
-        ctx->impl.regexp.loot.caps[i].end - ctx->impl.regexp.loot.caps[i].start;
-    v7_array_push(
-        ctx->v7, res,
-        (ctx->impl.regexp.loot.caps[i].start != NULL)
-            ? v7_mk_string(ctx->v7, ctx->impl.regexp.loot.caps[i].start,
-                           cap_len, 1)
-            : V7_UNDEFINED);
-    elem++;
-  }
-  return elem;
-}
-#endif
-
-/* String-based implementation of `p_init` in `struct _str_split_ctx` */
-static void subs_string_init(struct _str_split_ctx *ctx, struct v7 *v7,
-                             val_t sep) {
-  ctx->v7 = v7;
-  ctx->impl.string.sep = sep;
-}
-
-/* String-based implementation of `p_exec` in `struct _str_split_ctx` */
-static int subs_string_exec(struct _str_split_ctx *ctx, const char *start,
-                            const char *end) {
-  int ret = 1;
-  size_t sep_len;
-  const char *psep = v7_get_string(ctx->v7, &ctx->impl.string.sep, &sep_len);
-
-  if (sep_len == 0) {
-    /* separator is an empty string: match empty string */
-    ctx->match_start = start;
-    ctx->match_end = start;
-    ret = 0;
-  } else {
-    size_t i;
-    for (i = 0; start <= (end - sep_len); ++i, start = utfnshift(start, 1)) {
-      if (memcmp(start, psep, sep_len) == 0) {
-        ret = 0;
-        ctx->match_start = start;
-        ctx->match_end = start + sep_len;
-        break;
-      }
-    }
-  }
-
-  return ret;
-}
-
-#if V7_ENABLE__RegExp
-/* String-based implementation of `p_add_caps` in `struct _str_split_ctx` */
-static long subs_string_split_add_caps(struct _str_split_ctx *ctx, val_t res,
-                                       long elem, long limit) {
-  /* this is a stub function */
-  (void) ctx;
-  (void) res;
-  (void) limit;
-  return elem;
-}
-#endif
-
-/* }}} */
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err String_ctor(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t arg0 = v7_arg(v7, 0);
-
-  *res = arg0;
-
-  if (v7_argc(v7) == 0) {
-    *res = v7_mk_string(v7, NULL, 0, 1);
-  } else if (!v7_is_string(arg0)) {
-    rcode = to_string(v7, arg0, res, NULL, 0, NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-  if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
-    obj_prototype_set(v7, get_object_struct(this_obj),
-                      get_object_struct(v7->vals.string_prototype));
-    v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
-    /*
-     * implicitly returning `this`: `call_cfunction()` in bcode.c will do
-     * that for us
-     */
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_fromCharCode(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  int i, num_args = v7_argc(v7);
-
-  *res = v7_mk_string(v7, "", 0, 1); /* Empty string */
-
-  for (i = 0; i < num_args; i++) {
-    char buf[10];
-    val_t arg = v7_arg(v7, i);
-    double d = v7_get_double(v7, arg);
-    Rune r = (Rune)((int32_t)(isnan(d) || isinf(d) ? 0 : d) & 0xffff);
-    int n = runetochar(buf, &r);
-    val_t s = v7_mk_string(v7, buf, n, 1);
-    *res = s_concat(v7, *res, s);
-  }
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err s_charCodeAt(struct v7 *v7, double *res) {
-  return v7_char_code_at(v7, v7_get_this(v7), v7_arg(v7, 0), res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_charCodeAt(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  double dnum = 0;
-
-  rcode = s_charCodeAt(v7, &dnum);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  *res = v7_mk_number(v7, dnum);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_charAt(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  double code = 0;
-  char buf[10] = {0};
-  int len = 0;
-
-  rcode = s_charCodeAt(v7, &code);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (!isnan(code)) {
-    Rune r = (Rune) code;
-    len = runetochar(buf, &r);
-  }
-  *res = v7_mk_string(v7, buf, len, 1);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_concat(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  int i, num_args = v7_argc(v7);
-
-  rcode = to_string(v7, this_obj, res, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  for (i = 0; i < num_args; i++) {
-    val_t str = V7_UNDEFINED;
-
-    rcode = to_string(v7, v7_arg(v7, i), &str, NULL, 0, NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    *res = s_concat(v7, *res, str);
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err s_index_of(struct v7 *v7, int last, val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t arg0 = v7_arg(v7, 0);
-  size_t fromIndex = 0;
-  double dres = -1;
-
-  if (!v7_is_undefined(arg0)) {
-    const char *p1, *p2, *end;
-    size_t i, len1, len2, bytecnt1, bytecnt2;
-    val_t sub = V7_UNDEFINED;
-
-    rcode = to_string(v7, arg0, &sub, NULL, 0, NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    p1 = v7_get_string(v7, &this_obj, &bytecnt1);
-    p2 = v7_get_string(v7, &sub, &bytecnt2);
-
-    if (bytecnt2 <= bytecnt1) {
-      end = p1 + bytecnt1;
-      len1 = utfnlen(p1, bytecnt1);
-      len2 = utfnlen(p2, bytecnt2);
-
-      if (v7_argc(v7) > 1) {
-        /* `fromIndex` was provided. Normalize it */
-        double d = 0;
-        {
-          val_t arg = v7_arg(v7, 1);
-          rcode = to_number_v(v7, arg, &arg);
-          if (rcode != V7_OK) {
-            goto clean;
-          }
-          d = v7_get_double(v7, arg);
-        }
-        if (isnan(d) || d < 0) {
-          d = 0.0;
-        } else if (isinf(d) || d > len1) {
-          d = len1;
-        }
-        fromIndex = d;
-
-        /* adjust pointers accordingly to `fromIndex` */
-        if (last) {
-          const char *end_tmp = utfnshift(p1, fromIndex + len2);
-          end = (end_tmp < end) ? end_tmp : end;
-        } else {
-          p1 = utfnshift(p1, fromIndex);
-        }
-      }
-
-      /*
-       * TODO(dfrank): when `last` is set, start from the end and look
-       * backward. We'll need to improve `utfnshift()` for that, so that it can
-       * handle negative offsets.
-       */
-      for (i = 0; p1 <= (end - bytecnt2); i++, p1 = utfnshift(p1, 1)) {
-        if (memcmp(p1, p2, bytecnt2) == 0) {
-          dres = i;
-          if (!last) break;
-        }
-      }
-    }
-  }
-  if (!last && dres >= 0) dres += fromIndex;
-  *res = v7_mk_number(v7, dres);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_valueOf(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-
-  if (!v7_is_string(this_obj) &&
-      (v7_is_object(this_obj) &&
-       v7_get_proto(v7, this_obj) != v7->vals.string_prototype)) {
-    rcode =
-        v7_throwf(v7, TYPE_ERROR, "String.valueOf called on non-string object");
-    goto clean;
-  }
-
-  rcode = Obj_valueOf(v7, res);
-  goto clean;
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_indexOf(struct v7 *v7, v7_val_t *res) {
-  return s_index_of(v7, 0, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_lastIndexOf(struct v7 *v7, v7_val_t *res) {
-  return s_index_of(v7, 1, res);
-}
-
-#if V7_ENABLE__String__localeCompare
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_localeCompare(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t arg0 = V7_UNDEFINED;
-  val_t s = V7_UNDEFINED;
-
-  rcode = to_string(v7, v7_arg(v7, 0), &arg0, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = to_string(v7, this_obj, &s, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  *res = v7_mk_number(v7, s_cmp(v7, s, arg0));
-
-clean:
-  return rcode;
-}
-#endif
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_toString(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-
-  if (this_obj == v7->vals.string_prototype) {
-    *res = v7_mk_string(v7, "false", 5, 1);
-    goto clean;
-  }
-
-  if (!v7_is_string(this_obj) &&
-      !(v7_is_generic_object(this_obj) &&
-        is_prototype_of(v7, this_obj, v7->vals.string_prototype))) {
-    rcode = v7_throwf(v7, TYPE_ERROR,
-                      "String.toString called on non-string object");
-    goto clean;
-  }
-
-  rcode = obj_value_of(v7, this_obj, &this_obj);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = to_string(v7, this_obj, res, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-#if V7_ENABLE__RegExp
-WARN_UNUSED_RESULT
-enum v7_err call_regex_ctor(struct v7 *v7, val_t arg, val_t *res) {
-  /* TODO(mkm): make general helper out of this */
-  enum v7_err rcode = V7_OK;
-  val_t saved_args = v7->vals.arguments, args = v7_mk_dense_array(v7);
-  v7_array_push(v7, args, arg);
-  v7->vals.arguments = args;
-
-  rcode = Regex_ctor(v7, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-  v7->vals.arguments = saved_args;
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_match(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t so = V7_UNDEFINED, ro = V7_UNDEFINED;
-  long previousLastIndex = 0;
-  int lastMatch = 1, n = 0, flag_g;
-  struct v7_regexp *rxp;
-
-  *res = V7_NULL;
-
-  rcode = to_string(v7, this_obj, &so, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (v7_argc(v7) == 0) {
-    rcode = v7_mk_regexp(v7, "", 0, "", 0, &ro);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  } else {
-    rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-  if (!v7_is_regexp(v7, ro)) {
-    rcode = call_regex_ctor(v7, ro, &ro);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-  rxp = v7_get_regexp_struct(v7, ro);
-  flag_g = slre_get_flags(rxp->compiled_regexp) & SLRE_FLAG_G;
-  if (!flag_g) {
-    rcode = rx_exec(v7, ro, so, 0, res);
-    goto clean;
-  }
-
-  rxp->lastIndex = 0;
-  *res = v7_mk_dense_array(v7);
-  while (lastMatch) {
-    val_t result;
-
-    rcode = rx_exec(v7, ro, so, 1, &result);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    if (v7_is_null(result)) {
-      lastMatch = 0;
-    } else {
-      long thisIndex = rxp->lastIndex;
-      if (thisIndex == previousLastIndex) {
-        previousLastIndex = thisIndex + 1;
-        rxp->lastIndex = previousLastIndex;
-      } else {
-        previousLastIndex = thisIndex;
-      }
-      rcode =
-          v7_array_push_throwing(v7, *res, v7_array_get(v7, result, 0), NULL);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-      n++;
-    }
-  }
-
-  if (n == 0) {
-    *res = V7_NULL;
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_replace(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  const char *s;
-  size_t s_len;
-  /*
-   * Buffer of temporary strings returned by the replacement funciton.  Will be
-   * allocated below if only the replacement is a function.  We need to store
-   * each string in a separate `val_t`, because string data of length <= 5 is
-   * stored right in `val_t`, so if there's more than one replacement,
-   * each subsequent replacement will overwrite the previous one.
-   */
-  val_t *tmp_str_buf = NULL;
-  val_t out_str_o;
-  char *old_owned_mbuf_base = v7->owned_strings.buf;
-  char *old_owned_mbuf_end = v7->owned_strings.buf + v7->owned_strings.len;
-
-  rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  s = v7_get_string(v7, &this_obj, &s_len);
-
-  if (s_len != 0 && v7_argc(v7) > 1) {
-    const char *const str_end = s + s_len;
-    char *p = (char *) s;
-    uint32_t out_sub_num = 0;
-    val_t ro = V7_UNDEFINED, str_func = V7_UNDEFINED;
-    struct slre_prog *prog;
-    struct slre_cap out_sub[V7_RE_MAX_REPL_SUB], *ptok = out_sub;
-    struct slre_loot loot;
-    int flag_g;
-
-    rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-    rcode = obj_value_of(v7, v7_arg(v7, 1), &str_func);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    if (!v7_is_regexp(v7, ro)) {
-      rcode = call_regex_ctor(v7, ro, &ro);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-    }
-    prog = v7_get_regexp_struct(v7, ro)->compiled_regexp;
-    flag_g = slre_get_flags(prog) & SLRE_FLAG_G;
-
-    if (!v7_is_callable(v7, str_func)) {
-      rcode = to_string(v7, str_func, &str_func, NULL, 0, NULL);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-    }
-
-    do {
-      int i;
-      if (slre_exec(prog, 0, p, str_end, &loot)) break;
-      if (p != loot.caps->start) {
-        ptok->start = p;
-        ptok->end = loot.caps->start;
-        ptok++;
-        out_sub_num++;
-      }
-
-      if (v7_is_callable(v7, str_func)) { /* replace function */
-        const char *rez_str;
-        size_t rez_len;
-        val_t arr = v7_mk_dense_array(v7);
-
-        for (i = 0; i < loot.num_captures; i++) {
-          rcode = v7_array_push_throwing(
-              v7, arr, v7_mk_string(v7, loot.caps[i].start,
-                                    loot.caps[i].end - loot.caps[i].start, 1),
-              NULL);
-          if (rcode != V7_OK) {
-            goto clean;
-          }
-        }
-        rcode = v7_array_push_throwing(
-            v7, arr, v7_mk_number(v7, utfnlen(s, loot.caps[0].start - s)),
-            NULL);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-
-        rcode = v7_array_push_throwing(v7, arr, this_obj, NULL);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-
-        {
-          val_t val = V7_UNDEFINED;
-
-          rcode = b_apply(v7, str_func, this_obj, arr, 0, &val);
-          if (rcode != V7_OK) {
-            goto clean;
-          }
-
-          if (tmp_str_buf == NULL) {
-            tmp_str_buf = (val_t *) calloc(sizeof(val_t), V7_RE_MAX_REPL_SUB);
-          }
-
-          rcode = to_string(v7, val, &tmp_str_buf[out_sub_num], NULL, 0, NULL);
-          if (rcode != V7_OK) {
-            goto clean;
-          }
-        }
-        rez_str = v7_get_string(v7, &tmp_str_buf[out_sub_num], &rez_len);
-        if (rez_len) {
-          ptok->start = rez_str;
-          ptok->end = rez_str + rez_len;
-          ptok++;
-          out_sub_num++;
-        }
-      } else { /* replace string */
-        struct slre_loot newsub;
-        size_t f_len;
-        const char *f_str = v7_get_string(v7, &str_func, &f_len);
-        slre_replace(&loot, s, s_len, f_str, f_len, &newsub);
-        for (i = 0; i < newsub.num_captures; i++) {
-          ptok->start = newsub.caps[i].start;
-          ptok->end = newsub.caps[i].end;
-          ptok++;
-          out_sub_num++;
-        }
-      }
-      p = (char *) loot.caps[0].end;
-    } while (flag_g && p < str_end);
-    if (p <= str_end) {
-      ptok->start = p;
-      ptok->end = str_end;
-      ptok++;
-      out_sub_num++;
-    }
-    out_str_o = v7_mk_string(v7, NULL, 0, 1);
-    ptok = out_sub;
-    do {
-      size_t ln = ptok->end - ptok->start;
-      const char *ps = ptok->start;
-      if (ptok->start >= old_owned_mbuf_base &&
-          ptok->start < old_owned_mbuf_end) {
-        ps += v7->owned_strings.buf - old_owned_mbuf_base;
-      }
-      out_str_o = s_concat(v7, out_str_o, v7_mk_string(v7, ps, ln, 1));
-      p += ln;
-      ptok++;
-    } while (--out_sub_num);
-
-    *res = out_str_o;
-    goto clean;
-  }
-
-  *res = this_obj;
-
-clean:
-  if (tmp_str_buf != NULL) {
-    free(tmp_str_buf);
-    tmp_str_buf = NULL;
-  }
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_search(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  long utf_shift = -1;
-
-  if (v7_argc(v7) > 0) {
-    size_t s_len;
-    struct slre_loot sub;
-    val_t so = V7_UNDEFINED, ro = V7_UNDEFINED;
-    const char *s;
-
-    rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    if (!v7_is_regexp(v7, ro)) {
-      rcode = call_regex_ctor(v7, ro, &ro);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-    }
-
-    rcode = to_string(v7, this_obj, &so, NULL, 0, NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    s = v7_get_string(v7, &so, &s_len);
-
-    if (!slre_exec(v7_get_regexp_struct(v7, ro)->compiled_regexp, 0, s,
-                   s + s_len, &sub))
-      utf_shift = utfnlen(s, sub.caps[0].start - s); /* calc shift for UTF-8 */
-  } else {
-    utf_shift = 0;
-  }
-
-  *res = v7_mk_number(v7, utf_shift);
-
-clean:
-  return rcode;
-}
-
-#endif /* V7_ENABLE__RegExp */
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_slice(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  long from = 0, to = 0;
-  size_t len;
-  val_t so = V7_UNDEFINED;
-  const char *begin, *end;
-  int num_args = v7_argc(v7);
-
-  rcode = to_string(v7, this_obj, &so, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  begin = v7_get_string(v7, &so, &len);
-
-  to = len = utfnlen(begin, len);
-  if (num_args > 0) {
-    rcode = to_long(v7, v7_arg(v7, 0), 0, &from);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    if (from < 0) {
-      from += len;
-      if (from < 0) from = 0;
-    } else if ((size_t) from > len)
-      from = len;
-    if (num_args > 1) {
-      rcode = to_long(v7, v7_arg(v7, 1), 0, &to);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-
-      if (to < 0) {
-        to += len;
-        if (to < 0) to = 0;
-      } else if ((size_t) to > len)
-        to = len;
-    }
-  }
-
-  if (from > to) to = from;
-  end = utfnshift(begin, to);
-  begin = utfnshift(begin, from);
-
-  *res = v7_mk_string(v7, begin, end - begin, 1);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err s_transform(struct v7 *v7, val_t obj, Rune (*func)(Rune),
-                               val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t s = V7_UNDEFINED;
-  size_t i, n, len;
-  const char *p2, *p;
-
-  rcode = to_string(v7, obj, &s, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  p = v7_get_string(v7, &s, &len);
-
-  /* Pass NULL to make sure we're not creating dictionary value */
-  *res = v7_mk_string(v7, NULL, len, 1);
-
-  {
-    Rune r;
-    p2 = v7_get_string(v7, res, &len);
-    for (i = 0; i < len; i += n) {
-      n = chartorune(&r, p + i);
-      r = func(r);
-      runetochar((char *) p2 + i, &r);
-    }
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_toLowerCase(struct v7 *v7, v7_val_t *res) {
-  val_t this_obj = v7_get_this(v7);
-  return s_transform(v7, this_obj, tolowerrune, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_toUpperCase(struct v7 *v7, v7_val_t *res) {
-  val_t this_obj = v7_get_this(v7);
-  return s_transform(v7, this_obj, toupperrune, res);
-}
-
-static int s_isspace(Rune c) {
-  return isspacerune(c) || isnewline(c);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_trim(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t s = V7_UNDEFINED;
-  size_t i, n, len, start = 0, end, state = 0;
-  const char *p;
-  Rune r;
-
-  rcode = to_string(v7, this_obj, &s, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-  p = v7_get_string(v7, &s, &len);
-
-  end = len;
-  for (i = 0; i < len; i += n) {
-    n = chartorune(&r, p + i);
-    if (!s_isspace(r)) {
-      if (state++ == 0) start = i;
-      end = i + n;
-    }
-  }
-
-  *res = v7_mk_string(v7, p + start, end - start, 1);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_length(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  size_t len = 0;
-  val_t s = V7_UNDEFINED;
-
-  rcode = obj_value_of(v7, this_obj, &s);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (v7_is_string(s)) {
-    const char *p = v7_get_string(v7, &s, &len);
-    len = utfnlen(p, len);
-  }
-
-  *res = v7_mk_number(v7, len);
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_at(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  long arg0;
-  val_t s = V7_UNDEFINED;
-
-  rcode = to_long(v7, v7_arg(v7, 0), -1, &arg0);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = obj_value_of(v7, this_obj, &s);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (v7_is_string(s)) {
-    size_t n;
-    const unsigned char *p = (unsigned char *) v7_get_string(v7, &s, &n);
-    if (arg0 >= 0 && (size_t) arg0 < n) {
-      *res = v7_mk_number(v7, p[arg0]);
-      goto clean;
-    }
-  }
-
-  *res = v7_mk_number(v7, NAN);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_blen(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  size_t len = 0;
-  val_t s = V7_UNDEFINED;
-
-  rcode = obj_value_of(v7, this_obj, &s);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (v7_is_string(s)) {
-    v7_get_string(v7, &s, &len);
-  }
-
-  *res = v7_mk_number(v7, len);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-static enum v7_err s_substr(struct v7 *v7, val_t s, long start, long len,
-                            val_t *res) {
-  enum v7_err rcode = V7_OK;
-  size_t n;
-  const char *p;
-
-  rcode = to_string(v7, s, &s, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  p = v7_get_string(v7, &s, &n);
-  n = utfnlen(p, n);
-
-  if (start < (long) n && len > 0) {
-    if (start < 0) start = (long) n + start;
-    if (start < 0) start = 0;
-
-    if (start > (long) n) start = n;
-    if (len < 0) len = 0;
-    if (len > (long) n - start) len = n - start;
-    p = utfnshift(p, start);
-  } else {
-    len = 0;
-  }
-
-  *res = v7_mk_string(v7, p, len, 1);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_substr(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  long start, len;
-
-  rcode = to_long(v7, v7_arg(v7, 0), 0, &start);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &len);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = s_substr(v7, this_obj, start, len, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_substring(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  long start, end;
-
-  rcode = to_long(v7, v7_arg(v7, 0), 0, &start);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &end);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (start < 0) start = 0;
-  if (end < 0) end = 0;
-  if (start > end) {
-    long tmp = start;
-    start = end;
-    end = tmp;
-  }
-
-  rcode = s_substr(v7, this_obj, start, end - start, res);
-  goto clean;
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Str_split(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  const char *s, *s_end;
-  size_t s_len;
-  long num_args = v7_argc(v7);
-  rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-  s = v7_get_string(v7, &this_obj, &s_len);
-  s_end = s + s_len;
-
-  *res = v7_mk_dense_array(v7);
-
-  if (num_args == 0) {
-    /*
-     * No arguments were given: resulting array will contain just a single
-     * element: the source string
-     */
-    rcode = v7_array_push_throwing(v7, *res, this_obj, NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  } else {
-    val_t ro = V7_UNDEFINED;
-    long elem, limit;
-    size_t lookup_idx = 0, substr_idx = 0;
-    struct _str_split_ctx ctx;
-
-    rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &limit);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    /* Initialize substring context depending on the argument type */
-    if (v7_is_regexp(v7, ro)) {
-/* use RegExp implementation */
-#if V7_ENABLE__RegExp
-      ctx.p_init = subs_regexp_init;
-      ctx.p_exec = subs_regexp_exec;
-      ctx.p_add_caps = subs_regexp_split_add_caps;
-#else
-      assert(0);
-#endif
-    } else {
-      /*
-       * use String implementation: first of all, convert to String (if it's
-       * not already a String)
-       */
-      rcode = to_string(v7, ro, &ro, NULL, 0, NULL);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-
-      ctx.p_init = subs_string_init;
-      ctx.p_exec = subs_string_exec;
-#if V7_ENABLE__RegExp
-      ctx.p_add_caps = subs_string_split_add_caps;
-#endif
-    }
-    /* initialize context */
-    ctx.p_init(&ctx, v7, ro);
-
-    if (s_len == 0) {
-      /*
-       * if `this` is (or converts to) an empty string, resulting array should
-       * contain empty string if only separator does not match an empty string.
-       * Otherwise, the array is left empty
-       */
-      int matches_empty = !ctx.p_exec(&ctx, s, s);
-      if (!matches_empty) {
-        rcode = v7_array_push_throwing(v7, *res, this_obj, NULL);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-      }
-    } else {
-      size_t last_match_len = 0;
-
-      for (elem = 0; elem < limit && lookup_idx < s_len;) {
-        size_t substr_len;
-        /* find next match, and break if there's no match */
-        if (ctx.p_exec(&ctx, s + lookup_idx, s_end)) break;
-
-        last_match_len = ctx.match_end - ctx.match_start;
-        substr_len = ctx.match_start - s - substr_idx;
-
-        /* add next substring to the resulting array, if needed */
-        if (substr_len > 0 || last_match_len > 0) {
-          rcode = v7_array_push_throwing(
-              v7, *res, v7_mk_string(v7, s + substr_idx, substr_len, 1), NULL);
-          if (rcode != V7_OK) {
-            goto clean;
-          }
-          elem++;
-
-#if V7_ENABLE__RegExp
-          /* Add captures (for RegExp only) */
-          elem = ctx.p_add_caps(&ctx, *res, elem, limit);
-#endif
-        }
-
-        /* advance lookup_idx appropriately */
-        if (last_match_len == 0) {
-          /* empty match: advance to the next char */
-          const char *next = utfnshift((s + lookup_idx), 1);
-          lookup_idx += (next - (s + lookup_idx));
-        } else {
-          /* non-empty match: advance to the end of match */
-          lookup_idx = ctx.match_end - s;
-        }
-
-        /*
-         * always remember the end of the match, so that next time we will take
-         * substring from that position
-         */
-        substr_idx = ctx.match_end - s;
-      }
-
-      /* add the last substring to the resulting array, if needed */
-      if (elem < limit) {
-        size_t substr_len = s_len - substr_idx;
-        if (substr_len > 0 || last_match_len > 0) {
-          rcode = v7_array_push_throwing(
-              v7, *res, v7_mk_string(v7, s + substr_idx, substr_len, 1), NULL);
-          if (rcode != V7_OK) {
-            goto clean;
-          }
-        }
-      }
-    }
-  }
-
-clean:
-  return rcode;
-}
-
-V7_PRIVATE void init_string(struct v7 *v7) {
-  val_t str = mk_cfunction_obj_with_proto(v7, String_ctor, 1,
-                                          v7->vals.string_prototype);
-  v7_def(v7, v7->vals.global_object, "String", 6, V7_DESC_ENUMERABLE(0), str);
-
-  set_cfunc_prop(v7, str, "fromCharCode", Str_fromCharCode);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "charCodeAt", Str_charCodeAt);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "charAt", Str_charAt);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "concat", Str_concat);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "indexOf", Str_indexOf);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "substr", Str_substr);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "substring", Str_substring);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "valueOf", Str_valueOf);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "lastIndexOf", Str_lastIndexOf);
-#if V7_ENABLE__String__localeCompare
-  set_cfunc_prop(v7, v7->vals.string_prototype, "localeCompare",
-                 Str_localeCompare);
-#endif
-#if V7_ENABLE__RegExp
-  set_cfunc_prop(v7, v7->vals.string_prototype, "match", Str_match);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "replace", Str_replace);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "search", Str_search);
-#endif
-  set_cfunc_prop(v7, v7->vals.string_prototype, "split", Str_split);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "slice", Str_slice);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "trim", Str_trim);
-  set_cfunc_prop(v7, v7->vals.string_prototype, "toLowerCase", Str_toLowerCase);
-#if V7_ENABLE__String__localeLowerCase
-  set_cfunc_prop(v7, v7->vals.string_prototype, "toLocaleLowerCase",
-                 Str_toLowerCase);
-#endif
-  set_cfunc_prop(v7, v7->vals.string_prototype, "toUpperCase", Str_toUpperCase);
-#if V7_ENABLE__String__localeUpperCase
-  set_cfunc_prop(v7, v7->vals.string_prototype, "toLocaleUpperCase",
-                 Str_toUpperCase);
-#endif
-  set_cfunc_prop(v7, v7->vals.string_prototype, "toString", Str_toString);
-
-  v7_def(v7, v7->vals.string_prototype, "length", 6, V7_DESC_GETTER(1),
-         v7_mk_cfunction(Str_length));
-
-  /* Non-standard Cesanta extension */
-  set_cfunc_prop(v7, v7->vals.string_prototype, "at", Str_at);
-  v7_def(v7, v7->vals.string_prototype, "blen", 4, V7_DESC_GETTER(1),
-         v7_mk_cfunction(Str_blen));
-}
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_date.c"
-#endif
-/*
- * Copyright (c) 2015 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "common/str_util.h" */
-/* Amalgamated: #include "v7/src/std_object.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-
-#if V7_ENABLE__Date
-
-#include <locale.h>
-#include <time.h>
-
-#ifndef _WIN32
-extern long timezone;
-#include <sys/time.h>
-#endif
-
-#if defined(_MSC_VER)
-#define timezone _timezone
-#define tzname _tzname
-#if _MSC_VER >= 1800
-#define tzset _tzset
-#endif
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-typedef double etime_t; /* double is suitable type for ECMA time */
-/* inernally we have to use 64-bit integer for some operations */
-typedef int64_t etimeint_t;
-#define INVALID_TIME NAN
-
-#define msPerDay 86400000
-#define HoursPerDay 24
-#define MinutesPerHour 60
-#define SecondsPerMinute 60
-#define SecondsPerHour 3600
-#define msPerSecond 1000
-#define msPerMinute 60000
-#define msPerHour 3600000
-#define MonthsInYear 12
-
-/* ECMA alternative to struct tm */
-struct timeparts {
-  int year;  /* can be negative, up to +-282000 */
-  int month; /* 0-11 */
-  int day;   /* 1-31 */
-  int hour;  /* 0-23 */
-  int min;   /* 0-59 */
-  int sec;   /* 0-59 */
-  int msec;
-  int dayofweek; /* 0-6 */
-};
-
-static etimeint_t g_gmtoffms; /* timezone offset, ms, no DST */
-static const char *g_tzname;  /* current timezone name */
-
-/* Leap year formula copied from ECMA 5.1 standart as is */
-static int ecma_DaysInYear(int y) {
-  if (y % 4 != 0) {
-    return 365;
-  } else if (y % 4 == 0 && y % 100 != 0) {
-    return 366;
-  } else if (y % 100 == 0 && y % 400 != 0) {
-    return 365;
-  } else if (y % 400 == 0) {
-    return 366;
-  } else {
-    return 365;
-  }
-}
-
-static etimeint_t ecma_DayFromYear(etimeint_t y) {
-  return 365 * (y - 1970) + floor((y - 1969) / 4) - floor((y - 1901) / 100) +
-         floor((y - 1601) / 400);
-}
-
-static etimeint_t ecma_TimeFromYear(etimeint_t y) {
-  return msPerDay * ecma_DayFromYear(y);
-}
-
-static int ecma_IsLeapYear(int year) {
-  return ecma_DaysInYear(year) == 366;
-}
-
-static int *ecma_getfirstdays(int isleap) {
-  static int sdays[2][MonthsInYear + 1] = {
-      {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
-      {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
-
-  return sdays[isleap];
-}
-
-static int ecma_DaylightSavingTA(etime_t t) {
-  time_t time = t / 1000;
-  /*
-   * Win32 doesn't have locatime_r
-   * nixes don't have localtime_s
-   * as result using localtime
-   */
-  struct tm *tm = localtime(&time);
-  if (tm == NULL) {
-    /* doesn't work on windows for times before epoch */
-    return 0;
-  }
-  if (tm->tm_isdst > 0) {
-    return msPerHour;
-  } else {
-    return 0;
-  }
-}
-
-static int ecma_LocalTZA(void) {
-  return (int) -g_gmtoffms;
-}
-
-static etimeint_t ecma_UTC(etime_t t) {
-  return t - ecma_LocalTZA() - ecma_DaylightSavingTA(t - ecma_LocalTZA());
-}
-
-#if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
-    V7_ENABLE__Date__toJSON || V7_ENABLE__Date__getters ||          \
-    V7_ENABLE__Date__setters
-static int ecma_YearFromTime_s(etime_t t) {
-  int first = floor((t / msPerDay) / 366) + 1970,
-      last = floor((t / msPerDay) / 365) + 1970, middle = 0;
-
-  if (last < first) {
-    int temp = first;
-    first = last;
-    last = temp;
-  }
-
-  while (last > first) {
-    middle = (last + first) / 2;
-    if (ecma_TimeFromYear(middle) > t) {
-      last = middle - 1;
-    } else {
-      if (ecma_TimeFromYear(middle) <= t) {
-        if (ecma_TimeFromYear(middle + 1) > t) {
-          first = middle;
-          break;
-        }
-        first = middle + 1;
-      }
-    }
-  }
-
-  return first;
-}
-
-static etimeint_t ecma_Day(etime_t t) {
-  return floor(t / msPerDay);
-}
-
-static int ecma_DayWithinYear(etime_t t, int year) {
-  return (int) (ecma_Day(t) - ecma_DayFromYear(year));
-}
-
-static int ecma_MonthFromTime(etime_t t, int year) {
-  int *days, i;
-  etimeint_t dwy = ecma_DayWithinYear(t, year);
-
-  days = ecma_getfirstdays(ecma_IsLeapYear(year));
-
-  for (i = 0; i < MonthsInYear; i++) {
-    if (dwy >= days[i] && dwy < days[i + 1]) {
-      return i;
-    }
-  }
-
-  return -1;
-}
-
-static int ecma_DateFromTime(etime_t t, int year) {
-  int *days, mft = ecma_MonthFromTime(t, year),
-             dwy = ecma_DayWithinYear(t, year);
-
-  if (mft > 11) {
-    return -1;
-  }
-
-  days = ecma_getfirstdays(ecma_IsLeapYear(year));
-
-  return dwy - days[mft] + 1;
-}
-
-#define DEF_EXTRACT_TIMEPART(funcname, c1, c2) \
-  static int ecma_##funcname(etime_t t) {      \
-    int ret = (etimeint_t) floor(t / c1) % c2; \
-    if (ret < 0) {                             \
-      ret += c2;                               \
-    }                                          \
-    return ret;                                \
-  }
-
-DEF_EXTRACT_TIMEPART(HourFromTime, msPerHour, HoursPerDay)
-DEF_EXTRACT_TIMEPART(MinFromTime, msPerMinute, MinutesPerHour)
-DEF_EXTRACT_TIMEPART(SecFromTime, msPerSecond, SecondsPerMinute)
-DEF_EXTRACT_TIMEPART(msFromTime, 1, msPerSecond)
-
-static int ecma_WeekDay(etime_t t) {
-  int ret = (ecma_Day(t) + 4) % 7;
-  if (ret < 0) {
-    ret += 7;
-  }
-
-  return ret;
-}
-
-static void d_gmtime(const etime_t *t, struct timeparts *tp) {
-  tp->year = ecma_YearFromTime_s(*t);
-  tp->month = ecma_MonthFromTime(*t, tp->year);
-  tp->day = ecma_DateFromTime(*t, tp->year);
-  tp->hour = ecma_HourFromTime(*t);
-  tp->min = ecma_MinFromTime(*t);
-  tp->sec = ecma_SecFromTime(*t);
-  tp->msec = ecma_msFromTime(*t);
-  tp->dayofweek = ecma_WeekDay(*t);
-}
-#endif /* V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
-          V7_ENABLE__Date__getters || V7_ENABLE__Date__setters */
-
-#if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
-    V7_ENABLE__Date__getters || V7_ENABLE__Date__setters
-static etimeint_t ecma_LocalTime(etime_t t) {
-  return t + ecma_LocalTZA() + ecma_DaylightSavingTA(t);
-}
-
-static void d_localtime(const etime_t *time, struct timeparts *tp) {
-  etime_t local_time = ecma_LocalTime(*time);
-  d_gmtime(&local_time, tp);
-}
-#endif
-
-static etimeint_t ecma_MakeTime(etimeint_t hour, etimeint_t min, etimeint_t sec,
-                                etimeint_t ms) {
-  return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) *
-             msPerSecond +
-         ms;
-}
-
-static etimeint_t ecma_MakeDay(int year, int month, int date) {
-  int *days;
-  etimeint_t yday, mday;
-
-  year += floor(month / 12);
-  month = month % 12;
-  yday = floor(ecma_TimeFromYear(year) / msPerDay);
-  days = ecma_getfirstdays(ecma_IsLeapYear(year));
-  mday = days[month];
-
-  return yday + mday + date - 1;
-}
-
-static etimeint_t ecma_MakeDate(etimeint_t day, etimeint_t time) {
-  return (day * msPerDay + time);
-}
-
-static void d_gettime(etime_t *t) {
-#ifndef _WIN32
-  struct timeval tv;
-  gettimeofday(&tv, NULL);
-  *t = (etime_t) tv.tv_sec * 1000 + (etime_t) tv.tv_usec / 1000;
-#else
-  /* TODO(mkm): use native windows API in order to get ms granularity */
-  *t = time(NULL) * 1000.0;
-#endif
-}
-
-static etime_t d_mktime_impl(const struct timeparts *tp) {
-  return ecma_MakeDate(ecma_MakeDay(tp->year, tp->month, tp->day),
-                       ecma_MakeTime(tp->hour, tp->min, tp->sec, tp->msec));
-}
-
-#if V7_ENABLE__Date__setters
-static etime_t d_lmktime(const struct timeparts *tp) {
-  return ecma_UTC(d_mktime_impl(tp));
-}
-#endif
-
-static etime_t d_gmktime(const struct timeparts *tp) {
-  return d_mktime_impl(tp);
-}
-
-typedef etime_t (*fmaketime_t)(const struct timeparts *);
-typedef void (*fbreaktime_t)(const etime_t *, struct timeparts *);
-
-#if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
-    V7_ENABLE__Date__toJSON
-static val_t d_trytogetobjforstring(struct v7 *v7, val_t obj) {
-  enum v7_err rcode = V7_OK;
-  val_t ret = V7_UNDEFINED;
-
-  rcode = obj_value_of(v7, obj, &ret);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (ret == V7_TAG_NAN) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Date is invalid (for string)");
-    goto clean;
-  }
-
-clean:
-  (void) rcode;
-  return ret;
-}
-#endif
-
-#if V7_ENABLE__Date__parse || V7_ENABLE__Date__UTC
-static int d_iscalledasfunction(struct v7 *v7, val_t this_obj) {
-  /* TODO(alashkin): verify this statement */
-  return is_prototype_of(v7, this_obj, v7->vals.date_prototype);
-}
-#endif
-
-static const char *mon_name[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-
-int d_getnumbyname(const char **arr, int arr_size, const char *str) {
-  int i;
-  for (i = 0; i < arr_size; i++) {
-    if (strncmp(arr[i], str, 3) == 0) {
-      return i + 1;
-    }
-  }
-
-  return -1;
-}
-
-int date_parse(const char *str, int *a1, int *a2, int *a3, char sep,
-               char *rest) {
-  char frmDate[] = " %d/%d/%d%[^\0]";
-  frmDate[3] = frmDate[6] = sep;
-  return sscanf(str, frmDate, a1, a2, a3, rest);
-}
-
-#define NO_TZ 0x7FFFFFFF
-
-/*
- * not very smart but simple, and working according
- * to ECMA5.1 StringToDate function
- */
-static int d_parsedatestr(const char *jstr, size_t len, struct timeparts *tp,
-                          int *tz) {
-  char gmt[4];
-  char buf1[100] = {0}, buf2[100] = {0};
-  int res = 0;
-  char str[101];
-  memcpy(str, jstr, len);
-  str[len] = '\0';
-  memset(tp, 0, sizeof(*tp));
-  *tz = NO_TZ;
-
-  /* trying toISOSrting() format */
-  {
-    const char *frmISOString = " %d-%02d-%02dT%02d:%02d:%02d.%03dZ";
-    res = sscanf(str, frmISOString, &tp->year, &tp->month, &tp->day, &tp->hour,
-                 &tp->min, &tp->sec, &tp->msec);
-    if (res == 7) {
-      *tz = 0;
-      return 1;
-    }
-  }
-
-  /* trying toString()/toUTCString()/toDateFormat() formats */
-  {
-    char month[4];
-    int dowlen;
-    const char *frmString = " %*s%n %03s %02d %d %02d:%02d:%02d %03s%d";
-    res = sscanf(str, frmString, &dowlen, month, &tp->day, &tp->year, &tp->hour,
-                 &tp->min, &tp->sec, gmt, tz);
-    if ((res == 3 || (res >= 6 && res <= 8)) && dowlen == 3) {
-      if ((tp->month = d_getnumbyname(mon_name, ARRAY_SIZE(mon_name), month)) !=
-          -1) {
-        if (res == 7 && strncmp(gmt, "GMT", 3) == 0) {
-          *tz = 0;
-        }
-        return 1;
-      }
-    }
-  }
-
-  /* trying the rest */
-
-  /* trying date */
-
-  if (!(date_parse(str, &tp->month, &tp->day, &tp->year, '/', buf1) >= 3 ||
-        date_parse(str, &tp->day, &tp->month, &tp->year, '.', buf1) >= 3 ||
-        date_parse(str, &tp->year, &tp->month, &tp->day, '-', buf1) >= 3)) {
-    return 0;
-  }
-
-  /*  there is date, trying time; from here return 0 only on errors */
-
-  /* trying HH:mm */
-  {
-    const char *frmMMhh = " %d:%d%[^\0]";
-    res = sscanf(buf1, frmMMhh, &tp->hour, &tp->min, buf2);
-    /* can't get time, but have some symbols, assuming error */
-    if (res < 2) {
-      return (strlen(buf2) == 0);
-    }
-  }
-
-  /* trying seconds */
-  {
-    const char *frmss = ":%d%[^\0]";
-    memset(buf1, 0, sizeof(buf1));
-    res = sscanf(buf2, frmss, &tp->sec, buf1);
-  }
-
-  /* even if we don't get seconds we gonna try to get tz */
-  {
-    char *rest = res ? buf1 : buf2;
-    char *buf = res ? buf2 : buf1;
-    const char *frmtz = " %03s%d%[^\0]";
-
-    res = sscanf(rest, frmtz, gmt, tz, buf);
-    if (res == 1 && strncmp(gmt, "GMT", 3) == 0) {
-      *tz = 0;
-    }
-  }
-
-  /* return OK if we are at the end of string */
-  return res <= 2;
-}
-
-static int d_timeFromString(etime_t *time, const char *str, size_t str_len) {
-  struct timeparts tp;
-  int tz;
-
-  *time = INVALID_TIME;
-
-  if (str_len > 100) {
-    /* too long for valid date string */
-    return 0;
-  }
-
-  if (d_parsedatestr(str, str_len, &tp, &tz)) {
-    /* check results */
-    int valid = 0;
-
-    tp.month--;
-    valid = tp.day >= 1 && tp.day <= 31;
-    valid &= tp.month >= 0 && tp.month <= 11;
-    valid &= tp.hour >= 0 && tp.hour <= 23;
-    valid &= tp.min >= 0 && tp.min <= 59;
-    valid &= tp.sec >= 0 && tp.sec <= 59;
-
-    if (tz != NO_TZ && tz > 12) {
-      tz /= 100;
-    }
-
-    valid &= (abs(tz) <= 12 || tz == NO_TZ);
-
-    if (valid) {
-      *time = d_gmktime(&tp);
-
-      if (tz != NO_TZ) {
-        /* timezone specified, use it */
-        *time -= (tz * msPerHour);
-      } else if (tz != 0) {
-        /* assuming local timezone and moving back to UTC */
-        *time = ecma_UTC(*time);
-      }
-    }
-  }
-
-  return !isnan(*time);
-}
-
-/* notice: holding month in calendar format (1-12, not 0-11) */
-struct dtimepartsarr {
-  etime_t args[7];
-};
-
-enum detimepartsarr {
-  tpyear = 0,
-  tpmonth,
-  tpdate,
-  tphours,
-  tpminutes,
-  tpseconds,
-  tpmsec,
-  tpmax
-};
-
-static etime_t d_changepartoftime(const etime_t *current,
-                                  struct dtimepartsarr *a,
-                                  fbreaktime_t breaktimefunc,
-                                  fmaketime_t maketimefunc) {
-  /*
-   * 0 = year, 1 = month , 2 = date , 3 = hours,
-   * 4 = minutes, 5 = seconds, 6 = ms
-   */
-  struct timeparts tp;
-  unsigned long i;
-  int *tp_arr[7];
-  /*
-   * C89 doesn't allow initialization
-   * like x = {&tp.year, &tp.month, .... }
-   */
-  tp_arr[0] = &tp.year;
-  tp_arr[1] = &tp.month;
-  tp_arr[2] = &tp.day;
-  tp_arr[3] = &tp.hour;
-  tp_arr[4] = &tp.min;
-  tp_arr[5] = &tp.sec;
-  tp_arr[6] = &tp.msec;
-
-  memset(&tp, 0, sizeof(tp));
-
-  if (breaktimefunc != NULL) {
-    breaktimefunc(current, &tp);
-  }
-
-  for (i = 0; i < ARRAY_SIZE(tp_arr); i++) {
-    if (!isnan(a->args[i]) && !isinf(a->args[i])) {
-      *tp_arr[i] = (int) a->args[i];
-    }
-  }
-
-  return maketimefunc(&tp);
-}
-
-#if V7_ENABLE__Date__setters || V7_ENABLE__Date__UTC
-static etime_t d_time_number_from_arr(struct v7 *v7, int start_pos,
-                                      fbreaktime_t breaktimefunc,
-                                      fmaketime_t maketimefunc) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  etime_t ret_time = INVALID_TIME;
-  long cargs;
-
-  val_t objtime = V7_UNDEFINED;
-  rcode = obj_value_of(v7, this_obj, &objtime);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if ((cargs = v7_argc(v7)) >= 1 && objtime != V7_TAG_NAN) {
-    int i;
-    etime_t new_part = INVALID_TIME;
-    struct dtimepartsarr a;
-    for (i = 0; i < 7; i++) {
-      a.args[i] = INVALID_TIME;
-    }
-
-    for (i = 0; i < cargs && (i + start_pos < tpmax); i++) {
-      {
-        val_t arg = v7_arg(v7, i);
-        rcode = to_number_v(v7, arg, &arg);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-        new_part = v7_get_double(v7, arg);
-      }
-
-      if (isnan(new_part)) {
-        break;
-      }
-
-      a.args[i + start_pos] = new_part;
-    }
-
-    if (!isnan(new_part)) {
-      etime_t current_time = v7_get_double(v7, objtime);
-      ret_time =
-          d_changepartoftime(&current_time, &a, breaktimefunc, maketimefunc);
-    }
-  }
-
-clean:
-  (void) rcode;
-  return ret_time;
-}
-#endif /* V7_ENABLE__Date__setters */
-
-#if V7_ENABLE__Date__toString
-static int d_tptostr(const struct timeparts *tp, char *buf, int addtz);
-#endif
-
-/* constructor */
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Date_ctor(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  etime_t ret_time = INVALID_TIME;
-  if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
-    long cargs = v7_argc(v7);
-    if (cargs <= 0) {
-      /* no parameters - return current date & time */
-      d_gettime(&ret_time);
-    } else if (cargs == 1) {
-      /* one parameter */
-      val_t arg = v7_arg(v7, 0);
-      if (v7_is_string(arg)) { /* it could be string */
-        size_t str_size;
-        const char *str = v7_get_string(v7, &arg, &str_size);
-        d_timeFromString(&ret_time, str, str_size);
-      }
-      if (isnan(ret_time)) {
-        /*
-         * if cannot be parsed or
-         * not string at all - trying to convert to number
-         */
-        ret_time = 0;
-        rcode = to_number_v(v7, arg, &arg);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-        ret_time = v7_get_double(v7, arg);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-      }
-    } else {
-      /* 2+ paramaters - should be parts of a date */
-      struct dtimepartsarr a;
-      int i;
-
-      memset(&a, 0, sizeof(a));
-
-      for (i = 0; i < cargs; i++) {
-        val_t arg = v7_arg(v7, i);
-        rcode = to_number_v(v7, arg, &arg);
-        if (rcode != V7_OK) {
-          goto clean;
-        }
-        a.args[i] = v7_get_double(v7, arg);
-        if (isnan(a.args[i])) {
-          break;
-        }
-      }
-
-      if (i >= cargs) {
-        /*
-         * If date is supplied then let
-         * dt be ToNumber(date); else let dt be 1.
-         */
-        if (a.args[tpdate] == 0) {
-          a.args[tpdate] = 1;
-        }
-
-        if (a.args[tpyear] >= 0 && a.args[tpyear] <= 99) {
-          /*
-           * If y is not NaN and 0 <= ToInteger(y) <= 99,
-           * then let yr be 1900+ToInteger(y); otherwise, let yr be y.
-           */
-          a.args[tpyear] += 1900;
-        }
-
-        ret_time = ecma_UTC(d_changepartoftime(0, &a, 0, d_gmktime));
-      }
-    }
-
-    obj_prototype_set(v7, get_object_struct(this_obj),
-                      get_object_struct(v7->vals.date_prototype));
-
-    v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), v7_mk_number(v7, ret_time));
-    /*
-     * implicitly returning `this`: `call_cfunction()` in bcode.c will do
-     * that for us
-     */
-    goto clean;
-  } else {
-    /*
-     * according to 15.9.2.1 we should ignore all
-     * parameters in case of function-call
-     */
-    char buf[50];
-    int len;
-
-#if V7_ENABLE__Date__toString
-    struct timeparts tp;
-    d_gettime(&ret_time);
-    d_localtime(&ret_time, &tp);
-    len = d_tptostr(&tp, buf, 1);
-#else
-    len = 0;
-#endif /* V7_ENABLE__Date__toString */
-
-    *res = v7_mk_string(v7, buf, len, 1);
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-#if V7_ENABLE__Date__toString || V7_ENABLE__Date__toJSON
-static int d_timetoISOstr(const etime_t *time, char *buf, size_t buf_size) {
-  /* ISO format: "+XXYYYY-MM-DDTHH:mm:ss.sssZ"; */
-  struct timeparts tp;
-  char use_ext = 0;
-  const char *ey_frm = "%06d-%02d-%02dT%02d:%02d:%02d.%03dZ";
-  const char *simpl_frm = "%d-%02d-%02dT%02d:%02d:%02d.%03dZ";
-
-  d_gmtime(time, &tp);
-
-  if (abs(tp.year) > 9999 || tp.year < 0) {
-    *buf = (tp.year > 0) ? '+' : '-';
-    use_ext = 1;
-  }
-
-  return c_snprintf(buf + use_ext, buf_size - use_ext,
-                    use_ext ? ey_frm : simpl_frm, abs(tp.year), tp.month + 1,
-                    tp.day, tp.hour, tp.min, tp.sec, tp.msec) +
-         use_ext;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Date_toISOString(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  char buf[30];
-  etime_t time;
-  int len;
-
-  if (val_type(v7, this_obj) != V7_TYPE_DATE_OBJECT) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "This is not a Date object");
-    goto clean;
-  }
-
-  time = v7_get_double(v7, d_trytogetobjforstring(v7, this_obj));
-  len = d_timetoISOstr(&time, buf, sizeof(buf));
-  if (len > (int) (sizeof(buf) - 1 /*null-term*/)) {
-    len = (int) (sizeof(buf) - 1 /*null-term*/);
-  }
-
-  *res = v7_mk_string(v7, buf, len, 1);
-
-clean:
-  return rcode;
-}
-#endif /* V7_ENABLE__Date__toString || V7_ENABLE__Date__toJSON */
-
-#if V7_ENABLE__Date__toString
-typedef int (*ftostring_t)(const struct timeparts *, char *, int);
-
-WARN_UNUSED_RESULT
-static enum v7_err d_tostring(struct v7 *v7, val_t obj,
-                              fbreaktime_t breaktimefunc,
-                              ftostring_t tostringfunc, int addtz,
-                              v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  struct timeparts tp;
-  int len;
-  char buf[100];
-  etime_t time;
-
-  time = v7_get_double(v7, d_trytogetobjforstring(v7, obj));
-
-  breaktimefunc(&time, &tp);
-  len = tostringfunc(&tp, buf, addtz);
-
-  *res = v7_mk_string(v7, buf, len, 1);
-  return rcode;
-}
-
-/* using macros to avoid copy-paste technic */
-#define DEF_TOSTR(funcname, breaktimefunc, tostrfunc, addtz)               \
-  WARN_UNUSED_RESULT                                                       \
-  V7_PRIVATE enum v7_err Date_to##funcname(struct v7 *v7, v7_val_t *res) { \
-    val_t this_obj = v7_get_this(v7);                                      \
-    return d_tostring(v7, this_obj, breaktimefunc, tostrfunc, addtz, res); \
-  }
-
-/* non-locale function should always return in english and 24h-format */
-static const char *wday_name[] = {"Sun", "Mon", "Tue", "Wed",
-                                  "Thu", "Fri", "Sat"};
-
-static int d_tptodatestr(const struct timeparts *tp, char *buf, int addtz) {
-  (void) addtz;
-
-  return sprintf(buf, "%s %s %02d %d", wday_name[tp->dayofweek],
-                 mon_name[tp->month], tp->day, tp->year);
-}
-
-DEF_TOSTR(DateString, d_localtime, d_tptodatestr, 1)
-
-static const char *d_gettzname(void) {
-  return g_tzname;
-}
-
-static int d_tptotimestr(const struct timeparts *tp, char *buf, int addtz) {
-  int len;
-
-  len = sprintf(buf, "%02d:%02d:%02d GMT", tp->hour, tp->min, tp->sec);
-
-  if (addtz && g_gmtoffms != 0) {
-    len = sprintf(buf + len, "%c%02d00 (%s)", g_gmtoffms > 0 ? '-' : '+',
-                  abs((int) g_gmtoffms / msPerHour), d_gettzname());
-  }
-
-  return (int) strlen(buf);
-}
-
-DEF_TOSTR(TimeString, d_localtime, d_tptotimestr, 1)
-
-static int d_tptostr(const struct timeparts *tp, char *buf, int addtz) {
-  int len = d_tptodatestr(tp, buf, addtz);
-  *(buf + len) = ' ';
-  return d_tptotimestr(tp, buf + len + 1, addtz) + len + 1;
-}
-
-DEF_TOSTR(String, d_localtime, d_tptostr, 1)
-DEF_TOSTR(UTCString, d_gmtime, d_tptostr, 0)
-#endif /* V7_ENABLE__Date__toString */
-
-#if V7_ENABLE__Date__toLocaleString
-struct d_locale {
-  char locale[50];
-};
-
-static void d_getcurrentlocale(struct d_locale *loc) {
-  strcpy(loc->locale, setlocale(LC_TIME, 0));
-}
-
-static void d_setlocale(const struct d_locale *loc) {
-  setlocale(LC_TIME, loc ? loc->locale : "");
-}
-
-/* TODO(alashkin): check portability */
-WARN_UNUSED_RESULT
-static enum v7_err d_tolocalestr(struct v7 *v7, val_t obj, const char *frm,
-                                 v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  char buf[250];
-  size_t len;
-  struct tm t;
-  etime_t time;
-  struct d_locale prev_locale;
-  struct timeparts tp;
-
-  time = v7_get_double(v7, d_trytogetobjforstring(v7, obj));
-
-  d_getcurrentlocale(&prev_locale);
-  d_setlocale(0);
-  d_localtime(&time, &tp);
-
-  memset(&t, 0, sizeof(t));
-  t.tm_year = tp.year - 1900;
-  t.tm_mon = tp.month;
-  t.tm_mday = tp.day;
-  t.tm_hour = tp.hour;
-  t.tm_min = tp.min;
-  t.tm_sec = tp.sec;
-  t.tm_wday = tp.dayofweek;
-
-  len = strftime(buf, sizeof(buf), frm, &t);
-
-  d_setlocale(&prev_locale);
-
-  *res = v7_mk_string(v7, buf, len, 1);
-  return rcode;
-}
-
-#define DEF_TOLOCALESTR(funcname, frm)                                     \
-  WARN_UNUSED_RESULT                                                       \
-  V7_PRIVATE enum v7_err Date_to##funcname(struct v7 *v7, v7_val_t *res) { \
-    val_t this_obj = v7_get_this(v7);                                      \
-    return d_tolocalestr(v7, this_obj, frm, res);                          \
-  }
-
-DEF_TOLOCALESTR(LocaleString, "%c")
-DEF_TOLOCALESTR(LocaleDateString, "%x")
-DEF_TOLOCALESTR(LocaleTimeString, "%X")
-#endif /* V7_ENABLE__Date__toLocaleString */
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Date_valueOf(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  if (!v7_is_generic_object(this_obj) ||
-      (v7_is_generic_object(this_obj) &&
-       v7_get_proto(v7, this_obj) != v7->vals.date_prototype)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Date.valueOf called on non-Date object");
-    goto clean;
-  }
-
-  rcode = Obj_valueOf(v7, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-#if V7_ENABLE__Date__getters
-static struct timeparts *d_getTimePart(struct v7 *v7, val_t val,
-                                       struct timeparts *tp,
-                                       fbreaktime_t breaktimefunc) {
-  etime_t time;
-  time = v7_get_double(v7, val);
-  breaktimefunc(&time, tp);
-  return tp;
-}
-
-#define DEF_GET_TP_FUNC(funcName, tpmember, breaktimefunc)                   \
-  WARN_UNUSED_RESULT                                                         \
-  V7_PRIVATE enum v7_err Date_get##funcName(struct v7 *v7, v7_val_t *res) {  \
-    enum v7_err rcode = V7_OK;                                               \
-    val_t v = V7_UNDEFINED;                                                  \
-    struct timeparts tp;                                                     \
-    val_t this_obj = v7_get_this(v7);                                        \
-                                                                             \
-    rcode = obj_value_of(v7, this_obj, &v);                                  \
-    if (rcode != V7_OK) {                                                    \
-      goto clean;                                                            \
-    }                                                                        \
-    *res = v7_mk_number(                                                     \
-        v7, v == V7_TAG_NAN ? NAN : d_getTimePart(v7, v, &tp, breaktimefunc) \
-                                        ->tpmember);                         \
-  clean:                                                                     \
-    return rcode;                                                            \
-  }
-
-#define DEF_GET_TP(funcName, tpmember)               \
-  DEF_GET_TP_FUNC(UTC##funcName, tpmember, d_gmtime) \
-  DEF_GET_TP_FUNC(funcName, tpmember, d_localtime)
-
-DEF_GET_TP(Date, day)
-DEF_GET_TP(FullYear, year)
-DEF_GET_TP(Month, month)
-DEF_GET_TP(Hours, hour)
-DEF_GET_TP(Minutes, min)
-DEF_GET_TP(Seconds, sec)
-DEF_GET_TP(Milliseconds, msec)
-DEF_GET_TP(Day, dayofweek)
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Date_getTime(struct v7 *v7, v7_val_t *res) {
-  return Date_valueOf(v7, res);
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Date_getTimezoneOffset(struct v7 *v7, v7_val_t *res) {
-  (void) v7;
-  *res = v7_mk_number(v7, g_gmtoffms / msPerMinute);
-  return V7_OK;
-}
-#endif /* V7_ENABLE__Date__getters */
-
-#if V7_ENABLE__Date__setters
-WARN_UNUSED_RESULT
-static enum v7_err d_setTimePart(struct v7 *v7, int start_pos,
-                                 fbreaktime_t breaktimefunc,
-                                 fmaketime_t maketimefunc, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  etime_t ret_time =
-      d_time_number_from_arr(v7, start_pos, breaktimefunc, maketimefunc);
-
-  *res = v7_mk_number(v7, ret_time);
-  v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
-
-  return rcode;
-}
-
-#define DEF_SET_TP(name, start_pos)                                        \
-  WARN_UNUSED_RESULT                                                       \
-  V7_PRIVATE enum v7_err Date_setUTC##name(struct v7 *v7, v7_val_t *res) { \
-    return d_setTimePart(v7, start_pos, d_gmtime, d_gmktime, res);         \
-  }                                                                        \
-  WARN_UNUSED_RESULT                                                       \
-  V7_PRIVATE enum v7_err Date_set##name(struct v7 *v7, v7_val_t *res) {    \
-    return d_setTimePart(v7, start_pos, d_localtime, d_lmktime, res);      \
-  }
-
-DEF_SET_TP(Milliseconds, tpmsec)
-DEF_SET_TP(Seconds, tpseconds)
-DEF_SET_TP(Minutes, tpminutes)
-DEF_SET_TP(Hours, tphours)
-DEF_SET_TP(Date, tpdate)
-DEF_SET_TP(Month, tpmonth)
-DEF_SET_TP(FullYear, tpyear)
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Date_setTime(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-
-  if (v7_argc(v7) >= 1) {
-    rcode = to_number_v(v7, v7_arg(v7, 0), res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-  v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
-
-clean:
-  return rcode;
-}
-#endif /* V7_ENABLE__Date__setters */
-
-#if V7_ENABLE__Date__toJSON
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Date_toJSON(struct v7 *v7, v7_val_t *res) {
-  return Date_toISOString(v7, res);
-}
-#endif /* V7_ENABLE__Date__toJSON */
-
-#if V7_ENABLE__Date__now
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Date_now(struct v7 *v7, v7_val_t *res) {
-  etime_t ret_time;
-  (void) v7;
-
-  d_gettime(&ret_time);
-
-  *res = v7_mk_number(v7, ret_time);
-  return V7_OK;
-}
-#endif /* V7_ENABLE__Date__now */
-
-#if V7_ENABLE__Date__parse
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Date_parse(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  etime_t ret_time = INVALID_TIME;
-
-  if (!d_iscalledasfunction(v7, this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Date.parse() called on object");
-    goto clean;
-  }
-
-  if (v7_argc(v7) >= 1) {
-    val_t arg0 = v7_arg(v7, 0);
-    if (v7_is_string(arg0)) {
-      size_t size;
-      const char *time_str = v7_get_string(v7, &arg0, &size);
-
-      d_timeFromString(&ret_time, time_str, size);
-    }
-  }
-
-  *res = v7_mk_number(v7, ret_time);
-
-clean:
-  return rcode;
-}
-#endif /* V7_ENABLE__Date__parse */
-
-#if V7_ENABLE__Date__UTC
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Date_UTC(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  etime_t ret_time;
-
-  if (!d_iscalledasfunction(v7, this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Date.now() called on object");
-    goto clean;
-  }
-
-  ret_time = d_time_number_from_arr(v7, tpyear, 0, d_gmktime);
-  *res = v7_mk_number(v7, ret_time);
-
-clean:
-  return rcode;
-}
-#endif /* V7_ENABLE__Date__UTC */
-
-/****** Initialization *******/
-
-/*
- * We should clear V7_PROPERTY_ENUMERABLE for all Date props
- * TODO(mkm): check other objects
-*/
-static int d_set_cfunc_prop(struct v7 *v7, val_t o, const char *name,
-                            v7_cfunction_t *f) {
-  return v7_def(v7, o, name, strlen(name), V7_DESC_ENUMERABLE(0),
-                v7_mk_cfunction(f));
-}
-
-#define DECLARE_GET(func)                                       \
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "getUTC" #func, \
-                   Date_getUTC##func);                          \
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "get" #func, Date_get##func);
-
-#define DECLARE_SET(func)                                       \
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "setUTC" #func, \
-                   Date_setUTC##func);                          \
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "set" #func, Date_set##func);
-
-V7_PRIVATE void init_date(struct v7 *v7) {
-  val_t date =
-      mk_cfunction_obj_with_proto(v7, Date_ctor, 7, v7->vals.date_prototype);
-  v7_def(v7, v7->vals.global_object, "Date", 4, V7_DESC_ENUMERABLE(0), date);
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "valueOf", Date_valueOf);
-
-#if V7_ENABLE__Date__getters
-  DECLARE_GET(Date);
-  DECLARE_GET(FullYear);
-  DECLARE_GET(Month);
-  DECLARE_GET(Hours);
-  DECLARE_GET(Minutes);
-  DECLARE_GET(Seconds);
-  DECLARE_GET(Milliseconds);
-  DECLARE_GET(Day);
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "getTime", Date_getTime);
-#endif
-
-#if V7_ENABLE__Date__setters
-  DECLARE_SET(Date);
-  DECLARE_SET(FullYear);
-  DECLARE_SET(Month);
-  DECLARE_SET(Hours);
-  DECLARE_SET(Minutes);
-  DECLARE_SET(Seconds);
-  DECLARE_SET(Milliseconds);
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "setTime", Date_setTime);
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "getTimezoneOffset",
-                   Date_getTimezoneOffset);
-#endif
-
-#if V7_ENABLE__Date__now
-  d_set_cfunc_prop(v7, date, "now", Date_now);
-#endif
-#if V7_ENABLE__Date__parse
-  d_set_cfunc_prop(v7, date, "parse", Date_parse);
-#endif
-#if V7_ENABLE__Date__UTC
-  d_set_cfunc_prop(v7, date, "UTC", Date_UTC);
-#endif
-
-#if V7_ENABLE__Date__toString
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "toString", Date_toString);
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "toISOString",
-                   Date_toISOString);
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "toUTCString",
-                   Date_toUTCString);
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "toDateString",
-                   Date_toDateString);
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "toTimeString",
-                   Date_toTimeString);
-#endif
-#if V7_ENABLE__Date__toLocaleString
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleString",
-                   Date_toLocaleString);
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleDateString",
-                   Date_toLocaleDateString);
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleTimeString",
-                   Date_toLocaleTimeString);
-#endif
-#if V7_ENABLE__Date__toJSON
-  d_set_cfunc_prop(v7, v7->vals.date_prototype, "toJSON", Date_toJSON);
-#endif
-
-  /*
-   * GTM offset without DST
-   * TODO(alashkin): check this
-   * Could be changed to tm::tm_gmtoff,
-   * but tm_gmtoff includes DST, so
-   * side effects are possible
-   */
-  tzset();
-  g_gmtoffms = timezone * msPerSecond;
-  /*
-   * tzname could be changed by localtime_r call,
-   * so we have to store pointer
-   * TODO(alashkin): need restart on tz change???
-   */
-  g_tzname = tzname[0];
-}
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* V7_ENABLE__Date */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_function.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/str_util.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/bcode.h" */
-/* Amalgamated: #include "v7/src/eval.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/exec.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Function_ctor(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  long i, num_args = v7_argc(v7);
-  size_t size;
-  const char *s;
-  struct mbuf m;
-
-  mbuf_init(&m, 0);
-
-  if (num_args <= 0) {
-    goto clean;
-  }
-
-  mbuf_append(&m, "(function(", 10);
-
-  for (i = 0; i < num_args - 1; i++) {
-    rcode = obj_value_of(v7, v7_arg(v7, i), res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-    if (v7_is_string(*res)) {
-      if (i > 0) mbuf_append(&m, ",", 1);
-      s = v7_get_string(v7, res, &size);
-      mbuf_append(&m, s, size);
-    }
-  }
-  mbuf_append(&m, "){", 2);
-  rcode = obj_value_of(v7, v7_arg(v7, num_args - 1), res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-  if (v7_is_string(*res)) {
-    s = v7_get_string(v7, res, &size);
-    mbuf_append(&m, s, size);
-  }
-  mbuf_append(&m, "})\0", 3);
-
-  rcode = v7_exec(v7, m.buf, res);
-  if (rcode != V7_OK) {
-    rcode = v7_throwf(v7, SYNTAX_ERROR, "Invalid function body");
-    goto clean;
-  }
-
-clean:
-  mbuf_free(&m);
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Function_length(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t this_obj = v7_get_this(v7);
-  struct v7_js_function *func;
-
-  rcode = obj_value_of(v7, this_obj, &this_obj);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-  if (!is_js_function(this_obj)) {
-    *res = v7_mk_number(v7, 0);
-    goto clean;
-  }
-
-  func = get_js_function_struct(this_obj);
-
-  *res = v7_mk_number(v7, func->bcode->args_cnt);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Function_name(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  v7_val_t this_obj = v7_get_this(v7);
-  struct v7_js_function *func;
-
-  rcode = obj_value_of(v7, this_obj, &this_obj);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-  if (!is_js_function(this_obj)) {
-    goto clean;
-  }
-
-  func = get_js_function_struct(this_obj);
-
-  assert(func->bcode != NULL);
-
-  assert(func->bcode->names_cnt >= 1);
-  bcode_next_name_v(v7, func->bcode, func->bcode->ops.p, res);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Function_apply(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t this_arg = v7_arg(v7, 0);
-  val_t func_args = v7_arg(v7, 1);
-
-  rcode = obj_value_of(v7, this_obj, &this_obj);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (is_js_function(this_obj)) {
-    /*
-     * `Function_apply` is a cfunction, so, GC is inhibited before calling it.
-     * But the given function to call is a JS function, so we should enable GC;
-     * otherwise, it will be inhibited during the whole execution of the given
-     * JS function
-     */
-    v7_set_gc_enabled(v7, 1);
-  }
-
-  rcode = b_apply(v7, this_obj, this_arg, func_args, 0, res);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Function_toString(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  char *ops;
-  char *name;
-  size_t name_len;
-  char buf[50];
-  char *b = buf;
-  struct v7_js_function *func = get_js_function_struct(v7_get_this(v7));
-  int i;
-
-  b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "[function");
-
-  assert(func->bcode != NULL);
-  ops = func->bcode->ops.p;
-
-  /* first entry in name list */
-  ops = bcode_next_name(ops, &name, &name_len);
-
-  if (name_len > 0) {
-    b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), " %.*s", (int) name_len,
-                    name);
-  }
-  b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "(");
-  for (i = 0; i < func->bcode->args_cnt; i++) {
-    ops = bcode_next_name(ops, &name, &name_len);
-
-    b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "%.*s", (int) name_len,
-                    name);
-    if (i < func->bcode->args_cnt - 1) {
-      b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ",");
-    }
-  }
-  b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ")");
-
-  {
-    uint8_t loc_cnt =
-        func->bcode->names_cnt - func->bcode->args_cnt - 1 /*func name*/;
-
-    if (loc_cnt > 0) {
-      b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "{var ");
-      for (i = 0; i < loc_cnt; ++i) {
-        ops = bcode_next_name(ops, &name, &name_len);
-
-        b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "%.*s",
-                        (int) name_len, name);
-        if (i < (loc_cnt - 1)) {
-          b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ",");
-        }
-      }
-
-      b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "}");
-    }
-  }
-
-  b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "]");
-
-  *res = v7_mk_string(v7, buf, strlen(buf), 1);
-
-  return rcode;
-}
-
-V7_PRIVATE void init_function(struct v7 *v7) {
-  val_t ctor = mk_cfunction_obj(v7, Function_ctor, 1);
-
-  v7_set(v7, ctor, "prototype", 9, v7->vals.function_prototype);
-  v7_set(v7, v7->vals.global_object, "Function", 8, ctor);
-  set_method(v7, v7->vals.function_prototype, "apply", Function_apply, 1);
-  set_method(v7, v7->vals.function_prototype, "toString", Function_toString, 0);
-  v7_def(v7, v7->vals.function_prototype, "length", 6,
-         (V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1)),
-         v7_mk_cfunction(Function_length));
-  v7_def(v7, v7->vals.function_prototype, "name", 4,
-         (V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1)),
-         v7_mk_cfunction(Function_name));
-}
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_regex.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "common/utf.h" */
-/* Amalgamated: #include "common/str_util.h" */
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/std_regex.h" */
-/* Amalgamated: #include "v7/src/std_string.h" */
-/* Amalgamated: #include "v7/src/slre.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/array.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/regexp.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-
-#if V7_ENABLE__RegExp
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Regex_ctor(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  long argnum = v7_argc(v7);
-
-  if (argnum > 0) {
-    val_t arg = v7_arg(v7, 0);
-    val_t ro, fl;
-    size_t re_len, flags_len = 0;
-    const char *re, *flags = NULL;
-
-    if (v7_is_regexp(v7, arg)) {
-      if (argnum > 1) {
-        /* ch15/15.10/15.10.3/S15.10.3.1_A2_T1.js */
-        rcode = v7_throwf(v7, TYPE_ERROR, "invalid flags");
-        goto clean;
-      }
-      *res = arg;
-      goto clean;
-    }
-    rcode = to_string(v7, arg, &ro, NULL, 0, NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-    if (argnum > 1) {
-      rcode = to_string(v7, v7_arg(v7, 1), &fl, NULL, 0, NULL);
-      if (rcode != V7_OK) {
-        goto clean;
-      }
-
-      flags = v7_get_string(v7, &fl, &flags_len);
-    }
-    re = v7_get_string(v7, &ro, &re_len);
-    rcode = v7_mk_regexp(v7, re, re_len, flags, flags_len, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-
-  } else {
-    rcode = v7_mk_regexp(v7, "(?:)", 4, NULL, 0, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Regex_global(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  int flags = 0;
-  val_t this_obj = v7_get_this(v7);
-  val_t r = V7_UNDEFINED;
-  rcode = obj_value_of(v7, this_obj, &r);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (v7_is_regexp(v7, r)) {
-    flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp);
-  }
-
-  *res = v7_mk_boolean(v7, flags & SLRE_FLAG_G);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Regex_ignoreCase(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  int flags = 0;
-  val_t this_obj = v7_get_this(v7);
-  val_t r = V7_UNDEFINED;
-  rcode = obj_value_of(v7, this_obj, &r);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (v7_is_regexp(v7, r)) {
-    flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp);
-  }
-
-  *res = v7_mk_boolean(v7, flags & SLRE_FLAG_I);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Regex_multiline(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  int flags = 0;
-  val_t this_obj = v7_get_this(v7);
-  val_t r = V7_UNDEFINED;
-  rcode = obj_value_of(v7, this_obj, &r);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (v7_is_regexp(v7, r)) {
-    flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp);
-  }
-
-  *res = v7_mk_boolean(v7, flags & SLRE_FLAG_M);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Regex_source(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t r = V7_UNDEFINED;
-  const char *buf = 0;
-  size_t len = 0;
-
-  rcode = obj_value_of(v7, this_obj, &r);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (v7_is_regexp(v7, r)) {
-    buf = v7_get_string(v7, &v7_get_regexp_struct(v7, r)->regexp_string, &len);
-  }
-
-  *res = v7_mk_string(v7, buf, len, 1);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Regex_get_lastIndex(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  long lastIndex = 0;
-  val_t this_obj = v7_get_this(v7);
-
-  if (v7_is_regexp(v7, this_obj)) {
-    lastIndex = v7_get_regexp_struct(v7, this_obj)->lastIndex;
-  }
-
-  *res = v7_mk_number(v7, lastIndex);
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Regex_set_lastIndex(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  long lastIndex = 0;
-  val_t this_obj = v7_get_this(v7);
-
-  if (v7_is_regexp(v7, this_obj)) {
-    rcode = to_long(v7, v7_arg(v7, 0), 0, &lastIndex);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-    v7_get_regexp_struct(v7, this_obj)->lastIndex = lastIndex;
-  }
-
-  *res = v7_mk_number(v7, lastIndex);
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err rx_exec(struct v7 *v7, val_t rx, val_t vstr, int lind,
-                               val_t *res) {
-  enum v7_err rcode = V7_OK;
-  if (v7_is_regexp(v7, rx)) {
-    val_t s = V7_UNDEFINED;
-    size_t len;
-    struct slre_loot sub;
-    struct slre_cap *ptok = sub.caps;
-    const char *str = NULL;
-    const char *end = NULL;
-    const char *begin = NULL;
-    struct v7_regexp *rp = v7_get_regexp_struct(v7, rx);
-    int flag_g = slre_get_flags(rp->compiled_regexp) & SLRE_FLAG_G;
-
-    rcode = to_string(v7, vstr, &s, NULL, 0, NULL);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-    str = v7_get_string(v7, &s, &len);
-    end = str + len;
-    begin = str;
-
-    if (rp->lastIndex < 0) rp->lastIndex = 0;
-    if (flag_g || lind) begin = utfnshift(str, rp->lastIndex);
-
-    if (!slre_exec(rp->compiled_regexp, 0, begin, end, &sub)) {
-      int i;
-      val_t arr = v7_mk_array(v7);
-      char *old_mbuf_base = v7->owned_strings.buf;
-      ptrdiff_t rel = 0; /* creating strings might relocate the mbuf */
-
-      for (i = 0; i < sub.num_captures; i++, ptok++) {
-        rel = v7->owned_strings.buf - old_mbuf_base;
-        v7_array_push(v7, arr, v7_mk_string(v7, ptok->start + rel,
-                                            ptok->end - ptok->start, 1));
-      }
-      if (flag_g) rp->lastIndex = utfnlen(str, sub.caps->end + rel - str);
-      v7_def(v7, arr, "index", 5, V7_DESC_WRITABLE(0),
-             v7_mk_number(v7, utfnlen(str + rel, sub.caps->start - str)));
-      *res = arr;
-      goto clean;
-    } else {
-      rp->lastIndex = 0;
-    }
-  }
-
-  *res = V7_NULL;
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Regex_exec(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-
-  if (v7_argc(v7) > 0) {
-    rcode = rx_exec(v7, this_obj, v7_arg(v7, 0), 0, res);
-    if (rcode != V7_OK) {
-      goto clean;
-    }
-  } else {
-    *res = V7_NULL;
-  }
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Regex_test(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t tmp = V7_UNDEFINED;
-
-  rcode = Regex_exec(v7, &tmp);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  *res = v7_mk_boolean(v7, !v7_is_null(tmp));
-
-clean:
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Regex_flags(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  char buf[3] = {0};
-  val_t this_obj = v7_get_this(v7);
-  struct v7_regexp *rp = v7_get_regexp_struct(v7, this_obj);
-  size_t n = get_regexp_flags_str(v7, rp, buf);
-  *res = v7_mk_string(v7, buf, n, 1);
-
-  return rcode;
-}
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Regex_toString(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  size_t n1, n2 = 0;
-  char s2[3] = {0};
-  char buf[50];
-  val_t this_obj = v7_get_this(v7);
-  struct v7_regexp *rp;
-  const char *s1;
-
-  rcode = obj_value_of(v7, this_obj, &this_obj);
-  if (rcode != V7_OK) {
-    goto clean;
-  }
-
-  if (!v7_is_regexp(v7, this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Not a regexp");
-    goto clean;
-  }
-
-  rp = v7_get_regexp_struct(v7, this_obj);
-  s1 = v7_get_string(v7, &rp->regexp_string, &n1);
-  n2 = get_regexp_flags_str(v7, rp, s2);
-
-  c_snprintf(buf, sizeof(buf), "/%.*s/%.*s", (int) n1, s1, (int) n2, s2);
-
-  *res = v7_mk_string(v7, buf, strlen(buf), 1);
-
-clean:
-  return rcode;
-}
-
-V7_PRIVATE void init_regex(struct v7 *v7) {
-  val_t ctor =
-      mk_cfunction_obj_with_proto(v7, Regex_ctor, 1, v7->vals.regexp_prototype);
-  val_t lastIndex = v7_mk_dense_array(v7);
-
-  v7_def(v7, v7->vals.global_object, "RegExp", 6, V7_DESC_ENUMERABLE(0), ctor);
-
-  set_cfunc_prop(v7, v7->vals.regexp_prototype, "exec", Regex_exec);
-  set_cfunc_prop(v7, v7->vals.regexp_prototype, "test", Regex_test);
-  set_method(v7, v7->vals.regexp_prototype, "toString", Regex_toString, 0);
-
-  v7_def(v7, v7->vals.regexp_prototype, "global", 6, V7_DESC_GETTER(1),
-         v7_mk_cfunction(Regex_global));
-  v7_def(v7, v7->vals.regexp_prototype, "ignoreCase", 10, V7_DESC_GETTER(1),
-         v7_mk_cfunction(Regex_ignoreCase));
-  v7_def(v7, v7->vals.regexp_prototype, "multiline", 9, V7_DESC_GETTER(1),
-         v7_mk_cfunction(Regex_multiline));
-  v7_def(v7, v7->vals.regexp_prototype, "source", 6, V7_DESC_GETTER(1),
-         v7_mk_cfunction(Regex_source));
-  v7_def(v7, v7->vals.regexp_prototype, "flags", 5, V7_DESC_GETTER(1),
-         v7_mk_cfunction(Regex_flags));
-
-  v7_array_set(v7, lastIndex, 0, v7_mk_cfunction(Regex_get_lastIndex));
-  v7_array_set(v7, lastIndex, 1, v7_mk_cfunction(Regex_set_lastIndex));
-  v7_def(v7, v7->vals.regexp_prototype, "lastIndex", 9,
-         (V7_DESC_GETTER(1) | V7_DESC_SETTER(1)), lastIndex);
-}
-
-#endif /* V7_ENABLE__RegExp */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/std_proxy.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/std_object.h" */
-/* Amalgamated: #include "v7/src/std_proxy.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "v7/src/core.h" */
-/* Amalgamated: #include "v7/src/function.h" */
-/* Amalgamated: #include "v7/src/object.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/string.h" */
-/* Amalgamated: #include "v7/src/exceptions.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-#if V7_ENABLE__Proxy
-
-WARN_UNUSED_RESULT
-V7_PRIVATE enum v7_err Proxy_ctor(struct v7 *v7, v7_val_t *res) {
-  enum v7_err rcode = V7_OK;
-  val_t this_obj = v7_get_this(v7);
-  val_t target_v = v7_arg(v7, 0);
-  val_t handler_v = v7_arg(v7, 1);
-  struct v7_object *t = NULL;
-  v7_prop_attr_desc_t attrs_desc =
-      (V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0));
-
-  if (this_obj == v7_get_global(v7) || !v7_is_object(this_obj)) {
-    rcode = v7_throwf(v7, TYPE_ERROR, "Wrong 'this' object for Proxy ctor");
-    goto clean;
-  }
-
-  if (!v7_is_object(target_v) || !v7_is_object(handler_v)) {
-    rcode =
-        v7_throwf(v7, TYPE_ERROR,
-                  "Cannot create proxy with a non-object as target or handler");
-    goto clean;
-  }
-
-  t = get_object_struct(this_obj);
-  t->attributes |= V7_OBJ_PROXY;
-
-  v7_def(v7, this_obj, _V7_PROXY_TARGET_NAME, ~0, attrs_desc, target_v);
-  v7_def(v7, this_obj, _V7_PROXY_HANDLER_NAME, ~0, attrs_desc, handler_v);
-
-  (void) res;
-
-clean:
-  return rcode;
-}
-
-V7_PRIVATE void init_proxy(struct v7 *v7) {
-  /*v7_prop_attr_desc_t attrs_desc =*/
-  /*(V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0));*/
-  val_t proxy =
-      mk_cfunction_obj_with_proto(v7, Proxy_ctor, 1, v7->vals.proxy_prototype);
-
-  v7_def(v7, v7->vals.global_object, "Proxy", ~0, V7_DESC_ENUMERABLE(0), proxy);
-}
-
-V7_PRIVATE int is_special_proxy_name(const char *name, size_t name_len) {
-  int ret = 0;
-  if (name_len == (size_t) ~0) {
-    name_len = strlen(name);
-  }
-  if (name_len == 5 && (memcmp(name, _V7_PROXY_TARGET_NAME, name_len) == 0 ||
-                        memcmp(name, _V7_PROXY_HANDLER_NAME, name_len) == 0)) {
-    ret = 1;
-  }
-  return ret;
-}
-
-#endif /* V7_ENABLE__Proxy */
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/main.c"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/internal.h" */
-/* Amalgamated: #include "v7/src/gc.h" */
-/* Amalgamated: #include "v7/src/freeze.h" */
-/* Amalgamated: #include "v7/src/main.h" */
-/* Amalgamated: #include "v7/src/primitive.h" */
-/* Amalgamated: #include "v7/src/exec.h" */
-/* Amalgamated: #include "v7/src/util.h" */
-/* Amalgamated: #include "v7/src/conversion.h" */
-/* Amalgamated: #include "common/platform.h" */
-/* Amalgamated: #include "common/cs_file.h" */
-
-#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define fileno _fileno
-#endif
-
-#ifdef V7_EXE
-#define V7_MAIN
-#endif
-
-#ifdef V7_MAIN
-
-#include <sys/stat.h>
-
-static void show_usage(char *argv[]) {
-  fprintf(stderr, "V7 version %s (c) Cesanta Software, built on %s\n",
-          V7_VERSION, __DATE__);
-  fprintf(stderr, "Usage: %s [OPTIONS] js_file ...\n", argv[0]);
-  fprintf(stderr, "%s\n", "OPTIONS:");
-  fprintf(stderr, "%s\n", "  -e <expr>            execute expression");
-  fprintf(stderr, "%s\n", "  -t                   dump generated text AST");
-  fprintf(stderr, "%s\n", "  -b                   dump generated binary AST");
-  fprintf(stderr, "%s\n", "  -c                   dump compiled binary bcode");
-  fprintf(stderr, "%s\n", "  -mm                  dump memory stats");
-  fprintf(stderr, "%s\n", "  -vo <n>              object arena size");
-  fprintf(stderr, "%s\n", "  -vf <n>              function arena size");
-  fprintf(stderr, "%s\n", "  -vp <n>              property arena size");
-#ifdef V7_FREEZE
-  fprintf(stderr, "%s\n", "  -freeze filename     dump JS heap into a file");
-#endif
-  exit(EXIT_FAILURE);
-}
-
-#if V7_ENABLE__Memory__stats
-static void dump_mm_arena_stats(const char *msg, struct gc_arena *a) {
-  printf("%s: total allocations %lu, total garbage %lu, max %" SIZE_T_FMT
-         ", alive %lu\n",
-         msg, a->allocations, a->garbage, gc_arena_size(a), a->alive);
-  printf(
-      "%s: (bytes: total allocations %lu, total garbage %lu, max %" SIZE_T_FMT
-      ", alive %lu)\n",
-      msg, a->allocations * a->cell_size, a->garbage * a->cell_size,
-      gc_arena_size(a) * a->cell_size, a->alive * a->cell_size);
-}
-
-static void dump_mm_stats(struct v7 *v7) {
-  dump_mm_arena_stats("object: ", &v7->generic_object_arena);
-  dump_mm_arena_stats("function: ", &v7->function_arena);
-  dump_mm_arena_stats("property: ", &v7->property_arena);
-  printf("string arena len: %" SIZE_T_FMT "\n", v7->owned_strings.len);
-  printf("Total heap size: %" SIZE_T_FMT "\n",
-         v7->owned_strings.len +
-             gc_arena_size(&v7->generic_object_arena) *
-                 v7->generic_object_arena.cell_size +
-             gc_arena_size(&v7->function_arena) * v7->function_arena.cell_size +
-             gc_arena_size(&v7->property_arena) * v7->property_arena.cell_size);
-}
-#endif
-
-int v7_main(int argc, char *argv[], void (*pre_freeze_init)(struct v7 *),
-            void (*pre_init)(struct v7 *), void (*post_init)(struct v7 *)) {
-  int exit_rcode = EXIT_SUCCESS;
-  struct v7 *v7;
-  struct v7_create_opts opts;
-  int as_json = 0;
-  int i, j, show_ast = 0, binary_ast = 0, dump_bcode = 0, dump_stats = 0;
-  val_t res;
-  int nexprs = 0;
-  const char *exprs[16];
-
-  memset(&opts, 0, sizeof(opts));
-
-  (void) show_ast;
-  (void) binary_ast;
-  (void) dump_bcode;
-
-  /* Execute inline code */
-  for (i = 1; i < argc && argv[i][0] == '-'; i++) {
-    if (strcmp(argv[i], "-e") == 0 && i + 1 < argc) {
-      exprs[nexprs++] = argv[i + 1];
-      i++;
-    } else if (strcmp(argv[i], "-t") == 0) {
-      show_ast = 1;
-    } else if (strcmp(argv[i], "-b") == 0) {
-      show_ast = 1;
-      binary_ast = 1;
-    } else if (strcmp(argv[i], "-c") == 0) {
-      binary_ast = 1;
-      dump_bcode = 1;
-    } else if (strcmp(argv[i], "-h") == 0) {
-      show_usage(argv);
-    } else if (strcmp(argv[i], "-j") == 0) {
-      as_json = 1;
-#if V7_ENABLE__Memory__stats
-    } else if (strcmp(argv[i], "-mm") == 0) {
-      dump_stats = 1;
-#endif
-    } else if (strcmp(argv[i], "-vo") == 0 && i + 1 < argc) {
-      opts.object_arena_size = atoi(argv[i + 1]);
-      i++;
-    } else if (strcmp(argv[i], "-vf") == 0 && i + 1 < argc) {
-      opts.function_arena_size = atoi(argv[i + 1]);
-      i++;
-    } else if (strcmp(argv[i], "-vp") == 0 && i + 1 < argc) {
-      opts.property_arena_size = atoi(argv[i + 1]);
-      i++;
-    }
-#ifdef V7_FREEZE
-    else if (strcmp(argv[i], "-freeze") == 0 && i + 1 < argc) {
-      opts.freeze_file = argv[i + 1];
-      i++;
-    }
-#endif
-  }
-
-#ifndef V7_ALLOW_ARGLESS_MAIN
-  if (argc == 1) {
-    show_usage(argv);
-  }
-#endif
-
-  v7 = v7_create_opt(opts);
-  res = V7_UNDEFINED;
-
-  if (pre_freeze_init != NULL) {
-    pre_freeze_init(v7);
-  }
-
-#ifdef V7_FREEZE
-  /*
-   * Skip pre_init if freezing, but still execute cmdline expressions.
-   * This makes it easier to add custom code when freezing from cmdline.
-   */
-  if (opts.freeze_file == NULL) {
-#endif
-
-    if (pre_init != NULL) {
-      pre_init(v7);
-    }
-
-#ifdef V7_FREEZE
-  }
-#endif
-
-#if V7_ENABLE__Memory__stats > 0 && !defined(V7_DISABLE_GC)
-  if (dump_stats) {
-    printf("Memory stats during init:\n");
-    dump_mm_stats(v7);
-    v7_gc(v7, 0);
-    printf("Memory stats before run:\n");
-    dump_mm_stats(v7);
-  }
-#else
-  (void) dump_stats;
-#endif
-
-  /* Execute inline expressions */
-  for (j = 0; j < nexprs; j++) {
-    enum v7_err (*exec)(struct v7 *, const char *, v7_val_t *);
-    exec = v7_exec;
-
-    if (show_ast || dump_bcode) {
-#if !defined(V7_NO_COMPILER)
-      if (v7_compile(exprs[j], binary_ast, dump_bcode, stdout) != V7_OK) {
-        exit_rcode = EXIT_FAILURE;
-        fprintf(stderr, "%s\n", "parse error");
-      }
-#else  /* V7_NO_COMPILER */
-      exit_rcode = EXIT_FAILURE;
-      fprintf(stderr, "%s\n", "Parsing is disabled by V7_NO_COMPILER");
-#endif /* V7_NO_COMPILER */
-    } else if (exec(v7, exprs[j], &res) != V7_OK) {
-      v7_print_error(stderr, v7, exprs[j], res);
-      exit_rcode = EXIT_FAILURE;
-      res = V7_UNDEFINED;
-    }
-  }
-
-  /* Execute files */
-  for (; i < argc; i++) {
-    if (show_ast || dump_bcode) {
-#if !defined(V7_NO_COMPILER)
-      size_t size;
-      char *source_code;
-      if ((source_code = cs_read_file(argv[i], &size)) == NULL) {
-        exit_rcode = EXIT_FAILURE;
-        fprintf(stderr, "Cannot read [%s]\n", argv[i]);
-      } else {
-        if (_v7_compile(source_code, size, binary_ast, dump_bcode, stdout) !=
-            V7_OK) {
-          fprintf(stderr, "error: %s\n", v7->error_msg);
-          exit_rcode = EXIT_FAILURE;
-          exit(exit_rcode);
-        }
-        free(source_code);
-      }
-#else  /* V7_NO_COMPILER */
-      exit_rcode = EXIT_FAILURE;
-      fprintf(stderr, "%s\n", "Parsing is disabled by V7_NO_COMPILER");
-#endif /* V7_NO_COMPILER */
-    } else if (v7_exec_file(v7, argv[i], &res) != V7_OK) {
-      v7_print_error(stderr, v7, argv[i], res);
-      res = V7_UNDEFINED;
-    }
-  }
-
-#ifdef V7_FREEZE
-  if (opts.freeze_file != NULL) {
-    freeze(v7, opts.freeze_file);
-    exit(0);
-  }
-#endif
-
-  if (!(show_ast || dump_bcode)) {
-    char buf[2000];
-    char *s = v7_stringify(v7, res, buf, sizeof(buf),
-                           as_json ? V7_STRINGIFY_JSON : V7_STRINGIFY_DEBUG);
-    printf("%s\n", s);
-    if (s != buf) {
-      free(s);
-    }
-  }
-
-  if (post_init != NULL) {
-    post_init(v7);
-  }
-
-#if V7_ENABLE__Memory__stats
-  if (dump_stats) {
-    printf("Memory stats after run:\n");
-    dump_mm_stats(v7);
-  }
-#else
-  (void) dump_stats;
-#endif
-
-  v7_destroy(v7);
-  return exit_rcode;
-}
-#endif
-
-#ifdef V7_EXE
-int main(int argc, char *argv[]) {
-  return v7_main(argc, argv, NULL, NULL, NULL);
-}
-#endif
-#endif /* V7_EXPORT_INTERNAL_HEADERS */
--- a/ICE-Application/src/add-ons/v7/v7.h	Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1752 +0,0 @@
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/license.h"
-#endif
-/*
- * Copyright (c) 2013-2014 Cesanta Software Limited
- * All rights reserved
- *
- * This software is dual-licensed: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. For the terms of this
- * license, see <http://www.gnu.org/licenses/>.
- *
- * You are free to use this software under the terms of the GNU General
- * Public License, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * Alternatively, you can license this software under a commercial
- * license, as set out in <https://www.cesanta.com/license>.
- */
-
-#ifdef V7_EXPOSE_PRIVATE
-#define V7_PRIVATE
-#define V7_EXTERN extern
-#else
-#define V7_PRIVATE static
-#define V7_EXTERN static
-#endif /* CS_V7_SRC_LICENSE_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/features_profiles.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_FEATURES_PROFILES_H_
-#define CS_V7_SRC_FEATURES_PROFILES_H_
-
-#define V7_BUILD_PROFILE_MINIMAL 1
-#define V7_BUILD_PROFILE_MEDIUM 2
-#define V7_BUILD_PROFILE_FULL 3
-
-#ifndef V7_BUILD_PROFILE
-#define V7_BUILD_PROFILE V7_BUILD_PROFILE_FULL
-#endif
-
-#endif /* CS_V7_SRC_FEATURES_PROFILES_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/features_minimal.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/features_profiles.h" */
-
-#if V7_BUILD_PROFILE == V7_BUILD_PROFILE_MINIMAL
-
-/* This space is intentionally left blank. */
-
-#endif /* CS_V7_SRC_FEATURES_MINIMAL_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/features_medium.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/* Amalgamated: #include "v7/src/features_profiles.h" */
-
-#if V7_BUILD_PROFILE == V7_BUILD_PROFILE_MEDIUM
-
-#define V7_ENABLE__Date 1
-#define V7_ENABLE__Date__now 1
-#define V7_ENABLE__Date__UTC 1
-#define V7_ENABLE__Math 1
-#define V7_ENABLE__Math__atan2 1
-#define V7_ENABLE__RegExp 1
-
-#endif /* CS_V7_SRC_FEATURES_MEDIUM_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/features_full.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_FEATURES_FULL_H_
-#define CS_V7_SRC_FEATURES_FULL_H_
-
-/* Amalgamated: #include "v7/src/features_profiles.h" */
-
-#if V7_BUILD_PROFILE == V7_BUILD_PROFILE_FULL
-/*
- * DO NOT EDIT.
- * This file is generated by scripts/gen-features-full.pl.
- */
-#ifndef CS_ENABLE_UTF8
-#define CS_ENABLE_UTF8 1
-#endif
-
-#define V7_ENABLE__Array__reduce 1
-#define V7_ENABLE__Blob 1
-#define V7_ENABLE__Date 1
-#define V7_ENABLE__Date__UTC 1
-#define V7_ENABLE__Date__getters 1
-#define V7_ENABLE__Date__now 1
-#define V7_ENABLE__Date__parse 1
-#define V7_ENABLE__Date__setters 1
-#define V7_ENABLE__Date__toJSON 1
-#define V7_ENABLE__Date__toLocaleString 1
-#define V7_ENABLE__Date__toString 1
-#define V7_ENABLE__File__list 1
-#define V7_ENABLE__File__require 1
-#define V7_ENABLE__Function__bind 1
-#define V7_ENABLE__Function__call 1
-#define V7_ENABLE__Math 1
-#define V7_ENABLE__Math__abs 1
-#define V7_ENABLE__Math__acos 1
-#define V7_ENABLE__Math__asin 1
-#define V7_ENABLE__Math__atan 1
-#define V7_ENABLE__Math__atan2 1
-#define V7_ENABLE__Math__ceil 1
-#define V7_ENABLE__Math__constants 1
-#define V7_ENABLE__Math__cos 1
-#define V7_ENABLE__Math__exp 1
-#define V7_ENABLE__Math__floor 1
-#define V7_ENABLE__Math__log 1
-#define V7_ENABLE__Math__max 1
-#define V7_ENABLE__Math__min 1
-#define V7_ENABLE__Math__pow 1
-#define V7_ENABLE__Math__random 1
-#define V7_ENABLE__Math__round 1
-#define V7_ENABLE__Math__sin 1
-#define V7_ENABLE__Math__sqrt 1
-#define V7_ENABLE__Math__tan 1
-#define V7_ENABLE__Memory__stats 1
-#define V7_ENABLE__NUMBER__NEGATIVE_INFINITY 1
-#define V7_ENABLE__NUMBER__POSITIVE_INFINITY 1
-#define V7_ENABLE__Object__create 1
-#define V7_ENABLE__Object__defineProperties 1
-#define V7_ENABLE__Object__getOwnPropertyDescriptor 1
-#define V7_ENABLE__Object__getOwnPropertyNames 1
-#define V7_ENABLE__Object__getPrototypeOf 1
-#define V7_ENABLE__Object__hasOwnProperty 1
-#define V7_ENABLE__Object__isExtensible 1
-#define V7_ENABLE__Object__isFrozen 1
-#define V7_ENABLE__Object__isPrototypeOf 1
-#define V7_ENABLE__Object__isSealed 1
-#define V7_ENABLE__Object__keys 1
-#define V7_ENABLE__Object__preventExtensions 1
-#define V7_ENABLE__Object__propertyIsEnumerable 1
-#define V7_ENABLE__Proxy 1
-#define V7_ENABLE__RegExp 1
-#define V7_ENABLE__StackTrace 1
-#define V7_ENABLE__String__localeCompare 1
-#define V7_ENABLE__String__localeLowerCase 1
-#define V7_ENABLE__String__localeUpperCase 1
-
-#endif /* V7_BUILD_PROFILE == V7_BUILD_PROFILE_FULL */
-
-#endif /* CS_V7_SRC_FEATURES_FULL_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/v7_features.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_V7_FEATURES_H_
-#define CS_V7_SRC_V7_FEATURES_H_
-
-/* Only one will actually be used based on V7_BUILD_PROFILE. */
-/* Amalgamated: #include "v7/src/features_minimal.h" */
-/* Amalgamated: #include "v7/src/features_medium.h" */
-/* Amalgamated: #include "v7/src/features_full.h" */
-
-#endif /* CS_V7_SRC_V7_FEATURES_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/platform.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-#ifndef CS_V7_SRC_PLATFORM_H_
-#define CS_V7_SRC_PLATFORM_H_
-
-#ifdef __arm
-#undef V7_ENABLE__Date
-#define V7_ENABLE__Date 0
-#endif
-
-#endif /* CS_V7_SRC_PLATFORM_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/core_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Core
- */
-
-#ifndef CS_V7_SRC_CORE_PUBLIC_H_
-#define CS_V7_SRC_CORE_PUBLIC_H_
-
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200809L
-#endif
-
-/* Amalgamated: #include "v7/src/license.h" */
-/* Amalgamated: #include "v7/src/v7_features.h" */
-/* Amalgamated: #include "v7/src/platform.h" */
-
-#include <stddef.h> /* For size_t */
-#include <stdio.h>  /* For FILE */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * TODO(dfrank) : improve amalgamation, so that we'll be able to include
- * files here, and include common/platform.h
- *
- * For now, copy-pasting `WARN_UNUSED_RESULT` here
- */
-#ifdef __GNUC__
-#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-#define NOINSTR __attribute__((no_instrument_function))
-#else
-#define WARN_UNUSED_RESULT
-#define NOINSTR
-#endif
-
-#define V7_VERSION "1.0"
-
-#if (defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)) || \
-    (defined(_MSC_VER) && _MSC_VER <= 1200)
-#define V7_WINDOWS
-#endif
-
-#ifdef V7_WINDOWS
-typedef unsigned __int64 uint64_t;
-#else
-#include <inttypes.h>
-#endif
-/* 64-bit value, used to store JS values */
-typedef uint64_t v7_val_t;
-
-/* JavaScript `null` value */
-#define V7_NULL ((uint64_t) 0xfffe << 48)
-
-/* JavaScript `undefined` value */
-#define V7_UNDEFINED ((uint64_t) 0xfffd << 48)
-
-/* This if-0 is a dirty workaround to force etags to pick `struct v7` */
-#if 0
-/* Opaque structure. V7 engine context. */
-struct v7 {
-  /* ... */
-};
-#endif
-
-struct v7;
-
-/*
- * Code which is returned by some of the v7 functions. If something other than
- * `V7_OK` is returned from some function, the caller function typically should
- * either immediately cleanup and return the code further, or handle the error.
- */
-enum v7_err {
-  V7_OK,
-  V7_SYNTAX_ERROR,
-  V7_EXEC_EXCEPTION,
-  V7_AST_TOO_LARGE,
-  V7_INTERNAL_ERROR,
-};
-
-/* JavaScript -> C call interface */
-WARN_UNUSED_RESULT
-typedef enum v7_err(v7_cfunction_t)(struct v7 *v7, v7_val_t *res);
-
-/* Create V7 instance */
-struct v7 *v7_create(void);
-
-/*
- * Customizations of initial V7 state; used by `v7_create_opt()`.
- */
-struct v7_create_opts {
-  size_t object_arena_size;
-  size_t function_arena_size;
-  size_t property_arena_size;
-#ifdef V7_STACK_SIZE
-  void *c_stack_base;
-#endif
-#ifdef V7_FREEZE
-  /* if not NULL, dump JS heap after init */
-  char *freeze_file;
-#endif
-};
-
-/*
- * Like `v7_create()`, but allows to customize initial v7 state, see `struct
- * v7_create_opts`.
- */
-struct v7 *v7_create_opt(struct v7_create_opts opts);
-
-/* Destroy V7 instance */
-void v7_destroy(struct v7 *v7);
-
-/* Return root level (`global`) object of the given V7 instance. */
-v7_val_t v7_get_global(struct v7 *v);
-
-/* Return current `this` object. */
-v7_val_t v7_get_this(struct v7 *v);
-
-/* Return current `arguments` array */
-v7_val_t v7_get_arguments(struct v7 *v);
-
-/* Return i-th argument */
-v7_val_t v7_arg(struct v7 *v, unsigned long i);
-
-/* Return the length of `arguments` */
-unsigned long v7_argc(struct v7 *v7);
-
-/*
- * Tells the GC about a JS value variable/field owned
- * by C code.
- *
- * User C code should own v7_val_t variables
- * if the value's lifetime crosses any invocation
- * to the v7 runtime that creates new objects or new
- * properties and thus can potentially trigger GC.
- *
- * The registration of the variable prevents the GC from mistakenly treat
- * the object as garbage. The GC might be triggered potentially
- * allows the GC to update pointers
- *
- * User code should also explicitly disown the variables with v7_disown once
- * it goes out of scope or the structure containing the v7_val_t field is freed.
- *
- * Example:
- *
- *  ```
- *    struct v7_val cb;
- *    v7_own(v7, &cb);
- *    cb = v7_array_get(v7, args, 0);
- *    // do something with cb
- *    v7_disown(v7, &cb);
- *  ```
- */
-void v7_own(struct v7 *v7, v7_val_t *v);
-
-/*
- * Returns 1 if value is found, 0 otherwise
- */
-int v7_disown(struct v7 *v7, v7_val_t *v);
-
-/*
- * Enable or disable GC.
- *
- * Must be called before invoking v7_exec or v7_apply
- * from within a cfunction unless you know what you're doing.
- *
- * GC is disabled during execution of cfunctions in order to simplify
- * memory management of simple cfunctions.
- * However executing even small snippets of JS code causes a lot of memory
- * pressure. Enabling GC solves that but forces you to take care of the
- * reachability of your temporary V7 v7_val_t variables, as the GC needs
- * to know where they are since objects and strings can be either reclaimed
- * or relocated during a GC pass.
- */
-void v7_set_gc_enabled(struct v7 *v7, int enabled);
-
-/*
- * Set an optional C stack limit.
- *
- * It sets a flag that will cause the interpreter
- * to throw an InterruptedError.
- * It's safe to call it from signal handlers and ISRs
- * on single threaded environments.
- */
-void v7_interrupt(struct v7 *v7);
-
-/* Returns last parser error message. TODO: rename it to `v7_get_error()` */
-const char *v7_get_parser_error(struct v7 *v7);
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-/*
- * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
- *
- * Stack metric id. See `v7_stack_stat()`
- */
-enum v7_stack_stat_what {
-  /* max stack size consumed by `i_exec()` */
-  V7_STACK_STAT_EXEC,
-  /* max stack size consumed by `parse()` (which is called from `i_exec()`) */
-  V7_STACK_STAT_PARSER,
-
-  V7_STACK_STATS_CNT
-};
-
-/*
- * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
- *
- * Returns stack metric specified by the metric id `what`. See
- * `v7_stack_stat_clean()`
- */
-int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what);
-
-/*
- * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
- *
- * Clean all stack statistics gathered so far. See `v7_stack_stat()`
- */
-void v7_stack_stat_clean(struct v7 *v7);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_CORE_PUBLIC_H_ */
-#ifndef V7_EXPORT_INTERNAL_HEADERS
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/core_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Core
- */
-
-#ifndef CS_V7_SRC_CORE_PUBLIC_H_
-#define CS_V7_SRC_CORE_PUBLIC_H_
-
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200809L
-#endif
-
-/* Amalgamated: #include "v7/src/license.h" */
-/* Amalgamated: #include "v7/src/v7_features.h" */
-/* Amalgamated: #include "v7/src/platform.h" */
-
-#include <stddef.h> /* For size_t */
-#include <stdio.h>  /* For FILE */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * TODO(dfrank) : improve amalgamation, so that we'll be able to include
- * files here, and include common/platform.h
- *
- * For now, copy-pasting `WARN_UNUSED_RESULT` here
- */
-#ifdef __GNUC__
-#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-#define NOINSTR __attribute__((no_instrument_function))
-#else
-#define WARN_UNUSED_RESULT
-#define NOINSTR
-#endif
-
-#define V7_VERSION "1.0"
-
-#if (defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)) || \
-    (defined(_MSC_VER) && _MSC_VER <= 1200)
-#define V7_WINDOWS
-#endif
-
-#ifdef V7_WINDOWS
-typedef unsigned __int64 uint64_t;
-#else
-#include <inttypes.h>
-#endif
-/* 64-bit value, used to store JS values */
-typedef uint64_t v7_val_t;
-
-/* JavaScript `null` value */
-#define V7_NULL ((uint64_t) 0xfffe << 48)
-
-/* JavaScript `undefined` value */
-#define V7_UNDEFINED ((uint64_t) 0xfffd << 48)
-
-/* This if-0 is a dirty workaround to force etags to pick `struct v7` */
-#if 0
-/* Opaque structure. V7 engine context. */
-struct v7 {
-  /* ... */
-};
-#endif
-
-struct v7;
-
-/*
- * Code which is returned by some of the v7 functions. If something other than
- * `V7_OK` is returned from some function, the caller function typically should
- * either immediately cleanup and return the code further, or handle the error.
- */
-enum v7_err {
-  V7_OK,
-  V7_SYNTAX_ERROR,
-  V7_EXEC_EXCEPTION,
-  V7_AST_TOO_LARGE,
-  V7_INTERNAL_ERROR,
-};
-
-/* JavaScript -> C call interface */
-WARN_UNUSED_RESULT
-typedef enum v7_err(v7_cfunction_t)(struct v7 *v7, v7_val_t *res);
-
-/* Create V7 instance */
-struct v7 *v7_create(void);
-
-/*
- * Customizations of initial V7 state; used by `v7_create_opt()`.
- */
-struct v7_create_opts {
-  size_t object_arena_size;
-  size_t function_arena_size;
-  size_t property_arena_size;
-#ifdef V7_STACK_SIZE
-  void *c_stack_base;
-#endif
-#ifdef V7_FREEZE
-  /* if not NULL, dump JS heap after init */
-  char *freeze_file;
-#endif
-};
-
-/*
- * Like `v7_create()`, but allows to customize initial v7 state, see `struct
- * v7_create_opts`.
- */
-struct v7 *v7_create_opt(struct v7_create_opts opts);
-
-/* Destroy V7 instance */
-void v7_destroy(struct v7 *v7);
-
-/* Return root level (`global`) object of the given V7 instance. */
-v7_val_t v7_get_global(struct v7 *v);
-
-/* Return current `this` object. */
-v7_val_t v7_get_this(struct v7 *v);
-
-/* Return current `arguments` array */
-v7_val_t v7_get_arguments(struct v7 *v);
-
-/* Return i-th argument */
-v7_val_t v7_arg(struct v7 *v, unsigned long i);
-
-/* Return the length of `arguments` */
-unsigned long v7_argc(struct v7 *v7);
-
-/*
- * Tells the GC about a JS value variable/field owned
- * by C code.
- *
- * User C code should own v7_val_t variables
- * if the value's lifetime crosses any invocation
- * to the v7 runtime that creates new objects or new
- * properties and thus can potentially trigger GC.
- *
- * The registration of the variable prevents the GC from mistakenly treat
- * the object as garbage. The GC might be triggered potentially
- * allows the GC to update pointers
- *
- * User code should also explicitly disown the variables with v7_disown once
- * it goes out of scope or the structure containing the v7_val_t field is freed.
- *
- * Example:
- *
- *  ```
- *    struct v7_val cb;
- *    v7_own(v7, &cb);
- *    cb = v7_array_get(v7, args, 0);
- *    // do something with cb
- *    v7_disown(v7, &cb);
- *  ```
- */
-void v7_own(struct v7 *v7, v7_val_t *v);
-
-/*
- * Returns 1 if value is found, 0 otherwise
- */
-int v7_disown(struct v7 *v7, v7_val_t *v);
-
-/*
- * Enable or disable GC.
- *
- * Must be called before invoking v7_exec or v7_apply
- * from within a cfunction unless you know what you're doing.
- *
- * GC is disabled during execution of cfunctions in order to simplify
- * memory management of simple cfunctions.
- * However executing even small snippets of JS code causes a lot of memory
- * pressure. Enabling GC solves that but forces you to take care of the
- * reachability of your temporary V7 v7_val_t variables, as the GC needs
- * to know where they are since objects and strings can be either reclaimed
- * or relocated during a GC pass.
- */
-void v7_set_gc_enabled(struct v7 *v7, int enabled);
-
-/*
- * Set an optional C stack limit.
- *
- * It sets a flag that will cause the interpreter
- * to throw an InterruptedError.
- * It's safe to call it from signal handlers and ISRs
- * on single threaded environments.
- */
-void v7_interrupt(struct v7 *v7);
-
-/* Returns last parser error message. TODO: rename it to `v7_get_error()` */
-const char *v7_get_parser_error(struct v7 *v7);
-
-#if defined(V7_ENABLE_STACK_TRACKING)
-/*
- * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
- *
- * Stack metric id. See `v7_stack_stat()`
- */
-enum v7_stack_stat_what {
-  /* max stack size consumed by `i_exec()` */
-  V7_STACK_STAT_EXEC,
-  /* max stack size consumed by `parse()` (which is called from `i_exec()`) */
-  V7_STACK_STAT_PARSER,
-
-  V7_STACK_STATS_CNT
-};
-
-/*
- * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
- *
- * Returns stack metric specified by the metric id `what`. See
- * `v7_stack_stat_clean()`
- */
-int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what);
-
-/*
- * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
- *
- * Clean all stack statistics gathered so far. See `v7_stack_stat()`
- */
-void v7_stack_stat_clean(struct v7 *v7);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_CORE_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/primitive_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Primitives
- *
- * All primitive values but strings.
- *
- * "foreign" values are also here, see `v7_mk_foreign()`.
- */
-
-#ifndef CS_V7_SRC_PRIMITIVE_PUBLIC_H_
-#define CS_V7_SRC_PRIMITIVE_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/* Make numeric primitive value */
-NOINSTR v7_val_t v7_mk_number(struct v7 *v7, double num);
-
-/*
- * Returns number value stored in `v7_val_t` as `double`.
- *
- * Returns NaN for non-numbers.
- */
-NOINSTR double v7_get_double(struct v7 *v7, v7_val_t v);
-
-/*
- * Returns number value stored in `v7_val_t` as `int`. If the number value is
- * not an integer, the fraction part will be discarded.
- *
- * If the given value is a non-number, or NaN, the result is undefined.
- */
-NOINSTR int v7_get_int(struct v7 *v7, v7_val_t v);
-
-/* Returns true if given value is a primitive number value */
-int v7_is_number(v7_val_t v);
-
-/* Make boolean primitive value (either `true` or `false`) */
-NOINSTR v7_val_t v7_mk_boolean(struct v7 *v7, int is_true);
-
-/*
- * Returns boolean stored in `v7_val_t`:
- *  0 for `false` or non-boolean, non-0 for `true`
- */
-NOINSTR int v7_get_bool(struct v7 *v7, v7_val_t v);
-
-/* Returns true if given value is a primitive boolean value */
-int v7_is_boolean(v7_val_t v);
-
-/*
- * Make `null` primitive value.
- *
- * NOTE: this function is deprecated and will be removed in future releases.
- * Use `V7_NULL` instead.
- */
-NOINSTR v7_val_t v7_mk_null(void);
-
-/* Returns true if given value is a primitive `null` value */
-int v7_is_null(v7_val_t v);
-
-/*
- * Make `undefined` primitive value.
- *
- * NOTE: this function is deprecated and will be removed in future releases.
- * Use `V7_UNDEFINED` instead.
- */
-NOINSTR v7_val_t v7_mk_undefined(void);
-
-/* Returns true if given value is a primitive `undefined` value */
-int v7_is_undefined(v7_val_t v);
-
-/*
- * Make JavaScript value that holds C/C++ `void *` pointer.
- *
- * A foreign value is completely opaque and JS code cannot do anything useful
- * with it except holding it in properties and passing it around.
- * It behaves like a sealed object with no properties.
- *
- * NOTE:
- * Only valid pointers (as defined by each supported architecture) will fully
- * preserved. In particular, all supported 64-bit architectures (x86_64, ARM-64)
- * actually define a 48-bit virtual address space.
- * Foreign values will be sign-extended as required, i.e creating a foreign
- * value of something like `(void *) -1` will work as expected. This is
- * important because in some 64-bit OSs (e.g. Solaris) the user stack grows
- * downwards from the end of the address space.
- *
- * If you need to store exactly sizeof(void*) bytes of raw data where
- * `sizeof(void*)` >= 8, please use byte arrays instead.
- */
-NOINSTR v7_val_t v7_mk_foreign(struct v7 *v7, void *ptr);
-
-/*
- * Returns `void *` pointer stored in `v7_val_t`.
- *
- * Returns NULL if the value is not a foreign pointer.
- */
-NOINSTR void *v7_get_ptr(struct v7 *v7, v7_val_t v);
-
-/* Returns true if given value holds `void *` pointer */
-int v7_is_foreign(v7_val_t v);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_PRIMITIVE_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/string_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Strings
- */
-
-#ifndef CS_V7_SRC_STRING_PUBLIC_H_
-#define CS_V7_SRC_STRING_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Creates a string primitive value.
- * `str` must point to the utf8 string of length `len`.
- * If `len` is ~0, `str` is assumed to be NUL-terminated and `strlen(str)` is
- * used.
- *
- * If `copy` is non-zero, the string data is copied and owned by the GC. The
- * caller can free the string data afterwards. Otherwise (`copy` is zero), the
- * caller owns the string data, and is responsible for not freeing it while it
- * is used.
- */
-v7_val_t v7_mk_string(struct v7 *v7, const char *str, size_t len, int copy);
-
-/* Returns true if given value is a primitive string value */
-int v7_is_string(v7_val_t v);
-
-/*
- * Returns a pointer to the string stored in `v7_val_t`.
- *
- * String length returned in `len`, which is allowed to be NULL. Returns NULL
- * if the value is not a string.
- *
- * JS strings can contain embedded NUL chars and may or may not be NUL
- * terminated.
- *
- * CAUTION: creating new JavaScript object, array, or string may kick in a
- * garbage collector, which in turn may relocate string data and invalidate
- * pointer returned by `v7_get_string()`.
- *
- * Short JS strings are embedded inside the `v7_val_t` value itself. This is why
- * a pointer to a `v7_val_t` is required. It also means that the string data
- * will become invalid once that `v7_val_t` value goes out of scope.
- */
-const char *v7_get_string(struct v7 *v7, v7_val_t *v, size_t *len);
-
-/*
- * Returns a pointer to the string stored in `v7_val_t`.
- *
- * Returns NULL if the value is not a string or if the string is not compatible
- * with a C string.
- *
- * C compatible strings contain exactly one NUL char, in terminal position.
- *
- * All strings owned by the V7 engine (see `v7_mk_string()`) are guaranteed to
- * be NUL terminated. Out of these, those that don't include embedded NUL chars
- * are guaranteed to be C compatible.
- */
-const char *v7_get_cstring(struct v7 *v7, v7_val_t *v);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_STRING_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/object_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Objects
- */
-
-#ifndef CS_V7_SRC_OBJECT_PUBLIC_H_
-#define CS_V7_SRC_OBJECT_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Property attributes bitmask
- */
-typedef unsigned short v7_prop_attr_t;
-#define V7_PROPERTY_NON_WRITABLE (1 << 0)
-#define V7_PROPERTY_NON_ENUMERABLE (1 << 1)
-#define V7_PROPERTY_NON_CONFIGURABLE (1 << 2)
-#define V7_PROPERTY_GETTER (1 << 3)
-#define V7_PROPERTY_SETTER (1 << 4)
-#define _V7_PROPERTY_HIDDEN (1 << 5)
-/* property not managed by V7 HEAP */
-#define _V7_PROPERTY_OFF_HEAP (1 << 6)
-/* special property holding user data and destructor cb */
-#define _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR (1 << 7)
-/*
- * not a property attribute, but a flag for `v7_def()`. It's here in order to
- * keep all offsets in one place
- */
-#define _V7_DESC_PRESERVE_VALUE (1 << 8)
-
-#define V7_PROP_ATTR_IS_WRITABLE(a) (!(a & V7_PROPERTY_NON_WRITABLE))
-#define V7_PROP_ATTR_IS_ENUMERABLE(a) (!(a & V7_PROPERTY_NON_ENUMERABLE))
-#define V7_PROP_ATTR_IS_CONFIGURABLE(a) (!(a & V7_PROPERTY_NON_CONFIGURABLE))
-
-/*
- * Internal helpers for `V7_DESC_...` macros
- */
-#define _V7_DESC_SHIFT 16
-#define _V7_DESC_MASK ((1 << _V7_DESC_SHIFT) - 1)
-#define _V7_MK_DESC(v, n) \
-  (((v7_prop_attr_desc_t)(n)) << _V7_DESC_SHIFT | ((v) ? (n) : 0))
-#define _V7_MK_DESC_INV(v, n) _V7_MK_DESC(!(v), (n))
-
-/*
- * Property attribute descriptors that may be given to `v7_def()`: for each
- * attribute (`v7_prop_attr_t`), there is a corresponding macro, which takes
- * param: either 1 (set attribute) or 0 (clear attribute). If some particular
- * attribute isn't mentioned at all, it's left unchanged (or default, if the
- * property is being created)
- *
- * There is additional flag: `V7_DESC_PRESERVE_VALUE`. If it is set, the
- * property value isn't changed (or set to `undefined` if the property is being
- * created)
- */
-typedef unsigned long v7_prop_attr_desc_t;
-#define V7_DESC_WRITABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_WRITABLE)
-#define V7_DESC_ENUMERABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_ENUMERABLE)
-#define V7_DESC_CONFIGURABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_CONFIGURABLE)
-#define V7_DESC_GETTER(v) _V7_MK_DESC(v, V7_PROPERTY_GETTER)
-#define V7_DESC_SETTER(v) _V7_MK_DESC(v, V7_PROPERTY_SETTER)
-#define V7_DESC_PRESERVE_VALUE _V7_DESC_PRESERVE_VALUE
-
-#define _V7_DESC_HIDDEN(v) _V7_MK_DESC(v, _V7_PROPERTY_HIDDEN)
-#define _V7_DESC_OFF_HEAP(v) _V7_MK_DESC(v, _V7_PROPERTY_OFF_HEAP)
-
-/* See `v7_set_destructor_cb` */
-typedef void(v7_destructor_cb_t)(struct v7 *v7, void *ud);
-
-/* Make an empty object */
-v7_val_t v7_mk_object(struct v7 *v7);
-
-/*
- * Returns true if the given value is an object or function.
- * i.e. it returns true if the value holds properties and can be
- * used as argument to `v7_get`, `v7_set` and `v7_def`.
- */
-int v7_is_object(v7_val_t v);
-
-/* Set object's prototype. Return old prototype or undefined on error. */
-v7_val_t v7_set_proto(struct v7 *v7, v7_val_t obj, v7_val_t proto);
-
-/* Get object's prototype. */
-v7_val_t v7_get_proto(struct v7 *v7, v7_val_t obj);
-
-/*
- * Lookup property `name` in object `obj`. If `obj` holds no such property,
- * an `undefined` value is returned.
- *
- * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
- * `strlen(name)` is used.
- */
-v7_val_t v7_get(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len);
-
-/*
- * Like `v7_get()`, but "returns" value through `res` pointer argument.
- * `res` must not be `NULL`.
- *
- * Caller should check the error code returned, and if it's something other
- * than `V7_OK`, perform cleanup and return this code further.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_get_throwing(struct v7 *v7, v7_val_t obj, const char *name,
-                            size_t name_len, v7_val_t *res);
-
-/*
- * Define object property, similar to JavaScript `Object.defineProperty()`.
- *
- * `name`, `name_len` specify property name, `val` is a property value.
- * `attrs_desc` is a set of flags which can affect property's attributes,
- * see comment of `v7_prop_attr_desc_t` for details.
- *
- * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
- * `strlen(name)` is used.
- *
- * Returns non-zero on success, 0 on error (e.g. out of memory).
- *
- * See also `v7_set()`.
- */
-int v7_def(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len,
-           v7_prop_attr_desc_t attrs_desc, v7_val_t v);
-
-/*
- * Set object property. Behaves just like JavaScript assignment.
- *
- * See also `v7_def()`.
- */
-int v7_set(struct v7 *v7, v7_val_t obj, const char *name, size_t len,
-           v7_val_t val);
-
-/*
- * A helper function to define object's method backed by a C function `func`.
- * `name` must be NUL-terminated.
- *
- * Return value is the same as for `v7_set()`.
- */
-int v7_set_method(struct v7 *, v7_val_t obj, const char *name,
-                  v7_cfunction_t *func);
-
-/*
- * Delete own property `name` of the object `obj`. Does not follow the
- * prototype chain.
- *
- * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
- * `strlen(name)` is used.
- *
- * Returns 0 on success, -1 on error.
- */
-int v7_del(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len);
-
-#if V7_ENABLE__Proxy
-struct prop_iter_proxy_ctx;
-#endif
-
-/*
- * Context for property iteration, see `v7_next_prop()`.
- *
- * Clients should not interpret contents of this structure, it's here merely to
- * allow clients to allocate it not from the heap.
- */
-struct prop_iter_ctx {
-#if V7_ENABLE__Proxy
-  struct prop_iter_proxy_ctx *proxy_ctx;
-#endif
-  struct v7_property *cur_prop;
-
-  unsigned init : 1;
-};
-
-/*
- * Initialize the property iteration context `ctx`, see `v7_next_prop()` for
- * usage example.
- */
-enum v7_err v7_init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
-                                  struct prop_iter_ctx *ctx);
-
-/*
- * Destruct the property iteration context `ctx`, see `v7_next_prop()` for
- * usage example
- */
-void v7_destruct_prop_iter_ctx(struct v7 *v7, struct prop_iter_ctx *ctx);
-
-/*
- * Iterate over the `obj`'s properties.
- *
- * Usage example (here we assume we have some `v7_val_t obj`):
- *
- *     struct prop_iter_ctx ctx;
- *     v7_val_t name, val;
- *     v7_prop_attr_t attrs;
- *
- *     v7_init_prop_iter_ctx(v7, obj, &ctx);
- *     while (v7_next_prop(v7, &ctx, &name, &val, &attrs)) {
- *       if (V7_PROP_ATTR_IS_ENUMERABLE(attrs)) continue;
- *       ...
- *     }
- *     v7_destruct_prop_iter_ctx(v7, &ctx);
- *
- * As you see, v7_next_prop will iterate through all properties, including
- * non-enumerable ones, and it's your responsibility to test the attributes
- * with the provided `V7_PROP_ATTR_*` macros and proceed as you see fit.
- */
-int v7_next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, v7_val_t *name,
-                 v7_val_t *value, v7_prop_attr_t *attrs);
-
-/* Returns true if the object is an instance of a given constructor. */
-int v7_is_instanceof(struct v7 *v7, v7_val_t o, const char *c);
-
-/* Returns true if the object is an instance of a given constructor. */
-int v7_is_instanceof_v(struct v7 *v7, v7_val_t o, v7_val_t c);
-
-/*
- * Associates an opaque C value (anything that can be casted to a `void * )
- * with an object.
- *
- * You can achieve a similar effect by just setting a special property with
- * a foreign value (see `v7_mk_foreign`), except user data offers the following
- * advantages:
- *
- * 1. You don't have to come up with some arbitrary "special" property name.
- * 2. JS scripts cannot access user data by mistake via property lookup.
- * 3. The user data is available to the destructor. When the desctructor is
- *    invoked you cannot access any of its properties.
- * 4. Allows the implementation to use a more compact encoding
- *
- * Does nothing if `obj` is not a mutable object.
- */
-void v7_set_user_data(struct v7 *v7, v7_val_t obj, void *ud);
-
-/*
- * Get the opaque user data set with `v7_set_user_data`.
- *
- * Returns NULL if there is no user data set or if `obj` is not an object.
- */
-void *v7_get_user_data(struct v7 *v7, v7_val_t obj);
-
-/*
- * Register a callback which will be invoked when a given object gets
- * reclaimed by the garbage collector.
- *
- * The callback will be invoked while garbage collection is still in progress
- * and hence the internal state of the JS heap is in an undefined state.
- *
- * The only v7 API which is safe to use in this callback is `v7_disown()`,
- * that's why `v7` pointer is given to it. *Calls to any other v7 functions are
- * illegal here*.
- *
- * The intended use case is to reclaim resources allocated by C code.
- */
-void v7_set_destructor_cb(struct v7 *v7, v7_val_t obj, v7_destructor_cb_t *d);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_OBJECT_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/array_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Arrays
- */
-
-#ifndef CS_V7_SRC_ARRAY_PUBLIC_H_
-#define CS_V7_SRC_ARRAY_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/* Make an empty array object */
-v7_val_t v7_mk_array(struct v7 *v7);
-
-/* Returns true if given value is an array object */
-int v7_is_array(struct v7 *v7, v7_val_t v);
-
-/* Returns length on an array. If `arr` is not an array, 0 is returned. */
-unsigned long v7_array_length(struct v7 *v7, v7_val_t arr);
-
-/* Insert value `v` in array `arr` at the end of the array. */
-int v7_array_push(struct v7 *, v7_val_t arr, v7_val_t v);
-
-/*
- * Like `v7_array_push()`, but "returns" value through the `res` pointer
- * argument. `res` is allowed to be `NULL`.
- *
- * Caller should check the error code returned, and if it's something other
- * than `V7_OK`, perform cleanup and return this code further.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_array_push_throwing(struct v7 *v7, v7_val_t arr, v7_val_t v,
-                                   int *res);
-
-/*
- * Return array member at index `index`. If `index` is out of bounds, undefined
- * is returned.
- */
-v7_val_t v7_array_get(struct v7 *, v7_val_t arr, unsigned long index);
-
-/* Insert value `v` into `arr` at index `index`. */
-int v7_array_set(struct v7 *v7, v7_val_t arr, unsigned long index, v7_val_t v);
-
-/*
- * Like `v7_array_set()`, but "returns" value through the `res` pointer
- * argument. `res` is allowed to be `NULL`.
- *
- * Caller should check the error code returned, and if it's something other
- * than `V7_OK`, perform cleanup and return this code further.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_array_set_throwing(struct v7 *v7, v7_val_t arr,
-                                  unsigned long index, v7_val_t v, int *res);
-
-/* Delete value in array `arr` at index `index`, if it exists. */
-void v7_array_del(struct v7 *v7, v7_val_t arr, unsigned long index);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_ARRAY_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/function_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Functions
- */
-
-#ifndef CS_V7_SRC_FUNCTION_PUBLIC_H_
-#define CS_V7_SRC_FUNCTION_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Make a JS function object backed by a cfunction.
- *
- * `func` is a C callback.
- *
- * A function object is JS object having the Function prototype that holds a
- * cfunction value in a hidden property.
- *
- * The function object will have a `prototype` property holding an object that
- * will be used as the prototype of objects created when calling the function
- * with the `new` operator.
- */
-v7_val_t v7_mk_function(struct v7 *, v7_cfunction_t *func);
-
-/*
- * Make f a JS function with specified prototype `proto`, so that the resulting
- * function is better suited for the usage as a constructor.
- */
-v7_val_t v7_mk_function_with_proto(struct v7 *v7, v7_cfunction_t *f,
-                                   v7_val_t proto);
-
-/*
- * Make a JS value that holds C/C++ callback pointer.
- *
- * CAUTION: This is a low-level function value. It's not a real object and
- * cannot hold user defined properties. You should use `v7_mk_function` unless
- * you know what you're doing.
- */
-v7_val_t v7_mk_cfunction(v7_cfunction_t *func);
-
-/*
- * Returns true if given value is callable (i.e. it's either a JS function or
- * cfunction)
- */
-int v7_is_callable(struct v7 *v7, v7_val_t v);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_FUNCTION_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/regexp_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === RegExp
- */
-
-#ifndef CS_V7_SRC_REGEXP_PUBLIC_H_
-#define CS_V7_SRC_REGEXP_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Make RegExp object.
- * `regex`, `regex_len` specify a pattern, `flags` and `flags_len` specify
- * flags. Both utf8 encoded. For example, `regex` is `(.+)`, `flags` is `gi`.
- * If `regex_len` is ~0, `regex` is assumed to be NUL-terminated and
- * `strlen(regex)` is used.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_mk_regexp(struct v7 *v7, const char *regex, size_t regex_len,
-                         const char *flags, size_t flags_len, v7_val_t *res);
-
-/* Returns true if given value is a JavaScript RegExp object*/
-int v7_is_regexp(struct v7 *v7, v7_val_t v);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_REGEXP_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/conversion_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Conversion
- */
-
-#ifndef CS_V7_SRC_CONVERSION_PUBLIC_H_
-#define CS_V7_SRC_CONVERSION_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/* Stringify mode, see `v7_stringify()` and `v7_stringify_throwing()` */
-enum v7_stringify_mode {
-  V7_STRINGIFY_DEFAULT,
-  V7_STRINGIFY_JSON,
-  V7_STRINGIFY_DEBUG,
-};
-
-/*
- * Generate string representation of the JavaScript value `val` into a buffer
- * `buf`, `len`. If `len` is too small to hold a generated string,
- * `v7_stringify()` allocates required memory. In that case, it is caller's
- * responsibility to free the allocated buffer. Generated string is guaranteed
- * to be 0-terminated.
- *
- * Available stringification modes are:
- *
- * - `V7_STRINGIFY_DEFAULT`:
- *   Convert JS value to string, using common JavaScript semantics:
- *   - If value is an object:
- *     - call `toString()`;
- *     - If `toString()` returned non-primitive value, call `valueOf()`;
- *     - If `valueOf()` returned non-primitive value, throw `TypeError`.
- *   - Now we have a primitive, and if it's not a string, then stringify it.
- *
- * - `V7_STRINGIFY_JSON`:
- *   Generate JSON output
- *
- * - `V7_STRINGIFY_DEBUG`:
- *   Mostly like JSON, but will not omit non-JSON objects like functions.
- *
- * Example code:
- *
- *     char buf[100], *p;
- *     p = v7_stringify(v7, obj, buf, sizeof(buf), V7_STRINGIFY_DEFAULT);
- *     printf("JSON string: [%s]\n", p);
- *     if (p != buf) {
- *       free(p);
- *     }
- */
-char *v7_stringify(struct v7 *v7, v7_val_t v, char *buf, size_t len,
-                   enum v7_stringify_mode mode);
-
-/*
- * Like `v7_stringify()`, but "returns" value through the `res` pointer
- * argument. `res` must not be `NULL`.
- *
- * Caller should check the error code returned, and if it's something other
- * than `V7_OK`, perform cleanup and return this code further.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_stringify_throwing(struct v7 *v7, v7_val_t v, char *buf,
-                                  size_t size, enum v7_stringify_mode mode,
-                                  char **res);
-
-/*
- * A shortcut for `v7_stringify()` with `V7_STRINGIFY_JSON`
- */
-#define v7_to_json(a, b, c, d) v7_stringify(a, b, c, d, V7_STRINGIFY_JSON)
-
-/* Returns true if given value evaluates to true, as in `if (v)` statement. */
-int v7_is_truthy(struct v7 *v7, v7_val_t v);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_CONVERSION_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/exec_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Execution of JavaScript code
- */
-
-#ifndef CS_V7_SRC_EXEC_PUBLIC_H_
-#define CS_V7_SRC_EXEC_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Execute JavaScript `js_code`. The result of evaluation is stored in
- * the `result` variable.
- *
- * Return:
- *
- *  - V7_OK on success. `result` contains the result of execution.
- *  - V7_SYNTAX_ERROR if `js_code` in not a valid code. `result` is undefined.
- *  - V7_EXEC_EXCEPTION if `js_code` threw an exception. `result` stores
- *    an exception object.
- *  - V7_AST_TOO_LARGE if `js_code` contains an AST segment longer than 16 bit.
- *    `result` is undefined. To avoid this error, build V7 with V7_LARGE_AST.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_exec(struct v7 *v7, const char *js_code, v7_val_t *result);
-
-/*
- * Options for `v7_exec_opt()`. To get default options, like `v7_exec()` uses,
- * just zero out this struct.
- */
-struct v7_exec_opts {
-  /* Filename, used for stack traces only */
-  const char *filename;
-
-  /*
-   * Object to be used as `this`. Note: when it is zeroed out, i.e. it's a
-   * number `0`, the `undefined` value is assumed. It means that it's
-   * impossible to actually use the number `0` as `this` object, but it makes
-   * little sense anyway.
-   */
-  v7_val_t this_obj;
-
-  /* Whether the given `js_code` should be interpreted as JSON, not JS code */
-  unsigned is_json : 1;
-};
-
-/*
- * Customizable version of `v7_exec()`: allows to specify various options, see
- * `struct v7_exec_opts`.
- */
-enum v7_err v7_exec_opt(struct v7 *v7, const char *js_code,
-                        const struct v7_exec_opts *opts, v7_val_t *res);
-
-/*
- * Same as `v7_exec()`, but loads source code from `path` file.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_exec_file(struct v7 *v7, const char *path, v7_val_t *result);
-
-/*
- * Parse `str` and store corresponding JavaScript object in `res` variable.
- * String `str` should be '\0'-terminated.
- * Return value and semantic is the same as for `v7_exec()`.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_parse_json(struct v7 *v7, const char *str, v7_val_t *res);
-
-/*
- * Same as `v7_parse_json()`, but loads JSON string from `path`.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_parse_json_file(struct v7 *v7, const char *path, v7_val_t *res);
-
-#if !defined(V7_NO_COMPILER)
-
-/*
- * Compile JavaScript code `js_code` into the byte code and write generated
- * byte code into opened file stream `fp`. If `generate_binary_output` is 0,
- * then generated byte code is in human-readable text format. Otherwise, it is
- * in the binary format, suitable for execution by V7 instance.
- * NOTE: `fp` must be a valid, opened, writable file stream.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_compile(const char *js_code, int generate_binary_output,
-                       int use_bcode, FILE *fp);
-
-#endif /* V7_NO_COMPILER */
-
-/*
- * Call function `func` with arguments `args`, using `this_obj` as `this`.
- * `args` should be an array containing arguments or `undefined`.
- *
- * `res` can be `NULL` if return value is not required.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
-                     v7_val_t args, v7_val_t *res);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_EXEC_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/exceptions_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Exceptions
- */
-
-#ifndef CS_V7_SRC_EXCEPTIONS_PUBLIC_H_
-#define CS_V7_SRC_EXCEPTIONS_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/* Throw an exception with an already existing value. */
-WARN_UNUSED_RESULT
-enum v7_err v7_throw(struct v7 *v7, v7_val_t v);
-
-/*
- * Throw an exception with given formatted message.
- *
- * Pass "Error" as typ for a generic error.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_throwf(struct v7 *v7, const char *typ, const char *err_fmt, ...);
-
-/*
- * Rethrow the currently thrown object. In fact, it just returns
- * V7_EXEC_EXCEPTION.
- */
-WARN_UNUSED_RESULT
-enum v7_err v7_rethrow(struct v7 *v7);
-
-/*
- * Returns the value that is being thrown at the moment, or `undefined` if
- * nothing is being thrown. If `is_thrown` is not `NULL`, it will be set
- * to either 0 or 1, depending on whether something is thrown at the moment.
- */
-v7_val_t v7_get_thrown_value(struct v7 *v7, unsigned char *is_thrown);
-
-/* Clears currently thrown value, if any. */
-void v7_clear_thrown_value(struct v7 *v7);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_EXCEPTIONS_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/gc_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Garbage Collector
- */
-
-#ifndef CS_V7_SRC_GC_PUBLIC_H_
-#define CS_V7_SRC_GC_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-#if V7_ENABLE__Memory__stats
-
-/* Heap metric id, see `v7_heap_stat()` */
-enum v7_heap_stat_what {
-  V7_HEAP_STAT_HEAP_SIZE,
-  V7_HEAP_STAT_HEAP_USED,
-  V7_HEAP_STAT_STRING_HEAP_RESERVED,
-  V7_HEAP_STAT_STRING_HEAP_USED,
-  V7_HEAP_STAT_OBJ_HEAP_MAX,
-  V7_HEAP_STAT_OBJ_HEAP_FREE,
-  V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE,
-  V7_HEAP_STAT_FUNC_HEAP_MAX,
-  V7_HEAP_STAT_FUNC_HEAP_FREE,
-  V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE,
-  V7_HEAP_STAT_PROP_HEAP_MAX,
-  V7_HEAP_STAT_PROP_HEAP_FREE,
-  V7_HEAP_STAT_PROP_HEAP_CELL_SIZE,
-  V7_HEAP_STAT_FUNC_AST_SIZE,
-  V7_HEAP_STAT_BCODE_OPS_SIZE,
-  V7_HEAP_STAT_BCODE_LIT_TOTAL_SIZE,
-  V7_HEAP_STAT_BCODE_LIT_DESER_SIZE,
-  V7_HEAP_STAT_FUNC_OWNED,
-  V7_HEAP_STAT_FUNC_OWNED_MAX
-};
-
-/* Returns a given heap statistics */
-int v7_heap_stat(struct v7 *v7, enum v7_heap_stat_what what);
-#endif
-
-/*
- * Perform garbage collection.
- * Pass true to full in order to reclaim unused heap back to the OS.
- */
-void v7_gc(struct v7 *v7, int full);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_GC_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/util_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === Utility functions
- */
-
-#ifndef CS_V7_SRC_UTIL_PUBLIC_H_
-#define CS_V7_SRC_UTIL_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/* Output a string representation of the value to stdout.
- * V7_STRINGIFY_DEBUG mode is used. */
-void v7_print(struct v7 *v7, v7_val_t v);
-
-/* Output a string representation of the value to stdout followed by a newline.
- * V7_STRINGIFY_DEBUG mode is used. */
-void v7_println(struct v7 *v7, v7_val_t v);
-
-/* Output a string representation of the value to a file.
- * V7_STRINGIFY_DEBUG mode is used. */
-void v7_fprint(FILE *f, struct v7 *v7, v7_val_t v);
-
-/* Output a string representation of the value to a file followed by a newline.
- * V7_STRINGIFY_DEBUG mode is used. */
-void v7_fprintln(FILE *f, struct v7 *v7, v7_val_t v);
-
-/* Output stack trace recorded in the exception `e` to file `f` */
-void v7_fprint_stack_trace(FILE *f, struct v7 *v7, v7_val_t e);
-
-/* Output error object message and possibly stack trace to f */
-void v7_print_error(FILE *f, struct v7 *v7, const char *ctx, v7_val_t e);
-
-#if V7_ENABLE__Proxy
-
-struct v7_property;
-
-/*
- * C callback, analogue of JS callback `getOwnPropertyDescriptor()`.
- * Callbacks of this type are used for C API only, see `m7_mk_proxy()`.
- *
- * `name` is the name of the property, and the function should fill `attrs` and
- * `value` with the property data. Before this callback is called, `attrs` is
- * set to 0, and `value` is `V7_UNDEFINED`.
- *
- * It should return non-zero if the property should be considered existing, or
- * zero otherwise.
- *
- * You can inspect the property attributes with the `V7_PROP_ATTR_IS_*` macros.
- */
-typedef int(v7_get_own_prop_desc_cb_t)(struct v7 *v7, v7_val_t target,
-                                       v7_val_t name, v7_prop_attr_t *attrs,
-                                       v7_val_t *value);
-
-/* Handler for `v7_mk_proxy()`; each item is a cfunction */
-typedef struct {
-  v7_cfunction_t *get;
-  v7_cfunction_t *set;
-  v7_cfunction_t *own_keys;
-  v7_get_own_prop_desc_cb_t *get_own_prop_desc;
-} v7_proxy_hnd_t;
-
-/*
- * Create a Proxy object, see:
- * https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy
- *
- * Only two traps are implemented so far: `get()` and `set()`. Note that
- * `Object.defineProperty()` bypasses the `set()` trap.
- *
- * If `target` is not an object, the empty object will be used, so it's safe
- * to pass `V7_UNDEFINED` as `target`.
- */
-v7_val_t v7_mk_proxy(struct v7 *v7, v7_val_t target,
-                     const v7_proxy_hnd_t *handler);
-
-#endif /* V7_ENABLE__Proxy */
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_UTIL_PUBLIC_H_ */
-#ifdef V7_MODULE_LINES
-#line 1 "v7/src/main_public.h"
-#endif
-/*
- * Copyright (c) 2014 Cesanta Software Limited
- * All rights reserved
- */
-
-/*
- * === v7 main()
- */
-
-#ifndef CS_V7_SRC_MAIN_PUBLIC_H_
-#define CS_V7_SRC_MAIN_PUBLIC_H_
-
-/* Amalgamated: #include "v7/src/core_public.h" */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * V7 executable main function.
- *
- * There are various callbacks available:
- *
- * `pre_freeze_init()` and `pre_init()` are optional intialization functions,
- * aimed to export any extra functionality into vanilla v7 engine. They are
- * called after v7 initialization, before executing given files or inline
- * expressions. `pre_freeze_init()` is called before "freezing" v7 state;
- * whereas `pre_init` called afterwards.
- *
- * `post_init()`, if provided, is called after executing files and expressions,
- * before destroying v7 instance and exiting.
- */
-int v7_main(int argc, char *argv[], void (*pre_freeze_init)(struct v7 *),
-            void (*pre_init)(struct v7 *), void (*post_init)(struct v7 *));
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-#endif /* CS_V7_SRC_MAIN_PUBLIC_H_ */
-#endif /* V7_EXPORT_INTERNAL_HEADERS */