95 } |
95 } |
96 } |
96 } |
97 |
97 |
98 // ==================================================================== |
98 // ==================================================================== |
99 // Write stuff to the buffer |
99 // Write stuff to the buffer |
100 template<class T> void Write(T stuff) { |
100 template<class T> void Write (T stuff) { |
101 if (sizeof (char) != 1) { |
101 if (writesize + sizeof (T) >= allocsize) { |
102 error ("DataBuffer: sizeof(char) must be 1!\n"); |
102 // We don't have enough space in the buffer to write |
103 } |
103 // the stuff - thus resize. First, store the old |
104 |
104 // buffer temporarily: |
105 // Out of space, must resize |
|
106 if (writesize + sizeof(T) >= allocsize) { |
|
107 // First, store the old buffer temporarily |
|
108 char* copy = new char[allocsize]; |
105 char* copy = new char[allocsize]; |
109 memcpy (copy, buffer, allocsize); |
106 memcpy (copy, buffer, allocsize); |
110 |
107 |
111 // Remake the buffer with the new size. |
108 // Remake the buffer with the new size. Have enough space |
112 // Have a bit of leeway so we don't have to |
109 // for the stuff we're going to write, as well as a bit |
113 // resize immediately again. |
110 // of leeway so we don't have to resize immediately again. |
114 size_t newsize = allocsize + sizeof (T) + 128; |
111 size_t newsize = allocsize + sizeof (T) + 128; |
115 delete buffer; |
112 delete buffer; |
116 buffer = new unsigned char[newsize]; |
113 buffer = new unsigned char[newsize]; |
117 allocsize = newsize; |
114 allocsize = newsize; |
118 |
115 |
119 // Now, copy the new stuff over. |
116 // Now, copy the stuff back. |
120 memcpy (buffer, copy, allocsize); |
117 memcpy (buffer, copy, allocsize); |
121 |
|
122 // Nuke the copy now as it's no longer needed |
|
123 delete copy; |
118 delete copy; |
124 } |
119 } |
125 |
120 |
126 // Write the new stuff one byte at a time |
121 // Buffer is now guaranteed to have enough space. |
|
122 // Write the stuff one byte at a time. |
|
123 union_t<T> uni; |
|
124 uni.val = stuff; |
127 for (unsigned int x = 0; x < sizeof (T); x++) { |
125 for (unsigned int x = 0; x < sizeof (T); x++) { |
128 if (writesize >= allocsize) |
126 if (writesize >= allocsize) // should NEVER happen because resizing is done above |
129 error ("DataBuffer: written size exceeds allocated size!\n"); |
127 error ("DataBuffer: written size exceeds allocated size!\n"); |
130 buffer[writesize] = GetByteIndex<T> (stuff, x); |
128 |
|
129 buffer[writesize] = uni.b[x]; |
131 writesize++; |
130 writesize++; |
132 } |
131 } |
133 } |
132 } |
134 |
133 |
135 // ==================================================================== |
134 // ==================================================================== |
167 other->Write<unsigned char> (*(buffer+x)); |
166 other->Write<unsigned char> (*(buffer+x)); |
168 return other; |
167 return other; |
169 } |
168 } |
170 |
169 |
171 // ==================================================================== |
170 // ==================================================================== |
172 // Adds a mark to the buffer. A mark is a reference to a particular |
171 // Adds a mark to the buffer. A mark is a "pointer" to a particular |
173 // position in the bytecode. The actual permanent position cannot |
172 // position in the bytecode. The actual permanent position cannot |
174 // be predicted in any way or form, thus these things will be used |
173 // be predicted in any way or form, thus these things will be used |
175 // to "mark" a position like that for future use. |
174 // to "mark" a position like that for future use. |
176 unsigned int AddMark (int type, str name) { |
175 unsigned int AddMark (int type, str name) { |
177 // Find a free slot for the mark |
176 // Find a free slot for the mark |
186 ScriptMark* m = new ScriptMark; |
185 ScriptMark* m = new ScriptMark; |
187 m->name = name; |
186 m->name = name; |
188 m->type = type; |
187 m->type = type; |
189 m->pos = writesize; |
188 m->pos = writesize; |
190 marks[u] = m; |
189 marks[u] = m; |
191 printf ("add mark %u at %d\n", u, m->pos); |
|
192 return u; |
190 return u; |
193 } |
191 } |
194 |
192 |
|
193 // ==================================================================== |
|
194 // A ref is another "mark" that references a mark. When the bytecode |
|
195 // is written to file, they are changed into their marks' current |
|
196 // positions. Marks themselves are never written to files, only refs are |
195 unsigned int AddMarkReference (unsigned int marknum) { |
197 unsigned int AddMarkReference (unsigned int marknum) { |
196 unsigned int u; |
198 unsigned int u; |
197 for (u = 0; u < MAX_MARKS; u++) |
199 for (u = 0; u < MAX_MARKS; u++) |
198 if (!refs[u]) |
200 if (!refs[u]) |
199 break; |
201 break; |
202 error ("mark reference quota exceeded, all goto-statements, if-structs and loops add refs\n"); |
204 error ("mark reference quota exceeded, all goto-statements, if-structs and loops add refs\n"); |
203 |
205 |
204 // NOTE: Do not check if the mark actually exists here since a |
206 // NOTE: Do not check if the mark actually exists here since a |
205 // reference may come in the code earlier than the actual mark |
207 // reference may come in the code earlier than the actual mark |
206 // and the new mark number can be predicted. |
208 // and the new mark number can be predicted. |
|
209 // 11/8/12: eh? The mark is always created first. |
207 ScriptMarkReference* r = new ScriptMarkReference; |
210 ScriptMarkReference* r = new ScriptMarkReference; |
208 r->num = marknum; |
211 r->num = marknum; |
209 r->pos = writesize; |
212 r->pos = writesize; |
210 refs[u] = r; |
213 refs[u] = r; |
|
214 |
|
215 // Write a dummy placeholder for the reference |
|
216 Write<word> (1234); |
211 |
217 |
212 return u; |
218 return u; |
213 } |
219 } |
214 |
220 |
215 // Delete a mark and all references to it. |
221 // Delete a mark and all references to it. |
229 } |
235 } |
230 } |
236 } |
231 } |
237 } |
232 |
238 |
233 // Adjusts a mark to the current position |
239 // Adjusts a mark to the current position |
234 void MoveMark (unsigned int mark) { |
240 void MoveMark (unsigned int mark, int offset = -1) { |
235 if (!marks[mark]) |
241 if (!marks[mark]) |
236 return; |
242 return; |
237 printf ("move mark %u from %d to %d\n", mark, marks[mark]->pos, writesize); |
|
238 marks[mark]->pos = writesize; |
243 marks[mark]->pos = writesize; |
239 } |
244 } |
240 |
245 |
241 // Adjusts a mark to the current position |
|
242 void OffsetMark (unsigned int mark, size_t offset) { |
246 void OffsetMark (unsigned int mark, size_t offset) { |
243 if (!marks[mark]) |
247 if (!marks[mark]) |
244 return; |
248 return; |
245 printf ("move mark %u from %d to %d\n", mark, marks[mark]->pos, marks[mark]->pos+offset); |
|
246 marks[mark]->pos += offset; |
249 marks[mark]->pos += offset; |
247 } |
250 } |
248 |
251 |
249 // Dump the buffer (for debugging purposes) |
252 // Dump the buffer (for debugging purposes) |
250 void Dump() { |
253 void Dump() { |