text:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cerrno>
#include <string>
#include <unistd.h>
#include <signal.h>
#include <map>
#include <sys/socket.h>
#include <fcntl.h>
#include <readline/readline.h>
#include <readline/history.h>

#include <rfb/keysym.h>
#include "emulator.h"

#include "z80emu.h"
#include "8x16.h"
#include "readhex.h"

const bool debug = false;

bool Z80_INTERRUPT_FETCH = false;
unsigned short Z80_INTERRUPT_FETCH_DATA;

std::vector<board_base*> boards;

const int font_scale = 2;

uint32_t rfb_pixel(int  r, int g, int b)
{
    return (r << 16) | (g << 8) | (b);
}

void draw_glyph(rfbScreenInfoPtr server, int x, int y, char c)
{
    int    gx, gy;
    unsigned char    *glyph;

    glyph = fontbits + fontheight * c;
    for(gx = 0; gx < fontwidth + 1; gx++)
        for(gy = 0; gy < fontheight + 1; gy++) {
            int v;
            if(gx < fontwidth && gy < fontheight && (glyph[gy + gx / 8] & (1 << (7 - (gx % 8)))))
                v = 32;
            else
                v = 224;
            for(int j = 0; j < font_scale; j++)
                for(int i = 0; i < font_scale; i++) {
                int col = x + i + gx * font_scale;
                int row = y + j + gy * font_scale;
                rfbDrawPixel(server, col, row, rfb_pixel(v, v, v));
            }
        }
        rfbMarkRectAsModified(server, x, y, x + fontwidth * 2 + 1, y + fontheight * 2 + 1);

}

bool quit = false;

// -- GENERATED BY KEYS.PY

std::map<int, unsigned char> rfb_keys_to_AT_keycodes;

void populate_keycode_map()
{

    rfb_keys_to_AT_keycodes[XK_Shift_L] = 0x12;
    rfb_keys_to_AT_keycodes[XK_Shift_R] = 0x59;
    rfb_keys_to_AT_keycodes[XK_Tab] = 0x0D;
    rfb_keys_to_AT_keycodes[XK_grave] = 0x0E;
    rfb_keys_to_AT_keycodes[XK_asciitilde] = 0x0E;
    rfb_keys_to_AT_keycodes[XK_q] = 0x15;
    rfb_keys_to_AT_keycodes[XK_Q] = 0x15;
    rfb_keys_to_AT_keycodes[XK_1] = 0x16;
    rfb_keys_to_AT_keycodes[XK_exclam] = 0x16;
    rfb_keys_to_AT_keycodes[XK_z] = 0x1A;
    rfb_keys_to_AT_keycodes[XK_Z] = 0x1A;
    rfb_keys_to_AT_keycodes[XK_s] = 0x1B;
    rfb_keys_to_AT_keycodes[XK_S] = 0x1B;
    rfb_keys_to_AT_keycodes[XK_a] = 0x1C;
    rfb_keys_to_AT_keycodes[XK_A] = 0x1C;
    rfb_keys_to_AT_keycodes[XK_w] = 0x1D;
    rfb_keys_to_AT_keycodes[XK_W] = 0x1D;
    rfb_keys_to_AT_keycodes[XK_2] = 0x1E;
    rfb_keys_to_AT_keycodes[XK_at] = 0x1E;
    rfb_keys_to_AT_keycodes[XK_c] = 0x21;
    rfb_keys_to_AT_keycodes[XK_C] = 0x21;
    rfb_keys_to_AT_keycodes[XK_x] = 0x22;
    rfb_keys_to_AT_keycodes[XK_X] = 0x22;
    rfb_keys_to_AT_keycodes[XK_d] = 0x23;
    rfb_keys_to_AT_keycodes[XK_D] = 0x23;
    rfb_keys_to_AT_keycodes[XK_e] = 0x24;
    rfb_keys_to_AT_keycodes[XK_E] = 0x24;
    rfb_keys_to_AT_keycodes[XK_4] = 0x25;
    rfb_keys_to_AT_keycodes[XK_dollar] = 0x25;
    rfb_keys_to_AT_keycodes[XK_3] = 0x26;
    rfb_keys_to_AT_keycodes[XK_numbersign] = 0x26;
    rfb_keys_to_AT_keycodes[XK_v] = 0x2A;
    rfb_keys_to_AT_keycodes[XK_V] = 0x2A;
    rfb_keys_to_AT_keycodes[XK_f] = 0x2B;
    rfb_keys_to_AT_keycodes[XK_F] = 0x2B;
    rfb_keys_to_AT_keycodes[XK_t] = 0x2C;
    rfb_keys_to_AT_keycodes[XK_T] = 0x2C;
    rfb_keys_to_AT_keycodes[XK_r] = 0x2D;
    rfb_keys_to_AT_keycodes[XK_R] = 0x2D;
    rfb_keys_to_AT_keycodes[XK_5] = 0x2E;
    rfb_keys_to_AT_keycodes[XK_percent] = 0x2E;
    rfb_keys_to_AT_keycodes[XK_n] = 0x31;
    rfb_keys_to_AT_keycodes[XK_N] = 0x31;
    rfb_keys_to_AT_keycodes[XK_b] = 0x32;
    rfb_keys_to_AT_keycodes[XK_B] = 0x32;
    rfb_keys_to_AT_keycodes[XK_h] = 0x33;
    rfb_keys_to_AT_keycodes[XK_H] = 0x33;
    rfb_keys_to_AT_keycodes[XK_g] = 0x34;
    rfb_keys_to_AT_keycodes[XK_G] = 0x34;
    rfb_keys_to_AT_keycodes[XK_y] = 0x35;
    rfb_keys_to_AT_keycodes[XK_Y] = 0x35;
    rfb_keys_to_AT_keycodes[XK_6] = 0x36;
    rfb_keys_to_AT_keycodes[XK_asciicircum] = 0x36;
    rfb_keys_to_AT_keycodes[XK_m] = 0x3A;
    rfb_keys_to_AT_keycodes[XK_M] = 0x3A;
    rfb_keys_to_AT_keycodes[XK_j] = 0x3B;
    rfb_keys_to_AT_keycodes[XK_J] = 0x3B;
    rfb_keys_to_AT_keycodes[XK_u] = 0x3C;
    rfb_keys_to_AT_keycodes[XK_U] = 0x3C;
    rfb_keys_to_AT_keycodes[XK_7] = 0x3D;
    rfb_keys_to_AT_keycodes[XK_ampersand] = 0x3D;
    rfb_keys_to_AT_keycodes[XK_8] = 0x3E;
    rfb_keys_to_AT_keycodes[XK_asterisk] = 0x3E;
    rfb_keys_to_AT_keycodes[XK_comma] = 0x41;
    rfb_keys_to_AT_keycodes[XK_less] = 0x41;
    rfb_keys_to_AT_keycodes[XK_k] = 0x42;
    rfb_keys_to_AT_keycodes[XK_K] = 0x42;
    rfb_keys_to_AT_keycodes[XK_i] = 0x43;
    rfb_keys_to_AT_keycodes[XK_I] = 0x43;
    rfb_keys_to_AT_keycodes[XK_o] = 0x44;
    rfb_keys_to_AT_keycodes[XK_O] = 0x44;
    rfb_keys_to_AT_keycodes[XK_0] = 0x45;
    rfb_keys_to_AT_keycodes[XK_parenright] = 0x45;
    rfb_keys_to_AT_keycodes[XK_9] = 0x46;
    rfb_keys_to_AT_keycodes[XK_parenleft] = 0x46;
    rfb_keys_to_AT_keycodes[XK_period] = 0x49;
    rfb_keys_to_AT_keycodes[XK_greater] = 0x49;
    rfb_keys_to_AT_keycodes[XK_slash] = 0x4A;
    rfb_keys_to_AT_keycodes[XK_question] = 0x4A;
    rfb_keys_to_AT_keycodes[XK_l] = 0x4B;
    rfb_keys_to_AT_keycodes[XK_L] = 0x4B;
    rfb_keys_to_AT_keycodes[XK_semicolon] = 0x4C;
    rfb_keys_to_AT_keycodes[XK_colon] = 0x4C;
    rfb_keys_to_AT_keycodes[XK_p] = 0x4D;
    rfb_keys_to_AT_keycodes[XK_P] = 0x4D;
    rfb_keys_to_AT_keycodes[XK_minus] = 0x4E;
    rfb_keys_to_AT_keycodes[XK_underscore] = 0x4E;
    rfb_keys_to_AT_keycodes[XK_apostrophe] = 0x52;
    rfb_keys_to_AT_keycodes[XK_quotedbl] = 0x52;
    rfb_keys_to_AT_keycodes[XK_bracketleft] = 0x54;
    rfb_keys_to_AT_keycodes[XK_braceleft] = 0x54;
    rfb_keys_to_AT_keycodes[XK_equal] = 0x55;
    rfb_keys_to_AT_keycodes[XK_plus] = 0x55;
    rfb_keys_to_AT_keycodes[XK_Return] = 0x5A;
    rfb_keys_to_AT_keycodes[XK_bracketright] = 0x5B;
    rfb_keys_to_AT_keycodes[XK_braceright] = 0x5B;
    rfb_keys_to_AT_keycodes[XK_backslash] = 0x5D;
    rfb_keys_to_AT_keycodes[XK_bar] = 0x5D;
    rfb_keys_to_AT_keycodes[XK_BackSpace] = 0x66;
    rfb_keys_to_AT_keycodes[XK_Escape] = 0x76;
}
// -- END GENERATED BY KEYS.PY

struct socket_connection
{
    int listen_socket;
    int data_socket;
    bool telnet_char_mode;

    socket_connection(bool telnet_char_mode_) :
        listen_socket(-1),
        data_socket(-1),
        telnet_char_mode(telnet_char_mode_)
    {}

    bool listen(int port)
    {
        listen_socket = socket(PF_INET, SOCK_STREAM, 0);
        if(listen_socket < 0) {
            perror("socket");
            return false;
        }
        fcntl(listen_socket, F_SETFL, O_NONBLOCK);

        int reuse = 1;
        if(setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
            perror("setsockopt");
            return false;
        }

        struct in_addr addr;
        struct sockaddr_in socket_addr;
        socket_addr.sin_family = AF_INET; // AF_UNIX;
        socket_addr.sin_port = htons(port);
        addr.s_addr = 0;
        socket_addr.sin_addr = addr;

        if(bind(listen_socket, (struct sockaddr*)&socket_addr, sizeof(socket_addr)) != 0) {
            perror("bind");
            return false;
        }

        if(::listen(listen_socket, 1) != 0) {
            perror("listen");
            return false;
        }
        data_socket = -1;
        return true;
    }

    bool is_connected()
    {
        return data_socket > -1;
    }

    ssize_t send(unsigned char *buffer, size_t size)
    {
        if(data_socket > -1)
            return ::send(data_socket, buffer, size, 0);
        else
            return -1;
    }

    bool is_data_ready()
    {
        if(data_socket > -1) {
            fd_set fds;
            FD_ZERO(&fds);
            FD_SET(data_socket, &fds);

            struct timeval timeout;
            timeout.tv_sec = 0;
            timeout.tv_usec = 1;
            int result;
            if((result = select(data_socket + 1, &fds, NULL, NULL, &timeout)) == -1) {
                if(errno == EINTR)
                    return false;
                perror("select");
                exit(EXIT_FAILURE);
            }

            if(FD_ISSET(data_socket, &fds)) {
                return true;
            }
            return false;
        }
        return false;
    }

    ssize_t receive(unsigned char *buffer, size_t size)
    {
        if(data_socket > -1) {
            fd_set fds;
            FD_ZERO(&fds);
            FD_SET(data_socket, &fds);

            struct timeval timeout;
            timeout.tv_sec = 0;
            timeout.tv_usec = 1;
            int result;
            if((result = select(data_socket + 1, &fds, NULL, NULL, &timeout)) == -1) {
                if(errno == EINTR)
                    return 0;
                perror("select");
                exit(EXIT_FAILURE);
            }

            if(FD_ISSET(data_socket, &fds)) {
                ssize_t count;
                count = recv(data_socket, buffer, size, 0);
                if(count < 0) {
                    perror("recv");
                    exit(EXIT_FAILURE);
                } else if(count == 0) {
                    close(data_socket);
                    data_socket = -1;
                }
                return count;
            }
            return 0;
        }
        return 0;
    }

    bool cycle()
    {
        if(data_socket == -1) {
            fd_set fds;
            FD_ZERO(&fds);
            FD_SET(listen_socket, &fds);

            struct timeval timeout;
            timeout.tv_sec = 0;
            timeout.tv_usec = 1;
            int result;
            if((result = select(listen_socket + 1, &fds, NULL, NULL, &timeout)) == -1) {
                if(errno == EINTR)
                    return true;
                perror("select");
                return false;
            }

            if(FD_ISSET(listen_socket, &fds)) {
                struct sockaddr_in them;
                socklen_t addrlen = sizeof(them);
                data_socket = accept(listen_socket, (struct sockaddr *)&them, &addrlen);
                if(data_socket < 0)
                {
                    perror("accept");
                    return false;
                }
                if(false && telnet_char_mode) {
                    if(write(data_socket ,"\377\375\042\377\373\001", 6) != 6) {
                        printf("Telnet character mode was requested but sending the sequence failed\n");
                        close(data_socket);
                        data_socket = -1;
                        return false;
                    }
                    char c;
                    int i = 65;
                    while(i > 0) {
                        ssize_t wasread;
                        if((wasread = read(data_socket, &c, 1)) == 1) {
                            // printf("%d\n", i);
                            i--;
                        } else if(wasread < 0) {
                            // printf("Telnet character mode was requested but client socket read failed\n");
                            // close(data_socket);
                            // data_socket = -1;
                            // return false;
                        }
                    }
                }

            }
        }
        return true;
    }
};

struct FakeCPMboard : board_base
{
    bool debug;
    static const int CONOUT_OUT = 128; // write console
    static const int CONIN_IN = 128; // read console, NON-BLOCKING!! - loop in BIOS
    static const int CONST_IN = 129; // console read ready ? 0xff : 00
    static const int SELDSK_OUT = 130;
    static const int DISKSTAT_IN = 130; // okay ? 0xff : 0
    static const int SELTRK_L_OUT = 131;
    static const int SELTRK_H_OUT = 132;
    static const int SELSEC_L_OUT = 133;
    static const int SELSEC_H_OUT = 134;
    static const int SETDMA_L_OUT = 135;
    static const int SETDMA_H_OUT = 136;
    static const int READ_SECTOR_IN = 137; // READ sector - returns 0 or error code
    static const int WRITE_SECTOR_IN = 138; // WRITE sector - returns 0 or error code

    static const int sector_size = 128;
    static const int sectors_per_track = 64;
    static const int tracks_per_disk = 1024;
    static const int disk_size = tracks_per_disk * sectors_per_track * sector_size;
    int disk;
    int track;
    int sector;
    int dma;
    FILE *disks[4];

    FakeCPMboard(char *args) :
        disk(0),
        track(0),
        sector(0),
        dma(0),
        conn(true)
    {
        debug = true;
        char **ap, *disknames[10];

        for (ap = disknames; (*ap = strsep(&args, ",")) != NULL;)
            if (**ap != '\0')
                if (++ap >= &disknames[10])
                    break;
        int diskcount = ap - disknames;

        for(int i = 0; i < 4; i++) {
            if(i < diskcount) {
                disks[i] = fopen(disknames[i], "r+");
                if(disks[i] == NULL) {
                    fprintf(stderr, "couldn't open %s as a CPM disk.  To create it as a formatted 8MB CP/M disk, try \"python -c 'import sys; sys.stdout.write(\"\\xe5\"*(8192*1024));' > %s\"\n", disknames[i], disknames[i]);
                    exit(EXIT_FAILURE);
                }

                fseek(disks[i], 0, SEEK_END);

                if(ftell(disks[i]) != disk_size) {
                    fprintf(stderr, "%s is %lu bytes, and not 8MB. To create it as a formatted 8MB CP/M disk, try \"python -c 'import sys; sys.stdout.write(\"\\xe5\"*(8192*1024));' > %s\"\n", disknames[i], ftell(disks[i]), disknames[i]);
                    exit(EXIT_FAILURE);
                }
            } else
                disks[i] = NULL;
        }
    }

    std::vector<unsigned char> queued;
    const int server_port = 6607;
    struct socket_connection conn;
    virtual bool io_write(int addr, unsigned char data)
    {
        if(!conn.cycle()) {
            fprintf(stderr, "Unexpected failure polling for emulated serial port connection on port %d\n", server_port);
            exit(EXIT_FAILURE);
        }

        switch(addr) {
            case CONOUT_OUT:
                if(!conn.is_connected()) {
                    queued.push_back(data);
                } else {
                    if(queued.size() > 0) {
                        for(int i = 0; i < queued.size(); i++)
                            conn.send(&queued[i], 1);
                        queued.clear();
                    }
                    conn.send(&data, 1);
                }
                return true;
                break;
            case SELDSK_OUT:
                disk = data;
                if(debug)printf("Disk now %d\n", disk);
                return true;
                break;
            case SELTRK_L_OUT:
                track = (track & 0xFF00) | (data << 0);
                if(debug)printf("Track now %d\n", track);
                return true;
                break;
            case SELTRK_H_OUT:
                track = (track & 0x00FF) | (data << 8);
                if(debug)printf("Track now %d\n", track);
                return true;
                break;
            case SELSEC_L_OUT:
                sector = (sector & 0xFF00) | (data << 0);
                if(debug)printf("Sector now %d\n", sector);
                return true;
                break;
            case SELSEC_H_OUT:
                sector = (sector & 0x00FF) | (data << 8);
                if(debug)printf("Sector now %d\n", sector);
                return true;
                break;
            case SETDMA_L_OUT:
                dma = (dma & 0xFF00) | (data << 0);
                if(debug)printf("DMA address now %d\n", dma);
                return true;
                break;
            case SETDMA_H_OUT:
                dma = (dma & 0x00FF) | (data << 8);
                if(debug)printf("DMA address now %d\n", dma);
                return true;
                break;
        }
        return false;
    }
    virtual bool io_read(int addr, unsigned char &data)
    {
        if(!conn.cycle()) {
            if(debug)fprintf(stderr, "Unexpected failure polling for emulated serial port connection on port %d\n", server_port);
            exit(EXIT_FAILURE);
        }

        static unsigned char buffer[128];
        switch(addr) {
            case CONIN_IN:
                if(conn.receive(&data, 1) != 1) {
                    data = 0x00;
                }
		if(data == 10)
		    data = 13; // XXX turn newline into carriage return
                return true;
                break;
            case CONST_IN:
                data = conn.is_data_ready() ? 0xFF : 0x00;
                return true;
                break;
            case DISKSTAT_IN: // READ sector - returns 0 or error code
                data = (disks[disk] != NULL) ? 0xFF : 0x00;
                return true;
                break;
            case READ_SECTOR_IN: // READ sector - returns 0 or error code
                if(disks[disk] != NULL) {
                    printf("Read track %d, sector %d (%d) to %d\n", track, sector, (track * sectors_per_track + sector) * sector_size, dma);
                    long location = (track * sectors_per_track + sector) * sector_size;
                    if(location >= disk_size - sector_size) {
                        fprintf(stderr, "read past end of disk ignored!!\n");
                        data = 0xff;
                        return true;
                    }
                    fseek(disks[disk], location, SEEK_SET);
                    fread(buffer, sizeof(buffer), 1, disks[disk]);
                    for(int i = 0; i < sector_size; i++)
                        Z80_WRITE_BYTE(dma + i, buffer[i]);
                    data = 0x00;
                } else
                    data = 0xff;
                return true;
                break;
            case WRITE_SECTOR_IN: // WRITE sector - returns 0 or error code
                if(disks[disk] != NULL) {
                    printf("Write track %d, sector %d (%d) from %d\n", track, sector, (track * sectors_per_track + sector) * sector_size, dma);
                    long location = (track * sectors_per_track + sector) * sector_size;
                    if(location >= disk_size - sector_size) {
                        fprintf(stderr, "write past end of disk ignored!!\n");
                        data = 0xff;
                        return true;
                    }
                    fseek(disks[disk], location, SEEK_SET);
                    for(int i = 0; i < sector_size; i++)
                        Z80_READ_BYTE(dma + i, buffer[i]);
                    fwrite(buffer, sizeof(buffer), 1, disks[disk]);
                    data = 0x00;
                } else
                    data = 0xff;
                return true;
                break;
        }
        return false;
    }
    virtual void init(void)
    {
        if(!conn.listen(server_port)) {
            fprintf(stderr, "couldn't start listening on port %d for serial port emulation\n", server_port);
            exit(EXIT_FAILURE);
        }
        printf("listening on port 6607 for Fake CPM HW console emulation\n");
    }
    virtual void idle(void)
    {
        if(conn.is_connected() && queued.size() > 0) {
            for(int i = 0; i < queued.size(); i++)
                conn.send(&queued[i], 1);
            queued.clear();
        }
    }
    virtual void pause(void) {};
    virtual void resume(void) {};
};

struct IOboard : board_base
{
    const int PIC_port = 0x04;

    // Old command bytes from PIC to CPU
    const int CMD_SER_old = 0x01;
    const int CMD_KBD_old = 0x02;
    const int CMD_TIM_old = 0x03;

    // New command bytes from PIC to CPU,
    // can be ORd with a length in lower nybble
    const int CMD_SER = 0x10;
    const int CMD_KBD = 0x20;
    const int CMD_TIM = 0x30;
    const int CMD_SPI = 0x40;

    const int PIC_SER_SEND = 0x10;  // send bytes to serial, lower bits are count, bytes follow
    const int PIC_KBD_SEND = 0x20;  // placeholder for send-to-keyboard
    const int PIC_CFG_SEND = 0x30;  // placeholder for send PIC configuration
    const int PIC_SPI_WRITE = 0x40; // write bytes to SPI, lower bits and next byte are count, bytes follow
    const int PIC_SPI_READ = 0x50;  // read bytes from SPI, lower bits and next byte are count
    const int PIC_SPI_CS = 0x60;    // lower 4 bits are the chip-select mask

    std::vector<unsigned char> queue;
    double last_timer_interrupt;
    const double timer_frequency_hertz = 10;
    const double timer_interval_seconds = 1.0 / timer_frequency_hertz;
    bool paused;

    enum { NONE, PENDING, SIGNALED } interrupt_status;

    bool use_old_PIC_commands; // Use the old SER, TIM, and KBD command bytes
    bool give_timer_interrupts; // Use the old SER, TIM, and KBD command bytes

    IOboard(bool use_old_PIC_commands_, bool give_timer_interrupts_) :
        paused(false),
        interrupt_status(NONE),
        use_old_PIC_commands(use_old_PIC_commands_),
        give_timer_interrupts(give_timer_interrupts_),
        conn(false)
    { }

    virtual bool io_read(int addr, unsigned char &data)
    {
        if(addr == PIC_port) {
            bool handled = false;
            if(queue.size() > 0) {
                data = queue[0];
                queue.erase(queue.begin());
                handled = true;
            }
            if(queue.size() > 0)
                interrupt_status = PENDING;
            else {
                interrupt_status = NONE;
            }
            return handled;
        }
        return false;
    }

    virtual bool board_get_interrupt(int& irq)
    {
        if(interrupt_status == PENDING) {
            irq = 0;
            interrupt_status = SIGNALED;
            return true;
        }
        return false;
    }

    void enqueue(unsigned char b)
    {
        queue.push_back(b);
        if(interrupt_status == NONE)
            interrupt_status = PENDING;
    }

    void enqueue_AT_keycode(unsigned char key)
    {
        enqueue(use_old_PIC_commands ? CMD_KBD_old : CMD_KBD);
        enqueue(key);
    }

    virtual bool handle_rfb_key(rfbBool down, rfbKeySym key, rfbClientPtr cl)
    {
        if(down) {
            if(key==XK_Escape) {
                rfbCloseClient(cl);
                quit = true;
            } else if(key==XK_F12) {
                /* close down server, disconnecting clients */
                rfbShutdownServer(cl->screen,TRUE);
                quit = true;
            } else if(key==XK_F11) {
                /* close down server, but wait for all clients to disconnect */
                rfbShutdownServer(cl->screen,FALSE);
                quit = true;
            } else if(key==XK_F11) {
                /* close down server, but wait for all clients to disconnect */
                rfbShutdownServer(cl->screen,FALSE);
                quit = true;
            } else {
                auto found = rfb_keys_to_AT_keycodes.find(key);
                if(found != rfb_keys_to_AT_keycodes.end()){
                    unsigned char kc = found->second;
                    enqueue_AT_keycode(kc);
                }
            }
        } else {
            auto found = rfb_keys_to_AT_keycodes.find(key);
            if(found != rfb_keys_to_AT_keycodes.end()){
                unsigned char kc = found->second;
                enqueue_AT_keycode(0xF0);
                enqueue_AT_keycode(kc);
            }
        }
        return true;
    }
    const int server_port = 6606;
    socket_connection conn;
    void init(void)
    {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        last_timer_interrupt = tv.tv_sec + tv.tv_usec / 1000000.0;

        if(!conn.listen(server_port)) {
            fprintf(stderr, "couldn't start listening on port %d for serial port emulation\n", server_port);
            exit(EXIT_FAILURE);
        }
        printf("listening on port 6606 for serial port emulation\n");
    }

    double pause_time;

    void pause()
    {
        paused = true;
        struct timeval tv;
        gettimeofday(&tv, NULL);
        pause_time = tv.tv_sec + tv.tv_usec / 1000000.0;
    }

    void resume()
    {
        paused = false;
        struct timeval tv;
        gettimeofday(&tv, NULL);
        double now = tv.tv_sec + tv.tv_usec / 1000000.0;
        last_timer_interrupt += (now - pause_time);
    }

    void idle()
    {
        if(!paused) {
            if(give_timer_interrupts) {
                struct timeval tv;
                gettimeofday(&tv, NULL);
                double current_time = tv.tv_sec + tv.tv_usec / 1000000.0;

                while((current_time - last_timer_interrupt) > timer_interval_seconds) {
                    enqueue(use_old_PIC_commands ? CMD_TIM_old : CMD_TIM);
                    last_timer_interrupt += timer_interval_seconds;
                }
            }
        }

        if(conn.is_connected()) {
            static unsigned char buffer[128];
            ssize_t count;
            count = conn.receive(buffer, sizeof(buffer));
            for(int i = 0; i < count; i++) {
                enqueue(use_old_PIC_commands ? CMD_SER_old : CMD_SER);
                enqueue(buffer[i]);
            }
        }
        if(!conn.cycle()) {
            fprintf(stderr, "Unexpected failure polling for emulated serial port connection on port %d\n", server_port);
            exit(EXIT_FAILURE);
        }

    }
};

struct PIC8259board : board_base
{
    const int PORT0 = 0x00;
    const int PORT1 = 0x01;
    virtual bool io_write(int addr, unsigned char data)
    {
        if(addr == PORT0) {
            return true;
        }
        if(addr == PORT1) {
            return true;
        }
        return false;
    }
};

struct MEMORYboard : board_base
{
    unsigned char rom_bytes[16384];
    unsigned char ram_bytes[65536];
    bool loram;
    MEMORYboard(unsigned char rom[16384]) :
        loram(false)
    {
        memcpy(rom_bytes, rom, sizeof(rom_bytes));
    }
    virtual bool memory_read(int addr, unsigned char &data)
    {
        if(!loram && addr >= 0 && addr < sizeof(rom_bytes)) {
            data = rom_bytes[addr];
            if(debug) printf("read 0x%04X -> 0x%02X from ROM\n", addr, data);
            return true;
        }
        if(addr >= 0 && addr < sizeof(ram_bytes)) {
            data = ram_bytes[addr];
            if(debug) printf("read 0x%04X -> 0x%02X from RAM\n", addr, data);
            return true;
        }
        return false;
    }
    virtual bool memory_write(int addr, unsigned char data)
    {
        if(!loram && addr < sizeof(rom_bytes))
            return false;
        if(addr >= 0 && addr < sizeof(ram_bytes)) {
            ram_bytes[addr] = data;
            if(debug) printf("wrote 0x%02X to RAM 0x%04X\n", data, addr);
            return true;
        }
        return false;
    }
    virtual bool io_write(int addr, unsigned char data)
    {
        if(addr == 0x8) {
            loram = false;
            return true;
        }
        if(addr == 0x9) {
            loram = true;
            return true;
        }
        return false;
    }
};

struct VIDEOboard : board_base
{
    int video_board_width = 176;
    int video_board_height = 262;
    int video_rfb_scale_x = 3;
    int video_rfb_scale_y = 2;

    enum video_mode {
        NORMAL,
        DOUBLE,
        HALFMAX,
        MAX,
    };

    unsigned char fb_bytes[16384];
    int base_addr;

    rfbScreenInfoPtr rfb_server;
    int rfb_offset_x, rfb_offset_y;

    bool get_rfb_requirements(int& w, int& h)
    {
        w = video_board_width * video_rfb_scale_x;
        h = video_board_height * video_rfb_scale_y;
        return true;
    }
    void set_rfb(rfbScreenInfoPtr server, int offset_x, int offset_y)
    {
        rfb_server = server;
        rfb_offset_x = offset_x;
        rfb_offset_y = offset_y;
    }

    VIDEOboard(video_mode mode)
    {
        video_board_height = 262;
        video_rfb_scale_y = 2;

        switch(mode) {
            case NORMAL: {
                video_board_width = 176;
                video_rfb_scale_x = 3;
                break;
            };
            case DOUBLE: {
                video_board_width = 352;
                video_rfb_scale_x = 2;
                break;
            };
            case HALFMAX: {
                video_board_width = 248;
                video_rfb_scale_x = 2;
                break;
            };
            case MAX: {
                video_board_width = 496;
                video_rfb_scale_x = 1;
                break;
            };
        }

        base_addr = 0x4000;
        memset(fb_bytes, 0, sizeof(fb_bytes));
    }
    void init(void)
    {
        // make some nice RAM noise
        for(int i = 0 ; i < sizeof(fb_bytes); i++)
            memory_write(base_addr + i, random());
    }
    virtual bool memory_read(int addr, unsigned char &data)
    {
        if(addr >= base_addr && addr < base_addr + sizeof(fb_bytes)) {
            data = fb_bytes[addr - base_addr];
            if(debug) printf("read 0x%04X -> 0x%02X from VIDEO\n", addr, data);
            return true;
        }
        return false;
    }

    void set_video_pixel_in_rfb(int video_x, int video_y, bool set)
    {
        int rfb_x = video_x * video_rfb_scale_x + rfb_offset_x;
        int rfb_y = video_y * video_rfb_scale_y + rfb_offset_y;
        int v = set ? 255 : 0;

        for(int j = 0; j < video_rfb_scale_y; j++)
            for(int i = 0; i < video_rfb_scale_x; i++) {
                rfbDrawPixel(rfb_server, rfb_x + i, rfb_y + j, rfb_pixel(v, v, v));
            }
    }

    virtual bool memory_write(int addr, unsigned char data)
    {
        if(addr >= base_addr && addr < base_addr + sizeof(fb_bytes)) {
            fb_bytes[addr - base_addr] = data;
            if(debug) printf("wrote 0x%02X to VIDEO 0x%04X\n", data, addr);

            int pixel_start = (addr - base_addr) * 8;
            int pixel_row = pixel_start / video_board_width;
            if(pixel_row < video_board_height) {
                int pixel_column_start = pixel_start - (pixel_row * video_board_width);
                for(int i = 0; i < 8; i++) {
                    set_video_pixel_in_rfb(pixel_column_start + i, pixel_row, data & (0x80 >> i));
                }
            }

            return true;
        }
        return false;
    }
};

const int LCLEAR = 0x01; // LCD clear instruction
const int LRESET = 0x38; // LCD reset to normal instruction
const int LHALF1 = 0x80; // LCD move cursor to row 0
const int LHALF2 = 0xc0; // LCD move cursor to row 1

struct LCDboard : board_base
{
    const int LCDINST = 0x2; //  LCD instruction I/O port
    const int LCDDATA = 0x3; // LCD data I/O port
    const bool use_special_alice2_clear = true;

    enum lcd_model {
        LCD_1x16,
        LCD_2x16,
        LCD_4x40,
    };

    static const int lcd_max_rows = 4;
    static const int lcd_max_columns = 40;

    unsigned char lcd[lcd_max_rows * lcd_max_columns];
    int cursor;
    rfbScreenInfoPtr rfb_server;

    int lcd_rows;
    int lcd_columns;

    int rfb_offset_x, rfb_offset_y;

    bool get_rfb_requirements(int& w, int& h)
    {
        w = lcd_columns * (fontwidth + 1) * font_scale;
        h = (fontheight + 1) * lcd_rows * font_scale;
        return true;
    }
    void set_rfb(rfbScreenInfoPtr server, int offset_x, int offset_y)
    {
        rfb_server = server;
        rfb_offset_x = offset_x;
        rfb_offset_y = offset_y;
    }

    LCDboard(lcd_model model)
    {
        cursor = 0;

        switch(model) {
            case LCD_1x16: {
                lcd_rows = 1;
                lcd_columns = 16;
                break;
            };
            case LCD_2x16: {
                lcd_rows = 2;
                lcd_columns = 16;
                break;
            };
            case LCD_4x40: {
                lcd_rows = 4;
                lcd_columns = 40;
                break;
            };
        }

        memset(lcd, ' ', sizeof(lcd));
    }

    void init(void)
    {
        for(int i = 0; i < lcd_rows * lcd_columns; i++)
            draw_lcd_character(i);
    }

    virtual bool io_write(int addr, unsigned char data)
    {
        if(addr == LCDINST) {
            if(debug) printf("LCD instruction byte: 0x%02X\n", data);
            switch(data) {
                case LCLEAR: {
                    if(use_special_alice2_clear) {
                        static bool receivedFirstClear = false;
                        if(!receivedFirstClear) {
                            receivedFirstClear = true;
                            printf("using HOME instead of LCD CLEAR instruction\n");
                            printf("    (it seems we don't use CLEAR correctly)\n");
                        }
                        memset(lcd + cursor, ' ', sizeof(lcd) - cursor);
                        for(int i = 0; i < lcd_rows * lcd_columns; i++)
                            draw_lcd_character(i);
                        cursor = 0;
                    } else {
                        cursor = 0;
                        memset(lcd, ' ', sizeof(lcd));
                        for(int i = 0; i < lcd_rows * lcd_columns; i++)
                            draw_lcd_character(i);
                    }
                    break;
                }
                case LRESET:
                    cursor = 0;
                    break;
                case LHALF1:
                    cursor = 0;
                    break;
                case LHALF2:
                    cursor = lcd_rows;
                    break;
            }
            return true;
        }
        if(addr == LCDDATA) {
            if(debug)
                printf("LCD data byte: 0x%02X (%c)\n", data, data);

            lcd[cursor] = data;
            if(cursor < lcd_columns * lcd_rows)
                draw_lcd_character(cursor);
            cursor ++;

            return true;
        }
        return false;
    }

    void draw_lcd_character(int which)
    {
        int y = which / lcd_columns;
        int x = which - y * lcd_columns;
        int c = lcd[which];
        draw_glyph(rfb_server,
            rfb_offset_x + (fontwidth + 1) * font_scale * x,
            rfb_offset_y + (fontheight + 1) * font_scale * y,
            c);
    }
};

static void handleKey(rfbBool down, rfbKeySym key, rfbClientPtr cl)
{
    for(auto b = boards.begin(); b != boards.end(); b++)
        if((*b)->handle_rfb_key(down, key, cl))
            break;
}

void print_state(Z80_STATE* state)
{
    printf("BC :%04X  DE :%04X  HL :%04X  AF :%04X  IX : %04X  IY :%04X  SP :%04X\n",
        state->registers.word[Z80_BC], state->registers.word[Z80_DE],
        state->registers.word[Z80_HL], state->registers.word[Z80_AF],
        state->registers.word[Z80_IX], state->registers.word[Z80_IY],
        state->registers.word[Z80_SP]);
    printf("BC':%04X  DE':%04X  HL':%04X  AF':%04X\n",
        state->alternates[Z80_BC], state->alternates[Z80_DE],
        state->alternates[Z80_HL], state->alternates[Z80_AF]);
    printf("PC :%04X\n",
        state->pc);
}

struct BreakPoint
{
    enum Type {INSTRUCTION, DATA} type;
    int address;
    unsigned char old_value;
    bool enabled;
    BreakPoint(int address_, unsigned char old_value_) :
        type(DATA),
        address(address_),
        old_value(old_value_),
        enabled(true)
    {
    }
    BreakPoint(int address_) :
        type(INSTRUCTION),
        address(address_),
        old_value(0),
        enabled(true)
    {
    }
    void enable() { enabled = true; }
    void disable() { enabled = false; }
};

void clear_breakpoints(std::vector<BreakPoint>& breakpoints, Z80_STATE* state)
{
    for(auto i = breakpoints.begin(); i != breakpoints.end(); i++) {
        BreakPoint& bp = (*i);
        switch(bp.type) {
            case BreakPoint::DATA:
                Z80_READ_BYTE(bp.address, bp.old_value);
                break;
            case BreakPoint::INSTRUCTION:
                break;
        }
    }
}

bool is_breakpoint_triggered(std::vector<BreakPoint>& breakpoints, Z80_STATE* state, int& which)
{
    for(auto i = breakpoints.begin(); i != breakpoints.end(); i++) {
        BreakPoint& bp = (*i);
        if(bp.enabled)
            switch(bp.type) {
                case BreakPoint::INSTRUCTION:
                    if(state->pc == bp.address) {
                        which = i - breakpoints.begin();
                        return true;
                    }
                    break;
                case BreakPoint::DATA:
                    unsigned char data;
                    Z80_READ_BYTE(bp.address, data);
                    if(data != bp.old_value) {
                        which = i - breakpoints.begin();
                        return true;
                    }
                    break;
            }
    }
    return false;
}

struct Debugger
{
    std::vector<BreakPoint> breakpoints;
    std::string address_to_symbol[65536]; // XXX excessive memory?
    std::map<std::string, int> symbol_to_address; // XXX excessive memory?
    sig_t previous_sigint;
    bool state_may_have_changed;
    bool last_was_step;
    bool last_was_jump;
    std::string& get_symbol(int address, int& offset)
    {
        static std::string no_symbol = "";
        offset = 0;
        while(address >= 0 && address_to_symbol[address].empty()) {
            address--;
            offset++;
        }
        if(address < 0)
            return no_symbol;
        return address_to_symbol[address];
    }
    bool load_symbols(char *filename)
    {
        FILE *fp = fopen(filename, "ra");
        if(fp == NULL) {
            fprintf(stderr, "couldn't open %s to read symbols\n", filename);
            return false;
        }
        fseek(fp, 0, SEEK_END);
        ssize_t size = ftell(fp);
        fseek(fp, 0, SEEK_SET);
        char* buffer = new char[size];
        fread(buffer, size, 1, fp);
        fclose(fp);
        char *symbol_part = buffer;
        while((symbol_part - buffer) < size && (*symbol_part != ''))
            symbol_part++;
        if(symbol_part - buffer >= size) {
            fprintf(stderr, "couldn't find symbol section in %s\n", filename);
            delete[] buffer;
            return false;
        }
        int address, consumed;
        char symbol[512];
        while(sscanf(symbol_part, "%x %s%n", &address, symbol, &consumed) == 2) {
            address_to_symbol[address] = symbol;
            symbol_to_address[symbol] = address;
            symbol_part += consumed;
        }

        delete[] buffer;
        return true;
    }
    void ctor()
    {
        state_may_have_changed = true;
        last_was_step = false;
        last_was_jump = false;
    }
    Debugger()
    {
        ctor();
    }
    bool process_line(std::vector<board_base*>& boards, Z80_STATE* state, char *line);
    bool process_command(std::vector<board_base*>& boards, Z80_STATE* state, char *command);
    void go(FILE *fp, std::vector<board_base*>& boards, Z80_STATE* state);
    bool should_debug(std::vector<board_base*>& boards, Z80_STATE* state);
};

#include "bg80d.h"

__uint8_t reader(void *p)
{
    int& address = *(int*)p;
    unsigned char data;
    Z80_READ_BYTE(address, data);
    address++;
    return data;
}

int disassemble(int address, Debugger *d, int bytecount)
{
    int total_bytes = 0;

#if USE_BG80D

    while(bytecount > 0) {

        int address_was = address;

        int symbol_offset;
        std::string& sym = d->get_symbol(address, symbol_offset);

        bg80d::opcode_spec_t *opcode = bg80d::decode(reader, &address, address);
        if(opcode == 0)
            break;

        printf("%04X %s+0x%04X%*s", address_was, sym.c_str(), symbol_offset, 16 - (int)sym.size() - 5, "");

        int opcode_length = (opcode->pc_after - address_was);
        int opcode_bytes_pad = 1 + 3 + 3 + 3 - opcode_length * 3;
        for(int i = 0; i < opcode_length; i++) {
            unsigned char byte;
            Z80_READ_BYTE(address_was + i, byte);
            printf("%.2hhX ", byte);
        }

        printf("%*s", opcode_bytes_pad, "");
        printf("%5s %s\n", opcode->prefix, opcode->description);

        bytecount -= opcode_length;
	total_bytes += opcode_length;
    }
    // FB5C conin+0x0002         e6     AND A, n        ff          ;  AND of ff to reg

#else

    int symbol_offset;
    std::string& sym = d->get_symbol(address, symbol_offset);
    printf("%04X %s+0x%04X%*s : %02X %02X %02X\n", address, sym.c_str(), symbol_offset, 16 - (int)sym.size() - 5, "", buffer[0], buffer[1], buffer[2]);

#endif

    return total_bytes;
}

void disassemble_instructions(int address, Debugger *d, int insncount)
{
    for(int i = 0; i < insncount; i++)
	address += disassemble(address, d, 1);
}

// XXX make this pointers-to-members
typedef bool (*command_handler)(Debugger* d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv);

std::map<std::string, command_handler> command_handlers;

bool lookup_or_parse(std::map<std::string, int>& symbol_to_address, char *s, int& a)
{
    auto found = symbol_to_address.find(s);
    if(found != symbol_to_address.end()) {
        a = found->second;
    } else {
        char *endptr;
        a = strtol(s, &endptr, 0);
        if(*endptr != '\0') {
            printf("number parsing failed for %s; forgot to lead with 0x?\n", s);
            return false;
        }
    }
    return true;
}

void store_memory(void *arg, int address, unsigned char p)
{
    int *info = (int*)arg;
    Z80_WRITE_BYTE(address, p);
    info[0] = std::min(info[0], address);
    info[1] = std::max(info[1], address);
    info[2]++; // XXX Could be overwrites...
}

bool debugger_readhex(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 2) {
        fprintf(stderr, "readhex: expected filename argument\n");
        return false;
    }
    FILE *fp = fopen(argv[1], "ra");
    if(fp == NULL) {
        fprintf(stderr, "failed to open %s for reading\n", argv[1]);
        return false;
    }
    int info[3] = {0xffff, 0, 0};
    int success = read_hex(fp, store_memory, info, 0);
    if (!success) {
        fprintf(stderr, "error reading hex file %s\n", argv[1]);
        fclose(fp);
        return false;
    }
    printf("Read %d (0x%04X) bytes from %s into 0x%04X..0x%04X (might be sparse)\n",
        info[2], info[2], argv[1], info[0], info[1]);
    fclose(fp);
    return false;
}

bool debugger_readbin(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 3) {
        fprintf(stderr, "readbin: expected filename and address\n");
        return false;
    }
    static unsigned char buffer[128];

    int address;
    if(!lookup_or_parse(d->symbol_to_address, argv[2], address))
        return false;

    int a = address;
    FILE *fp = fopen(argv[1], "rb");
    if(fp == NULL) {
        fprintf(stderr, "failed to open %s for reading\n", argv[1]);
        return false;
    }
    size_t size;
    while((size = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
        for(int i = 0; i <= size; i++, a++)
            Z80_WRITE_BYTE(a, buffer[i]);
    }
    printf("Read %d (0x%04X) bytes from %s into 0x%04X..0x%04X\n",
        a - address, a - address, argv[1], address, a - 1);
    fclose(fp);
    return false;
}

void dump_buffer_hex(int indent, int actual_address, unsigned char *data, int size)
{
    int address = 0;
    int screen_lines = 0;

    while(size > 0) {
        if(screen_lines >= 24) {
            printf(":");
            static char line[512];
            fgets(line, sizeof(line), stdin);
            if(strcmp(line, "q") == 0)
                return;
            screen_lines = 0;
        }
        int howmany = std::min(size, 16);

        printf("%*s0x%04X: ", indent, "", actual_address + address);
        for(int i = 0; i < howmany; i++)
            printf("%02X ", data[i]);
        printf("\n");

        printf("%*s        ", indent, "");
        for(int i = 0; i < howmany; i++)
            printf(" %c ", isprint(data[i]) ? data[i] : '.');
        printf("\n");
        screen_lines++;

        size -= howmany;
        data += howmany;
        address += howmany;
    }
}

bool debugger_dis(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 3) {
        fprintf(stderr, "dis: expected address and count\n");
        return false;
    }
    char *endptr;

    int address;
    if(!lookup_or_parse(d->symbol_to_address, argv[1], address))
        return false;

    int count = strtol(argv[2], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[2]);
        return false;
    }
    disassemble_instructions(address, d, count);
    return false;
}

bool debugger_dump(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 3) {
        fprintf(stderr, "dump: expected address and length\n");
        return false;
    }
    char *endptr;

    int address;
    if(!lookup_or_parse(d->symbol_to_address, argv[1], address))
        return false;

    int length = strtol(argv[2], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[2]);
        return false;
    }
    static unsigned char buffer[65536];
    for(int i = 0; i < length; i++)
        Z80_READ_BYTE(address + i, buffer[i]);
    dump_buffer_hex(4, address, buffer, length);
    return false;
}

bool debugger_symbols(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 2) {
        fprintf(stderr, "symbols: expected filename argument\n");
        return false;
    }
    d->load_symbols(argv[1]);
    return false;
}

bool debugger_fill(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 4) {
        fprintf(stderr, "fill: expected address, length, and value\n");
        return false;
    }
    char *endptr;

    int address;
    if(!lookup_or_parse(d->symbol_to_address, argv[1], address))
        return false;

    int length = strtol(argv[2], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[2]);
        return false;
    }
    int value = strtol(argv[3], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[3]);
        return false;
    }
    printf("fill %d for %d with %d\n", address, length, value);
    for(int i = 0; i < length; i++)
        Z80_WRITE_BYTE(address + i, value);
    return false;
}

bool debugger_in(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 2) {
        fprintf(stderr, "out: expected port number\n");
        return false;
    }
    char *endptr;
    int port = strtol(argv[1], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[1]);
        return false;
    }
    unsigned char byte;
    Z80_INPUT_BYTE(port, byte);
    printf("received byte 0x%02X from port %d (0x%02X)\n", byte, port, port);
    return false;
}

bool debugger_out(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 3) {
        fprintf(stderr, "out: expected port number and byte\n");
        return false;
    }
    char *endptr;
    int port = strtol(argv[1], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[1]);
        return false;
    }
    int value = strtol(argv[2], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[2]);
        return false;
    }
    Z80_OUTPUT_BYTE(port, value);
    return false;
}

bool debugger_help(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    printf("Debugger commands:\n");
    printf("    dump addr count       - dump count bytes at addr\n");
    printf("    fill addr count byte  - fill count bytes with byte at addr\n");
    printf("    readhex file.hex      - read file.hex into memory\n");
    printf("    readbin addr file.bin - read file.bin into memory at addr\n");
    printf("    step [N]              - step [for N instructions]\n");
    printf("    watch addr            - break out of step if addr changes\n");
    printf("    break addr            - break into debugger at addr\n");
    printf("    disable N             - disable breakpoint N\n");
    printf("    enable N              - disable breakpoint N\n");
    printf("    remove N              - remove breakpoint N\n");
    printf("    list                  - list breakpoints and catchpoints\n");
    printf("    jump addr             - jump to addr \n");
    printf("    pc addr               - set PC to addr(in anticipation of \"step\")\n");
    printf("    in port               - input byte from port and print it\n");
    printf("    out port byte         - output byte to port\n");
    printf("    help                  - print this help message\n");
    printf("    ?                     - print this help message\n");
    printf("    dis addr count        - disassemble count instructions at addr\n");
    // printf("    reset\n");
    return false;
}

bool debugger_continue(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    d->state_may_have_changed = true;
    return true;
}

bool brads_zero_check = true;

bool debugger_step(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    int count = 1;
    bool verbose = false;

    if((argc > 1) && (strcmp(argv[1], "-v") == 0)) {
        verbose = true;
        argc--;
        argv++;
    }
    if(argc > 1) {
        char *endptr;
        count = strtol(argv[1], &endptr, 0);
        if(*endptr != '\0') {
            printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[1]);
            return false;
        }
    }
    unsigned long long total_cycles = 0;
    for(int i = 0; i < count; i++) {
        total_cycles += Z80Emulate(state, 1);
        if(i < count - 1) {
            if(verbose) {
                print_state(state);
                disassemble(state->pc, d, 1);
            }
        }
        if(d->should_debug(boards, state))
            break;
    }
    printf("%llu actual cycles emulated\n", total_cycles);
    d->state_may_have_changed = true;
    d->last_was_step = true;
    return false;
}

bool debugger_jump(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 2) {
        fprintf(stderr, "jump: expected address\n");
        return false;
    }

    if(!lookup_or_parse(d->symbol_to_address, argv[1], state->pc))
        return false;

    char *endptr;
    state->pc = strtol(argv[1], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[1]);
        return false;
    }

    d->state_may_have_changed = true;
    d->last_was_jump = true;
    return true;
}

bool debugger_pc(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 2) {
        fprintf(stderr, "jump: expected address\n");
        return false;
    }
    char *endptr;
    state->pc = strtol(argv[1], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[1]);
        return false;
    }
    d->state_may_have_changed = true;
    return false;
}

bool debugger_quit(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    quit = true;
    return true;
}

bool debugger_break(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 2) {
        fprintf(stderr, "break: expected address\n");
        return false;
    }

    int address;
    if(!lookup_or_parse(d->symbol_to_address, argv[1], address))
        return false;

    d->breakpoints.push_back(BreakPoint(address));
    return false;
}

bool debugger_watch(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 2) {
        fprintf(stderr, "break: expected address\n");
        return false;
    }

    int address;
    if(!lookup_or_parse(d->symbol_to_address, argv[1], address))
        return false;

    unsigned char old_value;
    Z80_READ_BYTE(address, old_value);
    d->breakpoints.push_back(BreakPoint(address, old_value));
    return false;
}

bool debugger_disable(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 2) {
        fprintf(stderr, "break: expected address\n");
        return false;
    }
    char *endptr;
    int i = strtol(argv[1], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[1]);
        return false;
    }
    if(i < 0 || i >= d->breakpoints.size()) {
        fprintf(stderr, "breakpoint %d is out of range\n", i);
        return false;
    }
    d->breakpoints[i].disable();
    return false;
}

bool debugger_enable(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 2) {
        fprintf(stderr, "break: expected address\n");
        return false;
    }
    char *endptr;
    int i = strtol(argv[1], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[1]);
        return false;
    }
    if(i < 0 || i >= d->breakpoints.size()) {
        fprintf(stderr, "breakpoint %d is out of range\n", i);
        return false;
    }
    d->breakpoints[i].enable();
    return false;
}

bool debugger_remove(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    if(argc != 2) {
        fprintf(stderr, "break: expected address\n");
        return false;
    }
    char *endptr;
    int i = strtol(argv[1], &endptr, 0);
    if(*endptr != '\0') {
        printf("number parsing failed for %s; forgot to lead with 0x?\n", argv[1]);
        return false;
    }
    if(i < 0 || i >= d->breakpoints.size()) {
        fprintf(stderr, "breakpoint %d is out of range\n", i);
        return false;
    }
    d->breakpoints.erase(d->breakpoints.begin() + i);
    return false;
}

bool debugger_list(Debugger *d, std::vector<board_base*>& boards, Z80_STATE* state, int argc, char **argv)
{
    printf("breakpoints:\n");
    for(auto i = d->breakpoints.begin(); i != d->breakpoints.end(); i++) {
        BreakPoint& bp = (*i);
        printf("%ld : ", i - d->breakpoints.begin());
        printf("%s ", bp.enabled ? " enabled" : "disabled");
        printf("%s ", (bp.type == BreakPoint::INSTRUCTION) ? " ins" : "data");
        if(bp.type == BreakPoint::INSTRUCTION) {
            int symbol_offset;
            std::string& sym = d->get_symbol(bp.address, symbol_offset);
            printf("break at 0x%04x (%s+%d)\n", bp.address, sym.c_str(), symbol_offset);
        } else {
            printf("change at 0x%04X from 0x%02X\n", bp.address, bp.old_value);
        }
    }
    return false;
}

void populate_command_handlers()
{
    command_handlers["?"] = debugger_help;
    command_handlers["help"] = debugger_help;
    command_handlers["readhex"] = debugger_readhex;
    command_handlers["readbin"] = debugger_readbin;
    command_handlers["dump"] = debugger_dump;
    command_handlers["fill"] = debugger_fill;
    command_handlers["symbols"] = debugger_symbols;
    command_handlers["in"] = debugger_in;
    command_handlers["out"] = debugger_out;
    command_handlers["go"] = debugger_continue;
    command_handlers["g"] = debugger_continue;
    command_handlers["step"] = debugger_step;
    command_handlers["jump"] = debugger_jump;
    command_handlers["pc"] = debugger_pc;
    command_handlers["break"] = debugger_break;
    command_handlers["watch"] = debugger_watch;
    command_handlers["enable"] = debugger_enable;
    command_handlers["disable"] = debugger_disable;
    command_handlers["remove"] = debugger_remove;
    command_handlers["list"] = debugger_list;
    command_handlers["quit"] = debugger_quit;
    command_handlers["exit"] = debugger_quit;
    command_handlers["dis"] = debugger_dis;
        // reset
}

bool Debugger::process_command(std::vector<board_base*>& boards, Z80_STATE* state, char *command)
{
    // process commands
    char **ap, *argv[10];

    for (ap = argv; (*ap = strsep(&command, " \t")) != NULL;)
        if (**ap != '\0')
            if (++ap >= &argv[10])
                break;
    int argc = ap - argv;

    if(argc == 0) {
        if(last_was_step)
            return debugger_step(this, boards, state, argc, argv);
        else
            return false;
    }

    last_was_step = false;
    auto it = command_handlers.find(argv[0]);
    if(it == command_handlers.end()) {
        fprintf(stderr, "debugger command not defined: \"%s\"\n", argv[0]);
        return false;
    }

    return (*it).second(this, boards, state, argc, argv);
}

bool Debugger::process_line(std::vector<board_base*>& boards, Z80_STATE* state, char *line)
{
    char *command;

    while((command = strsep(&line, ";")) != NULL) {
        bool run = process_command(boards, state, command);
        if(run)
            return true;
    }
    return false;
}

bool Debugger::should_debug(std::vector<board_base*>& boards, Z80_STATE* state)
{
    int which;
    bool should = !last_was_jump && is_breakpoint_triggered(breakpoints, state, which);
    last_was_jump = false;
    return should;
}

bool enter_debugger = false;

void mark_enter_debugger(int signal)
{
    enter_debugger = true;
}

void Debugger::go(FILE *fp, std::vector<board_base*>& boards, Z80_STATE* state)
{
    signal(SIGINT, previous_sigint);
    for(auto b = boards.begin(); b != boards.end(); b++)
        (*b)->pause();

    if(!feof(fp)) {
        bool run = false;
        do {
            if(state_may_have_changed) {
                state_may_have_changed = false;
                print_state(state);
                disassemble(state->pc, this, 1);
            }
            int which;
            if(is_breakpoint_triggered(breakpoints, state, which))
            {
                printf("breakpoint %d: ", which);
                BreakPoint& bp = breakpoints[which];
                if(bp.type == BreakPoint::INSTRUCTION) {
                    int symbol_offset;
                    std::string& sym = get_symbol(state->pc, symbol_offset);
                    printf("break at 0x%04x (%s+%d)\n", bp.address, sym.c_str(), symbol_offset);
                } else {
                    unsigned char new_value;
                    Z80_READ_BYTE(bp.address, new_value);
                    printf("change at 0x%04X from 0x%02X to 0x%02X\n", bp.address, bp.old_value, new_value);
                }
                clear_breakpoints(breakpoints, state);
            }
            if(fp == stdin) {
                char *line;
                line = readline("? ");
                if(strlen(line) > 0)
                    add_history(line);
                run = process_line(boards, state, line);
                free(line);
            } else {
                char line[512];
                if(fgets(line, sizeof(line), fp) == NULL)
                    break;
                line[strlen(line) - 1] = '\0';
                run = process_line(boards, state, line);
            }
            for(auto b = boards.begin(); b != boards.end(); b++)
                (*b)->idle();

        } while(!run);
    }

    for(auto b = boards.begin(); b != boards.end(); b++)
        (*b)->resume();

    previous_sigint = signal(SIGINT, mark_enter_debugger);
    state_may_have_changed = true;
}

void usage(char *progname)
{
    printf("\n");
    printf("usage: %s [options] {ROM.bin|ROM.hex}\n", progname);
    printf("\n");
    printf("options:\n");
    printf("\t-fakecpmhw driveA.bin[,driveB.bin[,...]]\n");
    printf("\t                        Start fake CPM hardware\n");
    printf("\t-debugger init          Invoke debugger on startup\n");
    printf("\t                        \"init\" can be commands (separated by \";\"\n");
    printf("\t                        or a filename.  The initial commands can be\n");
    printf("\t                        the empty string.\n");
    printf("\t-use-old-PIC-commands   Have PIC emulation send old PIC command bytes\n");
    printf("\t                        (for old ripped ROM)\n");
    printf("\t-no-PIC-timer           Don't issue PIC timer interrupts\n");
    printf("\t-video MODE             Use video MODE\n");
    printf("\t                        \"normal\"  - 176 columns (default)\n");
    printf("\t                        \"double\"  - 352 columns\n");
    printf("\t                        \"halfmax\" - 248 columns\n");
    printf("\t                        \"normal\"  - 496 columns\n");
    printf("\t-lcd TYPE               Use lcd TYPE, \"1x16\", \"2x16\", \"4x40\"\n");
    printf("\n");
}

int main(int argc, char **argv)
{
    const int cycles_per_loop = 50000;
    VIDEOboard::video_mode video = VIDEOboard::NORMAL;
    LCDboard::lcd_model lcd = LCDboard::LCD_2x16;
    bool use_old_PIC_commands = false;
    bool give_timer_interrupts = true;

    Debugger *debugger = NULL;
    char *debugger_argument = NULL;

    bool use_fake_CPM_HW = false;
    char *fake_cpm_hw_arg = NULL;

    char *progname = argv[0];
    argc -= 1;
    argv += 1;

    while((argc > 0) && (argv[0][0] == '-')) {
	if(
            (strcmp(argv[0], "-help") == 0) ||
            (strcmp(argv[0], "-h") == 0) ||
            (strcmp(argv[0], "-?") == 0))
         {
             usage(progname);
             exit(EXIT_SUCCESS);
	} else if(strcmp(argv[0], "-debugger") == 0) {
            if(argc < 2) {
                fprintf(stderr, "-debugger requires initial commands (can be empty, e.g. \"\"\n");
                usage(progname);
                exit(EXIT_FAILURE);
            }
            debugger = new Debugger();
            debugger_argument = argv[1];
	    argc -= 2;
	    argv += 2;
	} else if(strcmp(argv[0], "-fakecpmhw") == 0) {
            use_fake_CPM_HW = true;
            give_timer_interrupts = false;
            if(argc < 2) {
                fprintf(stderr, "-fake-CPM_HW requires parameter\n");
                usage(progname);
                exit(EXIT_FAILURE);
            }
            fake_cpm_hw_arg = argv[1];
	    argc -= 2;
	    argv += 2;
	} else if(strcmp(argv[0], "-no-PIC-timer") == 0) {
            give_timer_interrupts = false;
	    argc -= 1;
	    argv += 1;
	} else if(strcmp(argv[0], "-use-old-PIC-commands") == 0) {
            use_old_PIC_commands = true;
	    argc -= 1;
	    argv += 1;
	} else if(strcmp(argv[0], "-lcd") == 0) {
            if(argc < 2) {
                fprintf(stderr, "-lcd requires a parameter; 1x16, 2x16, or 4x40\n");
                usage(progname);
                exit(EXIT_FAILURE);
            }
            if(strcmp(argv[1], "1x16") == 0)
                lcd = LCDboard::LCD_1x16;
            else if(strcmp(argv[1], "2x16") == 0)
                lcd = LCDboard::LCD_2x16;
            else if(strcmp(argv[1], "4x40") == 0)
                lcd = LCDboard::LCD_4x40;
            else {
                fprintf(stderr, "-lcd parameter must be 1x16, 2x16, or 4x40\n");
                usage(progname);
                exit(EXIT_FAILURE);
            }
	    argc -= 2;
	    argv += 2;
	} else if(strcmp(argv[0], "-video") == 0) {
            if(argc < 2) {
                fprintf(stderr, "-video requires a parameter; normal, double, halfmax, or max\n");
                usage(progname);
                exit(EXIT_FAILURE);
            }
            if(strcmp(argv[1], "normal") == 0)
                video = VIDEOboard::NORMAL;
            else if(strcmp(argv[1], "double") == 0)
                video = VIDEOboard::DOUBLE;
            else if(strcmp(argv[1], "halfmax") == 0)
                video = VIDEOboard::HALFMAX;
            else if(strcmp(argv[1], "max") == 0)
                video = VIDEOboard::MAX;
            else {
                fprintf(stderr, "-video parameter must be normal, double, halfmax, or max\n");
                usage(progname);
                exit(EXIT_FAILURE);
            }
	    argc -= 2;
	    argv += 2;
	} else {
	    fprintf(stderr, "unknown parameter \"%s\"\n", argv[0]);
            usage(progname);
	    exit(EXIT_FAILURE);
	}
    }

    if(argc < 1) {
        usage(progname);
        exit(EXIT_FAILURE);
    }

    char *filename = argv[0];
    unsigned char b[16384];
    if (strlen(filename) >= 4 && strcmp(filename + strlen(filename) - 4, ".hex") == 0) {
        FILE *fp = fopen(filename, "ra");
        if(fp == NULL) {
            fprintf(stderr, "failed to open %s for reading\n", filename);
            exit(EXIT_FAILURE);
        }
        memset(b, '\0', sizeof(b));
        struct memory_desc md;
        memory_desc_init(&md, b, 0, sizeof(b));
        int success = read_hex(fp, memory_desc_store, &md, 1);
        if (!success) {
            fprintf(stderr, "error reading hex file %s\n", filename);
            exit(EXIT_FAILURE);
        }
        fclose(fp);
    } else {
        FILE *fp = fopen(filename, "rb");
        if(fp == NULL) {
            fprintf(stderr, "failed to open %s for reading\n", filename);
            exit(EXIT_FAILURE);
        }
        size_t length = fread(b, 1, sizeof(b), fp);
        if(length < 16384) {
            fprintf(stderr, "ROM read from %s was unexpectedly short (%zd bytes)\n", filename, length);
            exit(EXIT_FAILURE);
        }
        fclose(fp);
    }

    populate_keycode_map();
    populate_command_handlers();

    if(use_fake_CPM_HW)
        boards.push_back(new FakeCPMboard(fake_cpm_hw_arg));
    boards.push_back(new MEMORYboard(b));
    boards.push_back(new PIC8259board());
    boards.push_back(new VIDEOboard(video));
    boards.push_back(new LCDboard(lcd));
    boards.push_back(new IOboard(use_old_PIC_commands, give_timer_interrupts));

    const int border_width = 4;
    const int border_height = 4;

    int need_width = border_width * 2;
    int need_height = border_height;

    for(auto b = boards.begin(); b != boards.end(); b++) {
        int w, h;
        if((*b)->get_rfb_requirements(w, h)) {
            need_width = std::max(need_width, w + border_width * 2);
            need_height += h + border_height;
        }
    }

    int rfbargc = 0;
    char **rfbargv = 0;
    rfbScreenInfoPtr server = rfbGetScreen(&rfbargc,rfbargv,need_width,need_height,8,3,4);
    unsigned char* rfb_bytes = new unsigned char[need_width*need_height*4];
    server->frameBuffer = (char *)rfb_bytes;
    server->kbdAddEvent = handleKey;

    int y_offset = border_height;
    for(auto b = boards.begin(); b != boards.end(); b++) {
        int w, h;
        if((*b)->get_rfb_requirements(w, h)) {
            (*b)->set_rfb(server, (need_width - w) / 2, y_offset);
            y_offset += h + border_height;
        }
    }

    for(auto b = boards.begin(); b != boards.end(); b++) {
        (*b)->init();
    }

    Z80_STATE state;

    Z80Reset(&state);

    rfbInitServer(server);
    rfbProcessEvents(server, 1000);

    if(debugger) {
        enter_debugger = true;
        debugger->process_line(boards, &state, debugger_argument);
    }

    time_t time_then;
    time_then = time(NULL);
    unsigned long long total_cycles = 0;
    unsigned long long cycles_then = 0;
    while(!quit)
    {
        if(debugger && (enter_debugger || debugger->should_debug(boards, &state))) {
            debugger->go(stdin, boards, &state);
            enter_debugger = false;
        } else {
            struct timeval tv;
            double start, stop;

            gettimeofday(&tv, NULL);
            start = tv.tv_sec + tv.tv_usec / 1000000.0;
            if(debugger) {
                unsigned long long cycles = 0;
                do {
                    cycles += Z80Emulate(&state, 1);
                    if(enter_debugger || debugger->should_debug(boards, &state)) {
                        debugger->go(stdin, boards, &state);
                        enter_debugger = false;
                    }
                } while(cycles < cycles_per_loop);
                total_cycles += cycles;
            } else {
                total_cycles += Z80Emulate(&state, cycles_per_loop);
            }
            time_t then;
            then = time(NULL);

            time_t time_now;
            time_now = time(NULL);
            if(time_now != time_then) {
                if(debug) printf("%llu cycles per second\n", total_cycles - cycles_then);
                cycles_then = total_cycles;
                time_then = time_now;
            }
            gettimeofday(&tv, NULL);
            stop = tv.tv_sec + tv.tv_usec / 1000000.0;
            // printf("%f in Emulate\n", (stop - start) * 1000000);
        }

        struct timeval tv;
        double start, stop;

        gettimeofday(&tv, NULL);
        start = tv.tv_sec + tv.tv_usec / 1000000.0;
        rfbProcessEvents(server, 1000);
        gettimeofday(&tv, NULL);
        stop = tv.tv_sec + tv.tv_usec / 1000000.0;
        // printf("%f in rfbProcessEvents\n", (stop - start) * 1000000);

        gettimeofday(&tv, NULL);
        start = tv.tv_sec + tv.tv_usec / 1000000.0;
        for(auto b = boards.begin(); b != boards.end(); b++) {
            int irq;
            if((*b)->board_get_interrupt(irq)) {
                // Pretend to be 8259 configured for Alice2:
                Z80_INTERRUPT_FETCH = true;
                Z80_INTERRUPT_FETCH_DATA = 0x3f00 + irq * 4;
                total_cycles += Z80Interrupt(&state, 0xCD);
                break;
            }
        }
        gettimeofday(&tv, NULL);
        stop = tv.tv_sec + tv.tv_usec / 1000000.0;
        // printf("%f in board irq check\n", (stop - start) * 1000000);

        gettimeofday(&tv, NULL);
        start = tv.tv_sec + tv.tv_usec / 1000000.0;
        for(auto b = boards.begin(); b != boards.end(); b++) {
            (*b)->idle();
        }
        gettimeofday(&tv, NULL);
        stop = tv.tv_sec + tv.tv_usec / 1000000.0;
        // printf("%f in board idle\n", (stop - start) * 1000000);
    }

    return 0;
}


text:
from proposal import Tracer as ProposalMixin

from basictracer.tracer import BasicTracer

class DebugTracer(ProposalMixin, BasicTracer):
    """DebugTracer is a real implementation of an OpenTracing
    Tracer that uses the reference implementation extended with
    the Tracer proposal. It is used to run real examples with
    the extended API.
    """
    pass

redpajama_set_name: RedPajamaGithub


text:
static const char* type_to_name[] = {
    "passed",  // KYUA_RESULT_PASSED
    "failed",  // KYUA_RESULT_FAILED
    "broken",  // KYUA_RESULT_BROKEN
    "skipped",  // KYUA_RESULT_SKIPPED
    "expected_failure",  // KYUA_RESULT_EXPECTED_FAILURE
};

/// Creates a file with the result of the test.
///
/// \param path Path to the file to be created.
/// \param type The type of the result.
/// \param reason Textual explanation of the reason behind the result.  Must be
///     NULL with KYUA_RESULT_PASSED, or else non-NULL.
///
/// \return An error object.
kyua_error_t
kyua_result_write(const char* path, const enum kyua_result_type_t type,
                  const char* reason, ...)
{
    assert(type == KYUA_RESULT_PASSED || reason != NULL);
    assert(reason == NULL || type != KYUA_RESULT_PASSED);

    FILE* file = fopen(path, "w");
    if (file == NULL)
        return kyua_libc_error_new(errno, "Cannot create result file '%s'",
                                   path);
    if (reason != NULL) {
        char buffer[1024];
        va_list ap;
        va_start(ap, reason);
        (void)vsnprintf(buffer, sizeof(buffer), reason, ap);
        va_end(ap);
        fprintf(file, "%s: %s\n", type_to_name[type], buffer);
    } else {
        fprintf(file, "%s\n", type_to_name[type]);
    }
    fclose(file);

    return kyua_error_ok();
}


text:
$(function() {
  $('a[href*="#"]:not([href="#"])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html, body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});


text:
/*!
 * leading-editor
 *
 * Version: 1.0.7 - 2017-11-17T07:37:34.083Z
 * License:
 */

(function () {
    "use strict";
    (function () {
        var leadingEditorModule;
        leadingEditorModule = angular.module("leading.editor", []);

        leadingEditorModule.constant('editorConfig', {
            language: 'zh-cn'
        });

        leadingEditorModule.directive('editor', ['$parse','editorConfig', ckeditorDirective]);

        var setImmediate = window && window.setImmediate ? window.setImmediate : function (fn) {
            setTimeout(fn, 0);
        };

        function ckeditorDirective($parse,editorConfig) {
            return {
                restrict: 'A',
                require: "ngModel",
                link: function ($scope, $element, $attrs, ctrl) {
                    var _LDEditor, _updateByRender;
                    _updateByRender = false;
                    _LDEditor = (function () {
                        function _LDEditor() {
                            //var _self = this;
                            // _self.bindRender();
                            //_self.initEditor();
                        }

                        _LDEditor.prototype.initEditor = function () {
                            var _EConfig, _editorId, _self;
                            _self = this;
                            if (typeof CKEDITOR === 'undefined') {
                                console.error("Please import the local resources of ckeditor!");
                                return;
                            }
                            _EConfig = $scope.config ? $scope.config : {};
                            if (editorConfig) {
                                _EConfig = angular.extend({}, editorConfig);
                            }
                            var config = $scope.$eval($attrs.editor);
                            if (config) {
                                _EConfig = angular.extend({}, _EConfig, config);
                            }

                            _editorId = $attrs.id ? $attrs.id : "_editor" + (Date.now());
                            $element[0].id = _editorId;

                            this.editor = CKEDITOR.replace(_editorId, _EConfig);

                            return $.when( this.editor.promise ).then( function() {
                                _self.editorReady = true;
                                _self.editor.on("change", function (evt) {
                                    ctrl.$setViewValue(evt.editor.getData());
                                    if (!_updateByRender) {
                                        if (!$scope.$$phase) {
                                            $scope.$apply();
                                        }
                                    }
                                    _updateByRender = false;
                                });

                                _self.editor.on("instanceReady",function (evt) {

                                    this.document.on("keyup", function () {
                                        ctrl.$setViewValue(evt.editor.getData());
                                        if (!_updateByRender) {
                                            if (!$scope.$$phase) {
                                                $scope.$apply();
                                            }
                                        }
                                        _updateByRender = false;
                                    });
                                    this.document.on("mouseout", function () {
                                        ctrl.$setViewValue(evt.editor.getData());
                                        if (!_updateByRender) {
                                            if (!$scope.$$phase) {
                                                $scope.$apply();
                                            }
                                        }
                                        _updateByRender = false;
                                    });
                                    this.document.on("blur", function () {
                                        ctrl.$setViewValue(evt.editor.getData());
                                        if (!_updateByRender) {
                                            if (!$scope.$$phase) {
                                                $scope.$apply();
                                            }
                                        }
                                        _updateByRender = false;
                                    });

                                    _self.editor.setReadOnly(!!$attrs.readonly);
                                    $attrs.$observe('readonly', function (readonly) {
                                        _self.editor.setReadOnly(!!readonly);
                                    });

                                    // Defer the ready handler calling to ensure that the editor is
                                    // completely ready and populated with data.
                                    setImmediate(function () {
                                        $parse($attrs.ready)($scope);
                                    });
                                });

                                if (_self.modelContent && _self.modelContent.length > 0) {
                                    _self.setEditorContent();
                                }

                                $scope.$on("$destroy", function () {
                                    _self.editor.destroy();
                                });
                            });
                        };

                        _LDEditor.prototype.setEditorContent = function (content) {
                            if (!content) {
                                content = this.modelContent;
                            }
                            if (this.editor && this.editorReady) {
                                this.editor.setData(content);
                            }
                        };

                        _LDEditor.prototype.bindRender = function () {
                            var _self;
                            _self = this;
                            ctrl.$render = function () {
                                _self.modelContent = (ctrl.$isEmpty(ctrl.$viewValue) ? "" : ctrl.$viewValue);
                                _updateByRender = true;
                                _self.setEditorContent();
                            };
                        };

                        return _LDEditor;

                    })();
                    var editorInstance = new _LDEditor();
                    editorInstance.bindRender();
                    editorInstance.initEditor();
                }
            };
        }
    })();
}).call();


text:
'use strict';
var assert = require('assert');
var gulp = require('gulp');
var concatStream = require('concat-stream');
var compress = require('./');

describe('compress', function () {
	it('js', function (cb) {
		gulp.src('fixture/src/minify.js')
			.pipe(compress())
			.pipe(gulp.dest('fixture/dest'))
			.pipe(concatStream(function(buf){
				buf.forEach(function(item){
					assert.equal(-1, item.contents.toString().indexOf('message'));
				});

				cb();
			}));
	});

	it('css', function (cb) {
		gulp.src('fixture/src/minify.css')
			.pipe(compress({
				type: 'css'
			}))
			.pipe(gulp.dest('fixture/dest'))
			.pipe(concatStream(function(buf){
				buf.forEach(function(item){
					assert.notEqual(-1, item.contents.toString().indexOf('message'));
				});

				cb();
			}));
	});
});


text:
using System;
using Cake.Core;
using Cake.Core.Annotations;
using Cake.Core.IO;

namespace Cake.Common.Tools.MSBuild
{
    /// <summary>
    /// Contains functionality related to MSBuild.
    /// </summary>
    [CakeAliasCategory("MSBuild")]
    public static class MSBuildAliases
    {
        /// <summary>
        /// Builds the specified solution using MSBuild.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="solution">The solution.</param>
        [CakeMethodAlias]
        public static void MSBuild(this ICakeContext context, FilePath solution)
        {
            MSBuild(context, solution, settings => { });
        }

        /// <summary>
        /// Builds the specified solution using MSBuild.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="solution">The solution to build.</param>
        /// <param name="configurator">The settings configurator.</param>
        [CakeMethodAlias]
        public static void MSBuild(this ICakeContext context, FilePath solution, Action<MSBuildSettings> configurator)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (configurator == null)
            {
                throw new ArgumentNullException("configurator");
            }

            var settings = new MSBuildSettings();
            configurator(settings);

            // Perform the build.
            MSBuild(context, solution, settings);
        }

        /// <summary>
        /// Builds the specified solution using MSBuild.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="solution">The solution to build.</param>
        /// <param name="settings">The settings.</param>
        [CakeMethodAlias]
        public static void MSBuild(this ICakeContext context, FilePath solution, MSBuildSettings settings)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            var runner = new MSBuildRunner(context.FileSystem, context.Environment, context.ProcessRunner, context.Globber);
            runner.Run(solution, settings);
        }
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:gravity="center"
                  android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_gravity="center"
            android:layout_marginBottom="50dp"
            android:gravity="center_horizontal"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="Powered by "/>

            <ImageView
                android:layout_width="200dp"
                android:layout_height="50dp"
                android:layout_marginBottom="120dp"
                android:src="@drawable/og_logo_long"/>
        </LinearLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="50dp"
            android:text="Please enter your OpenGamma Service credentials:"/>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:layout_gravity="center">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:text="Use Password"/>

            <Switch
                android:id="@+id/login_type_switch"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:text="Use API Keys"/>

        </LinearLayout>

        <com.rengwuxian.materialedittext.MaterialEditText
            android:id="@+id/login_email_input"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="e@mail.com"
            android:inputType="textEmailAddress"
            android:paddingBottom="10dp"/>

        <com.rengwuxian.materialedittext.MaterialEditText
            android:id="@+id/login_api_key_input"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="your api key here"
            android:inputType="text"
            android:paddingBottom="10dp"
            android:visibility="gone"/>

        <com.rengwuxian.materialedittext.MaterialEditText
            android:id="@+id/login_password_input"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Password"
            android:inputType="textPassword"
            android:paddingBottom="10dp"/>

        <com.gc.materialdesign.views.ButtonRectangle
            android:id="@+id/login_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#336699"
            android:text="Login"/>

    </LinearLayout>

    <FrameLayout
        android:id="@+id/progressBarHolder"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="true"
        android:visibility="gone">

        <ProgressBar
            android:id="@+id/login_screen_progress_bar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:indeterminate="true"
            android:indeterminateTint="@android:color/darker_gray"/>
    </FrameLayout>
</RelativeLayout>


text:
<?php
// projectOverviewChart/backend/CBuilder.class.php

class CBuilder {
	// Get data for frontend
	public static function Get($data)	{
		// Load data for project
        TestSuiteDataService::LoadSubmissions($data->ProjectTSE, DataDepth::RESULT,
            new QueryPagination(1, SettingsService::GetTemplateByIdentifier(
                'project-overview-chart',
                $data->ProjectTSE->GetId())->Data['submissions-number'],
                'desc'
            )
        );

        // Reverse order of submissions
        $data->ProjectTSE->ReverseSubmissions();

        // Initialize Google chart object
        $projectOverviewChart = new OverviewChart();
        $googleChart = new GoogleChart();

        $googleChart->setType(GCType::COLUMN_CHART);

        // Assign options to chart
        $googleChart->setOptions(self::GetGCOptions());

        // Get data
        $googleChart->setData(self::GetGCData($data->ProjectTSE));

        // Set overview chart to google chart
        $projectOverviewChart->SetChart($googleChart);
        // Add possible values
        $projectOverviewChart->AddType(GCType::AREA_CHART);
        $projectOverviewChart->AddType(GCType::COLUMN_CHART);
        $projectOverviewChart->AddType(GCType::LINE_CHART);

        // return google chart object
        return new ValidationResult($projectOverviewChart->ExportObject());
	}

	/**
     * Get google chart data
     * @param ProjectTSE $project
     * @return mixed
     */
    private static function GetGCData(ProjectTSE $project)  {
        // Initialize data
        $gcData = new GCData();

        // Initialize array to hold submissions
        $submissions = array();

        // In this state, we need results for each submission,
        // these results are then proccessed without any other
        // needed information
        foreach ($project->GetSubmissions() as $submission)
        {
            // Initalize array to hold results
            $subResults = array();

            // Go through each category
            foreach ($submission->GetCategories() as $category)
            {
                // And each test case
                foreach ($category->GetTestCases() as $testCase)
                {
                    // Go through each result
                    foreach ($testCase->GetResults() as $result)
                    {
                        // Save value to array
                        $subResults[] = $result->GetValue();
                    }
                }
            }
            // Save results to array, this array has to be
            // dictionary so we are sure where each result
            // set belongs
            $submissions[$submission->GetDateTime()] = $subResults;
        }

        // Now merge all results into one, to get all possible columns
        $columns = array();
        foreach ($submissions as $submissionResultSet)
        {
            // Merge arrays
            $columns = array_merge($columns, $submissionResultSet);
            // And make it unique, because we only need to know the columns
            $columns = array_unique($columns);
        }

        // For now we have columns, we can start creating chart,
        // the first one is submission itself
        $colSubmission = new GCCol();
        $colSubmission->setId("submission");
        $colSubmission->setLabel("Submission");
        $colSubmission->setType("string");
        // Add to data set
        $gcData->AddColumn($colSubmission);

        // The next ones are values
        foreach ($columns as $column)
        {
            // Create new column
            $gcCol = new GCCol();
            $gcCol->setId("status-".$column);
            $gcCol->setLabel($column);
            $gcCol->setType("number");
            // Add to data set
            $gcData->AddColumn($gcCol);
        }

        // For each submission there is, create new row and assign cells
        foreach ($submissions as $dateCreated => $results)
        {
            // Create new row
            $gcRow = new GCRow();

            // Before getting any values, first cell is submission
            $gcCell = new GCCell();
            $gcCell->setValue($dateCreated);
            // Add cell to row
            $gcRow->AddCell($gcCell);

            // Load results into LINQ object
            $lResults = new LINQ($results);

            // Go through each column and get value for it
            foreach ($columns as $column)
            {
                // Create new cell
                $gcCell = new GCCell();

                // Set value
                $gcCell->setValue($lResults->Where(null, LINQ::IS_EQUAL, $column)->Count());

                // Add cell to row
                $gcRow->AddCell($gcCell);
            }

            // Add row to data set
            $gcData->AddRow($gcRow);
        }

        // Return data
        return $gcData;
    }

    /**
     * Get google chart options
     * @return mixed
     */
    private static function GetGCOptions()  {
        // Create options and set all in it
        $gcOptions = new GCOptions();
        $gcOptions->setFill(20);
        $gcOptions->setTitle("Running results");
        $gcOptions->setDisplayOverviewHeader(true);

        // Create vAxis
        $gcVAxis = new GCAxis();
        $gcVAxis->setGridlines(new GCGridlines(10));
        $gcVAxis->setTitle("Result count");

        // Add to options
        $gcOptions->setVAxis($gcVAxis);

        // Create hAxis
        $gcHAxis = new GCAxis();
        $gcHAxis->setTitle("Submission");

        // Add to options
        $gcOptions->setHAxis($gcHAxis);

        // Return options
        return $gcOptions;
    }
}

?>


text:
<?php

use yii\bootstrap\ActiveForm;
use yii\bootstrap\Html;
use bs\dbManager\models\BaseDumpManager;

/* @var $this yii\web\View */
/* @var \bs\dbManager\models\Restore $model */
/* @var string $file */
/* @var int $id */

$this->title = Yii::t('dbManager', 'Restore');
$this->params['breadcrumbs'][] = ['label' => Yii::t('dbManager', 'DB manager'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>

<?= Yii::t('dbManager', 'Restore') . ': ' .  $file ?>

        <?php $form = ActiveForm::begin([
            'action' => ['restore', 'id' => $id],
            'method' => 'post',
        ]) ?>

        <?= $form->errorSummary($model) ?>

        <?= $form->field($model, 'db')->dropDownList($model->getDBList(), ['prompt' => '']) ?>

        <?php if (!BaseDumpManager::isWindows()) {
            echo $form->field($model, 'runInBackground')->checkbox();
        } ?>

        <?php if ($model->hasPresets()): ?>
            <?= $form->field($model, 'preset')->dropDownList($model->getCustomOptions(), ['prompt' => '']) ?>
        <?php endif ?>

        <?= Html::submitButton(Yii::t('dbManager', 'Restore'), ['class' => 'btn btn-success']) ?>

        <?php ActiveForm::end() ?>


text:
/* TEMPLATE GENERATED TESTCASE FILE
Filename: CWE190_Integer_Overflow__int64_t_max_add_82a.cpp
Label Definition File: CWE190_Integer_Overflow.label.xml
Template File: sources-sinks-82a.tmpl.cpp
*/
/*
 * @description
 * CWE: 190 Integer Overflow
 * BadSource: max Set data to the max value for int64_t
 * GoodSource: Set data to a small, non-zero number (two)
 * Sinks: add
 *    GoodSink: Ensure there will not be an overflow before adding 1 to data
 *    BadSink : Add 1 to data, which can cause an overflow
 * Flow Variant: 82 Data flow: data passed in a parameter to an virtual method called via a pointer
 *
 * */

#include "std_testcase.h"
#include "CWE190_Integer_Overflow__int64_t_max_add_82.h"

namespace CWE190_Integer_Overflow__int64_t_max_add_82
{

#ifndef OMITBAD

void bad()
{
    int64_t data;
    data = 0LL;
    /* POTENTIAL FLAW: Use the maximum size of the data type */
    data = LLONG_MAX;
    CWE190_Integer_Overflow__int64_t_max_add_82_base* baseObject = new CWE190_Integer_Overflow__int64_t_max_add_82_bad;
    baseObject->action(data);
    delete baseObject;
}

#endif /* OMITBAD */

#ifndef OMITGOOD

/* goodG2B uses the GoodSource with the BadSink */
static void goodG2B()
{
    int64_t data;
    data = 0LL;
    /* FIX: Use a small, non-zero value that will not cause an overflow in the sinks */
    data = 2;
    CWE190_Integer_Overflow__int64_t_max_add_82_base* baseObject = new CWE190_Integer_Overflow__int64_t_max_add_82_goodG2B;
    baseObject->action(data);
    delete baseObject;
}

/* goodB2G uses the BadSource with the GoodSink */
static void goodB2G()
{
    int64_t data;
    data = 0LL;
    /* POTENTIAL FLAW: Use the maximum size of the data type */
    data = LLONG_MAX;
    CWE190_Integer_Overflow__int64_t_max_add_82_base* baseObject = new CWE190_Integer_Overflow__int64_t_max_add_82_goodB2G;
    baseObject->action(data);
    delete baseObject;
}

void good()
{
    goodG2B();
    goodB2G();
}

#endif /* OMITGOOD */

} /* close namespace */

/* Below is the main(). It is only used when building this testcase on
   its own for testing or for building a binary to use in testing binary
   analysis tools. It is not used when compiling all the testcases as one
   application, which is how source code analysis tools are tested. */

#ifdef INCLUDEMAIN

using namespace CWE190_Integer_Overflow__int64_t_max_add_82; /* so that we can use good and bad easily */

int main(int argc, char * argv[])
{
    /* seed randomness */
    srand( (unsigned)time(NULL) );
#ifndef OMITGOOD
    printLine("Calling good()...");
    good();
    printLine("Finished good()");
#endif /* OMITGOOD */
#ifndef OMITBAD
    printLine("Calling bad()...");
    bad();
    printLine("Finished bad()");
#endif /* OMITBAD */
    return 0;
}

#endif