|
1 /* GRAPHITE2 LICENSING |
|
2 |
|
3 Copyright 2010, SIL International |
|
4 All rights reserved. |
|
5 |
|
6 This library is free software; you can redistribute it and/or modify |
|
7 it under the terms of the GNU Lesser General Public License as published |
|
8 by the Free Software Foundation; either version 2.1 of License, or |
|
9 (at your option) any later version. |
|
10 |
|
11 This program is distributed in the hope that it will be useful, |
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 Lesser General Public License for more details. |
|
15 |
|
16 You should also have received a copy of the GNU Lesser General Public |
|
17 License along with this library in the file named "LICENSE". |
|
18 If not, write to the Free Software Foundation, 51 Franklin Street, |
|
19 Suite 500, Boston, MA 02110-1335, USA or visit their web page on the |
|
20 internet at http://www.fsf.org/licenses/lgpl.html. |
|
21 |
|
22 Alternatively, the contents of this file may be used under the terms of the |
|
23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public |
|
24 License, as published by the Free Software Foundation, either version 2 |
|
25 of the License or (at your option) any later version. |
|
26 */ |
|
27 // This class represents loaded graphite stack machine code. It performs |
|
28 // basic sanity checks, on the incoming code to prevent more obvious problems |
|
29 // from crashing graphite. |
|
30 // Author: Tim Eves |
|
31 |
|
32 #pragma once |
|
33 |
|
34 #include <cassert> |
|
35 #include <graphite2/Types.h> |
|
36 #include "inc/Main.h" |
|
37 #include "inc/Machine.h" |
|
38 |
|
39 namespace graphite2 { |
|
40 |
|
41 class Silf; |
|
42 class Face; |
|
43 |
|
44 namespace vm { |
|
45 |
|
46 class Machine::Code |
|
47 { |
|
48 public: |
|
49 enum status_t |
|
50 { |
|
51 loaded, |
|
52 alloc_failed, |
|
53 invalid_opcode, |
|
54 unimplemented_opcode_used, |
|
55 out_of_range_data, |
|
56 jump_past_end, |
|
57 arguments_exhausted, |
|
58 missing_return, |
|
59 nested_context_item |
|
60 }; |
|
61 |
|
62 private: |
|
63 class decoder; |
|
64 |
|
65 instr * _code; |
|
66 byte * _data; |
|
67 size_t _data_size, |
|
68 _instr_count; |
|
69 byte _max_ref; |
|
70 mutable status_t _status; |
|
71 bool _constraint, |
|
72 _modify, |
|
73 _delete; |
|
74 mutable bool _own; |
|
75 |
|
76 void release_buffers() throw (); |
|
77 void failure(const status_t) throw(); |
|
78 |
|
79 public: |
|
80 Code() throw(); |
|
81 Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end, |
|
82 uint8 pre_context, uint16 rule_length, const Silf &, const Face &); |
|
83 Code(const Machine::Code &) throw(); |
|
84 ~Code() throw(); |
|
85 |
|
86 Code & operator=(const Code &rhs) throw(); |
|
87 operator bool () const throw(); |
|
88 status_t status() const throw(); |
|
89 bool constraint() const throw(); |
|
90 size_t dataSize() const throw(); |
|
91 size_t instructionCount() const throw(); |
|
92 bool immutable() const throw(); |
|
93 bool deletes() const throw(); |
|
94 size_t maxRef() const throw(); |
|
95 |
|
96 int32 run(Machine &m, slotref * & map) const; |
|
97 |
|
98 CLASS_NEW_DELETE; |
|
99 }; |
|
100 |
|
101 inline Machine::Code::Code() throw() |
|
102 : _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0), |
|
103 _status(loaded), _constraint(false), _modify(false),_delete(false), |
|
104 _own(false) |
|
105 { |
|
106 } |
|
107 |
|
108 inline Machine::Code::Code(const Machine::Code &obj) throw () |
|
109 : _code(obj._code), |
|
110 _data(obj._data), |
|
111 _data_size(obj._data_size), |
|
112 _instr_count(obj._instr_count), |
|
113 _max_ref(obj._max_ref), |
|
114 _status(obj._status), |
|
115 _constraint(obj._constraint), |
|
116 _modify(obj._modify), |
|
117 _delete(obj._delete), |
|
118 _own(obj._own) |
|
119 { |
|
120 obj._own = false; |
|
121 } |
|
122 |
|
123 inline Machine::Code & Machine::Code::operator=(const Machine::Code &rhs) throw() { |
|
124 if (_instr_count > 0) |
|
125 release_buffers(); |
|
126 _code = rhs._code; |
|
127 _data = rhs._data; |
|
128 _data_size = rhs._data_size; |
|
129 _instr_count = rhs._instr_count; |
|
130 _status = rhs._status; |
|
131 _constraint = rhs._constraint; |
|
132 _modify = rhs._modify; |
|
133 _delete = rhs._delete; |
|
134 _own = rhs._own; |
|
135 rhs._own = false; |
|
136 return *this; |
|
137 } |
|
138 |
|
139 inline Machine::Code::operator bool () const throw () { |
|
140 return _code && status() == loaded; |
|
141 } |
|
142 |
|
143 inline Machine::Code::status_t Machine::Code::status() const throw() { |
|
144 return _status; |
|
145 } |
|
146 |
|
147 inline bool Machine::Code::constraint() const throw() { |
|
148 return _constraint; |
|
149 } |
|
150 |
|
151 inline size_t Machine::Code::dataSize() const throw() { |
|
152 return _data_size; |
|
153 } |
|
154 |
|
155 inline size_t Machine::Code::instructionCount() const throw() { |
|
156 return _instr_count; |
|
157 } |
|
158 |
|
159 inline bool Machine::Code::immutable() const throw() |
|
160 { |
|
161 return !(_delete || _modify); |
|
162 } |
|
163 |
|
164 inline bool Machine::Code::deletes() const throw() |
|
165 { |
|
166 return _delete; |
|
167 } |
|
168 |
|
169 inline size_t Machine::Code::maxRef() const throw() |
|
170 { |
|
171 return _max_ref; |
|
172 } |
|
173 |
|
174 } // namespace vm |
|
175 } // namespace graphite2 |