示例#1
2
文件: program.py 项目: nony05/pcbasic
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])
示例#2
2
文件: machine.py 项目: nony05/pcbasic
def bsave(g, offset, length):
    """ Save a block of memory into a file. """
    addr = state.basic_state.segment * 0x10 + offset
    g.write(str(get_memory_block(addr, length)))
    # Tandys repeat the header at the end of the file
    if tandy_syntax:
        g.write('\xfd' + vartypes.value_to_uint(state.basic_state.segment) +
                vartypes.value_to_uint(offset) +
                vartypes.value_to_uint(length))
示例#3
1
文件: program.py 项目: nony05/pcbasic
def rebuild_line_dict():
    """ Preparse to build line number dictionary. """
    state.basic_state.line_numbers, offsets = {}, []
    state.basic_state.bytecode.seek(0)
    scanline, scanpos, last = 0, 0, 0
    while True:
        state.basic_state.bytecode.read(1) # pass \x00
        scanline = util.parse_line_number(state.basic_state.bytecode)
        if scanline == -1:
            scanline = 65536
            # if parse_line_number returns -1, it leaves the stream pointer here: 00 _00_ 00 1A
            break
        state.basic_state.line_numbers[scanline] = scanpos
        last = scanpos
        util.skip_to(state.basic_state.bytecode, tk.end_line)
        scanpos = state.basic_state.bytecode.tell()
        offsets.append(scanpos)
    state.basic_state.line_numbers[65536] = scanpos
    # rebuild offsets
    state.basic_state.bytecode.seek(0)
    last = 0
    for pos in offsets:
        state.basic_state.bytecode.read(1)
        state.basic_state.bytecode.write(str(vartypes.value_to_uint(program_memory_start + pos)))
        state.basic_state.bytecode.read(pos - last - 3)
        last = pos
    # ensure program is properly sealed - last offset must be 00 00. keep, but ignore, anything after.
    state.basic_state.bytecode.write('\0\0\0')
示例#4
0
def get_data_memory_array(address):
    """ Retrieve data from data memory: array space """
    name_addr = -1
    arr_addr = -1
    the_arr = None
    for name in state.basic_state.array_memory:
        name_try, arr_try = state.basic_state.array_memory[name]
        if name_try <= address and name_try > name_addr:
            name_addr, arr_addr = name_try, arr_try
            the_arr = name
    if the_arr is None:
        return -1
    if address >= state.basic_state.var_current + arr_addr:
        offset = address - arr_addr - state.basic_state.var_current
        if offset >= var.array_size_bytes(the_arr):
            return -1
        _, byte_array, _ = state.basic_state.arrays[the_arr]
        return byte_array[offset]
    else:
        offset = address - name_addr - state.basic_state.var_current
        if offset < max(3, len(the_arr)) + 1:
            return get_name_in_memory(the_arr, offset)
        else:
            offset -= max(3, len(the_arr)) + 1
            dimensions, _, _ = state.basic_state.arrays[the_arr]
            data_rep = vartypes.value_to_uint(
                var.array_size_bytes(the_arr) + 1 + 2 * len(dimensions)) + chr(
                    len(dimensions))
            for d in dimensions:
                data_rep += vartypes.value_to_uint(
                    d + 1 - state.basic_state.array_base)
            return data_rep[offset]
示例#5
0
def get_data_memory_array(address):
    """ Retrieve data from data memory: array space """
    name_addr = -1
    arr_addr = -1
    the_arr = None 
    for name in state.basic_state.array_memory:
        name_try, arr_try = state.basic_state.array_memory[name]
        if name_try <= address and name_try > name_addr:
            name_addr, arr_addr = name_try, arr_try
            the_arr = name
    if the_arr == None:
        return -1        
    if address >= state.basic_state.var_current + arr_addr:
        offset = address - arr_addr - state.basic_state.var_current
        if offset >= var.array_size_bytes(the_arr):
            return -1
        _, byte_array, _ = state.basic_state.arrays[the_arr]    
        return byte_array[offset]
    else:
        offset = address - name_addr - state.basic_state.var_current
        if offset < max(3, len(the_arr))+1:
            return get_name_in_memory(the_arr, offset)
        else:
            offset -= max(3, len(the_arr))+1
            dimensions, _, _ = state.basic_state.arrays[the_arr]
            data_rep = vartypes.value_to_uint(var.array_size_bytes(the_arr) + 1 + 2*len(dimensions)) + chr(len(dimensions)) 
            for d in dimensions:
                data_rep += vartypes.value_to_uint(d + 1 - state.basic_state.array_base)
            return data_rep[offset]               
示例#6
0
def bsave(g, offset, length):
    """ Save a block of memory into a file. """
    addr = state.basic_state.segment * 0x10 + offset
    g.write(str(get_memory_block(addr, length)))
    # Tandys repeat the header at the end of the file
    if tandy_syntax:
        g.write('\xfd' + vartypes.value_to_uint(state.basic_state.segment) +
                vartypes.value_to_uint(offset) +
                vartypes.value_to_uint(length))
示例#7
0
def set_field_var_or_array(random_file, varname, indices, offset, length):
    """ Attach a string variable to a FIELD buffer. """
    if varname[-1] != '$':
        # type mismatch
        raise error.RunError(error.TYPE_MISMATCH)
    if offset + length > len(random_file.field.buffer):
        # FIELD overflow
        raise error.RunError(error.FIELD_OVERFLOW)
    str_addr = random_file.field.address + offset
    str_sequence = bytearray(chr(length)) + vartypes.value_to_uint(str_addr)
    # assign the string ptr to the variable name
    # desired side effect: if we re-assign this string variable through LET, it's no longer connected to the FIELD.
    if indices == []:
        state.basic_state.variables[varname] = str_sequence
        # update memory model (see set_var)
        if varname not in state.basic_state.var_memory:
            name_ptr = state.basic_state.var_current
            var_ptr = name_ptr + max(
                3, len(varname)
            ) + 1  # byte_size first_letter second_letter_or_nul remaining_length_or_nul
            state.basic_state.var_current += max(
                3, len(varname)) + 1 + byte_size['$']
            state.basic_state.var_memory[varname] = (name_ptr, var_ptr)
    else:
        check_dim_array(varname, indices)
        dimensions, lst, _ = state.basic_state.arrays[varname]
        bigindex = index_array(indices, dimensions)
        lst[bigindex * 3:(bigindex + 1) * 3] = str_sequence
示例#8
0
文件: program.py 项目: nony05/pcbasic
def store_line(linebuf):
    """ Store the given line buffer. """
    if state.basic_state.protected:
        raise error.RunError(error.IFC)
    # get the new line number
    linebuf.seek(1)
    scanline = util.parse_line_number(linebuf)
    # check if linebuf is an empty line after the line number
    empty = (util.skip_white_read(linebuf) in tk.end_line)
    pos, afterpos, deleteable, beyond = find_pos_line_dict(scanline, scanline)
    if empty and not deleteable:
        raise error.RunError(error.UNDEFINED_LINE_NUMBER)
    # read the remainder of the program into a buffer to be pasted back after the write
    state.basic_state.bytecode.seek(afterpos)
    rest = state.basic_state.bytecode.read()
    # insert
    state.basic_state.bytecode.seek(pos)
    # write the line buffer to the program buffer
    length = 0
    if not empty:
        # set offsets
        linebuf.seek(3) # pass \x00\xC0\xDE
        length = len(linebuf.getvalue())
        state.basic_state.bytecode.write( '\0' + str(vartypes.value_to_uint(program_memory_start + pos + length)) + linebuf.read())
    # write back the remainder of the program
    truncate_program(rest)
    # update all next offsets by shifting them by the length of the added line
    update_line_dict(pos, afterpos, length, deleteable, beyond)
    if not empty:
        state.basic_state.line_numbers[scanline] = pos
    # clear all program stacks
    flow.init_program()
    state.basic_state.last_stored = scanline
示例#9
0
def tokenise_uint(ins):
    """ Convert an unsigned int (line number) to tokenised form. """
    word = bytearray()
    while True:
        c = ins.read(1)
        if c in ascii_digits + whitespace:
            word += c
        else:    
            ins.seek(-len(c), 1)
            break
    # don't claim trailing w/s
    while len(word)>0 and chr(word[-1]) in whitespace:
        del word[-1]        
        ins.seek(-1, 1)
    # remove all whitespace
    trimword = bytearray()
    for c in word:
        if chr(c) not in whitespace:
            trimword += chr(c)
    word = trimword        
    # line number (jump)
    if len(word) > 0:
        if int(word) >= 65530:
            # note: anything >= 65530 is illegal in GW-BASIC
            # in loading an ASCII file, GWBASIC would interpret these as 
            # '6553 1' etcetera, generating a syntax error on load.
            # keep 6553 as line number and push back the last number:
            ins.seek(4-len(word), 1)
            word = word[:4]
        return str(vartypes.value_to_uint(int(word)))
    else:
        return ''    
示例#10
0
def set_field_var_or_array(random_file, varname, indices, offset, length):
    """ Attach a string variable to a FIELD buffer. """
    if varname[-1] != '$':
        # type mismatch
        raise error.RunError(13)
    field = random_file.field
    if offset+length > len(field):
        # FIELD overflow
        raise error.RunError(50)    
    str_addr = random_file.field_address + offset
    str_sequence = bytearray(chr(length)) + vartypes.value_to_uint(str_addr)
    # assign the string ptr to the variable name
    # desired side effect: if we re-assign this string variable through LET, it's no longer connected to the FIELD.
    if indices == []:
        state.basic_state.variables[varname] = str_sequence
        # update memory model (see set_var)
        if varname not in state.basic_state.var_memory:
            name_ptr = state.basic_state.var_current
            var_ptr = name_ptr + max(3, len(varname)) + 1 # byte_size first_letter second_letter_or_nul remaining_length_or_nul 
            state.basic_state.var_current += max(3, len(varname)) + 1 + byte_size['$']
            state.basic_state.var_memory[varname] = (name_ptr, var_ptr)
    else:
        check_dim_array(varname, indices)
        dimensions, lst, _ = state.basic_state.arrays[varname]
        bigindex = index_array(indices, dimensions)
        lst[bigindex*3:(bigindex+1)*3] = str_sequence
示例#11
0
def tokenise_uint(ins):
    """ Convert an unsigned int (line number) to tokenised form. """
    word = bytearray()
    while True:
        c = ins.read(1)
        if c and c in ascii_digits + ascii_whitespace:
            word += c
        else:
            ins.seek(-len(c), 1)
            break
    # don't claim trailing w/s
    while len(word) > 0 and chr(word[-1]) in ascii_whitespace:
        del word[-1]
        ins.seek(-1, 1)
    # remove all whitespace
    trimword = bytearray()
    for c in word:
        if chr(c) not in ascii_whitespace:
            trimword += chr(c)
    word = trimword
    # line number (jump)
    if len(word) > 0:
        if int(word) >= 65530:
            # note: anything >= 65530 is illegal in GW-BASIC
            # in loading an ASCII file, GWBASIC would interpret these as
            # '6553 1' etcetera, generating a syntax error on load.
            # keep 6553 as line number and push back the last number:
            ins.seek(4 - len(word), 1)
            word = word[:4]
        return str(vartypes.value_to_uint(int(word)))
    else:
        return ''
示例#12
0
def rebuild_line_dict():
    """ Preparse to build line number dictionary. """
    state.basic_state.line_numbers, offsets = {}, []
    state.basic_state.bytecode.seek(0)
    scanline, scanpos, last = 0, 0, 0
    while True:
        state.basic_state.bytecode.read(1)  # pass \x00
        scanline = util.parse_line_number(state.basic_state.bytecode)
        if scanline == -1:
            scanline = 65536
            # if parse_line_number returns -1, it leaves the stream pointer here: 00 _00_ 00 1A
            break
        state.basic_state.line_numbers[scanline] = scanpos
        last = scanpos
        util.skip_to(state.basic_state.bytecode, tk.end_line)
        scanpos = state.basic_state.bytecode.tell()
        offsets.append(scanpos)
    state.basic_state.line_numbers[65536] = scanpos
    # rebuild offsets
    state.basic_state.bytecode.seek(0)
    last = 0
    for pos in offsets:
        state.basic_state.bytecode.read(1)
        state.basic_state.bytecode.write(
            str(vartypes.value_to_uint(program_memory_start + pos)))
        state.basic_state.bytecode.read(pos - last - 3)
        last = pos
    # ensure program is properly sealed - last offset must be 00 00. keep, but ignore, anything after.
    state.basic_state.bytecode.write('\0\0\0')
示例#13
0
def tokenise_hex(ins, outs):
    """ Convert hex expression in Python string to number token. """
    ins.read(1)
    word = ''
    while True:
        c = util.peek(ins)
        if not c or c not in string.hexdigits:
            break
        else:
            word += ins.read(1)
    val = int(word, 16) if word else 0
    outs.write(tk.T_HEX + str(vartypes.value_to_uint(val)))
示例#14
0
def tokenise_hex(ins, outs):
    """ Convert hex expression in Python string to number token. """
    ins.read(1)
    word = ''
    while True:
        c = util.peek(ins).upper()
        if not c or c not in ascii_hexits:
            break
        else:
            word += ins.read(1).upper()
    val = int(word, 16) if word else 0
    outs.write(tk.T_HEX + str(vartypes.value_to_uint(val)))
示例#15
0
 def store(self, string_buffer, address=None):
     """ Store a new string and return the 3-byte memory sequence. """
     if address == None:
         # find new string address
         self.current -= len(string_buffer)
         address = self.current + 1 
     key = str(vartypes.value_to_uint(address))
     # don't store empty strings
     if len(string_buffer) > 0:
         if key in self.strings:
             raise KeyError('String key %s at %d already defined.' % (repr(key), address))
         self.strings[key] = string_buffer    
     return bytearray(chr(len(string_buffer)) + key)
示例#16
0
def tokenise_oct(ins, outs):
    """ Convert octal expression in Python string to number token. """
    # O is optional, could also be &777 instead of &O777
    if util.peek(ins).upper() == 'O':
        ins.read(1)
    word = ''
    while True:
        c = util.peek(ins).upper()
        if not c or c not in ascii_octits:
            break
        else:
            word += ins.read(1).upper()
    val = int(word, 8) if word else 0
    outs.write(tk.T_OCT + str(vartypes.value_to_uint(val)))
示例#17
0
 def store(self, string_buffer, address=None):
     """ Store a new string and return the 3-byte memory sequence. """
     if address is None:
         # find new string address
         self.current -= len(string_buffer)
         address = self.current + 1
     key = str(vartypes.value_to_uint(address))
     # don't store empty strings
     if len(string_buffer) > 0:
         if key in self.strings:
             raise KeyError('String key %s at %d already defined.' %
                            (repr(key), address))
         self.strings[key] = string_buffer
     return bytearray(chr(len(string_buffer)) + key)
示例#18
0
def tokenise_oct(ins, outs):
    """ Convert octal expression in Python string to number token. """
    # O is optional, could also be &777 instead of &O777
    if util.peek(ins).upper() == 'O':
        ins.read(1)
    word = ''
    while True:
        c = util.peek(ins)
        if not c or c not in string.octdigits:
            break
        else:
            word += ins.read(1)
    val = int(word, 8) if word else 0
    outs.write(tk.T_OCT + str(vartypes.value_to_uint(val)))
示例#19
0
文件: disk.py 项目: boriel/pcbasic
 def __init__(self, fhandle, filetype, number, name, mode,
                    seg, offset, length):
     """ Initialise program file object and write header. """
     iolayer.RawFile.__init__(self, fhandle, filetype, mode)
     self.number = number
     # don't lock binary files
     self.lock = ''
     self.access = 'RW'
     self.seg, self.offset, self.length = 0, 0, 0
     if self.mode == 'O':
         self.write(iolayer.type_to_magic[filetype])
         if self.filetype == 'M':
             self.write(vartypes.value_to_uint(seg) +
                        vartypes.value_to_uint(offset) +
                        vartypes.value_to_uint(length))
             self.seg, self.offset, self.length = seg, offset, length
     else:
         # drop magic byte
         self.read_raw(1)
         if self.filetype == 'M':
             self.seg = vartypes.uint_to_value(bytearray(self.read(2)))
             self.offset = vartypes.uint_to_value(bytearray(self.read(2)))
             # size gets ignored: even the \x1a at the end is read
             self.length = vartypes.uint_to_value(bytearray(self.read(2)))
示例#20
0
 def __init__(self, fhandle, filetype, number, name, mode,
                    seg, offset, length):
     """ Initialise program file object and write header. """
     devices.RawFile.__init__(self, fhandle, filetype, mode)
     self.number = number
     # don't lock binary files
     self.lock = ''
     self.access = 'RW'
     self.seg, self.offset, self.length = 0, 0, 0
     if self.mode == 'O':
         self.write(devices.type_to_magic[filetype])
         if self.filetype == 'M':
             self.write(vartypes.value_to_uint(seg) +
                        vartypes.value_to_uint(offset) +
                        vartypes.value_to_uint(length))
             self.seg, self.offset, self.length = seg, offset, length
     else:
         # drop magic byte
         self.read_raw(1)
         if self.filetype == 'M':
             self.seg = vartypes.uint_to_value(bytearray(self.read(2)))
             self.offset = vartypes.uint_to_value(bytearray(self.read(2)))
             # size gets ignored: even the \x1a at the end is read
             self.length = vartypes.uint_to_value(bytearray(self.read(2)))
示例#21
0
def value_varptr(ins):
    """ VARPTR, VARPTR$: get memory address for variable or FCB. """
    dollar = util.skip_white_read_if(ins, ('$',))
    util.require_read(ins, ('(',))
    if (not dollar) and util.skip_white(ins) == '#':
        filenum = parse_file_number_opthash(ins)
        var_ptr = machine.varptr_file(filenum)
    else:
        name, indices = get_var_or_array_name(ins)
        var_ptr = machine.varptr(name, indices)
    util.require_read(ins, (')',))
    if var_ptr < 0:
        raise error.RunError(error.IFC)
    if dollar:
        return vartypes.pack_string(bytearray(chr(var.byte_size[name[-1]])) + vartypes.value_to_uint(var_ptr))
    else:
        return vartypes.pack_int(var_ptr)
示例#22
0
def value_varptr(ins):
    """ VARPTR, VARPTR$: get memory address for variable or FCB. """
    dollar = util.skip_white_read_if(ins, ('$', ))
    util.require_read(ins, ('(', ))
    if (not dollar) and util.skip_white(ins) == '#':
        filenum = parse_file_number_opthash(ins)
        var_ptr = machine.varptr_file(filenum)
    else:
        name, indices = get_var_or_array_name(ins)
        var_ptr = machine.varptr(name, indices)
    util.require_read(ins, (')', ))
    if var_ptr < 0:
        raise error.RunError(error.IFC)
    if dollar:
        return vartypes.pack_string(
            bytearray(chr(var.byte_size[name[-1]])) +
            vartypes.value_to_uint(var_ptr))
    else:
        return vartypes.pack_int(var_ptr)
示例#23
0
文件: program.py 项目: nony05/pcbasic
def update_line_dict(pos, afterpos, length, deleteable, beyond):
    """ Update line number dictionary after deleting lines. """
    # subtract length of line we replaced
    length -= afterpos - pos
    addr = program_memory_start + afterpos
    state.basic_state.bytecode.seek(afterpos + length + 1)  # pass \x00
    while True:
        next_addr = bytearray(state.basic_state.bytecode.read(2))
        if len(next_addr) < 2 or next_addr == '\0\0':
            break
        next_addr = vartypes.uint_to_value(next_addr)
        state.basic_state.bytecode.seek(-2, 1)
        state.basic_state.bytecode.write(str(vartypes.value_to_uint(next_addr + length)))
        state.basic_state.bytecode.read(next_addr - addr - 2)
        addr = next_addr
    # update line number dict
    for key in deleteable:
        del state.basic_state.line_numbers[key]
    for key in beyond:
        state.basic_state.line_numbers[key] += length
示例#24
0
def update_line_dict(pos, afterpos, length, deleteable, beyond):
    """ Update line number dictionary after deleting lines. """
    # subtract length of line we replaced
    length -= afterpos - pos
    addr = program_memory_start + afterpos
    state.basic_state.bytecode.seek(afterpos + length + 1)  # pass \x00
    while True:
        next_addr = bytearray(state.basic_state.bytecode.read(2))
        if len(next_addr) < 2 or next_addr == '\0\0':
            break
        next_addr = vartypes.uint_to_value(next_addr)
        state.basic_state.bytecode.seek(-2, 1)
        state.basic_state.bytecode.write(
            str(vartypes.value_to_uint(next_addr + length)))
        state.basic_state.bytecode.read(next_addr - addr - 2)
        addr = next_addr
    # update line number dict
    for key in deleteable:
        del state.basic_state.line_numbers[key]
    for key in beyond:
        state.basic_state.line_numbers[key] += length
示例#25
0
def store_line(linebuf):
    """ Store the given line buffer. """
    if state.basic_state.protected:
        raise error.RunError(error.IFC)
    # get the new line number
    linebuf.seek(1)
    scanline = util.parse_line_number(linebuf)
    # check if linebuf is an empty line after the line number
    empty = (util.skip_white_read(linebuf) in tk.end_line)
    pos, afterpos, deleteable, beyond = find_pos_line_dict(scanline, scanline)
    if empty and not deleteable:
        raise error.RunError(error.UNDEFINED_LINE_NUMBER)
    # read the remainder of the program into a buffer to be pasted back after the write
    state.basic_state.bytecode.seek(afterpos)
    rest = state.basic_state.bytecode.read()
    # insert
    state.basic_state.bytecode.seek(pos)
    # write the line buffer to the program buffer
    length = 0
    if not empty:
        # set offsets
        linebuf.seek(3)  # pass \x00\xC0\xDE
        length = len(linebuf.getvalue())
        state.basic_state.bytecode.write(
            '\0' +
            str(vartypes.value_to_uint(program_memory_start + pos + length)) +
            linebuf.read())
    # write back the remainder of the program
    truncate_program(rest)
    # update all next offsets by shifting them by the length of the added line
    update_line_dict(pos, afterpos, length, deleteable, beyond)
    if not empty:
        state.basic_state.line_numbers[scanline] = pos
    # clear all program stacks
    flow.init_program()
    state.basic_state.last_stored = scanline
示例#26
0
文件: modes.py 项目: nony05/pcbasic
 def sprite_size_to_record(self, dx, dy):
     """ Write 4-byte record of sprite size. """
     return vartypes.value_to_uint(
         dx * self.bitsperpixel) + vartypes.value_to_uint(dy)
示例#27
0
def tokenise_number(ins, outs):
    """ Convert Python-string number representation to number token. """
    c = util.peek(ins)
    # handle hex or oct constants
    if c == '&':
        ins.read(1)
        nxt = util.peek(ins).upper()
        if nxt == 'H': # hex constant
            ins.read(1)
            word = ''
            while True: 
                if not util.peek(ins).upper() in ascii_hexits:
                    break
                else:
                    word += ins.read(1).upper()
            val = int(word, 16) if word else 0
            outs.write('\x0C' + str(vartypes.value_to_uint(val)))
        else: # nxt == 'O': # octal constant
            if nxt == 'O':
                ins.read(1)
            word = ''    
            while True: 
                if not util.peek(ins).upper() in ascii_octits:
                    break
                else:
                    word += ins.read(1).upper()
            val = int(word, 8) if word else 0
            outs.write('\x0B' + str(vartypes.value_to_uint(val)))
    # handle other numbers
    # note GW passes signs separately as a token and only stores positive numbers in the program        
    elif (c in ascii_digits or c=='.' or c in ('+','-')):
        have_exp = False
        have_point = False
        word = ''
        while True: 
            c = ins.read(1).upper()
            if c == '.' and not have_point and not have_exp:
                have_point = True
                word += c
            elif c in ('E', 'D') and not have_exp:    
                have_exp = True
                word += c
            elif c in ('-','+') and word=='':
                # must be first token
                word += c              
            elif c in ('+', '-') and word[-1] in ('E', 'D'):
                word += c
            elif c in ascii_digits: # (c >='0' and numc <='9'):
                word += c
            elif c in whitespace:
                # we'll remove this later but need to keep it for now so we can reposition the stream on removing trainling whitespace 
                word += c
            elif c in ('!', '#') and not have_exp:
                word += c
                break
            elif c == '%':
                # swallow a %, but break parsing
                break    
            else:
                if c != '':
                    ins.seek(-1,1)
                break
        # don't claim trailing whitespace, don't end in D or E            
        while len(word)>0 and (word[-1] in whitespace + ('D', 'E')):
            if word[-1] in ('D', 'E'):
                have_exp = False
            word = word[:-1]
            ins.seek(-1,1) # even if c==''
        # remove all internal whitespace
        trimword = ''
        for c in word:
            if c not in whitespace:
                trimword += c
        word = trimword
        # write out the numbers
        if len(word) == 1 and word in ascii_digits:
            # digit
            outs.write(chr(0x11+int(word)))
        elif not (have_exp or have_point or word[-1] in ('!', '#')) and int(word) <= 0x7fff and int(word) >= -0x8000:
            if int(word) <= 0xff and int(word)>=0:
                # one-byte constant
                outs.write('\x0f'+chr(int(word)))
            else:
                # two-byte constant
                outs.write('\x1c'+str(vartypes.value_to_sint(int(word))))
        else:
            mbf = str(from_str(word).to_bytes())
            if len(mbf) == 4:
                # single
                outs.write('\x1d'+mbf)
            else:    
                # double
                outs.write('\x1f'+mbf)
    elif c!='':
        ins.seek(-1,1)
示例#28
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])
示例#29
0
文件: modes.py 项目: nestormh/pcbasic
 def sprite_size_to_record(self, dx, dy):
     """ Write 4-byte record of sprite size. """
     return vartypes.value_to_uint(dx*self.bitsperpixel) + vartypes.value_to_uint(dy)
示例#30
0
文件: modes.py 项目: nestormh/pcbasic
def sprite_size_to_record_ega(self, dx, dy):
    """ Write 4-byte record of sprite size in EGA modes. """
    return vartypes.value_to_uint(dx) + vartypes.value_to_uint(dy)
示例#31
0
文件: modes.py 项目: nony05/pcbasic
def sprite_size_to_record_ega(self, dx, dy):
    """ Write 4-byte record of sprite size in EGA modes. """
    return vartypes.value_to_uint(dx) + vartypes.value_to_uint(dy)