51 |
51 |
52 // ============================================================================ |
52 // ============================================================================ |
53 // |
53 // |
54 void botscript_parser::check_toplevel() |
54 void botscript_parser::check_toplevel() |
55 { |
55 { |
56 if (m_current_mode != MODE_TOPLEVEL) |
56 if (m_current_mode != e_top_level_mode) |
57 error ("%1-statements may only be defined at top level!", token_string()); |
57 error ("%1-statements may only be defined at top level!", token_string()); |
58 } |
58 } |
59 |
59 |
60 // ============================================================================ |
60 // ============================================================================ |
61 // |
61 // |
62 void botscript_parser::check_not_toplevel() |
62 void botscript_parser::check_not_toplevel() |
63 { |
63 { |
64 if (m_current_mode == MODE_TOPLEVEL) |
64 if (m_current_mode == e_top_level_mode) |
65 error ("%1-statements must not be defined at top level!", token_string()); |
65 error ("%1-statements must not be defined at top level!", token_string()); |
66 } |
66 } |
67 |
67 |
68 // ============================================================================ |
68 // ============================================================================ |
69 // Main parser code. Begins read of the script file, checks the syntax of it |
69 // Main parser code. Begins read of the script file, checks the syntax of it |
72 void botscript_parser::parse_botscript (string file_name) |
72 void botscript_parser::parse_botscript (string file_name) |
73 { |
73 { |
74 // Lex and preprocess the file |
74 // Lex and preprocess the file |
75 m_lx->process_file (file_name); |
75 m_lx->process_file (file_name); |
76 |
76 |
77 m_current_mode = MODE_TOPLEVEL; |
77 m_current_mode = e_top_level_mode; |
78 m_num_states = 0; |
78 m_num_states = 0; |
79 m_num_events = 0; |
79 m_num_events = 0; |
80 m_scope_cursor = 0; |
80 m_scope_cursor = 0; |
81 m_state_spawn_defined = false; |
81 m_state_spawn_defined = false; |
82 m_got_main_loop = false; |
82 m_got_main_loop = false; |
218 } |
218 } |
219 } |
219 } |
220 |
220 |
221 // =============================================================================== |
221 // =============================================================================== |
222 // Script file ended. Do some last checks and write the last things to main buffer |
222 // Script file ended. Do some last checks and write the last things to main buffer |
223 if (m_current_mode != MODE_TOPLEVEL) |
223 if (m_current_mode != e_top_level_mode) |
224 error ("script did not end at top level; a `}` is missing somewhere"); |
224 error ("script did not end at top level; a `}` is missing somewhere"); |
225 |
225 |
226 // stateSpawn must be defined! |
226 // stateSpawn must be defined! |
227 if (!m_state_spawn_defined) |
227 if (!m_state_spawn_defined) |
228 error ("script must have a state named `stateSpawn`!"); |
228 error ("script must have a state named `stateSpawn`!"); |
291 |
291 |
292 if (!e) |
292 if (!e) |
293 error ("bad event, got `%1`\n", token_string()); |
293 error ("bad event, got `%1`\n", token_string()); |
294 |
294 |
295 m_lx->must_get_next (tk_brace_start); |
295 m_lx->must_get_next (tk_brace_start); |
296 m_current_mode = MODE_EVENT; |
296 m_current_mode = e_event_mode; |
297 buffer()->write_dword (dh_event); |
297 buffer()->write_dword (dh_event); |
298 buffer()->write_dword (e->number); |
298 buffer()->write_dword (e->number); |
299 m_num_events++; |
299 m_num_events++; |
300 } |
300 } |
301 |
301 |
304 void botscript_parser::parse_mainloop() |
304 void botscript_parser::parse_mainloop() |
305 { |
305 { |
306 check_toplevel(); |
306 check_toplevel(); |
307 m_lx->must_get_next (tk_brace_start); |
307 m_lx->must_get_next (tk_brace_start); |
308 |
308 |
309 m_current_mode = MODE_MAINLOOP; |
309 m_current_mode = e_main_loop_mode; |
310 m_main_loop_buffer->write_dword (dh_main_loop); |
310 m_main_loop_buffer->write_dword (dh_main_loop); |
311 } |
311 } |
312 |
312 |
313 // ============================================================================ |
313 // ============================================================================ |
314 // |
314 // |
316 { |
316 { |
317 check_toplevel(); |
317 check_toplevel(); |
318 bool onenter = (token_is (tk_onenter)); |
318 bool onenter = (token_is (tk_onenter)); |
319 m_lx->must_get_next (tk_brace_start); |
319 m_lx->must_get_next (tk_brace_start); |
320 |
320 |
321 m_current_mode = onenter ? MODE_ONENTER : MODE_ONEXIT; |
321 m_current_mode = onenter ? e_onenter_mode : e_onexit_mode; |
322 buffer()->write_dword (onenter ? dh_on_enter : dh_on_exit); |
322 buffer()->write_dword (onenter ? dh_on_enter : dh_on_exit); |
323 } |
323 } |
324 |
324 |
325 // ============================================================================ |
325 // ============================================================================ |
326 // |
326 // |
327 void botscript_parser::parse_variable_declaration() |
327 void botscript_parser::parse_variable_declaration() |
328 { |
328 { |
329 // For now, only globals are supported |
329 // For now, only globals are supported |
330 if (m_current_mode != MODE_TOPLEVEL || m_current_state.is_empty() == false) |
330 if (m_current_mode != e_top_level_mode || m_current_state.is_empty() == false) |
331 error ("variables must only be global for now"); |
331 error ("variables must only be global for now"); |
332 |
332 |
333 type_e type = (token_is (tk_int)) ? TYPE_INT : |
333 type_e type = (token_is (tk_int)) ? e_int_type : |
334 (token_is (tk_str)) ? TYPE_STRING : |
334 (token_is (tk_str)) ? e_string_type : |
335 TYPE_BOOL; |
335 e_bool_type; |
336 |
336 |
337 m_lx->must_get_next(); |
337 m_lx->must_get_next(); |
338 string varname = token_string(); |
338 string varname = token_string(); |
339 |
339 |
340 // Var name must not be a number |
340 // Var name must not be a number |
384 // Condition |
384 // Condition |
385 m_lx->must_get_next (tk_paren_start); |
385 m_lx->must_get_next (tk_paren_start); |
386 |
386 |
387 // Read the expression and write it. |
387 // Read the expression and write it. |
388 m_lx->must_get_next(); |
388 m_lx->must_get_next(); |
389 data_buffer* c = parse_expression (TYPE_INT); |
389 data_buffer* c = parse_expression (e_int_type); |
390 buffer()->merge_and_destroy (c); |
390 buffer()->merge_and_destroy (c); |
391 |
391 |
392 m_lx->must_get_next (tk_paren_end); |
392 m_lx->must_get_next (tk_paren_end); |
393 m_lx->must_get_next (tk_brace_start); |
393 m_lx->must_get_next (tk_brace_start); |
394 |
394 |
450 byte_mark* mark2 = buffer()->add_mark (""); // end |
450 byte_mark* mark2 = buffer()->add_mark (""); // end |
451 |
451 |
452 // Condition |
452 // Condition |
453 m_lx->must_get_next (tk_paren_start); |
453 m_lx->must_get_next (tk_paren_start); |
454 m_lx->must_get_next(); |
454 m_lx->must_get_next(); |
455 data_buffer* expr = parse_expression (TYPE_INT); |
455 data_buffer* expr = parse_expression (e_int_type); |
456 m_lx->must_get_next (tk_paren_end); |
456 m_lx->must_get_next (tk_paren_end); |
457 m_lx->must_get_next (tk_brace_start); |
457 m_lx->must_get_next (tk_brace_start); |
458 |
458 |
459 // write condition |
459 // write condition |
460 buffer()->merge_and_destroy (expr); |
460 buffer()->merge_and_destroy (expr); |
486 |
486 |
487 m_lx->must_get_next (tk_semicolon); |
487 m_lx->must_get_next (tk_semicolon); |
488 |
488 |
489 // Condition |
489 // Condition |
490 m_lx->must_get_next(); |
490 m_lx->must_get_next(); |
491 data_buffer* cond = parse_expression (TYPE_INT); |
491 data_buffer* cond = parse_expression (e_int_type); |
492 |
492 |
493 if (!cond) |
493 if (!cond) |
494 error ("bad statement for condition of for"); |
494 error ("bad statement for condition of for"); |
495 |
495 |
496 m_lx->must_get_next (tk_semicolon); |
496 m_lx->must_get_next (tk_semicolon); |
554 |
554 |
555 check_not_toplevel(); |
555 check_not_toplevel(); |
556 push_scope(); |
556 push_scope(); |
557 m_lx->must_get_next (tk_paren_start); |
557 m_lx->must_get_next (tk_paren_start); |
558 m_lx->must_get_next(); |
558 m_lx->must_get_next(); |
559 buffer()->merge_and_destroy (parse_expression (TYPE_INT)); |
559 buffer()->merge_and_destroy (parse_expression (e_int_type)); |
560 m_lx->must_get_next (tk_paren_end); |
560 m_lx->must_get_next (tk_paren_end); |
561 m_lx->must_get_next (tk_brace_start); |
561 m_lx->must_get_next (tk_brace_start); |
562 SCOPE (0).type = e_switch_scope; |
562 SCOPE (0).type = e_switch_scope; |
563 SCOPE (0).mark1 = buffer()->add_mark (""); // end mark |
563 SCOPE (0).mark1 = buffer()->add_mark (""); // end mark |
564 SCOPE (0).buffer1 = null; // default header |
564 SCOPE (0).buffer1 = null; // default header |
716 break; |
716 break; |
717 |
717 |
718 case e_for_scope: |
718 case e_for_scope: |
719 // write the incrementor at the end of the loop block |
719 // write the incrementor at the end of the loop block |
720 buffer()->merge_and_destroy (SCOPE (0).buffer1); |
720 buffer()->merge_and_destroy (SCOPE (0).buffer1); |
721 |
|
722 // fall-thru |
|
723 case e_while_scope: |
721 case e_while_scope: |
724 // write down the instruction to go back to the start of the loop |
722 // write down the instruction to go back to the start of the loop |
725 buffer()->write_dword (dh_goto); |
723 buffer()->write_dword (dh_goto); |
726 buffer()->add_reference (SCOPE (0).mark1); |
724 buffer()->add_reference (SCOPE (0).mark1); |
727 |
725 |
732 case e_do_scope: |
730 case e_do_scope: |
733 { |
731 { |
734 m_lx->must_get_next (tk_while); |
732 m_lx->must_get_next (tk_while); |
735 m_lx->must_get_next (tk_paren_start); |
733 m_lx->must_get_next (tk_paren_start); |
736 m_lx->must_get_next(); |
734 m_lx->must_get_next(); |
737 data_buffer* expr = parse_expression (TYPE_INT); |
735 data_buffer* expr = parse_expression (e_int_type); |
738 m_lx->must_get_next (tk_paren_end); |
736 m_lx->must_get_next (tk_paren_end); |
739 m_lx->must_get_next (tk_semicolon); |
737 m_lx->must_get_next (tk_semicolon); |
740 |
738 |
741 // If the condition runs true, go back to the start. |
739 // If the condition runs true, go back to the start. |
742 buffer()->merge_and_destroy (expr); |
740 buffer()->merge_and_destroy (expr); |
789 // Descend down the stack |
787 // Descend down the stack |
790 m_scope_cursor--; |
788 m_scope_cursor--; |
791 return; |
789 return; |
792 } |
790 } |
793 |
791 |
794 int dataheader = (m_current_mode == MODE_EVENT) ? dh_end_event : |
792 int dataheader = (m_current_mode == e_event_mode) ? dh_end_event : |
795 (m_current_mode == MODE_MAINLOOP) ? dh_end_main_loop : |
793 (m_current_mode == e_main_loop_mode) ? dh_end_main_loop : |
796 (m_current_mode == MODE_ONENTER) ? dh_end_on_enter : |
794 (m_current_mode == e_onenter_mode) ? dh_end_on_enter : |
797 (m_current_mode == MODE_ONEXIT) ? dh_end_on_exit : -1; |
795 (m_current_mode == e_onexit_mode) ? dh_end_on_exit : -1; |
798 |
796 |
799 if (dataheader == -1) |
797 if (dataheader == -1) |
800 error ("unexpected `}`"); |
798 error ("unexpected `}`"); |
801 |
799 |
802 // Data header must be written before mode is changed because |
800 // Data header must be written before mode is changed because |
803 // onenter and mainloop go into special buffers, and we want |
801 // onenter and mainloop go into special buffers, and we want |
804 // the closing data headers into said buffers too. |
802 // the closing data headers into said buffers too. |
805 buffer()->write_dword (dataheader); |
803 buffer()->write_dword (dataheader); |
806 m_current_mode = MODE_TOPLEVEL; |
804 m_current_mode = e_top_level_mode; |
807 m_lx->get_next (tk_semicolon); |
805 m_lx->get_next (tk_semicolon); |
808 } |
806 } |
809 |
807 |
810 // ============================================================================ |
808 // ============================================================================ |
811 // |
809 // |
814 constant_info info; |
812 constant_info info; |
815 |
813 |
816 // Get the type |
814 // Get the type |
817 m_lx->must_get_next(); |
815 m_lx->must_get_next(); |
818 string typestring = token_string(); |
816 string typestring = token_string(); |
819 info.type = GetTypeByName (typestring); |
817 info.type = get_type_by_name (typestring); |
820 |
818 |
821 if (info.type == TYPE_UNKNOWN || info.type == TYPE_VOID) |
819 if (info.type == e_unknown_type || info.type == e_void_type) |
822 error ("unknown type `%1` for constant", typestring); |
820 error ("unknown type `%1` for constant", typestring); |
823 |
821 |
824 m_lx->must_get_next(); |
822 m_lx->must_get_next(); |
825 info.name = token_string(); |
823 info.name = token_string(); |
826 |
824 |
827 m_lx->must_get_next (tk_assign); |
825 m_lx->must_get_next (tk_assign); |
828 |
826 |
829 switch (info.type) |
827 switch (info.type) |
830 { |
828 { |
831 case TYPE_BOOL: |
829 case e_bool_type: |
832 case TYPE_INT: |
830 case e_int_type: |
833 { |
831 { |
834 m_lx->must_get_next (tk_number); |
832 m_lx->must_get_next (tk_number); |
835 } break; |
833 } break; |
836 |
834 |
837 case TYPE_STRING: |
835 case e_string_type: |
838 { |
836 { |
839 m_lx->must_get_next (tk_string); |
837 m_lx->must_get_next (tk_string); |
840 } break; |
838 } break; |
841 |
839 |
842 case TYPE_UNKNOWN: |
840 case e_unknown_type: |
843 case TYPE_VOID: |
841 case e_void_type: |
844 break; |
842 break; |
845 } |
843 } |
846 |
844 |
847 info.val = m_lx->get_token()->text; |
845 info.val = m_lx->get_token()->text; |
848 m_constants << info; |
846 m_constants << info; |
921 |
919 |
922 m_lx->must_get_next (tk_colon); |
920 m_lx->must_get_next (tk_colon); |
923 |
921 |
924 // Return value |
922 // Return value |
925 m_lx->must_get_any_of ({tk_int, tk_void, tk_bool, tk_str}); |
923 m_lx->must_get_any_of ({tk_int, tk_void, tk_bool, tk_str}); |
926 comm->returnvalue = GetTypeByName (m_lx->get_token()->text); // TODO |
924 comm->returnvalue = get_type_by_name (m_lx->get_token()->text); // TODO |
927 assert (comm->returnvalue != -1); |
925 assert (comm->returnvalue != -1); |
928 |
926 |
929 m_lx->must_get_next (tk_colon); |
927 m_lx->must_get_next (tk_colon); |
930 |
928 |
931 // Num args |
929 // Num args |
944 while (curarg < comm->maxargs) |
942 while (curarg < comm->maxargs) |
945 { |
943 { |
946 command_argument arg; |
944 command_argument arg; |
947 m_lx->must_get_next (tk_colon); |
945 m_lx->must_get_next (tk_colon); |
948 m_lx->must_get_any_of ({tk_int, tk_bool, tk_str}); |
946 m_lx->must_get_any_of ({tk_int, tk_bool, tk_str}); |
949 type_e type = GetTypeByName (m_lx->get_token()->text); |
947 type_e type = get_type_by_name (m_lx->get_token()->text); |
950 assert (type != -1 && type != TYPE_VOID); |
948 assert (type != -1 && type != e_void_type); |
951 arg.type = type; |
949 arg.type = type; |
952 |
950 |
953 m_lx->must_get_next (tk_paren_start); |
951 m_lx->must_get_next (tk_paren_start); |
954 m_lx->must_get_next (tk_symbol); |
952 m_lx->must_get_next (tk_symbol); |
955 arg.name = m_lx->get_token()->text; |
953 arg.name = m_lx->get_token()->text; |
991 // Parses a command call |
989 // Parses a command call |
992 data_buffer* botscript_parser::parse_command (command_info* comm) |
990 data_buffer* botscript_parser::parse_command (command_info* comm) |
993 { |
991 { |
994 data_buffer* r = new data_buffer (64); |
992 data_buffer* r = new data_buffer (64); |
995 |
993 |
996 if (m_current_mode == MODE_TOPLEVEL) |
994 if (m_current_mode == e_top_level_mode) |
997 error ("command call at top level"); |
995 error ("command call at top level"); |
998 |
996 |
999 m_lx->must_get_next (tk_paren_start); |
997 m_lx->must_get_next (tk_paren_start); |
1000 m_lx->must_get_next(); |
998 m_lx->must_get_next(); |
1001 |
999 |
1347 else if (constant_info* constant = find_constant (token_string())) |
1345 else if (constant_info* constant = find_constant (token_string())) |
1348 { |
1346 { |
1349 // Type check |
1347 // Type check |
1350 if (reqtype != constant->type) |
1348 if (reqtype != constant->type) |
1351 error ("constant `%1` is %2, expression requires %3\n", |
1349 error ("constant `%1` is %2, expression requires %3\n", |
1352 constant->name, GetTypeName (constant->type), |
1350 constant->name, get_type_name (constant->type), |
1353 GetTypeName (reqtype)); |
1351 get_type_name (reqtype)); |
1354 |
1352 |
1355 switch (constant->type) |
1353 switch (constant->type) |
1356 { |
1354 { |
1357 case TYPE_BOOL: |
1355 case e_bool_type: |
1358 case TYPE_INT: |
1356 case e_int_type: |
1359 b->write_dword (dh_push_number); |
1357 b->write_dword (dh_push_number); |
1360 b->write_dword (atoi (constant->val)); |
1358 b->write_dword (atoi (constant->val)); |
1361 break; |
1359 break; |
1362 |
1360 |
1363 case TYPE_STRING: |
1361 case e_string_type: |
1364 b->write_string_index (constant->val); |
1362 b->write_string_index (constant->val); |
1365 break; |
1363 break; |
1366 |
1364 |
1367 case TYPE_VOID: |
1365 case e_void_type: |
1368 case TYPE_UNKNOWN: |
1366 case e_unknown_type: |
1369 break; |
1367 break; |
1370 } |
1368 } |
1371 } |
1369 } |
1372 else if ((g = find_global_variable (token_string()))) |
1370 else if ((g = find_global_variable (token_string()))) |
1373 { |
1371 { |
1378 else |
1376 else |
1379 { |
1377 { |
1380 // If nothing else, check for literal |
1378 // If nothing else, check for literal |
1381 switch (reqtype) |
1379 switch (reqtype) |
1382 { |
1380 { |
1383 case TYPE_VOID: |
1381 case e_void_type: |
1384 case TYPE_UNKNOWN: |
1382 case e_unknown_type: |
1385 error ("unknown identifier `%1` (expected keyword, function or variable)", token_string()); |
1383 error ("unknown identifier `%1` (expected keyword, function or variable)", token_string()); |
1386 break; |
1384 break; |
1387 |
1385 |
1388 case TYPE_BOOL: |
1386 case e_bool_type: |
1389 case TYPE_INT: |
1387 case e_int_type: |
1390 { |
1388 { |
1391 m_lx->must_be (tk_number); |
1389 m_lx->must_be (tk_number); |
1392 |
1390 |
1393 // All values are written unsigned - thus we need to write the value's |
1391 // All values are written unsigned - thus we need to write the value's |
1394 // absolute value, followed by an unary minus for negatives. |
1392 // absolute value, followed by an unary minus for negatives. |
1401 b->write_dword (dh_unary_minus); |
1399 b->write_dword (dh_unary_minus); |
1402 |
1400 |
1403 break; |
1401 break; |
1404 } |
1402 } |
1405 |
1403 |
1406 case TYPE_STRING: |
1404 case e_string_type: |
1407 // PushToStringTable either returns the string index of the |
1405 // PushToStringTable either returns the string index of the |
1408 // string if it finds it in the table, or writes it to the |
1406 // string if it finds it in the table, or writes it to the |
1409 // table and returns it index if it doesn't find it there. |
1407 // table and returns it index if it doesn't find it there. |
1410 m_lx->must_be (tk_string); |
1408 m_lx->must_be (tk_string); |
1411 b->write_string_index (token_string()); |
1409 b->write_string_index (token_string()); |
1432 int oper = parse_operator(); |
1430 int oper = parse_operator(); |
1433 |
1431 |
1434 if (!is_assignment_operator (oper)) |
1432 if (!is_assignment_operator (oper)) |
1435 error ("expected assignment operator"); |
1433 error ("expected assignment operator"); |
1436 |
1434 |
1437 if (m_current_mode == MODE_TOPLEVEL) |
1435 if (m_current_mode == e_top_level_mode) |
1438 error ("can't alter variables at top level"); |
1436 error ("can't alter variables at top level"); |
1439 |
1437 |
1440 // Parse the right operand |
1438 // Parse the right operand |
1441 m_lx->must_get_next(); |
1439 m_lx->must_get_next(); |
1442 data_buffer* retbuf = new data_buffer; |
1440 data_buffer* retbuf = new data_buffer; |
1568 data_buffer* botscript_parser::buffer() |
1566 data_buffer* botscript_parser::buffer() |
1569 { |
1567 { |
1570 if (m_switch_buffer != null) |
1568 if (m_switch_buffer != null) |
1571 return m_switch_buffer; |
1569 return m_switch_buffer; |
1572 |
1570 |
1573 if (m_current_mode == MODE_MAINLOOP) |
1571 if (m_current_mode == e_main_loop_mode) |
1574 return m_main_loop_buffer; |
1572 return m_main_loop_buffer; |
1575 |
1573 |
1576 if (m_current_mode == MODE_ONENTER) |
1574 if (m_current_mode == e_onenter_mode) |
1577 return m_on_enter_buffer; |
1575 return m_on_enter_buffer; |
1578 |
1576 |
1579 return m_main_buffer; |
1577 return m_main_buffer; |
1580 } |
1578 } |
1581 |
1579 |
1628 // Write the compiled bytecode to a file |
1626 // Write the compiled bytecode to a file |
1629 // |
1627 // |
1630 void botscript_parser::write_to_file (string outfile) |
1628 void botscript_parser::write_to_file (string outfile) |
1631 { |
1629 { |
1632 FILE* fp = fopen (outfile, "w"); |
1630 FILE* fp = fopen (outfile, "w"); |
1633 CHECK_FILE (fp, outfile, "writing"); |
1631 |
|
1632 if (fp == null) |
|
1633 error ("couldn't open %1 for writing: %2", outfile, strerror (errno)); |
1634 |
1634 |
1635 // First, resolve references |
1635 // First, resolve references |
1636 for (int u = 0; u < MAX_MARKS; u++) |
1636 for (mark_reference* ref : m_main_buffer->get_refs()) |
1637 { |
1637 { |
1638 mark_reference* ref = m_main_buffer->get_refs()[u]; |
|
1639 |
|
1640 if (!ref) |
|
1641 continue; |
|
1642 |
|
1643 // Substitute the placeholder with the mark position |
1638 // Substitute the placeholder with the mark position |
1644 generic_union<word> uni; |
1639 for (int v = 0; v < 4; v++) |
1645 uni.as_word = static_cast<word> (ref->target->pos); |
1640 m_main_buffer->get_buffer()[ref->pos + v] = ((ref->target->pos) << (8 * v)) & 0xFF; |
1646 |
1641 |
1647 for (int v = 0; v < (int) sizeof (word); v++) |
1642 print ("reference at %1 resolved to mark at %2\n", ref->pos, ref->target->pos); |
1648 memset (m_main_buffer->get_buffer() + ref->pos + v, uni.as_bytes[v], 1); |
|
1649 |
|
1650 /* |
|
1651 printf ("reference %u at %d resolved to %u at %d\n", |
|
1652 u, ref->pos, ref->num, MainBuffer->marks[ref->num]->pos); |
|
1653 */ |
|
1654 } |
1643 } |
1655 |
1644 |
1656 // Then, dump the main buffer to the file |
1645 // Then, dump the main buffer to the file |
1657 fwrite (m_main_buffer->get_buffer(), 1, m_main_buffer->get_write_size(), fp); |
1646 fwrite (m_main_buffer->get_buffer(), 1, m_main_buffer->get_write_size(), fp); |
1658 print ("-- %1 byte%s1 written to %2\n", m_main_buffer->get_write_size(), outfile); |
1647 print ("-- %1 byte%s1 written to %2\n", m_main_buffer->get_write_size(), outfile); |