257 // encountered it, then mark down that we have it. |
256 // encountered it, then mark down that we have it. |
258 if (statename.toLowercase() == "statespawn") |
257 if (statename.toLowercase() == "statespawn") |
259 m_isStateSpawnDefined = true; |
258 m_isStateSpawnDefined = true; |
260 |
259 |
261 // Must end in a colon |
260 // Must end in a colon |
262 m_lexer->mustGetNext (TK_Colon); |
261 m_lexer->mustGetNext (Token::Colon); |
263 |
262 |
264 // write the previous state's onenter and |
263 // write the previous state's onenter and |
265 // mainloop buffers to file now |
264 // mainloop buffers to file now |
266 if (m_currentState.isEmpty() == false) |
265 if (m_currentState.isEmpty() == false) |
267 writeMemberBuffers(); |
266 writeMemberBuffers(); |
268 |
267 |
269 currentBuffer()->writeDWord (DH_StateName); |
268 currentBuffer()->writeDWord (DataHeader::StateName); |
270 currentBuffer()->writeString (statename); |
269 currentBuffer()->writeString (statename); |
271 currentBuffer()->writeDWord (DH_StateIndex); |
270 currentBuffer()->writeDWord (DataHeader::StateIndex); |
272 currentBuffer()->writeDWord (m_numStates); |
271 currentBuffer()->writeDWord (m_numStates); |
273 |
272 |
274 m_numStates++; |
273 m_numStates++; |
275 m_currentState = statename; |
274 m_currentState = statename; |
276 m_gotMainLoop = false; |
275 m_gotMainLoop = false; |
279 // ============================================================================ |
278 // ============================================================================ |
280 // |
279 // |
281 void BotscriptParser::parseEventBlock() |
280 void BotscriptParser::parseEventBlock() |
282 { |
281 { |
283 checkToplevel(); |
282 checkToplevel(); |
284 m_lexer->mustGetNext (TK_String); |
283 m_lexer->mustGetNext (Token::String); |
285 |
284 |
286 EventDefinition* e = findEventByName (getTokenString()); |
285 EventDefinition* e = findEventByName (getTokenString()); |
287 |
286 |
288 if (e == null) |
287 if (e == null) |
289 error ("bad event, got `%1`\n", getTokenString()); |
288 error ("bad event, got `%1`\n", getTokenString()); |
290 |
289 |
291 m_lexer->mustGetNext (TK_BraceStart); |
290 m_lexer->mustGetNext (Token::BraceStart); |
292 m_currentMode = PARSERMODE_Event; |
291 m_currentMode = PARSERMODE_Event; |
293 currentBuffer()->writeDWord (DH_Event); |
292 currentBuffer()->writeDWord (DataHeader::Event); |
294 currentBuffer()->writeDWord (e->number); |
293 currentBuffer()->writeDWord (e->number); |
295 m_numEvents++; |
294 m_numEvents++; |
296 } |
295 } |
297 |
296 |
298 // ============================================================================ |
297 // ============================================================================ |
299 // |
298 // |
300 void BotscriptParser::parseMainloop() |
299 void BotscriptParser::parseMainloop() |
301 { |
300 { |
302 checkToplevel(); |
301 checkToplevel(); |
303 m_lexer->mustGetNext (TK_BraceStart); |
302 m_lexer->mustGetNext (Token::BraceStart); |
304 |
303 |
305 m_currentMode = PARSERMODE_MainLoop; |
304 m_currentMode = PARSERMODE_MainLoop; |
306 m_mainLoopBuffer->writeDWord (DH_MainLoop); |
305 m_mainLoopBuffer->writeDWord (DataHeader::MainLoop); |
307 } |
306 } |
308 |
307 |
309 // ============================================================================ |
308 // ============================================================================ |
310 // |
309 // |
311 void BotscriptParser::parseOnEnterExit() |
310 void BotscriptParser::parseOnEnterExit() |
312 { |
311 { |
313 checkToplevel(); |
312 checkToplevel(); |
314 bool onenter = (tokenIs (TK_Onenter)); |
313 bool onenter = (tokenIs (Token::Onenter)); |
315 m_lexer->mustGetNext (TK_BraceStart); |
314 m_lexer->mustGetNext (Token::BraceStart); |
316 |
315 |
317 m_currentMode = onenter ? PARSERMODE_Onenter : PARSERMODE_Onexit; |
316 m_currentMode = onenter ? PARSERMODE_Onenter : PARSERMODE_Onexit; |
318 currentBuffer()->writeDWord (onenter ? DH_OnEnter : DH_OnExit); |
317 currentBuffer()->writeDWord (onenter ? DataHeader::OnEnter : DataHeader::OnExit); |
319 } |
318 } |
320 |
319 |
321 // ============================================================================ |
320 // ============================================================================ |
322 // |
321 // |
323 void BotscriptParser::parseVar() |
322 void BotscriptParser::parseVar() |
324 { |
323 { |
325 Variable* var = new Variable; |
324 Variable* var = new Variable; |
326 var->origin = m_lexer->describeCurrentPosition(); |
325 var->origin = m_lexer->describeCurrentPosition(); |
327 var->isarray = false; |
326 var->isarray = false; |
328 const bool isconst = m_lexer->next (TK_Const); |
327 bool isconst = m_lexer->next (Token::Const); |
329 m_lexer->mustGetAnyOf ({TK_Int,TK_Str,TK_Void}); |
328 m_lexer->mustGetAnyOf ({Token::Int,Token::Str,Token::Void}); |
330 |
329 |
331 DataType vartype = (tokenIs (TK_Int)) ? TYPE_Int : |
330 DataType vartype = (tokenIs (Token::Int)) ? TYPE_Int |
332 (tokenIs (TK_Str)) ? TYPE_String : |
331 : (tokenIs (Token::Str)) ? TYPE_String |
333 TYPE_Bool; |
332 : TYPE_Bool; |
334 |
333 |
335 m_lexer->mustGetNext (TK_DollarSign); |
334 if (m_lexer->next (Token::Const)) |
336 m_lexer->mustGetNext (TK_Symbol); |
335 { |
|
336 if (isconst) |
|
337 error ("duplicate const in variable declaration"); |
|
338 |
|
339 isconst = true; |
|
340 } |
|
341 |
|
342 m_lexer->mustGetNext (Token::DollarSign); |
|
343 m_lexer->mustGetNext (Token::Symbol); |
337 String name = getTokenString(); |
344 String name = getTokenString(); |
338 |
345 |
339 if (m_lexer->next (TK_BracketStart)) |
346 if (m_lexer->next (Token::BracketStart)) |
340 { |
347 { |
341 m_lexer->mustGetNext (TK_BracketEnd); |
348 m_lexer->mustGetNext (Token::BracketEnd); |
342 var->isarray = true; |
349 var->isarray = true; |
343 |
350 |
344 if (isconst) |
351 if (isconst) |
345 error ("arrays cannot be const"); |
352 error ("arrays cannot be const"); |
346 } |
353 } |
347 |
354 |
348 for (Variable* var : SCOPE(0).globalVariables + SCOPE(0).localVariables) |
355 for (Variable* var : SCOPE(0).globalVariables + SCOPE(0).localVariables) |
349 { |
356 { |
350 if (var->name == name) |
357 if (var->name == name) |
|
358 { |
351 error ("Variable $%1 is already declared on this scope; declared at %2", |
359 error ("Variable $%1 is already declared on this scope; declared at %2", |
352 var->name, var->origin); |
360 var->name, var->origin); |
|
361 } |
353 } |
362 } |
354 |
363 |
355 var->name = name; |
364 var->name = name; |
356 var->statename = ""; |
365 var->statename = ""; |
357 var->type = vartype; |
366 var->type = vartype; |
410 { |
419 { |
411 checkNotToplevel(); |
420 checkNotToplevel(); |
412 pushScope(); |
421 pushScope(); |
413 |
422 |
414 // Condition |
423 // Condition |
415 m_lexer->mustGetNext (TK_ParenStart); |
424 m_lexer->mustGetNext (Token::ParenStart); |
416 |
425 |
417 // Read the expression and write it. |
426 // Read the expression and write it. |
418 DataBuffer* c = parseExpression (TYPE_Int); |
427 DataBuffer* c = parseExpression (TYPE_Int); |
419 currentBuffer()->mergeAndDestroy (c); |
428 currentBuffer()->mergeAndDestroy (c); |
420 |
429 |
421 m_lexer->mustGetNext (TK_ParenEnd); |
430 m_lexer->mustGetNext (Token::ParenEnd); |
422 m_lexer->mustGetNext (TK_BraceStart); |
431 m_lexer->mustGetNext (Token::BraceStart); |
423 |
432 |
424 // Add a mark - to here temporarily - and add a reference to it. |
433 // Add a mark - to here temporarily - and add a reference to it. |
425 // Upon a closing brace, the mark will be adjusted. |
434 // Upon a closing brace, the mark will be adjusted. |
426 ByteMark* mark = currentBuffer()->addMark (""); |
435 ByteMark* mark = currentBuffer()->addMark (""); |
427 |
436 |
428 // Use DH_IfNotGoto - if the expression is not true, we goto the mark |
437 // Use DataHeader::IfNotGoto - if the expression is not true, we goto the mark |
429 // we just defined - and this mark will be at the end of the scope block. |
438 // we just defined - and this mark will be at the end of the scope block. |
430 currentBuffer()->writeDWord (DH_IfNotGoto); |
439 currentBuffer()->writeDWord (DataHeader::IfNotGoto); |
431 currentBuffer()->addReference (mark); |
440 currentBuffer()->addReference (mark); |
432 |
441 |
433 // Store it |
442 // Store it |
434 SCOPE (0).mark1 = mark; |
443 SCOPE (0).mark1 = mark; |
435 SCOPE (0).type = SCOPE_If; |
444 SCOPE (0).type = SCOPE_If; |
438 // ============================================================================ |
447 // ============================================================================ |
439 // |
448 // |
440 void BotscriptParser::parseElse() |
449 void BotscriptParser::parseElse() |
441 { |
450 { |
442 checkNotToplevel(); |
451 checkNotToplevel(); |
443 m_lexer->mustGetNext (TK_BraceStart); |
452 m_lexer->mustGetNext (Token::BraceStart); |
444 pushScope (eNoReset); |
453 pushScope (true); |
445 |
454 |
446 if (SCOPE (0).type != SCOPE_If) |
455 if (SCOPE (0).type != SCOPE_If) |
447 error ("else without preceding if"); |
456 error ("else without preceding if"); |
448 |
457 |
449 // write down to jump to the end of the else statement |
458 // write down to jump to the end of the else statement |
450 // Otherwise we have fall-throughs |
459 // Otherwise we have fall-throughs |
451 SCOPE (0).mark2 = currentBuffer()->addMark (""); |
460 SCOPE (0).mark2 = currentBuffer()->addMark (""); |
452 |
461 |
453 // Instruction to jump to the end after if block is complete |
462 // Instruction to jump to the end after if block is complete |
454 currentBuffer()->writeDWord (DH_Goto); |
463 currentBuffer()->writeDWord (DataHeader::Goto); |
455 currentBuffer()->addReference (SCOPE (0).mark2); |
464 currentBuffer()->addReference (SCOPE (0).mark2); |
456 |
465 |
457 // Move the ifnot mark here and set type to else |
466 // Move the ifnot mark here and set type to else |
458 currentBuffer()->adjustMark (SCOPE (0).mark1); |
467 currentBuffer()->adjustMark (SCOPE (0).mark1); |
459 SCOPE (0).type = SCOPE_Else; |
468 SCOPE (0).type = SCOPE_Else; |
472 // the beginning with a go-to statement. |
481 // the beginning with a go-to statement. |
473 ByteMark* mark1 = currentBuffer()->addMark (""); // start |
482 ByteMark* mark1 = currentBuffer()->addMark (""); // start |
474 ByteMark* mark2 = currentBuffer()->addMark (""); // end |
483 ByteMark* mark2 = currentBuffer()->addMark (""); // end |
475 |
484 |
476 // Condition |
485 // Condition |
477 m_lexer->mustGetNext (TK_ParenStart); |
486 m_lexer->mustGetNext (Token::ParenStart); |
478 DataBuffer* expr = parseExpression (TYPE_Int); |
487 DataBuffer* expr = parseExpression (TYPE_Int); |
479 m_lexer->mustGetNext (TK_ParenEnd); |
488 m_lexer->mustGetNext (Token::ParenEnd); |
480 m_lexer->mustGetNext (TK_BraceStart); |
489 m_lexer->mustGetNext (Token::BraceStart); |
481 |
490 |
482 // write condition |
491 // write condition |
483 currentBuffer()->mergeAndDestroy (expr); |
492 currentBuffer()->mergeAndDestroy (expr); |
484 |
493 |
485 // Instruction to go to the end if it fails |
494 // Instruction to go to the end if it fails |
486 currentBuffer()->writeDWord (DH_IfNotGoto); |
495 currentBuffer()->writeDWord (DataHeader::IfNotGoto); |
487 currentBuffer()->addReference (mark2); |
496 currentBuffer()->addReference (mark2); |
488 |
497 |
489 // Store the needed stuff |
498 // Store the needed stuff |
490 SCOPE (0).mark1 = mark1; |
499 SCOPE (0).mark1 = mark1; |
491 SCOPE (0).mark2 = mark2; |
500 SCOPE (0).mark2 = mark2; |
498 { |
507 { |
499 checkNotToplevel(); |
508 checkNotToplevel(); |
500 pushScope(); |
509 pushScope(); |
501 |
510 |
502 // Initializer |
511 // Initializer |
503 m_lexer->mustGetNext (TK_ParenStart); |
512 m_lexer->mustGetNext (Token::ParenStart); |
504 DataBuffer* init = parseStatement(); |
513 DataBuffer* init = parseStatement(); |
505 |
514 |
506 if (init == null) |
515 if (init == null) |
507 error ("bad statement for initializer of for"); |
516 error ("bad statement for initializer of for"); |
508 |
517 |
509 m_lexer->mustGetNext (TK_Semicolon); |
518 m_lexer->mustGetNext (Token::Semicolon); |
510 |
519 |
511 // Condition |
520 // Condition |
512 DataBuffer* cond = parseExpression (TYPE_Int); |
521 DataBuffer* cond = parseExpression (TYPE_Int); |
513 |
522 |
514 if (cond == null) |
523 if (cond == null) |
515 error ("bad statement for condition of for"); |
524 error ("bad statement for condition of for"); |
516 |
525 |
517 m_lexer->mustGetNext (TK_Semicolon); |
526 m_lexer->mustGetNext (Token::Semicolon); |
518 |
527 |
519 // Incrementor |
528 // Incrementor |
520 DataBuffer* incr = parseStatement(); |
529 DataBuffer* incr = parseStatement(); |
521 |
530 |
522 if (incr == null) |
531 if (incr == null) |
523 error ("bad statement for incrementor of for"); |
532 error ("bad statement for incrementor of for"); |
524 |
533 |
525 m_lexer->mustGetNext (TK_ParenEnd); |
534 m_lexer->mustGetNext (Token::ParenEnd); |
526 m_lexer->mustGetNext (TK_BraceStart); |
535 m_lexer->mustGetNext (Token::BraceStart); |
527 |
536 |
528 // First, write out the initializer |
537 // First, write out the initializer |
529 currentBuffer()->mergeAndDestroy (init); |
538 currentBuffer()->mergeAndDestroy (init); |
530 |
539 |
531 // Init two marks |
540 // Init two marks |
532 ByteMark* mark1 = currentBuffer()->addMark (""); |
541 ByteMark* mark1 = currentBuffer()->addMark (""); |
533 ByteMark* mark2 = currentBuffer()->addMark (""); |
542 ByteMark* mark2 = currentBuffer()->addMark (""); |
534 |
543 |
535 // Add the condition |
544 // Add the condition |
536 currentBuffer()->mergeAndDestroy (cond); |
545 currentBuffer()->mergeAndDestroy (cond); |
537 currentBuffer()->writeDWord (DH_IfNotGoto); |
546 currentBuffer()->writeDWord (DataHeader::IfNotGoto); |
538 currentBuffer()->addReference (mark2); |
547 currentBuffer()->addReference (mark2); |
539 |
548 |
540 // Store the marks and incrementor |
549 // Store the marks and incrementor |
541 SCOPE (0).mark1 = mark1; |
550 SCOPE (0).mark1 = mark1; |
542 SCOPE (0).mark2 = mark2; |
551 SCOPE (0).mark2 = mark2; |
591 if (SCOPE (0).type != SCOPE_Switch) |
600 if (SCOPE (0).type != SCOPE_Switch) |
592 error ("case label outside switch"); |
601 error ("case label outside switch"); |
593 |
602 |
594 // Get a literal value for the case block. Zandronum does not support |
603 // Get a literal value for the case block. Zandronum does not support |
595 // expressions here. |
604 // expressions here. |
596 m_lexer->mustGetNext (TK_Number); |
605 m_lexer->mustGetNext (Token::Number); |
597 int num = m_lexer->token()->text.toLong(); |
606 int num = m_lexer->token()->text.toLong(); |
598 m_lexer->mustGetNext (TK_Colon); |
607 m_lexer->mustGetNext (Token::Colon); |
599 |
608 |
600 for (const CaseInfo& info : SCOPE(0).cases) |
609 for (const CaseInfo& info : SCOPE(0).cases) |
|
610 { |
601 if (info.number == num) |
611 if (info.number == num) |
602 error ("multiple case %1 labels in one switch", num); |
612 error ("multiple case %1 labels in one switch", num); |
|
613 } |
603 |
614 |
604 // Write down the expression and case-go-to. This builds |
615 // Write down the expression and case-go-to. This builds |
605 // the case tree. The closing event will write the actual |
616 // the case tree. The closing event will write the actual |
606 // blocks and move the marks appropriately. |
617 // blocks and move the marks appropriately. |
607 // |
618 // |
626 error ("default label outside switch"); |
637 error ("default label outside switch"); |
627 |
638 |
628 if (SCOPE (0).buffer1 != null) |
639 if (SCOPE (0).buffer1 != null) |
629 error ("multiple default labels in one switch"); |
640 error ("multiple default labels in one switch"); |
630 |
641 |
631 m_lexer->mustGetNext (TK_Colon); |
642 m_lexer->mustGetNext (Token::Colon); |
632 |
643 |
633 // The default header is buffered into buffer1, since |
644 // The default header is buffered into buffer1, since |
634 // it has to be the last of the case headers |
645 // it has to be the last of the case headers |
635 // |
646 // |
636 // Since the expression is pushed into the switch |
647 // Since the expression is pushed into the switch |
637 // and is only popped when case succeeds, we have |
648 // and is only popped when case succeeds, we have |
638 // to pop it with DH_Drop manually if we end up in |
649 // to pop it with DataHeader::Drop manually if we end up in |
639 // a default. |
650 // a default. |
640 DataBuffer* buf = new DataBuffer; |
651 DataBuffer* buf = new DataBuffer; |
641 SCOPE (0).buffer1 = buf; |
652 SCOPE (0).buffer1 = buf; |
642 buf->writeDWord (DH_Drop); |
653 buf->writeDWord (DataHeader::Drop); |
643 buf->writeDWord (DH_Goto); |
654 buf->writeDWord (DataHeader::Goto); |
644 addSwitchCase (buf); |
655 addSwitchCase (buf); |
645 } |
656 } |
646 |
657 |
647 // ============================================================================ |
658 // ============================================================================ |
648 // |
659 // |
649 void BotscriptParser::parseBreak() |
660 void BotscriptParser::parseBreak() |
650 { |
661 { |
651 if (m_scopeCursor == 0) |
662 if (m_scopeCursor == 0) |
652 error ("unexpected `break`"); |
663 error ("unexpected `break`"); |
653 |
664 |
654 currentBuffer()->writeDWord (DH_Goto); |
665 currentBuffer()->writeDWord (DataHeader::Goto); |
655 |
666 |
656 // switch and if use mark1 for the closing point, |
667 // switch and if use mark1 for the closing point, |
657 // for and while use mark2. |
668 // for and while use mark2. |
658 switch (SCOPE (0).type) |
669 switch (SCOPE (0).type) |
659 { |
670 { |
660 case SCOPE_If: |
671 case SCOPE_If: |
661 case SCOPE_Switch: |
672 case SCOPE_Switch: |
662 { |
|
663 currentBuffer()->addReference (SCOPE (0).mark1); |
673 currentBuffer()->addReference (SCOPE (0).mark1); |
664 } break; |
674 break; |
665 |
675 |
666 case SCOPE_For: |
676 case SCOPE_For: |
667 case SCOPE_While: |
677 case SCOPE_While: |
668 { |
|
669 currentBuffer()->addReference (SCOPE (0).mark2); |
678 currentBuffer()->addReference (SCOPE (0).mark2); |
670 } break; |
679 break; |
671 |
680 |
672 default: |
681 default: |
673 { |
|
674 error ("unexpected `break`"); |
682 error ("unexpected `break`"); |
675 } break; |
683 break; |
676 } |
684 } |
677 |
685 |
678 m_lexer->mustGetNext (TK_Semicolon); |
686 m_lexer->mustGetNext (Token::Semicolon); |
679 } |
687 } |
680 |
688 |
681 // ============================================================================ |
689 // ============================================================================ |
682 // |
690 // |
683 void BotscriptParser::parseContinue() |
691 void BotscriptParser::parseContinue() |
684 { |
692 { |
685 m_lexer->mustGetNext (TK_Semicolon); |
693 m_lexer->mustGetNext (Token::Semicolon); |
686 |
694 |
687 int curs; |
695 int curs; |
688 bool found = false; |
696 bool found = false; |
689 |
697 |
690 // Fall through the scope until we find a loop block |
698 // Fall through the scope until we find a loop block |
691 for (curs = m_scopeCursor; curs > 0 && !found; curs--) |
699 for (curs = m_scopeCursor; curs > 0 and !found; curs--) |
692 { |
700 { |
693 switch (m_scopeStack[curs].type) |
701 switch (m_scopeStack[curs].type) |
694 { |
702 { |
695 case SCOPE_For: |
703 case SCOPE_For: |
696 case SCOPE_While: |
704 case SCOPE_While: |
697 case SCOPE_Do: |
705 case SCOPE_Do: |
698 { |
706 currentBuffer()->writeDWord (DataHeader::Goto); |
699 currentBuffer()->writeDWord (DH_Goto); |
|
700 currentBuffer()->addReference (m_scopeStack[curs].mark1); |
707 currentBuffer()->addReference (m_scopeStack[curs].mark1); |
701 found = true; |
708 found = true; |
702 } break; |
709 break; |
703 |
710 |
704 default: |
711 default: |
705 break; |
712 break; |
706 } |
713 } |
707 } |
714 } |
743 { // write the incrementor at the end of the loop block |
750 { // write the incrementor at the end of the loop block |
744 currentBuffer()->mergeAndDestroy (SCOPE (0).buffer1); |
751 currentBuffer()->mergeAndDestroy (SCOPE (0).buffer1); |
745 } |
752 } |
746 case SCOPE_While: |
753 case SCOPE_While: |
747 { // write down the instruction to go back to the start of the loop |
754 { // write down the instruction to go back to the start of the loop |
748 currentBuffer()->writeDWord (DH_Goto); |
755 currentBuffer()->writeDWord (DataHeader::Goto); |
749 currentBuffer()->addReference (SCOPE (0).mark1); |
756 currentBuffer()->addReference (SCOPE (0).mark1); |
750 |
757 |
751 // Move the closing mark here since we're at the end of the while loop |
758 // Move the closing mark here since we're at the end of the while loop |
752 currentBuffer()->adjustMark (SCOPE (0).mark2); |
759 currentBuffer()->adjustMark (SCOPE (0).mark2); |
753 break; |
760 break; |
754 } |
761 } |
755 |
762 |
756 case SCOPE_Do: |
763 case SCOPE_Do: |
757 { |
764 { |
758 m_lexer->mustGetNext (TK_While); |
765 m_lexer->mustGetNext (Token::While); |
759 m_lexer->mustGetNext (TK_ParenStart); |
766 m_lexer->mustGetNext (Token::ParenStart); |
760 DataBuffer* expr = parseExpression (TYPE_Int); |
767 DataBuffer* expr = parseExpression (TYPE_Int); |
761 m_lexer->mustGetNext (TK_ParenEnd); |
768 m_lexer->mustGetNext (Token::ParenEnd); |
762 m_lexer->mustGetNext (TK_Semicolon); |
769 m_lexer->mustGetNext (Token::Semicolon); |
763 |
770 |
764 // If the condition runs true, go back to the start. |
771 // If the condition runs true, go back to the start. |
765 currentBuffer()->mergeAndDestroy (expr); |
772 currentBuffer()->mergeAndDestroy (expr); |
766 currentBuffer()->writeDWord (DH_IfGoto); |
773 currentBuffer()->writeDWord (DataHeader::IfGoto); |
767 currentBuffer()->addReference (SCOPE (0).mark1); |
774 currentBuffer()->addReference (SCOPE (0).mark1); |
768 break; |
775 break; |
769 } |
776 } |
770 |
777 |
771 case SCOPE_Switch: |
778 case SCOPE_Switch: |
809 // Descend down the stack |
816 // Descend down the stack |
810 m_scopeCursor--; |
817 m_scopeCursor--; |
811 return; |
818 return; |
812 } |
819 } |
813 |
820 |
814 int dataheader = (m_currentMode == PARSERMODE_Event) ? DH_EndEvent : |
821 int dataheader = (m_currentMode == PARSERMODE_Event) ? DataHeader::EndEvent |
815 (m_currentMode == PARSERMODE_MainLoop) ? DH_EndMainLoop : |
822 : (m_currentMode == PARSERMODE_MainLoop) ? DataHeader::EndMainLoop |
816 (m_currentMode == PARSERMODE_Onenter) ? DH_EndOnEnter : |
823 : (m_currentMode == PARSERMODE_Onenter) ? DataHeader::EndOnEnter |
817 (m_currentMode == PARSERMODE_Onexit) ? DH_EndOnExit : -1; |
824 : (m_currentMode == PARSERMODE_Onexit) ? DataHeader::EndOnExit |
|
825 : -1; |
818 |
826 |
819 if (dataheader == -1) |
827 if (dataheader == -1) |
820 error ("unexpected `}`"); |
828 error ("unexpected `}`"); |
821 |
829 |
822 // Data header must be written before mode is changed because |
830 // Data header must be written before mode is changed because |
823 // onenter and mainloop go into special buffers, and we want |
831 // onenter and mainloop go into special buffers, and we want |
824 // the closing data headers into said buffers too. |
832 // the closing data headers into said buffers too. |
825 currentBuffer()->writeDWord (dataheader); |
833 currentBuffer()->writeDWord (dataheader); |
826 m_currentMode = PARSERMODE_TopLevel; |
834 m_currentMode = PARSERMODE_TopLevel; |
827 m_lexer->next (TK_Semicolon); |
835 m_lexer->next (Token::Semicolon); |
828 } |
836 } |
829 |
837 |
830 // ============================================================================= |
838 // ============================================================================= |
831 // |
839 // |
832 void BotscriptParser::parseEventdef() |
840 void BotscriptParser::parseEventdef() |
833 { |
841 { |
834 EventDefinition* e = new EventDefinition; |
842 EventDefinition* e = new EventDefinition; |
835 |
843 |
836 m_lexer->mustGetNext (TK_Number); |
844 m_lexer->mustGetNext (Token::Number); |
837 e->number = getTokenString().toLong(); |
845 e->number = getTokenString().toLong(); |
838 m_lexer->mustGetNext (TK_Colon); |
846 m_lexer->mustGetNext (Token::Colon); |
839 m_lexer->mustGetNext (TK_Symbol); |
847 m_lexer->mustGetNext (Token::Symbol); |
840 e->name = m_lexer->token()->text; |
848 e->name = m_lexer->token()->text; |
841 m_lexer->mustGetNext (TK_ParenStart); |
849 m_lexer->mustGetNext (Token::ParenStart); |
842 m_lexer->mustGetNext (TK_ParenEnd); |
850 m_lexer->mustGetNext (Token::ParenEnd); |
843 m_lexer->mustGetNext (TK_Semicolon); |
851 m_lexer->mustGetNext (Token::Semicolon); |
844 addEvent (e); |
852 addEvent (e); |
845 } |
853 } |
846 |
854 |
847 // ============================================================================= |
855 // ============================================================================= |
848 // |
856 // |
850 { |
858 { |
851 CommandInfo* comm = new CommandInfo; |
859 CommandInfo* comm = new CommandInfo; |
852 comm->origin = m_lexer->describeCurrentPosition(); |
860 comm->origin = m_lexer->describeCurrentPosition(); |
853 |
861 |
854 // Return value |
862 // Return value |
855 m_lexer->mustGetAnyOf ({TK_Int,TK_Void,TK_Bool,TK_Str}); |
863 m_lexer->mustGetAnyOf ({Token::Int,Token::Void,Token::Bool,Token::Str}); |
856 comm->returnvalue = getTypeByName (m_lexer->token()->text); // TODO |
864 comm->returnvalue = getTypeByName (m_lexer->token()->text); // TODO |
857 ASSERT_NE (comm->returnvalue, -1); |
865 ASSERT_NE (comm->returnvalue, -1); |
858 |
866 |
859 // Number |
867 // Number |
860 m_lexer->mustGetNext (TK_Number); |
868 m_lexer->mustGetNext (Token::Number); |
861 comm->number = m_lexer->token()->text.toLong(); |
869 comm->number = m_lexer->token()->text.toLong(); |
862 m_lexer->mustGetNext (TK_Colon); |
870 m_lexer->mustGetNext (Token::Colon); |
863 |
871 |
864 // Name |
872 // Name |
865 m_lexer->mustGetNext (TK_Symbol); |
873 m_lexer->mustGetNext (Token::Symbol); |
866 comm->name = m_lexer->token()->text; |
874 comm->name = m_lexer->token()->text; |
867 |
875 |
868 // Arguments |
876 // Arguments |
869 m_lexer->mustGetNext (TK_ParenStart); |
877 m_lexer->mustGetNext (Token::ParenStart); |
870 comm->minargs = 0; |
878 comm->minargs = 0; |
871 |
879 |
872 while (m_lexer->peekNextType (TK_ParenEnd) == false) |
880 while (m_lexer->peekNextType (Token::ParenEnd) == false) |
873 { |
881 { |
874 if (comm->args.isEmpty() == false) |
882 if (comm->args.isEmpty() == false) |
875 m_lexer->mustGetNext (TK_Comma); |
883 m_lexer->mustGetNext (Token::Comma); |
876 |
884 |
877 CommandArgument arg; |
885 CommandArgument arg; |
878 m_lexer->mustGetAnyOf ({TK_Int,TK_Bool,TK_Str}); |
886 m_lexer->mustGetAnyOf ({Token::Int,Token::Bool,Token::Str}); |
879 DataType type = getTypeByName (m_lexer->token()->text); // TODO |
887 DataType type = getTypeByName (m_lexer->token()->text); // TODO |
880 ASSERT_NE (type, -1) |
888 ASSERT_NE (type, -1) |
881 ASSERT_NE (type, TYPE_Void) |
889 ASSERT_NE (type, TYPE_Void) |
882 arg.type = type; |
890 arg.type = type; |
883 |
891 |
884 m_lexer->mustGetNext (TK_Symbol); |
892 m_lexer->mustGetNext (Token::Symbol); |
885 arg.name = m_lexer->token()->text; |
893 arg.name = m_lexer->token()->text; |
886 |
894 |
887 // If this is an optional parameter, we need the default value. |
895 // If this is an optional parameter, we need the default value. |
888 if (comm->minargs < comm->args.size() || m_lexer->peekNextType (TK_Assign)) |
896 if (comm->minargs < comm->args.size() or m_lexer->peekNextType (Token::Assign)) |
889 { |
897 { |
890 m_lexer->mustGetNext (TK_Assign); |
898 m_lexer->mustGetNext (Token::Assign); |
891 |
899 |
892 switch (type) |
900 switch (type) |
893 { |
901 { |
894 case TYPE_Int: |
902 case TYPE_Int: |
895 case TYPE_Bool: |
903 case TYPE_Bool: |
896 m_lexer->mustGetNext (TK_Number); |
904 m_lexer->mustGetNext (Token::Number); |
897 break; |
905 break; |
898 |
906 |
899 case TYPE_String: |
907 case TYPE_String: |
900 error ("string arguments cannot have default values"); |
908 error ("string arguments cannot have default values"); |
901 |
909 |
925 { |
933 { |
926 checkToplevel(); |
934 checkToplevel(); |
927 m_lexer->mustGetSymbol ("zandronum"); |
935 m_lexer->mustGetSymbol ("zandronum"); |
928 String versionText; |
936 String versionText; |
929 |
937 |
930 while (m_lexer->next() && (m_lexer->tokenType() == TK_Number || m_lexer->tokenType() == TK_Dot)) |
938 while (m_lexer->next() and (m_lexer->tokenType() == Token::Number or m_lexer->tokenType() == Token::Dot)) |
931 versionText += getTokenString(); |
939 versionText += getTokenString(); |
932 |
940 |
933 // Note: at this point the lexer's pointing at the token after the version. |
941 // Note: at this point the lexer's pointing at the token after the version. |
934 if (versionText.isEmpty()) |
942 if (versionText.isEmpty()) |
935 error ("expected version string, got `%1`", getTokenString()); |
943 error ("expected version string, got `%1`", getTokenString()); |
|
944 |
936 if (g_validZandronumVersions.contains (versionText) == false) |
945 if (g_validZandronumVersions.contains (versionText) == false) |
937 error ("unknown version string `%2`: valid versions: `%1`\n", g_validZandronumVersions, versionText); |
946 error ("unknown version string `%2`: valid versions: `%1`\n", g_validZandronumVersions, versionText); |
938 |
947 |
939 StringList versionTokens = versionText.split ("."); |
948 StringList versionTokens = versionText.split ("."); |
940 m_zandronumVersion = versionTokens[0].toLong() * 10000 + versionTokens[1].toLong() * 100; |
949 m_zandronumVersion = versionTokens[0].toLong() * 10000 + versionTokens[1].toLong() * 100; |
941 m_defaultZandronumVersion = false; |
950 m_defaultZandronumVersion = false; |
942 m_lexer->tokenMustBe (TK_Semicolon); |
951 m_lexer->tokenMustBe (Token::Semicolon); |
943 } |
952 } |
944 |
953 |
945 // ============================================================================/ |
954 // ============================================================================/ |
946 // |
955 // |
947 // Parses a command call |
956 // Parses a command call |
948 // |
957 // |
949 DataBuffer* BotscriptParser::parseCommand (CommandInfo* comm) |
958 DataBuffer* BotscriptParser::parseCommand (CommandInfo* comm) |
950 { |
959 { |
951 DataBuffer* r = new DataBuffer (64); |
960 DataBuffer* r = new DataBuffer (64); |
952 |
961 |
953 if (m_currentMode == PARSERMODE_TopLevel && comm->returnvalue == TYPE_Void) |
962 if (m_currentMode == PARSERMODE_TopLevel and comm->returnvalue == TYPE_Void) |
954 error ("command call at top level"); |
963 error ("command call at top level"); |
955 |
964 |
956 m_lexer->mustGetNext (TK_ParenStart); |
965 m_lexer->mustGetNext (Token::ParenStart); |
957 m_lexer->mustGetNext (TK_Any); |
966 m_lexer->mustGetNext (Token::Any); |
958 |
967 |
959 int curarg = 0; |
968 int curarg = 0; |
960 |
969 |
961 for (;;) |
970 for (;;) |
962 { |
971 { |
963 if (tokenIs (TK_ParenEnd)) |
972 if (tokenIs (Token::ParenEnd)) |
964 { |
973 { |
965 if (curarg < comm->minargs) |
974 if (curarg < comm->minargs) |
|
975 { |
966 error ("too few arguments passed to %1\n\tusage is: %2", |
976 error ("too few arguments passed to %1\n\tusage is: %2", |
967 comm->name, comm->signature()); |
977 comm->name, comm->signature()); |
|
978 } |
968 |
979 |
969 break; |
980 break; |
970 } |
981 } |
971 |
982 |
972 if (curarg >= comm->args.size()) |
983 if (curarg >= comm->args.size()) |
973 error ("too many arguments (%3) passed to %1\n\tusage is: %2", |
984 error ("too many arguments (%3) passed to %1\n\tusage is: %2", |
974 comm->name, comm->signature()); |
985 comm->name, comm->signature()); |
975 |
986 |
976 r->mergeAndDestroy (parseExpression (comm->args[curarg].type, true)); |
987 r->mergeAndDestroy (parseExpression (comm->args[curarg].type, true)); |
977 m_lexer->mustGetNext (TK_Any); |
988 m_lexer->mustGetNext (Token::Any); |
978 |
989 |
979 if (curarg < comm->minargs - 1) |
990 if (curarg < comm->minargs - 1) |
980 { |
991 { |
981 m_lexer->tokenMustBe (TK_Comma); |
992 m_lexer->tokenMustBe (Token::Comma); |
982 m_lexer->mustGetNext (TK_Any); |
993 m_lexer->mustGetNext (Token::Any); |
983 } |
994 } |
984 else if (curarg < comm->args.size() - 1) |
995 else if (curarg < comm->args.size() - 1) |
985 { |
996 { |
986 // Can continue, but can terminate as well. |
997 // Can continue, but can terminate as well. |
987 if (tokenIs (TK_ParenEnd)) |
998 if (tokenIs (Token::ParenEnd)) |
988 { |
999 { |
989 curarg++; |
1000 curarg++; |
990 break; |
1001 break; |
991 } |
1002 } |
992 else |
1003 else |
993 { |
1004 { |
994 m_lexer->tokenMustBe (TK_Comma); |
1005 m_lexer->tokenMustBe (Token::Comma); |
995 m_lexer->mustGetNext (TK_Any); |
1006 m_lexer->mustGetNext (Token::Any); |
996 } |
1007 } |
997 } |
1008 } |
998 |
1009 |
999 curarg++; |
1010 curarg++; |
1000 } |
1011 } |
1001 |
1012 |
1002 // If the script skipped any optional arguments, fill in defaults. |
1013 // If the script skipped any optional arguments, fill in defaults. |
1003 while (curarg < comm->args.size()) |
1014 while (curarg < comm->args.size()) |
1004 { |
1015 { |
1005 r->writeDWord (DH_PushNumber); |
1016 r->writeDWord (DataHeader::PushNumber); |
1006 r->writeDWord (comm->args[curarg].defvalue); |
1017 r->writeDWord (comm->args[curarg].defvalue); |
1007 curarg++; |
1018 curarg++; |
1008 } |
1019 } |
1009 |
1020 |
1010 r->writeDWord (DH_Command); |
1021 r->writeDWord (DataHeader::Command); |
1011 r->writeDWord (comm->number); |
1022 r->writeDWord (comm->number); |
1012 r->writeDWord (comm->args.size()); |
1023 r->writeDWord (comm->args.size()); |
1013 |
1024 |
1014 return r; |
1025 return r; |
1015 } |
1026 } |
1016 |
1027 |
1017 // ============================================================================ |
1028 // ============================================================================ |
1018 // |
1029 // |
1019 String BotscriptParser::parseFloat() |
1030 String BotscriptParser::parseFloat() |
1020 { |
1031 { |
1021 m_lexer->tokenMustBe (TK_Number); |
1032 m_lexer->tokenMustBe (Token::Number); |
1022 String floatstring = getTokenString(); |
1033 String floatstring = getTokenString(); |
1023 Lexer::TokenInfo tok; |
1034 Lexer::TokenInfo tok; |
1024 |
1035 |
1025 // Go after the decimal point |
1036 // Go after the decimal point |
1026 if (m_lexer->peekNext (&tok) && tok.type ==TK_Dot) |
1037 if (m_lexer->peekNext (&tok) and tok.type ==Token::Dot) |
1027 { |
1038 { |
1028 m_lexer->skip(); |
1039 m_lexer->skip(); |
1029 m_lexer->mustGetNext (TK_Number); |
1040 m_lexer->mustGetNext (Token::Number); |
1030 floatstring += "."; |
1041 floatstring += "."; |
1031 floatstring += getTokenString(); |
1042 floatstring += getTokenString(); |
1032 } |
1043 } |
1033 |
1044 |
1034 return floatstring; |
1045 return floatstring; |
1038 // |
1049 // |
1039 // Parses an assignment operator. |
1050 // Parses an assignment operator. |
1040 // |
1051 // |
1041 AssignmentOperator BotscriptParser::parseAssignmentOperator() |
1052 AssignmentOperator BotscriptParser::parseAssignmentOperator() |
1042 { |
1053 { |
1043 const List<ETokenType> tokens = |
1054 const List<Token> tokens = |
1044 { |
1055 { |
1045 TK_Assign, |
1056 Token::Assign, |
1046 TK_AddAssign, |
1057 Token::AddAssign, |
1047 TK_SubAssign, |
1058 Token::SubAssign, |
1048 TK_MultiplyAssign, |
1059 Token::MultiplyAssign, |
1049 TK_DivideAssign, |
1060 Token::DivideAssign, |
1050 TK_ModulusAssign, |
1061 Token::ModulusAssign, |
1051 TK_DoublePlus, |
1062 Token::DoublePlus, |
1052 TK_DoubleMinus, |
1063 Token::DoubleMinus, |
1053 }; |
1064 }; |
1054 |
1065 |
1055 m_lexer->mustGetAnyOf (tokens); |
1066 m_lexer->mustGetAnyOf (tokens); |
1056 |
1067 |
1057 switch (m_lexer->tokenType()) |
1068 switch (m_lexer->tokenType()) |
1058 { |
1069 { |
1059 case TK_Assign: return ASSIGNOP_Assign; |
1070 case Token::Assign: return ASSIGNOP_Assign; |
1060 case TK_AddAssign: return ASSIGNOP_Add; |
1071 case Token::AddAssign: return ASSIGNOP_Add; |
1061 case TK_SubAssign: return ASSIGNOP_Subtract; |
1072 case Token::SubAssign: return ASSIGNOP_Subtract; |
1062 case TK_MultiplyAssign: return ASSIGNOP_Multiply; |
1073 case Token::MultiplyAssign: return ASSIGNOP_Multiply; |
1063 case TK_DivideAssign: return ASSIGNOP_Divide; |
1074 case Token::DivideAssign: return ASSIGNOP_Divide; |
1064 case TK_ModulusAssign: return ASSIGNOP_Modulus; |
1075 case Token::ModulusAssign: return ASSIGNOP_Modulus; |
1065 case TK_DoublePlus: return ASSIGNOP_Increase; |
1076 case Token::DoublePlus: return ASSIGNOP_Increase; |
1066 case TK_DoubleMinus: return ASSIGNOP_Decrease; |
1077 case Token::DoubleMinus: return ASSIGNOP_Decrease; |
1067 default: break; |
1078 default: break; |
1068 } |
1079 } |
1069 |
1080 |
1070 error ("WTF bad operator token %1", m_lexer->describeToken (m_lexer->token())); |
1081 error ("WTF bad operator token %1", m_lexer->describeToken (m_lexer->token())); |
1071 return (AssignmentOperator) 0; |
1082 return (AssignmentOperator) 0; |
1081 DataHeader array; |
1092 DataHeader array; |
1082 }; |
1093 }; |
1083 |
1094 |
1084 const AssignmentDataHeaderInfo gAssignmentDataHeaders[] = |
1095 const AssignmentDataHeaderInfo gAssignmentDataHeaders[] = |
1085 { |
1096 { |
1086 { ASSIGNOP_Assign, DH_AssignLocalVar, DH_AssignGlobalVar, DH_AssignGlobalArray }, |
1097 { ASSIGNOP_Assign, DataHeader::AssignLocalVar, DataHeader::AssignGlobalVar, |
1087 { ASSIGNOP_Add, DH_AddLocalVar, DH_AddGlobalVar, DH_AddGlobalArray }, |
1098 DataHeader::AssignGlobalArray }, |
1088 { ASSIGNOP_Subtract, DH_SubtractLocalVar, DH_SubtractGlobalVar, DH_SubtractGlobalArray }, |
1099 { ASSIGNOP_Add, DataHeader::AddLocalVar, DataHeader::AddGlobalVar, |
1089 { ASSIGNOP_Multiply, DH_MultiplyLocalVar, DH_MultiplyGlobalVar, DH_MultiplyGlobalArray }, |
1100 DataHeader::AddGlobalArray }, |
1090 { ASSIGNOP_Divide, DH_DivideLocalVar, DH_DivideGlobalVar, DH_DivideGlobalArray }, |
1101 { ASSIGNOP_Subtract, DataHeader::SubtractLocalVar, DataHeader::SubtractGlobalVar, |
1091 { ASSIGNOP_Modulus, DH_ModLocalVar, DH_ModGlobalVar, DH_ModGlobalArray }, |
1102 DataHeader::SubtractGlobalArray }, |
1092 { ASSIGNOP_Increase, DH_IncreaseLocalVar, DH_IncreaseGlobalVar, DH_IncreaseGlobalArray }, |
1103 { ASSIGNOP_Multiply, DataHeader::MultiplyLocalVar, DataHeader::MultiplyGlobalVar, |
1093 { ASSIGNOP_Decrease, DH_DecreaseLocalVar, DH_DecreaseGlobalVar, DH_DecreaseGlobalArray }, |
1104 DataHeader::MultiplyGlobalArray }, |
|
1105 { ASSIGNOP_Divide, DataHeader::DivideLocalVar, DataHeader::DivideGlobalVar, |
|
1106 DataHeader::DivideGlobalArray }, |
|
1107 { ASSIGNOP_Modulus, DataHeader::ModLocalVar, DataHeader::ModGlobalVar, |
|
1108 DataHeader::ModGlobalArray }, |
|
1109 { ASSIGNOP_Increase, DataHeader::IncreaseLocalVar, DataHeader::IncreaseGlobalVar, |
|
1110 DataHeader::IncreaseGlobalArray }, |
|
1111 { ASSIGNOP_Decrease, DataHeader::DecreaseLocalVar, DataHeader::DecreaseGlobalVar, |
|
1112 DataHeader::DecreaseGlobalArray }, |
1094 }; |
1113 }; |
1095 |
1114 |
1096 DataHeader BotscriptParser::getAssigmentDataHeader (AssignmentOperator op, Variable* var) |
1115 DataHeader BotscriptParser::getAssigmentDataHeader (AssignmentOperator op, Variable* var) |
1097 { |
1116 { |
1098 for (const auto& a : gAssignmentDataHeaders) |
1117 for (const auto& a : gAssignmentDataHeaders) |
1144 |
1163 |
1145 if (var->isarray) |
1164 if (var->isarray) |
1146 retbuf->mergeAndDestroy (arrayindex); |
1165 retbuf->mergeAndDestroy (arrayindex); |
1147 |
1166 |
1148 // Parse the right operand |
1167 // Parse the right operand |
1149 if (oper != ASSIGNOP_Increase && oper != ASSIGNOP_Decrease) |
1168 if (oper != ASSIGNOP_Increase and oper != ASSIGNOP_Decrease) |
1150 { |
1169 { |
1151 DataBuffer* expr = parseExpression (var->type); |
1170 DataBuffer* expr = parseExpression (var->type); |
1152 retbuf->mergeAndDestroy (expr); |
1171 retbuf->mergeAndDestroy (expr); |
1153 } |
1172 } |
1154 |
1173 |
1155 #if 0 |
1174 #if 0 |
1156 // <<= and >>= do not have data headers. Solution: expand them. |
1175 // <<= and >>= do not have data headers. Solution: expand them. |
1157 // a <<= b -> a = a << b |
1176 // a <<= b -> a = a << b |
1158 // a >>= b -> a = a >> b |
1177 // a >>= b -> a = a >> b |
1159 retbuf->WriteDWord (var->IsGlobal() ? DH_PushGlobalVar : DH_PushLocalVar); |
1178 retbuf->WriteDWord (var->IsGlobal() ? DataHeader::PushGlobalVar : DataHeader::PushLocalVar); |
1160 retbuf->WriteDWord (var->index); |
1179 retbuf->WriteDWord (var->index); |
1161 retbuf->MergeAndDestroy (expr); |
1180 retbuf->MergeAndDestroy (expr); |
1162 retbuf->WriteDWord ((oper == OPER_ASSIGNLEFTSHIFT) ? DH_LeftShift : DH_RightShift); |
1181 retbuf->WriteDWord ((oper == OPER_ASSIGNLEFTSHIFT) ? DataHeader::LeftShift : |
1163 retbuf->WriteDWord (var->IsGlobal() ? DH_AssignGlobalVar : DH_AssignLocalVar); |
1182 DataHeader::RightShift); |
|
1183 retbuf->WriteDWord (var->IsGlobal() ? DataHeader::AssignGlobalVar : DataHeader::AssignLocalVar); |
1164 retbuf->WriteDWord (var->index); |
1184 retbuf->WriteDWord (var->index); |
1165 #endif |
1185 #endif |
1166 |
1186 |
1167 DataHeader dh = getAssigmentDataHeader (oper, var); |
1187 DataHeader dh = getAssigmentDataHeader (oper, var); |
1168 retbuf->writeDWord (dh); |
1188 retbuf->writeDWord (dh); |
1358 if (fp == null) |
1378 if (fp == null) |
1359 error ("couldn't open %1 for writing: %2", outfile, strerror (errno)); |
1379 error ("couldn't open %1 for writing: %2", outfile, strerror (errno)); |
1360 |
1380 |
1361 // First, resolve references |
1381 // First, resolve references |
1362 for (MarkReference* ref : m_mainBuffer->references()) |
1382 for (MarkReference* ref : m_mainBuffer->references()) |
|
1383 { |
1363 for (int i = 0; i < 4; ++i) |
1384 for (int i = 0; i < 4; ++i) |
1364 m_mainBuffer->buffer()[ref->pos + i] = (ref->target->pos >> (8 * i)) & 0xFF; |
1385 m_mainBuffer->buffer()[ref->pos + i] = (ref->target->pos >> (8 * i)) & 0xFF; |
|
1386 } |
1365 |
1387 |
1366 // Then, dump the main buffer to the file |
1388 // Then, dump the main buffer to the file |
1367 fwrite (m_mainBuffer->buffer(), 1, m_mainBuffer->writtenSize(), fp); |
1389 fwrite (m_mainBuffer->buffer(), 1, m_mainBuffer->writtenSize(), fp); |
1368 print ("-- %1 byte%s1 written to %2\n", m_mainBuffer->writtenSize(), outfile); |
1390 print ("-- %1 byte%s1 written to %2\n", m_mainBuffer->writtenSize(), outfile); |
1369 fclose (fp); |
1391 fclose (fp); |