Navel

    # Bottles of beer in Navel
      Greg Michaelson
      greg@cee.hw.ac.uk #
    
    def itos n = if n=0 then "0" else itos1 "" n;
    def itos1 l n = if n=0 then l else itos1 (char (n%10+'0')):l n/10;
    def verse n = {(itos n) " bottle(s) of beer on the wall\n"
                   (itos n) " bottle(s) of beer on the wall\n"
                   "Take one down and pass it around\n"
                   (itos n-1) " bottle(s) of beer on the wall\n"};
    def verses n = 
     if n=0
     then ()
     else
      let v = write (?(verse n))
      in verses n-1;
    

    Postscript

    Postscript has two significant "modes." One is interactive, the other is document printing/typesetting. Belows are samples of both kinds of code.
    % How to do 99 Bottles of Beer in Postscript.
    % This doesn't go out to the printer. You'd need to hook a serial port
    % to your LaserPrinter or Postscript typesetter
    /beer {
      /bottles 7 string def
      99 -1 1
      { dup bottles cvs print ( bottles of beer on the wall, )
      bottles print (bottles of beer.  Take one down, pass it around, )
      1 sub bottles cvs print ( bottles of beer on the wall. )
      } for 
      (No more bottles of beer on the wall, no more bottles of beer.  )
      (Go to the store and buy some more... 99 bottles of beer) } def
    

    Pascal

    (* Pascal version of 99 Bottles of beer *)
    program BottlesOfBeers(input, output);
    var
      bottles: integer;
    begin
      bottles := 99;
      repeat
        WriteLn(bottles, ' bottles of beer on the wall, ',
                bottles, ' bottles of beer.');
        Write('Take one down, pass it around, ');
        bottles := bottles-1;
        WriteLn(bottles, ' bottles of beer on the wall.');
      until (bottles = 1);
      WriteLn('1 bottle of beer on the wall, one bottle of beer.');
      WriteLn('Take one down, pass it around,'
              ' no more bottles of beer on the wall')
    end.
    
    ---- Printable version ----
         %!PS
         
         % The 99 bottles of beer song in PostScript. This file
         % can be sent to a PostScript printer (it'll be about
         % eight pages or so...)
         
         % Stuart Morris
         
         % ------------- Variables & Procedures ------------
         
         /LM 72 def           % left margin
         /ypos 720 def        % initial top position
         /BM 72 def           % bottom margin
         /lineheight 18 def   % height of a line of text
         
         % starts a new line
         
         /crlf
         {
           ypos lineheight sub
           /ypos exch def
           LM ypos moveto
             
         } def
         
         % starts a new page if current one is full
         
         /newpage? 
         {
           ypos BM lt
           {
             showpage
             /ypos 720 def
             LM ypos moveto
         
           } if
         
         } def
         
         % returns the correct syntax of the bottle
         % string ("bottle" if one, "bottles" otherwise)
         
         /bottlestring  % stack: number of bottles
         {
           1 eq
           {
             ( bottle of beer)
           }
           {
             ( bottles of beer)
         
           } ifelse
         
         } def
         
         % ------------- Main Program ----------------
         
         LM ypos moveto
         
         /Times-Roman findfont 
           lineheight 2 sub scalefont 
           setfont
         
         99 -1 1
         {
           /numbottles 2 string def
           dup numbottles cvs show
           
           dup bottlestring show ( on the wall, ) show
           numbottles show dup bottlestring show (,) show
           crlf
         
           (Take one down, pass it around, ) show
           1 sub dup numbottles cvs show
           
           bottlestring show ( on the wall.) show
           crlf crlf
           newpage?
         
         } for
         
         showpage
    

    REXX

    /* Rexx Version of the Bottles program */
    /* by Lee Stewart (ls@sweng.stortek.com) */
       Trace Off;
       Do Forever;
          Do i = 99 To 1 By -1;
             If i > 1 Then pl = 's';
                      Else pl = '';
             Say i 'bottle'pl 'of beer on the wall,' i 'bottle'pl 'of beer';
             Say 'Take one down, pass it around';
             End;
          Say 'No more bottles of beer on the wall, no more bottles of beer';
          Say 'Go to the store and buy some more';
          End;
    

    PL/I

    
    /* And here is the PL/I version: */
    
     BOTTLES: PROC OPTIONS(MAIN);
    
       DCL NUM_BOT FIXED DEC(3);
       DCL PHRASE1 CHAR(100) VAR;
       DCL PHRASE2 CHAR(100) VAR;
       DCL PHRASE3 CHAR(100) VAR;
    
       DO NUM_BOT = 100 TO 1 BY -1;
    
          PHRASE1 = NUM_BOT||' Bottles of Beer on the wall,';
          PHRASE2 = NUM_BOT||' Bottles of Beer';
          PHRASE3 = 'Take one down and pass it around';
          DISPLAY(PHRASE1||PHRASE2);
          DISPLAY(PHRASE3);
       END;
       PHRASE1 = 'No more Bottles of Beer on the wall, ';
       PHRASE2 = 'No more Bottles of Beer';
       PHRASE3 = 'Go to the store and buy some more';
       DISPLAY(PHRASE1||PHRASE2);
       DISPLAY(PHRASE3);
     END BOTTLES;
    
    

    RPG/400

    
    
         H*
         H* RPG/400 VERSION OF THE BOTTLES PROGRAM *
         H*
         FSCREEN  O   F      80            WORKSTN
         C                     MOVE 100       X       30
         C           X         DOWGE0
         C                     EXCPT
         C                     SUB  1         X
         C                     END
         C                     SETON                     LR
         OSCREEN  E
         O                         X          3
         O                                   26 'BOTTLES OF BEER ON THE'
         O                                   31 'WALL,'
         O                         X         36
         O                                   53 'BOTTLES OF BEER'
         O        E
         O                                   22 'TAKE ONE DOWN AND PASS'
         O                                   32 'IT AROUND'
    
    

    Python

    #!/usr/local/bin/python
    #   python version of 99 bottles of beer, compact edition
    #   by Fredrik Lundh (fredrik_lundh@ivab.se)
    
    def bottle(n):
        try:
            return { 0: "no more bottles",
                     1: "1 bottle"} [n] + " of beer"
        except KeyError: return "%d bottles of beer" % n
    
    for i in range(99, 0, -1):
        b1, b0 = bottle(i), bottle(i-1)
        print "%(b1)s on the wall, %(b1)s,\n"\
    	  "take one down, pass it around,\n"\
    	  "%(b0)s on the wall." % locals()
    

    Perl

    The second one is intended to be the author's .sig for his email.
    #! /usr/bin/perl
    # Jim Menard     jimm@{bbn,io}.com     (617) 873-4326    http://www.io.com/~jimm/
    $nBottles = $ARGV[0];
    $nBottles = 100 if $nBottles eq '' || $nBottles < 0;
    
    foreach (reverse(1 .. $nBottles)) {
        $s = ($_ == 1) ? "" : "s";
        $oneLessS = ($_ == 2) ? "" : "s";
        print "\n$_ bottle$s of beer on the wall,\n";
        print "$_ bottle$s of beer,\n";
        print "Take one down, pass it around,\n";
        print $_ - 1, " bottle$oneLessS of beer on the wall\n";
    }
    print "\n*burp*\n";
    
    Signature version
    #!/usr/bin/perl -iake_one_down_pass_it_around:_bottles_of_beer:_on_the_wall:99
    for(($t,$a,$b,$i)=split/:/,$^I;$i;print){$_="-$i$a$b,-$i$a,-T$t,-".--$i."$a$b
    ";s/(-1_.*?e)s/$1/g;y/_-/ \n/}#     by Randolph Chung and Joey Hess
    
    

    Prolog

    /*
      99 bottles of beer in Prolog
    
      Rob van de Pol
      R.vandePol@voeding.tno.nl
      TNO Nutrition and Food Research Institute
      The Netherlands
    */
    
    domains
      count = integer
    
    predicates
      bottles(count)
    
    clauses
      bottles(1) :-
        write ("1 bottle of beer on the wall, 1 bottle of beer,\n"),
        write ("Take one down, and pass it around,\n"),
        write ("Now they are alle gone.").
      bottles(X) :-
        write ( X , " bottles of beer on the wall, " ,
                X , " bottles of beer,\n"),
        write ("Take one down, and pass it around,\n"),
        X1 = X - 1,
        write ( X1 , " bottles of beer on the wall.\n",
        bottles(X1).
    
    goal
      bottles(99)
    
    

    NROFF

    nroff is a text formatting macro language common under UNIX
    .\" Tim Goodwin <tim@pipex.net>
    .nr BO 99
    .de BP
    .if \\n(BO=0 No more
    .if !\\n(BO=0 \\n(BO
    .if \\n(BO=1 bottle
    .if !\\n(BO=1 bottles
    of beer
    ..
    .de WP
    .BP
    on the wall
    ..
    .de BE
    .WP
    .br
    .BP
    .br
    Take one down, pass it around
    .br
    .nr BO \\n(BO-1
    .WP
    .sp
    .if \\n(BO>0 .BE
    ..
    .BE
    
    

    Prograph

    Click for more info.


    Oberon

    MODULE BottlesOfBeers; (* Andrejs Jansons 27.10.95 *)
    
          IMPORT Out;
    
          PROCEDURE Start*;
               VAR
                    bottles: INTEGER;
               BEGIN
                    bottles := 99;
    
                    REPEAT
                        Out.Int(bottles, 2);
                        Out.String(" bottles of beer on the wall, ");
                        Out.Int(bottles, 2);
                        Out.String(" bottles of beer.");
                        Out.Ln;
                        Out.String("Take one down, pass it around, ");
    
                        DEC(bottles);
    
                        Out.Int(bottles, 2);
                        Out.String(" bottles of beer on the wall.");
                        Out.Ln
                    UNTIL bottles = 1;
    
                    Out.String("1 bottle of beer on the wall, one bottle of beer.");
                    Out.Ln;
                    Out.String("Take one down, pass it around,");
                    Out.String(" no more bottles of beer on the wall");
                    Out.Ln
               END Start;
    
    END BottlesOfBeers.
    

    This is a noteworty Object Oriented version in Oberon:

    MODULE BeerSong;
    
    (* An object-oriented beer song in Oberon-2              *)
    (* Contributed by Michael Griebling (mgriebling@bix.com) *)
    
    IMPORT O:=Out;
    
    TYPE
      WallObject* = RECORD beer-: SHORTINT END;
    
    VAR
      BeerWall : WallObject;
      
      PROCEDURE (VAR wall: WallObject) LineEmUp*;
      BEGIN wall.beer := 99
      END LineEmUp;
      
      PROCEDURE (VAR wall: WallObject) PassOneAround*;
      BEGIN DEC(wall.beer)
      END PassOneAround;
      
      PROCEDURE (VAR wall: WallObject) HasMoreBeer* () : BOOLEAN;
      BEGIN RETURN wall.beer > 0
      END HasMoreBeer;
      
      PROCEDURE SingOf(beer: SHORTINT);
      BEGIN 
        IF beer = 0 THEN O.String("No more") ELSE O.Int(beer, 1) END; 
        O.String(" bottle"); IF beer#1 THEN O.Char("s") END; O.String(" of beer")
      END SingOf;
         
      PROCEDURE (VAR wall: WallObject) SingVerse*;    
      BEGIN 
        SingOf(wall.beer); O.String(" on the wall, "); SingOf(wall.beer); O.Ln;
        O.String("Take one down and pass it around,"); O.Ln;
        SingOf(wall.beer-1); O.String(" on the wall."); O.Ln; O.Ln
      END SingVerse;
    
    BEGIN
      BeerWall.LineEmUp;
      WHILE BeerWall.HasMoreBeer() DO BeerWall.SingVerse; BeerWall.PassOneAround END
    END BeerSong.
    

    Pop

    define beer(n);
    
        define :inline PLURAL(N);
            (N==1 and nullstring or "s")
        enddefine;
    
        lvars i;
        for i from n by -1 to 1 do;
            nl(1);
            nprintf(PLURAL(i), i, '%P bottle%P of beer on the wall.');
            nprintf(PLURAL(i), i, '%P bottle%P of beer!');
            nprintf(i==1 and "it" or "one", 'Take %P down, pass it around.');
            if i>1 then
                nprintf(PLURAL(i-1), i-1, '%P more bottle%S of beer on the wall.');
            else
                npr('No more bottles of beer on the wall.');
            endif;
        endfor;
    
    enddefine;
    
    beer(100);
    

    Progress

    Progress is a database system that is used to create enterprise database solutions.
    /* Progress 4GL version of 99 Bottles of Beer.
     * programmer: Rich Uchytil  rich@cray.com
     * 10/30/95
     */
    
    def var i as int no-undo format "z9".
    
    do i = 99 to 1 by -1:
      disp i "bottles of beer on the wall," skip
           i @ x as int format "z9" "bottles of beer" skip
           "Take one down and pass it around," skip
           i - 1 format "z9" "bottles of beer on the wall."
      with no-labels no-box no-attr 1 down.
      pause 1 no-message.  /* needed otherwise it would run too fast */
    end.
    
    

    Pilot

    R: PILOT version of 99 Bottles of Beer
     : hacked by Akira KIDA, <SDI00379@niftyserve.or.jp>
    
    C:BOTTLES=99
    
    U:*BEERS
    *LOOP
    T:$T of beer on the wall, $T.
    T:Take one down, pass it around.
    C:BOTTLES=BOTTLES-1
    U:*BEERS
    T:$T on the wall.
    T:
    J(BOTTLES>0):*LOOP
    E:
    
    *BEERS
    C(BOTTLES=0):$T=No more bottles
    C(BOTTLES=1):$T=1 bottle
    C(BOTTLES>1):$T=#BOTTLES bottles
    E:
    

    PV-Wave

    PV-Wave, also known as IDL, is a language designed for visual data analysis.
    ;
    ; 99 bottles of beer
    ; V1
    ; Author: George M.Sigut  (sigut@bs.id.ethz.ch)
    ;
    ; yes, I DO know the second loop could be unrolled
    ;
    ninety_nine = 99
    texta = ' bottles of beer'
    textb = ' bottle of beer'
    textf = ' no more'
    ;
    number1 = strcompress(string(ninety_nine))
    text1   = texta
    number2 = strcompress(string(ninety_nine-1))
    text2   = texta
    for i=ninety_nine,3,-1 do begin &$
      print,number1,text1,' on the wall' &$
      print,number1,text1 &$
      print,' you take one down & pass it around' &$
      print,number2,text2 &$
      print &$
      number1 = number2 &$
      number2 = strcompress(string(i-2)) &$
    endfor
    ;
    text1 = texta
    text2 = textb
    for i=2,1,-1 do begin &$
      print,number1,text1,' on the wall' &$
      print,number1,text1 &$
      print,' you take one down & pass it around' &$
      print,number2,text2 &$
      print &$
      number1 = number2 &$
      text1   = textb &$
      number2 = textf &$
      text2   = texta &$
    endfor
    ;
    
    ;  ---------- Variant more in keeping with the language's style -----
    
    ;
    ; 99 bottles of beer
    ; V2
    ;
    ninety_nine = 99
    texta = ' bottles of beer'
    textb = ' bottle of beer'
    textf = ' no more'
    ;
    full_text = strarr(1,4,ninety_nine)
    ;
    full_text(0,1,*) = strcompress(string(ninety_nine-indgen(ninety_nine))) + texta
    full_text(0,0,*) = full_text(0,1,*) + ' on the wall'
    full_text(0,2,*) = ' you take one down & pass it around'
    full_text(0,3,0:ninety_nine-2)=full_text(0,1,1:ninety_nine-1)
    ;
    full_text(0,3,ninety_nine-2) = strcompress(1)+textb
    full_text(0,0,ninety_nine-1) = full_text(0,3,ninety_nine-2)+' on the wall'
    full_text(0,1,ninety_nine-1) = full_text(0,3,ninety_nine-2)
    full_text(0,3,ninety_nine-1) = textf+texta
    ;
    print,full_text
    ;
    
    

    Natural

    * PGM-ID: BEER
    * AUTHOR: CHRIS BEDNARA
    * COMMENT: NATURAL '99 BOTTLES OF BEER ON THE WALL' CODE
    *
    *-------------------------------------------------------
    DEFINE DATA
    	LOCAL
    	  01 #BOTTLES  (I2)
    END-DEFINE
    *
    FOR #BOTTLES 99 TO 2 STEP -1
    	IF #BOTTLES < 98
    	  WRITE #BOTTLES ' BOTTLES OF BEER ON THE WALL'
    	  WRITE ' '
    	END-IF
    *	
    	WRITE #BOTTLES ' BOTTLES OF BEER ON THE WALL'
    	WRITE #BOTTLES ' BOTTLES OF BEER'
    	WRITE 'TAKE ONE DOWN, PASS IT AROUND'
    END-FOR
    *
    WRITE '1 BOTTLE OF BEER ON THE WALL'
    WRITE ' '
    WRITE '1 BOTTLE OF BEER ON THE WALL'
    WRITE '1 BOTTLE OF BEER'
    WRITE 'TAKE IT DOWN, PASS IT AROUND'
    WRITE 'NO MORE BOTTLES OF BEER ON THE WALL'
    WRITE ' '
    WRITE 'NO MORE BOTTLES OF BEER ON THE WALL'
    WRITE 'NO MORE BOTTLES OF BEER'
    WRITE 'GO TO THE STORE AND BUY SOME MORE'
    WRITE '99 BOTTLES OF BEER'
    END
    WRITE 'TAKE ONE DOWN, PASS IT AROUND'
    

    NIAL

    Nial stands for Nested Interactive Array Language, which incorporates ideas from APL2, Lisp, FP and structured programming. Q'Nial is a Nial programming system developed at Queen's University in Canada Click here for more info.
    % Nial (Q'Nial) version of 99 bottles of beer
    %;
    % loaddef "beer;
    % beer 99;
    %;
    % Hacked by Akira KIDA, SDI00379@niftyserve.or.jp;
    
    bottles IS OPERATION A {
    	IF A = 0 THEN
    		'No more bottles'
    	ELSEIF A = 1 THEN
    		link (sketch A) ' bottle'
    	ELSE
    		link (sketch A) ' bottles'
    	ENDIF
    }
    
    beer IS OPERATION A {
    	FOR x WITH reverse count A DO
    		write link (bottles x) ' of beer on the wall, '
    			(bottles x) '.';
    		write 'Take one down, pass it around.';
    		write link (bottles (x - 1)) ' of beer on the wall.';
    		write '';
    	ENDFOR;
    }
    
    

    OPL

    OPL (Organiser Programming Language) is the language used by Psion palmtops.
    REM ********************************************************************
    REM *                        99 Bottles of Beer                        *
    REM *                                                                  *
    REM * A portable version for those who need this vital application     *
    REM * with them at all times. The following is written in Psion OPL,   *
    REM * the language used in the popular Series 3 and Series 3a palmtops *
    REM * (and other previous Psion products).                             *
    REM *                                                                  *
    REM * by Dave Wilson, dawilson@brooktree.com                           *
    REM *                                                                  *
    REM ********************************************************************
    
    PROC Main:
       LOCAL bottles%
       LOCAL bottle$(10)
       CLS
       bottles%=99
       bottle$=" bottles"
       PRINT "99 Bottles of Beer"
       PRINT
       WHILE(bottles% > 0)
          PRINT bottles%;bottle$;" of beer on the wall,"
          PRINT bottles%;bottle$;" of beer on the wall."
          PRINT "Take one down and pass it around,"
          bottles%=bottles%-1
          IF(bottles% = 1)
             bottle$=" bottle"
          ENDIF
          IF(bottles% <> 0)
             PRINT "There'll be ";bottles%;bottles$;" of beer on the wall."
          ELSE
             PRINT "There'll be no bottles of beer on the wall."
          ENDIF
          PRINT
       ENDWH
       PAUSE 0
    ENDP
    
    

    NEWLIB

    NEWLIB is a programming aid that operates as a command processor in the Time Sharing Option (TSO) environment. (Mostly based on PL/I, therefore the similarity.) It is used at DESY/Hamburg and KEK/Tsukuba.
    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    $   21/02/96 602211216  MEMBER NAME  <<EDTCL  (SPECTRUM)    CLIST   
    $ NEWLIB VERSION OF 99 BOTTLES OF BEER                              
    $ R.P.HOFMANN F15RPH@DSYIBM.DESY.DE                                 
    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    STORE                                                                
    ESC := '%'                                                           
    DO N0 = 1 TO 99                                                      
      N1 := 100-%N0                                                      
      IF N1 > 1 THEN                                                     
        IF N0 > 1  SHOW N1||' BOTTLES OF BEER ON THE WALL'               
        SHOW N1||' BOTTLES OF BEER ON THE WALL'                          
        SHOW N1||' BOTTLES OF BEER'                                      
      ELSE                                                               
        SHOW '1 BOTTLE OF BEER ON THE WALL'                              
        SHOW '1 BOTTLE OF BEER ON THE WALL'                              
        SHOW '1 BOTTLE OF BEER'                                          
      ENDIF                                                              
      SHOW 'TAKE 1 DOWN AND PASS IT ALL AROUND'                          
    END                                                                  
    SHOW '0 BOTTLES OF BEER ON THE WALL'                                 
    RESTORE                                                              
    

    Posix

    Posix is yet another U**x shell.
    #!/bin/sh
    # POSIX shell version of 99 Bottles
    # Dave Plonka - plonka@carroll1.cc.edu
    
    typeset -i n=99
    typeset bottles=bottles
    typeset no
    
    while let n
    do
       echo "${n?} ${bottles?} of beer on the wall,"
       echo "${n?} ${bottles?} of beer,"
       echo "take one down, pass it around,"
       n=n-1
       case ${n?} in
       0)
          no=no
          bottles=${bottles%s}s
          ;;
       1)
          bottles=${bottles%s}
          ;;
       esac
       echo "${no:-${n}} ${bottles?} of beer on the wall."
       echo
    done
    
    exit
    

    Quick Basic

    '99 Bottles of Beer on the Wall
    'Patrick Fleming   http://chem-www.mps.ohio-state.edu/~pfleming/
    
    CLS
    
    n = 100
    DO UNTIL n = 1
         n = n - 1
         PRINT n; "bottle";
         IF n <> 1 THEN PRINT "s";
         PRINT " of beer on the wall . . ."
         PRINT n; "bottle";
         IF n <> 1 THEN PRINT "s";
         PRINT " of beer!"
         PRINT "Take one down, pass it around . . ."
         PRINT n - 1; "bottle";
         IF n - 1 <> 1 THEN PRINT "s";
         PRINT " of beer on the wall!"
         PRINT
    LOOP
    
    END
    

    Rapid

    Rapid is a a prototyping language developed by Emultek. There were several screen shots associated with this, but this one is the most obviously the programming language part of it.


    PAL

    PAL is Prodigy Application Language. I listed this one as unique simply because you don't often get a peek at a truly proprietary language. This can't be compiled by anyone other than Prodigy employees.
    /*=========================================================================*/
    /*                                                                         */        
    /*                       PRODIGY SERVICES COMPANY                          */
    /*                                                                         */
    /*  Author:        Kim Moser (kmoser@prodigy.com)                          */
    /*  Application:   99 Bottles of Beer on the Wall                          */
    /*  Program Name:  XXXXBEER.PGM                                            */
    /*  Program Type:  Element preprocessor                                    */
    /*  File Name:     xxxxbeer.s                                              */
    /*  Version:       0.0                                                     */
    /*  Contents:      PAL                                                     */                                 
    /*=========================================================================*/
    /* PROGRAM DESCRIPTION: This function fills PEVs 10-110 with 99 verses     */
    /*  of the "99 Bottles of Beer on the Wall" song (one verse per PEV),      */
    /*  appends these verses to the file whose name was given in P1 (the       */
    /*  first parameter), then opens a window warning you to buy more beer.    */
    /*                                                                         */
    /*  The program is smart enough to pluralize "beer" when refering to       */
    /*  more than one, and says "no" when refering to 0 bottles.               */
    /*                                                                         */
    /*  The output is as follows:                                              */
    /*  99 bottles of beer on the wall, 99 bottles of beer.                    */
    /*  Take one down, pass it around, 98 bottles of beer on the wall.         */
    /*  ...                                                                    */
    /*  1 bottle of beer on the wall, 1 bottle of beer.                        */
    /*  Take one down, pass it around, no bottles of beer on the wall.         */
    /*  Time to buy more beer!                                                 */
    /*                                                                         */
    /*-------------------------------------------------------------------------*/
    /* MAINTENANCE LOG:                                                        */
    /*  PROGRAMMER        DATE        DESCRIPTION OF CHANGE                    */
    /*   Kim Moser      23-Oct-96      Creation.                               */
    /*=========================================================================*/
    
    #define DISPLAY_PEV  10
    
    #define Q_CTX_NAME "beer_ctx"
    context beer_ctx {
        var
        ctx_fp,                /* File pointer: where to write the song */
        ctx_bottle,            /* " bottle" */
        ctx_bottle_of_beer,    /* " bottle of beer" */
        ctx_bottles_of_beer,   /* " bottles of beer" */
        ctx_on_the_wall;       /* " on the wall" */
    }
    
    #define DEFAULT_FNAME    "beer.txt"
    
    "XXXXBEERPGM\00\0C"(var fname)
    {
        var i;
        var of_beer;
        var sentence;
    
        if (open_one_context(Q_CTX_NAME) > 1) {
            /* Error opening context */
            return (-1);
        }
    
        /* Initialize context: */
        /* Reduce string overhead by putting these phrases in variables: */
        of_beer = " of beer";
        ctx_bottle = " bottle";
        ctx_bottle_of_beer = string(ctx_bottle, of_beer);
        ctx_bottles_of_beer = string(ctx_bottle, "s", of_beer);
        ctx_on_the_wall = " on the wall";
    
        if (fname ==$ "") {
            /* No filename specified */
            fname = DEFAULT_FNAME;
        }
    
        if (open(fname, F_APPEND, ctx_fp) == 0) {
            for (i=99; i > 0; i-=1) {
                sentence = bottles_sentence(i);
    
                &0[DISPLAY_PEV + (100-i)] = sentence;
                write_line(ctx_fp, sentence);
            }
            write_line(ctx_fp, "Time to buy more beer!\n");
            close(ctx_fp);
        }
    
        close_all_contexts(Q_CTX_NAME);
    
        open_window("XXXXBEERWND\00\0E");  /* Warning: Time to buy more beer */
    }
    
    bottles_sentence(var n_bottles)
    {
        var bob1, bob2; /* " bottles of beer" or " bottle of beer" */
    
        bob1 = bob(n_bottles);
        bob2 = bob(n_bottles - 1);
    
        return (
            string(
                n_bottles,
                bob1,
                ctx_on_the_wall,
                ", ",
                n_bottles,
                bob1,
                ".\nTake one down, pass it around, ",
                (n_bottles-1 ? n_bottles-1 : "no"),
                bob2,
                ctx_on_the_wall,
                "."
            )
        );
    }
    
    bob(var n_bottles)
    {
        return (n_bottles==1 ? ctx_bottle_of_beer : ctx_bottles_of_beer);
    }
    

    PLEX

    PLEX (Programming Language for EXchanges) is a real-time language developed in 1970 by Ericsson to program telephony exchanges.
    ! The main program "99 bottles ..." programmed in PLEX  !
    ! Programmer Staale Andersen   etosta@eto.ericsson.se   !
    
    ! Comment: The need for an own parameterlist and a signal survey, !
    ! leads to the whole beer program beeing in 3 parts.              !
    
    
    
    DOCUMENT BEERPROGRAM;
    
    DECLARE;
              GLOBAL NSYMB COCA99 (#FFFF);
              GLOBAL STRING BEERS (7);
              STRING VARIABLE ONWALL1 31 DS;
              STRING VARIABLE ONWALL2 63 DS;
              STRING VARIABLE BOTTLES 31 DS;
              STRING VARIABLE TAKEDOWN 63 DS;
              VARIABLE CBEER 16 DS;
              VARIABLE CIOID 16 DS;
              VARIABLE TIOID 16;
              VARIABLE TSTARTPHASE 16;
              VARIABLE TSIGNALKEY 16;
              VARIABLE TBLOCKINFO 16;
    
    END DECLARE;
    PROGRAM BEERPROGRAM;
    PLEX;
    
              ENTER STTOR  WITH
                        +,                   
                        TSTARTPHASE,         
                        +,                   
                        +,                   
                        +,                   
                        +,                   
                        TSIGNALKEY;          
    
              TBLOCKINFO = #100;
     
              SEND STTORRY  WITH
                              TSIGNALKEY,    
                              TBLOCKINFO,    
                              5,             
                              255;           
     
                    EXIT;
      
              COMMAND BEERS TYPE COCA99,
                ID IS TIOID;
              CIOID = TIOID;
              ONWALL1 = " BOTTLES OF BEER ON A WALL, ";
              ONWALL2 = " BOTTLES OF BEER ON A WALL.";
              BOTTLES = " BOTTLES OF BEER";
              TAKEDOWN = "TAKE ONE DOWN AND PASS IT AROUND, ";
              ON CBEER FROM 99 DOWNTO 1 DO
                CASE CBEER IS
                WHEN 1 DO
                  BOTTLES = " BOTTLE OF BEER";
                  ONWALL1 = " BOTTLE OF BEER ON A WALL, ";
                  ONWALL2 = "NO MORE BOTTLES OF BEER ON A WALL.";
                WHEN 2 DO
                  ONWALL2 = " BOTTLE OF BEER ON A WALL.";
                OTHERWISE DO;
                ESAC;
                INSERT VALUE CBEER, ID IS CIOID,
                  FORMAT IS 5;
                INSERT STRING ONWALL1, ID IS CIOID;
                INSERT VALUE CBEER, ID IS CIOID,
                    FORMAT IS 5;
                INSERT STRING BOTTLES, ID IS CIOID;
                WRITE AFTER 1 NL, ID IS CIOID,
                  ABRANCH IS ERROR;
                
                INSERT STRING TAKEDOWN, ID IS CIOID;
                IF CBEER /= 1 THEN
                  INSERT VALUE (CBEER-1), ID IS CIOID,
                    FORMAT IS 5;
                FI;
                INSERT STRING ONWALL2, ID IS CIOID;
                WRITE AFTER 1 NL, ID IS CIOID,
                  ABRANCH IS ERROR;
                
              NO;
              
        ERROR)
              RELEASE DEVICE, ID IS CIOID,
                ABRANCH IS EXIT; 
        EXIT)
              EXIT;
    
    END PROGRAM;          
    
    DATA;
    
    END DATA;          
    
    *END;
    
    ID BEERPROGRAM TYPE DOCUMENT;
    CLA 19055;
    NUM CAA 100 99;
    REV A;
    DAT 96-12-12;
    DES ETO/TX/M/N STA;
    RES ETO/TX/M/N STA;
    APP ETO/TX/M/N TV;
    END ID;
    
    ! The source parameter list !
    
    DOCUMENT BEERSPARAM;
    
    BLOCK   BEER;
    TYPE     BTBEER;
    TYPEEXT  BTEXTBEER;
    
    USE     BEERPROGRAM;
    
    NSYMB     BTBEER = #8000;   
    NSYMB     BTEXTBEER= #4000;  
    
    STRING BEERS = "BEERS";
    NSYMB COCA99 = #0;
    
    
    END BLOCK;
    *END;
    ID BEERSPARAM TYPE DOCUMENT;
    CLA 19073;
    NUM CAA 100 99;
    REV A;
    DAT 96-12-13;
    DES ETO/TX/M/N STA;
    RES ETO/TX/M/N STA;
    APP ETO/TX/M/N TV;
    END ID;
    
    ! Signal Survey  !
    DOCUMENT BEERSURVEY;
    SIGNALSURVEY;
    USE BLOCK BEER;
    
    STTOR          ,  R     ,  723/15514 - APZ210                  ;
    STTORRY        ,  S     ,  724/15514 - APZ210                  ;
    
    END SIGNALSURVEY;
    *END;
    ID BEERSURVEY TYPE DOCUMENT;
    CLA 15514;
    NUM CAA 100 99;
    REV A;
    DAT 96-12-13;
    DES ETO/TX/M/N STA;
    RES ETO/TX/M/N STA;
    APP ETO/ETOTX/M/N TV;
    END ID;
    

    OBJ

    OBJ is an algebraic specification language.
    *** OBJ version of 99 bottles of beer
    *** programmer: Grigore Rosu  grosu@cs.ucsd.edu
    *** creator of OBJ language: Joseph Goguen
    
    obj STRING is sort String .
      ops We like some beer on the wall.  : -> String .
      ops Take one bottle of wall down ,  : -> String .
      ops And pass it arround the beer.   : -> String .
      ops Does anybody want bottles more? : -> String .
    endo
    
    obj LIST[X :: TRIV] is
      sort List .
      subsort Elt < List .
      op __ : List List -> List [assoc] .
    endo
    
    make CHUG is LIST [ STRING + NAT ] endm
    
    obj BEER is protecting CHUG .
      subsort Nat < String .
      ops beers puke : Nat -> List .
      op bottle? : Nat -> String .
      var N : Nat .
      eq beers(0) = Does anybody want some more? .
      cq beers(N) = puke(N) beers(p N) if N > 0 .
      eq puke(N) = N bottle?(N) of beer on the wall , N bottle?(N) of beer.
       Take one down , pass it arround , (p N) bottle?(p N) of beer on the wall. .
      cq bottle?(N) = bottle  if N == 1 .
      cq bottle?(N) = bottles if N =/= 1 .
    endo
    
    red beers(99) .
    
    

    POV-Ray

    POV-Ray is a ray-tracing program.
    // povray 3 file for the 99 bottles of beer ...
    
    #declare S1 = " bottles"
    #declare L1 = " of beer on the wall,\n"
    #declare L2 = " of beer.\n"
    #declare L3 = "Take one down and pass it around,\n"
    #declare L4 = " of beer on the wall.\n\n"
    
    #declare Beer = 99
    #declare S2 = concat(str(Beer,0,0),S1)
    
    #render "\n"
    
    #while (Beer > 0)
      #render concat(S2,L1)
      #render concat(S2,L2)
      #render L3
    
      #declare Beer = Beer - 1
    
      #if (Beer = 1)
        #declare S2 = "1 bottle"
      #else
        #if (Beer = 0)
          #declare S2 = "No more bottles"
        #else
          #declare S2 = concat(str(Beer,0,0),S1)
        #end
      #end
    
      #render concat(S2,L4)
    #end
    
    sphere { 0, 1 pigment { colour rgb <1,0,0> } }
    
    light_source { x*2, colour rgb 1 }
    
    camera {
      perspective
      location x*2
      look_at 0
    }
    

    Orthogonal

    ; 99 Bottles of Beer on the Wall
    ;    for Orthogonal
    ;        written by Brian Raiter 5/96
    
    :set bX = 7
    :set bY = 20
    
    [0,0]
    99  1   cw
            0           cw  0   ':' 'd' 'n' 'u' 'o' 'r' ' ' 't' 'i' ' ' cw
            99          cw  0   ':' 'e' 'r' 'o' 'm' ' ' 'e' 'm' cw      's'
            1           ?                                       'o'     's'
            99          !                                       's'     'a'
        cw  J   c   0   cw  ?   c   0   s   '.' 0   ccw ?   s   ' ' ccw 'p'
        ~   d   cw  ' ' J   0   d   s   ';' ' ' 0   cw          'y' 'b' ' '
        0   0   'o'     'r'                                     'u' 'o' ','
        ~   'l' 'n'     'e'                                     'b' 't' 'n'
        0   'l' ' '     'e'                                     ' ' 't' 'w'
        @   'a' 't'     'b'                                     ',' 'l' 'o'
        ~   'w' 'h'     ccw ' ' 'f' 'o' ' ' bY  bX  =   ?   's' 'e' ccw 'd'
        1   ' ' 'e'                                             'r'     ' '
        @   ccw ccw     cw  'l' 'l' 'a' 'w' ' ' 'e' 'h' 't' cw  'o'     bY
        ~               '.' cw  's' 'e' 'l' 't' 't' 'o' cw  ' ' 't'     bX
        0               0   ' ' cw  c   0   ret         'b' 'n' 's'     =
        ~               c   'o' cw  0   s   d   99  ' ' cw  'o' ' '     ?
        1               0   cw  'f' ' ' 'b' 'e' 'e' 'r' ' ' cw  'e'     ccw cw
        @               cw  s   'G' 'o' ' ' 't' 'o' ' ' 't' 'h' cw      't' 'e'
        #                                                               'i' 'n'
        cw  bX  bY  -   1   @   98  nop c   0   s   'T' 'a' 'k' 'e' ' ' H   'o'
                                                                        cw  cw
    

    PL/M-80

    /*
     * 99 bottles of beer in PL/M-80
     *
     * by John Durbetaki using AEDIT
     *
     */
    Ninety$Nine:
    Do;
    
    declare as              LITERALLY   'LITERALLY'
    declare CRLF            as          '0Dh,0Ah'
    
    declare Beers           BYTE DATA(99);
    declare Message1(*)     BYTE DATA(' of beer on the wall,',CRLF);
    declare Message2(*)     BYTE DATA(' of beeeeer . . . . ,',CRLF);
    declare Message3(*)     BYTE DATA('Take one down, pass it around,',CRLF);
    declare Message4(*)     BYTE DATA(' of beer on the wall.',CRLF);
    declare End$Message(*)  BYTE DATA(CRLF,'Time to buy more beer!',CRLF);
    declare STATUS          BYTE;
    declare How$Many(128)   BYTE;
    declare How$Many$Count  BYTE;
    
    Copy: PROCEDURE(Ap,Bp,Count);
        declare Ap              ADDRESS;
        declare A BASED Ap      BYTE;
        declare Bp              ADDRESS;
        declare B BASED Bp      BYTE;
        declare Count           BYTE;
    
        DO WHILE Count > 0;
            B=A;
            Ap=Ap+1;
            Bp=Bp+1;
            Count=Count-1;
            END;
        END;
    
    Make$How$Many: PROCEDURE(Beers);
        declare Beers           BYTE;
    
        if Beers = 0 THEN DO;
            CALL Copy(.('No more bottles'),.How$Many(0),How$Many$Count=15);
            END;
        else if Beers = 1 THEN DO;
            CALL Copy(.('One more bottle'),.How$Many(0),How$Many$Count=15);
            END;
        else DO;
            if Beers > 10 THEN DO;
                How$Many(0)='0'+(Beers/10);
                How$Many(1)='0'+(Beers MOD 10);
                CALL Copy(.(' bottles'),.How$Many(2),8);
                How$Many$Count=10;
                END;
            else DO;
                How$Many(0)='0'+Beers;
                CALL Copy(.(' bottles'),.How$Many(1),8);
                How$Many$Count=9;
                END;
            END;
        END;
    
    Chug: PROCEDURE(Beers);
        declare Beers           BYTE;
    
        CALL Make$How$Many(Beers);
        CALL WRITE(0,.How$Many,Count,.STATUS);
        CALL WRITE(0,.Message1,SIZE(Message1),.STATUS);
        CALL WRITE(0,.How$Many,Count,.STATUS);
        CALL WRITE(0,.Message2,SIZE(Message2),.STATUS);
        CALL WRITE(0,.Message3,SIZE(Message3),.STATUS);
        CALL Make$How$Many(Beers-1);
        CALL WRITE(0,.How$Many,Count,.STATUS);
        CALL WRITE(0,.Message4,SIZE(Message4),.STATUS);
        END;
    
        DO WHILE Beers > 0;
            CALL Chug(Beers);
            Beers=Beers-1;
            END;
        CALL WRITE(0,.End$Message,SIZE(End$Message),.STATUS);
        END;
    

    NewtonScript

    NewtonScript is an object-oriented language that runs on Apple Newton MessagePads. You can get a Steve Weyer's free compiler for it at http://www.netaxs.com/~weyer/newton/newtdev.htm.
    // A simple NewtonScript program to 99 Bottles.
    // Armen Nakashian, 3/13/97 armen@yawara.anime.net
    
    BeerSong
    {
    Drink:func()
    for b:=99 to 1 do
    begin   
            print(bob(b) & " on the wall, " & bob(b) & ".");
    
            print("Take one down, pass it around, " & bob(b-1) & " on the
    wall.");
    end,
    
    bob:func(i):
            if i==0 then return "no more bottles of beer",
            else if i==1 then return "1 bottle of beer",
            else return i & " bottles of beer",
    }
    
    

    Occam

    -- compiled with the University of Kent "kroc" compiler
    -- Tony Curtis  1997
    --
    PROC beer (CHAN OF BYTE key, screen, error)
     
      VAL INT BEERS IS 99 :                       -- big fridge!
     
      #USE "tty_utils.tco"
      PROC sorp (VAL INT n, CHAN OF BYTE out)     -- singular or plural?
        IF
          n > 1
            out.string ("s", 1, out)
          TRUE
            SKIP
      :
      PROC sayit (VAL INT n, CHAN OF BYTE out)     -- text for each iteration
        SEQ
          out.number (n, 1, out)
          out.string (" bottle", 1, out)
          sorp (n, out)
          out.string (" of beer on the wall, ", 1, out)
          out.number (n, 1, out)
          out.string (" bottle", 1, out)
          sorp (n, out)
          out.string (" of beer.", 1, out)
          out.string ("*c*n", 1, out)
          out.string ("Take one down, pass it around, ", 1, out)
          VAL INT next IS  n - 1 :
          IF
            next > 0
              SEQ
                out.number (next, 1, out)
                out.string (" bottle", 1, out)
                sorp (next, out)
                out.string (" of beer on the wall.", 1, out)
            TRUE
              out.string ("no bottles of beer on the wall.", 1, out)
          out.string ("*c*n", 1, out)
      :
      PROC beers (VAL INT nbeers, CHAN OF BYTE out)
        INT b :
        SEQ
          b := nbeers
          WHILE b > 0
            SEQ
              sayit (b, out)
              b := b - 1
      :
      beers (BEERS, screen)
    :
    

    PL/SQL

    PL/SQL is a programming language that resides in an Oracle database. As PL/SQL has no standard input or output this version is written to be run from the SQLPlus command line using an anonymous PL/SQL block.
    /* Start of code */
    set serveroutput on
    
    DECLARE
            counter         NUMBER;
    BEGIN
            dbms_output.enable;
    
            FOR counter IN REVERSE 1..99 LOOP
                    dbms_output.put_line(counter || ' bottles of beer on the wall,');
                    dbms_output.put_line(counter || ' bottles of beer.');
                    dbms_output.put_line('Take one down, pass it around,');
                    
                    IF (counter != 1) THEN
                            dbms_output.put_line(counter - 1 || ' bottles of beer on the wall.');
                    ELSE
                            dbms_output.put_line('No more beers.');
                    END IF;
            END LOOP;
    END;
    /
    /* End of code (The "/" in the line above is very important) */
    

    PH/FI

    PH/FI is a light, and powerful, interpreter for server-parsed ("dynamic" this year, SSH since NCSA invented the thing ages ago) html which can be used either as a CGI redirected processor or embbedded in Apache servers. Its web site is http://php.iquest.net/.
    <HTML>
    <HEAD>
    <TITLE>
    99 Bottles of beer.
    </TITLE>
    <META NAME="Author" CONTENT="Alejandro López-Valencia">
    <META NAME="E-Mail" CONTENT="palopez@usa.net">
    <META NAME="Description" CONTENT="Written in PHP/FI 2.0">
    </HEAD>
    <BODY BGCOLOR="#FFFFFF">
    <?
    /* Don't show the access information footer */
    setshowinfo(0)
    >
    <?
    /* Drink with the boys... */
    $hic = 99;
    while ($hic > 0) (
    	$huc = $hic - 1;
    
    /* Waste CPU, but you are using a Cray, aren't you? */
    
    	if ($hic = 1) (
    		$huc = $hic;
    	) ;
    
    	if ($hic = 1) $bottles = "bottle" else $bottles = "bottles" ;
    
    	echo $hic $bottles of beer on the wall, $hic $bottles of beer. <BR> ;
    	echo Take one and pass it around, <BR> ;
    	echo "$huc $bottles of beer on the wall. <BR>" ;
    	$hic--;
    )
    /* Pass out */
    echo No more bottles of beer on the wall. <BR> ;
    echo No more bottles of beer... <BR> ;
    echo Go to the store and buy some more... <BR> ;
    echo 99 bottles of beer. <BR> ;
    >
    </BODY>
    </HTML>
    

    OCL

    Operation Control Language is the JCL/batch/scripting language for the IBM System 32/34/36 computer series..
    ** 99 Bottles of Beer on the Wall
    // EVALUATE P1=99 P2='s'
    // TAG MOREBEER
    // * '?1? bottle?2? of beer on the wall,'
    // * '?1? bottle?2? of beer,'
    // IFF '?1?'='No more' * 'Take one down and pass it around,' 
    // ELSE * 'Go to the store and get some more,'
    // IFF '?1?'='No more' EVALUATE P1=?1?-1  * decrement the counter
    // ELSE EVALUATE P1=99 * reseed counter
    // IF ?1?>1 EVALUATE  * leave P2='s' (for efficiency - OCL is interpreted)
    // ELSE IF ?1?=1 EVALUATE P2=''
    // ELSE IF ?1?=0 EVALUATE P1='No more' P2='s'
    // * '?1? bottle?2? of beer on the wall.'
    // GOTO MOREBEER * ad infinitum
    

    RC

    rc shell script language..
    #!/usr/local/bin/rc
    # rc shell version of 99 bottles of beer
    # by Tom Culliton (culliton@clark.net)
    
    count = (99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78
             77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56
             55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34
             33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12
             11 10 9 8 7 6 5 4 3 2 1)
    bottles = bottles; one = one
    for (i in $count) {
            if (~ $i 1) {bottles = bottle; one = it}
            if (! ~ $i 99) {
                    echo $i $bottles 'of beer on the wall.'
                    echo
            }
            echo $i $bottles 'of beer on the wall,'
            echo $i $bottles 'of beer,'
            echo 'take' $one 'down and pass it around,'
    }
    echo 'no more bottles of beer on the wall!'
    

    RAMIS Executive

    *-----------------------------------------------------------------------
    * 99 BOTTLES OF BEER ON THE WALL - RAMIS EXECUTIVE VERSION
    *-----------------------------------------------------------------------
    
    CATALOGS BEER
    &&COUNT/I2 = 99;
    &&LOOP
    &&BOTTLES/A7 = IF &COUNT GT 1 THEN 'BOTTLES' ELSE 'BOTTLE ';
    &&PRINT &COUNT &BOTTLES OF BEER ON THE WALL, &COUNT &BOTTLES OF BEER
    &&PRINT TAKE ONE DOWN, PASS IT AROUND
    &&COUNT/I2 = &COUNT - 1;
    &&IF &COUNT GT 0 GOTO LOOP;
    &&PRINT NO MORE BOTTLES OF BEER ON THE WALL, NO MORE BOTTLES OF BEER
    &&PRINT GO TO THE STORE AND BUY SOME MORE
    END CATALOGS
    EXEC BEER
    

    RAMIS SBX

    *----------------------------------------------------------------------
    * 99 BOTTLES OF BEER ON THE WALL - RAMIS SBX VERSION
    *----------------------------------------------------------------------
    
    PROCESS;
    DECLARE COUNT AS I2;
    DO FROM COUNT = 99 TO 2 BY -1;
        PRINT &COUNT BOTTLES OF BEER ON THE WALL, &COUNT BOTTLES OF BEER;
        PRINT TAKE ONE DOWN, PASS IT AROUND;
    ENDDO;
    
    PRINT  1 BOTTLE  OF BEER ON THE WALL,  1 BOTTLE  OF BEER;
    PRINT TAKE ONE DOWN, PASS IT AROUND;
    PRINT NO MORE BOTTLES OF BEER ON THE WALL, NO MORE BOTTLES OF BEER;
    

    Compilation Copyright 1995, 1996, 1997 Tim Robinson. All Rights Reserved
    Permission to copy enthusiastically granted to instructors of computer science
    (who would like to demonstrate the styles of different programming languages
    to their students) provided that the names of the contributors are retained.

    More beer
    Back to the Funhouse