StdLib — Standard Library

Essential utility functions for Plan9Basic programs. These core functions support program flow control, type checking, type conversion, object introspection, and regional format configuration. They work across all supported platforms.

CategoryFunctionsDescription
Program Control3Pause execution, process system messages
Type Checking5Detect NaN, infinity, null strings, nil pointers, sign
Type Conversion3Convert between pointers and numbers
Object Information1Get class name of objects
Format Settings2Get/set regional format settings (dates, numbers, times)

Program Control

Functions for managing program execution timing and system message processing.

FunctionSignatureDescription
pause(seconds)pause@nPause execution for n whole seconds
processmessages()processmessages@Process all pending system messages
handlemessage()handlemessage@Process a single pending system message

pause(seconds)

Pauses program execution for a specified number of whole seconds. Fractional values are truncated to the integer part. Returns 0.

╯ plan9basic
println "Starting..."
pause(2)              ' Pause for 2 seconds
println "2 seconds later..."

pause(1)              ' Pause for 1 second
println "Done!"
⚠ Warning: The pause() function only accepts whole seconds. pause(0.5) is truncated to 0 and produces no delay. For sub-second timing, use Timer controls from the GUI library.
ⓘ Note: During a pause the program is blocked and will not respond to events. For responsive applications, use shorter pauses combined with processmessages().

processmessages()

Processes all pending system messages, allowing the application to remain responsive during long operations. Returns 1.

╯ plan9basic
' Long operation with responsive UI
for i = 1 to 1000000
    ' Do some work...
    
    ' Process messages every 1000 iterations
    if i mod 1000 = 0 then
        processmessages()
    endif
next

Use cases: keeping the UI responsive during long calculations, allowing button clicks during loops, preventing “application not responding” states.

handlemessage()

Processes a single pending system message from the queue. Returns 1. Use when you need more granular control over message processing; processmessages() is generally preferred.

╯ plan9basic
' Process one message at a time for finer control
handlemessage()

Type Checking

Functions for detecting invalid or special values.

FunctionSignatureDescription
isnan(n)isnan@nIs Not-a-Number? (1=yes, 0=no)
isinfinite(n)isinfinite@nIs infinite? (1=yes, 0=no)
isnull(s$)isnull@$Is string null/empty? (1=yes, 0=no)
isassigned(p#)isassigned@#Is pointer assigned? (1=assigned, 0=nil)
sign(n)sign@nSign of number: -1, 0, or 1

isnan(n)

Tests whether a numeric value is “Not a Number” (NaN). Returns 1 if NaN, 0 if valid.

╯ plan9basic
a = 0 / 0              ' This might produce NaN
b = sqr(-1)            ' Square root of negative number

if isnan(a) = 1 then
    println "a is not a number"
endif

' Safe calculation with NaN check
value = someCalculation()
if isnan(value) = 1 then
    println "Calculation resulted in an invalid value"
    value = 0          ' Use default
endif

Common NaN sources: division of 0 by 0, square root of negative numbers, logarithm of negative numbers, and other invalid mathematical operations.

isinfinite(n)

Tests whether a numeric value represents positive or negative infinity. Returns 1 if infinite, 0 if finite.

╯ plan9basic
a = 1 / 0              ' Division by zero produces infinity
b = -1 / 0             ' Negative infinity

if isinfinite(a) = 1 then
    println "a is infinite"
endif

' Validate calculation results
result = someCalculation()
if isinfinite(result) = 1 then
    println "Result overflow - value is infinite"
endif

isnull(s$)

Tests whether a string is null (empty or contains only the null character #0). Returns 1 if null, 0 if content exists.

╯ plan9basic
a$ = ""
b$ = "Hello"

if isnull(a$) = 1 then
    println "a$ is null or empty"
endif

if isnull(b$) = 0 then
    println "b$ has content: "; b$
endif

isassigned(p#)

Tests whether a pointer is assigned (not nil). Returns 1 if assigned (not nil), 0 if nil.

╯ plan9basic
obj# = createSomeObject()

if isassigned(obj#) = 1 then
    println "Object was created successfully"
else
    println "Object creation failed (nil pointer)"
endif
ⓘ Note: isassigned() returns 1 when the pointer IS valid (assigned). Think of it as “is not nil”. When the pointer is nil, it returns 0.

sign(n)

Returns the sign of a number: 1 if positive, 0 if zero, -1 if negative.

╯ plan9basic
println sign(42)       ' Output: 1
println sign(0)        ' Output: 0
println sign(-17)      ' Output: -1

' Use sign to determine direction
velocity = -5
direction = sign(velocity)
if direction = 1 then
    println "Moving forward"
else if direction = -1 then
    println "Moving backward"
else
    println "Stationary"
endif
ⓘ Note: This function is similar to sgn() in NumLib.

Type Conversion

Functions for converting between pointers and numeric values.

FunctionSignatureDescription
number(p#)number@#Pointer → numeric address
pointer#(n)pointer#@nNumeric address → pointer
pnttonum(p#)pnttonum@#Pointer → numeric (nil-safe, returns 0 for nil)

number(p#)

Converts a pointer value to its numeric (integer) representation — the raw memory address.

╯ plan9basic
obj# = createSomeObject()
addr = number(obj#)
println "Object address: "; addr

pointer#(n)

Converts a numeric value to a pointer.

╯ plan9basic
' Store a pointer as a number and restore it
obj# = createSomeObject()
addr = number(obj#)

' Later, restore the pointer
restored# = pointer#(addr)
⚠ Warning: Use pointer#() with extreme caution. Creating pointers from arbitrary numbers can cause crashes or undefined behavior if the address is invalid.

pnttonum(p#)

Converts a pointer to a numeric value with nil checking. Returns 0 if the pointer is nil — safer than number().

╯ plan9basic
' Safe nil check using pnttonum
obj# = createSomeObject()
addr = pnttonum(obj#)

if addr = 0 then
    println "Pointer is nil"
else
    println "Pointer address: "; addr
endif
ⓘ Note: pnttonum() is the recommended way to compare pointers to numbers. Direct pointer comparison in conditionals is not supported — always convert first.

Object Information

FunctionSignatureDescription
classname$(p#)classname$@#Get the class name of an object

Returns the Delphi class name of the object referenced by a pointer. Useful for runtime type checking and debugging.

╯ plan9basic
obj# = json_object#()
println "Type: "; classname$(obj#)
' Output: "TJSONObject"

' Use for runtime type checking
if classname$(obj#) = "TStringList" then
    println "It's a string list"
endif

Format Settings

Plan9Basic uses the system’s regional settings for formatting dates, times, and numbers. These functions let you customize those settings at runtime.

FunctionSignatureDescription
formatsettings(name$, value$)formatsettings@$$Set a format setting (returns 1=ok, 0=unknown)
formatsettings$(name$)formatsettings$@$Get the current value of a format setting

Available Settings

Setting NameTypeDescriptionExample Values
dateseparatorCharCharacter separating date parts/   -   .
timeseparatorCharCharacter separating time parts:   .
decimalseparatorCharDecimal point character.   ,
shortdateformatStringShort date format patternMM/dd/yyyy
longdateformatStringLong date format patternMMMM d, yyyy
shorttimeformatStringShort time format patternHH:mm
longtimeformatStringLong time format patternHH:mm:ss
timeamstringStringAM indicatorAM
timepmstringStringPM indicatorPM
╯ plan9basic
' Get current settings
println "Date separator: "; formatsettings$("dateseparator")
println "Decimal separator: "; formatsettings$("decimalseparator")
println "Short date format: "; formatsettings$("shortdateformat")

' Change to European format
formatsettings("dateseparator", ".")
formatsettings("decimalseparator", ",")
formatsettings("shortdateformat", "dd.MM.yyyy")

println "New date separator: "; formatsettings$("dateseparator")

Complete Examples

Safe Calculation with Validation

╯ safe_calc.bas
' Perform calculations with proper error checking
function safeDivide(a, b) local result
    if b = 0 then
        println "Warning: Division by zero"
        return 0
    endif
    
    result = a / b
    
    if isnan(result) = 1 then
        println "Warning: Result is NaN"
        return 0
    endif
    
    if isinfinite(result) = 1 then
        println "Warning: Result is infinite"
        return 0
    endif
    
    return result
endfunction

function safeSqrt(n) local result
    if n < 0 then
        println "Warning: Cannot take square root of negative number"
        return 0
    endif
    
    result = sqr(n)
    
    if isnan(result) = 1 then
        return 0
    endif
    
    return result
endfunction

println "=== Safe Calculation Demo ==="
println ""

println "10 / 2 = "; safeDivide(10, 2)
println "10 / 0 = "; safeDivide(10, 0)
println "sqrt(16) = "; safeSqrt(16)
println "sqrt(-4) = "; safeSqrt(-4)

Progress Indicator with Responsive UI

╯ progress.bas
' Simulate a long operation with progress updates
println "=== Processing with Progress ==="
println ""

total = 100
for i = 1 to total
    ' Simulate work
    processmessages()
    
    ' Update progress every 10%
    if i mod 10 = 0 then
        println "Progress: "; i; "%"
        pause(1)
    endif
next

println ""
println "Processing complete!"

Responsive Countdown Timer

╯ countdown.bas
' Simple countdown timer
function countdown(seconds) local i
    println "Countdown starting from "; seconds; " seconds..."
    println ""
    
    for i = seconds to 1 step -1
        println i; "..."
        pause(1)
        processmessages()
    next
    
    println ""
    println "Time's up!"
    return 0
endfunction

countdown(5)

Regional Format Configuration

╯ format_settings.bas
' Configure and display format settings
println "=== Format Settings Demo ==="
println ""

' Display current settings
println "Current Settings:"
println "  Date separator: "; formatsettings$("dateseparator")
println "  Time separator: "; formatsettings$("timeseparator")
println "  Decimal separator: "; formatsettings$("decimalseparator")
println "  Short date format: "; formatsettings$("shortdateformat")
println "  AM string: "; formatsettings$("timeamstring")
println "  PM string: "; formatsettings$("timepmstring")
println ""

' Switch to European format
println "Switching to European format..."
formatsettings("dateseparator", ".")
formatsettings("shortdateformat", "dd.MM.yyyy")
formatsettings("decimalseparator", ",")

println ""
println "New Settings:"
println "  Date separator: "; formatsettings$("dateseparator")
println "  Short date format: "; formatsettings$("shortdateformat")
println "  Decimal separator: "; formatsettings$("decimalseparator")

Value Validation Utility

╯ validate.bas
' Comprehensive value validation
function validateNumber(value) local valid
    valid = 1
    
    if isnan(value) = 1 then
        println "  - Value is NaN"
        valid = 0
    endif
    
    if isinfinite(value) = 1 then
        println "  - Value is infinite"
        valid = 0
    endif
    
    return valid
endfunction

function validateString(value$) local valid
    valid = 1
    
    if isnull(value$) = 1 then
        println "  - String is null or empty"
        valid = 0
    endif
    
    return valid
endfunction

function validatePointer(value#) local valid
    valid = 1
    
    if isassigned(value#) = 0 then
        println "  - Pointer is nil"
        valid = 0
    endif
    
    return valid
endfunction

println "=== Value Validation Demo ==="
println ""

println "Validating 42:"
validateNumber(42)

println "Validating 0/0:"
validateNumber(0/0)

println ""

println "Validating 'Hello':"
validateString("Hello")

println "Validating '':"
validateString("")

Number Sign Analysis

╯ sign_analysis.bas
' Analyze the sign of numbers
println "=== Number Sign Analysis ==="
println ""

for i = -3 to 3
    s = sign(i)
    
    print i; " is ";
    
    if s = 1 then
        println "positive"
    else if s = -1 then
        println "negative"
    else
        println "zero"
    endif
next

Best Practices

Pause Limitations

CallResult
pause(1)Pauses 1 second ✓
pause(2)Pauses 2 seconds ✓
pause(0.5)Truncated to 0 — no pause
pause(1.9)Truncated to 1 second

For sub-second timing or animations, use Timer controls from the GUI library instead.

Pause and Responsiveness

When using pause() for extended periods, break it into smaller chunks:

╯ plan9basic
' Instead of:
pause(10)  ' UI frozen for 10 seconds

' Use:
for i = 1 to 10
    pause(1)
    processmessages()
next

Checking for Invalid Values

Always validate calculation results that might produce special values:

╯ plan9basic
result = someCalculation()
if isnan(result) = 1 or isinfinite(result) = 1 then
    ' Handle error
    result = 0
endif

Pointer Safety

Always check for nil before using a pointer:

╯ plan9basic
obj# = getObject()
if isassigned(obj#) = 1 then
    ' Safe to use obj#
    println classname$(obj#)
else
    println "Object is nil"
endif

Quick Reference

FunctionSignatureDescription
pause(seconds)pause@nPause execution (whole seconds only)
processmessages()processmessages@Process all pending system messages
handlemessage()handlemessage@Process single system message
isnan(n)isnan@nIs Not-a-Number? (1=yes, 0=no)
isinfinite(n)isinfinite@nIs infinite? (1=yes, 0=no)
isnull(s$)isnull@$Is string null/empty? (1=yes, 0=no)
isassigned(p#)isassigned@#Is pointer assigned? (1=yes, 0=nil)
sign(n)sign@nSign: -1, 0, or 1
number(p#)number@#Pointer → numeric address
pointer#(n)pointer#@nNumeric address → pointer
pnttonum(p#)pnttonum@#Pointer → numeric (nil-safe)
classname$(p#)classname$@#Class name of object
formatsettings(name$, val$)formatsettings@$$Set format setting (1/0)
formatsettings$(name$)formatsettings$@$Get format setting

14 functions total across 5 categories.