Commits

Cat's Eye Technologies  committed f12c291

Out with the good air! In with the bad! (x4)

  • Participants
  • Parent commits cd46742
  • Tags rel_10_4_good_buddy

Comments (0)

Files changed (94)

File 1. ILLGOL/bin/illgol.exe

Binary file added.

File 1. ILLGOL/doc/illgol.html

+<html><head>
+<title>Cat's Eye Technologies: ILLGOL</title>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
+</head>
+<body bgcolor="#FFFFFF"
+      text="#000000"
+      link="#0000FF"
+      vlink="#007F00"
+      background="/img/puketrip.jpg">
+<CENTER>
+<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0>
+<TR>
+<TD ALIGN=CENTER VALIGN=CENTER bgcolor="#000000" BACKGROUND="/img/sineblack.gif"><A
+ HREF="/index.html"><img ALIGN=ABSMIDDLE
+ src="/img/3qtrsize.gif" ALT="Cat's Eye Technologies" BORDER=0></A></TD>
+<TD ALIGN=CENTER VALIGN=CENTER>
+&nbsp;&nbsp;&nbsp;
+<FONT face="Wide Latin,Rockwell Extra Bold,Chicago" SIZE=+3><b>ILLGOL</b></FONT>
+</TD></TR>
+</TABLE>
+<hr>
+<p><strong>NB</strong> ILLGOL, <a href="a-2/">Illgola-2</a>, and <a href="3/">Illberon</a> have been deprecated by
+Cat's Eye Technologies' newest offering,
+<br><font size=+2><a href="%23%23/">Open Sores Illgol##</a></font>
+<br><i>Upgrade now!!!</i>
+<p>
+<hr>
+<p><TABLE WIDTH="100%"><TR>
+<td colspan=2 align=center><b><i>
+"Yet another language that exists solely<br>
+by virtue of the fact that there's<br>
+a compiler for it that (mostly) works."</i></b><p>&nbsp;</td></tr><tr>
+<TD WIDTH="50%" ALIGN=LEFT VALIGN=TOP>
+
+<p><font face="Wide Latin,Rockwell Extra Bold,Chicago" size=+1>Teach yourself ILLGOL</font>
+
+<p>If you want to learn ILLGOL, you probably want to read
+the <a href="/esoteric/illgol/illgol.txt">documentation</a> first.  But you likely won't
+learn much from it.
+You'll have to play with the <a href="/esoteric/illgol/%23%23/prj/">sample sources</a>
+to discover more.
+
+<p>To play with ILLGOL you need to download a copy of
+the <a href="/esoteric/illgol/%23%23/">Illgol##</a>
+distribution which
+contains all the sample sources, documentation, and
+an Illgol##-to-8086 compiler.
+
+<p>The ILLGOL compiler translates ILLGOL programs into MS-DOS .COM
+files.  Syntactical errors will be caught, but may cause the compiler
+to go into a fit.  Very little by way of array bounds
+checking etc is done, though.  It's a very stupid little compiler.
+The command line syntax is:
+
+<pre>  ILLGOL illgol-file [com-file]</pre>
+
+<p>If com-file is omitted, <tt>OUT.COM</tt> will be written.
+
+</TD><TD WIDTH="50%" ALIGN=RIGHT VALIGN=TOP>
+
+<p><font face="Wide Latin,Rockwell Extra Bold,Chicago" size=+1>Review</font>
+<br>by Brian Connors
+
+<p>ILLGOL in short: Take three parts Perl, two parts Basic, two parts
+Fortran. Marinate for six hours in Budweiser and
+canola oil. Boil until pulped and serve with a side of
+Intercal.
+
+<p>ILLGOL in detail: ILLGOL is <a href="http://www.geocities.com/ResearchTriangle/Station/2266/tarpit/magenta.html"><img src="/img/webicon.gif" alt="[WWW]" border=0 width=12 height=12>Magenta</a> in the small. Kludgy, incompletely
+documented, fuzzy-minded about its aims, and just
+barely useable enough for real work, ILLGOL is easily
+the most disturbed language project I've ever seen. 
+
+<p>What sets it apart from ordinary computer languages is
+the initial air of normalcy. It looks like a fairly
+ordinary scripting language until its loose ends stick
+out: control structures like a bizarre combination of
+Basic and Fortran, clunky and arbitrarily vague
+runtime capabilities remniscent of Intercal, and a
+general lackadaisicalness straight out of the Camel
+book. 
+
+<p>ILLGOL is, to steal a word from the British, naff.
+
+</TD></TR>
+</TABLE>
+<p><hr><BR><font size=-1>Last Updated Jul 6 2001</font></CENTER></BODY>
+</HTML>

File 1. ILLGOL/doc/illgol.txt

+                                I L L G O L
+                                -----------
+                           A sick, sick language
+                           ---------------------
+
+Introduction to ILLGOL
+----------------------
+
+ILLGOL is sick.  Sick, I tell you.
+
+Now that we've got that out of the way and you can't say I didn't
+blame you, you have two choices: you can either delete this file
+archive and find something else to do, or you can continue reading.
+
+So you've decided to continue reading.  Well, I have some bad news.
+ILLGOL is highly contagious, so now you're sick too!  So you might
+as well have a look at some of the example sources to get a feel
+for what you're getting into.
+
+
+What You're Now Sick With
+-------------------------
+
+ILLGOL is a familiar-looking linear compiled language.  It is a free
+form language except for comments (which begin with the token "NB" and
+continue until the end of the current line.)  Tokens and user-defined
+identifiers are case-sensitive.
+
+An ILLGOL program consists of a sequence of assignments, delimited
+by ";" tokens, and the entire sequence terminated by the "FIN" token.
+A line number may optionally be included before each assignment.  In
+spite of this, ILLGOL is a block-structured language, using the "{" and
+"}" tokens to delimit blocks.
+
+An assignment may take a special form where the destination (the lvalue)
+may be missing, in which case the assignment resembles a command.
+These forms are:
+
+  if <expression> <block>
+  if <expression> <block> else <block>
+  while <expression> <block>
+  for <variable> = <expression> to <expression> <block>
+  for <variable> = <pointer> link <offset> <block>
+  do <function>
+  do <function>(<arguments>)
+  do <function>(<arguments>) until <expression>
+  do <function>(<arguments>) discard
+  do <function>(<arguments>) discard until <expression>
+  don't <function>
+  reinstate <function>
+
+Plus, there are some I/O commands:
+
+  text
+  print <expression-list>
+  in tty <variable>
+  out tty <expression>
+
+  hgr
+  hplot <expression>, <expression>, <expression>
+  border <expression>
+
+Expressions have the usual precedence (well, mostly.)  All values are
+16-bit, and we call this word-based.  The lower byte of a word can be
+extracted exclusively during an assignment by preceding the "=" token
+with the "BYTE" token. This allows safe construction of arrays of
+bytes.
+
+To create an array (or in fact allocate any larger-than-single-word
+memory for any occasion) you must use the unary "*" operator on an
+expression; this is somewhat analagous to C's malloc function.  The
+expression should evaluate to the desired number of bytes to allocate.
+
+(This situation is paralleled with variable declarations.  The first
+time a variable is used, it should be declared in a similar manner,
+by preceding it with a unary "*".)
+
+The result of the allocation expression is a pointer to the memory thus
+allocated.  You can use the following dereferencing tools to get at
+that memory, both in the source and destination of an assignment:
+
+  variable^             word pointed to by variable
+  variable[expression]  word pointed to by (variable plus expression)
+  variable.constant     word pointed to by (variable plus constant)
+
+Note that 'constant' is just a constant offset and does not care what
+'type' the variable is.  All of these dereferencing tools can be
+appended in an indefinately long chain (X[Y].Z^[W]^^.Q etc.)
+
+In the source of an assignment, the token "^" can be used as a unary
+operator on a variable, to return that variable's address (a pointer
+to that variable.)
+
+In addition to a plain assignment which uses the "=" operator,
+assignments involving the C-like "+=" and "-=" operators are also
+supported.  C-like postincrementation "++" and postdecrementation "--"
+are also supported, but preincrementation and predecrementation are
+not.
+
+Fixed-point arithmetic is supported with various built-in functions
+(fix, cos, int, sin, sif) and variations on the standard integer "*"
+and "/" operators.  By trailing the operator with a "." as in "*." or
+"/.", you indicate that you want the result corrected for fixed-point.
+Since all values are word-based, a fixed-point value contains eight
+bits left of the radix point and eight bits to the right, able to
+record positive values from 0 to 127_255/256 in increments of 1/256
+(and probably negative values in a similar range.)
+
+Functions can be defined by means of lambda blocks; that is, the
+source of an assignment is given as a program block.  The destination
+of the assignment is assigned a pointer to the machine function
+implementing that program block.  That function can be used in a 
+"do" assignment (if it does not use "yield" to return a value, or if
+the "discard" form of "do" is used) or called with the "call"
+operator (if it does use "yield" to return a value.)
+
+
+Notes on How to Use the Compiler
+--------------------------------
+
+The ILLGOL compiler translates ILLGOL programs into MS-DOS .COM
+files.  Syntactical errors will be caught but even a single error
+will kill the compile cycle.  Very little by way of array bounds
+checking etc is done, though.  It's a very stupid little compiler.
+The command line syntax is:
+
+  ILLGOL illgol-file [com-file]
+
+If com-file is omitted, OUT.COM will be written.
+
+
+EBNF grammar (approximate)
+--------------------------
+
+ILLGOL      ::= Assignments "FIN" .
+Assignments ::= Assignment {";" Assignment} .
+Assignment  ::= [number] name Deref ["BYTE"] ("=" | "+=" | "-=") BoolExpr
+              | "CONST" name "=" number {"," name "=" number}
+              | "while" BoolExpr Block
+              | "for" name "=" BoolExpr "to" BoolExpr Block
+              | "if" BoolExpr Block ["else" Block]
+              | "print" (BoolExpr | "EoL") {"," (BoolExpr | "EoL")}
+              | "do" BoolExpr ["(" BoolExpr {"," BoolExpr} ")"] ["discard"] ["until" BoolExpr]
+              | "hgr" | "text" | "hplot" BoolExpr "," BoolExpr "," BoolExpr
+BoolExpr    ::= NegExpr {"&" NegExpr | "|" NegExpr | "~" NegExpr} .
+NegExpr     ::= ["!"] CompExpr .                                       *I don't trust this*
+CompExpr    ::= AddExpr {"=" AddExpr | "!=" AddExpr | ">" AddExpr |
+                         ">=" AddExpr | "<" AddExpr | "<=" AddExpr} .
+AddExpr     ::= Term {"+" Term | "-" Term} .
+Term        ::= Factor {"*" ["."] Factor | "/" ["."] Factor} .
+Factor      ::= Primitive {"<<" Primitive | ">>" Primitive} .
+Primitive   ::= "^" name
+              | name Deref ["++"|"--"]
+              | number | string {string}
+              | "{" ["*" name {"," name} ";"] Assignments "}"
+              | "(" BoolExpr ")"              
+              | "*" BoolExpr .
+              | "abs" BoolExpr     & 0x7fff
+              | "asc" BoolExpr     & 0x007f
+              | "fix" BoolExpr     << 8
+              | "cos" BoolExpr     table lookup
+              | "fre" BoolExpr     0 - heapptr
+              | "int" BoolExpr     >> 8
+              | "rnd" BoolExpr     sequential hashing method
+              | "sin" BoolExpr     table lookup
+              | "str" BoolExpr     convert word to string of ASCII decimals
+              | "stu" BoolExpr     convert unsigned word to ASCII decimal
+              | "sif" BoolExpr     convert FIXED to string of ASCII decimals
+Member      ::= number | const_name .
+Block       ::= "{" Assignments "}" | Assignment .
+Deref       ::= {"." Member | "[" AddExpr "]" | "^"} .
+
+
+Further Exploration
+-------------------
+
+This document doesn't cover everything.  You'll have to discover the
+rest by experimenting with the compiler.
+
+eh.ill demonstrates what "don't" and "reinstate" do.
+alloc.ill demonstrates allocation and the "for link" loop.
+fact.ill demonstrates recursion, function calls & arguments.
+happy1.ill demonstrates Full Moon Fever "compatibility mode".
+fancy.ill demonstrates "border" and
+          demonstrates using FMF {...} within a larger program.
+hgr.ill demonstrates "hplot" et al.
+
+
+What the Critics have to Say about ILLGOL
+-----------------------------------------
+
+"ILLGOL is more powerful than BASIC because it's a compiled language."
+  -- Name withheld by request
+
+"ILLGOL rocks!  Not as a programming language, though, only as plant food."
+  -- Name withheld by request
+
+"You can write all your FORTRAN code in ILLGOL."
+  -- Name withheld by request
+
+"Programming in ILLGOL helps drown out the voices in my head."
+  -- Name withheld by request
+
+"ILLGOL uses the revolutionary 'imperative' paradigm, which is
+ preferred by four out of five programmers."
+  -- Name withheld by request
+
+"Wow!  I can't believe what a fast language ILLGOL is."
+  -- Name withheld by request
+
+"ILLGOL is better documented than the software we use at work.
+ No, seriously though.  It is."
+  -- Name withheld by request
+
+"I haven't killed anyone at ALL since I started programming in ILLGOL!"
+  -- Name withheld by request
+
+"Screw Haskell!  I'm using ILLGOL for my next project!"
+  -- Name withheld by request

File 1. ILLGOL/prj/Happy1.ill

+FMF{ CLRSCR
+GO 1 1
+PRINT "----------------------------------------------------------------------------"
+GO 1 3
+PRINT "----------------------------------------------------------------------------"
+GO 1 20
+PRINT "----------------------------------------------------------------------------"
+PAUSE 50
+GO 1 2 CLREOL GO 30 2 PRINT "Enter ... Mr. Happy."
+GO 1 19
+PAUSE 50
+PRINT "O" LF
+DO 20
+    PAUSE 5 INS;
+PAUSE 50
+GO 22 18
+PRINT "/"
+GO 23 15
+PRINT "You know you can't even get a"
+GO 23 16
+PRINT "decent burger in this town for"
+GO 23 17
+PRINT "less than $2.00.  Pisses me off."
+PAUSE 250
+GO 23 15 CLREOL
+GO 23 16 CLREOL
+GO 23 17 CLREOL
+GO 22 18 PRINT " "
+PAUSE 20
+GO 1 2 CLREOL GO 27 2 PRINT "E A R T H Q U A K E !!!!!!!"
+PAUSE 30
+GO 1 4
+DO 20
+   PAUSE 1 INSLIN DELLIN;
+
+GO 20 18
+DO 10
+    PAUSE 1 PRINT "? ?" LF LF LF PAUSE 1 PRINT " ? " LF LF LF;
+PRINT "   "
+PAUSE 50
+
+GO 1 19
+DO 21
+    DEL;
+PAUSE 50
+GO 1 2 CLREOL GO 31 2 PRINT "Exit... Mr. Happy."
+PAUSE 150
+CLRSCR };
+FIN

File 1. ILLGOL/prj/alloc.ill

+CONST val  = 0,
+      next = 2;
+
+*ListPtrC = (*4);
+ListPtrC^.val  = 3;
+ListPtrC^.next = 0;
+
+*ListPtrB = (*4);
+ListPtrB^.val  = 2;
+ListPtrB^.next = ListPtrC;
+
+*ListPtrA = (*4);
+ListPtrA^.val  = 1;
+ListPtrA^.next = ListPtrB;
+
+*L = 0; *char = 0;
+for L = ListPtrA link next
+{
+  print str(L^.val), EoL
+};
+FIN

File 1. ILLGOL/prj/eh.ill

+10 *f = { print str(#0), EoL };
+20 do f(1);
+30 don't f;
+40 do f(2);
+50 reinstate f;
+60 do f(3);
+FIN

File 1. ILLGOL/prj/fact.ill

+*fact = { if #0 > 1 yield #0 * call fact(#0 - 1) else yield 1 };
+
+*a = 1;
+for a = 1 to 7
+{
+  print stu(call fact(a)), EoL;
+};
+
+FIN

File 1. ILLGOL/prj/fancy.ill

+*x = 0;
+*y = 0;
+
+for x = 0 to 79
+  for y = 0 to 12
+  {
+    border x;
+    FMF {GO x y};
+    if ((x * y) <> 7)
+    {
+      out tty (x*y)
+    } else
+    {
+      out tty 32
+    }
+  };
+
+FIN

File 1. ILLGOL/prj/hello.ill

+print "Hello, world!", EoL FIN

File 1. ILLGOL/prj/hgr.ill

+hgr;
+*i=0; *x=0; *y=0; *c=0;
+for i = 0 to 100
+{
+  for x = 0 to 319
+  {
+    for y = 0 to 199
+    {
+      hplot x, y, (x+y+i);
+    }
+  }
+};
+while c <> 27 in tty c;
+text;
+FIN
+

File 1. ILLGOL/prj/hgr2.ill

+hgr;
+*c=0; *j=0; *i=0; *x=0; *y=0;
+for j = 0 to 100
+{
+  for i = 0 to 255
+  {
+    x = (1000 + cos i) >> 5;
+    y = (1000 + sin i) >> 5;
+    hplot x + j, y + j, i + j;
+  }
+};
+
+while c <> 27 { in tty c };
+text;
+FIN
+

File 1. ILLGOL/prj/test.ill

+CONST x = 0, y = 2;
+
+*coo = 0;
+
+*f = { out tty #(coo++); out tty #(coo--) };
+
+*z = 2;
+*a *4 = 0;
+a.x = 255;
+a.y = 32;
+*ptr = ^a + 2;
+while a.x >= 32
+{
+  while a.y <= 255
+  {
+    do f (a.x, a.y);
+    *foo = ptr^++
+  };
+  a[z] = 32;
+  a.x -= 1
+};
+
+*w = "Wrong!"; NB comment
+*r = "Right!";
+*a = 1;
+*b = 2;
+if a < b
+{
+  if b = a
+  {
+    print w
+  };
+  if b < a
+  {
+    print w
+  } else
+  {
+    print r
+  }
+} else
+{
+  print w
+};
+
+if ?a print r;
+if !(?a) print w;
+if ?(b-2) print w;
+if !(?(b-2)) print r;
+
+if a < b if b <> a print r;
+if b < a print w else print r;
+
+NB fixed-point arithmetic (such as it is) demo.
+
+   a = 0;
+   *char = 0;
+   while (char <> 27)
+   {
+     print sif(a); out tty 13; out tty 10;
+     in tty char;
+     a = a + 0.1;
+   };
+
+*char = 0;
+*r = 0;
+while (char <> 27)
+{
+  print sif(rnd(r)); out tty 13; out tty 10;
+  in tty char;
+};
+
+print str(fre(0));    out tty 13; out tty 10;
+print str(int(6.81)); out tty 13; out tty 10;
+
+*i = 0;  NB unfortunately required...
+
+for i = 33 to 43
+{
+  out tty i;
+};
+
+for i = 33 to 43 out tty i;
+
+a = 123;
+print str(a);
+out tty 13; out tty 10;
+print str(9999);
+out tty 13; out tty 10;
+print str(1);
+out tty 13; out tty 10;
+
+NB This is a comment
+
+10 print "And "
+         "so "
+         "it "
+         "begins...";
+
+20 *i = 0;
+
+30 *f = { print "Voila!"; out tty 13; out tty 10 };
+40 *g = { out tty i-- };
+
+50 do f; do f; do f;
+
+60 i = 34;
+70 do g; do g; do { out tty 13; out tty 10 };
+80 i = 255;
+90 do g until i = 65;
+
+*crlf = { out tty 13; out tty 10 };
+do crlf;
+
+*array *16 BYTE = 37;
+array.1    BYTE = 38;
+array.2    BYTE = 39;
+array.3    BYTE = 99;
+array.4    BYTE = 64;
+array.5    BYTE = 0;
+
+print ^array; do crlf;
+array.3         = 7000;
+print ^array; do crlf;
+array.1    BYTE = 7000;
+print ^array; do crlf;
+
+*s = "Fantastic!";
+print s; do crlf;
+s^ BYTE = 65;
+print s++; do crlf;
+array[2] = s--;
+array[2]^ BYTE = 99;
+print s; do crlf;
+
+print str(10 - 5), EoL;
+
+FIN

File 1. ILLGOL/prj/trig.ill

+*c = 0;
+*a = 0;
+while c <> 27
+{
+  print str(a), " ", str(cos(a)), " ", str(sin(a)), EoL;
+  in tty c;
+  a += 1;
+};
+FIN

File 1. ILLGOL/src/8086.c

+/*
+  8086.c
+  8086 machine-code generating module including simple peephole opt.
+*/
+
+byte s[16384];    /* codespace */
+byte * m;
+#define GEN(x) *m = x; m++;
+byte hi, lo;
+#define GENW(x) lo=(byte)(x&0xff); hi=(byte)((x>>8)&0xff); \
+                GEN(lo); GEN(hi);
+byte lbl = 0;
+void g_label(void) { lbl = 1; }
+
+#define DID(x)  lbl=0; return x;
+
+/* unoptimizable-at-first-glance instructions */
+
+int g_hlt(void)         { GEN(244); DID(1); }
+
+int g_push_ax(void)     { GEN(80); DID(1); }
+int g_push_bx(void)     { GEN(83); DID(1); }
+int g_push_cx(void)     { GEN(81); DID(1); }
+int g_push_dx(void)     { GEN(82); DID(1); }
+
+int g_push_si(void)     { GEN(86); DID(1); }
+int g_push_di(void)     { GEN(87); DID(1); }
+
+int g_push_BX(void)     { GEN(255); GEN(55);  DID(2); }
+
+int g_push_bp(void)	{ GEN(0x55); DID(1); }
+int g_mov_ax_BP(sbyte s) { GEN(0x8B); GEN(0x46); GEN(s); DID(3); }
+int g_mov_bp_sp(void)   { GEN(0x8B); GEN(0xEC); DID(2); }
+int g_pop_bp(void)      { GEN(0x5D); DID(1); }
+
+int g_lahf(void)      { GEN(159); DID(1); }
+
+int g_int(byte i)     { GEN(205); GEN(i); DID(2); }
+
+int g_es(void)         { GEN(38); return 1; }   /* retain lbl status */
+
+int g_mov_ax_I(word i)   { GEN(161); GENW(i); g_label(); DID(3); }
+int g_mov_I_ax(word i)   { GEN(163); GENW(i); g_label(); DID(3); }
+int g_mov_es_I(word i)   { GEN(142); GEN(6); GENW(i); g_label(); DID(4); }
+
+int g_mov_ax_sp(void)    { GEN(0x8B); GEN(0xC4); DID(2); }
+int g_add_ax(sword i)    { GEN(5); GENW(i); DID(3); }
+int g_mov_bp_ax(void)    { GEN(0x8B); GEN(0xE8); DID(2); }
+int g_mov_dh_al(void)    { GEN(0x8A); GEN(0xF0); DID(2); }
+
+int g_jmp(sword i)       { GEN(0xe9); GENW(i); DID(3); }
+
+int g_jmp_ax(void)    { GEN(255); GEN(224); DID(2); }
+int g_call_ax(void)   { GEN(255); GEN(208); DID(2); }
+
+int g_mov_ax_BX(void) { GEN(139); GEN(7); DID(2); }
+int g_mov_cl_BX(void) { GEN(138); GEN(15); DID(2); }
+int g_mov_DI_al(void) { GEN(136); GEN(5); DID(2); }
+int g_cmp_bx_ax(void)   { GEN(57);  GEN(195); DID(2); }
+int g_cmp_al_DI(void)   { GEN(58); GEN(5); DID(2); }
+int g_mov_al_SI(void)   { GEN(138); GEN(4); DID(2); }
+int g_mov_ax_DI(void)   { GEN(139); GEN(5); DID(2); }
+int g_cmp_dl(byte q)    { GEN(0x80); GEN(0xFA); GEN(q); DID(3); }
+int g_cmp_al_dl(void)   { GEN(0x38); GEN(0xD0); DID(2); }
+
+int g_add_BX_ax(void)   { GEN(1); GEN(7); DID(2); }
+int g_sub_BX_ax(void)   { GEN(0x29); GEN(7); DID(2); }
+
+int g_add_BX_al(void)   { GEN(0); GEN(7); DID(2); }
+int g_sub_BX_al(void)   { GEN(0x28); GEN(7); DID(2); }
+
+int g_shl_ax_1(void)    { GEN(209); GEN(224); DID(2); }
+int g_shr_ax_1(void)    { GEN(209); GEN(232); DID(2); }
+
+int g_shl_ax_cl(void)   { GEN(211); GEN(224); DID(2); }
+int g_shr_ax_cl(void)   { GEN(211); GEN(232); DID(2); }
+
+int g_cmp_ax(word i)    { GEN(0x3D); GENW(i); g_label(); DID(3); }
+int g_cmp_bx(word i)    { GEN(0x81); GEN(0xFB); GENW(i); g_label(); DID(4); }
+
+int g_cmp_ax_dx(void)   { GEN(0x39); GEN(0xD0); DID(2); }
+int g_jle(sbyte d)      { GEN(0x7E); GEN(d); DID(2); }
+int g_jge(sbyte d)      { GEN(0x7D); GEN(d); DID(2); }
+int g_jl(sbyte d)       { GEN(0x7C); GEN(d); DID(2); }
+int g_jg(sbyte d)       { GEN(0x7F); GEN(d); DID(2); }
+
+int g_add_bx_ax(void)   { GEN(1); GEN(0xC3); DID(2); }
+int g_add_al(sbyte s)   { GEN(4); GEN(s); DID(2); }
+int g_jmp_bx(void)      { GEN(0xff); GEN(0xe3); DID(2); }
+
+int g_mov_al_ah(void)   { GEN(0x88); GEN(0xE0); DID(2); }
+int g_mov_ah_dl(void)   { GEN(0x88); GEN(0xD4); DID(2); }
+int g_mov_ah_al(void)   { GEN(0x88); GEN(0xC4); DID(2); }
+int g_mov_dl_ah(void)   { GEN(0x88); GEN(0xE2); DID(2); }
+
+int g_add_dx(sword w)   { GEN(0x81); GEN(0xC2); GENW(w); DID(4); }
+int g_mov_BX_dl(void)   { GEN(0x88); GEN(0x17); DID(2); }
+
+int g_cmp_al(sbyte b)   { GEN(0x3C); GEN(b); DID(2); }
+int g_mov_bl_al(void)	{ GEN(0x88); GEN(0xC3); DID(2); }
+int g_shl_bl_1(void)	{ GEN(0xD0); GEN(0xE3); DID(2); }
+int g_add_bx(sword w)   { GEN(0x81); GEN(0xC3); GENW(w); g_label(); DID(4); }
+int g_mov_cx_BX(void)   { GEN(0x8B); GEN(0x0F); DID(2); }
+int g_sub_bx_ax(void)   { GEN(0x29); GEN(0xC3); DID(2); }
+int g_sub_al(sbyte b)   { GEN(0x2C); GEN(b); DID(2); }
+int g_neg_cx(void)      { GEN(0xF7); GEN(0xD9); DID(2); }
+int g_xor_cx_dx(void)   { GEN(0x31); GEN(0xD1); DID(2); }
+int g_call_bx(void)     { GEN(0xFF); GEN(0xD3); DID(2); }
+int g_mov_es_ax(void)   { GEN(0x8E); GEN(0xC0); DID(2); }
+int g_mov_ax_ds(void)   { GEN(0x8C); GEN(0xD8); DID(2); }
+int g_and_ax(sword w)   { GEN(0x25); GENW(w); g_label(); DID(3); }
+int g_neg_ax(void)      { GEN(0xF7); GEN(0xD8); DID(2); }
+int g_add_ax_bx(void)	{ GEN(0x01); GEN(0xD8); DID(2); }
+int g_mov_DI_cl(void)	{ GEN(0x88); GEN(0x0D); DID(2); }
+int g_call_dx(void)     { GEN(0xFF); GEN(0xD2); DID(2); }
+int g_mov_bx_I(sword w) { GEN(0x8B); GEN(0x1E); GENW(w); g_label(); DID(4); }
+int g_mov_I_bx(sword w) { GEN(0x89); GEN(0x1E); GENW(w); g_label(); DID(4); }
+
+/* optimizable instructions */
+
+int g_xchg_dx_ax(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 146) { DID(-1); }
+    m++;
+  }
+  GEN(146);
+  DID(1);
+}
+
+int g_xchg_bx_ax(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 147) { DID(-1); }
+    m++;
+  }
+  GEN(147);
+  DID(1);
+}
+
+int g_xchg_cx_ax(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 145) { DID(-1); }
+    m++;
+  }
+  GEN(145);
+  DID(1);
+}
+
+int g_xchg_si_ax(void) { GEN(0x96); DID(1); }
+int g_mov_ax_BP_SI(void) { GEN(0x8B); GEN(2); DID(2); }
+
+int g_mov_bx_ax(void) { GEN(137); GEN(195); DID(2); }
+int g_mov_cx_ax(void) { GEN(137); GEN(193); DID(2); }
+int g_mov_dx_ax(void) { GEN(137); GEN(194); DID(2); }
+
+int g_mov_ax_bx(void) { GEN(0x89); GEN(0xD8); DID(2); }
+int g_mov_ax_cx(void) { GEN(0x89); GEN(0xC8); DID(2); }
+int g_mov_ax_dx(void) { GEN(0x89); GEN(0xD0); DID(2); }
+
+int g_mov_bx_cx(void) { GEN(0x89); GEN(0xCB); DID(2); }
+int g_mov_bx_dx(void) { GEN(139); GEN(210); DID(2); }
+
+int g_mov_dx_bx(void) { GEN(0x89); GEN(0xDA); DID(2); }
+int g_mov_cx_bx(void) { GEN(0x89); GEN(0xD9); DID(2); }
+int g_mov_dx_cx(void) { GEN(0x89); GEN(0xCA); DID(2); }
+int g_mov_cx_dx(void) { GEN(0x89); GEN(0xD1); DID(2); }
+
+int g_pop_ax(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 80) { DID(-1); }
+    if (*m == 83)
+    {
+      return g_mov_ax_bx() - 1;
+    }
+    if (*m == 81)
+    {
+      return g_mov_ax_cx() - 1;
+    }
+    if (*m == 82)
+    {
+      return g_mov_ax_dx() - 1;
+    }
+    m++;
+  }
+  GEN(88);
+  DID(1);
+}
+
+int g_pop_bx(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 83) { DID(-1); }
+    if (*m == 80)
+    {
+      return g_mov_bx_ax() - 1;
+    }
+    if (*m == 81)
+    {
+      return g_mov_bx_cx() - 1;
+    }
+    if (*m == 82)
+    {
+      return g_mov_bx_dx() - 1;
+    }
+    m++;
+  }
+  GEN(91);
+  DID(1);
+}
+
+int g_pop_cx(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 81) { DID(-1); }
+    if (*m == 80)
+    {
+      return g_mov_cx_ax() - 1;
+    }
+    if (*m == 83)
+    {
+      return g_mov_cx_bx() - 1;
+    }
+    if (*m == 82)
+    {
+      return g_mov_cx_dx() - 1;
+    }
+    m++;
+  }
+  GEN(89);
+  DID(1);
+}
+
+int g_pop_dx(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 82) { DID(-1); }
+    if (*m == 80)
+    {
+      return g_mov_dx_ax() - 1;
+    }
+    if (*m == 83)
+    {
+      return g_mov_dx_bx() - 1;
+    }
+    if (*m == 81)
+    {
+      return g_mov_dx_cx() - 1;
+    }
+    m++;
+  }
+  GEN(90);
+  DID(1);
+}
+
+int g_pop_di(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 87) { DID(-1) };
+    m++;
+  }
+  GEN(95);
+  DID(1);
+}
+
+int g_pop_si(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 86) { DID(-1); }
+    m++;
+  }
+  GEN(94);
+  DID(1);
+}
+
+int g_ret(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 208)
+    {
+      m--;
+      if (*m == 255) /* call ax */
+      {
+        return g_jmp_ax() - 2;
+      }
+      m++;
+    }
+    m++;
+  }
+  GEN(0xc3);
+  DID(1);
+}
+
+int g_xor_ax_ax(void) { GEN(51); GEN(192); DID(2); }
+int g_xor_bx_bx(void) { GEN(0x31); GEN(0xDB); DID(2); }
+int g_xor_cx_cx(void) { GEN(49); GEN(201); DID(2); }
+int g_xor_dx_dx(void) { GEN(49); GEN(210); DID(2); }
+
+int g_xor_al_al(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 228)
+    {
+      m--;
+      if (*m == 50) /* xor ah, ah */
+      {
+        return g_xor_ax_ax() - 2;
+      }
+      m++;
+    }
+    m++;
+  }
+  GEN(50);
+  GEN(192);
+  DID(2);
+}
+
+int g_xor_bl_bl(void) { GEN(0x30); GEN(0xDB); DID(2); }
+int g_xor_cl_cl(void) { GEN(0x30); GEN(0xC9); DID(2); }
+int g_xor_dl_dl(void) { GEN(0x30); GEN(0xD2); DID(2); }
+
+int g_xor_ah_ah(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 192)
+    {
+      m--;
+      if (*m == 50) /* xor al, al */
+      {
+        return g_xor_ax_ax() - 2;
+      }
+      m++;
+    }
+    m++;
+  }
+  GEN(50); GEN(228); DID(2);
+}
+
+int g_xor_bh_bh(void) { GEN(48); GEN(255); DID(2); }
+int g_xor_ch_ch(void) { GEN(0x30); GEN(0xED); DID(2); }
+int g_xor_dh_dh(void) { GEN(0x30); GEN(0xF6); DID(2); }
+
+int g_mov_ah_cl(void) { GEN(136); GEN(204); DID(2); }
+int g_mov_dh_cl(void) { GEN(136); GEN(206); DID(2); }
+
+int g_mov_BX_al(void) { GEN(136); GEN(7); DID(2); }
+int g_mov_BX_ax(void) { GEN(137); GEN(7); DID(2); }
+int g_mov_BX_cl(void) { GEN(136); GEN(15); DID(2); }
+int g_mov_BX_cx(void) { GEN(137); GEN(15); DID(2); }
+
+int g_or_ax_ax(void)  { GEN(11); GEN(192); DID(2); }
+int g_or_al_al(void)  { GEN(10); GEN(192); DID(2); }
+int g_or_dx_dx(void)  { GEN(9); GEN(210); DID(2); }
+int g_not_ax(void)    { GEN(247); GEN(208); DID(2); }
+
+int g_inc_si(void)    { GEN(70); DID(1); }
+int g_inc_di(void)    { GEN(71); DID(1); }
+
+int g_inc_bx(void)    { GEN(67); DID(1); }
+int g_inc_cx(void)    { GEN(0x41); DID(1); }
+int g_inc_dx(void)    { GEN(0x42); DID(1); }
+
+int g_dec_bx(void)    { GEN(0x4B); DID(1); }
+int g_dec_cx(void)    { GEN(0x49); DID(1); }
+int g_dec_dx(void)    { GEN(74); DID(1); }
+
+int g_dec_dh(void)    { GEN(0xFE); GEN(0xCE); DID(2); }
+int g_inc_dh(void)    { GEN(0xFE); GEN(0xC6); DID(2); }
+int g_dec_dl(void)    { GEN(0xFE); GEN(0xCA); DID(2); }
+int g_inc_dl(void)    { GEN(0xFE); GEN(0xC2); DID(2); }
+
+int g_clc(void)       { GEN(0xF8); DID(1); }
+int g_rcr_cx_1(void)  { GEN(0xD1); GEN(0xD9); DID(2); }
+int g_rcr_dx_1(void)  { GEN(0xD1); GEN(0xDA); DID(2); }
+
+int g_and_ax_dx(void) { GEN(35); GEN(194); DID(2); }
+int g_or_ax_dx(void)  { GEN(1); GEN(194); DID(2); }
+int g_xor_ax_dx(void) { GEN(51); GEN(194); DID(2); }
+
+int g_add_ax_dx(void) { GEN(1); GEN(208); DID(2); }
+int g_sub_ax_dx(void) { GEN(41); GEN(208); DID(2); }
+int g_sub_dx_ax(void) { GEN(41); GEN(194); DID(2); }
+
+int g_imul_dx(void)   { GEN(247); GEN(234); DID(2); }
+int g_idiv_cx(void)   { GEN(247); GEN(249); DID(2); }
+
+int g_inc_ax(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 72) { DID(-1); }
+    m++;
+  }
+  GEN(64);
+  DID(1);
+}
+
+int g_dec_ax(void)
+{
+  if (!lbl)
+  {
+    m--;
+    if (*m == 64) { DID(-1); }
+    m++;
+  }
+  GEN(72);
+  DID(1);
+}
+
+int g_nop(void)
+{
+  if (!lbl) { DID(0); }
+  GEN(144); DID(1);
+}
+
+int g_mov_ah(byte i)
+{
+  if (i == 0)
+  {
+    return g_xor_ah_ah();
+  }
+  GEN(180); GEN(i); DID(2);
+}
+
+int g_mov_bh(byte i)
+{
+  if (i == 0)
+  {
+    return g_xor_bh_bh();
+  }
+  GEN(0xB7); GEN(i); DID(2);
+}
+
+int g_mov_ch(byte i)
+{
+  if (i == 0)
+  {
+    return g_xor_ch_ch();
+  }
+  GEN(0xB5); GEN(i); DID(2);
+}
+
+int g_mov_dh(byte i)
+{
+  if (i == 0)
+  {
+    return g_xor_dh_dh();
+  }
+  GEN(0xB6); GEN(i); DID(2);
+}
+
+int g_mov_al(byte i)
+{
+  if (i == 0)
+  {
+    return g_xor_al_al();
+  }
+  GEN(176); GEN(i); DID(2);
+}
+
+int g_mov_bl(byte i)
+{
+  if (i == 0)
+  {
+    return g_xor_bl_bl();
+  }
+  GEN(179); GEN(i); DID(2);
+}
+
+int g_mov_cl(byte i)
+{
+  if (i == 0)
+  {
+    return g_xor_cl_cl();
+  }
+  GEN(177); GEN(i); DID(2);
+}
+
+int g_mov_dl(byte i)
+{
+  if (i == 0)
+  {
+    return g_xor_dl_dl();
+  }
+  GEN(0xB2); GEN(i); DID(2);
+}
+
+int g_jz(sbyte i)      { GEN(116); GEN(i); DID(2); }
+int g_jnz(sbyte i)     { GEN(117); GEN(i); DID(2); }
+int g_ja(sbyte i)      { GEN(119); GEN(i); DID(2); }
+int g_jb(sbyte i)      { GEN(114); GEN(i); DID(2); }
+
+int g_and_ah(byte i)     { GEN(128); GEN(228); GEN(i); DID(3); }
+
+int g_mov_ax(word i)
+{
+  if (i == 0)
+  {
+    return g_xor_ax_ax();
+  }
+  GEN(0xB8);
+  GENW(i);
+  DID(3);
+}
+
+int g_mov_bx(word i)
+{
+  if (i == 0)
+  {
+    return g_xor_bx_bx();
+  }
+  GEN(187); GENW(i); DID(3);
+}
+
+int g_mov_cx(word i)
+{
+  if (i == 0)
+  {
+    return g_xor_cx_cx();
+  }
+  GEN(185); GENW(i); DID(3);
+}
+
+int g_mov_dx(word i)
+{
+  if (i == 0)
+  {
+    return g_xor_dx_dx();
+  }
+  GEN(0xBA); GENW(i); DID(3);
+}
+
+byte * g_lambda(void)
+{
+  g_label();
+  return m;
+}
+
+byte * g_close_lambda(byte * l)
+{
+  byte * q = stalloc(m - l);
+  memcpy(q, l, m - l);
+  m = l;
+  return q;
+}

File 1. ILLGOL/src/illgol.c

+/*
+  illgol.c - an ILLGOL to 8086 compiler
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef unsigned char byte;
+typedef unsigned int  word;
+typedef signed   char sbyte;
+typedef signed   int  sword;
+
+#include "static.c"
+#include "8086.c"
+#include "symbol.c"
+#include "runtime.c"
+#include "scan.c"
+#include "parse.c"
+
+int main(int argc, char ** argv)
+{
+  int c = 0;
+  FILE * outf;
+  FILE * inf;
+  char * ofn;
+
+  printf("ILLGOL to 8086 compiler (c)1999 Cat's-Eye Technologies.\n");
+
+  if (argc < 3)
+  {
+    ofn = "out.com";
+  } else
+  {
+    ofn = argv[2];
+  }
+  inf = fopen(argv[1], "r");
+  if (inf == NULL)
+  {
+    char s[128];
+    sprintf(s, "prj\\%s.ill", argv[1]);
+    inf = fopen(s, "r");
+    ofn = (char *)malloc(128);
+    sprintf(ofn, "%s.com", argv[1]);
+  }
+  if (inf != NULL)
+  {
+    outf = fopen(ofn, "wb");
+    if (outf != NULL)
+    {
+      scanfile = inf;
+      m = s;
+      dp = d;
+      sbuffer = stalloc(16);   /* string buffer for str, stf, etc */
+      scan();
+      if(illgol())
+      {
+	/* write jump */
+	char q[16]; int soc = 0; int soh = 0;
+	c = (m - s);
+	q[0] = 0xe9;
+	soc = (dp - d) + 3;
+	soh = soc + 259 + c;
+	q[1] = soc & 0xff;          /* low word of start of code */
+	q[2] = (soc >> 8) & 0xff;   /* high word of start of code */
+	q[3] = 144;                 /* nop to line things up again */
+	q[4] = soh & 0xff;          /* low word of start of heap */
+	q[5] = (soh >> 8) & 0xff;   /* high word of start of heap */
+	fwrite(q, 6, 1, outf);
+	/* write data */
+	/* fprintf(stderr, "Data length: %d\n", (dp - d)); */
+	fwrite(d, (dp - d), 1, outf);
+	/* write c bytes to f */
+	fwrite(s, c, 1, outf);
+	printf("Success, %d bytes written to '%s'\n", (c+(dp-d)+6), ofn);
+      } else
+      {
+	fprintf(stderr, "Failure: could not compile '%s'\n", argv[1]);
+      }
+      fclose(outf);
+      fclose(inf);
+      return 0;
+    }
+    fclose(inf);
+    fprintf(stderr, "Failure: could not open output file '%s'\n", ofn);
+    return 1;
+  }
+  fprintf(stderr, "Failure: could not open input file '%s'\n", argv[1]);
+  return 1;
+}

File 1. ILLGOL/src/parse.c

+/*
+  parse.c for illgol.c
+*/
+
+#define tokeq(x)  (!strcmp(token,x))
+#define tokne(x)  (strcmp(token,x))
+
+int lino = 0;
+byte * seedaddr = NULL;
+byte * sbuffer;
+
+void error(char * s)
+{
+  fprintf(stderr, "Error (token '%s', line %d): %s.\n", token, lino, s);
+}
+
+int member(void)
+{
+  if (token[0] >= '0' && token[0] <= '9')
+  {
+    int v = atoi(token);
+    scan();
+    return v;
+  }
+  if (sym_exists(token))
+  {
+    int c = 0;
+    int v = 0;
+    sym_addr(token, &c, &v);
+    scan();
+    if (c) return v;
+  }
+  error("Unrecognized member");
+  return 0;
+}
+
+void assignment(void);
+void assignments(void);
+void block(void);
+void boolexpr(void);
+void addexpr(void);
+
+void dereference(void)    /* assume address has already been pushed */
+{
+  while(tokeq(".") || tokeq("[") || tokeq("^"))
+  {
+    if(tokeq("."))
+    {
+      scan();
+      g_pop_bx();
+      g_add_bx(member());
+      g_push_bx();
+    }
+    else if(tokeq("["))
+    {
+      scan();
+      addexpr();
+      if(tokeq("]"))
+      {
+	scan();
+	g_pop_ax();
+	g_pop_bx();
+	g_add_bx_ax();
+	g_push_bx();
+      } else
+      {
+	error("Missing ]");
+      }
+    }
+    else if(tokeq("^"))
+    {
+      scan();
+      g_pop_bx();
+      g_mov_ax_BX();
+      g_push_ax();
+    }
+  }
+}
+
+int name(int dcl)
+{
+  if(sym_exists(token) || dcl)
+  {
+    int c = 0;
+    int v = 0;
+    int l = 0;
+    l = caddr(sym_addr(token, &c, &v));
+    scan();
+    g_mov_bx(l);
+    g_push_bx();
+    dereference();
+    return l;
+  } else
+  {
+    error("Expected identifier");
+    return 0;
+  }
+}
+
+void primitive(void)
+{
+  int ptr = 0; /* pointer-to-variable such as in: x = ^y; */
+
+  if(tokeq("call"))
+  {
+    byte * b = m; int l; int c; int v; int a = 0; int i;
+    scan();
+    boolexpr();
+    if(tokeq("("))
+    {
+      scan();
+      a++;
+      boolexpr();
+      g_pop_ax();
+      g_pop_bx();
+      g_push_ax();
+      g_push_bx();
+      while (tokeq(","))
+      {
+	scan();
+	a++;
+	boolexpr();
+	g_pop_ax();
+	g_pop_bx();
+	g_push_ax();
+	g_push_bx();
+      }
+      if(tokeq(")"))
+      {
+	scan();
+      } else
+      {
+	error("Missing )");
+      }
+    }
+    g_pop_bx();
+    g_push_bp();
+    g_mov_ax_sp();
+    g_add_ax(a << 1);
+    g_mov_bp_ax();
+    g_call_bx();
+    g_pop_dx();   /* hang on to returnval */
+    g_pop_bp();
+    for(i=0;i<a;i++)
+    {
+      g_pop_ax();  /* clean up stack arguments */
+    }
+    g_push_dx();
+    return;
+  }
+
+  if(tokeq("sin"))
+  {
+    runtime_trig();
+    scan();
+    boolexpr();
+    g_pop_ax();
+    g_mov_bx(caddr(sin_routine));
+    g_call_bx();
+    g_push_cx();
+    return;
+  }
+
+  if(tokeq("cos"))
+  {
+    runtime_trig();
+    scan();
+    boolexpr();
+    g_pop_ax();
+    g_mov_bx(caddr(cos_routine));
+    g_call_bx();
+    g_push_cx();
+    return;
+  }
+
+  if(tokeq("abs"))
+  {
+    scan();
+    boolexpr();
+    g_pop_ax();
+    g_and_ax(0x7fff);
+    g_push_ax();
+    return;
+  }
+
+  if(tokeq("asc"))
+  {
+    scan();
+    boolexpr();
+    g_pop_ax();
+    g_and_ax(0x007f);
+    g_push_ax();
+    return;
+  }
+
+  if(tokeq("fix"))
+  {
+    scan();
+    boolexpr();
+    g_pop_ax();
+    g_mov_ah_al();
+    g_xor_al_al();
+    g_push_ax();
+    return;
+  }
+
+  if(tokeq("int"))
+  {
+    scan();
+    boolexpr();
+    g_pop_ax();
+    g_mov_al_ah();
+    g_xor_ah_ah();
+    g_push_ax();
+    return;
+  }
+
+  if(tokeq("fre"))
+  {
+    scan();
+    boolexpr();
+    g_pop_ax();
+    g_mov_ax_I(caddr(d)-2);
+    g_neg_ax();
+    g_push_ax();
+    return;
+  }
+
+  if(tokeq("rnd"))
+  {
+    scan();
+    if(tokeq("("))
+    {
+      scan();
+      name(0);
+      if(tokeq(")"))
+      {
+	scan();
+      } else error("Missing )");
+    } else
+    {
+      error("Need identifier in rnd()");
+    }
+    g_pop_bx();
+    g_mov_ax_BX();
+    g_mov_dx(58653U);
+    g_imul_dx();
+    g_mov_dx(13849U);
+    g_add_ax_dx();
+    g_mov_BX_ax();
+    g_push_ax();
+    return;
+  }
+
+  if(tokeq("stu"))
+  {
+    scan();
+    boolexpr();
+    g_pop_ax();
+    g_mov_bx(caddr(sbuffer + 14));
+    g_label(); g_xor_dx_dx();
+    g_mov_cx(10);
+    g_idiv_cx();
+    g_add_dx('0');
+    g_mov_BX_dl();
+    g_dec_bx();
+    g_or_ax_ax();
+    g_jnz(-18);
+    g_inc_bx();
+    g_push_bx();
+    return;
+  }
+
+  if(tokeq("str"))
+  {
+    scan();
+    boolexpr();
+    g_pop_ax();
+    g_push_ax();
+    g_cmp_ax(0);
+    g_jg(+2);
+    g_neg_ax();
+    g_label(); g_mov_bx(caddr(sbuffer + 14));
+    g_label(); g_xor_dx_dx();
+    g_mov_cx(10);
+    g_idiv_cx();
+    g_add_dx('0');
+    g_mov_BX_dl();
+    g_dec_bx();
+    g_or_ax_ax();
+    g_jnz(-18);
+    g_pop_ax();
+    g_cmp_ax(0);
+    g_jge(+5);
+    g_mov_al('-');
+    g_mov_BX_al();
+    g_dec_bx();
+    g_label(); g_inc_bx();
+    g_push_bx();
+    return;
+  }
+
+  if(tokeq("sif"))
+  {
+    scan();
+    boolexpr();
+
+    g_pop_ax();
+    g_push_ax();
+    g_xor_ah_ah();
+    g_mov_dx(39);
+    g_imul_dx();
+    /* g_mov_al_ah();
+    g_mov_ah_dl(); */
+
+    g_mov_bx(caddr(sbuffer + 14));
+    g_mov_cx(10);
+    g_label(); g_xor_dx_dx();
+    g_idiv_cx();
+    g_add_dx('0');
+    g_mov_BX_dl();
+    g_dec_bx();
+    g_cmp_bx(caddr(sbuffer + 10));
+    g_jnz(-17);
+
+    g_mov_dx('.');
+    g_mov_BX_dl();
+    g_dec_bx();
+
+    g_pop_ax();
+    g_mov_al_ah();
+    g_xor_ah_ah();
+
+    g_label(); g_xor_dx_dx();
+    g_idiv_cx();
+    g_add_dx('0');
+    g_mov_BX_dl();
+    g_dec_bx();
+    g_or_ax_ax();
+    g_jnz(-15);
+    g_inc_bx();
+
+    g_push_bx();
+
+    return;
+  }
+
+  if(tokeq("^"))
+  {
+    scan(); ptr = 1;
+  }
+  if(tokeq("#"))
+  {
+    scan();
+    if (tokeq("("))
+    {
+      scan();
+      boolexpr();
+      if (tokeq(")"))
+      {
+	scan();
+	g_pop_ax();
+	g_shl_ax_1();
+	g_neg_ax();
+	g_xchg_si_ax();
+	g_mov_ax_BP_SI();
+	g_push_ax();
+	return;
+      }
+      error("Missing )");
+      return;
+    }
+    g_mov_ax_BP(-2 * member());
+    g_push_ax();
+    return;
+  }
+  if(sym_exists(token))
+  {
+    name(0);
+    if (!ptr)
+    {
+      g_pop_bx();
+      g_push_BX();
+      if (tokeq("++"))
+      {
+	scan();
+	g_mov_ax_BX();
+	g_inc_ax();
+	g_mov_BX_ax();
+      }
+      if (tokeq("--"))
+      {
+	scan();
+	g_mov_ax_BX();
+	g_dec_ax();
+	g_mov_BX_ax();
+      }
+    }
+    return;
+  }
+  if (ptr)
+  {
+    error("Identifier should follow ^");
+  }
+  if(token[0] >= '0' && token[0] <= '9')
+  {
+    int v = atoi(token);
+    g_mov_ax(v);
+    g_push_ax();
+    scan();
+    if (tokeq("."))
+    {
+      scan();
+      while(strlen(token) < 4)
+      {
+	strcat(token, "0");
+      }
+      v = atoi(token) / 39;
+      scan();
+      if (v > 255) v = 255;
+      g_pop_ax();
+      g_mov_ah_al();
+      g_mov_al(v & 0xff);
+      g_push_ax();
+    }
+    return;
+  }
+  if(token[0] == '"')
+  {
+    char * q = (token+1);
+    byte * b = stalloc(strlen(q)+1);
+    strcpy((char *)b, q);
+    g_mov_ax(caddr(b));
+    g_push_ax();
+    scan();
+    while(token[0] == '"')
+    {
+      char * q = (token+1);
+      byte * b;
+      stretract();
+      b = stalloc(strlen(q)+1);
+      strcpy((char *)b, q);
+      scan();
+    }
+    return;
+  }
+  if(tokeq("{"))
+  {
+    byte * l; byte * q; int c=0; int v=0; int lc;
+    scan();
+    l = m;    /* this is our lambda function */
+    g_label();
+    g_nop();
+    assignments();
+    if (tokeq("}"))
+    {
+      scan();
+      g_ret();
+      /* move it to the data area... */
+      q = stalloc(m - l);
+      memcpy(q, l, m - l);
+      m = l;
+      g_mov_ax(caddr(q));
+      g_push_ax();
+      return;
+    }
+    error("Missing }");
+    return;
+  }
+  if(tokeq("("))
+  {
+    scan();
+    boolexpr();
+    if (tokeq(")"))
+    {
+      scan();
+      return;
+    }
+    error("Missing )");
+    return;
+  }
+  if(tokeq("*"))
+  {
+    scan();
+    boolexpr();
+    /* gen code to allocate that many bytes */
+    g_mov_bx(260);
+    g_mov_ax_BX();
+    g_pop_dx();
+    g_push_ax();
+    g_add_ax_dx();
+    g_mov_BX_ax();
+    return;
+  }
+  error("Unrecognized primitive");
+}
+
+void factor(void)
+{
+  primitive();
+  while(tokeq(">>") || tokeq("<<"))
+  {
+    char x = token[0];
+    scan();
+    primitive();
+    if (x == '>')
+    {
+      g_pop_cx();
+      g_pop_ax();
+      g_shr_ax_cl();
+      g_push_ax();
+    }
+    if (x == '<')
+    {
+      g_pop_cx();
+      g_pop_ax();
+      g_shr_ax_cl();
+      g_push_ax();
+    }
+  }
+}
+
+void term(void)
+{
+  int fixed = 0;
+  factor();
+  while(tokeq("*") || tokeq("/"))
+  {
+    char x = token[0];
+    scan();
+    if (tokeq("."))
+    {
+      fixed = 1;
+      scan();
+    }
+    factor();
+    if(x == '*')
+    {
+      g_pop_ax();
+      g_pop_dx();
+      g_imul_dx();
+      if (fixed)
+      {
+	g_mov_al_ah();
+	g_mov_ah_dl();
+      }
+      g_push_ax();
+    }
+    if(x == '/')
+    {
+      g_pop_ax();
+      g_pop_cx();
+      g_xor_dx_dx();
+      if (fixed)
+      {
+	g_mov_dl_ah();
+	g_mov_ah_al();
+	g_xor_al_al();
+      }
+      g_idiv_cx();
+      g_push_ax();
+    }
+  }
+}
+
+void addexpr(void)
+{
+  term();
+  while(tokeq("+") || tokeq("-"))
+  {
+    char x = token[0];
+    scan();
+    term();
+    if(x == '+')
+    {
+      g_pop_ax();
+      g_pop_dx();
+      g_add_ax_dx();
+      g_push_ax();
+    }
+    if(x == '-')
+    {
+      g_pop_dx();
+      g_pop_ax();
+      g_sub_ax_dx();
+      g_push_ax();
+    }
+  }
+}
+
+void compexpr(void)
+{
+  char x, y;
+  addexpr();
+  while(tokeq("=") || tokeq("<>") || tokeq(">") ||
+	tokeq(">=") || tokeq("<") || tokeq("<="))
+  {
+    x = token[0]; y = token[1];
+    scan();
+    addexpr();
+    if(x == '=')
+    {
+      g_pop_ax();
+      g_pop_dx();
+      g_sub_ax_dx();
+      g_jz(+3);
+      g_xor_ax_ax();
+      g_dec_ax();
+      g_label(); g_inc_ax();
+      g_push_ax();
+    }
+    if(x == '<' && y == '>')
+    {
+      g_pop_ax();
+      g_pop_dx();
+      g_xor_cx_cx();
+      g_sub_ax_dx();
+      g_jz(+1);
+      g_inc_cx();
+      g_label(); g_push_cx();
+    }
+    if(x == '<' && y == 0)
+    {
+      g_pop_dx();
+      g_pop_ax();
+      g_xor_cx_cx();
+      g_cmp_ax_dx();
+      g_jge(+1);
+      g_inc_cx();
+      g_label(); g_push_cx();
+    }
+    if(x == '>' && y == 0)
+    {
+      g_pop_dx();
+      g_pop_ax();
+      g_xor_cx_cx();
+      g_cmp_ax_dx();
+      g_jle(+1);
+      g_inc_cx();
+      g_label(); g_push_cx();
+    }
+    if(x == '<' && y == '=')
+    {
+      g_pop_dx();
+      g_pop_ax();
+      g_xor_cx_cx();
+      g_cmp_ax_dx();
+      g_jg(+1);
+      g_inc_cx();
+      g_label(); g_push_cx();
+    }
+    if(x == '>' && y == '=')
+    {
+      g_pop_dx();
+      g_pop_ax();
+      g_xor_cx_cx();
+      g_cmp_ax_dx();
+      g_jl(+1);
+      g_inc_cx();
+      g_label(); g_push_cx();
+    }
+  }
+}
+
+void negexpr(void)
+{
+  if(tokeq("!"))
+  {
+    scan(); /* generate boolean not */
+    compexpr();
+    g_pop_ax();
+    g_or_ax_ax();
+    g_jz(+3);
+    g_xor_ax_ax();
+    g_dec_ax();
+    g_inc_ax();
+    g_push_ax();
+  } else
+  if(tokeq("?"))
+  {
+    scan(); /* generate boolean buffer */
+    compexpr();
+    g_pop_ax();
+    g_xor_bx_bx();
+    g_or_ax_ax();
+    g_jz(+1);
+    g_inc_bx();
+    g_push_bx();
+  } else
+  {
+    compexpr();
+  }
+}
+
+void boolexpr(void)
+{
+  negexpr();
+  while(tokeq("&") || tokeq("|") || tokeq("~"))
+  {
+    char x = token[0];
+    scan();
+    negexpr();
+    if(x == '&')
+    {
+      g_pop_ax();
+      g_pop_dx();
+      g_and_ax_dx();
+      g_push_dx();
+    }
+    if(x == '|')
+    {
+      g_pop_ax();
+      g_pop_dx();
+      g_or_ax_dx();
+      g_push_dx();
+    }
+    if(x == '~')
+    {
+      g_pop_ax();
+      g_pop_dx();
+      g_xor_ax_dx();
+      g_push_dx();
+    }
+  }
+}
+
+void fullmoonfever(void)
+{
+  int ok = 1;
+  while(ok)
+  {
+    /* error("FMF"); */
+    if(tokeq("GO"))
+    {
+      scan();
+      boolexpr();
+      boolexpr();
+      g_pop_ax();
+      g_pop_dx();
+      g_mov_dh_al();
+      g_mov_ah(2);
+      g_xor_bx_bx();
+      g_int(0x10);
+    }
+    else if(tokeq("PRINT"))
+    {
+      scan();
+      boolexpr();
+      g_pop_si();