def f(x): x = cast_primitive(UnsignedLongLong, x) x <<= 60 x /= 3 x <<= 1 x = cast_primitive(SignedLongLong, x) x >>= 32 return cast_primitive(Signed, x)
def make_stat_result(tup): """Turn a tuple into an os.stat_result object.""" positional = tuple( lltype.cast_primitive(TYPE, value) for value, (name, TYPE) in zip(tup, STAT_FIELDS)[:N_INDEXABLE_FIELDS]) kwds = {} for value, (name, TYPE) in zip(tup, STAT_FIELDS)[N_INDEXABLE_FIELDS:]: kwds[name] = lltype.cast_primitive(TYPE, value) return os.stat_result(positional, kwds)
def make_stat_result(tup): """Turn a tuple into an os.stat_result object.""" positional = tuple( lltype.cast_primitive(TYPE, value) for value, (name, TYPE) in zip(tup, STAT_FIELDS)[:N_INDEXABLE_FIELDS] ) kwds = {} for value, (name, TYPE) in zip(tup, STAT_FIELDS)[N_INDEXABLE_FIELDS:]: kwds[name] = lltype.cast_primitive(TYPE, value) return os.stat_result(positional, kwds)
def convert_const(self, value): if isinstance(value, objectmodel.Symbolic): return value T = typeOf(value) if isinstance(T, Number) or T is Bool: return cast_primitive(self.lowleveltype, value) raise TyperError("not an integer: %r" % (value,))
def convert_const(self, value): if isinstance(value, objectmodel.Symbolic): return value T = typeOf(value) if isinstance(T, Number) or T is Bool: return cast_primitive(self.lowleveltype, value) raise TyperError("not an integer: %r" % (value, ))
def emit_const(self, const, kind, allow_short=False): value = const.value value_key = value if kind == 'int': TYPE = const.concretetype if isinstance(TYPE, lltype.Ptr): assert TYPE.TO._gckind == 'raw' self.see_raw_object(value) value = llmemory.cast_ptr_to_adr(value) TYPE = llmemory.Address if TYPE == llmemory.Address: value = adr2int(value) if TYPE is lltype.SingleFloat: value = longlong.singlefloat2int(value) if not isinstance(value, (llmemory.AddressAsInt, ComputedIntSymbolic)): value = lltype.cast_primitive(lltype.Signed, value) if type(value) is r_int: value = int(value) if allow_short: try: short_num = -128 <= value <= 127 except TypeError: # "Symbolics cannot be compared!" short_num = False if short_num: # emit the constant as a small integer self.code.append(chr(value & 0xFF)) return True constants = self.constants_i elif kind == 'ref': value = lltype.cast_opaque_ptr(llmemory.GCREF, value) constants = self.constants_r if not value: # nullptr value_key = None else: value_key = value._obj.container elif kind == 'float': if const.concretetype == lltype.Float: value = longlong.getfloatstorage(value) else: assert longlong.is_longlong(const.concretetype) value = rffi.cast(lltype.SignedLongLong, value) constants = self.constants_f else: raise AssemblerError('unimplemented %r in %r' % (const, self.ssareprname)) key = (kind, Constant(value_key)) try: val = self.constants_dict[key] except KeyError: constants.append(value) val = 256 - len(constants) assert val >= 0, "too many constants" self.constants_dict[key] = val # emit the constant normally, as one byte that is an index in the # list of constants self.code.append(chr(val)) return False
def ll_decode_latin1(self, value): sb = ootype.new(ootype.UnicodeBuilder) length = value.ll_strlen() sb.ll_allocate(length) for i in range(length): c = value.ll_stritem_nonneg(i) sb.ll_append_char(cast_primitive(UniChar, c)) return sb.ll_build()
def ll_str2unicode(str): lgt = len(str.chars) s = mallocunicode(lgt) for i in range(lgt): if ord(str.chars[i]) > 127: raise UnicodeDecodeError s.chars[i] = cast_primitive(UniChar, str.chars[i]) return s
def typed_write(self, TP, byte_offset, value): if self.readonly or not is_alignment_correct(TP, byte_offset): raise CannotWrite lldata = self._get_gc_data() byte_offset += self._get_gc_data_extra_offset() value = lltype.cast_primitive(TP, value) return llop.gc_store_indexed(lltype.Void, lldata, byte_offset, value, scale_factor, base_ofs)
def typed_write(self, TP, byte_offset, value): """ Write the value of type TP at byte_offset. No bounds checks """ if self.readonly or not is_alignment_correct(TP, byte_offset): raise CannotWrite ptr = self.get_raw_address() value = lltype.cast_primitive(TP, value) return llop.raw_store(lltype.Void, ptr, byte_offset, value)
def make_stat_result(tup): """Turn a tuple into an os.stat_result object.""" assert len(tup) == len(STAT_FIELDS) assert float not in [type(x) for x in tup] positional = [] for i in range(N_INDEXABLE_FIELDS): name, TYPE = STAT_FIELDS[i] value = lltype.cast_primitive(TYPE, tup[i]) positional.append(value) kwds = {} kwds['st_atime'] = tup[7] + 1e-9 * tup[-3] kwds['st_mtime'] = tup[8] + 1e-9 * tup[-2] kwds['st_ctime'] = tup[9] + 1e-9 * tup[-1] for value, (name, TYPE) in zip(tup, STAT_FIELDS)[N_INDEXABLE_FIELDS:]: if name.startswith('nsec_'): continue # ignore the nsec_Xtime here kwds[name] = lltype.cast_primitive(TYPE, value) return os.stat_result(positional, kwds)
def cast_to_int(x): TP = lltype.typeOf(x) if isinstance(TP, lltype.Ptr): return heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) if TP == llmemory.Address: return heaptracker.adr2int(x) if TP is lltype.SingleFloat: return longlong.singlefloat2int(x) return lltype.cast_primitive(lltype.Signed, x)
def ll_encode_latin1(self, s): length = len(s.chars) result = mallocstr(length) for i in range(length): c = s.chars[i] if ord(c) > 255: raise UnicodeEncodeError("character not in latin1 range") result.chars[i] = cast_primitive(Char, c) return result
def ll_encode_latin1(self, value): sb = ootype.new(ootype.StringBuilder) length = value.ll_strlen() sb.ll_allocate(length) for i in range(length): c = value.ll_stritem_nonneg(i) if ord(c) > 255: raise UnicodeEncodeError("%d > 255, not latin-1" % ord(c)) sb.ll_append_char(cast_primitive(Char, c)) return sb.ll_build()
def unspecialize_value(value): """Casts 'value' to a Signed, a GCREF or a FLOATSTORAGE.""" if isinstance(lltype.typeOf(value), lltype.Ptr): if lltype.typeOf(value).TO._gckind == 'gc': return lltype.cast_opaque_ptr(llmemory.GCREF, value) else: return ptr2int(value) elif isinstance(value, float): return longlong.getfloatstorage(value) else: return lltype.cast_primitive(lltype.Signed, value)
def unwrap(TYPE, box): if TYPE is lltype.Void: return None if isinstance(TYPE, lltype.Ptr): if TYPE.TO._gckind == "gc": return box.getref(TYPE) else: return llmemory.cast_adr_to_ptr(box.getaddr(), TYPE) if TYPE == lltype.Float: return box.getfloat() else: return lltype.cast_primitive(TYPE, box.getint())
def ll_str(self, value): if not value: return self.ll.ll_constant('None') sb = ootype.new(ootype.StringBuilder) lgt = value.ll_strlen() sb.ll_allocate(lgt) for i in range(lgt): c = value.ll_stritem_nonneg(i) if ord(c) > 127: raise UnicodeEncodeError("%d > 127, not ascii" % ord(c)) sb.ll_append_char(cast_primitive(Char, c)) return sb.ll_build()
def unspecialize_value(value): """Casts 'value' to a Signed, a GCREF or a FLOATSTORAGE.""" if isinstance(lltype.typeOf(value), lltype.Ptr): if lltype.typeOf(value).TO._gckind == 'gc': return lltype.cast_opaque_ptr(llmemory.GCREF, value) else: adr = llmemory.cast_ptr_to_adr(value) return heaptracker.adr2int(adr) elif isinstance(value, float): return longlong.getfloatstorage(value) else: return lltype.cast_primitive(lltype.Signed, value)
def newlist_and_gc_store(TYPE, value): size = rffi.sizeof(TYPE) lst = resizable_list_supporting_raw_ptr(['\x00'] * size) ll_data = ll_for_resizable_list(lst) ll_items = ll_data.items LIST = lltype.typeOf(ll_data).TO # rlist.LIST_OF(lltype.Char) base_ofs = llmemory.itemoffsetof(LIST.items.TO, 0) scale_factor = llmemory.sizeof(lltype.Char) value = lltype.cast_primitive(TYPE, value) llop.gc_store_indexed(lltype.Void, ll_items, 0, value, scale_factor, base_ofs) return lst
def ll_str(self, s): # XXX crazy that this is here, but I don't want to break # rmodel logic if not s: return self.ll.ll_constant('None') lgt = len(s.chars) result = mallocstr(lgt) for i in range(lgt): c = s.chars[i] if ord(c) > 127: raise UnicodeEncodeError("character not in ascii range") result.chars[i] = cast_primitive(Char, c) return result
def _new(x): "NOT_RPYTHON" kind = getkind(lltype.typeOf(x)) if kind == "int": intval = lltype.cast_primitive(lltype.Signed, x) return BoxInt(intval) elif kind == "ref": ptrval = lltype.cast_opaque_ptr(llmemory.GCREF, x) return BoxPtr(ptrval) elif kind == "float": return BoxFloat(longlong.getfloatstorage(x)) else: raise NotImplementedError(kind)
def get_string(self, builder, r): current = getattr(builder, self.builder_cache) if current and r.random() < .8: v_string = r.choice(current) string = v_string.getref(self.ptr) else: string = self.alloc(builder.get_index(500, r).getint()) v_string = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, string)) current.append(v_string) for i in range(len(string.chars)): char = r.random_integer() % self.max string.chars[i] = lltype.cast_primitive(self.primitive, char) return v_string
def get_string(self, builder, r): current = getattr(builder, self.builder_cache) if current and r.random() < .8: v_string = r.choice(current) string = getref(self.ptr, v_string) else: string = self.alloc(getint(builder.get_index(500, r))) v_string = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, string)) current.append(v_string) for i in range(len(string.chars)): char = r.random_integer() % self.max string.chars[i] = lltype.cast_primitive(self.primitive, char) return v_string
def _new(x): "NOT_RPYTHON" T = lltype.typeOf(x) kind = getkind(T) if kind == "int": if isinstance(T, lltype.Ptr): intval = ptr2int(x) else: intval = lltype.cast_primitive(lltype.Signed, x) return ConstInt(intval) elif kind == "float": return ConstFloat(longlong.getfloatstorage(x)) else: raise NotImplementedError(kind)
def ll_join_chars(length_dummy, lst, RES): if RES is ootype.String: target = Char buf = ootype.new(ootype.StringBuilder) else: target = UniChar buf = ootype.new(ootype.UnicodeBuilder) length = lst.ll_length() buf.ll_allocate(length) i = 0 while i < length: buf.ll_append_char(cast_primitive(target, lst.ll_getitem_fast(i))) i += 1 return buf.ll_build()
def initialize_from_env(): # This uses the same algorithms as CPython 3.5. The environment # variable we read also defaults to "PYTHONHASHSEED". If needed, # a different RPython interpreter can patch the value of the # global variable 'env_var_name', or just patch the whole # initialize_from_env() function. value = os.environ.get(env_var_name) if value and value != "random": with rffi.scoped_view_charp(value) as ptr: with lltype.scoped_alloc(rffi.CCHARPP.TO, 1) as endptr: endptr[0] = ptr seed = strtoul(ptr, endptr, 10) full = endptr[0][0] == '\x00' seed = lltype.cast_primitive(lltype.Unsigned, seed) if not full or seed > r_uint(4294967295) or ( rposix.get_saved_errno() == errno.ERANGE and seed == lltype.cast_primitive(lltype.Unsigned, rffi.cast(rffi.ULONG, -1))): os.write( 2, "%s must be \"random\" or an integer " "in range [0; 4294967295]\n" % (env_var_name, )) os._exit(1) if not seed: # disable the randomized hash s = '\x00' * 16 else: s = lcg_urandom(seed) else: try: s = rurandom.urandom(random_ctx, 16) except Exception as e: os.write( 2, "%s: failed to get random numbers to initialize Python\n" % (str(e), )) os._exit(1) raise # makes the annotator happy select_random_seed(s)
def PyMember_GetOne(space, obj, w_member): addr = rffi.cast(ADDR, obj) addr += w_member.c_offset member_type = rffi.cast(lltype.Signed, w_member.c_type) for converter in integer_converters: typ, lltyp, _ = converter if typ == member_type: result = rffi.cast(rffi.CArrayPtr(lltyp), addr) if lltyp is rffi.FLOAT: w_result = space.newfloat( lltype.cast_primitive(lltype.Float, result[0])) elif typ == T_BOOL: x = rffi.cast(lltype.Signed, result[0]) w_result = space.newbool(x != 0) elif typ == T_DOUBLE: w_result = space.newfloat(result[0]) else: w_result = space.newint(result[0]) return w_result if member_type == T_STRING: result = rffi.cast(rffi.CCHARPP, addr) if result[0]: w_result = PyString_FromString(space, result[0]) else: w_result = space.w_None elif member_type == T_STRING_INPLACE: result = rffi.cast(rffi.CCHARP, addr) w_result = PyString_FromString(space, result) elif member_type == T_CHAR: result = rffi.cast(rffi.CCHARP, addr) w_result = space.newtext(result[0]) elif member_type == T_OBJECT: obj_ptr = rffi.cast(PyObjectP, addr) if obj_ptr[0]: w_result = from_ref(space, obj_ptr[0]) else: w_result = space.w_None elif member_type == T_OBJECT_EX: obj_ptr = rffi.cast(PyObjectP, addr) if obj_ptr[0]: w_result = from_ref(space, obj_ptr[0]) else: w_name = space.newtext(rffi.charp2str(w_member.c_name)) raise OperationError(space.w_AttributeError, w_name) else: raise oefmt(space.w_SystemError, "bad memberdescr type") return w_result
def emit_const(self, const, kind, allow_short=False): value = const.value if kind == 'int': TYPE = const.concretetype if isinstance(TYPE, lltype.Ptr): assert TYPE.TO._gckind == 'raw' self.see_raw_object(value) value = llmemory.cast_ptr_to_adr(value) TYPE = llmemory.Address if TYPE == llmemory.Address: value = heaptracker.adr2int(value) if TYPE is lltype.SingleFloat: value = longlong.singlefloat2int(value) if not isinstance(value, (llmemory.AddressAsInt, ComputedIntSymbolic)): value = lltype.cast_primitive(lltype.Signed, value) if allow_short: try: short_num = -128 <= value <= 127 except TypeError: # "Symbolics cannot be compared!" short_num = False if short_num: # emit the constant as a small integer self.code.append(chr(value & 0xFF)) return True constants = self.constants_i elif kind == 'ref': value = lltype.cast_opaque_ptr(llmemory.GCREF, value) constants = self.constants_r elif kind == 'float': if const.concretetype == lltype.Float: value = longlong.getfloatstorage(value) else: assert longlong.is_longlong(const.concretetype) value = rffi.cast(lltype.SignedLongLong, value) constants = self.constants_f else: raise AssemblerError('unimplemented %r in %r' % (const, self.ssareprname)) key = (kind, Constant(value)) if key not in self.constants_dict: constants.append(value) val = 256 - len(constants) assert val >= 0, "too many constants" self.constants_dict[key] = val # emit the constant normally, as one byte that is an index in the # list of constants self.code.append(chr(self.constants_dict[key])) return False
def PyMember_GetOne(space, obj, w_member): addr = rffi.cast(ADDR, obj) addr += w_member.c_offset member_type = rffi.cast(lltype.Signed, w_member.c_type) for converter in integer_converters: typ, lltyp, _ = converter if typ == member_type: result = rffi.cast(rffi.CArrayPtr(lltyp), addr) if lltyp is rffi.FLOAT: w_result = space.wrap(lltype.cast_primitive(lltype.Float, result[0])) elif typ == T_BOOL: x = rffi.cast(lltype.Signed, result[0]) w_result = space.wrap(x != 0) else: w_result = space.wrap(result[0]) return w_result if member_type == T_STRING: result = rffi.cast(rffi.CCHARPP, addr) if result[0]: w_result = PyString_FromString(space, result[0]) else: w_result = space.w_None elif member_type == T_STRING_INPLACE: result = rffi.cast(rffi.CCHARP, addr) w_result = PyString_FromString(space, result) elif member_type == T_CHAR: result = rffi.cast(rffi.CCHARP, addr) w_result = space.wrap(result[0]) elif member_type == T_OBJECT: obj_ptr = rffi.cast(PyObjectP, addr) if obj_ptr[0]: w_result = from_ref(space, obj_ptr[0]) else: w_result = space.w_None elif member_type == T_OBJECT_EX: obj_ptr = rffi.cast(PyObjectP, addr) if obj_ptr[0]: w_result = from_ref(space, obj_ptr[0]) else: w_name = space.wrap(rffi.charp2str(w_member.c_name)) raise OperationError(space.w_AttributeError, w_name) else: raise OperationError(space.w_SystemError, space.wrap("bad memberdescr type")) return w_result
def _new(x): "NOT_RPYTHON" T = lltype.typeOf(x) kind = getkind(T) if kind == "int": if isinstance(T, lltype.Ptr): intval = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) else: intval = lltype.cast_primitive(lltype.Signed, x) return ConstInt(intval) elif kind == "ref": return cpu.ts.new_ConstRef(x) elif kind == "float": return ConstFloat(longlong.getfloatstorage(x)) else: raise NotImplementedError(kind)
def convert_const(self, value): if value is None: return nullptr(self.lowleveltype.TO) #value = getattr(value, '__self__', value) # for bound string methods if not isinstance(value, self.basetype): raise TyperError("not a str: %r" % (value,)) try: return self.CACHE[value] except KeyError: p = self.malloc(len(value)) for i in range(len(value)): p.chars[i] = cast_primitive(self.base, value[i]) p.hash = 0 self.ll.ll_strhash(p) # precompute the hash self.CACHE[value] = p return p
def convert_const(self, value): if value is None: return nullptr(self.lowleveltype.TO) #value = getattr(value, '__self__', value) # for bound string methods if not isinstance(value, self.basetype): raise TyperError("not a str: %r" % (value, )) try: return self.CACHE[value] except KeyError: p = self.malloc(len(value)) for i in range(len(value)): p.chars[i] = cast_primitive(self.base, value[i]) p.hash = 0 self.ll.ll_strhash(p) # precompute the hash self.CACHE[value] = p return p
def ll_join_chars(length, chars, RES): # no need to optimize this, will be replaced by string builder # at some point soon num_chars = length if RES is StringRepr.lowleveltype: target = Char malloc = mallocstr else: target = UniChar malloc = mallocunicode result = malloc(num_chars) res_chars = result.chars i = 0 while i < num_chars: res_chars[i] = cast_primitive(target, chars[i]) i += 1 return result
def gc_load_from_string(self, TYPE, buf, offset): if TYPE not in self.cache_load: assert isinstance(TYPE, lltype.Primitive) if TYPE in (lltype.Float, lltype.SingleFloat): TARGET_TYPE = lltype.Float else: TARGET_TYPE = lltype.Signed def llf(buf, offset): x = str_gc_load(TYPE, buf, offset) return lltype.cast_primitive(TARGET_TYPE, x) fn = compile(llf, [str, int]) self.cache_load[TYPE] = fn # fn = self.cache_load[TYPE] x = fn(buf, offset) return lltype.cast_primitive(TYPE, x)
def specialize_value(TYPE, x): """'x' must be a Signed, a GCREF or a FLOATSTORAGE. This function casts it to a more specialized type, like Char or Ptr(..). """ INPUT = lltype.typeOf(x) if INPUT is lltype.Signed: if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'raw': # non-gc pointer return rffi.cast(TYPE, x) elif TYPE is lltype.SingleFloat: return longlong.int2singlefloat(x) else: return lltype.cast_primitive(TYPE, x) elif INPUT is longlong.FLOATSTORAGE: if longlong.is_longlong(TYPE): return rffi.cast(TYPE, x) assert TYPE is lltype.Float return longlong.getrealfloat(x) else: return lltype.cast_opaque_ptr(TYPE, x)
def cast_from_int(TYPE, x): if isinstance(TYPE, lltype.Ptr): if isinstance(x, (int, long, llmemory.AddressAsInt)): x = llmemory.cast_int_to_adr(x) #if repr(x.ptr).startswith('<* <C object '): # pom pom pom # # assume that we want a "C-style" cast, without typechecking the value return rffi.cast(TYPE, x) #return llmemory.cast_adr_to_ptr(x, TYPE) elif TYPE == llmemory.Address: if isinstance(x, (int, long, llmemory.AddressAsInt)): x = llmemory.cast_int_to_adr(x) assert lltype.typeOf(x) == llmemory.Address return x elif TYPE is lltype.SingleFloat: assert lltype.typeOf(x) is lltype.Signed return longlong.int2singlefloat(x) else: if lltype.typeOf(x) == llmemory.Address: x = heaptracker.adr2int(x) return lltype.cast_primitive(TYPE, x)
def str_storage_getitem(self, TYPE, buf, offset): if TYPE not in self.cache: from rpython.translator.c.test.test_genc import compile assert isinstance(TYPE, lltype.Primitive) if TYPE in (lltype.Float, lltype.SingleFloat): TARGET_TYPE = lltype.Float else: TARGET_TYPE = lltype.Signed def llf(buf, offset): x = str_storage_getitem(TYPE, buf, offset) return lltype.cast_primitive(TARGET_TYPE, x) fn = compile(llf, [str, int]) self.cache[TYPE] = fn # fn = self.cache[TYPE] x = fn(buf, offset) return lltype.cast_primitive(TYPE, x)
def read(self, TYPE, data, offset): if TYPE not in self.cache: from rpython.translator.c.test.test_genc import compile assert isinstance(TYPE, lltype.Primitive) if TYPE in (lltype.Float, lltype.SingleFloat): TARGET_TYPE = lltype.Float else: TARGET_TYPE = lltype.Signed def llf(data, offset): buf = StringBuffer(data) x = buf.typed_read(TYPE, offset) return lltype.cast_primitive(TARGET_TYPE, x) fn = compile(llf, [str, int]) self.cache[TYPE] = fn # fn = self.cache[TYPE] x = fn(data, offset) return lltype.cast_primitive(TYPE, x)
def process_args(args): real_args = [] ARGS = lltype.typeOf(funcobj).ARGS i = 0 for ARG in ARGS: if ARG is lltype.Void: real_args.append(None) else: if ARG is lltype.Float: real_args.append(args[i]) elif isinstance(ARG, lltype.Primitive): real_args.append(lltype.cast_primitive(ARG, args[i])) elif isinstance(ARG, lltype.Ptr): if ARG.TO._gckind == 'gc': real_args.append(lltype.cast_opaque_ptr(ARG, args[i])) else: real_args.append(rffi.cast(ARG, args[i])) else: raise Exception("Unexpected arg: %s" % ARG) i += 1 return real_args
def strslice2unicode_latin1(s, start, end): """ Convert s[start:end] to unicode. s is supposed to be an RPython string encoded in latin-1, which means that the numeric value of each char is the same as the corresponding unicode code point. Internally it's implemented at the level of low-level helpers, to avoid the extra copy we would need if we take the actual slice first. No bound checking is done, use carefully. """ from rpython.rtyper.annlowlevel import llstr, hlunicode from rpython.rtyper.lltypesystem.rstr import malloc, UNICODE from rpython.rtyper.lltypesystem.lltype import cast_primitive, UniChar length = end-start ll_s = llstr(s) ll_res = malloc(UNICODE, length) ll_res.hash = 0 for i in range(length): ch = ll_s.chars[start+i] ll_res.chars[i] = cast_primitive(UniChar, ch) return hlunicode(ll_res)
def make_statvfs_result(tup): args = tuple(lltype.cast_primitive(TYPE, value) for value, (name, TYPE) in zip(tup, STATVFS_FIELDS)) return os.statvfs_result(args)
def op_cast_primitive(TYPE, value): assert isinstance(lltype.typeOf(value), lltype.Primitive) return lltype.cast_primitive(TYPE, value)
def llf(v): return lltype.cast_primitive(lltype.Bool, v)
def llf(v): return lltype.cast_primitive(lltype.Signed, v)