Ejemplo n.º 1
2
def renum(new_line, start_line, step):
    """ Renumber stored program. """
    new_line = 10 if new_line is None else new_line
    start_line = 0 if start_line is None else start_line
    step = 10 if step is None else step
    # get a sorted list of line numbers
    keys = sorted([ k for k in state.basic_state.line_numbers.keys() if k >= start_line])
    # assign the new numbers
    old_to_new = {}
    for old_line in keys:
        if old_line < 65535 and new_line > 65529:
            raise error.RunError(error.IFC)
        if old_line == 65536:
            break
        old_to_new[old_line] = new_line
        state.basic_state.last_stored = new_line
        new_line += step
    # write the new numbers
    for old_line in old_to_new:
        state.basic_state.bytecode.seek(state.basic_state.line_numbers[old_line])
        # skip the \x00\xC0\xDE & overwrite line number
        state.basic_state.bytecode.read(3)
        state.basic_state.bytecode.write(str(vartypes.value_to_uint(old_to_new[old_line])))
    # rebuild the line number dictionary
    new_lines = {}
    for old_line in old_to_new:
        new_lines[old_to_new[old_line]] = state.basic_state.line_numbers[old_line]
        del state.basic_state.line_numbers[old_line]
    state.basic_state.line_numbers.update(new_lines)
    # write the indirect line numbers
    state.basic_state.bytecode.seek(0)
    while util.skip_to_read(state.basic_state.bytecode, ('\x0e',)) == '\x0e':
        # get the old g number
        jumpnum = vartypes.uint_to_value(bytearray(state.basic_state.bytecode.read(2)))
        try:
            newjump = old_to_new[jumpnum]
        except KeyError:
            # not redefined, exists in program?
            if jumpnum in state.basic_state.line_numbers:
                newjump = jumpnum
            else:
                linum = get_line_number(state.basic_state.bytecode.tell())
                console.write_line('Undefined line ' + str(jumpnum) + ' in ' + str(linum))
        state.basic_state.bytecode.seek(-2, 1)
        state.basic_state.bytecode.write(str(vartypes.value_to_uint(newjump)))
    # stop running if we were
    flow.set_pointer(False)
    # reset loop stacks
    state.basic_state.gosub_return = []
    state.basic_state.for_next_stack = []
    state.basic_state.while_wend_stack = []
    # renumber error handler
    if state.basic_state.on_error:
        state.basic_state.on_error = old_to_new[state.basic_state.on_error]
    # renumber event traps
    for handler in state.basic_state.events.all:
        if handler.gosub:
            handler.set_jump(old_to_new[handler.gosub])
Ejemplo n.º 2
0
 def switch_mode(self):
     """ Switch loop mode. """
     last_execute, last_auto = self.last_mode
     if state.basic_state.parse_mode != last_execute:
         # move pointer to the start of direct line (for both on and off!)
         flow.set_pointer(False, 0)
         state.console_state.screen.cursor.reset_visibility()
     return ((not state.basic_state.auto_mode) and
             (not state.basic_state.parse_mode) and last_execute)
Ejemplo n.º 3
0
def bluescreen(e):
    """ Display a modal exception message. """
    state.console_state.screen.screen(0, 0, 0, 0, new_width=80)
    console.clear()
    console.init_mode()
    exc_type, exc_value, exc_traceback = sys.exc_info()
    # log the standard python error
    logging.error(''.join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
    # format the error more readably on the screen
    state.console_state.screen.set_border(4)
    state.console_state.screen.set_attr(0x70)
    console.write_line('EXCEPTION')
    state.console_state.screen.set_attr(15)
    if state.basic_state.run_mode:
        state.basic_state.bytecode.seek(-1, 1)
        program.edit(program.get_line_number(state.basic_state.bytecode.tell()),
                                         state.basic_state.bytecode.tell())
        console.write_line('\n')
    else:
        state.basic_state.direct_line.seek(0)
        console.write_line(str(tokenise.detokenise_compound_statement(state.basic_state.direct_line)[0])+'\n')
    stack = traceback.extract_tb(exc_traceback)
    for s in stack[-4:]:
        stack_line = '{0}:{1}, {2}'.format(
            os.path.split(s[0])[-1], s[1], s[2])
        stack_line_2 = '    {0}'.format(s[3])
        state.console_state.screen.set_attr(15)
        console.write_line(stack_line)
        state.console_state.screen.set_attr(7)
        console.write_line(stack_line_2)
    exc_message = traceback.format_exception_only(exc_type, exc_value)[0]
    state.console_state.screen.set_attr(15)
    console.write('{0}:'.format(exc_type.__name__))
    state.console_state.screen.set_attr(7)
    console.write_line(' {0}'.format(str(exc_value)))
    state.console_state.screen.set_attr(0x70)
    console.write_line(
        '\nThis is a bug in PC-BASIC.')
    state.console_state.screen.set_attr(7)
    console.write(
        'Sorry about that. Please send the above messages to the bugs forum\nby e-mail to ')
    state.console_state.screen.set_attr(15)
    console.write(
        '*****@*****.**')
    state.console_state.screen.set_attr(7)
    console.write(
        ' or by filing a bug\nreport at ')
    state.console_state.screen.set_attr(15)
    console.write(
        'https://github.com/robhagemans/pcbasic/issues')
    state.console_state.screen.set_attr(7)
    console.write_line(
        '. Please include')
    console.write_line('as much information as you can about what you were doing and how this happened.')
    console.write_line('Thank you!')
    state.console_state.screen.set_attr(7)
    flow.set_pointer(False)
Ejemplo n.º 4
0
def switch_mode():
    """ Switch loop mode. """
    last_execute, last_auto = state.basic_state.last_mode
    if state.basic_state.execute_mode != last_execute:
        # move pointer to the start of direct line (for both on and off!)
        flow.set_pointer(False, 0)
        state.console_state.screen.cursor.reset_visibility()
    return ((not state.basic_state.auto_mode) and
            (not state.basic_state.execute_mode) and last_execute)
Ejemplo n.º 5
0
def bluescreen(e):
    """ Display a modal exception message. """
    state.console_state.screen.screen(0, 0, 0, 0, new_width=80)
    console.clear()
    console.init_mode()
    exc_type, exc_value, exc_traceback = sys.exc_info()
    # log the standard python error
    logging.error(''.join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
    # format the error more readably on the screen
    state.console_state.screen.set_border(4)
    state.console_state.screen.set_attr(0x70)
    console.write_line('EXCEPTION')
    state.console_state.screen.set_attr(15)
    if state.basic_state.run_mode:
        state.basic_state.bytecode.seek(-1, 1)
        program.edit(program.get_line_number(state.basic_state.bytecode.tell()),
                                         state.basic_state.bytecode.tell())
        console.write_line('\n')
    else:
        state.basic_state.direct_line.seek(0)
        console.write_line(str(tokenise.detokenise_compound_statement(state.basic_state.direct_line)[0])+'\n')
    stack = traceback.extract_tb(exc_traceback)
    for s in stack[-4:]:
        stack_line = '{0}:{1}, {2}'.format(
            os.path.split(s[0])[-1], s[1], s[2])
        stack_line_2 = '    {0}'.format(s[3])
        state.console_state.screen.set_attr(15)
        console.write_line(stack_line)
        state.console_state.screen.set_attr(7)
        console.write_line(stack_line_2)
    exc_message = traceback.format_exception_only(exc_type, exc_value)[0]
    state.console_state.screen.set_attr(15)
    console.write('{0}:'.format(exc_type.__name__))
    state.console_state.screen.set_attr(7)
    console.write_line(' {0}'.format(str(exc_value)))
    state.console_state.screen.set_attr(0x70)
    console.write_line(
        '\nThis is a bug in PC-BASIC.')
    state.console_state.screen.set_attr(7)
    console.write(
        'Sorry about that. Please send the above messages to the bugs forum\nby e-mail to ')
    state.console_state.screen.set_attr(15)
    console.write(
        '*****@*****.**')
    state.console_state.screen.set_attr(7)
    console.write(
        ' or by filing a bug\nreport at ')
    state.console_state.screen.set_attr(15)
    console.write(
        'https://github.com/robhagemans/pcbasic/issues')
    state.console_state.screen.set_attr(7)
    console.write_line(
        '. Please include')
    console.write_line('as much information as you can about what you were doing and how this happened.')
    console.write_line('Thank you!')
    state.console_state.screen.set_attr(7)
    flow.set_pointer(False)
Ejemplo n.º 6
0
def list_lines(from_line, to_line):
    """ List line range. """
    if state.basic_state.protected:
        # don't list protected files
        raise error.RunError(error.IFC)
    # 65529 is max insertable line number for GW-BASIC 3.23.
    # however, 65530-65535 are executed if present in tokenised form.
    # in GW-BASIC, 65530 appears in LIST, 65531 and above are hidden
    if to_line is None:
        to_line = max_list_line
    # sort by positions, not line numbers!
    listable = sorted([ state.basic_state.line_numbers[num]
                            for num in state.basic_state.line_numbers
                            if num >= from_line and num <= to_line ])
    lines = []
    for pos in listable:
        state.basic_state.bytecode.seek(pos + 1)
        _, line, _ = tokenise.detokenise_line(state.basic_state.bytecode)
        lines.append(str(line))
    flow.set_pointer(False)
    return lines
Ejemplo n.º 7
0
def list_lines(dev, from_line, to_line):
    """ List line range to console or device. """
    if state.basic_state.protected:
        # don't list protected files
        raise error.RunError(5)
    # 65529 is max insertable line number for GW-BASIC 3.23. 
    # however, 65530-65535 are executed if present in tokenised form.
    # in GW-BASIC, 65530 appears in LIST, 65531 and above are hidden
    if to_line == None:
        to_line = max_list_line
    # sort by positions, not line numbers!
    listable = sorted([ state.basic_state.line_numbers[num] for num in state.basic_state.line_numbers if num >= from_line and num <= to_line ])
    for pos in listable:        
        state.basic_state.bytecode.seek(pos + 1)
        _, line, _ = tokenise.detokenise_line(state.basic_state.bytecode)
        if dev == backend.devices['SCRN:']:
            console.list_line(str(line))
        else:
            dev.write_line(str(line))
    dev.close()
    flow.set_pointer(False)
Ejemplo n.º 8
0
def list_lines(from_line, to_line):
    """ List line range. """
    if state.basic_state.protected:
        # don't list protected files
        raise error.RunError(error.IFC)
    # 65529 is max insertable line number for GW-BASIC 3.23.
    # however, 65530-65535 are executed if present in tokenised form.
    # in GW-BASIC, 65530 appears in LIST, 65531 and above are hidden
    if to_line is None:
        to_line = max_list_line
    # sort by positions, not line numbers!
    listable = sorted([
        state.basic_state.line_numbers[num]
        for num in state.basic_state.line_numbers
        if num >= from_line and num <= to_line
    ])
    lines = []
    for pos in listable:
        state.basic_state.bytecode.seek(pos + 1)
        _, line, _ = tokenise.detokenise_line(state.basic_state.bytecode)
        lines.append(str(line))
    flow.set_pointer(False)
    return lines
Ejemplo n.º 9
0
def renum(new_line, start_line, step):
    """ Renumber stored program. """
    new_line = 10 if new_line is None else new_line
    start_line = 0 if start_line is None else start_line
    step = 10 if step is None else step
    # get a sorted list of line numbers
    keys = sorted(
        [k for k in state.basic_state.line_numbers.keys() if k >= start_line])
    # assign the new numbers
    old_to_new = {}
    for old_line in keys:
        if old_line < 65535 and new_line > 65529:
            raise error.RunError(error.IFC)
        if old_line == 65536:
            break
        old_to_new[old_line] = new_line
        state.basic_state.last_stored = new_line
        new_line += step
    # write the new numbers
    for old_line in old_to_new:
        state.basic_state.bytecode.seek(
            state.basic_state.line_numbers[old_line])
        # skip the \x00\xC0\xDE & overwrite line number
        state.basic_state.bytecode.read(3)
        state.basic_state.bytecode.write(
            str(vartypes.value_to_uint(old_to_new[old_line])))
    # rebuild the line number dictionary
    new_lines = {}
    for old_line in old_to_new:
        new_lines[
            old_to_new[old_line]] = state.basic_state.line_numbers[old_line]
        del state.basic_state.line_numbers[old_line]
    state.basic_state.line_numbers.update(new_lines)
    # write the indirect line numbers
    state.basic_state.bytecode.seek(0)
    while util.skip_to_read(state.basic_state.bytecode, ('\x0e', )) == '\x0e':
        # get the old g number
        jumpnum = vartypes.uint_to_value(
            bytearray(state.basic_state.bytecode.read(2)))
        try:
            newjump = old_to_new[jumpnum]
        except KeyError:
            # not redefined, exists in program?
            if jumpnum in state.basic_state.line_numbers:
                newjump = jumpnum
            else:
                linum = get_line_number(state.basic_state.bytecode.tell())
                console.write_line('Undefined line ' + str(jumpnum) + ' in ' +
                                   str(linum))
        state.basic_state.bytecode.seek(-2, 1)
        state.basic_state.bytecode.write(str(vartypes.value_to_uint(newjump)))
    # stop running if we were
    flow.set_pointer(False)
    # reset loop stacks
    state.basic_state.gosub_return = []
    state.basic_state.for_next_stack = []
    state.basic_state.while_wend_stack = []
    # renumber error handler
    if state.basic_state.on_error:
        state.basic_state.on_error = old_to_new[state.basic_state.on_error]
    # renumber event traps
    for handler in state.basic_state.events.all:
        if handler.gosub:
            handler.set_jump(old_to_new[handler.gosub])
Ejemplo n.º 10
0
def renum(new_line, start_line, step):
    """ Renumber stored program. """
    new_line = 10 if new_line is None else new_line
    start_line = 0 if start_line is None else start_line
    step = 10 if step is None else step
    # get a sorted list of line numbers
    keys = sorted([ k for k in state.basic_state.line_numbers.keys() if k >= start_line])
    # assign the new numbers
    old_to_new = {}
    for old_line in keys:
        if old_line < 65535 and new_line > 65529:
            raise error.RunError(error.IFC)
        if old_line == 65536:
            break
        old_to_new[old_line] = new_line
        state.basic_state.last_stored = new_line
        new_line += step
    # write the new numbers
    for old_line in old_to_new:
        state.basic_state.bytecode.seek(state.basic_state.line_numbers[old_line])
        # skip the \x00\xC0\xDE & overwrite line number
        state.basic_state.bytecode.read(3)
        state.basic_state.bytecode.write(str(vartypes.integer_to_bytes(vartypes.int_to_integer_unsigned(old_to_new[old_line]))))
    # write the indirect line numbers
    ins = state.basic_state.bytecode
    ins.seek(0)
    while util.skip_to_read(ins, (tk.T_UINT,)) == tk.T_UINT:
        # get the old g number
        jumpnum = vartypes.integer_to_int_unsigned(vartypes.bytes_to_integer(ins.read(2)))
        # handle exception for ERROR GOTO
        if jumpnum == 0:
            pos = ins.tell()
            # skip line number token
            ins.seek(-3, 1)
            if util.backskip_white(ins) == tk.GOTO and util.backskip_white(ins) == tk.ERROR:
                ins.seek(pos)
                continue
            ins.seek(pos)
        try:
            newjump = old_to_new[jumpnum]
        except KeyError:
            # not redefined, exists in program?
            if jumpnum not in state.basic_state.line_numbers:
                linum = get_line_number(ins.tell()-1)
                console.write_line('Undefined line ' + str(jumpnum) + ' in ' + str(linum))
            newjump = jumpnum
        ins.seek(-2, 1)
        ins.write(str(vartypes.integer_to_bytes(vartypes.int_to_integer_unsigned(newjump))))
    # rebuild the line number dictionary
    new_lines = {}
    for old_line in old_to_new:
        new_lines[old_to_new[old_line]] = state.basic_state.line_numbers[old_line]
        del state.basic_state.line_numbers[old_line]
    state.basic_state.line_numbers.update(new_lines)
    # stop running if we were
    flow.set_pointer(False)
    # reset loop stacks
    state.basic_state.gosub_return = []
    state.basic_state.for_next_stack = []
    state.basic_state.while_wend_stack = []
    # renumber error handler
    if state.basic_state.on_error:
        state.basic_state.on_error = old_to_new[state.basic_state.on_error]
    # renumber event traps
    for handler in state.basic_state.events.all:
        if handler.gosub:
            handler.set_jump(old_to_new[handler.gosub])
Ejemplo n.º 11
0
def renum(new_line, start_line, step):
    """ Renumber stored program. """
    new_line = 10 if new_line is None else new_line
    start_line = 0 if start_line is None else start_line
    step = 10 if step is None else step
    # get a sorted list of line numbers
    keys = sorted(
        [k for k in state.basic_state.line_numbers.keys() if k >= start_line])
    # assign the new numbers
    old_to_new = {}
    for old_line in keys:
        if old_line < 65535 and new_line > 65529:
            raise error.RunError(error.IFC)
        if old_line == 65536:
            break
        old_to_new[old_line] = new_line
        state.basic_state.last_stored = new_line
        new_line += step
    # write the new numbers
    for old_line in old_to_new:
        state.basic_state.bytecode.seek(
            state.basic_state.line_numbers[old_line])
        # skip the \x00\xC0\xDE & overwrite line number
        state.basic_state.bytecode.read(3)
        state.basic_state.bytecode.write(
            str(
                vartypes.integer_to_bytes(
                    vartypes.int_to_integer_unsigned(old_to_new[old_line]))))
    # write the indirect line numbers
    ins = state.basic_state.bytecode
    ins.seek(0)
    while util.skip_to_read(ins, (tk.T_UINT, )) == tk.T_UINT:
        # get the old g number
        jumpnum = vartypes.integer_to_int_unsigned(
            vartypes.bytes_to_integer(ins.read(2)))
        # handle exception for ERROR GOTO
        if jumpnum == 0:
            pos = ins.tell()
            # skip line number token
            ins.seek(-3, 1)
            if util.backskip_white(ins) == tk.GOTO and util.backskip_white(
                    ins) == tk.ERROR:
                ins.seek(pos)
                continue
            ins.seek(pos)
        try:
            newjump = old_to_new[jumpnum]
        except KeyError:
            # not redefined, exists in program?
            if jumpnum not in state.basic_state.line_numbers:
                linum = get_line_number(ins.tell() - 1)
                console.write_line('Undefined line ' + str(jumpnum) + ' in ' +
                                   str(linum))
            newjump = jumpnum
        ins.seek(-2, 1)
        ins.write(
            str(
                vartypes.integer_to_bytes(
                    vartypes.int_to_integer_unsigned(newjump))))
    # rebuild the line number dictionary
    new_lines = {}
    for old_line in old_to_new:
        new_lines[
            old_to_new[old_line]] = state.basic_state.line_numbers[old_line]
        del state.basic_state.line_numbers[old_line]
    state.basic_state.line_numbers.update(new_lines)
    # stop running if we were
    flow.set_pointer(False)
    # reset loop stacks
    state.basic_state.gosub_return = []
    state.basic_state.for_next_stack = []
    state.basic_state.while_wend_stack = []
    # renumber error handler
    if state.basic_state.on_error:
        state.basic_state.on_error = old_to_new[state.basic_state.on_error]
    # renumber event traps
    for handler in state.basic_state.events.all:
        if handler.gosub:
            handler.set_jump(old_to_new[handler.gosub])