Here is the string patch with the interpreter left in. Take your pick :-)
David Index: Makefile.in =================================================================== RCS file: /cvs/public/parrot/Makefile.in,v retrieving revision 1.85 diff -c -r1.85 Makefile.in *** Makefile.in 27 Dec 2001 23:57:58 -0000 1.85 --- Makefile.in 30 Dec 2001 08:38:15 -0000 *************** *** 44,50 **** #XXX This target is not portable to Win32 ! shared: libparrot.so libcore_prederef_0_3.so libparrot.so: $(O_FILES) $(CC) -shared $(C_LIBS) -o $@ $(O_FILES) --- 44,50 ---- #XXX This target is not portable to Win32 ! shared: Libparrot.so libcore_prederef_0_3.so libparrot.so: $(O_FILES) $(CC) -shared $(C_LIBS) -o $@ $(O_FILES) *************** *** 173,178 **** --- 173,179 ---- $(RM_F) Parrot/Jit.pm $(RM_F) include/parrot/jit_struct.h $(RM_F) libparrot.so libcore_prederef_0_3.so + $(RM_F) *~ cd docs && $(MAKE) clean && cd .. cd classes && $(MAKE) clean && cd .. cd languages && $(MAKE) clean && cd .. Index: core.ops =================================================================== RCS file: /cvs/public/parrot/core.ops,v retrieving revision 1.60 diff -c -r1.60 core.ops *** core.ops 28 Dec 2001 21:20:19 -0000 1.60 --- core.ops 30 Dec 2001 08:38:18 -0000 *************** *** 104,110 **** op err(s) { char *tmp = strerror(errno); ! STRING *s = string_make(interpreter, tmp, strlen(tmp), 0, 0, 0); $1 = s; goto NEXT(); } --- 104,110 ---- op err(s) { char *tmp = strerror(errno); ! STRING *s = string_make(interpreter, tmp, strlen(tmp), NULL, 0, NULL); $1 = s; goto NEXT(); } *************** *** 165,174 **** default: file = (FILE *)$2; } ! string_grow($1, 65535); memset(($1)->bufstart, 0, 65535); fgets(($1)->bufstart, 65534, file); ! ($1)->strlen = strlen(($1)->bufstart); goto NEXT(); } --- 165,174 ---- default: file = (FILE *)$2; } ! $1 = string_make(interpreter, NULL, 65535, NULL, 0, NULL); memset(($1)->bufstart, 0, 65535); fgets(($1)->bufstart, 65534, file); ! ($1)->strlen = ($1)->bufused = strlen(($1)->bufstart); goto NEXT(); } *************** *** 359,369 **** INTVAL len = $3; string_destroy($1); ! tmp = malloc(len + 1); ! read($2, tmp, len); ! s = string_make(interpreter, tmp, len, 0, 0, 0); $1 = s; - free(tmp); goto NEXT(); } --- 359,368 ---- INTVAL len = $3; string_destroy($1); ! s = string_make(interpreter, NULL, len, NULL, 0, NULL); ! read($2, s->bufstart, len); ! s->bufused = s->buflen; $1 = s; goto NEXT(); } *************** *** 860,865 **** --- 859,868 ---- =item B<lt>(s, sc, ic) + =item B<lt>(sc, s, ic) + + =item B<lt>(sc, sc, ic) + Branch if $1 is less than $2. =cut *************** *** 885,890 **** --- 888,900 ---- goto NEXT(); } + op lt(sc, s|sc, ic) { + if (string_compare(interpreter, $1, $2) < 0) { + goto OFFSET($3); + } + goto NEXT(); + } + ######################################## *************** *** 900,905 **** --- 910,919 ---- =item B<le>(s, sc, ic) + =item B<le>(sc, s, ic) + + =item B<le>(sc, sc, ic) + Branch if $1 is less than or equal to $2. =cut *************** *** 925,930 **** --- 939,951 ---- goto NEXT(); } + op le(sc, s|sc, ic) { + if (string_compare(interpreter, $1, $2) <= 0) { + goto OFFSET($3); + } + goto NEXT(); + } + ######################################## *************** *** 940,945 **** --- 961,970 ---- =item B<gt>(s, sc, ic) + =item B<gt>(sc, s, ic) + + =item B<gt>(sc, sc, ic) + Branch if $1 is greater than $2. =cut *************** *** 965,970 **** --- 990,1002 ---- goto NEXT(); } + op gt(sc, s|sc, ic) { + if (string_compare(interpreter, $1, $2) > 0) { + goto OFFSET($3); + } + goto NEXT(); + } + ######################################## *************** *** 980,985 **** --- 1012,1021 ---- =item B<ge>(s, sc, ic) + =item B<ge>(sc, s, ic) + + =item B<ge>(sc, sc, ic) + Branch if $1 is greater than or equal to $2. =cut *************** *** 1005,1010 **** --- 1041,1053 ---- goto NEXT(); } + op ge(sc, s|sc, ic) { + if (string_compare(interpreter, $1, $2) >= 0) { + goto OFFSET($3); + } + goto NEXT(); + } + ######################################## *************** *** 1035,1041 **** } op if (s, ic) { ! if (string_bool(interpreter, $1)) { goto OFFSET($2); } goto NEXT(); --- 1078,1084 ---- } op if (s, ic) { ! if (string_bool($1)) { goto OFFSET($2); } goto NEXT(); *************** *** 1117,1123 **** $1 = $2 + $3; goto NEXT(); } - ######################################## --- 1160,1165 ---- Index: packfile.c =================================================================== RCS file: /cvs/public/parrot/packfile.c,v retrieving revision 1.16 diff -c -r1.16 packfile.c *** packfile.c 6 Dec 2001 21:22:13 -0000 1.16 --- packfile.c 30 Dec 2001 08:38:21 -0000 *************** *** 1484,1493 **** self->type = PFC_STRING; if (encoding == 0) { ! self->string = string_make(interpreter, cursor, size, NULL, flags, NULL); /* fixme */ } else if (encoding == 3) { ! self->string = string_make(interpreter, cursor, size, encoding_lookup("utf32"), flags, chartype_lookup("unicode")); /* fixme */ } else { return 0; --- 1484,1496 ---- self->type = PFC_STRING; if (encoding == 0) { ! self->string = string_make(interpreter, cursor, size, NULL, flags, ! NULL); /* fixme */ } else if (encoding == 3) { ! self->string = string_make(interpreter, cursor, size, ! encoding_lookup("utf32"), flags, ! chartype_lookup("unicode")); /* fixme */ } else { return 0; Index: pbc2c.pl =================================================================== RCS file: /cvs/public/parrot/pbc2c.pl,v retrieving revision 1.8 diff -c -r1.8 pbc2c.pl *** pbc2c.pl 27 Dec 2001 21:18:03 -0000 1.8 --- pbc2c.pl 30 Dec 2001 08:38:21 -0000 *************** *** 123,129 **** $data = '"' . $data . '"' unless $data =~ m/^"/; print <<END_C; ! c = PackFile_Constant_new_string(interpreter, string_make(interpreter, $data, $size, $encoding, $flags, $type)); END_C } else { die; --- 123,130 ---- $data = '"' . $data . '"' unless $data =~ m/^"/; print <<END_C; ! c = PackFile_Constant_new_string(interpreter, string_make(interpreter, ! $data, $size, $encoding, $flags, $type)); END_C } else { die; Index: string.c =================================================================== RCS file: /cvs/public/parrot/string.c,v retrieving revision 1.27 diff -c -r1.27 string.c *** string.c 29 Dec 2001 22:12:37 -0000 1.27 --- string.c 30 Dec 2001 08:38:22 -0000 *************** *** 1,7 **** /* string.c * Copyright: (When this is determined...it will go here) * CVS Info ! * $Id: string.c,v 1.27 2001/12/29 22:12:37 dan Exp $ * Overview: * This is the api definitions for the string subsystem * Data Structure and Algorithms: --- 1,7 ---- /* string.c * Copyright: (When this is determined...it will go here) * CVS Info ! * $Id: string.c,v 1.26 2001/12/28 18:20:12 ajgough Exp $ * Overview: * This is the api definitions for the string subsystem * Data Structure and Algorithms: *************** *** 31,39 **** * and compute its string length */ STRING * ! string_make(struct Parrot_Interp *interpreter, void *buffer, INTVAL buflen, ! const ENCODING *encoding, INTVAL flags, const CHARTYPE *type) { ! STRING *s = new_string_header(interpreter); if (!type) { type = string_native_type; --- 31,40 ---- * and compute its string length */ STRING * ! string_make(struct Parrot_Interp *interpreter, const void *buffer, ! INTVAL buflen, const ENCODING *encoding, INTVAL flags, ! const CHARTYPE *type) { ! STRING *s; if (!type) { type = string_native_type; *************** *** 43,69 **** encoding = encoding_lookup(type->default_encoding); } ! s->bufstart = mem_sys_allocate(buflen); ! mem_sys_memcopy(s->bufstart, buffer, buflen); s->encoding = encoding; - s->buflen = s->bufused = buflen; s->flags = flags; - string_compute_strlen(s); s->type = type; ! return s; ! } ! ! /*=for api string string_grow ! * reallocate memory for the string if it is too small ! */ ! void ! string_grow(STRING* s, INTVAL newsize) { ! INTVAL newsize_in_bytes = string_max_bytes(s, newsize); ! if (s->buflen < newsize_in_bytes) { ! s->bufstart = mem_sys_realloc(s->bufstart, newsize_in_bytes); } ! s->buflen = newsize_in_bytes; } /*=for api string string_destroy --- 44,68 ---- encoding = encoding_lookup(type->default_encoding); } ! s = mem_sys_allocate(sizeof(STRING)+buflen); s->encoding = encoding; s->flags = flags; s->type = type; + s->buflen = buflen; ! if (buffer) { ! mem_sys_memcopy(s->bufstart, buffer, buflen); ! s->bufused = buflen; ! string_compute_strlen(s); ! } ! else { ! s->strlen = s->bufused = 0; } ! ! /* Make it null terminate. This will simplify making a native string */ ! s->bufstart[s->bufused]='\0'; ! ! return s; } /*=for api string string_destroy *************** *** 80,86 **** * return the length of the string */ INTVAL ! string_length(STRING* s) { return s->strlen; } --- 79,85 ---- * return the length of the string */ INTVAL ! string_length(const STRING* s) { return s->strlen; } *************** *** 91,97 **** * functions are fleshed out, this function can DTRT. */ static INTVAL ! string_index(STRING* s, INTVAL index) { return s->encoding->decode(s->encoding->skip_forward(s->bufstart, index)); } --- 90,96 ---- * functions are fleshed out, this function can DTRT. */ static INTVAL ! string_index(const STRING* s, INTVAL index) { return s->encoding->decode(s->encoding->skip_forward(s->bufstart, index)); } *************** *** 99,105 **** * return the length of the string */ INTVAL ! string_ord(STRING* s, INTVAL index) { if((s == NULL) || (string_length(s) == 0)) { INTERNAL_EXCEPTION(ORD_OUT_OF_STRING, "Cannot get character of empty string"); --- 98,104 ---- * return the length of the string */ INTVAL ! string_ord(const STRING* s, INTVAL index) { if((s == NULL) || (string_length(s) == 0)) { INTERNAL_EXCEPTION(ORD_OUT_OF_STRING, "Cannot get character of empty string"); *************** *** 129,136 **** * create a copy of the argument passed in */ STRING* ! string_copy(struct Parrot_Interp *interpreter, STRING *s) { ! return string_make(interpreter, s->bufstart, s->bufused, s->encoding, s->flags, s->type); } --- 128,135 ---- * create a copy of the argument passed in */ STRING* ! string_copy(struct Parrot_Interp *interpreter, const STRING *s) { ! return string_make(interpreter, s->bufstart, s->bufused, s->encoding, s->flags, s->type); } *************** *** 138,199 **** * create a transcoded copy of the argument passed in */ STRING* ! string_transcode(struct Parrot_Interp *interpreter, STRING *src, ! const ENCODING *encoding, const CHARTYPE *type, ! STRING *dest) { ! if (!dest) { ! dest = string_make(interpreter, NULL, 0, encoding, 0, type); ! } ! else { ! dest->encoding = encoding; ! dest->type = type; ! } ! string_grow(dest, src->strlen); ! ! if (src->encoding == dest->encoding && src->type == dest->type) { ! mem_sys_memcopy(dest->bufstart, src->bufstart, src->bufused); ! ! dest->bufused = src->bufused; ! } ! else { ! CHARTYPE_TRANSCODER transcoder1 = NULL; ! CHARTYPE_TRANSCODER transcoder2 = NULL; ! char *srcstart; ! char *srcend; ! char *deststart; ! char *destend; ! ! if (src->type != dest->type) { ! transcoder1 = chartype_lookup_transcoder(src->type, dest->type); ! if (!transcoder1) { ! transcoder1 = chartype_lookup_transcoder(src->type, ! string_unicode_type); ! transcoder2 = chartype_lookup_transcoder(string_unicode_type, ! dest->type); ! } ! } ! ! srcstart = src->bufstart; ! srcend = srcstart + src->bufused; ! deststart = dest->bufstart; ! destend = deststart + dest->buflen; ! ! while (srcstart < srcend) { ! INTVAL c = src->encoding->decode(srcstart); ! ! if (transcoder1) c = transcoder1(c); ! if (transcoder2) c = transcoder2(c); ! ! deststart = dest->encoding->encode(deststart, c); ! ! srcstart = src->encoding->skip_forward(srcstart, 1); } ! dest->bufused = destend - deststart; } dest->strlen = src->strlen; return dest; } --- 137,194 ---- * create a transcoded copy of the argument passed in */ STRING* ! string_transcode(struct Parrot_Interp *interpreter, ! const STRING *src, const ENCODING *encoding, ! const CHARTYPE *type, STRING **dest_ptr) { ! STRING *dest; ! CHARTYPE_TRANSCODER transcoder1 = NULL; ! CHARTYPE_TRANSCODER transcoder2 = NULL; ! void *srcstart; ! void *srcend; ! void *deststart; ! void *destend; ! ! if (src->encoding == encoding && src->type == type) { ! return string_copy(interpreter, src); ! } ! ! dest = string_make(interpreter, NULL, src->strlen*src->encoding->max_bytes, ! encoding, 0, type); ! ! if (src->type != dest->type) { ! transcoder1 = chartype_lookup_transcoder(src->type, dest->type); ! if (!transcoder1) { ! transcoder1 = chartype_lookup_transcoder(src->type, ! string_unicode_type); ! transcoder2 = chartype_lookup_transcoder(string_unicode_type, ! dest->type); } + } ! srcstart = (void*)src->bufstart; ! srcend = srcstart + src->bufused; ! deststart = dest->bufstart; ! destend = deststart + dest->buflen; ! ! while (srcstart < srcend) { ! INTVAL c = src->encoding->decode(srcstart); ! ! if (transcoder1) c = transcoder1(c); ! if (transcoder2) c = transcoder2(c); ! ! deststart = dest->encoding->encode(deststart, c); ! ! srcstart = src->encoding->skip_forward(srcstart, 1); } + dest->bufused = destend - deststart; dest->strlen = src->strlen; + dest->bufstart[dest->bufused]='\0'; + + if (dest_ptr) { + *dest_ptr = dest; + } return dest; } *************** *** 209,249 **** return s->strlen; } - /*=for api string string_max_bytes - * get the maximum number of bytes needed by iv characters - */ - INTVAL - string_max_bytes(STRING* s, INTVAL iv) { - return iv * s->encoding->max_bytes; - } - /*=for api string string_concat * concatenate two strings */ STRING* ! string_concat(struct Parrot_Interp *interpreter, STRING* a, STRING* b, ! INTVAL flags) { ! if(a != NULL) { ! if (b == NULL || b->strlen == 0) { ! return a; } ! if (a->type != b->type || a->encoding != b->encoding) { ! b = string_transcode(interpreter, b, a->encoding, a->type, NULL); } - string_grow(a, a->strlen + b->strlen); - mem_sys_memcopy((void*)((ptrcast_t)a->bufstart + a->bufused), - b->bufstart, b->bufused); - a->strlen = a->strlen + b->strlen; - a->bufused = a->bufused + b->bufused; } else { ! if (b == NULL) { ! return string_make(interpreter, "", 0, 0, 0, 0); } - return string_make(interpreter, - b->bufstart,b->buflen,b->encoding,flags,b->type); } ! return a; } /*=for api string string_repeat --- 204,250 ---- return s->strlen; } /*=for api string string_concat * concatenate two strings */ STRING* ! string_concat(struct Parrot_Interp *interpreter, const STRING* a, ! const STRING* b, INTVAL flags) { ! STRING *result; ! ! if (a != NULL && a->strlen != 0) { ! if (b != NULL && b->strlen != 0) { ! result = string_make(interpreter, NULL, a->bufused + ! b->strlen*a->encoding->max_bytes, ! a->encoding, 0, a->type); ! mem_sys_memcopy(result->bufstart,a->bufstart,a->bufused); ! if (a->type != b->type || a->encoding != b->encoding) { ! b = string_transcode(interpreter, b, a->encoding, a->type, NULL); ! } ! mem_sys_memcopy((void*)((ptrcast_t)result->bufstart + a->bufused), ! b->bufstart, b->bufused); ! result->strlen = a->strlen + b->strlen; ! result->bufused = a->bufused + b->bufused; ! result->bufstart[result->bufused]='\0'; } ! else { ! return string_copy(interpreter, a); } } else { ! if (a != NULL) { ! return string_transcode(interpreter, b, a->encoding, a->type, NULL); ! } ! else { ! if (b != NULL) { ! return string_copy(interpreter, b); ! } ! else { ! return string_make(interpreter, "", 0, NULL, 0, NULL); ! } } } ! return result; } /*=for api string string_repeat *************** *** 251,258 **** * Allocates I<d> if needed, also returns d. */ STRING* ! string_repeat(struct Parrot_Interp *interpreter, STRING* s, INTVAL num, ! STRING** d) { STRING* dest; INTVAL i; --- 252,258 ---- * Allocates I<d> if needed, also returns d. */ STRING* ! string_repeat(struct Parrot_Interp *interpreter, const STRING* s, INTVAL num, STRING** d) { STRING* dest; INTVAL i; *************** *** 260,293 **** INTERNAL_EXCEPTION(NEG_REPEAT, "Cannot repeat with negative arg"); } ! if (!d || !*d) { ! dest = string_make(interpreter, ! NULL, 0, s->encoding, ! 0, s->type); ! } ! else { ! dest = *d; ! } ! string_grow(dest, s->strlen * num); if (num == 0) { - dest->strlen = 0; return dest; } ! /* copy s into dest */ ! mem_sys_memcopy(dest->bufstart, s->bufstart, s->bufused); ! ! /* copy from start of dest to later part of dest n times */ ! for (i = 1; i< num; i++) { mem_sys_memcopy((void*)((ptrcast_t)dest->bufstart+s->bufused * i), ! dest->bufstart, s->bufused); } - dest->type = s->type; - dest->encoding = s->encoding; - dest->language = s->language; dest->bufused = s->bufused * num; ! string_compute_strlen(dest); return dest; } --- 260,283 ---- INTERNAL_EXCEPTION(NEG_REPEAT, "Cannot repeat with negative arg"); } ! dest = string_make(interpreter, NULL, s->bufused*num, s->encoding, 0, ! s->type); if (num == 0) { return dest; } ! /* copy s into dest num times */ ! for (i = 0; i< num; i++) { mem_sys_memcopy((void*)((ptrcast_t)dest->bufstart+s->bufused * i), ! s->bufstart, s->bufused); } dest->bufused = s->bufused * num; ! dest->strlen = s->strlen *num; ! ! if (d != NULL) { ! *d = dest; ! } return dest; } *************** *** 296,306 **** * Allocate memory for d if necessary. */ STRING* ! string_substr(struct Parrot_Interp *interpreter, STRING* src, INTVAL offset, ! INTVAL length, STRING** d) { STRING *dest; ! char *substart; ! char *subend; if (offset < 0) { offset = src->strlen + offset; } --- 286,295 ---- * Allocate memory for d if necessary. */ STRING* ! string_substr(struct Parrot_Interp *interpreter, const STRING* src, INTVAL offset, INTVAL length, STRING** d) { STRING *dest; ! void *substart; ! void *subend; if (offset < 0) { offset = src->strlen + offset; } *************** *** 314,331 **** if (length > (src->strlen - offset) ) { length = src->strlen - offset; } ! if (!d || !*d) { ! dest = string_make(interpreter, NULL, 0, src->encoding, 0, src->type); ! } ! else { ! dest = *d; ! } substart = src->encoding->skip_forward(src->bufstart, offset); subend = src->encoding->skip_forward(substart, length); - string_grow(dest, length); mem_sys_memcopy(dest->bufstart, substart, subend - substart); dest->bufused = subend - substart; dest->strlen = length; return dest; } --- 303,320 ---- if (length > (src->strlen - offset) ) { length = src->strlen - offset; } ! dest = string_make(interpreter, NULL, length*src->encoding->max_bytes, ! src->encoding, 0, src->type); substart = src->encoding->skip_forward(src->bufstart, offset); subend = src->encoding->skip_forward(substart, length); mem_sys_memcopy(dest->bufstart, substart, subend - substart); dest->bufused = subend - substart; dest->strlen = length; + dest->bufstart[dest->bufused]='\0'; + + if (d != NULL) { + *d = dest; + } return dest; } *************** *** 334,341 **** */ STRING* string_chopn(STRING* s, INTVAL n) { ! char *bufstart = s->bufstart; ! char *bufend = bufstart + s->bufused; if (n > s->strlen) { n = s->strlen; } --- 323,330 ---- */ STRING* string_chopn(STRING* s, INTVAL n) { ! void *bufstart = s->bufstart; ! void *bufend = bufstart + s->bufused; if (n > s->strlen) { n = s->strlen; } *************** *** 345,350 **** --- 334,340 ---- bufend = s->encoding->skip_backward(bufend, n); s->bufused = bufend - bufstart; s->strlen = s->strlen - n; + s->bufstart[s->bufused] = '\0'; return s; } *************** *** 352,374 **** * compare two strings. */ INTVAL ! string_compare(struct Parrot_Interp *interpreter, STRING* s1, STRING* s2) { ! char *s1start; ! char *s1end; ! char *s2start; ! char *s2end; INTVAL cmp = 0; if (s1->type != s2->type || s1->encoding != s2->encoding) { ! s1 = ! string_transcode(interpreter, s1, NULL, string_unicode_type, NULL); ! s2 = ! string_transcode(interpreter, s2, NULL, string_unicode_type, NULL); } ! s1start = s1->bufstart; s1end = s1start + s1->bufused; ! s2start = s2->bufstart; s2end = s2start + s2->bufused; while (cmp == 0 && s1start < s1end && s2start < s2end) { --- 342,365 ---- * compare two strings. */ INTVAL ! string_compare(struct Parrot_Interp *interpreter, const STRING* s1, ! const STRING* s2) { ! void *s1start; ! void *s1end; ! void *s2start; ! void *s2end; INTVAL cmp = 0; if (s1->type != s2->type || s1->encoding != s2->encoding) { ! s1 = string_transcode(interpreter, s1, NULL, string_unicode_type, ! NULL); ! s2 = string_transcode(interpreter, s2, NULL, string_unicode_type, ! NULL); } ! s1start = (void*)s1->bufstart; s1end = s1start + s1->bufused; ! s2start = (void*)s2->bufstart; s2end = s2start + s2->bufused; while (cmp == 0 && s1start < s1end && s2start < s2end) { *************** *** 388,394 **** } /* A string is "true" if it is equal to anything but "" and "0" */ ! BOOLVAL string_bool (struct Parrot_Interp *interpreter, STRING* s) { INTVAL len; if (s == NULL) { return 0; --- 379,385 ---- } /* A string is "true" if it is equal to anything but "" and "0" */ ! BOOLVAL string_bool (const STRING* s) { INTVAL len; if (s == NULL) { return 0; *************** *** 423,434 **** rounding towards zero. */ ! INTVAL string_to_int (struct Parrot_Interp *interpreter, STRING *s) { INTVAL i = 0; if (s) { ! char *start = s->bufstart; ! char *end = start + s->bufused; int sign = 1; BOOLVAL in_number = 0; --- 414,425 ---- rounding towards zero. */ ! INTVAL string_to_int (const STRING *s) { INTVAL i = 0; if (s) { ! void *start = (void*)s->bufstart; ! void *end = start + s->bufused; int sign = 1; BOOLVAL in_number = 0; *************** *** 461,472 **** return i; } ! FLOATVAL string_to_num (struct Parrot_Interp *interpreter, STRING *s) { FLOATVAL f = 0.0; if (s) { ! char *start = s->bufstart; ! char *end = start + s->bufused; int sign = 1; BOOLVAL seen_dot = 0; BOOLVAL seen_e = 0; --- 452,463 ---- return i; } ! FLOATVAL string_to_num (const STRING *s) { FLOATVAL f = 0.0; if (s) { ! void *start = (void*)s->bufstart; ! void *end = start + s->bufused; int sign = 1; BOOLVAL seen_dot = 0; BOOLVAL seen_e = 0; Index: classes/perlstring.pmc =================================================================== RCS file: /cvs/public/parrot/classes/perlstring.pmc,v retrieving revision 1.10 diff -c -r1.10 perlstring.pmc *** classes/perlstring.pmc 28 Dec 2001 18:20:12 -0000 1.10 --- classes/perlstring.pmc 30 Dec 2001 08:38:23 -0000 *************** *** 47,53 **** INTVAL get_integer () { STRING* s = (STRING*) SELF->cache.struct_val; ! return string_to_int(interpreter, s); } INTVAL get_integer_index (INTVAL index) { --- 47,53 ---- INTVAL get_integer () { STRING* s = (STRING*) SELF->cache.struct_val; ! return string_to_int(s); } INTVAL get_integer_index (INTVAL index) { *************** *** 55,61 **** FLOATVAL get_number () { STRING* s = (STRING*) SELF->cache.struct_val; ! return string_to_num(interpreter, s); } FLOATVAL get_number_index (INTVAL index) { --- 55,61 ---- FLOATVAL get_number () { STRING* s = (STRING*) SELF->cache.struct_val; ! return string_to_num(s); } FLOATVAL get_number_index (INTVAL index) { *************** *** 69,75 **** } BOOLVAL get_bool () { ! return string_bool(interpreter, SELF->cache.struct_val); } void* get_value () { --- 69,75 ---- } BOOLVAL get_bool () { ! return string_bool(SELF->cache.struct_val); } void* get_value () { *************** *** 455,461 **** dest->vtable = &Parrot_base_vtables[enum_class_PerlString]; dest->cache.struct_val = string_repeat(INTERP, SELF->cache.struct_val, ! string_to_int(interpreter, value), NULL ); } --- 455,461 ---- dest->vtable = &Parrot_base_vtables[enum_class_PerlString]; dest->cache.struct_val = string_repeat(INTERP, SELF->cache.struct_val, ! string_to_int(value), NULL ); } *************** *** 463,469 **** dest->vtable = &Parrot_base_vtables[enum_class_PerlString]; dest->cache.struct_val = string_repeat(INTERP, SELF->cache.struct_val, ! string_to_int(interpreter, value), NULL ); } --- 463,469 ---- dest->vtable = &Parrot_base_vtables[enum_class_PerlString]; dest->cache.struct_val = string_repeat(INTERP, SELF->cache.struct_val, ! string_to_int(value), NULL ); } *************** *** 471,477 **** dest->vtable = &Parrot_base_vtables[enum_class_PerlString]; dest->cache.struct_val = string_repeat(INTERP, SELF->cache.struct_val, ! string_to_int(interpreter, value), NULL ); } --- 471,477 ---- dest->vtable = &Parrot_base_vtables[enum_class_PerlString]; dest->cache.struct_val = string_repeat(INTERP, SELF->cache.struct_val, ! string_to_int(value), NULL ); } Index: docs/strings.pod =================================================================== RCS file: /cvs/public/parrot/docs/strings.pod,v retrieving revision 1.7 diff -c -r1.7 strings.pod *** docs/strings.pod 28 Dec 2001 18:20:12 -0000 1.7 --- docs/strings.pod 30 Dec 2001 08:38:24 -0000 *************** *** 77,83 **** To repeat a string, (ie, turn 'xyz' into 'xyzxyzxyz') use: ! STRING* string_repeat(struct Parrot_Interp *, STRING* s, INTVAL n, STRING** d) Which will repeat string I<s> n times and store the result into I<d>, which it also returns. If I<*d> or I<**d> is NULL, a new string will be allocated --- 77,83 ---- To repeat a string, (ie, turn 'xyz' into 'xyzxyzxyz') use: ! STRING* string_repeat(STRING* s, INTVAL n, STRING** d) Which will repeat string I<s> n times and store the result into I<d>, which it also returns. If I<*d> or I<**d> is NULL, a new string will be allocated *************** *** 91,97 **** To retrieve a substring of the string, call ! STRING* string_substr(struct Parrot_Interp *, STRING* src, INTVAL offset, INTVAL length, STRING** dest) The result will be placed in C<dest>. (Passing in C<dest> avoids allocating a new string at runtime. If --- 91,97 ---- To retrieve a substring of the string, call ! STRING* string_substr(STRING* src, INTVAL offset, INTVAL length, STRING** dest) The result will be placed in C<dest>. (Passing in C<dest> avoids allocating a new string at runtime. If *************** *** 113,119 **** To compare two strings, use: ! INTVAL string_compare(struct Parrot_Interp *, STRING* s1, STRING* s2) The value returned will be less than, equal to, or greater than zero depending on whether C<s1> is less than, equal to, or greater than C<s2>. --- 113,119 ---- To compare two strings, use: ! INTVAL string_compare(STRING* s1, STRING* s2) The value returned will be less than, equal to, or greater than zero depending on whether C<s1> is less than, equal to, or greater than C<s2>. *************** *** 124,130 **** To test a string for truth, use: ! BOOLVAL string_bool(struct Parrot_Interp *, STRING* s); A string is false if it --- 124,130 ---- To test a string for truth, use: ! BOOLVAL string_bool(STRING* s); A string is false if it *************** *** 152,158 **** structure in F<string.h>: struct parrot_string { - void *bufstart; INTVAL buflen; INTVAL bufused; INTVAL flags; --- 152,157 ---- *************** *** 160,176 **** INTVAL encoding; INTVAL type; INTVAL unused; }; Let's look at each element of this structure in turn. - =head2 C<bufstart> - - This pointer points to the buffer which holds the string, encoded in - whatever is the string's specified encoding. Because of this, you should - not make any assumptions about what's in the buffer, and hence you - shouldn't try and access it directly. - =head2 C<buflen> This is used for memory allocation; it tells you the currently allocated --- 159,169 ---- INTVAL encoding; INTVAL type; INTVAL unused; + char bufstart[1]; }; Let's look at each element of this structure in turn. =head2 C<buflen> This is used for memory allocation; it tells you the currently allocated *************** *** 236,241 **** --- 229,241 ---- This field is, as its name suggests, unused; however, it can be used to hold a pointer to the correct vtable for foreign strings. + =head2 C<bufstart> + + This pointer points to the buffer which holds the string, encoded in + whatever is the string's specified encoding. Because of this, you should + not make any assumptions about what's in the buffer, and hence you + shouldn't try and access it directly. + =head1 String Vtable Functions The L</String Manipulation Functions> above are implemented in terms of *************** *** 326,357 **** not helping construct the Parrot core itself, you probably want to look away now. - The first two functions to note are - INTVAL string_compute_strlen(STRING* s) ! and ! ! INTVAL string_max_bytes(STRING *s, INTVAL iv) ! ! The first updates the contents of C<< s->strlen >> by contemplating the ! buffer C<bufstart> and working out how many characters it contains. The ! second is given a number of characters which we assume are going to be ! added into the string at some point; it returns the maximum number of ! bytes that need to be allocated to admit that number of characters. For ! fixed-width encodings, this is trivial - the "native" encoding, for ! instance, encodes one byte per character, so C<string_native_max_bytes> ! simply returns the C<INTVAL> it is passed; C<string_utf8_max_bytes>, on the ! other hand, returns three times the value that it is passed because a ! UTF8 character may occupy up to three bytes. ! ! To grow a string to a specified size, use ! ! void string_grow(STRING *s, INTVAL newsize) ! ! The size is given in characters; C<string_max_bytes> is called to turn ! this into a size in bytes, and then the buffer is grown to accomodate ! (at least) that many bytes. =head1 Transcoding --- 326,335 ---- not helping construct the Parrot core itself, you probably want to look away now. INTVAL string_compute_strlen(STRING* s) ! Updates the contents of C<< s->strlen >> by contemplating the ! buffer C<bufstart> and working out how many characters it contains. =head1 Transcoding Index: encodings/singlebyte.c =================================================================== RCS file: /cvs/public/parrot/encodings/singlebyte.c,v retrieving revision 1.5 diff -c -r1.5 singlebyte.c *** encodings/singlebyte.c 6 Dec 2001 00:11:24 -0000 1.5 --- encodings/singlebyte.c 30 Dec 2001 08:38:24 -0000 *************** *** 41,55 **** } static void * ! singlebyte_skip_forward (void *ptr, INTVAL n) { ! byte_t *bptr = ptr; return bptr + n; } static void * ! singlebyte_skip_backward (void *ptr, INTVAL n) { ! byte_t *bptr = ptr; return bptr - n; } --- 41,55 ---- } static void * ! singlebyte_skip_forward (const void *ptr, INTVAL n) { ! byte_t *bptr = (byte_t*)ptr; return bptr + n; } static void * ! singlebyte_skip_backward (const void *ptr, INTVAL n) { ! byte_t *bptr = (byte_t*)ptr; return bptr - n; } Index: encodings/utf16.c =================================================================== RCS file: /cvs/public/parrot/encodings/utf16.c,v retrieving revision 1.4 diff -c -r1.4 utf16.c *** encodings/utf16.c 6 Dec 2001 00:11:24 -0000 1.4 --- encodings/utf16.c 30 Dec 2001 08:38:24 -0000 *************** *** 77,84 **** } static void * ! utf16_skip_forward (void *ptr, INTVAL n) { ! utf16_t *u16ptr = ptr; while (n-- > 0) { if (UNICODE_IS_HIGH_SURROGATE(*u16ptr)) { --- 77,84 ---- } static void * ! utf16_skip_forward (const void *ptr, INTVAL n) { ! utf16_t *u16ptr = (utf16_t*)ptr; while (n-- > 0) { if (UNICODE_IS_HIGH_SURROGATE(*u16ptr)) { *************** *** 100,107 **** } static void * ! utf16_skip_backward (void *ptr, INTVAL n) { ! utf16_t *u16ptr = ptr; while (n--> 0) { u16ptr--; --- 100,107 ---- } static void * ! utf16_skip_backward (const void *ptr, INTVAL n) { ! utf16_t *u16ptr = (utf16_t*)ptr; while (n--> 0) { u16ptr--; Index: encodings/utf32.c =================================================================== RCS file: /cvs/public/parrot/encodings/utf32.c,v retrieving revision 1.1 diff -c -r1.1 utf32.c *** encodings/utf32.c 31 Oct 2001 22:51:31 -0000 1.1 --- encodings/utf32.c 30 Dec 2001 08:38:24 -0000 *************** *** 44,58 **** } static void * ! utf32_skip_forward (void *ptr, INTVAL n) { ! utf32_t *u32ptr = ptr; return u32ptr + n; } static void * ! utf32_skip_backward (void *ptr, INTVAL n) { ! utf32_t *u32ptr = ptr; return u32ptr - n; } --- 44,58 ---- } static void * ! utf32_skip_forward (const void *ptr, INTVAL n) { ! utf32_t *u32ptr = (utf32_t*)ptr; return u32ptr + n; } static void * ! utf32_skip_backward (const void *ptr, INTVAL n) { ! utf32_t *u32ptr = (utf32_t*)ptr; return u32ptr - n; } Index: encodings/utf8.c =================================================================== RCS file: /cvs/public/parrot/encodings/utf8.c,v retrieving revision 1.4 diff -c -r1.4 utf8.c *** encodings/utf8.c 6 Dec 2001 00:11:24 -0000 1.4 --- encodings/utf8.c 30 Dec 2001 08:38:25 -0000 *************** *** 97,104 **** } static void * ! utf8_skip_forward (void *ptr, INTVAL n) { ! utf8_t *u8ptr = ptr; while (n-- > 0) { u8ptr += UTF8SKIP(u8ptr); --- 97,104 ---- } static void * ! utf8_skip_forward (const void *ptr, INTVAL n) { ! utf8_t *u8ptr = (utf8_t*)ptr; while (n-- > 0) { u8ptr += UTF8SKIP(u8ptr); *************** *** 108,115 **** } static void * ! utf8_skip_backward (void *ptr, INTVAL n) { ! utf8_t *u8ptr = ptr; while (n-- > 0) { u8ptr--; --- 108,115 ---- } static void * ! utf8_skip_backward (const void *ptr, INTVAL n) { ! utf8_t *u8ptr = (utf8_t*)ptr; while (n-- > 0) { u8ptr--; Index: include/parrot/encoding.h =================================================================== RCS file: /cvs/public/parrot/include/parrot/encoding.h,v retrieving revision 1.4 diff -c -r1.4 encoding.h *** include/parrot/encoding.h 6 Dec 2001 00:11:24 -0000 1.4 --- include/parrot/encoding.h 30 Dec 2001 08:38:25 -0000 *************** *** 19,26 **** INTVAL (*characters)(const void *ptr, INTVAL bytes); INTVAL (*decode)(const void *ptr); void *(*encode)(void *ptr, INTVAL c); ! void *(*skip_forward)(void *ptr, INTVAL n); ! void *(*skip_backward)(void *ptr, INTVAL n); } ENCODING; const ENCODING * --- 19,26 ---- INTVAL (*characters)(const void *ptr, INTVAL bytes); INTVAL (*decode)(const void *ptr); void *(*encode)(void *ptr, INTVAL c); ! void *(*skip_forward)(const void *ptr, INTVAL n); ! void *(*skip_backward)(const void *ptr, INTVAL n); } ENCODING; const ENCODING * Index: include/parrot/string.h =================================================================== RCS file: /cvs/public/parrot/include/parrot/string.h,v retrieving revision 1.15 diff -c -r1.15 string.h *** include/parrot/string.h 28 Dec 2001 18:20:12 -0000 1.15 --- include/parrot/string.h 30 Dec 2001 08:38:25 -0000 *************** *** 16,22 **** #include "parrot/parrot.h" typedef struct { - void *bufstart; INTVAL buflen; INTVAL flags; INTVAL bufused; --- 16,21 ---- *************** *** 24,29 **** --- 23,29 ---- const ENCODING *encoding; const CHARTYPE *type; INTVAL language; + char bufstart[1]; } STRING; *************** *** 31,72 **** INTVAL string_compute_strlen(STRING*); - INTVAL - string_max_bytes(STRING*, INTVAL); STRING* ! string_concat(struct Parrot_Interp *, STRING*, STRING*, INTVAL); STRING* ! string_repeat(struct Parrot_Interp *, STRING* , INTVAL, STRING**); STRING* string_chopn(STRING*, INTVAL); STRING* ! string_substr(struct Parrot_Interp *interpreter, STRING*, INTVAL, INTVAL, STRING**); INTVAL ! string_compare(struct Parrot_Interp *, STRING*, STRING*); BOOLVAL ! string_bool(struct Parrot_Interp *, STRING*); /* Declarations of other functions */ INTVAL ! string_length(STRING*); INTVAL ! string_ord(STRING* s, INTVAL index); FLOATVAL ! string_to_num (struct Parrot_Interp *interpreter, STRING *s); INTVAL ! string_to_int (struct Parrot_Interp *interpreter, STRING *s); ! void ! string_grow(STRING* s, INTVAL newsize); void string_destroy(STRING* s); STRING* ! string_make(struct Parrot_Interp *interpreter, void *buffer, INTVAL buflen, const ENCODING *encoding, INTVAL flags, const CHARTYPE *type); STRING* ! string_copy(struct Parrot_Interp *interpreter, STRING *i); STRING* ! string_transcode(struct Parrot_Interp *interpreter, STRING *src, const ENCODING *encoding, const CHARTYPE *type, STRING *dest); void string_init(void); #endif --- 31,76 ---- INTVAL string_compute_strlen(STRING*); STRING* ! string_concat(struct Parrot_Interp *interpreter, const STRING*, const STRING*, ! INTVAL); STRING* ! string_repeat(struct Parrot_Interp *interpreter, const STRING* , INTVAL, ! STRING**); STRING* string_chopn(STRING*, INTVAL); STRING* ! string_substr(struct Parrot_Interp *interpreter, const STRING*, INTVAL, ! INTVAL, STRING**); INTVAL ! string_compare(struct Parrot_Interp *interpreter, const STRING*, const STRING*); BOOLVAL ! string_bool(const STRING*); /* Declarations of other functions */ INTVAL ! string_length(const STRING*); INTVAL ! string_ord(const STRING* s, INTVAL index); FLOATVAL ! string_to_num (const STRING *s); INTVAL ! string_to_int (const STRING *s); void string_destroy(STRING* s); STRING* ! string_make(struct Parrot_Interp *interpreter, const void *buffer, ! INTVAL buflen, const ENCODING *encoding, INTVAL flags, ! const CHARTYPE *type); STRING* ! string_copy(struct Parrot_Interp *interpreter, const STRING *i); STRING* ! string_transcode(struct Parrot_Interp *interpreter, const STRING *src, ! const ENCODING *encoding, const CHARTYPE *type, STRING **d); void string_init(void); + static INTVAL + string_index(const STRING* s, INTVAL index); #endif Index: t/op/string.t =================================================================== RCS file: /cvs/public/parrot/t/op/string.t,v retrieving revision 1.16 diff -c -r1.16 string.t *** t/op/string.t 28 Dec 2001 18:20:13 -0000 1.16 --- t/op/string.t 30 Dec 2001 08:38:28 -0000 *************** *** 1,13 **** #! perl -w ! use Parrot::Test tests => 48; ! output_is( <<'CODE', <<OUTPUT, "set_s_sc" ); set S4, "JAPH\n" print S4 end CODE JAPH OUTPUT output_is( <<'CODE', '4', "length_i_s" ); --- 1,16 ---- #! perl -w ! use Parrot::Test tests => 63; ! output_is( <<'CODE', <<OUTPUT, "set_s_s|sc" ); set S4, "JAPH\n" + set S5, S4 print S4 + print S5 end CODE JAPH + JAPH OUTPUT output_is( <<'CODE', '4', "length_i_s" ); *************** *** 18,38 **** end CODE ! output_is( <<'CODE', <<OUTPUT, "chopn_s_ic" ); set S4, "JAPHxyzw" set S5, "japhXYZW" ! set S3, "\n" chopn S4, 3 chopn S4, 1 ! chopn S5, 4 print S4 ! print S3 print S5 print S3 end CODE JAPH japh OUTPUT output_is(<<'CODE', <<OUTPUT, "chopn, OOB values"); --- 21,46 ---- end CODE ! output_is( <<'CODE', <<OUTPUT, "chopn_s_i|ic" ); set S4, "JAPHxyzw" set S5, "japhXYZW" ! set S3, S4 ! set S1 "\n" ! set I1 4 chopn S4, 3 chopn S4, 1 ! chopn S5, I1 print S4 ! print S1 print S5 + print S1 print S3 + print S1 end CODE JAPH japh + JAPHxyzw OUTPUT output_is(<<'CODE', <<OUTPUT, "chopn, OOB values"); *************** *** 57,81 **** ** nothing ** OUTPUT ! output_is( <<'CODE', 'JAPH', "substr_s_s_i_i" ); set S4, "12345JAPH01" set I4, 5 set I5, 4 substr S5, S4, I4, I5 print S5 end CODE # negative offsets output_is(<<'CODE', <<'OUTPUT', "neg substr offset"); set S0, "A string of length 21" ! set I0, -9 ! set I1, 6 ! substr_s_s_i S1, S0, I0, I1 ! print S0 ! print "\n" ! print S1 ! print "\n" end CODE A string of length 21 --- 65,106 ---- ** nothing ** OUTPUT ! output_is( <<'CODE', <<'OUTPUT', "substr_s_s|sc_i|ic_i|ic" ); set S4, "12345JAPH01" set I4, 5 set I5, 4 substr S5, S4, I4, I5 print S5 + substr S5, S4, I4, 4 + print S5 + substr S5, S4, 5, I5 + print S5 + substr S5, S4, 5, 4 + print S5 + substr S5, "12345JAPH01", I4, I5 + print S5 + substr S5, "12345JAPH01", I4, 4 + print S5 + substr S5, "12345JAPH01", 5, I5 + print S5 + substr S5, "12345JAPH01", 5, 4 + print S5 + print "\n" end CODE + JAPHJAPHJAPHJAPHJAPHJAPHJAPHJAPH + OUTPUT # negative offsets output_is(<<'CODE', <<'OUTPUT', "neg substr offset"); set S0, "A string of length 21" ! set I0, -9 ! set I1, 6 ! substr S1, S0, I0, I1 ! print S0 ! print "\n" ! print S1 ! print "\n" end CODE A string of length 21 *************** *** 83,110 **** OUTPUT # This asks for substring it shouldn't be allowed... ! output_is(<<'CODE', 'Cannot take substr outside string', "sub err:OOR"); set S0, "A string of length 21" ! set I0, -99 ! set I1, 6 ! substr_s_s_i S1, S0, I0, I1 ! print S0 ! print "\n" ! print S1 ! print "\n" end CODE # This asks for substring much greater than length of original string output_is(<<'CODE', <<'OUTPUT', "len>strlen"); set S0, "A string of length 21" ! set I0, 12 ! set I1, 1000 ! substr_s_s_i S1, S0, I0, I1 ! print S0 ! print "\n" ! print S1 ! print "\n" end CODE A string of length 21 --- 108,140 ---- OUTPUT # This asks for substring it shouldn't be allowed... ! output_is(<<'CODE', 'Cannot take substr outside string', "substr OOB"); set S0, "A string of length 21" ! set I0, -99 ! set I1, 6 ! substr S1, S0, I0, I1 ! end ! CODE ! ! # This asks for substring it shouldn't be allowed... ! output_is(<<'CODE', 'Cannot take substr outside string', "substr OOB"); ! set S0, "A string of length 21" ! set I0, 99 ! set I1, 6 ! substr S1, S0, I0, I1 end CODE # This asks for substring much greater than length of original string output_is(<<'CODE', <<'OUTPUT', "len>strlen"); set S0, "A string of length 21" ! set I0, 12 ! set I1, 1000 ! substr S1, S0, I0, I1 ! print S0 ! print "\n" ! print S1 ! print "\n" end CODE A string of length 21 *************** *** 114,168 **** # The same, with a negative offset output_is(<<'CODE', <<'OUTPUT', "len>strlen, -ve os"); set S0, "A string of length 21" ! set I0, -9 ! set I1, 1000 ! substr_s_s_i S1, S0, I0, I1 ! print S0 ! print "\n" ! print S1 ! print "\n" end CODE A string of length 21 length 21 OUTPUT ! output_is( <<'CODE', '<><', "2-param concat, null onto null" ); ! print "<>" ! concat S0,S0 ! print "<" ! end CODE ! output_is( <<'CODE', <<OUTPUT, '2-param concat, "foo1" onto null' ); ! concat S0,"foo1" ! print S0 ! print "\n" ! end CODE foo1 OUTPUT ! output_is( <<'CODE', <<OUTPUT, '2-param concat, "foo2" onto null' ); ! set S1,"foo2" ! concat S0,S1 ! print S0 ! print "\n" end CODE ! foo2 OUTPUT ! output_is( <<'CODE', <<OUTPUT, "concat" ); ! set S1, "fish" ! set S2, "bone" ! concat S1, S2 ! print S1 ! set S2, "\n" ! print S2 end CODE ! fishbone OUTPUT --- 144,230 ---- # The same, with a negative offset output_is(<<'CODE', <<'OUTPUT', "len>strlen, -ve os"); set S0, "A string of length 21" ! set I0, -9 ! set I1, 1000 ! substr S1, S0, I0, I1 ! print S0 ! print "\n" ! print S1 ! print "\n" end CODE A string of length 21 length 21 OUTPUT ! output_is( <<'CODE', '<><', "concat_s_s|sc, null onto null" ); ! print "<>" ! concat S0, S0 ! concat S1, "" ! print "<" ! end CODE ! output_is( <<'CODE', <<OUTPUT, 'concat_s_s|sc, "foo1" onto null' ); ! concat S0, "foo1" ! set S1, "foo2" ! concat S2, S1 ! print S0 ! print "\n" ! print S2 ! print "\n" ! end CODE foo1 + foo2 OUTPUT ! output_is( <<'CODE', <<OUTPUT, "concat_s_s|sc" ); ! set S1, "fish" ! set S2, "bone" ! concat S1, S2 ! print S1 ! concat S1, "\n" ! print S1 end CODE ! fishbonefishbone OUTPUT ! output_is( <<'CODE', <<OUTPUT, "concat_s_s|sc_s|sc" ); ! set S1, "japh" ! set S2, "JAPH" ! concat S0, "japh", "JAPH" ! print S0 ! print "\n" ! concat S0, S1, "JAPH" ! print S0 ! print "\n" ! concat S0, "japh", S2 ! print S0 ! print "\n" ! concat S0, S1, S2 ! print S0 ! print "\n" end CODE ! japhJAPH ! japhJAPH ! japhJAPH ! japhJAPH ! OUTPUT ! ! output_is( <<'CODE', <<OUTPUT, "concat - ensure copy is made" ); ! set S2, "JAPH" ! concat S0, S2, "" ! concat S1, "", S2 ! chopn S0, 1 ! chopn S1, 1 ! print S2 ! print "\n" ! end ! CODE ! JAPH OUTPUT *************** *** 201,207 **** ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "eq_s_sc_ic"); @{[ compare_strings( 1, "eq", @strings ) ]} print "ok\\n" end --- 263,269 ---- ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "eq_sc_s_ic"); @{[ compare_strings( 1, "eq", @strings ) ]} print "ok\\n" end *************** *** 212,275 **** ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "eq_sc_s_ic"); ! set S0, "I am legion" ! eq "I am legion", S0, GOOD1 ! print "not " ! GOOD1: print "ok 1\\n" ! eq "I am legend", S0, BAD1 ! branch GOOD2 ! BAD1: print "not " ! GOOD2: print "ok 2\\n" ! end CODE ! ok 1 ! ok 2 OUTPUT output_is(<<CODE, <<OUTPUT, "ne_sc_s_ic"); ! set S0, "I am legion" ! ne "I am legend", S0, GOOD1 ! print "not " ! GOOD1: print "ok 1\\n" ! ne "I am legion", S0, BAD1 ! branch GOOD2 ! BAD1: print "not " ! GOOD2: print "ok 2\\n" ! end CODE ! ok 1 ! ok 2 OUTPUT ! output_is(<<CODE, <<OUTPUT, "eq_sc_s"); set S0, "Sparticus" bsr TEST1 print "ok 1\\n" bsr TEST2 print "ok 2\\n" end TEST1: eq "Sparticus", S0 print "not " ret ! TEST2: ne "Spartisnt", S0 print "not " ret CODE ok 1 ok 2 OUTPUT ! output_is(<<CODE, <<OUTPUT, "ne_s_s_ic"); ! @{[ compare_strings( 0, "ne", @strings ) ]} print "ok\\n" end ERROR: --- 274,383 ---- ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "eq_s_sc_ic"); ! @{[ compare_strings( 2, "eq", @strings ) ]} ! print "ok\\n" ! end ! ERROR: ! print "bad\\n" ! end ! CODE ! ok ! OUTPUT ! output_is(<<CODE, <<OUTPUT, "eq_sc_sc_ic"); ! @{[ compare_strings( 3, "eq", @strings ) ]} ! print "ok\\n" ! end ! ERROR: ! print "bad\\n" ! end ! CODE ! ok ! OUTPUT ! output_is(<<CODE, <<OUTPUT, "ne_s_s_ic"); ! @{[ compare_strings( 0, "ne", @strings ) ]} ! print "ok\\n" ! end ! ERROR: ! print "bad\\n" ! end CODE ! ok OUTPUT output_is(<<CODE, <<OUTPUT, "ne_sc_s_ic"); ! @{[ compare_strings( 1, "ne", @strings ) ]} ! print "ok\\n" ! end ! ERROR: ! print "bad\\n" ! end ! CODE ! ok ! OUTPUT ! output_is(<<CODE, <<OUTPUT, "ne_s_sc_ic"); ! @{[ compare_strings( 2, "ne", @strings ) ]} ! print "ok\\n" ! end ! ERROR: ! print "bad\\n" ! end ! CODE ! ok ! OUTPUT ! output_is(<<CODE, <<OUTPUT, "ne_sc_sc_ic"); ! @{[ compare_strings( 3, "ne", @strings ) ]} ! print "ok\\n" ! end ! ERROR: ! print "bad\\n" ! end CODE ! ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "eq_s|sc_s|sc"); set S0, "Sparticus" bsr TEST1 print "ok 1\\n" bsr TEST2 print "ok 2\\n" + bsr TEST3 + print "ok 3\\n" + bsr TEST4 + print "ok 4\\n" end TEST1: eq "Sparticus", S0 print "not " ret ! TEST2: eq S0, "Sparticus" ! print "not " ! ret ! ! TEST3: eq S0, S0 ! print "not " ! ret ! ! TEST4: eq "Sparticus", "Sparticus" print "not " ret CODE ok 1 ok 2 + ok 3 + ok 4 OUTPUT ! output_is(<<CODE, <<OUTPUT, "lt_s_s_ic"); ! @{[ compare_strings( 0, "lt", @strings ) ]} print "ok\\n" end ERROR: *************** *** 279,286 **** ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "ne_s_sc_ic"); ! @{[ compare_strings( 1, "ne", @strings ) ]} print "ok\\n" end ERROR: --- 387,394 ---- ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "lt_sc_s_ic"); ! @{[ compare_strings( 1, "lt", @strings ) ]} print "ok\\n" end ERROR: *************** *** 290,297 **** ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "lt_s_s_ic"); ! @{[ compare_strings( 0, "lt", @strings ) ]} print "ok\\n" end ERROR: --- 398,405 ---- ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "lt_s_sc_ic"); ! @{[ compare_strings( 2, "lt", @strings ) ]} print "ok\\n" end ERROR: *************** *** 301,308 **** ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "lt_s_sc_ic"); ! @{[ compare_strings( 1, "lt", @strings ) ]} print "ok\\n" end ERROR: --- 409,416 ---- ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "lt_sc_sc_ic"); ! @{[ compare_strings( 3, "lt", @strings ) ]} print "ok\\n" end ERROR: *************** *** 323,329 **** ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "le_s_sc_ic"); @{[ compare_strings( 1, "le", @strings ) ]} print "ok\\n" end --- 431,437 ---- ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "le_sc_s_ic"); @{[ compare_strings( 1, "le", @strings ) ]} print "ok\\n" end *************** *** 334,339 **** --- 442,469 ---- ok OUTPUT + output_is(<<CODE, <<OUTPUT, "le_s_sc_ic"); + @{[ compare_strings( 2, "le", @strings ) ]} + print "ok\\n" + end + ERROR: + print "bad\\n" + end + CODE + ok + OUTPUT + + output_is(<<CODE, <<OUTPUT, "le_sc_sc_ic"); + @{[ compare_strings( 3, "le", @strings ) ]} + print "ok\\n" + end + ERROR: + print "bad\\n" + end + CODE + ok + OUTPUT + output_is(<<CODE, <<OUTPUT, "gt_s_s_ic"); @{[ compare_strings( 0, "gt", @strings ) ]} print "ok\\n" *************** *** 345,351 **** ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "gt_s_sc_ic"); @{[ compare_strings( 1, "gt", @strings ) ]} print "ok\\n" end --- 475,481 ---- ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "gt_sc_s_ic"); @{[ compare_strings( 1, "gt", @strings ) ]} print "ok\\n" end *************** *** 356,361 **** --- 486,513 ---- ok OUTPUT + output_is(<<CODE, <<OUTPUT, "gt_s_sc_ic"); + @{[ compare_strings( 2, "gt", @strings ) ]} + print "ok\\n" + end + ERROR: + print "bad\\n" + end + CODE + ok + OUTPUT + + output_is(<<CODE, <<OUTPUT, "gt_sc_sc_ic"); + @{[ compare_strings( 3, "gt", @strings ) ]} + print "ok\\n" + end + ERROR: + print "bad\\n" + end + CODE + ok + OUTPUT + output_is(<<CODE, <<OUTPUT, "ge_s_s_ic"); @{[ compare_strings( 0, "ge", @strings ) ]} print "ok\\n" *************** *** 367,373 **** ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "ge_s_sc_ic"); @{[ compare_strings( 1, "ge", @strings ) ]} print "ok\\n" end --- 519,525 ---- ok OUTPUT ! output_is(<<CODE, <<OUTPUT, "ge_sc_s_ic"); @{[ compare_strings( 1, "ge", @strings ) ]} print "ok\\n" end *************** *** 378,383 **** --- 530,557 ---- ok OUTPUT + output_is(<<CODE, <<OUTPUT, "ge_s_sc_ic"); + @{[ compare_strings( 2, "ge", @strings ) ]} + print "ok\\n" + end + ERROR: + print "bad\\n" + end + CODE + ok + OUTPUT + + output_is(<<CODE, <<OUTPUT, "ge_sc_sc_ic"); + @{[ compare_strings( 3, "ge", @strings ) ]} + print "ok\\n" + end + ERROR: + print "bad\\n" + end + CODE + ok + OUTPUT + output_is(<<'CODE', <<OUTPUT, "same constant twice bug"); set S0, "" set S1, "" *************** *** 421,426 **** --- 595,606 ---- end CODE + output_is(<<'CODE',ord('a'),'2-param ord, multi-character string'); + ord I0,"abc" + print I0 + end + CODE + output_is(<<'CODE',ord('a'),'2-param ord, one-character string register'); set S0,"a" ord I0,S0 *************** *** 493,498 **** --- 673,685 ---- end CODE + output_is(<<'CODE','Cannot get character past end of string','3-param ord, multi-character string register, from end, OOB'); + set S0,"ab" + ord I0,S0,-3 + print I0 + end + CODE + output_is(<<CODE, <<OUTPUT, "if_s_ic"); set S0, "I've told you once, I've told you twice..." if S0, OK1 *************** *** 554,560 **** ok 9 OUTPUT ! output_is(<<CODE, <<OUTPUT, "repeat"); set S0, "x" repeat S1, S0, 12 --- 741,747 ---- ok 9 OUTPUT ! output_is(<<CODE, <<OUTPUT, "repeat_s_s|sc_i|ic"); set S0, "x" repeat S1, S0, 12 *************** *** 596,601 **** --- 783,794 ---- >< done OUTPUT + output_is(<<'CODE','Cannot repeat with negative arg','repeat OOB'); + repeat S0, "japh", -1 + end + CODE + + # Set all string registers to values given by &$_[0](reg num) sub set_str_regs { my $code = shift; *************** *** 623,643 **** while (@strings) { my $s1 = shift @strings; my $s2 = shift @strings; ! my $arg; ! $rt .= " set S0, \"$s1\"\n"; ! if ($const) { ! $arg = "\"$s2\""; } else { ! $rt .= " set S1, \"$s2\"\n"; ! $arg = "S1"; } if (eval "\"$s1\" $op \"$s2\"") { ! $rt .= " $op S0, $arg, OK$i\n"; $rt .= " branch ERROR\n"; } else { ! $rt .= " $op S0, $arg, ERROR\n"; } $rt .= "OK$i:\n"; $i++; --- 816,849 ---- while (@strings) { my $s1 = shift @strings; my $s2 = shift @strings; ! my $arg1; ! my $arg2; ! if ($const == 3) { ! $arg1 = "\"$s1\""; ! $arg2 = "\"$s2\""; ! } ! elsif ($const == 2) { ! $rt .= " set S0, \"$s1\"\n"; ! $arg1 = "S0"; ! $arg2 = "\"$s2\""; ! } ! elsif ($const == 1) { ! $rt .= " set S0, \"$s2\"\n"; ! $arg1 = "\"$s1\""; ! $arg2 = "S0"; } else { ! $rt .= " set S0, \"$s1\"\n"; ! $rt .= " set S1, \"$s2\"\n"; ! $arg1 = "S0"; ! $arg2 = "S1"; } if (eval "\"$s1\" $op \"$s2\"") { ! $rt .= " $op $arg1, $arg2, OK$i\n"; $rt .= " branch ERROR\n"; } else { ! $rt .= " $op $arg1, $arg2, ERROR\n"; } $rt .= "OK$i:\n"; $i++;