Softanza
StartFrançais
Softanza
Research · narration

Your First Taste of Systems Programming - Without the Fear

Systems programming traditionally requires mastering three domains:

by Mansour Ayouni · in the repository since 2025-07-12 · feature essay · area System programming

How Softanza's Complete Low-Level Framework Takes You from Buffers to OS Integration


The Three Pillars of Systems Programming

  1. Memory Management - Allocating, manipulating, and freeing memory safely
  2. Process Control - Spawning programs, capturing output, managing execution
  3. Data Transformation - Moving data between memory, files, and external tools

Softanza gives you all three in a safe, learnable environment:

  • stkBuffer/stkPointer - Safe memory operations with bounds checking
  • stzSystemCall - Cross-platform process execution with named commands
  • Integration layer - Seamless data flow between memory and OS

Part 1: Memory - Your Foundation

Understanding Buffers

Buffers are chunks of memory you directly control:

Haro
# Create a buffer - like a box that holds 50 bytes
oMemory = new stkMemory()
oBuffer = oMemory.CreateBuffer(50)

? oBuffer.Size()        # --> 0 (nothing in it yet)
? oBuffer.Capacity()    # --> 50 (but can hold 50 bytes)

# Put data in it
oBuffer.Write(0, "Hello")
? oBuffer.Size()        # --> 5 (now has 5 bytes)
? oBuffer.Read(0, 5)    # --> "Hello"

illustration

Working with Pointers

Pointers let you reference memory indirectly:

Haro
# Create pointer to buffer section
oPointer = oBuffer.GetReadPointer()
? oPointer.Read(0, 5)   # --> "Hello"

# Create view of specific range
oView = oPointer.CreateSubView(0, 3)
? oView.ReadAll()       # --> "Hel"

illustration


Part 2: Process Control - Talking to the OS

The stzSystemCall Class

Instead of cryptic shell commands, use named operations:

Haro
# List files (cross-platform)
Sy = new stzSystemCall(:ListFiles)
? Sy.Run()
# Works on Windows, Linux, macOS automatically

# Copy file with parameters
Sy = new stzSystemCall(:CopyFile)
Sy.SetParam(:source, "data.txt")
Sy.SetParam(:dest, "backup.txt")
Sy.Run()

if Sy.Succeeded()
    ? "File copied successfully"
ok

illustration

Available Command Domains

Over 80 pre-built commands across categories:

  • Files: :CopyFile, :MoveFile, :FindFiles
  • Network: :Ping, :DownloadFile, :CurlPost
  • Git: :GitCommit, :GitPush, :GitStatus
  • Media: :ResizeImage, :VideoToGif, :CompressVideo
  • Database: :SqliteQuery, :SqliteBackup
  • Security: :EncryptFile, :Sha256sum
  • Docker: :DockerBuild, :DockerRun

All handle cross-platform differences automatically.


Part 3: Integration - Where Power Emerges

Buffer → SystemCall Pipeline

Process data through external tools:

Haro
# Create buffer with data
oBuffer = oMemory.CreateBuffer(1000)
oBuffer.Write(0, "# My Document\n\nContent here")

# Save to file
oBuffer.SaveToFileAll("doc.md")

# Convert with Pandoc
Sy = new stzSystemCall(:Markdown2Html)
Sy.SetParam(:input, "doc.md")
Sy.SetParam(:output, "doc.html")
Sy.Run()

# Load result back
oBuffer.Clear()
oBuffer.LoadFromFile("doc.html")
? oBuffer.Size()  # HTML is larger than Markdown

illustration

SystemCall → Buffer Pattern

Capture external tool output directly:

Haro
# Download file
Sy = new stzSystemCall(:DownloadFile)
Sy.SetParams([
    [:url, "https://api.example.com/data.json"],
    [:file, "temp.json"]
])
Sy.Run()

# Load into buffer for parsing
oBuffer.LoadFromFile("temp.json")
cJson = oBuffer.Read(0, oBuffer.Size())

# Process in memory
oData = ParseJson(cJson)

illustration

Direct Integration Methods

Enhanced buffer methods for syscalls:

Haro
# Load syscall output directly
oBuffer.LoadFromSystemCall(
    StzSystemCallQ(:GitLog).WithParamQ(:n, "5")
)

# Process buffer through tool
oBuffer.Write(0, "uncompressed data...")
Sy = new stzSystemCall(:GzipCompress)
oBuffer.SaveAndProcess("data.txt", Sy)

illustration


Part 4: Real-World Examples

Example 1: Image Processing Pipeline

Haro
# Download images
aUrls = ["url1", "url2", "url3"]
oDownload = new stzSystemCall(:DownloadFile)

for i = 1 to len(aUrls)
    oDownload.SetParams([
        [:url, aUrls[i]],
        [:file, "image" + i + ".jpg"]
    ])
    oDownload.Run()
next

# Batch resize
oResize = new stzSystemCall(:ResizeImage)
for i = 1 to 3
    oResize.Reset()
    oResize.SetParams([
        [:input, "image" + i + ".jpg"],
        [:size, "800x600"],
        [:output, "thumb" + i + ".jpg"]
    ])
    oResize.Run()
next

illustration

Example 2: Git Workflow Automation

Haro
# Check status
Sy = new stzSystemCall(:GitStatus)
cStatus = Sy.Run()

if substr(cStatus, "modified:") > 0
    # Commit changes
    new stzSystemCall(:GitCommit) {
        SetParam(:message, "Auto-commit: " + TimeStamp())
        Run()
    }
    
    # Push to remote
    new stzSystemCall(:GitPush) {
        SetParam(:branch, "main")
        Run()
        
        if Succeeded()
            ? "Pushed successfully"
        else
            ? "Push failed: " + Error()
        ok
    }
ok

illustration

Example 3: Data Processing Chain

Haro
# Download → Decompress → Parse → Process → Save

# 1. Download
StzSystemCallQ(:DownloadFile).
    SetParamsQ([[:url, "..."], [:file, "data.zip"]]).
    Run()

# 2. Extract
StzSystemCallQ(:UnzipFiles).
    SetParamsQ([[:source, "data.zip"], [:dest, "data/"]]).
    Run()

# 3. Load into buffer
oBuffer = oMemory.CreateBuffer(10000)
oBuffer.LoadFromFile("data/records.csv")

# 4. Process in memory
cCsv = oBuffer.Read(0, oBuffer.Size())
aRecords = ParseCSV(cCsv)
aFiltered = FilterRecords(aRecords)

# 5. Save results
oBuffer.Clear()
oBuffer.Write(0, RecordsToJSON(aFiltered))
oBuffer.SaveToFileAll("output.json")

illustration

Example 4: Binary File Analysis

Haro
# Download binary file
Sy = new stzSystemCall(:DownloadFile)
Sy.SetParams([[:url, "..."], [:file, "program.exe"]])
Sy.Run()

# Calculate checksum
oHash = new stzSystemCall(:Sha256sum)
oHash.SetParam(:file, "program.exe")
cChecksum = oHash.Run()

# Load into buffer for analysis
oBuffer = oMemory.CreateBuffer(1000000)
oBuffer.LoadFromFile("program.exe")

# Read header
cHeader = oBuffer.Read(0, 64)
? "Magic bytes: " + hex(cHeader[1]) + hex(cHeader[2])

# Get pointer to specific section
oPtr = oBuffer.GetReadPointer()
oView = oPtr.CreateSubView(100, 200)
? "Section data: " + oView.ReadAll()

illustration


Part 5: Advanced Patterns

Pattern 1: Streaming Large Files

Haro
# Process file in chunks
oBuffer = oMemory.CreateBuffer(4096)  # 4KB buffer
fp = fopen("large_file.dat", "rb")

nBytesRead = 0
while TRUE
    # Read chunk
    cChunk = fread(fp, 4096)
    if len(cChunk) = 0
        break
    ok
    
    # Load into buffer
    oBuffer.Clear()
    oBuffer.Write(0, cChunk)
    
    # Process through syscall
    oBuffer.SaveToFileAll("chunk.tmp")
    Sy = new stzSystemCall(:ProcessChunk)
    Sy.SetParam(:file, "chunk.tmp")
    Sy.Run()
    
    nBytesRead += len(cChunk)
end

fclose(fp)
? "Processed " + nBytesRead + " bytes"

illustration

Pattern 2: Error Recovery with Retry

Haro
def DownloadWithRetry(cUrl, cFile, nMaxRetries)
    Sy = new stzSystemCall(:DownloadFile)
    Sy.SetParams([[:url, cUrl], [:file, cFile]])
    
    for i = 1 to nMaxRetries
        Sy.Run()
        
        if Sy.Succeeded() and fexists(cFile)
            ? "Downloaded on attempt " + i
            return TRUE
        ok
        
        ? "Attempt " + i + " failed, retrying..."
        sleep(i * 1000)  # Exponential backoff
    next
    
    return FALSE

illustration

Pattern 3: Parallel Processing

Haro
# Process multiple files concurrently
aFiles = ["file1.jpg", "file2.jpg", "file3.jpg"]
aCalls = []

# Queue all operations
for cFile in aFiles
    Sy = new stzSystemCall(:ResizeImage)
    Sy.SetParams([
        [:input, cFile],
        [:size, "800x600"],
        [:output, "thumb_" + cFile]
    ])
    aCalls + Sy
next

# Execute (would need async support)
for oCall in aCalls
    oCall.Run()  # Future: oCall.RunAsync()
next

illustration


Part 6: Learning Path

Stage 1: Buffers (Week 1)

  • Create and manipulate buffers
  • Understand capacity vs size
  • Practice read/write operations
  • File loading and saving

Stage 2: System Calls (Week 2)

  • Execute simple commands
  • Work with parameters
  • Handle success/failure
  • Capture output

Stage 3: Integration (Week 3)

  • Buffer → File → SysCall → Buffer
  • Process data through external tools
  • Build simple pipelines
  • Error handling

Stage 4: Pointers (Week 4)

  • Create pointer views
  • Copy between pointers
  • Understand indirection
  • Zero-copy operations

Stage 5: Real Projects (Week 5+)

  • Build complete workflows
  • Optimize performance
  • Handle edge cases
  • Production patterns

Installation Requirements

For full functionality, install these external tools:

Bash, shown for comparison, not run
# Git
https://git-scm.com/downloads

# ImageMagick
https://imagemagick.org/script/download.php

# FFmpeg
https://ffmpeg.org/download.html

# Pandoc
https://pandoc.org/installing.html

Optional Tools

Bash, shown for comparison, not run
# Docker
https://docker.com/products/docker-desktop

# SQLite
https://sqlite.org/download.html

# GPG
https://gnupg.org/download/

Most tools provide installers for Windows, Linux, and macOS.


Why This Matters

Traditional systems programming requires:

  • Learning C/C++ syntax
  • Understanding pointers and segfaults
  • Platform-specific APIs
  • Manual memory management

Softanza's approach gives you:

  • ✅ Safe memory operations (no segfaults)
  • ✅ Cross-platform abstractions (one API)
  • ✅ Named operations (self-documenting)
  • ✅ Gradual learning curve (high → low level)
  • ✅ Real-world utility (production-ready)

You're not becoming a C programmer - you're becoming a systems-aware Haro programmer who understands what happens beneath the surface and can drop down when needed.

Cite

Mansour Ayouni. "Your First Taste of Systems Programming - Without the Fear". Softanza narrations, 2025. https://mayouni.github.io/stzsite/en/narrations/stz-lowlevel-system-programming.html

Not run: its code touches files, the network, the clock or chance. The article is published as written; its blocks are illustrations. The code of the articles is Haro code. Where an article was written before the language took its present name, the name was changed and nothing else. Genre, area and series read from the file's name, the year from its first commit: derived, until the article carries its own header. The file on GitHub(opens in a new tab)