Hi there! My name is Adrian Kummerländer and I am a software developer currently studying mathematics in Karlsruhe. On these pages you will find blog articles covering amongst other topics some of my experiences in software development, open source and self hosting as well as repositories and information on some of my personal projects. If you have any comments or questions feel free to reach out. I hope you will find something here worth your time.

» Notes on BlackBerry OS 10 development in 2017

October 3, 2017 | Adrian Kummerländer

I recently broke my seven-year streak of only using smartphones in the tradition of Nokia's fabled N900. The reason for this change was the growing age of my Jolla phone combined with my continued desire for a working physical keyboard1. In today's market overflowing with faceless, exchangeable, uninspired and uniform touch-only devices this left me no choice but to opt for the last true BlackBerry: The Passport.

» Tinkering with meta tools

January 20, 2017 | Adrian Kummerländer

If the contents of this website are of interest to you chances are that you also know how easy it is to spend large parts of one's leisure time tinkering with computer systems and improving workflows while losing sight of what one actually wants to accomplish. I am going to use this article to document parts of my current personal computing setup in an attempt to summarize and refocus my efforts in this direction in addition to articulating some of my thoughts in this context.

» Visualisierung von Metriken in Voronoi-Diagrammen

May 22, 2016 | Adrian Kummerländer

In der Analysis 2 Vorlesung meines Mathematik Studiums beschäftigen wir uns derzeit mit Normen und Metriken in endlich dimensionalen Vektorräumen, welche wiederum die Grundlage für die Übertragung der, aus Analysis 1 bekannten, Konvergenz und Stetigkeitsbegriffe in höhere Dimensionen schaffen. Während der Bearbeitung der entsprechenden Übungsblätter habe ich dabei nach Visualisierungsmöglichkeiten recherchiert, um eine bessere Intuition für diese Begriffe zu erlangen. Voronoi-Diagramme sind eine solche Möglichkeit, deren Grundlagen und Generierung ich in diesem Artikel zwischen Theorie und Praxis näher erläutern möchte.

» Implement deferred word, conditional resolution

April 13, 2017 at 19:51 | slang | d2126f | Adrian Kummerlaender

Due to the non-trivial way tokens were previously processed the compiler could not safely perform tail-call elimination. Thus the slang evaluation depth was restricted by the maximum call stack size.

This issue is mitigated by introducing deferred word resolution - i.e. pushing expanded tokens onto a buffer stack and processing them in an explicit loop.

This change ties into the implementation of the language's conditional primitive. The previous implementation did implicitly not support direct nesting of conditional expressions such as:

truthA if
    truthB if
    then else

This issue is now made explicit by disallowing direct nesting of conditionals as depicted above. Appropriate exceptions are generated when required and the conditional primitive is reimplemented in a more robust fashion under the assumption that this rule holds. Note that nesting is still fully supported iff. the nested conditional is contained in a deferredly evaluated word. As a positive side effect this will make it slightly harder to generate unreadable code by forcing developers to write simpler words.

The main change of the conditional primitive lies in deferring branch token processing until the conditional expression is concluded by else. This is achieved by capturing non-dropped tokens in an internal buffer akin to how the word definition operator § is implemented. The branch buffer is discharged after else is evaluated. Discharging is triggered via the newly introduced result method of the primitive evaluation module. This avenue for injecting tokens into the processing stream may be used by further primitives in the future.

» Expand conditional primitive to choose between `then` and `else` branch

April 12, 2017 at 16:15 | slang | 061db1 | Adrian Kummerlaender

i.e. 1 if true then false else evaluates to true, 0 if true then false else evaluates to false.

» Use `pandoc` as markdown processor

January 17, 2017 at 19:38 | blog.kummerlaender.eu | 23f629 | Adrian Kummerlaender

The trigger but not the actual reason for this replacement of kramdown with pandoc was a strange generation issue with kramdown's latest release.

All recent articles failed to generate anything more than an empty page. A quick check of the resulting HTML for those articles offered nothing out of the ordinary. After taking a close look at the articles in question I narrowed the set of failing articles down to those containing footnotes - tangentially I only started using footnotes a couple of articles ago i.e. this explained this part of the issue.

Some debugging of InputXSLT offered the following problem: Xerces-C generated an error message and stopped processing XML inputs containing nbsp non-blocking space characters in the implementation of the external-command function. This change in kramdown's output can be traced back to enhancement issue 399. Obviously this is not a problem in kramdown but an issue in the way this static site generator is wrapping HTML inputs.

This problem should be solvable by adding appropriate namespace and doctype declarations to the markdown-generated HTML output. Instead I opted to perform the change to pandoc I had already planned for quite some time.

The choice fell on pandoc as it offers some additional markdown features as well as allowing for conversion to a rich set of document formats. i.e. features like printing articles as PDF using LaTeX are trivial to implement if pandoc is the markdown processor of choice. Furthermore page compilation is noticeably faster using pandoc.

One might note that this switch only solved the original issue by coincidence: Should pandoc start to generate non-blocking space characters the same problem will occur. But I have hopes that such a change would be configurable via pandoc's plethora of configuration options. As this static site generator assumes everything to be XHTML I see no reason why I should not continue to treat HTML inputs as XML.

» Implement support of server side math expression rendering

May 4, 2016 at 21:39 | blog.kummerlaender.eu | 67162f | Adrian Kummerlaender

Many websites employ the MathJax library for dynamically rendering LaTeX math expressions on the client side. I expect to require support for doing just that in the future. But as with syntax highlighting I am of the opinion that this kind of stuff should be performed once during site compilation instead of wasting ressources by forcing each client to do this job for every single page request.

Luckily there is a MathJax-node module that allows using the MathJax library on the server side.

This commit adds support for rendering math expressions written in Markdown respectively LaTeX as follows: $$1 + 1 \neq 0$$ on the server side.

This required the introduction of a new math_highlighter helper template in formatter.xsl based on the tex2html utility provided by MathJax-node. This formatter is matched against the (Markdown parser generated) script node in formatter.xsl's embellish mode. The HTML rendering of the expression is then embedded in a p class="math" node. This explicit labeling allows master.xsl to include the math.css rules only for pages that actually contain math expressions.

Note that the XHTML rendering utility stylesheet xhtml.xsl currently adds a XML comment to each span node. This is a workaround to prevent Xalan from collapsing "empty" span tag pairs into single nodes which otherwise leads to rendering errors as it is not valid HTML and is interpreted as a wrong tree structure by the browser.

Note that the CSS rules declared in math.css are explicitly not part of the MIT licensed part of this repository but where generated by MathJax.

As there is currently no productive content making use of math expressions a demo page is available under page/math_test/.

» Interpose `open` library function

February 20, 2016 at 21:30 | change | b3ef0f | Adrian Kummerlaender

open is not as side effect free as I had imagined - i.e. if the flag O_TRUNC is passed it truncates the file contents alongside opening the file descriptor. In practice this is done by emacs prior to writing the new file content and as such needs to be intercepted so we can start tracking the file before it is changed.

Interposing open required some changes to make the library work without including fcntl.h. This header not only defines some of the flags we require to check if a library call actually is able to change files but also defines the open library function.

While implementing this change I noticed that the function interpositions implemented in C++ actually need to be declared as external "C" so their names do not get wrangled during compilation. I suspect that this was previously implicitly done for e.g. mmap and write by the included C standard library headers. However this did not work for open which is why all function interpositions are now explicitly declared external.

End result: emacs file changes are now tracked correctly.

» Implement static allocator for initialization

February 17, 2016 at 14:02 | change | af756d | Adrian Kummerlaender

The previous interposition logic based on plain usage of dlsym analogously to various online examples led to a deadlock during neovim startup. This deadlock was caused by neovim's custom memory allocation library jemalloc because it calls mmap during its initialization phase. The problem with calling mmap during initialization is that this already leads to executing libChangeLog's mmap version whoes static actual_mmap function pointer is not initialized at this point in time. This is detected and leads to a call to dlsym to remedy this situation. Sadly dlsym in turn requires memory allocation using calloc which leads us back to initializing jemalloc and as such to a deadlock.

I first saw this as a bug in jemalloc which seemed to be confirmed by a short search in my search engine of choice. This prompted me to create an appropriate bug report which was dismissed as a problem in the way mmap was interposed and not as a bug in the library. Thus it seems to be accepted practice that it is not the responsibility of a custom memory allocator to cater to the initialization needs of other libraries relying on function interposition. This is of course a valid position as the whole issue is a kind of chicken and egg problem where both sides can be argued.

To cut to the chase I was left with the only option of working around this deadlock by adapting libChangeLog to call dlsym without relying on the wrapped application's memory allocator of choice. The most straight forward way to do this is to provide another custom memory allocator alongside the payload function interpositions of mmap and friends.

init/alloc.cc implements such a selectively transparent memory allocator that offers a small static buffer for usage in the context of executing dlsym.The choice between forwarding memory allocation requests to the wrapped application's allocator and using the static buffer is governed by init::dlsymContext. This tiny helper class maintains an dlsym_level counter by posing as a scope guard.

The end result of this extension to libChangeLog is that it now also works with applications using jemalloc such as neovim and should overall be much more robust during its initialization phase.

» Implement support for excluding arbitrary paths from tracking

February 14, 2016 at 19:52 | change | 1ffaf3 | Adrian Kummerlaender

The library may be provided with a new-line separated list of regular expressions via the newly introduced CHANGE_LOG_IGNORE_PATTERN_PATH.

Any proposed tracking path that is matched by any of the provided patterns is excluded from change reporting. This functionality uses the Standard's regular expression parsing functionality and as such doesn't introduce any new dependencies. If no file path is provided or the provided file path is unreadable all paths will be tracked.

change was adapted to set CHANGE_LOG_IGNORE_PATTERN_PATH to .change_log_ignore which means that it will by default exclude any patterns provided via this file in the current working directory.

An example for such a file customized for hiding vim's internal write logic may look as follows:


Note that this is implemented in a fashion where it is not guaranteed that the full canonical path is checked against the patterns. It remains to be decided if this is enough for all common use cases of this new functionality.

tracking::PathMatcher lacks any explicit thread synchronization - according to my current knowledge this should not be necessary as we are only ever reading the private std::vector<std::regex> instance. If invalid regular expressions are provided they are silently ignored.

» Delay tracking activation

February 11, 2016 at 17:43 | change | 7582ab | Adrian Kummerlaender

Introduce global static enabled variable used to signal the interposed functions to either start tracking or perform plain forwarding without any additional logic. This is required as e.g. nvim crashed when wrapped in libChangeLog because it called interposed functions during library initialization.

» Add initial working directory to settings handler

December 12, 2015 at 22:31 | MetaTerm | e3f734 | Adrian Kummerlaender

In addition to increasing customizability this change makes it clear that the working directory property only concerns the intial working directory and is not updated if the contained process changes its directory.

Note that setting the intial working directory is broken in upstream QMLTermWidget and the appropriate patch 1 is not merged at the time of this commit.

» Reimplemented `kill` command using actual signal sending

September 4, 2015 at 20:05 | MetaTerm | 52dd09 | Adrian Kummerlaender

Previously kill merely destroyed the terminal widget. This is contrary to the expected notion of kill, i.e. actually killing the process explicitly instead of relying on side effects.

The normal mode d verb now explicitly destroys the current item's content, be it a terminal widget or a history view.

» Prevent visual selection change on `kill` command

August 30, 2015 at 16:41 | MetaTerm | e5a3db | Adrian Kummerlaender

TerminalItem's reset member method wrongly performed a visual selection change which led to inconsistency when calling kill on a non-selected index. Visual selection update is now performed on history view instantiation.

» Automatically destroy terminal when killed and display history

August 29, 2015 at 20:12 | MetaTerm | 0dd495 | Adrian Kummerlaender

Child processes of MetaTerm may be terminated using other ways that the integrated kill command. Automatic terminal widget destruction in such a event prevents the user from viewing the output of non-interactive applications. This requires MetaTerm to display the application's output after it was terminated. This requirement is implemented via the new HistoryViewer widget that is instantiated after the terminal widget instance has been destroyed.

» Extract all settings into `SettingsHandler` object

August 19, 2015 at 09:13 | MetaTerm | 4cb435 | Adrian Kummerlaender

This enables the user to straight forwardly change all application settings via command mode.

During the implementation of this change I discovered that the way I was passing around StateHandler and SettingsHandler instances using properties was unnecessary. If all object instances are created in a common hierarchy they can access each other by their id property - i.e. settings and mode are available to the whole application without property trickery.

» Restructure QML and JS sources

August 15, 2015 at 14:06 | MetaTerm | d84312 | Adrian Kummerlaender

list holds the components of the central list UI element. command holds the UI and implementation parts of the command mode. widget holds more or less general purpose elements that may also be of use in other circumstances.

» Changed token determination regarding identifier values

June 10, 2015 at 18:32 | SimpleParser | 0985a6 | Adrian Kummerlaender

» Implemented basic tape log printout in _Turing_ example

March 14, 2015 at 21:43 | TypeAsValue | 73be8f | Adrian Kummerlaender