A historical DailyWTF moment

Today, in work, we wound up discussing this classic DailyWTF.com article — “Remember, the enterprisocity of an application is directly proportionate to the number of constants defined”:

public class SqlWords
  public const string SELECT = " SELECT ";
  public const string TOP = " TOP ";
  public const string DISTINCT = " DISTINCT ";
  /* etc. */

public class SqlQueries
  public const string SELECT_ACTIVE_PRODCUTS =
    SqlWords.SELECT +
    SqlWords.STAR +
    SqlWords.FROM +
    SqlTables.PRODUCTS +
    SqlWords.WHERE +
    SqlWords.EQUALS +
  /* etc. */

This made me recall the legendary source code for the original Bourne shell, in Version 7 Unix. As this article notes:

Steve Bourne, at Bell Labs, worked on his version of shell starting from 1974 and this shell was released in 1978 as Bourne shell. Steve previously was involved with the development of Algol-68 compiler and he transferred general approach and some syntax sugar to his new project.

“Some syntax sugar” is an understatement. Here’s an example, from cmd.c:

LOCAL REGPTR    syncase(esym)
        REG INT esym;
        IF wdval==esym
        THEN    return(0);
        ELSE    REG REGPTR      r=getstak(REGTYPE);
                LOOP wdarg->argnxt=r->regptr;
                     IF wdval ORF ( word()!=')' ANDF wdval!='|' )
                     THEN synbad();
                     IF wdval=='|'
                     THEN word();
                     ELSE break;
                IF wdval==ECSYM
                THEN    r->regnxt=syncase(esym);
                ELSE    chksym(esym);

Here are the #define macros Bourne used to “Algolify” the C compiler, in mac.h:

 *      UNIX shell
 *      S. R. Bourne
 *      Bell Telephone Laboratories

#define LOCAL   static
#define PROC    extern
#define TYPE    typedef
#define STRUCT  TYPE struct
#define UNION   TYPE union
#define REG     register

#define IF      if(
#define THEN    ){
#define ELSE    } else {
#define ELIF    } else if (
#define FI      ;}

#define BEGIN   {
#define END     }
#define SWITCH  switch(
#define IN      ){
#define ENDSW   }
#define FOR     for(
#define WHILE   while(
#define DO      ){
#define OD      ;}
#define REP     do{
#define PER     }while(
#define DONE    );
#define LOOP    for(;;){
#define POOL    }

#define SKIP    ;
#define DIV     /
#define REM     %
#define NEQ     ^
#define ANDF    &&
#define ORF     ||

#define TRUE    (-1)
#define FALSE   0
#define LOBYTE  0377
#define STRIP   0177
#define QUOTE   0200

#define EOF     0
#define NL      '\n'
#define SP      ' '
#define LQ      '`'
#define RQ      '\''
#define MINUS   '-'
#define COLON   ':'

#define MAX(a,b)        ((a)>(b)?(a):(b))

Having said all that, the Bourne shell was an awesome achievement; many of the coding constructs we still use in modern Bash scripts, 30 years later, are identical to the original design.

This entry was posted in Uncategorized and tagged , , , , , , , , , , , , . Bookmark the permalink. Both comments and trackbacks are currently closed.


  1. Posted February 14, 2008 at 19:47 | Permalink

    As well as the surface WTF, there was also its interesting approach to memory management. The Bourne shell avoided using libc so that it could fit into the space available on the PDP11, so it could not use malloc(). For efficiency, it didn’t bother explicitly checking for out of memory conditions. Instead, it trapped SIGSEGV, and called sbrk() in the signal handler. This had a habit of breaking on other architectures (especially the 68000) so many workstation vendors had to redo this part of the shell.

  2. nishad
    Posted February 14, 2008 at 21:08 | Permalink

    Dudes, let us not be defending fucking sh. Sh is and always was an abomination. Sh is like a fourteen-year-old saying, “I bet I can write a language!” Say good fucking riddance to sh!

  3. Nix
    Posted February 15, 2008 at 00:28 | Permalink

    When I first read the source for the original Bourne shell, it was a revelation. This is what those weird syntactic tricks were originally meant for! `if’ was an external command! Flow control constructs were external, and worked by moving the file pointer shared with the parent shell!

    All these nifty features Unix hardly ever uses these days (like shared file pointers other than the first three) were actually getting used.

    In a sense Unix suffered, just like all systems do, when it stopped being principally hacked by a small group with a shared vision. That vision is somewhat strange to those of us who grew up with more modern Unixes, but it’s still strangely compelling.

  4. Posted February 15, 2008 at 12:15 | Permalink

    I think Nix is confusing the Version 6 shell with the Bourne shell. The control commands are built-in to the Bourne shell and the PWB shell, but not the V6 shell. See http://www.in-ulm.de/~mascheck/bourne/v6/ and http://www.in-ulm.de/~mascheck/bourne/PWB/ and http://www.in-ulm.de/~mascheck/bourne/v7/ and the big switch in the middle of cmd.c with cases like IFSYM, FORSYM, etc.

  5. Posted February 15, 2008 at 21:20 | Permalink

    Russ Cox wrote a follow-up here, featuring an interesting factoid — it seems ‘the Bourne shell code, along with the 4.2BSD finger implementation, was the impetus for the International Obfuscated C Code Contest.’ ha!

  6. Nix
    Posted February 15, 2008 at 22:07 | Permalink

    Er, oops, yep, Tony’s right. Sorry, I was looking at the source for the Bourne shell and the V6 shell on the same day and they must have got sort of blurred.

  7. pertti
    Posted February 16, 2008 at 10:16 | Permalink

    C=64 generator is still bugging. It doesn’t show the source code, but, instead, tries to run it without any input.

  8. Posted February 18, 2008 at 11:42 | Permalink

    pertti: feel free to mail me at jm at jmason.org with more details and an example. if you mean the c=64 image converter, it seems to be working ok for me…

  9. fool
    Posted June 8, 2011 at 05:13 | Permalink

    nishad is a noob. Nix has it right.

    “Cathedral” gives way to a vast “bazaar” of noobs, and you get what we have today: same old thing. And young people ignorant of history, dumb enough to believe things are “new”. No new innovations in OS for decades. Same OS all around, relabeled, rebranded. Same utilities reinvented over and over and over again, in umpteen languages.

    UNIX and BSD were developed by small groups, unfettered by masses of incapable idiots submitting stupid patches or requesting endless features. The masses simply didn’t exist like they do today.

    Today we call such idiots developers and admins.

    Try and boot your system without /bin/sh and watch all the things that break. You’re still using 1970’s technology. I just explained why.

  10. Nix
    Posted June 8, 2011 at 11:05 | Permalink

    I don’t think I ever mentioned incapable idiots. I suspect the ‘small group with a shared vision’ stopped about the time the BSD people got involved, and while they perpetrated some abominations while they got up to speed (part of BSD sockets for instance), they did some great stuff too (fixing signal handling so it didn’t drive you insane, for instance). They just didn’t have the same design vision as the core Unix team, because so much of that resided inside one or a few people’s heads. (They had a different one.)

    It is the same with every system as it grows to maturity. No idiots are required: just groups of bright people who are separated and who don’t spend all their time talking to each other, so cannot live in each others’ heads.