/********************************************************************
*
*
*  HCS II XPRESS Compiler
*
*  Version 4.10
*
*  June 15, 2000
*
*    Copyright (C) 2001  Circuit Cellar Incorporated
*                        4 Park St.
*                        Vernon, CT 06066
*
*                        steve@circuitcellar.com;
*
*   This program is free software; you can redistribute it and/or
*   modify it under the terms of the GNU General Public License
*   as published by the Free Software Foundation; either version 2
*   of the License, or (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program; if not, write to the Free Software
*   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
*
*  Copyright (c) 1999-2000, Creative Control Concepts
*  Copyright (c) 1992-1998, Circuit Cellar Inc.
*
*
*	Version 4.10 -- June 15, 2000				-- Add support for Stat-Link HVAC Interface
*
*	Version 4.01 -- May 1, 2000				-- Add support for CID Name via %N string flag
*								-- Add support for CID Num via %M string flag
*								-- Add support for %S fixed size value flag
*	Version 4.00 -- January 5, 2000				-- Version Increment
*	Version 3.63 -- December 25, 1999			-- Version Increment
*	Version 3.62 -- August 25, 1999
*								-- Fix 8th Module bug so 8 of each can be used
*								-- Added more detailed error messages
*	Version 3.60 -- March 10, 1998
*								-- Version change to match update
*
*	Version 3.50 -- April 7, 1997
*								-- Final Answer MAN support
*
*	Version 3.05 -- November 3, 1996
*								-- Answer MAN support
*
*	Version 3.01 -- May 8, 1995
*								-- Version change to match update
*
*	Version 3.00 -- March 16, 1995
*								-- Release version
*
*	Version 2.70 -- Version change to match rest of release
*	Version 2.69 -- Added power fail stuff
*	Version 2.68 -- Added network module display bitmaps, network string out
*	Version 2.67 -- Added embedded version, LogSize, and NetByte
*	Version 2.66 -- Added analog I/O and netbit display bitmaps
*	Version 2.65 -- Version number change to match rest of beta release
*	Version 2.64 -- Added more modem and Caller ID stuff
*	Version 2.63 -- Added Caller ID stuff
*	Version 2.62 -- Added CONSOLE stuff
*	Version 2.61 -- Beta release to match rest of suite
*								-- Upped IF/END array size
*
*	Version 2.55	-- May 18, 1994
*								-- Cleaned up CS support for initial beta
*	Version 2.50 -- First pass at CS support
*
*	Version 2.10 -- December 20, 1993
*								-- Release version
*
*	Version 2.00 -- March 3, 1993
*								-- Release version
*
*	Version 1.20 -- November 12, 1992
*								-- Added MCIR support
*								-- Added TV-Link support
*								-- Fix GIF bug
*								-- Fix tab bug
*								-- Increase labels to 512
*
*  Version 1.00 -- March 1992
*								-- Release version
*
*
*********************************************************************/  
  
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
  
#define true    1
#define false   0
  
#define maxtmr	127
#define maxvar  127
#define maxinp  207
#define maxout  207
#define maxadc	135
#define maxdac  31
#define maxif		1024
  
#define bell    0x07
#define cr      0x0d
#define esc     0x1b
  FILE * fp, *outp;

int version = 410;		/* Low two digits must be minor version number */

int linenum = 1, errors = 0;
int numpl = 0, numir = 0, numlcd = 0;
int numdio = 0, numaman = 0, numdiop = 0, sc = 0;
int adcres = 8, adcchan = 8;
int adcgain[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int digin[4] = { 0, 0, 0, 0 }, digout[4] =
{
0, 0, 0, 0};
int anain[3] = { 0, 0, 0 }, anaout[1] =
{
0};
int netbits[5] = { 0, 0, 0, 0, 0 }, netmod[1] =
{
0};
int proc_eqn = false, eqn_end = false;
int lparens = 0, eparens = 0;
int sequence = false;

unsigned int iftable[maxif][3], ifctr = 0, bytectr = 0;
unsigned int ifcount = 0, endcount = 0;

unsigned int house_used = 0, checksum = 0;

char label[512][32], def[512][32];
char *sptr, substring[128];

int
open_files (char *input, char *output) 
{
  if ((fp = fopen (input, "r")) == NULL)
    {
      printf ("\nInput file %s not found", input);
      errors++;
      return 1;
    }
  
if ((outp = fopen (output, "wb+")) == NULL)
    {
      printf ("\nOutput file %s could not be created", output);
      errors++;
      return 1;
    }
  
return 0;
}

void
close_files (void) 
{
  fclose (outp);
  fclose (fp);
}

void
out_file (char ch) 
{
  int i;
  
fputc (ch, outp);
  checksum += (int) ch;
  bytectr++;
  
for (i = 0; i < maxif; i++)
    if (iftable[i][0])
      iftable[i][2]++;
}

void
out_file_no_check (char ch) 
{
  fputc (ch, outp);
}

char
get_ch (void) 
{
  if (*sptr)
    return *sptr++;
  
  else
    return fgetc (fp);
}

void
unget_ch (char ch) 
{
  if (*sptr)
    *sptr--;
  
  else
    ungetc (ch, fp);
}

void
replace (char *st) 
{
  int i;
  
for (i = 0; *def[i]; i++)
    {
      if (strcmp (st, label[i]))
	continue;
      strcpy (substring, def[i]);
      sptr = substring;
      read_word (st);
      break;
    }
}

int
read_word (char *st) 
{
  char ch, *local;
  int done = false, lead = true;
  
local = st;
  
while (!done && ((ch = toupper (get_ch ())) != EOF))
    {
      switch (ch)
	{
	case '!':
	  while (get_ch () != '\n')
	    {
	    }
	  if (proc_eqn)
	    if (lead)
	      {
		*st++ = '\n';
		eqn_end = true;
		done = true;
	      }
	  
	    else
	      {
		unget_ch ('\n');
		eqn_end = true;
		done = true;
	      }
	  
	  else
	    linenum++;
	  break;
	case '\t':
	case ',':
	case ' ':
	  if (lead)
	    break;
	  
	  else
	    {
	      done = true;
	      break;
	    }
	case '\n':
	  linenum++;
	case ';':
	  if (proc_eqn)
	    if (lead)
	      {
		*st++ = ch;
		if (ch == '\n')
		  {
		    unget_ch (ch);
		    linenum--;
		  }
		eqn_end = true;
		done = true;
		break;
	      }
	  
	    else
	      {
		unget_ch (ch);
		if (ch == '\n')
		  linenum--;
		eqn_end = true;
		done = true;
		break;
	      }
	  
	  else
	  if (lead)
	    break;
	  
	  else
	    {
	      unget_ch (ch);
	      if (ch == '\n')
		linenum--;
	      done = true;
	      break;
	    }
	case '+':
	case '-':
	case '*':
	case '/':
	  if (proc_eqn)
	    if (lead)
	      {
		*st++ = ch;
		done = true;
		break;
	      }
	  
	    else
	      {
		unget_ch (ch);
		done = true;
		break;
	      }
	  
	  else
	    {
	      *st++ = ch;
	      lead = false;
	      break;
	    }
	case ':':
	case '"':
	case '(':
	case ')':
	  if (lead)
	    {
	      *st++ = ch;
	      done = true;
	      break;
	    }
	  
	  else
	    {
	      unget_ch (ch);
	      done = true;
	      break;
	    }
	case '>':
	case '<':
	case '=':
	  if (lead)
	    {
	      *st++ = ch;
	      ch = toupper (get_ch ());
	      if ((ch == '>') || (ch == '<') || (ch == '='))
		{
		  *st++ = ch;
		  done = true;
		  break;
		}
	      
	      else
		{
		  unget_ch (ch);
		  done = true;
		  break;
		}
	    }
	  
	  else
	    {
	      unget_ch (ch);
	      done = true;
	      break;
	    }
	default:
	  if (iscntrl (ch))
	    break;
	  *st++ = ch;
	  lead = false;
	}
    }
  *st = '\000';
  
replace (local);
  
return !feof (fp);
}

int
read_line (char *st) 
{
  char ch;
  int done = false;
  
while (!done && ((ch = toupper (fgetc (fp))) != EOF))
    {
      switch (ch)
	{
	case '!':
	  unget_ch (ch);
	  done = true;
	  break;
	case '\n':
	  linenum++;
	  done = true;
	  break;
	default:
	  if (iscntrl (ch))
	    break;
	  *st++ = ch;
	}
    }
  *st = '\000';
  
return !feof (fp);
}

int
read_string (char *st) 
{
  char ch;
  int done = false;
  
while (!done && ((ch = fgetc (fp)) != EOF))
    {
      switch (ch)
	{
	case '"':
	  done = true;
	  break;
	case '\n':
	  linenum++;
	  done = true;
	  break;
	default:
	  if (iscntrl (ch))
	    break;
	  *st++ = ch;
	}
    }
  *st = '\000';
  
return !feof (fp);
}



/* 990825 MB - New Error Messages with more detailed info */ 
  void
nsyn_error (char *err, char *msg) 
{
  printf ("\n* Syntax error in line %i: \"%s\" ", linenum, err);
  printf ("\n  - %s ", msg);
  errors++;
}

void
nval_error (char *err, char *msg) 
{
  printf ("\n* Illegal value in line %i: \"%s\" ", linenum, err);
  printf ("\n  - %s", msg);
  errors++;
}

void
syn_error (char *err) 
{
  printf ("\n* Syntax error in line %i: \"%s\" ", linenum, err);
  errors++;
}

void
val_error (char *err) 
{
  printf ("\n* Illegal value in line %i: \"%s\" ", linenum, err);
  errors++;
}

void
if_error (void) 
{
  printf ("\n* Too many IFs at line %i", linenum);
  errors++;
}

void
paren_error (void) 
{
  printf ("\n* Parentheses mismatch in line %i.", linenum);
  errors++;
}

int
bcd (int num) 
{
  return (((num / 10) * 16) + (num % 10));
}

void
Process_Operator (int *res) 
{
  char *keyp, keyw[80];
  
keyp = keyw;
  
read_word (keyp);
  if (!strcmp (keyp, "="))
    *res = 0x01;
  
  else if (!strcmp (keyp, "<>"))
    *res = 0x02;
  
  else if (!strcmp (keyp, "><"))
    *res = 0x02;
  
  else if (!strcmp (keyp, ">"))
    *res = 0x03;
  
  else if (!strcmp (keyp, "<"))
    *res = 0x04;
  
  else if (!strcmp (keyp, ">="))
    *res = 0x05;
  
  else if (!strcmp (keyp, "=>"))
    *res = 0x05;
  
  else if (!strcmp (keyp, "<="))
    *res = 0x06;
  
  else if (!strcmp (keyp, "=<"))
    *res = 0x06;
  
  else
    syn_error (keyp);
}

void
Process_Operand (int *res) 
{
  int num;
  char *keyp, keyw[80];
  
keyp = keyw;
  
read_word (keyp);
  
if (!strcmp (keyp, "VARIABLE"))
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > maxvar))
	val_error (keyp);
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x30;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "ADC"))
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > maxadc))
	nval_error (keyp, "Invalid ADC ID");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x31;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "TIMER"))
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > maxtmr))
	nval_error (keyp, "Invalid Timer ID");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x32;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "IRCODE"))
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > 511))
	nval_error (keyp, "Valid IR Codes are 0-511");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 3;
      res[1] = 0x33;
      res[2] = num % 256;
      res[3] = num / 256;
    }
  
  else if (!strcmp (keyp, "TRUE"))
    {
      res[0] = 1;
      res[1] = 0x36;
    }
  
  else if (!strcmp (keyp, "ON"))
    {
      res[0] = 1;
      res[1] = 0x36;
    }
  
  else if (!strcmp (keyp, "FALSE"))
    {
      res[0] = 1;
      res[1] = 0x37;
    }
  
  else if (!strcmp (keyp, "OFF"))
    {
      res[0] = 1;
      res[1] = 0x37;
    }
  
  else if (!strcmp (keyp, "RANDOM"))
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > 255))
	nval_error (keyp, "RANDOM value should be 0-255");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x38;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "MONTH"))
    {
      res[0] = 1;
      res[1] = 0x39;
    }
  
  else if (!strcmp (keyp, "DAY"))
    {
      res[0] = 1;
      res[1] = 0x3A;
    }
  
  else if (!strcmp (keyp, "YEAR"))
    {
      res[0] = 1;
      res[1] = 0x3B;
    }
  
  else if (!strcmp (keyp, "DOW"))
    {
      res[0] = 1;
      res[1] = 0x3C;
    }
  
  else if (!strcmp (keyp, "HOUR"))
    {
      res[0] = 1;
      res[1] = 0x3D;
    }
  
  else if (!strcmp (keyp, "MINUTE"))
    {
      res[0] = 1;
      res[1] = 0x3E;
    }
  
  else if (!strcmp (keyp, "SECOND"))
    {
      res[0] = 1;
      res[1] = 0x3F;
    }
  
  else if (!strcmp (keyp, "DTMFDIGIT") & sequence)
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > 255))
	nval_error (keyp, "Expecting value between 0 and 255");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x40;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "DTMFNUMBER") & sequence)
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > 255))
	nval_error (keyp, "Expecting value between 0 and 255");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x41;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "RINGS"))
    {
      res[0] = 1;
      res[1] = 0x42;
    }
  
  else if (!strcmp (keyp, "DIALTONE") & sequence)
    {
      res[0] = 1;
      res[1] = 0x43;
    }
  
  else if (!strcmp (keyp, "CALLPROGRESS") & sequence)
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > 255))
	nval_error (keyp, "Expecting CALLPROGRESS value between 0 and 255");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x44;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "CIDNEW"))
    {
      res[0] = 1;
      res[1] = 0x45;
    }
  
  else if (!strcmp (keyp, "CIDMONTH"))
    {
      res[0] = 1;
      res[1] = 0x46;
    }
  
  else if (!strcmp (keyp, "CIDDAY"))
    {
      res[0] = 1;
      res[1] = 0x47;
    }
  
  else if (!strcmp (keyp, "CIDHOUR"))
    {
      res[0] = 1;
      res[1] = 0x48;
    }
  
  else if (!strcmp (keyp, "CIDMINUTE"))
    {
      res[0] = 1;
      res[1] = 0x49;
    }
  
  else if (!strcmp (keyp, "CIDAREA"))
    {
      res[0] = 1;
      res[1] = 0x4A;
    }
  
  else if (!strcmp (keyp, "CIDEXCH"))
    {
      res[0] = 1;
      res[1] = 0x4B;
    }
  
  else if (!strcmp (keyp, "CIDNUMBER"))
    {
      res[0] = 1;
      res[1] = 0x4C;
    }
  
  else if (!strcmp (keyp, "LOGSIZE"))
    {
      res[0] = 1;
      res[1] = 0x4D;
    }
  
  else if (!strcmp (keyp, "NETBYTE"))
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > 40))
	nval_error (keyp, "Expecting NETBYTE value between 0 and 40");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x4E;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "ACPOWER"))
    {
      res[0] = 1;
      res[1] = 0x4F;
    }
  
  else if (!strcmp (keyp, "ACFAILED"))
    {
      res[0] = 1;
      res[1] = 0x50;
    }
  
  else if (!strcmp (keyp, "FREQUENCY"))
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > 7))
	nval_error (keyp, "Expecting FREQUENCY value between 0 and 7");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x51;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "TOTAL"))
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > 7))
	nval_error (keyp, "Expecting TOTAL value between 0 and 7");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x52;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "KEYDIGIT"))
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > 7))
	nval_error (keyp, "Expecting KEYDIGIT value between 0 and 7");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x53;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "KEYNUMBER"))
    {
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num < 0) || (num > 7))
	nval_error (keyp, "Expecting KEYNUMBER value between 0 and 7");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
      
res[0] = 2;
      res[1] = 0x54;
      res[2] = num;
    }
  
  else if (!strcmp (keyp, "("))
    {
      eparens++;
      res[0] = 1;
      res[1] = 0x70;
    }
  
  else if (!strcmp (keyp, ")"))
    {
      eparens--;
      res[0] = 1;
      res[1] = 0x71;
    }
  
  else if (!strcmp (keyp, "+"))
    {
      res[0] = 1;
      res[1] = 0x75;
    }
  
  else if (!strcmp (keyp, "-"))
    {
      res[0] = 1;
      res[1] = 0x76;
    }
  
  else if (!strcmp (keyp, "*"))
    {
      res[0] = 1;
      res[1] = 0x77;
    }
  
  else if (!strcmp (keyp, "/"))
    {
      res[0] = 1;
      res[1] = 0x78;
    }
  
  else if (!strcmp (keyp, ";") || !strcmp (keyp, "\n"))
    {
      res[0] = 0;
    }
  
  else if (isdigit (keyp[0]))
    {
      num = atoi (keyp);
      if ((num < 0) || (num > 32767))
	nval_error (keyp, "Integer values must be between 0 and 32767");
      
if (num < 256)
	{
	  res[0] = 2;
	  res[1] = 0x34;
	  res[2] = num;
	}
      
      else
	{
	  res[0] = 3;
	  res[1] = 0x35;
	  res[2] = num % 256;
	  res[3] = num / 256;
	}
    }
  
  else
    nval_error (keyp, "Invalid Operand");
}

void
Process_Equation (void) 
{
  int i, operand[5];
  
proc_eqn = true;
  eqn_end = false;
  eparens = 0;
  
while (!eqn_end)
    {
      Process_Operand (operand);
      for (i = 1; i <= operand[0]; i++)
	out_file (operand[i]);
    }
  
proc_eqn = false;
  eqn_end = false;
  
if (eparens)
    paren_error ();
}

void
dotime (void) 
{
  char *keyp, keyw[80];
  int hour;
  
keyp = keyw;
  
read_word (keyp);
  if (!strcmp (keyp, "="))
    out_file (0x10);
  
  else if (!strcmp (keyp, "<>"))
    out_file (0x11);
  
  else if (!strcmp (keyp, "><"))
    out_file (0x11);
  
  else if (!strcmp (keyp, ">"))
    out_file (0x12);
  
  else if (!strcmp (keyp, "<"))
    out_file (0x13);
  
  else if (!strcmp (keyp, ">="))
    out_file (0x14);
  
  else if (!strcmp (keyp, "=>"))
    out_file (0x14);
  
  else if (!strcmp (keyp, "<="))
    out_file (0x15);
  
  else if (!strcmp (keyp, "=<"))
    out_file (0x15);
  
  else
    nsyn_error (keyp, "Unknown or missing operator");
  
read_word (keyp);
  hour = bcd (atoi (keyp));
  
read_word (keyp);
  if (strcmp (keyp, ":"))
    nsyn_error (keyp, "Expecting \":\"");
  
read_word (keyp);
  out_file (bcd (atoi (keyp)));
  out_file (hour);
  
read_word (keyp);
  if (strcmp (keyp, ":"))
    nsyn_error (keyp, "Expecting \":\"");
  
read_word (keyp);
  if (!strcmp (keyp, "DY"))
    out_file (0x00);
  
  else if (!strcmp (keyp, "SU"))
    out_file (0x01);
  
  else if (!strcmp (keyp, "MO"))
    out_file (0x02);
  
  else if (!strcmp (keyp, "TU"))
    out_file (0x03);
  
  else if (!strcmp (keyp, "WE"))
    out_file (0x04);
  
  else if (!strcmp (keyp, "TH"))
    out_file (0x05);
  
  else if (!strcmp (keyp, "FR"))
    out_file (0x06);
  
  else if (!strcmp (keyp, "SA"))
    out_file (0x07);
  
  else if (!strcmp (keyp, "WK"))
    out_file (0x08);
  
  else if (!strcmp (keyp, "EN"))
    out_file (0x09);
  
  else
    nsyn_error (keyp,
		 "Unknown or missing day of week [SU,MO,TU,WE,TH,FR,SA,DY,WK,EN]");
}

void
doibutton (void) 
{
  char *keyp, keyw[80];
  int i, num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 7))
    nval_error (keyp, "Expecting Node Value between 0 and 7");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (!strcmp (keyp, "="))
    out_file (0x23);
  
  else
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (num);
  
for (i = 0; i < 8; i++)
    {
      read_word (keyp);
      num = atoi (keyp);
      out_file (0x34);
      out_file (num);
    }

}

void
doircode (void) 
{
  char *keyp, keyw[80];
  int num, i, op, secondop[5];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 511))
    nval_error (keyp, "Valid IR Codes are 0-511");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x33);
  out_file (num % 256);
  out_file (num / 256);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
doinput (void) 
{
  char *keyp, keyw[80];
  int input;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  input = atoi (keyp);
  if ((input < 0) || (input > maxinp))
    nval_error (keyp, "Invalid INPUT ID/Reference");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
read_word (keyp);
  if (!strcmp (keyp, "ON"))
    out_file (0x17);
  
  else if (!strcmp (keyp, "OFF"))
    out_file (0x18);
  
  else if (!strcmp (keyp, "EDGE"))
    out_file (0x19);
  
  else
    nsyn_error (keyp, "Expecting ON, OFF, or EDGE");
  
out_file (input % 256);
  out_file (input / 256);
}

void
dooutput (void) 
{
  char *keyp, keyw[80];
  int output;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  output = atoi (keyp);
  if ((output < 0) || (output > maxout))
    nval_error (keyp, "Invalid OUTPUT ID/Reference");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
read_word (keyp);
  if (!strcmp (keyp, "ON"))
    out_file (0x1D);
  
  else if (!strcmp (keyp, "OFF"))
    out_file (0x1E);
  
  else
    nsyn_error (keyp, "Expecting ON or OFF");
  
out_file (output);
}

void
donetbit (void) 
{
  char *keyp, keyw[80];
  int net;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  net = atoi (keyp);
  if ((net < 0) || (net > 511))
    nval_error (keyp, "Expecting NetBit Value between 0 and 511");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
read_word (keyp);
  if (!strcmp (keyp, "ON"))
    out_file (0x1A);
  
  else if (!strcmp (keyp, "OFF"))
    out_file (0x1B);
  
  else if (!strcmp (keyp, "EDGE"))
    out_file (0x1C);
  
  else
    nsyn_error (keyp, "Expecting ON, OFF, or EDGE");
  
out_file (net % 256);
  out_file (net / 256);
}

void
doadc (void) 
{
  char *keyp, keyw[80];
  int num, i, op, secondop[5];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > maxadc))
    nval_error (keyp, "Invalid ADC Reference/ID");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x31);
  out_file (num);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dotimer (void) 
{
  char *keyp, keyw[80];
  int num, i, op, secondop[5];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > maxtmr))
    nval_error (keyp, "Invalid Timer");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
if (secondop[1] == 0x36)
    {
      out_file (0x21);
      out_file (num);
    }
  
  else if (secondop[1] == 0x37)
    {
      out_file (0x22);
      out_file (num);
    }
  
  else
    {
      out_file (op);
      out_file (0x32);
      out_file (num);
      
for (i = 1; i <= secondop[0]; i++)
	out_file (secondop[i]);
    }
}

void
domodule (void) 
{
  char *keyp, keyw[80], modlet;
  int modnum;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  modlet = *keyp++;
  modnum = atoi (keyp);
  if ((modlet < 'A') || (modlet > 'P'))
    nval_error (keyp, "Invalid X10 House Code - should be A-P");
  if ((modnum < 1) || (modnum > 16))
    nval_error (keyp, "Invalid X10 Unit Code - should be 1-16");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
read_word (keyp);
  if (!strcmp (keyp, "ON"))
    out_file (0x1F);
  
  else if (!strcmp (keyp, "OFF"))
    out_file (0x20);
  
  else
    nsyn_error (keyp, "Expecting ON or OFF");
  
out_file (modlet);
  out_file (modnum);
}

void
dovariable (void) 
{
  char *keyp, keyw[80];
  int num, i, op, secondop[5];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > maxvar))
    nval_error (keyp, "Invalid variable reference");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x30);
  out_file (num);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
domonth (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x39);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
doday (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x3A);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
doyear (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x3B);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dodow (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x3C);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dohour (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x3D);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dominute (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x3E);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dosecond (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x3F);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dorings (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x42);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dodtone (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x43);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
docprog (void) 
{
  char *keyp, keyw[80];
  int num, i, op, secondop[5];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 255))
    nval_error (keyp, "Expecting value between 0 and 255");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x44);
  out_file (num);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
docidnew (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x45);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
docidmon (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x46);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
docidday (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x47);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
docidhour (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x48);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
docidmin (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x49);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
docidarea (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x4A);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
docidexch (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x4B);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
docidnum (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x4C);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dologsize (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x4D);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
donetbyte (void) 
{
  char *keyp, keyw[80];
  int num, i, op, secondop[5];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 40))
    nval_error (keyp, "Expecting NetByte ID between 0 and 40");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x4E);
  out_file (num);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
doacpower (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x4F);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
doacfailed (void) 
{
  int i, op, secondop[5];
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x50);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dofreq (void) 
{
  char *keyp, keyw[80];
  int num, i, op, secondop[5];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 7))
    nval_error (keyp, "Expecting value between 0 and 7");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x51);
  out_file (num);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dototal (void) 
{
  char *keyp, keyw[80];
  int num, i, op, secondop[5];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 7))
    nval_error (keyp, "Expecting value between 0 and 7");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x52);
  out_file (num);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dokeydigit (void) 
{
  char *keyp, keyw[80];
  int num, i, op, secondop[5];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 7))
    nval_error (keyp, "Expecting value between 0 and 7");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x53);
  out_file (num);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dokeynumber (void) 
{
  char *keyp, keyw[80];
  int num, i, op, secondop[5];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 7))
    nval_error (keyp, "Expecting value between 0 and 7");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
Process_Operator (&op);
  
Process_Operand (secondop);
  
out_file (op);
  out_file (0x54);
  out_file (num);
  
for (i = 1; i <= secondop[0]; i++)
    out_file (secondop[i]);
}

void
dothentmr (void) 
{
  char *keyp, keyw[80];
  int timer;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  timer = atoi (keyp);
  if ((timer < 0) || (timer > maxtmr))
    nval_error (keyp, "Invalid Timer ID");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
read_word (keyp);
  if (!strcmp (keyp, "ON"))
    out_file (0x84);
  
  else if (!strcmp (keyp, "TRUE"))
    out_file (0x84);
  
  else if (!strcmp (keyp, "OFF"))
    out_file (0x85);
  
  else if (!strcmp (keyp, "FALSE"))
    out_file (0x85);
  
  else
    nsyn_error (keyp, "Expecting ON, TRUE, OFF, or FALSE");
  
out_file (timer);
}

void
dothenout (void) 
{
  char *keyp, keyw[80];
  int outnum;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  outnum = atoi (keyp);
  if ((outnum < 0) || (outnum > maxout))
    nval_error (keyp, "Invalid Output ID");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
read_word (keyp);
  if (!strcmp (keyp, "ON"))
    out_file (0x82);
  
  else if (!strcmp (keyp, "TRUE"))
    out_file (0x82);
  
  else if (!strcmp (keyp, "OFF"))
    out_file (0x83);
  
  else if (!strcmp (keyp, "FALSE"))
    out_file (0x83);
  
  else
    nsyn_error (keyp, "Expecting ON, TRUE, OFF, or FALSE");
  
out_file (outnum);
}

void
dothennet (void) 
{
  char *keyp, keyw[80];
  int netnum;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  netnum = atoi (keyp);
  if ((netnum < 0) || (netnum > 511))
    nval_error (keyp, "Invalid NetBit ID");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
read_word (keyp);
  if (!strcmp (keyp, "ON"))
    out_file (0x86);
  
  else if (!strcmp (keyp, "TRUE"))
    out_file (0x86);
  
  else if (!strcmp (keyp, "OFF"))
    out_file (0x87);
  
  else if (!strcmp (keyp, "FALSE"))
    out_file (0x87);
  
  else
    nsyn_error (keyp, "Expecting ON, TRUE, OFF, or FALSE");
  
out_file (netnum % 256);
  out_file (netnum / 256);
}

void
doinc (void) 
{
  char *keyp, keyw[80];
  int varnum;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  if (strcmp (keyp, "VARIABLE"))
    nsyn_error (keyp, "Expecting Variable Label/Reference");
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  varnum = atoi (keyp);
  if ((varnum < 0) || (varnum > maxvar))
    nval_error (keyp, "Invalid Variable Reference");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
out_file (0x80);
  out_file (varnum);
}

void
dodec (void) 
{
  char *keyp, keyw[80];
  int varnum;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  if (strcmp (keyp, "VARIABLE"))
    nsyn_error (keyp, "Expecting Variable Label/Reference");
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  varnum = atoi (keyp);
  if ((varnum < 0) || (varnum > maxvar))
    nval_error (keyp, "Invalid Variable Reference");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
out_file (0x81);
  out_file (varnum);
}

void
domsg (void) 
{
  char *keyp, keyw[80], *strp, str[80];
  int i, numvar = 0, done = false;
  int varnum[10];
  
keyp = keyw;
  strp = str;
  
for (i = 0; i < 10; i++)
    varnum[i] = 0;
  
read_word (keyp);
  if (strcmp (keyp, "\""))
    nsyn_error (keyp, "Expecting \"");
  
read_string (strp);
  
done = false;
  keyp = strp;
  while (!done)
    {
      keyp = strstr (keyp, "%P");
      if (keyp)
	{
	  numvar++;
	  keyp += 2;
	}
      
      else
	done = true;
    }
  
done = false;
  keyp = strp;
  while (!done)
    {
      keyp = strstr (keyp, "%p");
      if (keyp)
	{
	  numvar++;
	  keyp += 2;
	}
      
      else
	done = true;
    }
  
done = false;
  keyp = strp;
  while (!done)
    {
      keyp = strstr (keyp, "%Q");
      if (keyp)
	{
	  numvar++;
	  keyp += 2;
	}
      
      else
	done = true;
    }
  
done = false;
  keyp = strp;
  while (!done)
    {
      keyp = strstr (keyp, "%q");
      if (keyp)
	{
	  numvar++;
	  keyp += 2;
	}
      
      else
	done = true;
    }
  
done = false;
  keyp = strp;
  while (!done)
    {
      keyp = strstr (keyp, "%R");
      if (keyp)
	{
	  numvar++;
	  keyp += 2;
	}
      
      else
	done = true;
    }
  
done = false;
  keyp = strp;
  while (!done)
    {
      keyp = strstr (keyp, "%r");
      if (keyp)
	{
	  numvar++;
	  keyp += 2;
	}
      
      else
	done = true;
    }
  
done = false;
  keyp = strp;
  while (!done)
    {
      keyp = strstr (keyp, "%S");
      if (keyp)
	{
	  numvar++;
	  keyp += 2;
	}
      
      else
	done = true;
    }
  
done = false;
  keyp = strp;
  while (!done)
    {
      keyp = strstr (keyp, "%s");
      if (keyp)
	{
	  numvar++;
	  keyp += 2;
	}
      
      else
	done = true;
    }
  
keyp = keyw;
  
for (i = 0; i < numvar; i++)
    {
      read_word (keyp);
      if (strcmp (keyp, "VARIABLE"))
	nsyn_error (keyp, "Expecting Variable Reference");
      
read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      
read_word (keyp);
      varnum[i] = atoi (keyp);
      if ((varnum[i] < 0) || (varnum[i] > 127))
	nval_error (keyp, "Invalid Varible Reference/ID");
      
read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
    }
  
i = 0;
  while (*strp)
    {
      if (*strp == '%')
	{
	  strp++;
	  switch (toupper (*strp))
	    {
	    case 'A':
	      out_file (0x80);
	      break;
	    case 'B':
	      out_file (0x81);
	      break;
	    case 'C':
	      out_file (0x82);
	      break;
	    case 'D':
	      out_file (0x83);
	      break;
	    case 'E':
	      out_file (0x84);
	      break;
	      
		// %M will dump data from CID Number if CID Modem is in use
	    case 'M':
	      out_file (0x85);
	      break;
	      
		// %N will dump data from CID Name if CID Modem is in use
	    case 'N':
	      out_file (0x86);
	      break;
	    case 'P':
	      out_file (0x90);
	      strp++;
	      out_file (*strp - '0');
	      out_file (varnum[i++]);
	      break;
	    case 'Q':
	      out_file (0x91);
	      strp++;
	      out_file (*strp - '0');
	      out_file (varnum[i++]);
	      break;
	    case 'R':
	      out_file (0x92);
	      strp++;
	      out_file (*strp - '0');
	      out_file (varnum[i++]);
	      break;
	    case 'S':
	      out_file (0x93);
	      strp++;
	      out_file (*strp - '0');
	      out_file (varnum[i++]);
	      break;
	    
case '%':
	      out_file ('%');
	      break;
	    default:
	      out_file ('%');
	      out_file (*strp);
	    }
	}
      
      else
	out_file (*strp);
      strp++;
    }
  
out_file (cr);
}

void
dolcdmsg (void) 
{
  char *keyp, keyw[80];
  int lcdnum;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  lcdnum = atoi (keyp);
  if ((lcdnum < 0) || (lcdnum > 7))
    nval_error (keyp, "Invalid LCD Module ID (0-7)");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0x88);
  out_file (lcdnum);
  
domsg ();
}

void
dodiomsg (void) 
{
  char *keyp, keyw[80];
  int dionum;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  dionum = atoi (keyp);
  if ((dionum < 0) || (dionum > 7))
    nval_error (keyp, "Invalid DIO Module ID (0-7)");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0x89);
  out_file (dionum);
  
domsg ();
}

void
dotvmsg (void) 
{
  char *keyp, keyw[80];
  int tvnum;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  tvnum = atoi (keyp);
  if ((tvnum < 0) || (tvnum > 7))
    nval_error (keyp, "Invalid TV Module ID (0-7)");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0x8A);
  out_file (tvnum);
  
domsg ();
}

void
doconmsg (void) 
{
  char *keyp, keyw[80];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0x97);
  
domsg ();
}

void
donetmsg (void) 
{
  char *keyp, keyw[80];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0x99);
  
domsg ();
}

void
dominit (void) 
{
  char *keyp, keyw[80], *strp, str[80];
  
keyp = keyw;
  strp = str;
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0x98);
  
read_word (keyp);
  if (strcmp (keyp, "\""))
    nsyn_error (keyp, "Expecting \"");
  
read_string (strp);
  
while (*strp)
    {
      out_file (*strp);
      strp++;
    }
  out_file (0x00);
}

void
doalloff (void) 
{
  char *keyp, keyw[80], modlet;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  modlet = *keyp;
  if ((modlet < 'A') || (modlet > 'P'))
    nval_error (keyp, "Invalid X10 House Code.  Should be A-P");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
out_file (modlet);
  out_file (0x00);
  out_file (0x01);
  out_file (0x00);
}

void
doallon (void) 
{
  char *keyp, keyw[80], modlet;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  modlet = *keyp;
  if ((modlet < 'A') || (modlet > 'P'))
    nval_error (keyp, "Invalid X10 House Code.  Should be A-P");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
out_file (modlet);
  out_file (0x00);
  out_file (0x02);
  out_file (0x00);
}

void
dothenmod (void) 
{
  char *keyp, keyw[80], modlet;
  int modnum, modfunc, level = 0;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  modlet = *keyp++;
  modnum = atoi (keyp);
  if ((modlet < 'A') || (modlet > 'P'))
    nval_error (keyp, "Invalid X10 House Code.  Should be A-P");
  if ((modnum < 1) || (modnum > 16))
    nval_error (keyp, "Invalid X10 Unit Code.  Should be 1-16");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
read_word (keyp);
  if (!strcmp (keyp, "ON"))
    modfunc = 0x03;
  
  else if (!strcmp (keyp, "ONA"))
    modfunc = 0x83;
  
  else if (!strcmp (keyp, "OFF"))
    modfunc = 0x04;
  
  else if (!strcmp (keyp, "DIM"))
    {
      modfunc = 0x05;
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      read_word (keyp);
      level = atoi (keyp);
      if ((level < 1) || (level > 30))
	nval_error (keyp, "Invalid DIM value.  Expecting 0-30.");
      read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
    }
  
  else if (!strcmp (keyp, "BRIGHT"))
    {
      modfunc = 0x06;
      read_word (keyp);
      if (strcmp (keyp, "("))
	nsyn_error (keyp, "Expecting \"(\"");
      read_word (keyp);
      level = atoi (keyp);
      if ((level < 1) || (level > 30))
	nval_error (keyp, "Invalid BRIGHT value.  Expecting 0-30.");
      read_word (keyp);
      if (strcmp (keyp, ")"))
	nsyn_error (keyp, "Expecting \")\"");
    }
  
  else
    nsyn_error (keyp,
		 "Invalid X10 Action. Expecting ON, ONA, OFF, DIM, or BRIGHT");
  
out_file (modlet);
  out_file (modnum);
  out_file (modfunc);
  out_file (level);
}

void
dothenvar (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > maxvar))
    nval_error (keyp, "Invliad Variable Reference/ID");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xa0);
  out_file (num);
  
Process_Equation ();
  
out_file (0xfc);
}

void
dodac (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > maxdac))
    nval_error (keyp, "Invalid DAC reference");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xa1);
  out_file (num);
  
Process_Equation ();
  
out_file (0xfc);
}

void
dorefresh (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xa2);
  
Process_Equation ();
  
out_file (0xfc);
}

void
docleartotal (void) 
{
  char *keyp, keyw[80];
  int varnum;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  varnum = atoi (keyp);
  if ((varnum < 0) || (varnum > 7))
    nval_error (keyp, "Expecting Module ID 0-7");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
out_file (0x9A);
  out_file (varnum);
}

void
dolog (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 254))
    nval_error (keyp, "Log Event ID should be 0-254");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xa4);
  out_file (num);
  
Process_Equation ();
  
out_file (0xfc);
}

void
domcirmsg (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 7))
    nval_error (keyp, "Expecting MCIR ID 0-7");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xa3);
  out_file (num);
  
Process_Equation ();
  
out_file (0xfc);
}

void
domrings (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xa5);
  
Process_Equation ();
  
out_file (0xfc);
}

void
docid (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xa6);
  
Process_Equation ();
  
out_file (0xfc);
}

void
dothennbyt (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 7))
    val_error (keyp);
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xa7);
  out_file (num);
  
Process_Equation ();
  
out_file (0xfc);
}

void
dowait (void) 
{
  char *keyp, keyw[80];
  int time;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  time = atoi (keyp);
  if ((time < 1) || (time > 255))
    nval_error (keyp,
		 "WAIT value must be between 0 and 255 (0 and 25.5 seconds)");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
out_file (0x8f);
  out_file (time);
}

void
dodialstr (void) 
{
  char *keyp, keyw[80], *strp, strw[80];
  int num;
  
keyp = keyw;
  strp = strw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  if (strcmp (keyp, "\""))
    nsyn_error (keyp, "Expecting \"");
  
out_file (0x92);
  
read_string (strp);
  
while (*strp)
    {
      out_file (*strp);
      strp++;
    }
  
out_file (0);
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
}

void
dodialdigit (void) 
{
  char *keyp, keyw[80];
  int varnum;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  if (strcmp (keyp, "VARIABLE"))
    nsyn_error (keyp, "Expecting Variable Reference/ID");
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  varnum = atoi (keyp);
  if ((varnum < 0) || (varnum > maxvar))
    nval_error (keyp, "Invalid Variable Reference/ID");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
out_file (0x93);
  out_file (varnum);
}

void
dodialnumber (void) 
{
  char *keyp, keyw[80];
  int varnum, digits;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  if (strcmp (keyp, "VARIABLE"))
    nsyn_error (keyp, "Expecting Variable Reference/ID");
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  varnum = atoi (keyp);
  if ((varnum < 0) || (varnum > maxvar))
    nval_error (keyp, "Invalid Variable Reference/ID");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  digits = atoi (keyp);
  if ((digits < 1) || (digits > 4))
    nval_error (keyp, "Invalid Dial Digits");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
out_file (0x94);
  out_file (varnum);
  out_file (digits);
}

void
dosay (void) 
{
  out_file (0x95);
  domsg ();
}

void
dosayw (void) 
{
  out_file (0x96);
  domsg ();
}

void
dopwmtotal (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 7))
    nval_error (keyp, "Expecting Module ID of 0-7");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xa8);
  out_file (num);
  
Process_Equation ();
  
out_file (0xfc);
}

void
dopwmhigh (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 7))
    nval_error (keyp, "Expecting Module ID of 0-7");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xa9);
  out_file (num);
  
Process_Equation ();
  
out_file (0xfc);
}

void
dobitdir (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 7))
    nval_error (keyp, "Expecting Module ID of 0-7");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xaa);
  out_file (num);
  
Process_Equation ();
  
out_file (0xfc);
}

void
dokeypto (void) 
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 7))
    nval_error (keyp, "Expecting Module ID of 0-7");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xab);
  out_file (num);
  
Process_Equation ();
  
out_file (0xfc);
}

void
dohvacled (void)
{
  char *keyp, keyw[80];
  int num, lnum;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 32))
    nval_error (keyp, "Expecting Thermostat ID of 0-32");
  
read_word (keyp);
  if (strcmp (keyp, ","))
    nsyn_error (keyp, "Expecting \",\"");
  
read_word (keyp);
  lnum = atoi (keyp);
  if ((lnum < 1) || (lnum > 4))
    nval_error (keyp, "Expecting Statnet LED ID of 1-4");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0x9b);
  out_file (num);
  

    // LED and state are combined.  LED is upper nybble, LED State is lower
    num = (lnum << 4);
  
read_word (keyp);
  if (!strcmp (keyp, "ON"))
    {
      num++;			// Make lower nibble 1
    }
  else if (strcmp (keyp, "OFF"))
    {
      nval_error (keyp, "Expecting ON or OFF");
    }
  
out_file (num);
}

void
dohvacfan (void)
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 32))
    nval_error (keyp, "Expecting Thermostat ID of 0-32");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0x9c);
  out_file (num);
  
read_word (keyp);
  if (!strcmp (keyp, "ON"))
    {
      out_file ('1');
    }
  else if (!strcmp (keyp, "AUTO"))
    {
      out_file ('0');
    }
  else
    {
      nval_error (keyp, "Expecting AUTO or ON");
    }
}

void
dohvacnet (void)
{
  char *keyp, keyw[80];
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0x9d);
  domsg ();
}

void
dohvacmode (void)
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 32))
    nval_error (keyp, "Expecting Thermostat ID of 0-32");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0x9e);
  out_file (num);
  
read_word (keyp);
  if (!strcmp (keyp, "OFF"))
    {
      out_file ('O');
    }
  else if (!strcmp (keyp, "AUTO"))
    {
      out_file ('A');
    }
  else if (!strcmp (keyp, "HEAT"))
    {
      out_file ('H');
    }
  else if (!strcmp (keyp, "COOL"))
    {
      out_file ('C');
    }
  else
    {
      nval_error (keyp, "Expecting OFF, HEAT, COOL, or AUTO");
    }
}

void
dohvacsetp (void)
{
  char *keyp, keyw[80];
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "("))
    nsyn_error (keyp, "Expecting \"(\"");
  
read_word (keyp);
  num = atoi (keyp);
  if ((num < 0) || (num > 32))
    nval_error (keyp, "Expecting Thermostat ID of 0-32");
  
read_word (keyp);
  if (strcmp (keyp, ")"))
    nsyn_error (keyp, "Expecting \")\"");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
out_file (0xac);
  out_file (num);
  
Process_Equation ();
  
out_file (0xfc);
}

void
ProcessIF (void) 
{
  char *keyp, keyw[80];
  int done = false;
  
keyp = keyw;
  
lparens = 0;
  
while (!done)
    {
      if (!(read_word (keyp)))
	break;
      if (!strcmp (keyp, "("))
	{
	  lparens++;
	  out_file (0x70);
	}
      
      else if (!strcmp (keyp, ")"))
	{
	  lparens--;
	  out_file (0x71);
	}
      
      else if (!strcmp (keyp, "AND"))
	out_file (0x72);
      
      else if (!strcmp (keyp, "OR"))
	out_file (0x73);
      
      else if (!strcmp (keyp, "NOT"))
	out_file (0x74);
      
      else if (!strcmp (keyp, "RESET"))
	out_file (0x16);
      
      else if (!strcmp (keyp, "TIME"))
	dotime ();
      
      else if (!strcmp (keyp, "INPUT"))
	doinput ();
      
      else if (!strcmp (keyp, "NETBIT"))
	donetbit ();
      
      else if (!strcmp (keyp, "OUTPUT"))
	dooutput ();
      
      else if (!strcmp (keyp, "MODULE"))
	domodule ();
      
      else if (!strcmp (keyp, "VARIABLE"))
	dovariable ();
      
      else if (!strcmp (keyp, "ADC"))
	doadc ();
      
      else if (!strcmp (keyp, "TIMER"))
	dotimer ();
      
      else if (!strcmp (keyp, "IRCODE"))
	doircode ();
      
      else if (!strcmp (keyp, "MONTH"))
	domonth ();
      
      else if (!strcmp (keyp, "DAY"))
	doday ();
      
      else if (!strcmp (keyp, "YEAR"))
	doyear ();
      
      else if (!strcmp (keyp, "DOW"))
	dodow ();
      
      else if (!strcmp (keyp, "HOUR"))
	dohour ();
      
      else if (!strcmp (keyp, "MINUTE"))
	dominute ();
      
      else if (!strcmp (keyp, "SECOND"))
	dosecond ();
      
      else if (!strcmp (keyp, "RINGS"))
	dorings ();
      
      else if (!strcmp (keyp, "DIALTONE") & sequence)
	dodtone ();
      
      else if (!strcmp (keyp, "CALLPROGRESS") & sequence)
	docprog ();
      
      else if (!strcmp (keyp, "CIDNEW"))
	docidnew ();
      
      else if (!strcmp (keyp, "CIDMONTH"))
	docidmon ();
      
      else if (!strcmp (keyp, "CIDDAY"))
	docidday ();
      
      else if (!strcmp (keyp, "CIDHOUR"))
	docidhour ();
      
      else if (!strcmp (keyp, "CIDMINUTE"))
	docidmin ();
      
      else if (!strcmp (keyp, "CIDAREA"))
	docidarea ();
      
      else if (!strcmp (keyp, "CIDEXCH"))
	docidexch ();
      
      else if (!strcmp (keyp, "CIDNUMBER"))
	docidnum ();
      
      else if (!strcmp (keyp, "LOGSIZE"))
	dologsize ();
      
      else if (!strcmp (keyp, "NETBYTE"))
	donetbyte ();
      
      else if (!strcmp (keyp, "ACPOWER"))
	doacpower ();
      
      else if (!strcmp (keyp, "ACFAILED"))
	doacfailed ();
      
      else if (!strcmp (keyp, "FREQUENCY"))
	dofreq ();
      
      else if (!strcmp (keyp, "TOTAL"))
	dototal ();
      
      else if (!strcmp (keyp, "KEYDIGIT"))
	dokeydigit ();
      
      else if (!strcmp (keyp, "KEYNUMBER"))
	dokeynumber ();
      
      else if (!strcmp (keyp, "IBUTTON"))
	doibutton ();
      
      else if (!strcmp (keyp, "THEN"))
	done = true;
      
      else
	nsyn_error (keyp, "Unknown command for IF statement");
    }
  
if (lparens)
    paren_error ();
}

int
ProcessTHEN () 
{
  char *keyp, keyw[80];
  int i, ElseFound = false, done = false;
  
keyp = keyw;
  
while (!done)
    {
      if (!(read_word (keyp)))
	break;
      if (!strcmp (keyp, "MODULE"))
	dothenmod ();
      
      else if (!strcmp (keyp, "ALLLIGHTSON"))
	doallon ();
      
      else if (!strcmp (keyp, "ALLUNITSOFF"))
	doalloff ();
      
      else if (!strcmp (keyp, "TIMER"))
	dothentmr ();
      
      else if (!strcmp (keyp, "OUTPUT"))
	dothenout ();
      
      else if (!strcmp (keyp, "NETBIT"))
	dothennet ();
      
      else if (!strcmp (keyp, "VARIABLE"))
	dothenvar ();
      
      else if (!strcmp (keyp, "DAC"))
	dodac ();
      
      else if (!strcmp (keyp, "LCD"))
	dolcdmsg ();
      
      else if (!strcmp (keyp, "LPT"))
	dodiomsg ();
      
      else if (!strcmp (keyp, "MCIR"))
	domcirmsg ();
      
      else if (!strcmp (keyp, "TV"))
	dotvmsg ();
      
      else if (!strcmp (keyp, "CONSOLE"))
	doconmsg ();
      
      else if (!strcmp (keyp, "NETWORK"))
	donetmsg ();
      
      else if (!strcmp (keyp, "MODEMINIT"))
	dominit ();
      
      else if (!strcmp (keyp, "REFRESH"))
	dorefresh ();
      
      else if (!strcmp (keyp, "LOG"))
	dolog ();
      
      else if (!strcmp (keyp, "MODEMRINGS"))
	domrings ();
      
      else if (!strcmp (keyp, "CALLERID"))
	docid ();
      
      else if (!strcmp (keyp, "NETBYTE"))
	dothennbyt ();
      
      else if (!strcmp (keyp, "INC"))
	doinc ();
      
      else if (!strcmp (keyp, "DEC"))
	dodec ();
      
      else if (!strcmp (keyp, "WAIT") & sequence)
	dowait ();
      
      else if (!strcmp (keyp, "DIALSTR") & sequence)
	dodialstr ();
      
      else if (!strcmp (keyp, "DIALDIGIT") & sequence)
	dodialdigit ();
      
      else if (!strcmp (keyp, "DIALNUMBER") & sequence)
	dodialnumber ();
      
      else if (!strcmp (keyp, "SAY"))
	dosay ();
      
      else if (!strcmp (keyp, "SAYW") & sequence)
	dosayw ();
      
      else if (!strcmp (keyp, "CLEARTOTAL"))
	docleartotal ();
      
      else if (!strcmp (keyp, "PWMTOTAL"))
	dopwmtotal ();
      
      else if (!strcmp (keyp, "PWMHIGH"))
	dopwmhigh ();
      
      else if (!strcmp (keyp, "BITDIRECTION"))
	dobitdir ();
      
      else if (!strcmp (keyp, "KEYPADTIMEOUT"))
	dokeypto ();
      
      else if (!strcmp (keyp, "RESETIO"))
	out_file (0x8B);
      
      else if (!strcmp (keyp, "CLEARVARIABLES"))
	out_file (0x8C);
      
      else if (!strcmp (keyp, "CLEARTIMERS"))
	out_file (0x8D);
      
      else if (!strcmp (keyp, "CLEARLOG"))
	out_file (0x8E);
      
      else if (!strcmp (keyp, "OFFHOOK") & sequence)
	out_file (0x90);
      
      else if (!strcmp (keyp, "ONHOOK"))
	out_file (0x91);
      
      else if (!strcmp (keyp, "HVACLED"))
	dohvacled ();
      
      else if (!strcmp (keyp, "HVACFAN"))
	dohvacfan ();
      
      else if (!strcmp (keyp, "HVACNET"))
	dohvacnet ();
      
      else if (!strcmp (keyp, "HVACMODE"))
	dohvacmode ();
      
      else if (!strcmp (keyp, "HVACSETPOINT"))
	dohvacsetp ();
      
      else if (!strcmp (keyp, "IF"))
	{
	  ifcount++;
	  ifctr++;
	  if (ifctr >= maxif)
	    {
	      if_error ();
	      ifctr--;
	    }
	  i = ifctr;
	  out_file (0xF1);
	  ProcessIF ();
	  out_file (0xFD);
	  out_file (0x00);
	  iftable[i][1] = bytectr;
	  out_file (0x00);
	  out_file (0x00);
	  iftable[i][0] = 1;
	  ElseFound = ProcessTHEN ();
	  iftable[i][0] = 0;
	  
if (ElseFound)
	    {
	      ifctr++;
	      if (ifctr >= maxif)
		{
		  if_error ();
		  ifctr--;
		}
	      i = ifctr;
	      out_file (0xF2);
	      out_file (0x00);
	      iftable[i][1] = bytectr;
	      out_file (0x00);
	      out_file (0x00);
	      iftable[i][0] = 1;
	      ProcessTHEN ();
	      iftable[i][0] = 0;
	    }
	  out_file (0xFE);
	}
      
      else if (!strcmp (keyp, "IFA") || !strcmp (keyp, "GIF"))
	{
	  ifcount++;
	  ifctr++;
	  if (ifctr >= maxif)
	    {
	      if_error ();
	      ifctr--;
	    }
	  i = ifctr;
	  out_file (0xF0);
	  ProcessIF ();
	  out_file (0xFD);
	  out_file (0x00);
	  iftable[i][1] = bytectr;
	  out_file (0x00);
	  out_file (0x00);
	  iftable[i][0] = 1;
	  ElseFound = ProcessTHEN ();
	  iftable[i][0] = 0;
	  
if (ElseFound)
	    {
	      ifctr++;
	      if (ifctr >= maxif)
		{
		  if_error ();
		  ifctr--;
		}
	      i = ifctr;
	      out_file (0xF2);
	      out_file (0x00);
	      iftable[i][1] = bytectr;
	      out_file (0x00);
	      out_file (0x00);
	      iftable[i][0] = 1;
	      ProcessTHEN ();
	      iftable[i][0] = 0;
	    }
	  out_file (0xFE);
	}
      
      else if (!strcmp (keyp, "ELSE"))
	{
	  ElseFound = true;
	  done = true;
	}
      
      else if (!strcmp (keyp, "END") || !strcmp (keyp, "GEND"))
	{
	  endcount++;
	  ElseFound = false;
	  done = true;
	}
      
      else
	nsyn_error (keyp, "Unknown command for THEN statement/section");
    }
  
return (ElseFound);
}

void
ProcessDEFINE (void) 
{
  char *keyp, keyw[80];
  int i;
  
keyp = keyw;
  
for (i = 0; *label[i] != NULL; i++)
    {
    }
  
read_word (keyp);
  strcpy (label[i], keyp);
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
read_line (keyp);
  strcpy (def[i], keyp);
  strcat (def[i], " ");
  
*label[i + 1] = NULL;
}

void
ProcessCONFIG (void) 
{
  char *keyp, keyw[80], *lnk, link[80];
  int i, num;
  
keyp = keyw;
  lnk = link;
  
read_word (lnk);
  
if (!strcmp (lnk, "SC"))
    {
      read_word (keyp);
      if (strcmp (keyp, "="))
	nsyn_error (keyp, "Expecting \"=\"");
      
read_word (keyp);
      if (!strcmp (keyp, "HCS180"))
	{
	  sc = 1;
	  digin[0] |= 0x03;	/* Inputs  0-15 */
	  digout[0] |= 0x01;	/* Outputs 0-7  */
	  anain[0] |= 0x01;	/* ADC     0-7  */
	}
      
      else if (!strcmp (keyp, "IND180"))
	{
	  sc = 2;
	  digin[0] |= 0xe0;	/* Inputs  40-63 */
	  digout[0] |= 0xe0;	/* Outputs 40-63 */
	  anain[0] |= 0x02;	/* ADC      8-15 */
	}
      
      else if (!strcmp (keyp, "SPECTRASENSE"))
	{
	  sc = 3;
	  digin[2] |= 0x70;	/* Inputs  160-183 */
	  digout[2] |= 0x70;	/* Outputs 160-183 */
	  anain[2] |= 0x01;	/* ADC     128-135 */
	}
      
      else
	nsyn_error (keyp,
		     "Unknown controller.  Expecting HCS180, IND180, or SPECTRASENSE");
    }
  

  else if (!strcmp (lnk, "BUF"))
    {
      read_word (keyp);
      if (strcmp (keyp, "="))
	nsyn_error (keyp, "Expecting \"=\"");
      
read_word (keyp);
      num = atoi (keyp);
      switch (num)
	{
	case 2:
	  digin[2] |= 0x80;	/* Inputs  184-191 */
	  digin[3] |= 0x03;	/* Inputs  192-207 */
	  digout[2] |= 0x80;	/* Outputs 184-191 */
	  digout[3] |= 0x03;	/* Outputs 192-207 */
	case 1:
	  digin[0] |= 0x1c;	/* Inputs  16-39 */
	  digout[0] |= 0x1c;	/* Outputs 16-39 */
	  break;
	default:
	  nval_error (keyp,
		      "Invalid BUFIO/BUF50 Reference.  You can only have 1 or 2");
	}
    }
  

  else if (!strcmp (lnk, "ADCRES"))
    {
      read_word (keyp);
      if (strcmp (keyp, "="))
	nsyn_error (keyp, "Expecting \"=\"");
      
read_word (keyp);
      num = atoi (keyp);
      if ((num == 8) || (num == 10) || (num == 12))
	adcres = num;
      
      else
	nval_error (keyp, "Invalid ACDRES value. Expecting 8, 10, or 12.");
      
if ((sc == 2) && (adcres == 12))
	{
	  adcchan = 16;
	  anain[0] &= 0xfd;	/* Turn off ADC 8-15 */
	  anain[1] |= 0x30;	/* ADC 96-111 */
	}
      
      else
	adcchan = 8;
    }
  

  else if (!strcmp (lnk, "IND54"))
    {
      read_word (keyp);
      if (strcmp (keyp, "="))
	nsyn_error (keyp, "Expecting \"=\"");
      
read_word (keyp);
      if (!strcmp (keyp, "IN"))
	digin[1] |= 0x07;	/* Inputs  64-87 */
      
      else if (!strcmp (keyp, "OUT"))
	digout[1] |= 0x07;	/* Outputs 64-87 */
      
      else
	nsyn_error (keyp, "Expecting IN or OUT");
      read_word (keyp);
      if (strcmp (keyp, ","))
	nsyn_error (keyp, "Expecting \",\"");
      
read_word (keyp);
      if (!strcmp (keyp, "IN"))
	digin[1] |= 0x38;	/* Inputs  88-111 */
      
      else if (!strcmp (keyp, "OUT"))
	digout[1] |= 0x38;	/* Outputs 88-111 */
      
      else
	nsyn_error (keyp, "Expecting IN or OUT");
      read_word (keyp);
      if (strcmp (keyp, ","))
	nsyn_error (keyp, "Expecting \",\"");
      
read_word (keyp);
      if (!strcmp (keyp, "IN"))
	{
	  digin[1] |= 0xc0;	/* Inputs  112-135 */
	  digin[2] |= 0x01;
	}
      
      else if (!strcmp (keyp, "OUT"))
	{
	  digout[1] |= 0xc0;	/* Outputs 112-135 */
	  digout[2] |= 0x01;
	}
      
      else
	nsyn_error (keyp, "Expecting IN or OUT");
      read_word (keyp);
      if (strcmp (keyp, ","))
	nsyn_error (keyp, "Expecting \",\"");
      
read_word (keyp);
      if (!strcmp (keyp, "IN"))
	digin[1] |= 0x0e;	/* Inputs  136-159 */
      
      else if (!strcmp (keyp, "OUT"))
	digout[1] |= 0x0e;	/* Outputs 136-159 */
      
      else
	nsyn_error (keyp, "Expecting IN or OUT");
    }
  

  else if (!strcmp (lnk, "ADCGAIN"))
    {
      read_word (keyp);
      if (strcmp (keyp, "="))
	nsyn_error (keyp, "Expecting \"=\"");
      
for (i = 0; i < adcchan; i++)
	{
	  read_word (keyp);
	  if (!strcmp (keyp, ","))
	    read_word (keyp);
	  
num = atoi (keyp);
	  switch (num)
	    {
	    case 1:
	      adcgain[i] = 0;
	      break;
	    case 2:
	      adcgain[i] = 1;
	      break;
	    case 4:
	      adcgain[i] = 2;
	      break;
	    case 8:
	      adcgain[i] = 3;
	      break;
	    default:
	      nval_error (keyp,
			  "Invalid ADCGAIN value. Expecting 1, 2, 4, or 8.");
	    }
	}
    }
  

  else
    {				/* Module Configuration */
      read_word (keyp);
      if (strcmp (keyp, "="))
	nsyn_error (keyp, "Expecting \"=\"");
      
read_word (keyp);
      num = atoi (keyp);
      
	/* 990825 MB - Fix number check to allow 8th module */ 
	if ((num < 0) || (num > 8))
	nval_error (keyp, "Invalid # of modules.  Expecting 0-8");
      
if (!strcmp (lnk, "PL-LINK"))
	{
	  
	    /* 990825 MB - Add check for more than 1 PL-Link */ 
	    if (num > 1)
	    nval_error (keyp, "You can only have 1 PL-Link in a system");
	  numpl = num;
	  netmod[0] |= 0x01;
	}
      
      else if (!strcmp (lnk, "IR-LINK"))
	{
	  numir = num;
	  netmod[0] |= 0x02;
	  switch ((num + 3) / 4)
	    {
	    case 2:
	      netbits[3] |= 0x80;
	    case 1:
	      netbits[3] |= 0x40;
	    }
	}
      
      else if (!strcmp (lnk, "LCD-LINK"))
	{
	  numlcd = num;
	  netmod[0] |= 0x04;
	  netbits[1] |= (int) pow (2, (int) ((num + 1) / 2)) - 1;
	}
      
      else if (!strcmp (lnk, "DIO-LINK"))
	{
	  numdio = num;
	  netmod[0] |= 0x08;
	  netbits[0] = pow (2, num) - 1;
	}
      
      else if (!strcmp (lnk, "AMAN-LINK"))
	{
	  numaman = num;
	  netmod[0] |= 0x10;
	  anaout[0] = pow (2, num) - 1;
	  switch (num)
	    {
	    case 8:
	      netbits[3] |= 0x0c;
	    case 7:
	      netbits[3] |= 0x03;
	    case 6:
	      netbits[2] |= 0xc0;
	    case 5:
	      netbits[2] |= 0x30;
	    case 4:
	      netbits[2] |= 0x0c;
	    case 3:
	      netbits[2] |= 0x03;
	    case 2:
	      netbits[1] |= 0xc0;
	    case 1:
	      netbits[1] |= 0x30;
	    }
	}
      
      else if (!strcmp (lnk, "DIO+-LINK"))
	{
	  numdiop = num;
	  netmod[0] |= 0x20;
	  netbits[4] = pow (2, num) - 1;
	}
      
      else
	nsyn_error (lnk, "Unknown Module Type");
    }
}

void
ProcessDISPLAY (void) 
{
  char *keyp, keyw[80], ch;
  int num;
  
keyp = keyw;
  
read_word (keyp);
  if (strcmp (keyp, "MODULES"))
    nsyn_error (keyp, "Expecting MODULES");
  
read_word (keyp);
  if (strcmp (keyp, "="))
    nsyn_error (keyp, "Expecting \"=\"");
  
read_line (keyp);
  
while (*keyp != NULL)
    {
      ch = *keyp++;
      if ((ch >= 'A') & (ch <= 'P'))
	house_used |= (1 << (int) (ch - 'A'));
    }
}

void
compile (char *infile) 
{
  char *keyp, keyw[80];
  int i, c, ElseFound, done = false;
  
keyp = keyw;
  
for (i = 0; i < maxif; i++)
    iftable[i][0] = 0;
  
open_files (infile, "events.bin");
  
if (errors)
    return;
  
*label[0] = NULL;
  sptr = substring;
  
printf ("\nCompiling CONFIG Section...");
  
while (!done)
    {
      if (!read_word (keyp))
	{
	  close_files ();
	  return;
	}
      if (!strcmp (keyp, "DEFINE"))
	ProcessDEFINE ();
      
      else if (!strcmp (keyp, "CONFIG"))
	ProcessCONFIG ();
      
      else if (!strcmp (keyp, "DISPLAY"))
	ProcessDISPLAY ();
      
      else if (!strcmp (keyp, "BEGIN"))
	{
	  printf ("\nCompiling XPRESS Section...");
	  out_file_no_check (version / 100);
	  out_file_no_check (version % 100);
	  out_file_no_check (sc);
	  out_file_no_check (adcres);
	  for (i = 0; i <= 15; i++)
	    out_file_no_check (adcgain[i]);
	  out_file_no_check (adcchan);
	  for (i = 0; i <= 3; i++)
	    out_file_no_check (digin[i]);
	  for (i = 0; i <= 3; i++)
	    out_file_no_check (digout[i]);
	  for (i = 0; i <= 2; i++)
	    out_file_no_check (anain[i]);
	  for (i = 0; i <= 0; i++)
	    out_file_no_check (anaout[i]);
	  for (i = 0; i <= 4; i++)
	    out_file_no_check (netbits[i]);
	  for (i = 0; i <= 0; i++)
	    out_file_no_check (netmod[i]);
	  out_file_no_check (numpl);
	  out_file_no_check (numir);
	  out_file_no_check (numlcd);
	  out_file_no_check (numdio);
	  out_file_no_check (numaman);
	  out_file_no_check (numdiop);
	  out_file_no_check (house_used % 256);
	  out_file_no_check (house_used / 256);
	  done = true;
	}
      
      else
	nsyn_error (keyp,
		     "Unknown section ID (DEFINE/CONFIG/DISPLAY/BEGIN)"); }
  
done = false;
  
while (!done)
    {
      if (!read_word (keyp))
	break;
      if (!strcmp (keyp, "IF"))
	{
	  ifcount++;
	  ifctr++;
	  if (ifctr >= maxif)
	    {
	      if_error ();
	      ifctr--;
	    }
	  i = ifctr;
	  out_file (0xF1);
	  ProcessIF ();
	  out_file (0xFD);
	  out_file (0x00);
	  iftable[i][1] = bytectr;
	  out_file (0x00);
	  out_file (0x00);
	  iftable[i][0] = 1;
	  ElseFound = ProcessTHEN ();
	  iftable[i][0] = 0;
	  
if (ElseFound)
	    {
	      ifctr++;
	      if (ifctr >= maxif)
		{
		  if_error ();
		  ifctr--;
		}
	      i = ifctr;
	      out_file (0xF2);
	      out_file (0x00);
	      iftable[i][1] = bytectr;
	      out_file (0x00);
	      out_file (0x00);
	      iftable[i][0] = 1;
	      ProcessTHEN ();
	      iftable[i][0] = 0;
	    }
	  out_file (0xFE);
	}
      
      else if (!strcmp (keyp, "IFA") || !strcmp (keyp, "GIF"))
	{
	  ifcount++;
	  ifctr++;
	  if (ifctr >= maxif)
	    {
	      if_error ();
	      ifctr--;
	    }
	  i = ifctr;
	  out_file (0xF0);
	  ProcessIF ();
	  out_file (0xFD);
	  out_file (0x00);
	  iftable[i][1] = bytectr;
	  out_file (0x00);
	  out_file (0x00);
	  iftable[i][0] = 1;
	  ElseFound = ProcessTHEN ();
	  iftable[i][0] = 0;
	  
if (ElseFound)
	    {
	      ifctr++;
	      if (ifctr >= maxif)
		{
		  if_error ();
		  ifctr--;
		}
	      i = ifctr;
	      out_file (0xF2);
	      out_file (0x00);
	      iftable[i][1] = bytectr;
	      out_file (0x00);
	      out_file (0x00);
	      iftable[i][0] = 1;
	      ProcessTHEN ();
	      iftable[i][0] = 0;
	    }
	  out_file (0xFE);
	}
      
      else if (!strcmp (keyp, "SEQUENTIAL") & !sequence)
	{
	  printf ("\nCompiling SEQUENTIAL section...");
	  sequence = true;
	  out_file (0xEF);
	}
      
      else
	nsyn_error (keyp, "Expecting IF, IFA, GIF, or SEQUENTIAL");
    }
  out_file (0xFF);
  out_file (0xFF);
  out_file (0xFF);
  
i = 1;
  while (iftable[i][1])
    {
      fputc ((iftable[i][1] - 1) % 256, outp);
      fputc ((iftable[i][1] - 1) / 256, outp);
      i++;
    }
  
out_file (0xEE);
  out_file (0xEE);
  out_file (0xEE);
  

/* Now do a second pass, inserting all IF and IFA offsets */ 
    printf ("\nCalculating IF section offsets...");
  i = 1;
  while (iftable[i][1])
    {
      fseek (outp, iftable[i][1] + 47, SEEK_SET);
      fputc (iftable[i][2] % 256, outp);
      fputc (iftable[i][2] / 256, outp);
      i++;
    }
  

/* Finally, do a third pass to establish a checksum */ 
    printf ("\nCalculating program checksum...");
  i = 0;
  fseek (outp, 47L, SEEK_SET);
  
while ((c = fgetc (outp)) != EOF)
    i = i + c;
  
fseek (outp, 0, SEEK_END);
  fputc (-(i % 256), outp);
  
close_files ();
  
if (ifcount != endcount)
    {
      printf ("\nMissing END somewhere in program");
      errors++;
    }
}

main (int argc, char *argv[]) 
{
  char *file, name[16];
  
printf ("\n\nXPRESS Compiler");
  printf ("\n Version %1d.%02d", version / 100, version % 100);
  printf ("\n Copyright (c) 1999, Creative Control Concepts");
  printf ("\n Copyright (c) 1992-1998, Circuit Cellar Inc.\n");
  
setcbrk (1);		/* Turn on ctrl-break checking */
  
file = name;
  
if (argc < 2)
    compile ("EVENTS.HCS");
  
  else
    {
      if (strchr (argv[1], '.'))
	compile (argv[1]);
      
      else
	{
	  strcpy (file, argv[1]);
	  strcat (file, ".HCS");
	  compile (file);
	}
    }
  
if (errors)
    if (errors == 1)
      printf ("\n\n>>> %i error encountered during compile. <<< \a\n",
	       errors); 
    else
      printf ("\n\n>>> %i errors encountered during compile. <<< \a\n",
	       errors); 
  else
    printf ("\n\n*** Compile complete.  No errors. ***\n");
  
return (errors);
}

