String Functions

Description

PowerBASIC provides standard string manipulation functions that operate on STRING variables and return a new STRING. These functions are case-sensitive for character content but preserve the original case (except UCASE$/LCASE$). All functions return a new string; the original is unchanged.

LEFT$

Syntax: LEFT$(string$, n)

Description

Returns the leftmost n characters of string$. If n is less than 1, an empty string is returned. If n exceeds the string length, the entire string is returned.

Parameters

ParameterDescription
string$The source STRING expression
nNumber of characters to extract (numeric expression)

Example

LOCAL s$, r$ AS STRING
s$ = "Hello World"
r$ = LEFT$(s$, 5)       ' r$ = "Hello"

Generated Assembly

Source: pb_cg_emit_left_builtin (pb_codegen.c:2820)
; Clamp n to [0, buffer_capacity-1]
cmp    rax, 0
jge    __pb_left_count_nonneg_N
xor    rax, rax
__pb_left_count_nonneg_N:
cmp    rax, <capacity-1>
jle    __pb_left_count_cap_N
mov    rax, <capacity-1>
__pb_left_count_cap_N:
mov    [rbp - print_len_offset], rax   ; effective count

lea    rcx, [rbp - asciiz_scratch]     ; dest buffer
mov    rdx, [rbp - print_ptr_offset]   ; source
mov    r8, [rbp - print_len_offset]
add    r8, 1                           ; count + 1 for NUL
call   [__imp_lstrcpynA]               ; lstrcpynA(dest, src, n+1)
lea    rax, [rbp - asciiz_scratch]     ; return buffer ptr

RIGHT$

Syntax: RIGHT$(string$, n)

Description

Returns the rightmost n characters of string$. If n is less than 1, an empty string is returned. If n exceeds the string length, the entire string is returned.

Parameters

ParameterDescription
string$The source STRING expression
nNumber of characters to extract (numeric expression)

Example

LOCAL s$, r$ AS STRING
s$ = "Hello World"
r$ = RIGHT$(s$, 5)      ' r$ = "World"

Generated Assembly

Source: pb_cg_emit_right_builtin (pb_codegen.c:2863)
; Get source length via lstrlenA
mov    rcx, [rbp - print_ptr_offset]
call   [__imp_lstrlenA]
mov    [rbp - written_offset], rax     ; source length
; Clamp n to [0, min(source_len, buffer_capacity)]
; Compute start offset = source_len - n
mov    rdx, [rbp - print_ptr_offset]
add    rdx, [rbp - written_offset]     ; src + source_len
sub    rdx, [rbp - print_len_offset]   ; src + source_len - n
; Copy n bytes + NUL
lea    rcx, [rbp - asciiz_scratch]
mov    r8, [rbp - print_len_offset]
call   [__imp_memcpy]
; NUL-terminate at buffer[n]

MID$

Syntax: MID$(string$, start [, count])

Description

Returns a substring of string$ starting at position start (1-based). If count is omitted, returns all characters from start to the end. If start is less than 1, it is clamped to 1. If start exceeds the string length, an empty string is returned.

Parameters

ParameterDescription
string$The source STRING expression
start1-based start position (numeric expression)
count(Optional) Number of characters to extract; defaults to remaining length

Example

LOCAL s$, r$ AS STRING
s$ = "Hello World"
r$ = MID$(s$, 7, 5)     ' r$ = "World"
r$ = MID$(s$, 7)        ' r$ = "World" (rest of string)

Generated Assembly

Source: pb_cg_emit_mid_builtin (pb_codegen.c:2932)
; Clamp start >= 1, convert to 0-based
cmp    rax, 1
jge    __pb_mid_start_ok_N
mov    rax, 1
__pb_mid_start_ok_N:
sub    rax, 1                           ; 0-based index
; If start >= source_len -> empty result
cmp    rax, [rbp - written_offset]
jae    __pb_mid_empty_N
; Compute count (or remaining length), clamp to buffer
; Copy from source[start] for count+1 bytes
mov    rdx, [rbp - print_ptr_offset]
add    rdx, rax                         ; source + start
lea    rcx, [rbp - asciiz_scratch]
mov    r8, [rbp - print_len_offset]
add    r8, 1
call   [__imp_lstrcpynA]
jmp    __pb_mid_done_N
__pb_mid_empty_N:
mov    byte [rbp - asciiz_scratch], 0   ; empty string
__pb_mid_done_N:

TRIM$ / LTRIM$ / RTRIM$

Syntax: TRIM$(string$)   LTRIM$(string$)   RTRIM$(string$)

Description

Removes whitespace characters (space, tab, CR, LF) from a string.

Parameters

ParameterDescription
string$The STRING expression to trim

Example

LOCAL s$, r$ AS STRING
s$ = "   Hello World   "
r$ = TRIM$(s$)          ' r$ = "Hello World"
r$ = LTRIM$(s$)         ' r$ = "Hello World   "
r$ = RTRIM$(s$)         ' r$ = "   Hello World"

Generated Assembly

Source: pb_cg_emit_trim_builtin (pb_codegen.c:3066) + pb_cg_emit_trim_temp (pb_codegen.c:1930)
; Copy source to scratch buffer
lea    rcx, [rbp - asciiz_scratch]
mov    rdx, [rbp - print_ptr_offset]
mov    r8, capacity
call   [__imp_lstrcpynA]

; Find first non-whitespace (leading)
xor    rax, rax                        ; index = 0
__pb_trim_lead_loop:
cmp    rax, [rbp - len_offset]
jae    __pb_trim_all_ws_N              ; all whitespace -> empty
mov    r9b, byte [r11 + rax]           ; buffer[index]
cmp    r9b, 32                         ; space
je     __pb_trim_lead_next
cmp    r9b, 9                          ; tab
je     __pb_trim_lead_next
cmp    r9b, 10                         ; LF
je     __pb_trim_lead_next
cmp    r9b, 13                         ; CR
je     __pb_trim_lead_next
jmp    __pb_trim_lead_done
__pb_trim_lead_next:
inc    rax
jmp    __pb_trim_lead_loop
__pb_trim_lead_done:

; Find last non-whitespace (trailing)
mov    rdx, [rbp - len_offset]
__pb_trim_trail_loop:
cmp    rdx, rax
jbe    __pb_trim_bounds_done           ; crossed over
; Check buffer[rdx-1] for whitespace, dec if so
; ...
; Shift left if leading whitespace removed
; NUL-terminate at new position

UCASE$ / LCASE$

Syntax: UCASE$(string$)   LCASE$(string$)

Description

Converts all alphabetic characters in string$ to uppercase or lowercase respectively. Non-alphabetic characters are unchanged. Only ASCII range [A-Za-z] is handled.

Parameters

ParameterDescription
string$The STRING expression to convert

Example

LOCAL s$, r$ AS STRING
s$ = "Hello World"
r$ = UCASE$(s$)         ' r$ = "HELLO WORLD"
r$ = LCASE$(s$)         ' r$ = "hello world"

Generated Assembly

Source: pb_cg_emit_string_builtin_to_heap_temp (pb_codegen.c:3397)
; Copy source to heap, iterate byte-by-byte:
; UCASE: if 'a' <= byte <= 'z': sub byte, 32
; LCASE: if 'A' <= byte <= 'Z': add byte, 32
; Then point descriptor to result