robhagemans / pcbasic

PC-BASIC - A free, cross-platform emulator for the GW-BASIC family of interpreters
http://www.pc-basic.org
Other
393 stars 48 forks source link

Crash attempting to save a program as binary with text-encoding #212

Closed einstein95 closed 1 year ago

einstein95 commented 1 year ago

Bug report

Problem

When using --convert=B and --text-encoding in the same command line, pcbasic fails to do so. I expected pcbasic to decode the plain text file using the specified text encoding and then save it as binary.

Steps

  1. Run pcbasic --text-encoding=437 --convert=B plaintext.bas --output tokenized.bas
  2. Watch as it fails with a TypeError

Program Any plain text program should do the trick.

Crash log

Traceback (most recent call last):
  File "/bin/pcbasic", line 8, in <module>
    sys.exit(main())
  File "/lib/python3.10/site-packages/pcbasic/main.py", line 39, in main
    _convert(settings)
  File "/lib/python3.10/site-packages/pcbasic/main.py", line 73, in _convert
    session.execute(b'SAVE "%s"%s' % (outfile, mode_suffix))
  File "/lib/python3.10/site-packages/pcbasic/basic/api.py", line 91, in execute
    self._impl.execute(cmd)
  File "/lib/python3.10/site-packages/pcbasic/basic/implementation.py", line 250, in execute
    self.interpreter.loop()
  File "/lib/python3.10/site-packages/pcbasic/basic/interpreter.py", line 124, in loop
    self.parse()
  File "/lib/python3.10/site-packages/pcbasic/basic/interpreter.py", line 114, in parse
    self.parser.parse_statement(ins)
  File "/lib/python3.10/site-packages/pcbasic/basic/parser/statements.py", line 82, in parse_statement
    self._callbacks[c](parse_args(ins))
  File "/lib/python3.10/site-packages/pcbasic/basic/implementation.py", line 659, in save_
    with self.files.open(
  File "/lib/python3.10/site-packages/pcbasic/basic/devices/files.py", line 94, in open
    new_file = device.open(
  File "/lib/python3.10/site-packages/pcbasic/basic/devices/disk.py", line 792, in open
    return self._create_file_object(fhandle, filetype, mode)
  File "/lib/python3.10/site-packages/pcbasic/basic/devices/disk.py", line 293, in _create_file_object
    return BinaryFile(fhandle, filetype, number, mode, seg, offset, length, self._locks)
  File "/lib/python3.10/site-packages/pcbasic/basic/devices/diskfiles.py", line 44, in __init__
    self.write(TYPE_TO_MAGIC[filetype])
  File "/lib/python3.10/site-packages/pcbasic/basic/devices/devicebase.py", line 197, in write
    self._fhandle.write(s)
TypeError: write() argument must be str, not bytes

Notes

PC-BASIC version: PC-BASIC 2.0.6 Operating system version: Arch Linux

robhagemans commented 1 year ago

Thanks for reporting! I had a look and there seem to be a number of things wrong with the code that decides whether to open a text or binary stream. The intended behaviour is that --text-encoding only affects text files (plaintext programs and data files opened for INPUT, OUTPUT or APPEND). Here the binary program is opened as a text file, then treated as binary again, leading to the exception reported.

Aside - come to think about it, is it right for --text-encoding to be applied to data files at all? They might be used for binary data with the likes of MKS$. On the other hand, any code page covers all byte values by definition, the output would be mangled but consistent if read with the same codepage setting.

robhagemans commented 1 year ago

Resolved by commit 676a231