
/*  A Bison parser, made from ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script
 by  Bison version A2.6 (Andrew Consortium)
  */

#define YYBISON 1  /* Identify Bison output.  */

#define YYLSP_NEEDED

#define	LEX_INT	258
#define	LEX_ID	259
#define	LEX_STRING	260

#line 1 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"

#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#include "bool.h"
#include "mem.h"
#include "Throwback.h"

#include "script.h"

static const char mem_err[] = "Out of memory\n";

#define YYDEBUG 0
#define YYERROR_VERBOSE

#define YYPARSE_PARAM     ptree
#define YYPARSE_PARAMTYPE gr_tree*
#define YYLEX_PARAM       ptree
#define YYLEX_PARAMTYPE   gr_tree*

static void yyprint(const char* pformat, ...)
{
	va_list arg;

	va_start(arg, pformat);
	vfprintf(stderr, pformat, arg);
	va_end(arg);
}

#line 36 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
typedef union{
gr_node*	pvar;
int		value;
char*		pstring;
} YYSTYPE;

#ifndef YYLTYPE
typedef struct yyltype
{
      int timestamp;
      int first_line;
      int first_column;
      int last_line;
      int last_column;
      char *text;
} yyltype;

#define YYLTYPE yyltype
#endif

#include <stdio.h>

#ifndef __cplusplus
#ifndef __STDC__
#define const
#endif
#endif



#define	YYFINAL		31
#define	YYFLAG		-32768
#define	YYNTBASE	12

#define YYTRANSLATE(x) ((unsigned)(x) <= 260 ? yytranslate[x] : 19)

static const char yytranslate[] = {     0,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     6,
     7,     2,     2,    10,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
    11,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     8,     2,     9,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     1,     2,     3,     4,     5
};

#if YYDEBUG != 0
static const short yyprhs[] = {     0,
     0,     2,     5,    11,    13,    15,    20,    25,    27,    31,
    33,    37,    39,    41,    45,    49
};

static const short yyrhs[] = {    13,
     0,     4,     4,     0,     4,     4,     6,    17,     7,     0,
     4,     0,    14,     0,     4,     6,    17,     7,     0,     4,
     8,    16,     9,     0,    14,     0,    14,    10,    16,     0,
    18,     0,    18,    10,    17,     0,    13,     0,    15,     0,
     4,    11,     3,     0,     4,    11,    15,     0,     4,    11,
     5,     0
};

#endif

#if YYDEBUG != 0
static const short yyrline[] = { 0,
    55,    60,    69,    79,    88,    89,    97,   106,   107,   113,
   114,   120,   121,   122,   130,   138
};
#endif

#define YYNTOKENS 12
#define YYNNTS 7
#define YYNRULES 16
#define YYNSTATES 32
#define YYMAXUTOK 260

static const char * const yytname[] = {   "$","error","$undefined.","LEX_INT",
"LEX_ID","LEX_STRING","'('","')'","'['","']'","','","'='","input","var","id",
"attr","idlist","params","param", NULL
};
static const short yytoknum[] = { 0,
   256,   257,   258,   259,   260,    40,    41,    91,    93,    44,
    61,     0
};

static const short yyr1[] = {     0,
    12,    13,    13,    14,    15,    15,    15,    16,    16,    17,
    17,    18,    18,    18,    18,    18
};

static const short yyr2[] = {     0,
     1,     2,     5,     1,     1,     4,     4,     1,     3,     1,
     3,     1,     1,     3,     3,     3
};

static const short yydefact[] = {     0,
     0,     1,     2,     0,     4,    12,     5,    13,     0,    10,
     0,     0,     0,     3,     0,     0,     4,     8,     0,    14,
     4,    16,    15,    11,     6,     0,     7,     9,     0,     0,
     0
};

static const short yydefgoto[] = {    29,
     6,     7,     8,    19,     9,    10
};

static const short yypact[] = {     0,
     3,-32768,    10,     8,    -3,-32768,-32768,-32768,    11,     9,
     8,    13,     6,-32768,     8,    14,-32768,    12,    15,-32768,
     7,-32768,-32768,-32768,-32768,    13,-32768,-32768,    20,    23,
-32768
};

static const short yypgoto[] = {-32768,
    25,   -12,    16,     1,    -9,-32768
};


#define	YYLAST		29


static const short yytable[] = {    18,
     3,    16,    11,     1,    12,    24,     3,    13,    20,    21,
    22,     5,    11,    18,    12,     4,    17,    14,    15,    30,
    25,    26,    31,    27,     2,     0,    28,     0,    23
};

static const short yycheck[] = {    12,
     4,    11,     6,     4,     8,    15,     4,    11,     3,     4,
     5,     4,     6,    26,     8,     6,     4,     7,    10,     0,
     7,    10,     0,     9,     0,    -1,    26,    -1,    13
};
#define YYPURE 1

/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
#line 3 "bison.simple"

/* Skeleton output parser for bison,
   Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.

   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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* As a special exception, when this file is copied by Bison into a
   Bison output file, you may use that output file without restriction.
   This special exception was added by the Free Software Foundation
   in version 1.24 of Bison.  */

#ifdef __cplusplus
extern "C" {
void yyerror(int line, int col, const char*, ...);
};
#else /* not __cplusplus */
void yyerror(int line, int col, const char*, ...);
#endif /* not __cplusplus */

/* This is the parser code that is written into each bison parser
  when the %semantic_parser declaration is not specified in the grammar.
  It was written by Richard Stallman by simplifying the hairy parser
  used when %semantic_parser is specified.  */

/* Note: there must be only one dollar sign in this file.
   It is replaced by the list of actions, each action
   as one case of the switch.  */

#define yyerrok		(yyerrstatus = 0)
#define yyclearin	(yychar = YYEMPTY)
#define YYEMPTY		-2
#define YYEOF		0
#define YYACCEPT	return(0)
#define YYABORT 	return(1)
#define YYERROR		goto yyerrlab1
/* Like YYERROR except do call yyerror.
   This remains here temporarily to ease the
   transition to the new meaning of YYERROR, for GCC.
   Once GCC version 2 has supplanted version 1, this can go.  */
#define YYFAIL		goto yyerrlab
#define YYRECOVERING()  (!!yyerrstatus)
#define YYBACKUP(token, value) \
do								\
  if (yychar == YYEMPTY && yylen == 1)				\
    { yychar = (token), yylval = (value);			\
      yychar1 = YYTRANSLATE (yychar);				\
      YYPOPSTACK;						\
      goto yybackup;						\
    }								\
  else								\
    { yyerror (yylsp->last_line, yylsp->last_column, "syntax error: cannot back up"); YYERROR; }	\
while (0)

#define YYTERROR	1
#define YYERRCODE	256

int yylex(YYSTYPE*, YYLTYPE*, YYLEX_PARAMTYPE);
#define YYLEX		yylex(&yylval, &yylloc, YYLEX_PARAM)

#if YYDEBUG != 0
int yydebug;			/*  nonzero means print parse trace	*/
/* Since this is uninitialized, it does not stop multiple parsers
   from coexisting.  */
#endif

/*  YYINITDEPTH indicates the initial size of the parser's stacks	*/

#ifndef	YYINITDEPTH
#define YYINITDEPTH 200
#endif

/*  YYMAXDEPTH is the maximum size the stacks can grow to
    (effective only if the built-in stack extension method is used).  */

#ifdef YYMAXDEPTH
#if YYMAXDEPTH == 0
#undef YYMAXDEPTH
#endif
#endif

#ifndef YYMAXDEPTH
#define YYMAXDEPTH 10000
#endif

/* Prevent warning if -Wstrict-prototypes.  */

/* This is the most reliable way to avoid incompatibilities
   in available built-in functions on various systems.  */
static void
__yy_memcpy (char *from, char *to, int count)
{
  register char *f = from;
  register char *t = to;
  register int i = count;

  while (i-- > 0)
    *t++ = *f++;
}

#line 115 "bison.simple"

/* The user can define YYPARSE_PARAM as the name of an argument to be passed
   into yyparse.  The argument should have type void *.
   It should actually point to an object.
   Grammar actions can access the variable by casting it
   to the proper pointer type.  */

static int
yyparse(YYPARSE_PARAMTYPE YYPARSE_PARAM)
{
  register int yystate;
  register int yyn;
  register short *yyssp;
  register YYSTYPE *yyvsp;
  int yyerrstatus;	/*  number of tokens to shift before error messages enabled */
  int yychar1 = 0;		/*  lookahead token as an internal (translated) token number */

  short	yyssa[YYINITDEPTH];	/*  the state stack			*/
  YYSTYPE yyvsa[YYINITDEPTH];	/*  the semantic value stack		*/

  short *yyss = yyssa;		/*  refer to the stacks thru separate pointers */
  YYSTYPE *yyvs = yyvsa;	/*  to allow yyoverflow to reallocate them elsewhere */

  YYLTYPE yylsa[YYINITDEPTH];	/*  the location stack			*/
  YYLTYPE *yyls = yylsa;
  YYLTYPE *yylsp;

#define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)

  int yystacksize = YYINITDEPTH;

  int yychar;
  YYSTYPE yylval;
  int yynerrs;
  YYLTYPE yylloc;

  YYSTYPE yyval;		/*  the variable used to return		*/
				/*  semantic values from the action	*/
				/*  routines				*/

  int yylen;

#if YYDEBUG != 0
  if (yydebug)
    fprintf(stderr, "Starting parse\n");
#endif

  yystate = 0;
  yyerrstatus = 0;
  yynerrs = 0;
  yychar = YYEMPTY;		/* Cause a token to be read.  */

  /* Initialize stack pointers.
     Waste one element of value and location stack
     so that they stay on the same level as the state stack.
     The wasted elements are never initialized.  */

  yyssp = yyss - 1;
  yyvsp = yyvs;
  yylsp = yyls;
  yylsp->last_line = 1;
  yylsp->last_column = 1;

/* Push a new state, which is found in  yystate  .  */
/* In all cases, when you get here, the value and location stacks
   have just been pushed. so pushing a state here evens the stacks.  */
yynewstate:

  *++yyssp = yystate;

  if (yyssp >= yyss + yystacksize - 1)
    {
      /* Give user a chance to reallocate the stack */
      /* Use copies of these so that the &'s don't force the real ones into memory. */
      YYSTYPE *yyvs1 = yyvs;
      short *yyss1 = yyss;
      YYLTYPE *yyls1 = yyls;

      /* Get the current used size of the three stacks, in elements.  */
      int size = yyssp - yyss + 1;

#ifdef yyoverflow
      /* Each stack pointer address is followed by the size of
	 the data in use in that stack, in bytes.  */
      /* This used to be a conditional around just the two extra args,
	 but that might be undefined if yyoverflow is a macro.  */
      yyoverflow("parser stack overflow",
		 &yyss1, size * sizeof (*yyssp),
		 &yyvs1, size * sizeof (*yyvsp),
		 &yyls1, size * sizeof (*yylsp),
		 &yystacksize);

      yyss = yyss1; yyvs = yyvs1;
      yyls = yyls1;
#else /* no yyoverflow */
      /* Extend the stack our own way.  */
      if (yystacksize >= YYMAXDEPTH)
	{
	  yyerror(yylsp->last_line, yylsp->last_column, "parser stack overflow");
	  return 2;
	}
      yystacksize *= 2;
      if (yystacksize > YYMAXDEPTH)
	yystacksize = YYMAXDEPTH;
      yyss = (short *) malloc (yystacksize * sizeof (*yyssp));
      __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
      yyvs = (YYSTYPE *) malloc (yystacksize * sizeof (*yyvsp));
      __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
      yyls = (YYLTYPE *) malloc (yystacksize * sizeof (*yylsp));
      __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
#endif /* no yyoverflow */

      yyssp = yyss + size - 1;
      yyvsp = yyvs + size - 1;
      yylsp = yyls + size - 1;

#if YYDEBUG != 0
      if (yydebug)
	fprintf(stderr, "Stack size increased to %d\n", yystacksize);
#endif

      if (yyssp >= yyss + yystacksize - 1)
	YYABORT;
    }

#if YYDEBUG != 0
  if (yydebug)
    fprintf(stderr, "Entering state %d\n", yystate);
#endif

  goto yybackup;
 yybackup:

/* Do appropriate processing given the current state.  */
/* Read a lookahead token if we need one and don't already have one.  */
/* yyresume: */

  /* First try to decide what to do without reference to lookahead token.  */

  yyn = yypact[yystate];
  if (yyn == YYFLAG)
    goto yydefault;

  /* Not known => get a lookahead token if don't already have one.  */

  /* yychar is either YYEMPTY or YYEOF
     or a valid token in external form.  */

  if (yychar == YYEMPTY)
    {
#if YYDEBUG != 0
      if (yydebug)
	fprintf(stderr, "Reading a token: ");
#endif
      yychar = YYLEX;
    }

  /* Convert token to internal form (in yychar1) for indexing tables with */

  if (yychar <= 0)		/* This means end of input. */
    {
      yychar1 = 0;
      yychar = YYEOF;		/* Don't call YYLEX any more */

#if YYDEBUG != 0
      if (yydebug)
	fprintf(stderr, "Now at end of input.\n");
#endif
    }
  else
    {
      yychar1 = YYTRANSLATE(yychar);

#if YYDEBUG != 0
      if (yydebug)
	{
	  fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
	  /* Give the individual parser a way to print the precise meaning
	     of a token, for further debugging info.  */
#ifdef YYPRINT
	  YYPRINT (stderr, yychar, yylval);
#endif
	  fprintf (stderr, ")\n");
	}
#endif
    }

  yyn += yychar1;
  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
    goto yydefault;

  yyn = yytable[yyn];

  /* yyn is what to do for this token type in this state.
     Negative => reduce, -yyn is rule number.
     Positive => shift, yyn is new state.
       New state is final state => don't bother to shift,
       just return success.
     0, or most negative number => error.  */

  if (yyn < 0)
    {
      if (yyn == YYFLAG)
	goto yyerrlab;
      yyn = -yyn;
      goto yyreduce;
    }
  else if (yyn == 0)
    goto yyerrlab;

  if (yyn == YYFINAL)
    YYACCEPT;

  /* Shift the lookahead token.  */

#if YYDEBUG != 0
  if (yydebug)
    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
#endif

  /* Discard the token being shifted unless it is eof.  */
  if (yychar != YYEOF)
    yychar = YYEMPTY;

  *++yyvsp = yylval;
  *++yylsp = yylloc;

  /* count tokens shifted since error; after three, turn off error status.  */
  if (yyerrstatus) yyerrstatus--;

  yystate = yyn;
  goto yynewstate;

/* Do the default action for the current state.  */
yydefault:

  yyn = yydefact[yystate];
  if (yyn == 0)
    goto yyerrlab;

/* Do a reduction.  yyn is the number of a rule to reduce with.  */
yyreduce:
  yylen = yyr2[yyn];
  if (yylen > 0)
    yyval = yyvsp[1-yylen]; /* implement default value of the action */

#if YYDEBUG != 0
  if (yydebug)
    {
      int i;

      fprintf (stderr, "Reducing via rule %d (line %d), ",
	       yyn, yyrline[yyn]);

      /* Print the symbols being reduced, and their result.  */
      for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
	fprintf (stderr, "%s ", yytname[yyrhs[i]]);
      fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
    }
#endif


  switch (yyn) {

case 1:
#line 56 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
{
			ptree->m_ptop = yyvsp[0].pvar;
		;
    break;}
case 2:
#line 61 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
{
			yyval.pvar = var_new_var( yylsp[-1].first_line
					, yylsp[-1].first_column
					, yyvsp[-1].pstring
					, yyvsp[0].pstring
					, 0);
			if (!yyval.pvar) YYABORT;
		;
    break;}
case 3:
#line 70 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
{
			yyval.pvar = var_new_var(yylsp[-1].first_line
					, yylsp[-1].first_column
					, yyvsp[-4].pstring
					, yyvsp[-3].pstring
					, yyvsp[-1].pvar);
			if (!yyval.pvar) YYABORT;
		;
    break;}
case 4:
#line 80 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
{
			yyval.pvar = var_new_attr(yylsp[-1].first_line
					, yylsp[-1].first_column
					, yyvsp[0].pstring
					, 0);
			if (!yyval.pvar) YYABORT;
		;
    break;}
case 6:
#line 90 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
{
			yyval.pvar = var_new_attr(yylsp[-1].first_line
					, yylsp[-1].first_column
					, yyvsp[-3].pstring
					, yyvsp[-1].pvar);
			if (!yyval.pvar) YYABORT;
		;
    break;}
case 7:
#line 98 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
{
			yyval.pvar = var_new_list(yylsp[-1].first_line
					, yylsp[-1].first_column
					, yyvsp[-3].pstring
					, yyvsp[-1].pvar);
			if (!yyval.pvar) YYABORT;
		;
    break;}
case 9:
#line 108 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
{
			yyval.pvar = yyvsp[-2].pvar;
			yyvsp[-2].pvar->pnext = yyvsp[0].pvar;
		;
    break;}
case 11:
#line 115 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
{
			yyval.pvar = yyvsp[-2].pvar;
			yyvsp[-2].pvar->pnext = yyvsp[0].pvar;
		;
    break;}
case 14:
#line 123 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
{
			yyval.pvar = var_new_int_prop(yylsp[-1].first_line
					, yylsp[-1].first_column
					, yyvsp[-2].pstring
					, yyvsp[0].value);
			if (!yyval.pvar) YYABORT;
		;
    break;}
case 15:
#line 131 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
{
			yyval.pvar = var_new_attr_prop(yylsp[-1].first_line
					, yylsp[-1].first_column
					, yyvsp[-2].pstring
					, yyvsp[0].pvar);
			if (!yyval.pvar) YYABORT;
		;
    break;}
case 16:
#line 139 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"
{
			yyval.pvar = var_new_str_prop(yylsp[-1].first_line
					, yylsp[-1].first_column
					, yyvsp[-2].pstring
					, yyvsp[0].pstring);
			if (!yyval.pvar) YYABORT;
		;
    break;}
}
   /* the action file gets copied in in place of this dollarsign */
#line 378 "bison.simple"

  yyvsp -= yylen;
  yyssp -= yylen;
  yylsp -= yylen;

#if YYDEBUG != 0
  if (yydebug)
    {
      short *ssp1 = yyss - 1;
      fprintf (stderr, "state stack now");
      while (ssp1 != yyssp)
	fprintf (stderr, " %d", *++ssp1);
      fprintf (stderr, "\n");
    }
#endif

  *++yyvsp = yyval;

  yylsp++;
  if (yylen == 0)
    {
      yylsp->first_line = yylloc.first_line;
      yylsp->first_column = yylloc.first_column;
      yylsp->last_line = (yylsp-1)->last_line;
      yylsp->last_column = (yylsp-1)->last_column;
      yylsp->text = 0;
    }
  else
    {
      yylsp->last_line = (yylsp+yylen-1)->last_line;
      yylsp->last_column = (yylsp+yylen-1)->last_column;
    }

  /* Now "shift" the result of the reduction.
     Determine what state that goes to,
     based on the state we popped back to
     and the rule number reduced by.  */

  yyn = yyr1[yyn];

  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
    yystate = yytable[yystate];
  else
    yystate = yydefgoto[yyn - YYNTBASE];

  goto yynewstate;

yyerrlab:   /* here on detecting error */

  if (! yyerrstatus)
    /* If not already recovering from an error, report this error.  */
    {
      ++yynerrs;

#ifdef YYERROR_VERBOSE
      yyn = yypact[yystate];

      if (yyn > YYFLAG && yyn < YYLAST)
	{
	  int size = 0;
	  char *msg;
	  int x, count;

	  count = 0;
	  /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
	  for (x = (yyn < 0 ? -yyn : 0);
	       x < (sizeof(yytname) / sizeof(char *)); x++)
	    if (yycheck[x + yyn] == x)
	      size += strlen(yytname[x]) + 15, count++;
	  msg = (char *) malloc(size + 15);
	  if (msg != 0)
	    {
	      strcpy(msg, "parse error");

	      if (count < 5)
		{
		  count = 0;
		  for (x = (yyn < 0 ? -yyn : 0);
		       x < (sizeof(yytname) / sizeof(char *)); x++)
		    if (yycheck[x + yyn] == x)
		      {
			strcat(msg, count == 0 ? ", expecting `" : " or `");
			strcat(msg, yytname[x]);
			strcat(msg, "'");
			count++;
		      }
		}
	      yyerror(yylsp->last_line, yylsp->last_column, msg);
	      free(msg);
	    }
	  else
	    yyerror (yylsp->last_line, yylsp->last_column, "parse error; also virtual memory exceeded");
	}
      else
#endif /* YYERROR_VERBOSE */
	yyerror(yylsp->last_line, yylsp->last_column, "parse error");
    }

  goto yyerrlab1;
yyerrlab1:   /* here on error raised explicitly by an action */

  if (yyerrstatus == 3)
    {
      /* if just tried and failed to reuse lookahead token after an error, discard it.  */

      /* return failure if at end of input */
      if (yychar == YYEOF)
	YYABORT;

#if YYDEBUG != 0
      if (yydebug)
	fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
#endif

      yychar = YYEMPTY;
    }

  /* Else will try to reuse lookahead token
     after shifting the error token.  */

  yyerrstatus = 3;		/* Each real token shifted decrements this */

  goto yyerrhandle;

yyerrdefault:  /* current state does not do anything special for the error token. */

#if 0
  /* This is wrong; only states that explicitly want error tokens
     should shift them.  */
  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
  if (yyn) goto yydefault;
#endif

yyerrpop:   /* pop the current state because it cannot handle the error token */

  if (yyssp == yyss) YYABORT;
  yyvsp--;
  yystate = *--yyssp;
  yylsp--;

#if YYDEBUG != 0
  if (yydebug)
    {
      short *ssp1 = yyss - 1;
      fprintf (stderr, "Error: state stack now");
      while (ssp1 != yyssp)
	fprintf (stderr, " %d", *++ssp1);
      fprintf (stderr, "\n");
    }
#endif

yyerrhandle:

  yyn = yypact[yystate];
  if (yyn == YYFLAG)
    goto yyerrdefault;

  yyn += YYTERROR;
  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
    goto yyerrdefault;

  yyn = yytable[yyn];
  if (yyn < 0)
    {
      if (yyn == YYFLAG)
	goto yyerrpop;
      yyn = -yyn;
      goto yyreduce;
    }
  else if (yyn == 0)
    goto yyerrpop;

  if (yyn == YYFINAL)
    YYACCEPT;

#if YYDEBUG != 0
  if (yydebug)
    fprintf(stderr, "Shifting error token, ");
#endif

  *++yyvsp = yylval;
  *++yylsp = yylloc;

  yystate = yyn;
  goto yynewstate;
}
#line 147 "ADFS::HardDisc4.$.MultiMedia.Dev.Music.DigitalCD.!DigitalCD.Sources.Script.y.script"


static int yy_get(gr_tree* ptree)
{
	ptree->prev_char = ptree->cur_char;

	if (ptree->prev_char == '\n')
	{
		ptree->cur_line++;
		ptree->prev_col = ptree->cur_col;
		ptree->cur_col = 1;
	}
	else if (ptree->prev_char == '\t')
		ptree->cur_col += 8;
	else
		ptree->cur_col++;

	ptree->cur_char = fgetc(ptree->m_file);

	return ptree->cur_char;
}

static void yy_unget(gr_tree* ptree)
{
	ungetc(ptree->cur_char, ptree->m_file);

	ptree->cur_char = ptree->prev_char;

	if (ptree->prev_char == '\n')
	{
		ptree->cur_line--;
		ptree->cur_col = ptree->prev_col;
	}
	else if (ptree->prev_char == '\t')
		ptree->cur_col -= 8;
	else
		ptree->cur_col--;
}

static bool yy_addtostring(gr_tree* ptree, int i, int c)
{
	// If buffer is full, make it bigger.
	if (i == ptree->length)
	{
		char* pstr;
		if (ptree->length)
		{
			ptree->symbuf[ptree->length] = 0;
			ptree->length *= 2;
		}
		else
			ptree->length = 40;
		pstr = (char*) mem_alloc(ptree->length + 1);
		if (!pstr) return false;
		if (ptree->symbuf)
		{
			strcpy(pstr, ptree->symbuf);
			mem_free(ptree->symbuf);
		}
		ptree->symbuf = pstr;
	}

	// Add this character to the buffer.
	ptree->symbuf[i] = c;

	return true;
}

int yylex(YYSTYPE* plval, YYLTYPE* pos, gr_tree* ptree)
{
	int c = ' ';
	int ret;

	// Ignore whitespace, get first nonwhite character.
	while ((c != EOF) && (c <= ' '))
		c = yy_get(ptree);

	pos->first_line = pos->last_line = ptree->cur_line;
	pos->first_column = pos->last_column = ptree->cur_col;

	if (c == EOF)
	{
#if YYDEBUG != 0
		yyprint("Line %4d, Column %3d: EOF:\n", pos->first_line, pos->first_column);
#endif
		return 0;
	}

	// Char starts a number => parse the number.
	if (isdigit(c))
	{
		int i = 0;

		do
		{
			// Add this character to the buffer.
			if (!yy_addtostring(ptree, i, c))
				yyerror(pos->first_line, pos->first_column, mem_err);
			i++;
			// Get another character.
			c = yy_get(ptree);
		}
		while (c != EOF && isdigit(c));

		yy_unget(ptree);
		ptree->symbuf[i] = '\0';

		plval->value = atoi(ptree->symbuf);

		ret = LEX_INT;

#if YYDEBUG != 0
		yyprint("Line %4d, Column %3d: LEX_INT: %d\n", pos->first_line, pos->first_column, plval->value);
#endif

		pos->last_line = ptree->cur_line;
		pos->last_column = ptree->cur_col;

		return ret;
	}

	// Char starts an identifier => read the name.
	if (isalpha(c) || (c == '_'))
	{
		int i = 0;

		do
		{
			// Add this character to the buffer.
			if (!yy_addtostring(ptree, i, c))
				yyerror(pos->first_line, pos->first_column, mem_err);
			i++;
			// Get another character.
			c = yy_get(ptree);
		}
		while (c != EOF && (isalnum(c) || (c == '_')));

		yy_unget(ptree);
		ptree->symbuf[i] = '\0';

		plval->pstring = mem_allocstring(ptree->symbuf);

		if (!plval->pstring)
		{
#if YYDEBUG != 0
			yyerror(pos->first_line, pos->first_column, mem_err);
#endif
			return 0; /* error */
		}

		ret = LEX_ID;

#if YYDEBUG != 0
		yyprint("Line %4d, Column %3d: LEX_ID: %s\n", pos->first_line, pos->first_column, plval->pstring);
#endif

		pos->last_line = ptree->cur_line;
		pos->last_column = ptree->cur_col;

		return ret;
	}

	// Char starts an identifier => read the name.
	if (c == '"')
	{
		int i = 0;

		while (((c = yy_get(ptree)) != EOF) && (c != '"'))
		{
			// Add this character to the buffer.
			if (!yy_addtostring(ptree, i, c))
				yyerror(pos->first_line, pos->first_column, mem_err);
			i++;
		}

		ptree->symbuf[i] = '\0';

		plval->pstring = mem_allocstring(ptree->symbuf);

		if (!plval->pstring)
		{
#if YYDEBUG != 0
			yyerror(pos->first_line, pos->first_column, mem_err);
#endif
			return 0; /* error */
		}

		ret = LEX_STRING;

#if YYDEBUG != 0
		yyprint("Line %4d, Column %3d: LEX_STRING: \"%s\"\n", pos->first_line, pos->first_column, plval->pstring);
#endif

		pos->last_line = ptree->cur_line;
		pos->last_column = ptree->cur_col;

		return ret;
	}

	// Any other character is a token by itself.
#if YYDEBUG != 0
	yyprint("Line %4d, Column %3d: CHAR: %c\n",pos->first_line, pos->first_column, c);
#endif

	return c;
}

void yyerror(int line, int column, const char* pformat, ...)
{
	va_list arg;

	va_start(arg, pformat);
	Throwback_VError(line, column, pformat, arg);
	va_end(arg);
}

static void yylog(const gr_node* pfirst, int level)
{
	int i;
	const gr_node* pvar = pfirst;

	while(pvar)
	{
		yyprint("Line: %4d Col: %3d ", pvar->line, pvar->column);
		for (i = 0; i < level; i++)
			yyprint("\t");
		switch(pvar->type)
		{
			case gr_type_var:
			{
				yyprint("var: %s %s\n", pvar->pname, pvar->pparams);
			}
			break;
			case gr_type_attr:
			{
				yyprint("attr: %s\n", pvar->pname);
			}
			break;
			case gr_type_int_prop:
			{
				yyprint("int prop: %s = %d\n", pvar->pname, pvar->ivalue);
			}
			break;
			case gr_type_attr_prop:
			{
				yyprint("attr prop: %s = %s\n", pvar->pname, pvar->pstring);
			}
			break;
			case gr_type_str_prop:
			{
				yyprint("id attr: %s = \"%s\"\n", pvar->pname, pvar->pstring);
			}
			break;
		}
			if (pvar->pparams)
				yylog(pvar->pparams, level + 1);
		pvar = pvar->pnext;
	}
}

gr_node* var_new_var(int line, int column, char* ptype, char* pname, gr_node* pparams)
{
	gr_node* pvar = mem_alloc(sizeof(gr_node));

	if (!pvar)
	{
		yyerror(0, 0, "Out of memory\n");
		return NULL;
	}

	pvar->pnext = NULL;
	pvar->type = gr_type_var;
	pvar->line = line;
	pvar->column  = column;
	pvar->pname = ptype;
	pvar->ivalue = 0;
	pvar->pstring = pname;
	pvar->pparams = pparams;

	return pvar;
}

gr_node* var_new_attr(int line, int column, char* pname, gr_node* pparams)
{
	gr_node* pvar = mem_alloc(sizeof(gr_node));

	if (!pvar)
	{
		yyerror(0, 0, "Out of memory\n");
		return NULL;
	}

	pvar->pnext = NULL;
	pvar->type = gr_type_attr;
	pvar->line = line;
	pvar->column  = column;
	pvar->pname = pname;
	pvar->ivalue = 0;
	pvar->pstring = NULL;
	pvar->pparams = pparams;

	return pvar;
}

gr_node* var_new_list(int line, int column, char* pname, gr_node* pparams)
{
	gr_node* pvar = mem_alloc(sizeof(gr_node));

	if (!pvar)
	{
		yyerror(0, 0, "Out of memory\n");
		return NULL;
	}

	pvar->pnext = NULL;
	pvar->type = gr_type_list;
	pvar->line = line;
	pvar->column  = column;
	pvar->pname = pname;
	pvar->ivalue = 0;
	pvar->pstring = NULL;
	pvar->pparams = pparams;

	return pvar;
}

gr_node* var_new_int_prop(int line, int column, char* pname, int value)
{
	gr_node* pvar = mem_alloc(sizeof(gr_node));

	if (!pvar)
	{
		yyerror(0, 0, "Out of memory\n");
		return NULL;
	}

	pvar->pnext = NULL;
	pvar->type = gr_type_int_prop;
	pvar->line = line;
	pvar->column  = column;
	pvar->pname = pname;
	pvar->ivalue = value;
	pvar->pstring = NULL;
	pvar->pparams = NULL;

	return pvar;
}

gr_node* var_new_attr_prop(int line, int column, char* pname, gr_node* pattr)
{
	gr_node* pvar = mem_alloc(sizeof(gr_node));

	if (!pvar)
	{
		yyerror(0, 0, "Out of memory\n");
		return NULL;
	}

	pvar->pnext = NULL;
	pvar->type = gr_type_attr_prop;
	pvar->line = line;
	pvar->column  = column;
	pvar->pname = pname;
	pvar->ivalue = 0;
	pvar->pstring = NULL;
	pvar->pparams = pattr;

	return pvar;
}

gr_node* var_new_str_prop(int line, int column, char* pname, char* pstring)
{
	gr_node* pvar = mem_alloc(sizeof(gr_node));

	if (!pvar)
	{
		yyerror(0, 0, "Out of memory\n");
		return NULL;
	}

	pvar->pnext = NULL;
	pvar->type = gr_type_str_prop;
	pvar->line = line;
	pvar->column  = column;
	pvar->pname = pname;
	pvar->ivalue = 0;
	pvar->pstring = pstring;
	pvar->pparams = NULL;

	return pvar;
}

void var_delete(gr_node** pvar)
{
	if (!*pvar) return;

	mem_free((*pvar)->pname);
	while ((*pvar)->pparams) var_delete(&((*pvar)->pparams));
	mem_free((*pvar)->pstring);

	*pvar = (*pvar)->pnext;
}

gr_tree* grtree_parse(const char* filename)
{
	gr_tree*	ptree = mem_alloc(sizeof(gr_tree));
	int		bErr;

	if (!ptree)
	{
		yyerror(0, 0, "Out of memory\n");
		return NULL;
	}

	ptree->m_filename = filename;
	ptree->m_file = fopen(filename, "rb");

	if (ptree->m_file)
	{
		ptree->m_ptop = 0;
		ptree->symbuf = 0;
		ptree->length = 0;
		ptree->cur_line = 1;
		ptree->cur_col = 0;
		ptree->cur_char = 0;
		ptree->prev_col = 0;
		ptree->prev_char = 0;

		Throwback_Start(filename);
		bErr = yyparse(ptree);
		Throwback_Stop();

		fclose(ptree->m_file);

		if (bErr)
		{
			grtree_delete(ptree);
			ptree = NULL;
		}
	}
	else
	{
		yyerror(0, 0, "Could not open file\n");
		free(ptree);
		return NULL;
	}

	return ptree;
}

void grtree_delete(gr_tree* ptree)
{
	while (ptree->m_ptop) var_delete(&ptree->m_ptop);
	mem_free(ptree->symbuf);
}
