Est. 1998 Intermediate

TINCL

TINCL, The Idiotically Named CGI Language, is a template-and-C preprocessor written in 1998 by Ben Olmstead - the creator of Malbolge - for writing CGI programs at the Colorado School of Mines. A TINCL source file is divided into named sections, mixes literal HTML with escaped blocks of C, and is compiled by a flex-based translator into a C program; the language was never taken past beta, and its distribution archive is lost

Created by Ben Olmstead, then a student at the Colorado School of Mines in Golden, Colorado, writing from the account bolmstea on the school's student web server. He is far better known for Malbolge, the deliberately unusable esoteric language he released the same month, and for maintaining the Random Programming Languages List; TINCL is the practical, unfunny half of the same personal web site

Paradigm Template and preprocessor language for CGI, translated to C. A source file is a sequence of named sections in which literal HTML is the default and everything else is an escape: %{ ... }% encloses C to be emitted verbatim, %( name )% calls an output fragment, %[ name ]% substitutes a form field, %! NAME !% substitutes an environment variable and %# expr #% prints a C integer expression. Control flow is not the language's own - it is whatever C you write between the escapes, so a loop is written by leaving a brace unclosed across a stretch of HTML
Typing Whatever C gives it. TINCL declares no types and performs no checking of its own; variables are declared in C blocks and the generated program is handed to a C compiler. Values arriving from the outside world are strings: get_value("name") returns a char pointer or NULL, getenv() supplies environment variables, and the runtime helper set_var( int *var, int min, int max, int def, char *str ) is the documented way to turn one into a bounded integer
First Appeared 1998. Every dated artefact points at April of that year: the demonstration page is written 18 April 1998 and calls the language still in Beta, and the project page carries the line 'Last Update: 20 Apr 98' unchanged in every capture from 2000 to 2004. How long before that Olmstead had been working on it is not recorded anywhere, so 1998 is the date of first public evidence rather than a documented start
Latest Version There is none to quote. TINCL was never given a version number - the project page describes it as being in 'Beta/flux' and warns that backwards compatibility, documentation and working implementations are all not guaranteed. The only release was a file called tincl.zip linked from that page and last updated on 20 April 1998; the Internet Archive never captured it, and no copy is known to survive

TINCL - The Idiotically Named CGI Language - is a template language for writing web programs, written in April 1998 by Ben Olmstead while he was a student at the Colorado School of Mines. A TINCL file is mostly HTML; where it is not HTML, it is C, wrapped in percent-brace escapes. A flex-based translator turns the whole thing into a C source file, and a C compiler turns that into a CGI executable.

The interesting thing about TINCL is who wrote it and when. In the same weeks of the same spring, on the same student account, Olmstead released Malbolge, the language built so that programming in it would be as close to the infernal as possible and which resisted being used at all for two years. TINCL is what the author of the world’s most hostile programming language wrote when he wanted to get a form processed. It is sensible, unglamorous, thoroughly commented and, by his own classification, serious - which is precisely why it disappeared while Malbolge became famous.

What actually survives

Everything on this page comes from four files, and it is worth being exact about them:

SourceDateWhat it gives
tincl/ project pagewritten 20 Apr 1998, captured 2000-2004The expansion of the name, the build requirements, the beta warning, the link to the lost tincl.zip
beer.html demo pagewritten 18 Apr 1998, captured from Oct 1999The description “based on C and generating C code (it was heavily influenced by Lex)”, and a live form pointing at a compiled TINCL program
tincl/templ.tincaptured 2002-2004, byte-identical306 lines: the complete language reference, written as commentary inside a working TINCL program
99bob.tincaptured Jan 2000The one deployed application: thirty lines, of which twenty-three are program

What does not survive is the implementation. tincl.zip was linked from the project page for six years and was never crawled; when the student account went away in 2004 the compiler went with it. There is no mirror, no source repository, no packaged copy and no reimplementation. TINCL is a language for which the specification is intact and the compiler is gone - the opposite of the usual situation with lost languages, and arguably the more frustrating one.

The name

The project page states it plainly:

TINCL (The Idiotically Named CGI Language) is a language designed for CGI programming. Like Lex and yacc, it is essentially just a C wrapper (at least for now). It is currently in Beta/flux, so backwards compatibility, documentation, and working implementations are not guaranteed.

The recursive self-deprecation is of its period and of its author - the same person whose “Ego Gratification Page” opens “About me: I’m a human, not a computer or a cucumber or something” and whose esoteric-language list opens by asking whether you have ever wondered what life would be like without our nifty tools. It also has a practical consequence: a language whose name is a joke about its own name is almost impossible to search for, and in 2026 the phrase “The Idiotically Named CGI Language” appears, so far as could be determined, nowhere on the live web outside archived copies of Olmstead’s own pages.

How a TINCL program is built

A source file is divided into up to five sections, each introduced by a name between %. and .%. Any section may be omitted:

SectionPurpose
%.config.%Declarations about the program: which HTTP methods supply input, whether to emit the default header, plus C #includes and globals that go to the top of the generated file
%.fragments.%Named blocks of output text, compiled into zero-argument C functions
%.headers.%Literal HTTP headers, with leading whitespace stripped and blank lines ignored
%.html.%The body of the program: HTML by default, C where escaped
%.c.%Straight C for the end of the generated file - function definitions and anything else

Skipping %.config.% accepts all defaults; skipping %.headers.% emits the default Content-type: text/html unless no-default-headers is set in %.config.%; skipping %.html.% produces an empty document. The config section is a small vocabulary of English words rather than a syntax - get-input, post-input, no-post-input, command-line-input, no-default-headers - and commas between them are ignored, “and may be used as desired to make the place look nicer.”

The escapes

Inside %.html.%, anything that is not a recognised escape is text to be echoed. The escapes are:

EscapeMeaning
%{ ... }%A block of C, emitted verbatim into the generated program
%' name '%Declare a fragment; everything up to the next declaration is its text
%( name )%Call a fragment; exactly synonymous with %{ name(); }%
%[ name ]%Print the form field name; inside C it becomes get_value( "name" ) with no semicolon
%! NAME !%Print the environment variable at run time; inside C, getenv( "NAME" )
%# expr #%Print a C integer expression as a signed base-10 number
%: ... :%A TINCL comment, non-recursive, stripped before the C file is written
`%? c %a :: b
%" ... "%Synonym for }% ... %{, for writing readable interleaved conditionals

Hyphens inside fragment names are mapped to underscores, “merely a convenience the author likes and nothing more” - which is how a fragment written %'html-header'% becomes the C function html_header().

Control flow by unbalanced brace

The design decision that gives TINCL its character is that it has no control structures. It has C, and C’s braces are allowed to be left open across stretches of HTML. The reference file says so outright: it is “completely permissible to leave unbalanced {} in a C block”. So a conditional plural is written like this, from the surviving beer program:

%#beer#% bottle%{ if ( beer != 1 ) { }%s%{ } }% of beer on the wall,<br>

and a loop over a fragment like this:

%{ while( beer > 0 ) { %(fragment)% } }%

Because that quickly becomes unreadable, the language supplies %" and "% as aliases so the same conditional can be written as %{ if ( bool ) { %"Some HTML"% } }%, and %?, %|, ::, |% as an even terser form. The aliases can be mixed freely with the raw braces - “a feature which can be either used or abused as you see fit.”

The one surviving application

99bob.tin is the complete deployed program, minus its comment header:

%.config.%

get-input, post-input

%{
#include <stdlib.h>
int beer;
}%

%.fragments.%
<p>
%#beer#% bottle%{ if ( beer != 1 ) { }%s%{ } }% of beer on the wall,<br>
%#beer#% bottle%{ if ( beer != 1 ) { }%s%{ } }% of beer,<br>
Take one down and pass it around,<br>
%{ if ( !--beer ) { }%No more%{ } else { }%%#beer#%%{ } }% bottle%{ if ( beer != 1 ) { }%s%{ } }% of beer on the wall.
</p>

%.html.%
%{  set_var( &beer, 0, 1000, 99, get_value( "beer" ) );  }%
<html><head><title>%#beer#% Bottles of Beer on the Wall</title></head>
<body>
%{ while( beer > 0 ) { %(fragment)% } }%
</body></html>

Three things are worth noticing. The config section declares that the program accepts both GET and POST, and that is the whole of its request handling. The unnamed leading text in %.fragments.% becomes a fragment called fragment, which is why the loop can call %(fragment)% without anything having been named. And the single line of real logic is the set_var call, which is the language’s answer to hostile input.

Taking untrusted input seriously in 1998

set_var has the signature

1
int set_var( int *var, int min, int max, int def, char *str )

and the documentation explains the arguments in terms of what a stranger might do to you: min and max are the bounds, because “if you’re using it for a loop, you don’t want someone taking up all your processor time, for example”, and def is what to use when str is null or is not a number. A form field is never an integer until it has been through a function that takes a floor, a ceiling and a fallback. In the beer program the bounds are 0 and 1000 - though the public demo page advertises 0 to 200, so the page and the program had already drifted apart by the time both were archived.

The reference file is similarly blunt about the two things it will not protect you from. Printing a form field directly “can lead to strange happenings, although no security breeches: just, if someone types in some HTML code it will be interpreted as HTML code”, with <img src="wherever"> given as the example - a plain description of what would later be called cross-site scripting, written before the term existed and dismissed as a cosmetic problem. And printing environment variables you should not, such as PATH, “is not a security hole, just a window, but windows let crackers see the holes.”

There is also a debugging feature that is more thoughtful than the beta status suggests. Passing -t to the compiler turns on command-line-input and turns off GET, POST and default headers “no matter what the config section says”, so that a program can be driven from a shell with name=value arguments - the stated reason being “so you don’t have to post potential security holes before they’re ready.”

Where it sits in 1998

TINCL was written into a specific gap. CGI in 1998 usually meant Perl, or C with a library. The alternative approach - HTML as the outer layer with code embedded in it - was arriving at exactly that moment: PHP/FI had become PHP 3 in June 1998, Microsoft’s Active Server Pages had shipped in 1996, and Perl’s HTML templating modules were in circulation. TINCL is a member of that family that chose C as its embedded language and compilation as its execution model. Its own comparison is not to any of them but to lex and yacc: like them it is a translator that eats an annotated source file and produces C, and like them its generated output is meant to be handed straight to cc.

That choice has one obvious payoff and one obvious cost. The payoff is that a TINCL page is a compiled binary with no interpreter startup, at a time when CGI meant forking a new process for every request - though no benchmark of TINCL against anything was ever published, so this is an argument about design and not a measured result. The cost is that the whole edifice needs a C toolchain plus flex on the server, that a typo in an escape surfaces as a C syntax error in generated code, and that the audience for “CGI, but you must know C” was never large.

Running TINCL

It cannot be done. The compiler was distributed only as tincl.zip from www.mines.edu/students/b/bolmstea/tincl/; that page stopped answering in 2004 and the Internet Archive holds captures of the page but never of the archive. There is no Docker image, no package, no mirror and no reimplementation.

Rebuilding it is not a hopeless project: templ.tin documents the sections, the escapes, the aliases, the runtime helpers (get_value, set_var and affirmative) and the config vocabulary in enough detail that a flex scanner emitting C could plausibly be written from it in a weekend. How long the original took its author is not recorded anywhere. But that would be a reconstruction from the manual, not the language as it shipped.

Why it matters

TINCL matters for three reasons, none of which is technical merit.

First, as a counterweight. Ben Olmstead is remembered for one artefact, a language engineered so that its first working program had to be found by a search algorithm rather than written. TINCL shows the same person, in the same month, on the same web server, doing careful, defensive, well-commented work on a tool for real use - bounds-checking form input, providing an offline test mode, warning the reader about echoing environment variables. Esoteric programming languages are usually made by people who understand ordinary ones very well, and here is the proof in the same directory listing.

Second, as an illustration of what survives. TINCL had a documentation file, a working demo, a public download and six years of continuous availability. What made it into 2026 is the documentation and the demo - text files a crawler could save - while the download, the only part that could not be regenerated, evaporated. The language’s presence in modern encyclopedia lists rests entirely on a stranger’s anonymous 2005 copy-paste of a beer song into a novelty catalogue, whose author and URL fields were left as “Anonymous” and “n/a” - the only attribution to survive the trip being the six lines of comment Olmstead had put at the top of the file himself.

Third, as a marker in the history of web templating. The idea that a page should be HTML on the outside and code on the inside was not obvious in 1998; it had to be arrived at repeatedly, by different people, in different languages, most of whom were not aware of each other. TINCL is one of those independent arrivals - smaller and shorter-lived than PHP or ASP, but recognisably the same idea, worked out by one student in one spring, and documented well enough that a quarter of a century later you can still read exactly what he meant.

Timeline

1998
7 and 15 April: on the page he titles 'Malbolge: Programming from Hell', signed "'98, Ben Olmstead/Public Domain", Olmstead stamps his two esoteric languages with the dates of their last update - 'Last update: 7 Apr 98/05:00 MTN' over the Dis archives and 'Last update: 15 Apr 98/11:35 MTN' over the Malbolge ones. TINCL is written in the same weeks, on the same student account, by the same person, for exactly the opposite purpose: getting ordinary work done
1998
18 April: the demonstration page beer.html is written. It introduces TINCL as 'The Idiotically Named CGI Language', 'a short language, based on C and generating C code (it was heavily influenced by Lex)', and says it is 'as of the current time of writing (18 Apr '98) still in Beta and may change as I learn more of what's actually helpful for CGI programming'. The page carries an HTML form that POSTs to /cgi-bin/cgiwrap/bolmstea/beer, a compiled TINCL program
1998
20 April: the date stamped on the TINCL project page as 'Last Update', beside the link to tincl.zip. Nothing in any later capture of that page changes - the same paragraph, the same beta warning, the same 1998 date is still being served in 2004. As far as the surviving record shows, active work on the language stopped within days of it becoming public
1999
13 October: the Internet Archive makes its first capture of the demo page, preserving both the description of the language and the live form. The CGI program behind the form is long gone, but the page is the earliest surviving evidence that TINCL was ever compiled and run
2000
22 January: the Archive captures 99bob.tin, the thirty-line TINCL source of the beer-song CGI - six lines of comment header and twenty-three lines of program - the only complete TINCL application that survives. On 17 August it takes its first capture of the project page itself
2000
10 July: Olmstead updates his Random Programming Languages List, which catalogues sixteen languages - Befunge, BrainF***, INTERCAL, Malbolge, SORTA, TRUE and ten others. TINCL is not on it, and by the list's own stated rule it could not be: 'In general, I do not plan to include Serious Programming Languages on this list.' By implication, the author counted his own CGI language among the serious ones
2002
12 June: the Archive first captures templ.tin, the 306-line annotated template that is the language's entire documentation - an executable TINCL program whose comments describe every section, escape and alias in the language. The file is byte-identical in all eight captures taken between 2002 and February 2004, so no version of it later than 1998 is known
2004
6 May: the TINCL directory starts returning 404. The parent directory www.mines.edu/students/b/bolmstea/ answers for the last time on 5 April and is returning 404 by 3 June, taking tincl.zip - the only copy of the compiler ever published - with it. Everything that survives about the language survives because a crawler happened to save a text file
2005
20 April: an anonymous submitter posts the beer-song program to 99-bottles-of-beer.net, where it becomes entry 452 in the 'real language' category, dated 04/20/05, with the author and e-mail fields both filled in as Anonymous and the URL field as n/a. That entry - on a site whose masthead advertised 'one program in 878 variations' when the page was first archived in January 2006 - is how the name reached the language catalogues. The catalogue's own metadata carries no attribution; the pasted source still does, because Olmstead's comment header names him and the year and links to the demo page
2026
99-bottles-of-beer.net stops resolving - the domain still has a mail record but no address record - so the catalogue entry has to be read from an archived copy too. The TINCL program in it and the two files on the Archive's copy of a 1998 student web page are, as far as can be determined, the complete surviving record of the language

Notable Uses & Legacy

99 Bottles of Beer CGI at the Colorado School of Mines

The only TINCL program known to have been deployed. A thirty-line source file, 99bob.tin - twenty-three lines of program under a six-line comment header - compiled to a CGI executable served through cgiwrap on the school's student web server, which read a form field named beer and printed that many verses. Its own demo page advertises bounds of 0 to 200 verses while the source passes 0 and 1000 to set_var - a discrepancy preserved for twenty-eight years because both files were captured

templ.tin, the language's documentation

TINCL's reference manual is a TINCL program. The 306-line templ.tin walks through every section and escape in the language inside %: ... :% comments, while simultaneously being a compilable page that greets the reader, prints a scaled number, echoes a form field and dumps PATH_INFO. It is both the specification and the largest surviving example

99-bottles-of-beer.net entry 452

Not a use so much as the reason anyone still has the name. The anonymous 2005 submission appears to be the only copy of a TINCL program to have lived outside the Internet Archive, and is the source of the language's appearance in modern encyclopedia lists. Its author, e-mail and URL fields read Anonymous, Anonymous and n/a - though the pasted source retains Olmstead's own comment header, which is where the name and the 1998 date can still be read

Language Influence

Influenced By

C Lex Flex HTML

Running Today

Run examples using the official Docker image:

docker pull
Last updated: