src/parser.cpp

changeset 135
8b9132fea327
parent 134
eca2fc0acaa2
child 137
73d057b030d0
equal deleted inserted replaced
134:eca2fc0acaa2 135:8b9132fea327
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include <cstring>
29 #include "parser.h" 30 #include "parser.h"
30 #include "events.h" 31 #include "events.h"
31 #include "commands.h" 32 #include "commands.h"
32 #include "stringTable.h" 33 #include "stringTable.h"
33 #include "list.h" 34 #include "list.h"
47 m_onenterBuffer (new DataBuffer), 48 m_onenterBuffer (new DataBuffer),
48 m_mainLoopBuffer (new DataBuffer), 49 m_mainLoopBuffer (new DataBuffer),
49 m_lexer (new Lexer), 50 m_lexer (new Lexer),
50 m_numStates (0), 51 m_numStates (0),
51 m_numEvents (0), 52 m_numEvents (0),
52 m_currentMode (PARSERMODE_TopLevel), 53 m_currentMode (ParserMode::TopLevel),
53 m_isStateSpawnDefined (false), 54 m_isStateSpawnDefined (false),
54 m_gotMainLoop (false), 55 m_gotMainLoop (false),
55 m_scopeCursor (-1), 56 m_scopeCursor (-1),
56 m_isElseAllowed (false), 57 m_isElseAllowed (false),
57 m_highestGlobalVarIndex (0), 58 m_highestGlobalVarIndex (0),
68 69
69 // ============================================================================ 70 // ============================================================================
70 // 71 //
71 void BotscriptParser::checkToplevel() 72 void BotscriptParser::checkToplevel()
72 { 73 {
73 if (m_currentMode != PARSERMODE_TopLevel) 74 if (m_currentMode != ParserMode::TopLevel)
74 error ("%1-statements may only be defined at top level!", getTokenString()); 75 error ("%1-statements may only be defined at top level!", getTokenString());
75 } 76 }
76 77
77 // ============================================================================ 78 // ============================================================================
78 // 79 //
79 void BotscriptParser::checkNotToplevel() 80 void BotscriptParser::checkNotToplevel()
80 { 81 {
81 if (m_currentMode == PARSERMODE_TopLevel) 82 if (m_currentMode == ParserMode::TopLevel)
82 error ("%1-statements must not be defined at top level!", getTokenString()); 83 error ("%1-statements must not be defined at top level!", getTokenString());
83 } 84 }
84 85
85 // ============================================================================ 86 // ============================================================================
86 // 87 //
213 } 214 }
214 } 215 }
215 } 216 }
216 217
217 // Script file ended. Do some last checks and write the last things to main buffer 218 // Script file ended. Do some last checks and write the last things to main buffer
218 if (m_currentMode != PARSERMODE_TopLevel) 219 if (m_currentMode != ParserMode::TopLevel)
219 error ("script did not end at top level; a `}` is missing somewhere"); 220 error ("script did not end at top level; a `}` is missing somewhere");
220 221
221 if (isReadOnly() == false) 222 if (isReadOnly() == false)
222 { 223 {
223 // stateSpawn must be defined! 224 // stateSpawn must be defined!
263 // write the previous state's onenter and 264 // write the previous state's onenter and
264 // mainloop buffers to file now 265 // mainloop buffers to file now
265 if (m_currentState.isEmpty() == false) 266 if (m_currentState.isEmpty() == false)
266 writeMemberBuffers(); 267 writeMemberBuffers();
267 268
268 currentBuffer()->writeDWord (DataHeader::StateName); 269 currentBuffer()->writeHeader (DataHeader::StateName);
269 currentBuffer()->writeString (statename); 270 currentBuffer()->writeString (statename);
270 currentBuffer()->writeDWord (DataHeader::StateIndex); 271 currentBuffer()->writeHeader (DataHeader::StateIndex);
271 currentBuffer()->writeDWord (m_numStates); 272 currentBuffer()->writeDWord (m_numStates);
272 273
273 m_numStates++; 274 m_numStates++;
274 m_currentState = statename; 275 m_currentState = statename;
275 m_gotMainLoop = false; 276 m_gotMainLoop = false;
286 287
287 if (e == null) 288 if (e == null)
288 error ("bad event, got `%1`\n", getTokenString()); 289 error ("bad event, got `%1`\n", getTokenString());
289 290
290 m_lexer->mustGetNext (Token::BraceStart); 291 m_lexer->mustGetNext (Token::BraceStart);
291 m_currentMode = PARSERMODE_Event; 292 m_currentMode = ParserMode::Event;
292 currentBuffer()->writeDWord (DataHeader::Event); 293 currentBuffer()->writeHeader (DataHeader::Event);
293 currentBuffer()->writeDWord (e->number); 294 currentBuffer()->writeDWord (e->number);
294 m_numEvents++; 295 m_numEvents++;
295 } 296 }
296 297
297 // ============================================================================ 298 // ============================================================================
299 void BotscriptParser::parseMainloop() 300 void BotscriptParser::parseMainloop()
300 { 301 {
301 checkToplevel(); 302 checkToplevel();
302 m_lexer->mustGetNext (Token::BraceStart); 303 m_lexer->mustGetNext (Token::BraceStart);
303 304
304 m_currentMode = PARSERMODE_MainLoop; 305 m_currentMode = ParserMode::MainLoop;
305 m_mainLoopBuffer->writeDWord (DataHeader::MainLoop); 306 m_mainLoopBuffer->writeHeader (DataHeader::MainLoop);
306 } 307 }
307 308
308 // ============================================================================ 309 // ============================================================================
309 // 310 //
310 void BotscriptParser::parseOnEnterExit() 311 void BotscriptParser::parseOnEnterExit()
311 { 312 {
312 checkToplevel(); 313 checkToplevel();
313 bool onenter = (tokenIs (Token::Onenter)); 314 bool onenter = (tokenIs (Token::Onenter));
314 m_lexer->mustGetNext (Token::BraceStart); 315 m_lexer->mustGetNext (Token::BraceStart);
315 316 m_currentMode = onenter ? ParserMode::Onenter : ParserMode::Onexit;
316 m_currentMode = onenter ? PARSERMODE_Onenter : PARSERMODE_Onexit; 317 currentBuffer()->writeHeader (onenter ? DataHeader::OnEnter : DataHeader::OnExit);
317 currentBuffer()->writeDWord (onenter ? DataHeader::OnEnter : DataHeader::OnExit);
318 } 318 }
319 319
320 // ============================================================================ 320 // ============================================================================
321 // 321 //
322 void BotscriptParser::parseVar() 322 void BotscriptParser::parseVar()
408 else 408 else
409 SCOPE(0).localVariables << var; 409 SCOPE(0).localVariables << var;
410 410
411 suggestHighestVarIndex (isInGlobalState(), var->index); 411 suggestHighestVarIndex (isInGlobalState(), var->index);
412 m_lexer->mustGetNext (Token::Semicolon); 412 m_lexer->mustGetNext (Token::Semicolon);
413 print ("Declared %3 variable #%1 $%2\n", var->index, var->name, isInGlobalState() ? "global" : "state-local"); 413 print ("Declared %3 variable #%1 $%2\n", var->index, var->name, isInGlobalState() ? "global" :
414 "state-local");
414 } 415 }
415 416
416 // ============================================================================ 417 // ============================================================================
417 // 418 //
418 void BotscriptParser::parseIf() 419 void BotscriptParser::parseIf()
434 // Upon a closing brace, the mark will be adjusted. 435 // Upon a closing brace, the mark will be adjusted.
435 ByteMark* mark = currentBuffer()->addMark (""); 436 ByteMark* mark = currentBuffer()->addMark ("");
436 437
437 // Use DataHeader::IfNotGoto - if the expression is not true, we goto the mark 438 // Use DataHeader::IfNotGoto - if the expression is not true, we goto the mark
438 // we just defined - and this mark will be at the end of the scope block. 439 // we just defined - and this mark will be at the end of the scope block.
439 currentBuffer()->writeDWord (DataHeader::IfNotGoto); 440 currentBuffer()->writeHeader (DataHeader::IfNotGoto);
440 currentBuffer()->addReference (mark); 441 currentBuffer()->addReference (mark);
441 442
442 // Store it 443 // Store it
443 SCOPE (0).mark1 = mark; 444 SCOPE (0).mark1 = mark;
444 SCOPE (0).type = SCOPE_If; 445 SCOPE (0).type = SCOPE_If;
458 // write down to jump to the end of the else statement 459 // write down to jump to the end of the else statement
459 // Otherwise we have fall-throughs 460 // Otherwise we have fall-throughs
460 SCOPE (0).mark2 = currentBuffer()->addMark (""); 461 SCOPE (0).mark2 = currentBuffer()->addMark ("");
461 462
462 // Instruction to jump to the end after if block is complete 463 // Instruction to jump to the end after if block is complete
463 currentBuffer()->writeDWord (DataHeader::Goto); 464 currentBuffer()->writeHeader (DataHeader::Goto);
464 currentBuffer()->addReference (SCOPE (0).mark2); 465 currentBuffer()->addReference (SCOPE (0).mark2);
465 466
466 // Move the ifnot mark here and set type to else 467 // Move the ifnot mark here and set type to else
467 currentBuffer()->adjustMark (SCOPE (0).mark1); 468 currentBuffer()->adjustMark (SCOPE (0).mark1);
468 SCOPE (0).type = SCOPE_Else; 469 SCOPE (0).type = SCOPE_Else;
490 491
491 // write condition 492 // write condition
492 currentBuffer()->mergeAndDestroy (expr); 493 currentBuffer()->mergeAndDestroy (expr);
493 494
494 // Instruction to go to the end if it fails 495 // Instruction to go to the end if it fails
495 currentBuffer()->writeDWord (DataHeader::IfNotGoto); 496 currentBuffer()->writeHeader (DataHeader::IfNotGoto);
496 currentBuffer()->addReference (mark2); 497 currentBuffer()->addReference (mark2);
497 498
498 // Store the needed stuff 499 // Store the needed stuff
499 SCOPE (0).mark1 = mark1; 500 SCOPE (0).mark1 = mark1;
500 SCOPE (0).mark2 = mark2; 501 SCOPE (0).mark2 = mark2;
541 ByteMark* mark1 = currentBuffer()->addMark (""); 542 ByteMark* mark1 = currentBuffer()->addMark ("");
542 ByteMark* mark2 = currentBuffer()->addMark (""); 543 ByteMark* mark2 = currentBuffer()->addMark ("");
543 544
544 // Add the condition 545 // Add the condition
545 currentBuffer()->mergeAndDestroy (cond); 546 currentBuffer()->mergeAndDestroy (cond);
546 currentBuffer()->writeDWord (DataHeader::IfNotGoto); 547 currentBuffer()->writeHeader (DataHeader::IfNotGoto);
547 currentBuffer()->addReference (mark2); 548 currentBuffer()->addReference (mark2);
548 549
549 // Store the marks and incrementor 550 // Store the marks and incrementor
550 SCOPE (0).mark1 = mark1; 551 SCOPE (0).mark1 = mark1;
551 SCOPE (0).mark2 = mark2; 552 SCOPE (0).mark2 = mark2;
621 // of buffering setup and stuff like that. 622 // of buffering setup and stuff like that.
622 // 623 //
623 // We null the switch buffer for the case-go-to statement as 624 // We null the switch buffer for the case-go-to statement as
624 // we want it all under the switch, not into the case-buffers. 625 // we want it all under the switch, not into the case-buffers.
625 m_switchBuffer = null; 626 m_switchBuffer = null;
626 currentBuffer()->writeDWord (DataHeader::CaseGoto); 627 currentBuffer()->writeHeader (DataHeader::CaseGoto);
627 currentBuffer()->writeDWord (num); 628 currentBuffer()->writeDWord (num);
628 addSwitchCase (null); 629 addSwitchCase (null);
629 SCOPE (0).casecursor->number = num; 630 SCOPE (0).casecursor->number = num;
630 } 631 }
631 632
648 // and is only popped when case succeeds, we have 649 // and is only popped when case succeeds, we have
649 // to pop it with DataHeader::Drop manually if we end up in 650 // to pop it with DataHeader::Drop manually if we end up in
650 // a default. 651 // a default.
651 DataBuffer* buf = new DataBuffer; 652 DataBuffer* buf = new DataBuffer;
652 SCOPE (0).buffer1 = buf; 653 SCOPE (0).buffer1 = buf;
653 buf->writeDWord (DataHeader::Drop); 654 buf->writeHeader (DataHeader::Drop);
654 buf->writeDWord (DataHeader::Goto); 655 buf->writeHeader (DataHeader::Goto);
655 addSwitchCase (buf); 656 addSwitchCase (buf);
656 } 657 }
657 658
658 // ============================================================================ 659 // ============================================================================
659 // 660 //
660 void BotscriptParser::parseBreak() 661 void BotscriptParser::parseBreak()
661 { 662 {
662 if (m_scopeCursor == 0) 663 if (m_scopeCursor == 0)
663 error ("unexpected `break`"); 664 error ("unexpected `break`");
664 665
665 currentBuffer()->writeDWord (DataHeader::Goto); 666 currentBuffer()->writeHeader (DataHeader::Goto);
666 667
667 // switch and if use mark1 for the closing point, 668 // switch and if use mark1 for the closing point,
668 // for and while use mark2. 669 // for and while use mark2.
669 switch (SCOPE (0).type) 670 switch (SCOPE (0).type)
670 { 671 {
701 switch (m_scopeStack[curs].type) 702 switch (m_scopeStack[curs].type)
702 { 703 {
703 case SCOPE_For: 704 case SCOPE_For:
704 case SCOPE_While: 705 case SCOPE_While:
705 case SCOPE_Do: 706 case SCOPE_Do:
706 currentBuffer()->writeDWord (DataHeader::Goto); 707 currentBuffer()->writeHeader (DataHeader::Goto);
707 currentBuffer()->addReference (m_scopeStack[curs].mark1); 708 currentBuffer()->addReference (m_scopeStack[curs].mark1);
708 found = true; 709 found = true;
709 break; 710 break;
710 711
711 default: 712 default:
750 { // write the incrementor at the end of the loop block 751 { // write the incrementor at the end of the loop block
751 currentBuffer()->mergeAndDestroy (SCOPE (0).buffer1); 752 currentBuffer()->mergeAndDestroy (SCOPE (0).buffer1);
752 } 753 }
753 case SCOPE_While: 754 case SCOPE_While:
754 { // write down the instruction to go back to the start of the loop 755 { // write down the instruction to go back to the start of the loop
755 currentBuffer()->writeDWord (DataHeader::Goto); 756 currentBuffer()->writeHeader (DataHeader::Goto);
756 currentBuffer()->addReference (SCOPE (0).mark1); 757 currentBuffer()->addReference (SCOPE (0).mark1);
757 758
758 // Move the closing mark here since we're at the end of the while loop 759 // Move the closing mark here since we're at the end of the while loop
759 currentBuffer()->adjustMark (SCOPE (0).mark2); 760 currentBuffer()->adjustMark (SCOPE (0).mark2);
760 break; 761 break;
768 m_lexer->mustGetNext (Token::ParenEnd); 769 m_lexer->mustGetNext (Token::ParenEnd);
769 m_lexer->mustGetNext (Token::Semicolon); 770 m_lexer->mustGetNext (Token::Semicolon);
770 771
771 // If the condition runs true, go back to the start. 772 // If the condition runs true, go back to the start.
772 currentBuffer()->mergeAndDestroy (expr); 773 currentBuffer()->mergeAndDestroy (expr);
773 currentBuffer()->writeDWord (DataHeader::IfGoto); 774 currentBuffer()->writeHeader (DataHeader::IfGoto);
774 currentBuffer()->addReference (SCOPE (0).mark1); 775 currentBuffer()->addReference (SCOPE (0).mark1);
775 break; 776 break;
776 } 777 }
777 778
778 case SCOPE_Switch: 779 case SCOPE_Switch:
789 // the headers (thus won't fall-through if no case matched) 790 // the headers (thus won't fall-through if no case matched)
790 if (SCOPE (0).buffer1) 791 if (SCOPE (0).buffer1)
791 currentBuffer()->mergeAndDestroy (SCOPE (0).buffer1); 792 currentBuffer()->mergeAndDestroy (SCOPE (0).buffer1);
792 else 793 else
793 { 794 {
794 currentBuffer()->writeDWord (DataHeader::Drop); 795 currentBuffer()->writeHeader (DataHeader::Drop);
795 currentBuffer()->writeDWord (DataHeader::Goto); 796 currentBuffer()->writeHeader (DataHeader::Goto);
796 currentBuffer()->addReference (SCOPE (0).mark1); 797 currentBuffer()->addReference (SCOPE (0).mark1);
797 } 798 }
798 799
799 // Go through all of the buffers we 800 // Go through all of the buffers we
800 // recorded down and write them. 801 // recorded down and write them.
816 // Descend down the stack 817 // Descend down the stack
817 m_scopeCursor--; 818 m_scopeCursor--;
818 return; 819 return;
819 } 820 }
820 821
821 int dataheader = (m_currentMode == PARSERMODE_Event) ? DataHeader::EndEvent 822 DataHeader dataheader =
822 : (m_currentMode == PARSERMODE_MainLoop) ? DataHeader::EndMainLoop 823 (m_currentMode == ParserMode::Event) ? DataHeader::EndEvent
823 : (m_currentMode == PARSERMODE_Onenter) ? DataHeader::EndOnEnter 824 : (m_currentMode == ParserMode::MainLoop) ? DataHeader::EndMainLoop
824 : (m_currentMode == PARSERMODE_Onexit) ? DataHeader::EndOnExit 825 : (m_currentMode == ParserMode::Onenter) ? DataHeader::EndOnEnter
825 : -1; 826 : (m_currentMode == ParserMode::Onexit) ? DataHeader::EndOnExit
826 827 : DataHeader::NumDataHeaders;
827 if (dataheader == -1) 828
829 if (dataheader == DataHeader::NumDataHeaders)
828 error ("unexpected `}`"); 830 error ("unexpected `}`");
829 831
830 // Data header must be written before mode is changed because 832 // Data header must be written before mode is changed because
831 // onenter and mainloop go into special buffers, and we want 833 // onenter and mainloop go into special buffers, and we want
832 // the closing data headers into said buffers too. 834 // the closing data headers into said buffers too.
833 currentBuffer()->writeDWord (dataheader); 835 currentBuffer()->writeHeader (dataheader);
834 m_currentMode = PARSERMODE_TopLevel; 836 m_currentMode = ParserMode::TopLevel;
835 m_lexer->next (Token::Semicolon); 837 m_lexer->next (Token::Semicolon);
836 } 838 }
837 839
838 // ============================================================================= 840 // =============================================================================
839 // 841 //
933 { 935 {
934 checkToplevel(); 936 checkToplevel();
935 m_lexer->mustGetSymbol ("zandronum"); 937 m_lexer->mustGetSymbol ("zandronum");
936 String versionText; 938 String versionText;
937 939
938 while (m_lexer->next() and (m_lexer->tokenType() == Token::Number or m_lexer->tokenType() == Token::Dot)) 940 while (m_lexer->next() and (m_lexer->tokenType() == Token::Number or m_lexer->tokenType() ==
941 Token::Dot))
939 versionText += getTokenString(); 942 versionText += getTokenString();
940 943
941 // Note: at this point the lexer's pointing at the token after the version. 944 // Note: at this point the lexer's pointing at the token after the version.
942 if (versionText.isEmpty()) 945 if (versionText.isEmpty())
943 error ("expected version string, got `%1`", getTokenString()); 946 error ("expected version string, got `%1`", getTokenString());
944 947
945 if (g_validZandronumVersions.contains (versionText) == false) 948 if (g_validZandronumVersions.contains (versionText) == false)
946 error ("unknown version string `%2`: valid versions: `%1`\n", g_validZandronumVersions, versionText); 949 error ("unknown version string `%2`: valid versions: `%1`\n", g_validZandronumVersions,
950 versionText);
947 951
948 StringList versionTokens = versionText.split ("."); 952 StringList versionTokens = versionText.split (".");
949 m_zandronumVersion = versionTokens[0].toLong() * 10000 + versionTokens[1].toLong() * 100; 953 m_zandronumVersion = versionTokens[0].toLong() * 10000 + versionTokens[1].toLong() * 100;
950 m_defaultZandronumVersion = false; 954 m_defaultZandronumVersion = false;
951 m_lexer->tokenMustBe (Token::Semicolon); 955 m_lexer->tokenMustBe (Token::Semicolon);
957 // 961 //
958 DataBuffer* BotscriptParser::parseCommand (CommandInfo* comm) 962 DataBuffer* BotscriptParser::parseCommand (CommandInfo* comm)
959 { 963 {
960 DataBuffer* r = new DataBuffer (64); 964 DataBuffer* r = new DataBuffer (64);
961 965
962 if (m_currentMode == PARSERMODE_TopLevel and comm->returnvalue == TYPE_Void) 966 if (m_currentMode == ParserMode::TopLevel and comm->returnvalue == TYPE_Void)
963 error ("command call at top level"); 967 error ("command call at top level");
964 968
965 m_lexer->mustGetNext (Token::ParenStart); 969 m_lexer->mustGetNext (Token::ParenStart);
966 m_lexer->mustGetNext (Token::Any); 970 m_lexer->mustGetNext (Token::Any);
967 971
1011 } 1015 }
1012 1016
1013 // If the script skipped any optional arguments, fill in defaults. 1017 // If the script skipped any optional arguments, fill in defaults.
1014 while (curarg < comm->args.size()) 1018 while (curarg < comm->args.size())
1015 { 1019 {
1016 r->writeDWord (DataHeader::PushNumber); 1020 r->writeHeader (DataHeader::PushNumber);
1017 r->writeDWord (comm->args[curarg].defvalue); 1021 r->writeDWord (comm->args[curarg].defvalue);
1018 curarg++; 1022 curarg++;
1019 } 1023 }
1020 1024
1021 r->writeDWord (DataHeader::Command); 1025 r->writeHeader (DataHeader::Command);
1022 r->writeDWord (comm->number); 1026 r->writeDWord (comm->number);
1023 r->writeDWord (comm->args.size()); 1027 r->writeDWord (comm->args.size());
1024 1028
1025 return r; 1029 return r;
1026 } 1030 }
1156 } 1160 }
1157 1161
1158 // Get an operator 1162 // Get an operator
1159 AssignmentOperator oper = parseAssignmentOperator(); 1163 AssignmentOperator oper = parseAssignmentOperator();
1160 1164
1161 if (m_currentMode == PARSERMODE_TopLevel) 1165 if (m_currentMode == ParserMode::TopLevel)
1162 error ("can't alter variables at top level"); 1166 error ("can't alter variables at top level");
1163 1167
1164 if (var->isarray) 1168 if (var->isarray)
1165 retbuf->mergeAndDestroy (arrayindex); 1169 retbuf->mergeAndDestroy (arrayindex);
1166 1170
1182 DataHeader::RightShift); 1186 DataHeader::RightShift);
1183 retbuf->WriteDWord (var->IsGlobal() ? DataHeader::AssignGlobalVar : DataHeader::AssignLocalVar); 1187 retbuf->WriteDWord (var->IsGlobal() ? DataHeader::AssignGlobalVar : DataHeader::AssignLocalVar);
1184 retbuf->WriteDWord (var->index); 1188 retbuf->WriteDWord (var->index);
1185 #endif 1189 #endif
1186 1190
1187 DataHeader dh = getAssigmentDataHeader (oper, var); 1191 retbuf->writeHeader (getAssigmentDataHeader (oper, var));
1188 retbuf->writeDWord (dh);
1189 retbuf->writeDWord (var->index); 1192 retbuf->writeDWord (var->index);
1190 return retbuf; 1193 return retbuf;
1191 } 1194 }
1192 1195
1193 // ============================================================================ 1196 // ============================================================================
1312 DataBuffer* BotscriptParser::currentBuffer() 1315 DataBuffer* BotscriptParser::currentBuffer()
1313 { 1316 {
1314 if (m_switchBuffer != null) 1317 if (m_switchBuffer != null)
1315 return m_switchBuffer; 1318 return m_switchBuffer;
1316 1319
1317 if (m_currentMode == PARSERMODE_MainLoop) 1320 if (m_currentMode == ParserMode::MainLoop)
1318 return m_mainLoopBuffer; 1321 return m_mainLoopBuffer;
1319 1322
1320 if (m_currentMode == PARSERMODE_Onenter) 1323 if (m_currentMode == ParserMode::Onenter)
1321 return m_onenterBuffer; 1324 return m_onenterBuffer;
1322 1325
1323 return m_mainBuffer; 1326 return m_mainBuffer;
1324 } 1327 }
1325 1328
1328 void BotscriptParser::writeMemberBuffers() 1331 void BotscriptParser::writeMemberBuffers()
1329 { 1332 {
1330 // If there was no mainloop defined, write a dummy one now. 1333 // If there was no mainloop defined, write a dummy one now.
1331 if (m_gotMainLoop == false) 1334 if (m_gotMainLoop == false)
1332 { 1335 {
1333 m_mainLoopBuffer->writeDWord (DataHeader::MainLoop); 1336 m_mainLoopBuffer->writeHeader (DataHeader::MainLoop);
1334 m_mainLoopBuffer->writeDWord (DataHeader::EndMainLoop); 1337 m_mainLoopBuffer->writeHeader (DataHeader::EndMainLoop);
1335 } 1338 }
1336 1339
1337 // Write the onenter and mainloop buffers, in that order in particular. 1340 // Write the onenter and mainloop buffers, in that order in particular.
1338 for (DataBuffer** bufp : List<DataBuffer**> ({&m_onenterBuffer, &m_mainLoopBuffer})) 1341 for (DataBuffer** bufp : List<DataBuffer**> ({&m_onenterBuffer, &m_mainLoopBuffer}))
1339 { 1342 {
1357 1360
1358 if (stringcount == 0) 1361 if (stringcount == 0)
1359 return; 1362 return;
1360 1363
1361 // Write header 1364 // Write header
1362 m_mainBuffer->writeDWord (DataHeader::StringList); 1365 m_mainBuffer->writeHeader (DataHeader::StringList);
1363 m_mainBuffer->writeDWord (stringcount); 1366 m_mainBuffer->writeDWord (stringcount);
1364 1367
1365 // Write all strings 1368 // Write all strings
1366 for (int i = 0; i < stringcount; i++) 1369 for (int i = 0; i < stringcount; i++)
1367 m_mainBuffer->writeString (getStringTable()[i]); 1370 m_mainBuffer->writeString (getStringTable()[i]);
1374 void BotscriptParser::writeToFile (String outfile) 1377 void BotscriptParser::writeToFile (String outfile)
1375 { 1378 {
1376 FILE* fp = fopen (outfile, "wb"); 1379 FILE* fp = fopen (outfile, "wb");
1377 1380
1378 if (fp == null) 1381 if (fp == null)
1379 error ("couldn't open %1 for writing: %2", outfile, strerror (errno)); 1382 error ("couldn't open %1 for writing: %2", outfile, std::strerror (errno));
1380 1383
1381 // First, resolve references 1384 // First, resolve references
1382 for (MarkReference* ref : m_mainBuffer->references()) 1385 for (MarkReference* ref : m_mainBuffer->references())
1383 { 1386 {
1384 for (int i = 0; i < 4; ++i) 1387 for (int i = 0; i < 4; ++i)

mercurial