Esempio n. 1
0
def value_environ(ins):
    """ ENVIRON$: get environment string. """
    util.require_read(ins, ('$',))
    expr = parse_bracket(ins)
    if expr[0] == '$':
        return vartypes.pack_string(shell.get_env(vartypes.unpack_string(expr)))
    else:
        expr = vartypes.pass_int_unpack(expr)
        util.range_check(1, 255, expr)
        return vartypes.pack_string(shell.get_env_entry(expr))
Esempio n. 2
0
def value_environ(ins):
    """ ENVIRON$: get environment string. """
    util.require_read(ins, ('$', ))
    expr = parse_bracket(ins)
    if expr[0] == '$':
        return vartypes.pack_string(shell.get_env(
            vartypes.unpack_string(expr)))
    else:
        expr = vartypes.pass_int_unpack(expr)
        util.range_check(1, 255, expr)
        return vartypes.pack_string(shell.get_env_entry(expr))
Esempio n. 3
0
 def _input_entry(self, typechar, allow_past_end):
     """ Read a number or string entry for INPUT """
     word, blanks = '', ''
     last = self._skip_whitespace(self.whitespace_input)
     # read first non-whitespace char
     c = self.read(1)
     # LF escapes quotes
     # may be true if last == '', hence "in ('\n', '\0')" not "in '\n0'"
     quoted = (c == '"' and typechar == '$' and last not in ('\n', '\0'))
     if quoted:
         c = self.read(1)
     # LF escapes end of file, return empty string
     if not c and not allow_past_end and last not in ('\n', '\0'):
         raise error.RunError(error.INPUT_PAST_END)
     # we read the ending char before breaking the loop
     # this may raise FIELD OVERFLOW
     # on reading from a KYBD: file, control char replacement takes place
     # which means we need to use read() not read_raw()
     while c and not ((typechar != '$' and c in self.soft_sep) or
                     (c in ',\r' and not quoted)):
         if c == '"' and quoted:
             # whitespace after quote will be skipped below
             break
         elif c == '\n' and not quoted:
             # LF, LFCR are dropped entirely
             c = self.read(1)
             if c == '\r':
                 c = self.read(1)
             continue
         elif c == '\0':
             # NUL is dropped even within quotes
             pass
         elif c in self.whitespace_input and not quoted:
             # ignore whitespace in numbers, except soft separators
             # include internal whitespace in strings
             if typechar == '$':
                 blanks += c
         else:
             word += blanks + c
             blanks = ''
         if len(word) + len(blanks) >= 255:
             break
         if not quoted:
             c = self.read(1)
         else:
             # no CRLF replacement inside quotes.
             # -- but should there be KYBD: control char replacement?
             c = self.read_raw(1)
     # if separator was a whitespace char or closing quote
     # skip trailing whitespace before any comma or hard separator
     if c and c in self.whitespace_input or (quoted and c == '"'):
         self._skip_whitespace(' ')
         if (self.next_char in ',\r'):
             c = self.read(1)
     # file position is at one past the separator char
     # convert result to requested type, be strict about non-numeric chars
     value = vartypes.pack_string(bytearray(word))
     if typechar != '$':
         value = representation.str_to_value_keep(value, allow_nonnum=False)
     return value, c
Esempio n. 4
0
 def _input_entry(self, typechar, allow_past_end):
     """ Read a number or string entry for INPUT """
     word, blanks = '', ''
     last = self._skip_whitespace(self.whitespace_input)
     # read first non-whitespace char
     c = self.read(1)
     # LF escapes quotes
     # may be true if last == '', hence "in ('\n', '\0')" not "in '\n0'"
     quoted = (c == '"' and typechar == '$' and last not in ('\n', '\0'))
     if quoted:
         c = self.read(1)
     # LF escapes end of file, return empty string
     if not c and not allow_past_end and last not in ('\n', '\0'):
         raise error.RunError(error.INPUT_PAST_END)
     # we read the ending char before breaking the loop
     # this may raise FIELD OVERFLOW
     # on reading from a KYBD: file, control char replacement takes place
     # which means we need to use read() not read_raw()
     while c and not ((typechar != '$' and c in self.soft_sep) or
                      (c in ',\r' and not quoted)):
         if c == '"' and quoted:
             # whitespace after quote will be skipped below
             break
         elif c == '\n' and not quoted:
             # LF, LFCR are dropped entirely
             c = self.read(1)
             if c == '\r':
                 c = self.read(1)
             continue
         elif c == '\0':
             # NUL is dropped even within quotes
             pass
         elif c in self.whitespace_input and not quoted:
             # ignore whitespace in numbers, except soft separators
             # include internal whitespace in strings
             if typechar == '$':
                 blanks += c
         else:
             word += blanks + c
             blanks = ''
         if len(word) + len(blanks) >= 255:
             break
         if not quoted:
             c = self.read(1)
         else:
             # no CRLF replacement inside quotes.
             # -- but should there be KYBD: control char replacement?
             c = self.read_raw(1)
     # if separator was a whitespace char or closing quote
     # skip trailing whitespace before any comma or hard separator
     if c and c in self.whitespace_input or (quoted and c == '"'):
         self._skip_whitespace(' ')
         if (self.next_char in ',\r'):
             c = self.read(1)
     # file position is at one past the separator char
     # convert result to requested type, be strict about non-numeric chars
     value = vartypes.pack_string(bytearray(word))
     if typechar != '$':
         value = representation.str_to_value_keep(value, allow_nonnum=False)
     return value, c
Esempio n. 5
0
def vplus(left, right):
    """ Left+right. """
    if left[0] == '$':
        return vartypes.pack_string(
            vartypes.pass_string_unpack(left) +
            vartypes.pass_string_unpack(right))
    else:
        return vartypes.number_add(left, right)
Esempio n. 6
0
 def _input_entry(self, typechar, allow_past_end):
     """ Read a number or string entry from KYBD: for INPUT# """
     word, blanks = '', ''
     if self.input_last:
         c, self.input_last = self.input_last, ''
     else:
         last = self._skip_whitespace(self.whitespace_input)
         # read first non-whitespace char
         c = self.read(1)
     # LF escapes quotes
     # may be true if last == '', hence "in ('\n', '\0')" not "in '\n0'"
     quoted = (c == '"' and typechar == '$' and last not in ('\n', '\0'))
     if quoted:
         c = self.read(1)
     # LF escapes end of file, return empty string
     if not c and not allow_past_end and last not in ('\n', '\0'):
         raise error.RunError(error.INPUT_PAST_END)
     # we read the ending char before breaking the loop
     # this may raise FIELD OVERFLOW
     # on reading from a KYBD: file, control char replacement takes place
     # which means we need to use read() not read_raw()
     parsing_trail = False
     while c and not (c in ',\r' and not quoted):
         if c == '"' and quoted:
             parsing_trail = True
         elif c == '\n' and not quoted:
             # LF, LFCR are dropped entirely
             c = self.read(1)
             if c == '\r':
                 c = self.read(1)
             continue
         elif c == '\0':
             # NUL is dropped even within quotes
             pass
         elif c in self.whitespace_input and not quoted:
             # ignore whitespace in numbers, except soft separators
             # include internal whitespace in strings
             if typechar == '$':
                 blanks += c
         else:
             word += blanks + c
             blanks = ''
         if len(word) + len(blanks) >= 255:
             break
         # there should be KYBD: control char replacement here even if quoted
         c = self.read(1)
         if parsing_trail:
             if c not in self.whitespace_input:
                 if c not in (',', '\r'):
                     self.input_last = c
                 break
         parsing_trail = parsing_trail or (typechar != '$' and c == ' ')
     # file position is at one past the separator char
     # convert result to requested type, be strict about non-numeric chars
     value = vartypes.pack_string(bytearray(word))
     if typechar != '$':
         value = representation.str_to_value_keep(value, allow_nonnum=False)
     return value, c
Esempio n. 7
0
def str_to_type(word, type_char):
    """ Convert Python-string to requested type. """
    packed = vartypes.pack_string(bytearray(word))
    if type_char == '$':
        return packed
    else:
        try:
            return str_to_value_keep(packed, allow_nonnum=False)
        except AttributeError:
            return None
Esempio n. 8
0
def get_string_copy_packed(sequence):
    """ Return a packed copy of a string from its 3-byte sequence. """
    length = ord(sequence[0:1])
    address = vartypes.uint_to_value(sequence[-2:])
    if address >= memory.var_start():
        # string is stored in string space
        return state.basic_state.strings.copy_packed(sequence)
    else: 
        # string is stored in code space or field buffers
        if address < memory.field_mem_start:
            return vartypes.pack_string('\0' * length)
        # find the file we're in
        start = address - memory.field_mem_start
        number = 1 + start // memory.field_mem_offset
        offset = start % memory.field_mem_offset
        try:
            return vartypes.pack_string(state.io_state.fields[number][offset:offset+length])
        except KeyError, IndexError:
            return vartypes.pack_string('\0' * length)
Esempio n. 9
0
def get_string_copy_packed(sequence):
    """ Return a packed copy of a string from its 3-byte sequence. """
    length = ord(sequence[0:1])
    address = vartypes.uint_to_value(sequence[-2:])
    if address >= memory.var_start():
        # string is stored in string space
        return state.basic_state.strings.copy_packed(sequence)
    else:
        # string is stored in code space or field buffers
        if address < memory.field_mem_start:
            return vartypes.pack_string('\0' * length)
        # find the file we're in
        start = address - memory.field_mem_start
        number = 1 + start // memory.field_mem_offset
        offset = start % memory.field_mem_offset
        try:
            return vartypes.pack_string(
                state.io_state.fields[number].buffer[offset:offset + length])
        except KeyError, IndexError:
            return vartypes.pack_string('\0' * length)
Esempio n. 10
0
def value_right(ins):
    """ RIGHT$: get substring at the end of string. """
    util.require_read(ins, ('(', ))
    s = vartypes.pass_string_unpack(parse_expression(ins))
    util.require_read(ins, (',', ))
    stop = vartypes.pass_int_unpack(parse_expression(ins))
    util.require_read(ins, (')', ))
    util.range_check(0, 255, stop)
    if stop == 0:
        return vartypes.null['$']
    stop = min(stop, len(s))
    return vartypes.pack_string(s[-stop:])
Esempio n. 11
0
def value_right(ins):
    """ RIGHT$: get substring at the end of string. """
    util.require_read(ins, ('(',))
    s = vartypes.pass_string_unpack(parse_expression(ins))
    util.require_read(ins, (',',))
    stop = vartypes.pass_int_unpack(parse_expression(ins))
    util.require_read(ins, (')',))
    util.range_check(0, 255, stop)
    if stop == 0:
        return vartypes.null['$']
    stop = min(stop, len(s))
    return vartypes.pack_string(s[-stop:])
Esempio n. 12
0
def value_input(ins):
    """ INPUT$: get characters from the keyboard or a file. """
    util.require_read(ins, ('$', ))
    util.require_read(ins, ('(', ))
    num = vartypes.pass_int_unpack(parse_expression(ins))
    util.range_check(1, 255, num)
    infile = state.io_state.kybd_file
    if util.skip_white_read_if(ins, (',', )):
        infile = devices.get_file(parse_file_number_opthash(ins))
    util.require_read(ins, (')', ))
    word = vartypes.pack_string(bytearray(infile.read_raw(num)))
    if len(word) < num:
        # input past end
        raise error.RunError(error.INPUT_PAST_END)
    return word
Esempio n. 13
0
def value_string(ins):
    """ STRING$: repeat characters. """
    util.require_read(ins, ('(',))
    n, j = parse_expr_list(ins, 2)
    n = vartypes.pass_int_unpack(n)
    util.range_check(0, 255, n)
    if j[0] == '$':
        j = vartypes.unpack_string(j)
        util.range_check(1, 255, len(j))
        j = j[0]
    else:
        j = vartypes.pass_int_unpack(j)
        util.range_check(0, 255, j)
    util.require_read(ins, (')',))
    return vartypes.pack_string(bytearray(chr(j)*n))
Esempio n. 14
0
def value_string(ins):
    """ STRING$: repeat characters. """
    util.require_read(ins, ('(', ))
    n, j = parse_expr_list(ins, 2)
    n = vartypes.pass_int_unpack(n)
    util.range_check(0, 255, n)
    if j[0] == '$':
        j = vartypes.unpack_string(j)
        util.range_check(1, 255, len(j))
        j = j[0]
    else:
        j = vartypes.pass_int_unpack(j)
        util.range_check(0, 255, j)
    util.require_read(ins, (')', ))
    return vartypes.pack_string(bytearray(chr(j) * n))
Esempio n. 15
0
def value_input(ins):
    """ INPUT$: get characters from the keyboard or a file. """
    util.require_read(ins, ('$',))
    util.require_read(ins, ('(',))
    num = vartypes.pass_int_unpack(parse_expression(ins))
    util.range_check(1, 255, num)
    infile = state.io_state.kybd_file
    if util.skip_white_read_if(ins, (',',)):
        infile = devices.get_file(parse_file_number_opthash(ins))
    util.require_read(ins, (')',))
    word = vartypes.pack_string(bytearray(infile.read_raw(num)))
    if len(word) < num:
        # input past end
        raise error.RunError(error.INPUT_PAST_END)
    return word
Esempio n. 16
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)
Esempio n. 17
0
def value_mid(ins):
    """ MID$: get substring. """
    util.require_read(ins, ('(',))
    s = vartypes.pass_string_unpack(parse_expression(ins))
    util.require_read(ins, (',',))
    start = vartypes.pass_int_unpack(parse_expression(ins))
    if util.skip_white_read_if(ins, (',',)):
        num = vartypes.pass_int_unpack(parse_expression(ins))
    else:
        num = len(s)
    util.require_read(ins, (')',))
    util.range_check(1, 255, start)
    util.range_check(0, 255, num)
    if num == 0 or start > len(s):
        return vartypes.null['$']
    start -= 1
    stop = start + num
    stop = min(stop, len(s))
    return vartypes.pack_string(s[start:stop])
Esempio n. 18
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)
Esempio n. 19
0
def value_mid(ins):
    """ MID$: get substring. """
    util.require_read(ins, ('(', ))
    s = vartypes.pass_string_unpack(parse_expression(ins))
    util.require_read(ins, (',', ))
    start = vartypes.pass_int_unpack(parse_expression(ins))
    if util.skip_white_read_if(ins, (',', )):
        num = vartypes.pass_int_unpack(parse_expression(ins))
    else:
        num = len(s)
    util.require_read(ins, (')', ))
    util.range_check(1, 255, start)
    util.range_check(0, 255, num)
    if num == 0 or start > len(s):
        return vartypes.null['$']
    start -= 1
    stop = start + num
    stop = min(stop, len(s))
    return vartypes.pack_string(s[start:stop])
Esempio n. 20
0
def value_hex(ins):
    """ HEX$: hexadecimal representation of int. """
    # allow range -32768 to 65535
    val = vartypes.pass_int_unpack(parse_bracket(ins), 0xffff)
    return vartypes.pack_string(representation.hex_to_str(vartypes.value_to_sint(val))[2:])
Esempio n. 21
0
def value_oct(ins):
    """ OCT$: octal representation of int. """
    # allow range -32768 to 65535
    val = vartypes.pass_int_unpack(parse_bracket(ins), 0xffff)
    return vartypes.pack_string(representation.oct_to_str(vartypes.value_to_sint(val))[2:])
Esempio n. 22
0
def value_chr(ins):
    """ CHR$: character for ASCII value. """
    val = vartypes.pass_int_unpack(parse_bracket(ins))
    util.range_check(0, 255, val)
    return vartypes.pack_string(bytearray(chr(val)))
Esempio n. 23
0
def value_mkd(ins):
    """ MKD$: return the byte representation of a double. """
    return vartypes.pack_string(vartypes.pass_double_keep(parse_bracket(ins))[1])
Esempio n. 24
0
def value_time(ins):
    """ TIME$: get current system time. """
    return vartypes.pack_string(timedate.get_time())
Esempio n. 25
0
def value_space(ins):
    """ SPACE$: repeat spaces. """
    num = vartypes.pass_int_unpack(parse_bracket(ins))
    util.range_check(0, 255, num)
    return vartypes.pack_string(bytearray(' '*num))
Esempio n. 26
0
def value_time(ins):
    """ TIME$: get current system time. """
    return vartypes.pack_string(timedate.get_time())
Esempio n. 27
0
def value_inkey(ins):
    """ INKEY$: get a character from the keyboard. """
    return vartypes.pack_string(bytearray(state.console_state.keyb.get_char()))
Esempio n. 28
0
def parse_expr_unit(ins):
    """ Compute the value of the expression unit at the current code pointer. """
    d = util.skip_white(ins)
    # string literal
    if d == '"':
        ins.read(1)
        output = bytearray()
        # while tokenised nmbers inside a string literal will be printed as tokenised numbers, they don't actually execute as such:
        # a \00 character, even if inside a tokenised number, will break a string literal (and make the parser expect a 
        # line number afterwards, etc. We follow this.
        d = ins.read(1)
        while d not in util.end_line + ('"',):
            output += d
            d = ins.read(1)
        if d == '\0':
            ins.seek(-1, 1)
        return vartypes.pack_string(output)
    # variable name
    elif d >= 'A' and d <= 'Z':
        name, indices = get_var_or_array_name(ins)
        return var.get_var_or_array(name, indices)
    # number literals as ASCII are accepted in tokenised streams. only if they start with a figure (not & or .)
    # this happens e.g. after non-keywords like AS. They are not acceptable as line numbers.
    elif d >= '0' and d <= '9':
        outs = StringIO()
        representation.tokenise_number(ins, outs)
        outs.seek(0)
        return util.parse_value(outs)
    # number literals
    elif d in token.number:
        return util.parse_value(ins)   
    # gw-basic allows adding line numbers to numbers     
    elif d == token.T_UINT:
        return vartypes.pack_int(util.parse_jumpnum(ins))
    # brackets
    elif d == '(':
        return parse_bracket(ins)
    # single-byte tokens 
    else:
        ins.read(1)       
        if d == '\x85':         return value_input(ins)
        elif d == '\xC8':       return value_screen(ins)
        elif d == '\xD0':       return value_usr(ins)
        elif d == '\xD1':       return value_fn(ins)
        elif d == '\xD3':       return value_not(ins)
        elif d == '\xD4':       return value_erl(ins)
        elif d == '\xD5':       return value_err(ins)
        elif d == '\xD6':       return value_string(ins)
        elif d == '\xD8':       return value_instr(ins)    
        elif d == '\xDA':       return value_varptr(ins)
        elif d == '\xDB':       return value_csrlin(ins)
        elif d == '\xDC':       return value_point(ins)
        elif d == '\xDE':       return value_inkey(ins)
        elif d == '\xE9':       return parse_expr_unit(ins)
        elif d == '\xEA':       return value_neg(ins)     
        # two-byte tokens
        elif d == '\xFD':
            d = ins.read(1)
            if d == '\x81':      return value_cvi(ins)
            elif d =='\x82':     return value_cvs(ins)
            elif d =='\x83':     return value_cvd(ins)
            elif d =='\x84':     return value_mki(ins)
            elif d =='\x85':     return value_mks(ins)
            elif d =='\x86':     return value_mkd(ins)
            elif d == '\x8b':    return value_exterr(ins)
        # two-byte tokens
        elif d == '\xFE':
            d = ins.read(1)        
            if d == '\x8D':      return value_date(ins)
            elif d == '\x8E':    return value_time(ins)
            elif d == '\x93':    return value_play(ins)
            elif d == '\x94':    return value_timer(ins)
            elif d == '\x95':    return value_erdev(ins)
            elif d == '\x96':    return value_ioctl(ins)
            elif d == '\x9B':    return value_environ(ins)
            elif d == '\x9E':    return value_pmap(ins)
        # two-byte tokens                    
        elif d == '\xFF':
            d = ins.read(1)
            if d == '\x81':     return value_left(ins)
            elif d == '\x82':   return value_right(ins)
            elif d == '\x83':   return value_mid(ins)
            elif d == '\x84':   return value_sgn(ins)
            elif d == '\x85':   return value_int(ins)
            elif d == '\x86':   return value_abs(ins)
            elif d == '\x87':   return value_sqrt(ins)
            elif d == '\x88':   return value_rnd(ins)
            elif d == '\x89':   return value_sin(ins)
            elif d == '\x8a':   return value_log(ins)
            elif d == '\x8b':   return value_exp(ins)
            elif d == '\x8c':   return value_cos(ins)
            elif d == '\x8D':   return value_tan(ins)
            elif d == '\x8E':   return value_atn(ins)
            elif d == '\x8F':   return value_fre(ins)
            elif d == '\x90':   return value_inp(ins)
            elif d == '\x91':   return value_pos(ins)
            elif d == '\x92':   return value_len(ins)
            elif d == '\x93':   return value_str(ins)
            elif d == '\x94':   return value_val(ins)
            elif d == '\x95':   return value_asc(ins)
            elif d == '\x96':   return value_chr(ins)
            elif d == '\x97':   return value_peek(ins)
            elif d == '\x98':   return value_space(ins)
            elif d == '\x99':   return value_oct(ins)
            elif d == '\x9A':   return value_hex(ins)
            elif d == '\x9B':   return value_lpos(ins)
            elif d == '\x9C':   return value_cint(ins)
            elif d == '\x9D':   return value_csng(ins)
            elif d == '\x9E':   return value_cdbl(ins)
            elif d == '\x9F':   return value_fix(ins)    
            elif d == '\xA0':   return value_pen(ins)
            elif d == '\xA1':   return value_stick(ins)
            elif d == '\xA2':   return value_strig(ins)
            elif d == '\xA3':   return value_eof(ins)
            elif d == '\xA4':   return value_loc(ins)
            elif d == '\xA5':   return value_lof(ins)
        else:
            return None
Esempio n. 29
0
def value_oct(ins):
    """ OCT$: octal representation of int. """
    # allow range -32768 to 65535
    val = vartypes.pass_int_unpack(parse_bracket(ins), 0xffff)
    return vartypes.pack_string(
        representation.oct_to_str(vartypes.value_to_sint(val))[2:])
Esempio n. 30
0
def value_date(ins):
    """ DATE$: get current system date. """
    return vartypes.pack_string(timedate.get_date())
Esempio n. 31
0
def value_inkey(ins):
    """ INKEY$: get a character from the keyboard. """
    return vartypes.pack_string(bytearray(state.console_state.keyb.get_char()))
Esempio n. 32
0
def value_mki(ins):
    """ MKI$: return the byte representation of an int. """
    return vartypes.pack_string(vartypes.value_to_sint(vartypes.pass_int_unpack(parse_bracket(ins))))
Esempio n. 33
0
def value_space(ins):
    """ SPACE$: repeat spaces. """
    num = vartypes.pass_int_unpack(parse_bracket(ins))
    util.range_check(0, 255, num)
    return vartypes.pack_string(bytearray(' ' * num))
Esempio n. 34
0
def value_mks(ins):
    """ MKS$: return the byte representation of a single. """
    return vartypes.pack_string(vartypes.pass_single_keep(parse_bracket(ins))[1])
Esempio n. 35
0
def value_chr(ins):
    """ CHR$: character for ASCII value. """
    val = vartypes.pass_int_unpack(parse_bracket(ins))
    util.range_check(0, 255, val)
    return vartypes.pack_string(bytearray(chr(val)))
Esempio n. 36
0
def parse_expr_unit(ins):
    """ Compute the value of the expression unit at the current code pointer. """
    d = util.skip_white(ins)
    # string literal
    if d == '"':
        ins.read(1)
        output = bytearray()
        # while tokenised nmbers inside a string literal will be printed as tokenised numbers, they don't actually execute as such:
        # a \00 character, even if inside a tokenised number, will break a string literal (and make the parser expect a
        # line number afterwards, etc. We follow this.
        d = ins.read(1)
        while d not in tk.end_line + ('"', ):
            output += d
            d = ins.read(1)
        if d == '\0':
            ins.seek(-1, 1)
        return vartypes.pack_string(output)
    # variable name
    elif d in string.ascii_uppercase:
        name, indices = get_var_or_array_name(ins)
        return var.get_var_or_array(name, indices)
    # number literals as ASCII are accepted in tokenised streams. only if they start with a figure (not & or .)
    # this happens e.g. after non-keywords like AS. They are not acceptable as line numbers.
    elif d in string.digits:
        outs = StringIO()
        representation.tokenise_number(ins, outs)
        outs.seek(0)
        return representation.parse_value(outs)
    # number literals
    elif d in tk.number:
        return representation.parse_value(ins)
    # gw-basic allows adding line numbers to numbers
    elif d == tk.T_UINT:
        return vartypes.pack_int(util.parse_jumpnum(ins))
    # brackets
    elif d == '(':
        return parse_bracket(ins)
    # single-byte tokens
    else:
        ins.read(1)
        if d == tk.INPUT: return value_input(ins)
        elif d == tk.SCREEN: return value_screen(ins)
        elif d == tk.USR: return value_usr(ins)
        elif d == tk.FN: return value_fn(ins)
        elif d == tk.NOT: return value_not(ins)
        elif d == tk.ERL: return value_erl(ins)
        elif d == tk.ERR: return value_err(ins)
        elif d == tk.STRING: return value_string(ins)
        elif d == tk.INSTR: return value_instr(ins)
        elif d == tk.VARPTR: return value_varptr(ins)
        elif d == tk.CSRLIN: return value_csrlin(ins)
        elif d == tk.POINT: return value_point(ins)
        elif d == tk.INKEY: return value_inkey(ins)
        elif d == tk.O_PLUS: return parse_expr_unit(ins)
        elif d == tk.O_MINUS:
            return value_neg(ins)
            # two-byte tokens
        elif d == '\xFD':
            d += ins.read(1)
            if d == tk.CVI: return value_cvi(ins)
            elif d == tk.CVS: return value_cvs(ins)
            elif d == tk.CVD: return value_cvd(ins)
            elif d == tk.MKI: return value_mki(ins)
            elif d == tk.MKS: return value_mks(ins)
            elif d == tk.MKD: return value_mkd(ins)
            elif d == tk.EXTERR: return value_exterr(ins)
        # two-byte tokens
        elif d == '\xFE':
            d += ins.read(1)
            if d == tk.DATE: return value_date(ins)
            elif d == tk.TIME: return value_time(ins)
            elif d == tk.PLAY: return value_play(ins)
            elif d == tk.TIMER: return value_timer(ins)
            elif d == tk.ERDEV: return value_erdev(ins)
            elif d == tk.IOCTL: return value_ioctl(ins)
            elif d == tk.ENVIRON: return value_environ(ins)
            elif d == tk.PMAP: return value_pmap(ins)
        # two-byte tokens
        elif d == '\xFF':
            d += ins.read(1)
            if d == tk.LEFT: return value_left(ins)
            elif d == tk.RIGHT: return value_right(ins)
            elif d == tk.MID: return value_mid(ins)
            elif d == tk.SGN: return value_sgn(ins)
            elif d == tk.INT: return value_int(ins)
            elif d == tk.ABS: return value_abs(ins)
            elif d == tk.SQR: return value_sqr(ins)
            elif d == tk.RND: return value_rnd(ins)
            elif d == tk.SIN: return value_sin(ins)
            elif d == tk.LOG: return value_log(ins)
            elif d == tk.EXP: return value_exp(ins)
            elif d == tk.COS: return value_cos(ins)
            elif d == tk.TAN: return value_tan(ins)
            elif d == tk.ATN: return value_atn(ins)
            elif d == tk.FRE: return value_fre(ins)
            elif d == tk.INP: return value_inp(ins)
            elif d == tk.POS: return value_pos(ins)
            elif d == tk.LEN: return value_len(ins)
            elif d == tk.STR: return value_str(ins)
            elif d == tk.VAL: return value_val(ins)
            elif d == tk.ASC: return value_asc(ins)
            elif d == tk.CHR: return value_chr(ins)
            elif d == tk.PEEK: return value_peek(ins)
            elif d == tk.SPACE: return value_space(ins)
            elif d == tk.OCT: return value_oct(ins)
            elif d == tk.HEX: return value_hex(ins)
            elif d == tk.LPOS: return value_lpos(ins)
            elif d == tk.CINT: return value_cint(ins)
            elif d == tk.CSNG: return value_csng(ins)
            elif d == tk.CDBL: return value_cdbl(ins)
            elif d == tk.FIX: return value_fix(ins)
            elif d == tk.PEN: return value_pen(ins)
            elif d == tk.STICK: return value_stick(ins)
            elif d == tk.STRIG: return value_strig(ins)
            elif d == tk.EOF: return value_eof(ins)
            elif d == tk.LOC: return value_loc(ins)
            elif d == tk.LOF: return value_lof(ins)
        else:
            return None
Esempio n. 37
0
def value_mkd(ins):
    """ MKD$: return the byte representation of a double. """
    return vartypes.pack_string(
        vartypes.pass_double_keep(parse_bracket(ins))[1])
Esempio n. 38
0
def value_mks(ins):
    """ MKS$: return the byte representation of a single. """
    return vartypes.pack_string(
        vartypes.pass_single_keep(parse_bracket(ins))[1])
Esempio n. 39
0
def value_date(ins):
    """ DATE$: get current system date. """
    return vartypes.pack_string(timedate.get_date())
Esempio n. 40
0
def value_hex(ins):
    """ HEX$: hexadecimal representation of int. """
    # allow range -32768 to 65535
    val = vartypes.pass_int_unpack(parse_bracket(ins), 0xffff)
    return vartypes.pack_string(
        representation.hex_to_str(vartypes.value_to_sint(val))[2:])
Esempio n. 41
0
def vplus(left, right):
    """ Left+right. """
    if left[0] == '$':
        return vartypes.pack_string(vartypes.pass_string_unpack(left) + vartypes.pass_string_unpack(right))
    else:
        return vartypes.number_add(left, right)
Esempio n. 42
0
def parse_expr_unit(ins):
    """ Compute the value of the expression unit at the current code pointer. """
    d = util.skip_white(ins)
    # string literal
    if d == '"':
        ins.read(1)
        output = bytearray()
        # while tokenised nmbers inside a string literal will be printed as tokenised numbers, they don't actually execute as such:
        # a \00 character, even if inside a tokenised number, will break a string literal (and make the parser expect a
        # line number afterwards, etc. We follow this.
        d = ins.read(1)
        while d not in tk.end_line + ('"',):
            output += d
            d = ins.read(1)
        if d == '\0':
            ins.seek(-1, 1)
        return vartypes.pack_string(output)
    # variable name
    elif d in string.ascii_uppercase:
        name, indices = get_var_or_array_name(ins)
        return var.get_var_or_array(name, indices)
    # number literals as ASCII are accepted in tokenised streams. only if they start with a figure (not & or .)
    # this happens e.g. after non-keywords like AS. They are not acceptable as line numbers.
    elif d in string.digits:
        outs = StringIO()
        representation.tokenise_number(ins, outs)
        outs.seek(0)
        return representation.parse_value(outs)
    # number literals
    elif d in tk.number:
        return representation.parse_value(ins)
    # gw-basic allows adding line numbers to numbers
    elif d == tk.T_UINT:
        return vartypes.pack_int(util.parse_jumpnum(ins))
    # brackets
    elif d == '(':
        return parse_bracket(ins)
    # single-byte tokens
    else:
        ins.read(1)
        if d == tk.INPUT:         return value_input(ins)
        elif d == tk.SCREEN:      return value_screen(ins)
        elif d == tk.USR:         return value_usr(ins)
        elif d == tk.FN:          return value_fn(ins)
        elif d == tk.NOT:         return value_not(ins)
        elif d == tk.ERL:         return value_erl(ins)
        elif d == tk.ERR:         return value_err(ins)
        elif d == tk.STRING:      return value_string(ins)
        elif d == tk.INSTR:       return value_instr(ins)
        elif d == tk.VARPTR:      return value_varptr(ins)
        elif d == tk.CSRLIN:      return value_csrlin(ins)
        elif d == tk.POINT:       return value_point(ins)
        elif d == tk.INKEY:       return value_inkey(ins)
        elif d == tk.O_PLUS:      return parse_expr_unit(ins)
        elif d == tk.O_MINUS:     return value_neg(ins)
        # two-byte tokens
        elif d == '\xFD':
            d += ins.read(1)
            if d == tk.CVI:       return value_cvi(ins)
            elif d == tk.CVS:     return value_cvs(ins)
            elif d == tk.CVD:     return value_cvd(ins)
            elif d == tk.MKI:     return value_mki(ins)
            elif d == tk.MKS:     return value_mks(ins)
            elif d == tk.MKD:     return value_mkd(ins)
            elif d == tk.EXTERR:  return value_exterr(ins)
        # two-byte tokens
        elif d == '\xFE':
            d += ins.read(1)
            if d == tk.DATE:      return value_date(ins)
            elif d == tk.TIME:    return value_time(ins)
            elif d == tk.PLAY:    return value_play(ins)
            elif d == tk.TIMER:   return value_timer(ins)
            elif d == tk.ERDEV:   return value_erdev(ins)
            elif d == tk.IOCTL:   return value_ioctl(ins)
            elif d == tk.ENVIRON: return value_environ(ins)
            elif d == tk.PMAP:    return value_pmap(ins)
        # two-byte tokens
        elif d == '\xFF':
            d += ins.read(1)
            if d == tk.LEFT:    return value_left(ins)
            elif d == tk.RIGHT: return value_right(ins)
            elif d == tk.MID:   return value_mid(ins)
            elif d == tk.SGN:   return value_sgn(ins)
            elif d == tk.INT:   return value_int(ins)
            elif d == tk.ABS:   return value_abs(ins)
            elif d == tk.SQR:   return value_sqr(ins)
            elif d == tk.RND:   return value_rnd(ins)
            elif d == tk.SIN:   return value_sin(ins)
            elif d == tk.LOG:   return value_log(ins)
            elif d == tk.EXP:   return value_exp(ins)
            elif d == tk.COS:   return value_cos(ins)
            elif d == tk.TAN:   return value_tan(ins)
            elif d == tk.ATN:   return value_atn(ins)
            elif d == tk.FRE:   return value_fre(ins)
            elif d == tk.INP:   return value_inp(ins)
            elif d == tk.POS:   return value_pos(ins)
            elif d == tk.LEN:   return value_len(ins)
            elif d == tk.STR:   return value_str(ins)
            elif d == tk.VAL:   return value_val(ins)
            elif d == tk.ASC:   return value_asc(ins)
            elif d == tk.CHR:   return value_chr(ins)
            elif d == tk.PEEK:  return value_peek(ins)
            elif d == tk.SPACE: return value_space(ins)
            elif d == tk.OCT:   return value_oct(ins)
            elif d == tk.HEX:   return value_hex(ins)
            elif d == tk.LPOS:  return value_lpos(ins)
            elif d == tk.CINT:  return value_cint(ins)
            elif d == tk.CSNG:  return value_csng(ins)
            elif d == tk.CDBL:  return value_cdbl(ins)
            elif d == tk.FIX:   return value_fix(ins)
            elif d == tk.PEN:   return value_pen(ins)
            elif d == tk.STICK: return value_stick(ins)
            elif d == tk.STRIG: return value_strig(ins)
            elif d == tk.EOF:   return value_eof(ins)
            elif d == tk.LOC:   return value_loc(ins)
            elif d == tk.LOF:   return value_lof(ins)
        else:
            return None
Esempio n. 43
0
 def copy_packed(self, key):
     """ Return a packed copy of the string by its 2-byte key or 3-byte sequence. """
     return vartypes.pack_string(self.retrieve(key)[:])
Esempio n. 44
0
def value_mki(ins):
    """ MKI$: return the byte representation of an int. """
    return vartypes.pack_string(
        vartypes.value_to_sint(vartypes.pass_int_unpack(parse_bracket(ins))))
Esempio n. 45
0
    def set_gwbasic_vars(self, dictionary):
        """ Retrieve variables from Python script """
        for new_var_name, new_var_value in dictionary.iteritems():
            var_name = self.name_recover(new_var_name)

            if type(new_var_value) == str:
                if var_name[-1] != '$':
                    raise Exception("Type mismatch. Variable name is %s, but a string value was received (%s)" %
                                    (new_var_name , new_var_value))

                ins = cStringIO.StringIO(var_name)
                var_name = util.get_var_name(ins)
                var.set_var(var_name, vartypes.pack_string(bytearray(new_var_value + "\0")))
            elif type(new_var_value) == int:
                if var_name[-1] != '%':
                    raise Exception("Type mismatch. Variable name is %s, but a integer value was received (%d)" %
                                    (new_var_name , new_var_value))

                ins = cStringIO.StringIO(var_name)
                var_name = util.get_var_name(ins)
                var.set_var(var_name, vartypes.pack_int(new_var_value))
            elif type(new_var_value) == float:
                if var_name[-1] == '!':
                    ins = cStringIO.StringIO(var_name)
                    var_name = util.get_var_name(ins)
                    bytearray_val = fp.Single.from_value(new_var_value).to_bytes()
                    var.set_var(var_name, ('!', bytearray_val))
                elif var_name[-1] == '#':
                    ins = cStringIO.StringIO(var_name)
                    var_name = util.get_var_name(ins)
                    bytearray_val = fp.Double.from_value(new_var_value).to_bytes()
                    var.set_var(var_name, ('#', bytearray_val))
                else:
                    raise Exception("Type mismatch. Variable name is %s, but a floating-point value was received (%f)" %
                                    (new_var_name , new_var_value))
            elif type(new_var_value) == list:
                matrix = np.array(new_var_value)

                dimensions = matrix.shape

                if var_name in state.basic_state.arrays.keys():
                    var.erase_array(var_name)
                dimensions = [x for x in dimensions]
                var.dim_array(var_name, dimensions)

                indexes = [list(xrange(d)) for d in dimensions]
                indexes = list(itertools.product(*indexes))

                for index in indexes:
                    item_value = new_var_value
                    for coord in index:
                        item_value = item_value[coord]

                    if var_name[-1] == '$':
                        matrix_element = vartypes.pack_string(bytearray(item_value + "\0"))
                    elif var_name[-1] == '%':
                        matrix_element = vartypes.pack_int(item_value)
                    elif var_name[-1] == '!':
                        matrix_element = ( '!', fp.Single.from_value(item_value).to_bytes())
                    elif var_name[-1] == '#':
                        matrix_element = ('#', fp.Double.from_value(item_value).to_bytes())
                    else:
                        raise Exception("Array type unknown for variable %s" % new_var_name)

                    try:
                        var.set_var_or_array(var_name, index, matrix_element)
                    except:
                        import traceback
                        traceback.print_exc()

            else:
                logging.debug('Received variable was not processed: %s.', new_var_name)
Esempio n. 46
0
 def copy_packed(self, key):
     """ Return a packed copy of the string by its 2-byte key or 3-byte sequence. """
     return vartypes.pack_string(self.retrieve(key)[:])