summaryrefslogtreecommitdiff
path: root/src/map/script.hpp
blob: 66939aa2b4b50ebb713b8b3e297f763c9c725b87 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#ifndef SCRIPT_HPP
#define SCRIPT_HPP

#include <cstdint>
#include <cstring> // for inlined get_str - TODO remove

#include <string>
#include <vector>

#include "../common/db.hpp"
#include "../common/dumb_ptr.hpp"

#include "map.t.hpp"

enum class ByteCode : uint8_t;
struct str_data_t;

class ScriptBuffer
{
    std::vector<ByteCode> script_buf;
public:
    // construction methods used only by script.cpp
    void add_scriptc(ByteCode a);
    void add_scriptb(uint8_t a);
    void add_scripti(uint32_t a);
    void add_scriptl(str_data_t *a);
    void set_label(str_data_t *ld, int pos_);
    const char *parse_simpleexpr(const char *p);
    const char *parse_subexpr(const char *p, int limit);
    const char *parse_expr(const char *p);
    const char *parse_line(const char *p);
    void parse_script(const char *src, int line);

    // consumption methods used only by script.cpp
    ByteCode operator[](size_t i) const { return script_buf[i]; }
    const char *get_str(size_t i) const
    {
        return reinterpret_cast<const char *>(&script_buf[i]);
    }

    // method used elsewhere
};

struct ScriptPointer
{
    const ScriptBuffer *code;
    size_t pos;

    ScriptPointer()
    : code()
    , pos()
    {}

    ScriptPointer(const ScriptBuffer *c, size_t p)
    : code(c)
    , pos(p)
    {}

    ByteCode peek() const { return (*code)[pos]; }
    ByteCode pop() { return (*code)[pos++]; }
    const char *pops()
    {
        const char *rv = code->get_str(pos);
        pos += strlen(rv);
        ++pos;
        return rv;
    }
};

// internal
class SIR
{
    uint32_t impl;
    SIR(SP v)
    : impl(static_cast<uint32_t>(v))
    {}
    SIR(unsigned v, uint8_t i)
    : impl((i << 24) | v)
    {}
public:
    SIR() : impl() {}

    unsigned base() const { return impl & 0x00ffffff; }
    uint8_t index() const { return impl >> 24; }
    SIR iplus(uint8_t i) const { return SIR(base(), index() + i); }
    static SIR from(unsigned v, uint8_t i=0) { return SIR(v, i); }

    SP sp() const { return static_cast<SP>(impl); }
    static SIR from(SP v) { return SIR(v); }

    friend bool operator == (SIR l, SIR r) { return l.impl == r.impl; }
    friend bool operator < (SIR l, SIR r) { return l.impl < r.impl; }
};

struct script_data
{
    ByteCode type;
    union uu
    {
        SIR reg;
        int numi;
        dumb_string str;
        // Not a ScriptPointer - pos is stored in a separate slot,
        // to avoid exploding the struct for everyone.
        const ScriptBuffer *script;

        uu() { memset(this, '\0', sizeof(*this)); }
        ~uu() = default;
        uu(const uu&) = default;
        uu& operator = (const uu&) = default;
    } u;
};

struct script_stack
{
    std::vector<struct script_data> stack_datav;
};

enum class ScriptEndState;
// future improvements coming!
class ScriptState
{
public:
    struct script_stack *stack;
    int start, end;
    ScriptEndState state;
    int rid, oid;
    ScriptPointer scriptp, new_scriptp;
    int defsp, new_defsp;
};

std::unique_ptr<const ScriptBuffer> parse_script(const char *, int);
typedef struct argrec
{
    const char *name;
    union _aru
    {
        int i;
        const char *s;

        _aru() = default;
        _aru(int n) : i(n) {}
        _aru(const char *z) : s(z) {}
    } v;
} argrec_t;
int run_script_l(ScriptPointer, int, int, int, argrec_t *args);
int run_script(ScriptPointer, int, int);

extern
Map<std::string, int> scriptlabel_db;
extern
UPMap<std::string, const ScriptBuffer> userfunc_db;

void script_config_read();
void do_init_script(void);
void do_final_script(void);

extern char mapreg_txt[256];

extern int script_errors;

#endif // SCRIPT_HPP