
Sic parvis magna
I’m blessed that I started using computers at a very young age and in a time where home computers had just arrived and only had one kilobyte of RAM. That allowed me to be part of the PC revolution from the start.
I know what’s happening underneath the graphical user interfaces and how machines communicate with each other over a global network.
I have commercially and professionally used multiple programming languages in my life and as far as operating systems are concerned, I am platform agnostic. I use a combination of tools that get the job done and that won’t break the bank.
Networking, Systems and Infrastructure
I used to be a certified Mikrotik Certified Network Associate (MTCNA) and a Microsoft Certified Professional (MCP) for Windows Server.
Such certificates are “time-bombed” and expire after three years or so, which is a nice business model to get the customers to pay for the exact same certification again and again and again.
When I was still in commercial satellite communications, I worked on a daily basis with:
-
- Cisco IOS,
- Mikrotik RouterOS,
- Juniper Junos OS,
- Ubuntu Linux,
- Windows Server,
- VMware vSphere and ESXi,
- ProxMox VE,
- PowerEdge Servers,
- EqualLogic Storage Arrays,
- iSCSI and NFS,
- TCP/IPv4,
- Subnetting and Supernetting,
- Switching,
- Static Routing,
- BGP and OSPF,
- BIND9 DNS servers,
- CACTI and PHP Network Weathermaps (Graphing),
- WhatsUp Gold (Monitoring, Alerting, Triggering of Actions and Automation Scripts).
I have also given TCP/IPv4 trainings.
Programming
I wrote my first line of code in 1982 on a Casio PB100 in BASIC.
I wrote a book on natural language parser programming in Pascal for interactive fiction games in the year I finished the Gymnasium/High School, 1989/90. I also had a version of that parser written in PowerBASIC. It could understand rather complex German and English sentences.
I have learned COBOL, JCL and DB2 SQL on an actual IBM mainframe.
I have worked for the company and with the team that created the Xbase++ programming language.
Since Xbase++, I know how multi-threading works.
In a previous job, I used Lua on a daily basis and also gave Lua trainings.
Programming, query and domain specific languages that I’ve learned (most of them self-taught) and used in my career:
-
- BASIC: Too many dialects too count, from the ZX81 over the Apple ][ to PowerBasic to modern multi-threaded, object-oriented dialects like BlitzMax,
- 6502 Assembler,
- UCSD Pascal, Turbo Pascal, object-oriented Borland Pascal,
- C and C++,
- COBOL,
- JCL,
- DB2 and MySQL SQL,
- HTML,
- Xbase++,
- Flash/Actionscript,
- C#,
- Python,
- Go,
- Lua.
Ancient history
One of my first tasks at Alaska Software was to write a parser that extracted all code samples from the documentation and checked if they could compile properly. This led to a second project, the Sample Inspector, that provided a GUI interface to a library of useful code samples – an extension to the technical documentation of the product.

Later, I also implemented client-side parts of the NNTP protocol for a News Reader GUI client that I had written in Xbase++ (as a pet project) – it was later shipped under the name Baumbart.

In another pet project, I had implemented the IRC protocol to write an Internet Relay Chat bot that also included a very basic natural language parser, so it could interact with human users. It was called Xenia B, but it as never released or shipped with the product.


During my work on the Alaska ADSDBE reference documentation, I also wrote a GUI management interface for the Advantage Database Server.

Archeological Dig Site
Most of the code that I have written is owned by my previous employers and I no longer have access to any of that work.
The downloads below were hobby projects of mine which I have abandoned in the meanwhile and they come with no warranty or support whatsoever. Follow the instructions (if there are any), respect the licenses and hopefully you will have some fun with the stuff or find some use for it.
BlitzMax thread class module
This BlitzMax module contains an (abstract) class for OOP-style multithreading and multi-threading/multi-processing related helper functions. Since I’ve given up on BlitzMax and the language’s creator has also abandoned it, there won’t be any further development of this module. (BSD license.)
GUICoffee
The following sample code is a remake of the old Alaska Software Xbase++ ‘coffee’ sample application. I haven’t used Xbase++ in quite a few years now, so I had to rewrite it based upon what I could remember of the coffee sample. Basically, it is about ten programmers who drink coffee while they are working and when their cups run empty, they go to a coffee machine and get themselves a refill. When the coffee machine runs empty, too, the guy who needs coffee has to cook some fresh one first. I’ve added to this simple scenario a button that will ‘close the office’ for the day and send the developers home. Before they do that, they finish their coffees and return their cups. The last one to do so turns off the coffee machine.
This idea is implemented using ten worker threads, one for each developer. They share one resource, namely the coffee machine. The purpose of the sample is to demonstrate mutexes as a means of synchronizing access to shared resources by concurrently running threads. As you probably already know, not synchronizing the access to shared resources is a perfect way to crash your application and giving you a hell of time to find the bug.
Here is the code, written on OS X, but it also works on Windows:
'GUI Coffee, Inc. SuperStrict 'Put something on the screen. Import MaxGui.Drivers Import MaxGui.CocoaMaxGui Import Pub.Threads Import BRL.Random Import BRL.Event Import BRL.Eventqueue AppTitle = "Coffee, Inc." Global x:Int = 0 Global y:Int = 0 Global width:Int = 640 Global height:Int = 480 Global AppWindow:TGadget = CreateWindow (AppTitle, x, y, width, height) Global fileMenu:TGadget = CreateMenu ("&File", 0, WindowMenu (AppWindow)) Global xit:TGadget = CreateMenu ("E&xit", 1, fileMenu) Global helpMenu:TGadget = CreateMenu ("&Help", 2, WindowMenu (AppWindow)) Global about:TGadget = CreateMenu ("&About...", 3, helpMenu) UpdateWindowMenu AppWindow Global devStatus:TGadget[10] For Local n:Int = 0 To 9 devStatus[n] = CreateTextField (4, 4 + n*30, ClientWidth (AppWindow) - 8, 24, AppWindow) Next Global goHome:TGadget = CreateButton ("Go home, guys!", 240, 400, 140, 24, AppWindow, BUTTON_OK) 'Setup the office environment. Const cupSize:Int = 200 'Your simple Italian coffee machine. One load is good for eight cups. Type CoffeeMachine Field hasCups:Int = 10 Field hasCoffee:Int Field isCooking:Int Field myMutex:Int Method Create() hasCoffee = 0 myMutex = CreateMutex() End Method Method giveCoffee:Int( name: String, nPos:Int ) LockMutex( myMutex ) If hasCoffee <= 0 Local boiler:String = "" For Local n:Int = 1 To 8 boiler :+ "+++" SetGadgetText( devStatus[nPos], name + " is cooking fresh coffee: " + boiler ) Delay 300 Next hasCoffee = 8 * cupSize End If SetGadgetText( devStatus[nPos], name + " takes coffee." ) hasCoffee :- cupSize Delay 750 UnlockMutex( myMutex ) Return cupSize End Method Method giveCup( name: String, nPos:Int ) LockMutex( myMutex ) SetGadgetText( devStatus[nPos], name + " takes a cup.") hasCups :- 1 Delay 400 UnlockMutex( myMutex ) End Method Method returnCup( name: String, nPos:Int ) LockMutex( myMutex ) SetGadgetText( devStatus[nPos], name + " returns his cup to the kitchen.") hasCups :+ 1 Delay 1000 If hasCups = 10 SetGadgetText( devStatus[nPos], name + " is last, he turns off the coffee machine.") Delay 3000 HideGadget( goHome ) End If UnlockMutex( myMutex ) End Method End Type 'A very simple software developer. He only works as long as he has coffee. Type Developer Field Name:String Field Position:Int Field hasCoffee:Int Field machine:CoffeeMachine Global EOB:Int = False Method Create:Developer( name:String, pos:Int, machine:CoffeeMachine ) Self.Name = name Self.Position = pos Self.hasCoffee = 0 Self.machine = machine Return Self End Method Function SignalEOB() SetGadgetText( goHome, "Office is closing!" ) DisableGadget( goHome ) EOB = True End Function Method Working() machine.giveCup( name, Position ) Repeat hasCoffee :- Rand(1, Int(cupSize/4) ) If hasCoffee <= 0 SetGadgetText( devStatus[Position], name + " needs coffee !!!") hasCoffee = machine.GiveCoffee( name, Position ) Else Local cupContents:String = "" For Local n:Int = 1 To Int( 1 + hasCoffee/10) cupContents :+ "#" Next SetGadgetText( devStatus[Position], name + " is happily working. Coffee left: " + cupContents + " ( " + hasCoffee + " ml)." ) End If Delay 600 Until EOB machine.returnCup( name, Position ) SetGadgetText( devStatus[Position], name + " went home.") End Method End Type 'The thread factory Function BuildThread:Object( data:Object) Local myDev:Developer = Developer(data) myDev.Working() End Function 'Start the coffee machine Global Luigi:CoffeeMachine = New CoffeeMachine Luigi.Create() 'Get the guys to work Global DevTeam:Developer[10] Global devName:String[] = [ "Mark", .. "Brucey", .. "Skidracer", .. "SebHoll", .. "SimonH", .. "SimonA", .. "FlameDuck", .. "MarkT", .. "RobH", .. "Woz"] For Local n:Int = 0 To 9 DevTeam[n] = New Developer DevTeam[n].Create( devName[n], n, Luigi ) Next 'Ready, steady, go! Global handles:Int[10] For Local n:Int = 0 To 9 handles[n]=CreateThread( BuildThread, Object(DevTeam[n]) ) Next 'Send the boys home Function ShutDown() Developer.SignalEOB() For Local n:Int = 0 To 9 DetachThread( handles[n] ) Next End Function 'Your good old fashioned GUI event loop Repeat Select WaitEvent () Case EVENT_GADGETACTION If (EventSource () = goHome) ShutDown() End If Case EVENT_WINDOWCLOSE ShutDown() End Case EVENT_MENUACTION If EventData () = 1 Then ShutDown() End End If If EventData () = 3 Then Notify ("Coffee, Inc. only works with coffee!") End Select Forever
Application bundle for Mac OS X/Intel.
Application bundle for Mac OS X/PPC.
Executable for Windows.
Digital Nomad NNTP Server
As mentioned earlier, back at Alaska Software, I had written the first version of an NNTP desktop GUI client called Baumbart. This here is a multi-threaded NNTP/News server written in C#. I wrote it a couple of years ago to get familiar with the C# language. (GPL.)
Digital Nomad for Mono/MySQL
(C# Source Code only, compatible with OS X.)
Digital Nomad for Windows
(Installer bundled with MSDE 2000, Windows only. This was created in Windows XP times and it probably won’t run on current versions of Windows, but I won’t be investing time in this build anymore to fix or update it.)