/* A Bison parser, made by GNU Bison 1.875.  */

/* Skeleton parser for Yacc-like parsing with Bison,
   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 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., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, 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.  */

/* Written by Richard Stallman by simplifying the original so called
   ``semantic'' parser.  */

/* All symbols defined below should begin with yy or YY, to avoid
   infringing on user name space.  This should be done even for local
   variables, as they might otherwise be expanded by user macros.
   There are some unavoidable exceptions within include files to
   define necessary library symbols; they are noted "INFRINGES ON
   USER NAME SPACE" below.  */

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

/* Skeleton name.  */
#define YYSKELETON_NAME "yacc.c"

/* Pure parsers.  */
#define YYPURE 0

/* Using locations.  */
#define YYLSP_NEEDED 0



/* Tokens.  */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
   /* Put the tokens into the symbol table, so that GDB and other debuggers
      know about them.  */
   enum yytokentype {
     QSTRING = 258,
     NUM = 259,
     IPADDR = 260,
     ID = 261,
     CHR = 262,
     ADDOP = 263,
     MULOP = 264,
     COMPARISON = 265,
     OROP = 266,
     ANDOP = 267,
     NOTOP = 268,
     VAR = 269,
     CONST = 270,
     TYPE = 271,
     PROCEDURE = 272,
     FUNCTION = 273,
     ARRAY = 274,
     RECORD = 275,
     RETURN = 276,
     RESTART = 277,
     PRINT = 278,
     SELECT = 279,
     IF = 280,
     ELSE = 281,
     FOR = 282,
     TO = 283,
     DOWNTO = 284,
     LOAD = 285,
     GET = 286,
     REPEAT = 287,
     UNTIL = 288,
     AT = 289,
     WITH = 290,
     TRY = 291,
     EXCEPT = 292,
     RAISE = 293,
     THEN = 294,
     WHILE = 295,
     DO = 296,
     BREAK = 297,
     ASSIGN = 298,
     OF = 299,
     LABEL = 300,
     GOTO = 301,
     NEW = 302,
     DISPOSE = 303,
     CBEGIN = 304,
     END = 305,
     DOTS = 306,
     PROGRAM = 307,
     THEN_PREC = 308,
     UMINUS = 309
   };
#endif
#define QSTRING 258
#define NUM 259
#define IPADDR 260
#define ID 261
#define CHR 262
#define ADDOP 263
#define MULOP 264
#define COMPARISON 265
#define OROP 266
#define ANDOP 267
#define NOTOP 268
#define VAR 269
#define CONST 270
#define TYPE 271
#define PROCEDURE 272
#define FUNCTION 273
#define ARRAY 274
#define RECORD 275
#define RETURN 276
#define RESTART 277
#define PRINT 278
#define SELECT 279
#define IF 280
#define ELSE 281
#define FOR 282
#define TO 283
#define DOWNTO 284
#define LOAD 285
#define GET 286
#define REPEAT 287
#define UNTIL 288
#define AT 289
#define WITH 290
#define TRY 291
#define EXCEPT 292
#define RAISE 293
#define THEN 294
#define WHILE 295
#define DO 296
#define BREAK 297
#define ASSIGN 298
#define OF 299
#define LABEL 300
#define GOTO 301
#define NEW 302
#define DISPOSE 303
#define CBEGIN 304
#define END 305
#define DOTS 306
#define PROGRAM 307
#define THEN_PREC 308
#define UMINUS 309




/* Copy the first part of user declarations.  */
#line 1 "mglparse.y"

/*
 * mglparse.y  -  Parser for Bootrom Menu Generation Language
 *
 * Copyright (C) 1997-2007 Gero Kuhlmann   <gero@gkminix.han.de>
 *
 *  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
 *  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.
 *
 * $Id: mglparse.y,v 1.14 2005/11/13 20:14:30 gkminix Exp $
 */

#include "mknbi.h"
#include "mgl.h"
#include "gencode.h"



/*
 *****************************************************************************
 *
 * Global variables
 */
int curlevel = 0;			/* Current nesting level */
struct typesdef *typetab = NULL;	/* Types table */



/*
 *****************************************************************************
 *
 * Local variables
 */
static int inargdef = FALSE;		/* TRUE when defining proc args */
static int inexcept = FALSE;		/* TRUE when in except block */
static int reclevel = 0;		/* Current level within a record def */
static varclass curclass = CLASS_LOCAL;	/* Current storage class for args */
static struct sym *procstack[MAX_LEVELS + 1];     /* Sym stack for proc nesting */
static struct typesdef *recstack[MAX_LEVELS + 1]; /* Sym stack for rec nesting */



/*
 *****************************************************************************
 *
 * Forward declarations
 */
static void procargassign __P((struct sym *proc));
static void assignvartype __P((struct typesdef *tp, struct symlist *symlist));
static int checkassign __P((struct typesdef *type1, struct typesdef *type2));
static int checkexpr __P((struct expr *e1, struct expr *e2, int binary));
static int checkvar __P((struct expr *ep));
static struct typesdef *recordcreate __P((void));
static struct typesdef *enumcreate __P((struct symlist *slist));
static struct typesdef *arraycreate __P((struct typesdef *index, struct typesdef *base));
static struct typesdef *ptrcreate __P((struct typesdef *base));
static struct typesdef *getptrbase __P((struct typesdef *ptr));
static struct expr *makeboolexpr __P((struct expr *ep));
static struct expr *setprocexpr __P((struct sym *sp, struct expr *ep));
static struct expr *genrtvar __P((int id));
static struct expr *genrtfunc __P((int id,
					struct expr *ep1,
					struct expr *ep2,
					struct expr *ep3));



/*
 *****************************************************************************
 *
 * Make life simpler using preprocessor defines:
 */
#define newexpr()	((struct expr *)nbmalloc(sizeof(struct expr)))
#define newtype()	((struct typesdef *)nbmalloc(sizeof(struct typesdef)))
#define newtypelist()	((struct typelist *)nbmalloc(sizeof(struct typelist)))
#define newvarinfo()	((struct varinfo *)nbmalloc(sizeof(struct varinfo)))



/*
 *****************************************************************************
 *
 * Print an error message. This routine is for internal use by the yacc
 * parser only.
 */

/* YYERROR_VERBOSE specifies if the parser prints verbose error messages */
#ifdef YYBISON
# ifndef YYERROR_VERBOSE
#  define YYERROR_VERBOSE 1
# endif
#else
# ifndef YYERROR_VERBOSE
#  define YYERROR_VERBOSE 0
# endif
#endif

/* Specify our own yyerror() routine to avoid to depend on any runtime lib */
#ifdef yyerror
# undef yyerror
# define yyerror(msg)	error(msg, TRUE)
#else
static inline void yyerror(msg)
char *msg;
{
#if YYERROR_VERBOSE
  /*
   * If the parser is verbose already, we don't need to print the offending
   * token.
   */
#ifdef YYBISON
  if (strstr(msg, "unexpected ID") != NULL)
	error(msg, TRUE);
  else
	error(msg, FALSE);
#else
  error(msg, FALSE);
#endif
#else
  error(msg, TRUE);
#endif
}
#endif


/* Bison doesn't call yyerror() with the YYERROR macro, so we do it instead */
#ifdef YYBISON
# define YYERRPARSE(msg)	do {					\
					yyerror("parse error, " msg);	\
					YYERROR;			\
				} while(0)
#else
# define YYERRPARSE(msg)	YYERROR
#endif


/* Print an error message if a certain ID name has been expected */
#define YYEXPECT(id, exp)	if (!issymname((id), (exp))) \
					YYERRPARSE("'" exp "' expected")



/*
 *****************************************************************************
 *
 * Redirect any bison printing routines so that they print using the
 * nblib log file facility.
 */
#ifdef YYBISON
# if YYDEBUG
#  ifdef YYFPRINTF
#   undef YYFPRINTF
#  endif
#  define YYFPRINTF yyfprintf

#  ifdef __STDC__
static void yyfprintf(FILE *fd, const char *msg, ...)
#  else
static void yyfprintf(va_list) va_dcl
#  endif
{
  va_list args;
#  ifndef __STDC__
  FILE *fd;
  char *msg;
#  endif
  size_t len;
  char *buf;

  /* Startup variadic argument handling */
#  ifdef __STDC__
  va_start(args, msg);
#  else
  va_start(args);
  fd = va_arg(args, FILE *);
  msg = va_arg(args, char *);
#  endif
  if (msg == NULL)
	return;

  /* When the parser wants to print to stderr, it is an error message */
  if (fd == stderr) {
	len = strlen(msg);
	if (len > 0 && msg[len - 1] == '\n')
		len--;
	if (len > 0) {
		buf = (char *)nbmalloc(len + 1);
		strncpy(buf, msg, len);
		buf[len] = '\0';
		prnverr(msg, args);
	}
	return;
  }

  /* For stdout we just print into the log file */
  if (fd == stdout) {
	prnvlog(LOGLEVEL_NOTICE, msg, args);
	return;
  }

  /* Otherwise we have to print into a file */
  (void)vfprintf(fd, msg, args);
}
# endif
#endif


/* Enabling traces.  */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif

/* Enabling verbose error messages.  */
#ifdef YYERROR_VERBOSE
# undef YYERROR_VERBOSE
# define YYERROR_VERBOSE 1
#else
# define YYERROR_VERBOSE 0
#endif

#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 226 "mglparse.y"
typedef union YYSTYPE {
	struct symlist  *symlist;	/* List of symbols in variable decl */
	struct typelist *typelist;	/* List of types in array decl */
	struct typesdef *type;		/* Expression type */
	struct sym      *symbol;	/* Pointer to symbol */
	struct expr     *expr;		/* expression tree */
	short           *ipaddr;	/* IP address */
	pcchar_t        *string;	/* string buffer */
	pcchar_t         chrarg;	/* character argument */
	int              intarg;	/* integer argument */
	int              op;		/* arithmetic operation */
} YYSTYPE;
/* Line 191 of yacc.c.  */
#line 414 "y.tab.c"
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif



/* Copy the second part of user declarations.  */


/* Line 214 of yacc.c.  */
#line 426 "y.tab.c"

#if ! defined (yyoverflow) || YYERROR_VERBOSE

/* The parser invokes alloca or malloc; define the necessary symbols.  */

# if YYSTACK_USE_ALLOCA
#  define YYSTACK_ALLOC alloca
# else
#  ifndef YYSTACK_USE_ALLOCA
#   if defined (alloca) || defined (_ALLOCA_H)
#    define YYSTACK_ALLOC alloca
#   else
#    ifdef __GNUC__
#     define YYSTACK_ALLOC __builtin_alloca
#    endif
#   endif
#  endif
# endif

# ifdef YYSTACK_ALLOC
   /* Pacify GCC's `empty if-body' warning. */
#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
# else
#  if defined (__STDC__) || defined (__cplusplus)
#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
#   define YYSIZE_T size_t
#  endif
#  define YYSTACK_ALLOC malloc
#  define YYSTACK_FREE free
# endif
#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */


#if (! defined (yyoverflow) \
     && (! defined (__cplusplus) \
	 || (YYSTYPE_IS_TRIVIAL)))

/* A type that is properly aligned for any stack member.  */
union yyalloc
{
  short yyss;
  YYSTYPE yyvs;
  };

/* The size of the maximum gap between one aligned stack and the next.  */
# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)

/* The size of an array large to enough to hold all stacks, each with
   N elements.  */
# define YYSTACK_BYTES(N) \
     ((N) * (sizeof (short) + sizeof (YYSTYPE))				\
      + YYSTACK_GAP_MAXIMUM)

/* Copy COUNT objects from FROM to TO.  The source and destination do
   not overlap.  */
# ifndef YYCOPY
#  if 1 < __GNUC__
#   define YYCOPY(To, From, Count) \
      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
#  else
#   define YYCOPY(To, From, Count)		\
      do					\
	{					\
	  register YYSIZE_T yyi;		\
	  for (yyi = 0; yyi < (Count); yyi++)	\
	    (To)[yyi] = (From)[yyi];		\
	}					\
      while (0)
#  endif
# endif

/* Relocate STACK from its old location to the new one.  The
   local variables YYSIZE and YYSTACKSIZE give the old and new number of
   elements in the stack, and YYPTR gives the new location of the
   stack.  Advance YYPTR to a properly aligned location for the next
   stack.  */
# define YYSTACK_RELOCATE(Stack)					\
    do									\
      {									\
	YYSIZE_T yynewbytes;						\
	YYCOPY (&yyptr->Stack, Stack, yysize);				\
	Stack = &yyptr->Stack;						\
	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
	yyptr += yynewbytes / sizeof (*yyptr);				\
      }									\
    while (0)

#endif

#if defined (__STDC__) || defined (__cplusplus)
   typedef signed char yysigned_char;
#else
   typedef short yysigned_char;
#endif

/* YYFINAL -- State number of the termination state. */
#define YYFINAL  7
/* YYLAST -- Last index in YYTABLE.  */
#define YYLAST   848

/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS  65
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS  100
/* YYNRULES -- Number of rules. */
#define YYNRULES  221
/* YYNRULES -- Number of states. */
#define YYNSTATES  394

/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
#define YYUNDEFTOK  2
#define YYMAXUTOK   309

#define YYTRANSLATE(YYX) 						\
  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)

/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
static const unsigned 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,    64,     2,     2,     2,
      59,    60,     2,     2,    57,     2,    55,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,    58,    56,
       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,    61,     2,    62,    63,     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,     6,     7,     8,     9,    10,    11,    12,    13,    14,
      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
      45,    46,    47,    48,    49,    50,    51,    52,    53,    54
};

#if YYDEBUG
/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
   YYRHS.  */
static const unsigned short yyprhs[] =
{
       0,     0,     3,    10,    13,    15,    17,    20,    23,    24,
      26,    28,    31,    35,    39,    43,    47,    50,    52,    56,
      60,    62,    64,    66,    70,    74,    76,    78,    82,    86,
      88,    90,    94,    98,   100,   102,   104,   106,   108,   110,
     113,   117,   121,   122,   126,   130,   137,   139,   143,   146,
     150,   154,   156,   158,   162,   163,   167,   170,   176,   181,
     188,   192,   196,   197,   198,   199,   205,   207,   211,   213,
     214,   218,   219,   223,   227,   229,   231,   233,   235,   239,
     243,   245,   249,   253,   259,   261,   263,   264,   266,   268,
     270,   272,   274,   276,   278,   280,   282,   284,   286,   288,
     290,   292,   294,   296,   298,   300,   304,   314,   318,   322,
     327,   329,   334,   337,   341,   344,   346,   350,   353,   354,
     357,   362,   366,   370,   371,   374,   379,   382,   384,   389,
     392,   395,   398,   400,   403,   404,   411,   413,   415,   420,
     425,   429,   434,   437,   438,   442,   446,   449,   454,   456,
     460,   465,   467,   469,   474,   477,   478,   479,   483,   484,
     488,   489,   490,   495,   496,   501,   509,   513,   515,   517,
     519,   521,   523,   527,   531,   535,   539,   543,   546,   549,
     551,   553,   555,   557,   559,   564,   571,   575,   578,   580,
     582,   584,   586,   591,   596,   597,   599,   601,   605,   609,
     613,   617,   619,   621,   623,   625,   627,   629,   631,   635,
     639,   643,   647,   651,   654,   657,   663,   664,   665,   670,
     671,   676
};

/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const short yyrhs[] =
{
      66,     0,    -1,    67,    70,   102,   105,   103,    55,    -1,
      52,    69,    -1,    56,    -1,     1,    -1,     6,    68,    -1,
       1,    68,    -1,    -1,    71,    -1,    72,    -1,    71,    72,
      -1,    14,    79,    68,    -1,    15,    75,    68,    -1,    16,
      77,    68,    -1,    45,    74,    68,    -1,    91,    68,    -1,
       6,    -1,    73,    57,     6,    -1,    73,    57,     1,    -1,
       1,    -1,    73,    -1,    76,    -1,    75,    56,    76,    -1,
       6,    10,   155,    -1,     1,    -1,    78,    -1,    77,    56,
      78,    -1,     6,    10,    81,    -1,     1,    -1,    80,    -1,
      79,    56,    80,    -1,    73,    58,    81,    -1,     1,    -1,
      82,    -1,    84,    -1,    86,    -1,    90,    -1,     1,    -1,
       6,    83,    -1,   156,    51,   156,    -1,    59,    73,    60,
      -1,    -1,    61,   155,    62,    -1,    61,     1,    62,    -1,
      19,    61,    85,    62,    44,    81,    -1,    82,    -1,    85,
      57,    82,    -1,    85,     1,    -1,    87,    88,    50,    -1,
      87,     1,    50,    -1,    20,    -1,    89,    -1,    88,    56,
      89,    -1,    -1,    73,    58,    81,    -1,    63,     6,    -1,
      92,    70,   102,   105,   103,    -1,    17,   101,    93,    68,
      -1,    18,   101,    93,    58,    81,    68,    -1,    17,     1,
      68,    -1,    18,     1,    68,    -1,    -1,    -1,    -1,    59,
      94,    96,    95,    60,    -1,    97,    -1,    96,    56,    97,
      -1,   100,    -1,    -1,    14,    98,   100,    -1,    -1,    15,
      99,   100,    -1,    73,    58,    81,    -1,     6,    -1,    49,
      -1,    50,    -1,   107,    -1,   106,    58,   107,    -1,    49,
     105,    50,    -1,   107,    -1,   106,    58,   107,    -1,   105,
      56,   107,    -1,   105,    56,   106,    58,   107,    -1,     6,
      -1,     1,    -1,    -1,    22,    -1,    21,    -1,    42,    -1,
     108,    -1,   109,    -1,   120,    -1,   110,    -1,   113,    -1,
     117,    -1,   118,    -1,   125,    -1,   129,    -1,   133,    -1,
     131,    -1,   136,    -1,   119,    -1,   124,    -1,     1,    -1,
     146,    43,   143,    -1,     6,    59,    64,    61,   143,    62,
      60,    43,   143,    -1,     1,    43,   143,    -1,   146,    43,
       1,    -1,     6,    59,   153,    60,    -1,     6,    -1,     6,
      59,     1,    60,    -1,    23,   112,    -1,    23,   111,   112,
      -1,    23,     1,    -1,   143,    -1,   111,    57,   143,    -1,
     111,     1,    -1,    -1,    34,   160,    -1,   114,    44,   115,
      50,    -1,   114,     1,    50,    -1,    24,   112,   161,    -1,
      -1,   116,   104,    -1,   115,    56,   116,   104,    -1,   155,
      58,    -1,    26,    -1,    31,   146,   112,   161,    -1,    31,
       1,    -1,    46,     6,    -1,    46,     1,    -1,    38,    -1,
      38,   143,    -1,    -1,   122,   105,   123,   105,   121,    50,
      -1,    36,    -1,    37,    -1,    47,    59,   146,    60,    -1,
      48,    59,   146,    60,    -1,   126,    39,   104,    -1,   126,
      39,   104,   127,    -1,    25,   143,    -1,    -1,    26,   128,
     104,    -1,   130,    41,   104,    -1,    40,   143,    -1,   132,
     105,    33,   143,    -1,    32,    -1,   134,    41,   104,    -1,
      27,   108,   135,   143,    -1,    28,    -1,    29,    -1,    30,
     143,   137,   140,    -1,    30,     1,    -1,    -1,    -1,     6,
     138,   164,    -1,    -1,     6,   139,     1,    -1,    -1,    -1,
      35,     6,   141,   164,    -1,    -1,    35,     6,   142,     1,
      -1,     6,    59,    64,    61,   143,    62,    60,    -1,    59,
     143,    60,    -1,   144,    -1,   145,    -1,   146,    -1,   152,
      -1,   151,    -1,   143,    12,   143,    -1,   143,    11,   143,
      -1,   143,     8,   143,    -1,   143,     9,   143,    -1,   143,
      10,   143,    -1,    13,   143,    -1,     8,   143,    -1,   147,
      -1,   148,    -1,   149,    -1,   150,    -1,     6,    -1,   146,
      61,   143,    62,    -1,   146,    61,   143,    57,   143,    62,
      -1,   146,    55,     6,    -1,   146,    63,    -1,     4,    -1,
       3,    -1,     7,    -1,     5,    -1,     6,    59,   153,    60,
      -1,     6,    59,     1,    60,    -1,    -1,   154,    -1,   143,
      -1,   143,    57,   154,    -1,   143,    57,     1,    -1,     1,
      57,   154,    -1,    59,   155,    60,    -1,   158,    -1,   159,
      -1,   157,    -1,   151,    -1,   157,    -1,   151,    -1,     6,
      -1,   155,    12,   155,    -1,   155,    11,   155,    -1,   155,
       8,   155,    -1,   155,     9,   155,    -1,   155,    10,   155,
      -1,    13,   155,    -1,     8,   155,    -1,    61,   143,    57,
     143,    62,    -1,    -1,    -1,    35,     6,   162,   143,    -1,
      -1,    35,     6,   163,     1,    -1,   143,    -1
};

/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
static const unsigned short yyrline[] =
{
       0,   304,   304,   317,   342,   343,   348,   349,   353,   355,
     360,   361,   366,   367,   368,   369,   370,   381,   400,   419,
     423,   438,   465,   466,   471,   498,   513,   514,   519,   532,
     547,   548,   553,   562,   577,   578,   579,   580,   581,   592,
     626,   680,   693,   696,   712,   728,   755,   767,   779,   800,
     814,   830,   850,   851,   855,   857,   876,   908,   913,   917,
     923,   929,   938,   940,   940,   940,   945,   946,   951,   952,
     952,   953,   953,   958,   971,   996,  1030,  1058,  1059,  1060,
    1065,  1066,  1067,  1068,  1073,  1080,  1088,  1090,  1091,  1092,
    1093,  1094,  1095,  1096,  1097,  1098,  1099,  1100,  1101,  1102,
    1103,  1104,  1105,  1106,  1107,  1118,  1139,  1172,  1179,  1195,
    1204,  1217,  1232,  1233,  1286,  1295,  1303,  1319,  1328,  1330,
    1341,  1345,  1350,  1368,  1370,  1371,  1376,  1391,  1413,  1458,
    1473,  1482,  1497,  1515,  1541,  1541,  1557,  1591,  1606,  1636,
    1666,  1670,  1678,  1688,  1688,  1699,  1707,  1723,  1733,  1747,
    1784,  1840,  1845,  1860,  1884,  1894,  1897,  1897,  1901,  1901,
    1912,  1915,  1915,  1919,  1919,  1935,  1960,  1961,  1962,  1963,
    1964,  1965,  1976,  2000,  2024,  2065,  2091,  2154,  2175,  2206,
    2207,  2208,  2209,  2214,  2264,  2300,  2325,  2410,  2461,  2473,
    2485,  2497,  2520,  2557,  2568,  2575,  2583,  2592,  2598,  2607,
    2621,  2622,  2623,  2624,  2625,  2631,  2632,  2637,  2668,  2692,
    2716,  2757,  2783,  2842,  2864,  2896,  2922,  2933,  2933,  2944,
    2944,  2954
};
#endif

#if YYDEBUG || YYERROR_VERBOSE
/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
   First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
  "$end", "error", "$undefined", "QSTRING", "NUM", "IPADDR", "ID", "CHR", 
  "ADDOP", "MULOP", "COMPARISON", "OROP", "ANDOP", "NOTOP", "VAR", 
  "CONST", "TYPE", "PROCEDURE", "FUNCTION", "ARRAY", "RECORD", "RETURN", 
  "RESTART", "PRINT", "SELECT", "IF", "ELSE", "FOR", "TO", "DOWNTO", 
  "LOAD", "GET", "REPEAT", "UNTIL", "AT", "WITH", "TRY", "EXCEPT", 
  "RAISE", "THEN", "WHILE", "DO", "BREAK", "ASSIGN", "OF", "LABEL", 
  "GOTO", "NEW", "DISPOSE", "CBEGIN", "END", "DOTS", "PROGRAM", 
  "THEN_PREC", "UMINUS", "'.'", "';'", "','", "':'", "'('", "')'", "'['", 
  "']'", "'^'", "'$'", "$accept", "mgl", "prog_header", "eol", "prog_id", 
  "blocks", "block_multiple", "block_single", "id_list", "labeldecls", 
  "constdecls", "const_declaration", "typedecls", "type_declaration", 
  "vardecls", "var_declaration", "type_spec", "type_single", 
  "string_length", "type_array", "index_list", "type_record", 
  "record_name", "record_decls", "record_declaration", "type_pointer", 
  "procedure", "proc_def", "proc_args", "@1", "@2", "proc_arg_block", 
  "proc_arg_decl", "@3", "@4", "arg_declaration", "proc_name", 
  "proc_begin", "proc_end", "commandblock", "commands", "label", 
  "command", "assignment", "callproc", "print", "print_expr", 
  "print_coordinates", "select", "select_name", "select_items", 
  "item_number", "get", "goto", "raise", "tryblock", "@5", "try_name", 
  "except_name", "ptrops", "if", "if_name", "else", "@6", "while", 
  "while_name", "repeat", "repeat_name", "for", "for_name", 
  "for_direction", "load", "from", "@7", "@8", "gateway", "@9", "@10", 
  "expr", "binaryop", "unaryop", "variable", "var_id", "var_array", 
  "var_record", "var_pointer", "constant", "func", "expressions", 
  "exprlist", "const_expr", "const_value", "const_id", "const_binaryop", 
  "const_unaryop", "coordinates", "timeout", "@11", "@12", "inetaddr", 0
};
#endif

# ifdef YYPRINT
/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
   token YYLEX-NUM.  */
static const unsigned short yytoknum[] =
{
       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
     305,   306,   307,   308,   309,    46,    59,    44,    58,    40,
      41,    91,    93,    94,    36
};
# endif

/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
static const unsigned char yyr1[] =
{
       0,    65,    66,    67,    68,    68,    69,    69,    70,    70,
      71,    71,    72,    72,    72,    72,    72,    73,    73,    73,
      73,    74,    75,    75,    76,    76,    77,    77,    78,    78,
      79,    79,    80,    80,    81,    81,    81,    81,    81,    82,
      82,    82,    83,    83,    83,    84,    85,    85,    85,    86,
      86,    87,    88,    88,    89,    89,    90,    91,    92,    92,
      92,    92,    93,    94,    95,    93,    96,    96,    97,    98,
      97,    99,    97,   100,   101,   102,   103,   104,   104,   104,
     105,   105,   105,   105,   106,   106,   107,   107,   107,   107,
     107,   107,   107,   107,   107,   107,   107,   107,   107,   107,
     107,   107,   107,   107,   107,   108,   108,   108,   108,   109,
     109,   109,   110,   110,   110,   111,   111,   111,   112,   112,
     113,   113,   114,   115,   115,   115,   116,   116,   117,   117,
     118,   118,   119,   119,   121,   120,   122,   123,   124,   124,
     125,   125,   126,   128,   127,   129,   130,   131,   132,   133,
     134,   135,   135,   136,   136,   137,   138,   137,   139,   137,
     140,   141,   140,   142,   140,   143,   143,   143,   143,   143,
     143,   143,   144,   144,   144,   144,   144,   145,   145,   146,
     146,   146,   146,   147,   148,   148,   149,   150,   151,   151,
     151,   151,   152,   152,   153,   153,   154,   154,   154,   154,
     155,   155,   155,   155,   155,   156,   156,   157,   158,   158,
     158,   158,   158,   159,   159,   160,   161,   162,   161,   163,
     161,   164
};

/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
static const unsigned char yyr2[] =
{
       0,     2,     6,     2,     1,     1,     2,     2,     0,     1,
       1,     2,     3,     3,     3,     3,     2,     1,     3,     3,
       1,     1,     1,     3,     3,     1,     1,     3,     3,     1,
       1,     3,     3,     1,     1,     1,     1,     1,     1,     2,
       3,     3,     0,     3,     3,     6,     1,     3,     2,     3,
       3,     1,     1,     3,     0,     3,     2,     5,     4,     6,
       3,     3,     0,     0,     0,     5,     1,     3,     1,     0,
       3,     0,     3,     3,     1,     1,     1,     1,     3,     3,
       1,     3,     3,     5,     1,     1,     0,     1,     1,     1,
       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
       1,     1,     1,     1,     1,     3,     9,     3,     3,     4,
       1,     4,     2,     3,     2,     1,     3,     2,     0,     2,
       4,     3,     3,     0,     2,     4,     2,     1,     4,     2,
       2,     2,     1,     2,     0,     6,     1,     1,     4,     4,
       3,     4,     2,     0,     3,     3,     2,     4,     1,     3,
       4,     1,     1,     4,     2,     0,     0,     3,     0,     3,
       0,     0,     4,     0,     4,     7,     3,     1,     1,     1,
       1,     1,     3,     3,     3,     3,     3,     2,     2,     1,
       1,     1,     1,     1,     4,     6,     3,     2,     1,     1,
       1,     1,     4,     4,     0,     1,     1,     3,     3,     3,
       3,     1,     1,     1,     1,     1,     1,     1,     3,     3,
       3,     3,     3,     2,     2,     5,     0,     0,     4,     0,
       4,     1
};

/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
   means the default is an error.  */
static const unsigned char yydefact[] =
{
       0,     0,     0,     8,     0,     0,     3,     1,     0,     0,
       0,     0,     0,     0,     0,     9,    10,     0,     8,     5,
       4,     7,     6,    20,    17,     0,     0,    30,    25,     0,
       0,    22,    29,     0,     0,    26,     0,    74,    62,     0,
      62,    20,    21,     0,    75,     0,    11,    16,     0,     0,
       0,     0,    12,     0,     0,    13,     0,     0,    14,    60,
      63,     0,    61,     0,    15,   104,   110,    88,    87,     0,
     118,     0,     0,     0,     0,   148,   136,   132,     0,    89,
       0,     0,     0,     0,     0,    80,    90,    91,    93,    94,
       0,    95,    96,   102,    92,     0,   103,    97,     0,    98,
       0,   100,     0,    99,     0,   101,     0,   179,   180,   181,
     182,     0,    19,    18,    38,   189,   188,   191,    42,   190,
       0,    51,     0,     0,    32,    34,    35,    36,     0,    37,
     206,     0,   205,    31,   207,     0,     0,     0,   204,    24,
     203,   201,   202,    23,    28,    27,     0,    58,     0,     0,
       0,   114,   183,     0,     0,     0,     0,     0,   112,   115,
     167,   168,   169,   171,   170,   216,   142,     0,   183,     0,
     154,   155,   129,   183,   118,   133,   146,   131,   130,     0,
       0,    76,     0,     0,     0,     0,   123,     0,     0,     0,
       0,     0,     0,     0,     0,   187,     0,     0,    39,     0,
       0,    56,    20,     0,     0,    52,     0,   214,   213,     0,
       0,     0,     0,     0,     0,    69,    71,     0,    64,    66,
      68,     0,   107,     0,     0,   196,     0,   195,     0,   178,
     177,     0,   119,     0,   117,     0,   113,     0,     0,     0,
       0,     0,     0,   122,     0,   151,   152,     0,   156,   160,
     216,     0,     0,     0,    82,     2,   104,   110,    81,   121,
     127,     0,     0,     0,   137,     0,     0,   140,     0,    77,
     145,     0,   149,   108,   105,   186,     0,    57,     0,     0,
      46,     0,    41,    50,     0,    49,     0,    40,   200,   210,
     211,   212,   209,   208,     0,     0,     0,     0,     0,    59,
       0,   111,     0,     0,   109,     0,     0,     0,     0,   166,
     116,   174,   175,   176,   173,   172,   217,   150,     0,     0,
       0,   153,   128,   138,   139,     0,   120,     0,   124,   126,
     134,     0,   143,   141,     0,   147,     0,   184,    44,    43,
      48,     0,     0,    55,    53,    70,    72,    73,    67,    65,
       0,   199,     0,   198,   197,   193,     0,   192,     0,     0,
       0,   221,   157,   159,   161,    83,     0,     0,    79,     0,
      78,     0,    47,     0,     0,     0,     0,   218,   220,     0,
       0,   125,   135,   144,   185,    45,     0,     0,   215,   162,
     164,     0,   165,   106
};

/* YYDEFGOTO[NTERM-NUM]. */
static const short yydefgoto[] =
{
      -1,     2,     3,    21,     6,    14,    15,    16,   217,    43,
      30,    31,    34,    35,    26,    27,   124,   125,   198,   126,
     281,   127,   128,   204,   205,   129,    17,    18,    61,   146,
     298,   218,   219,   294,   295,   220,    38,    45,   183,   267,
      83,    84,    85,    86,    87,    88,   157,   158,    89,    90,
     261,   262,    91,    92,    93,    94,   367,    95,   265,    96,
      97,    98,   333,   369,    99,   100,   101,   102,   103,   104,
     247,   105,   249,   318,   319,   321,   379,   380,   225,   160,
     161,   162,   107,   108,   109,   110,   163,   164,   226,   227,
     263,   131,   140,   141,   142,   232,   243,   359,   360,   362
};

/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
   STATE-NUM.  */
#define YYPACT_NINF -187
static const short yypact[] =
{
     -38,    38,   119,   773,    19,    19,  -187,  -187,   109,   155,
     206,   266,   284,   302,    -3,   773,  -187,    19,   773,  -187,
    -187,  -187,  -187,    39,  -187,   131,    46,  -187,  -187,   135,
      51,  -187,  -187,   147,    53,  -187,    19,  -187,    70,    19,
      70,  -187,   112,    19,  -187,   619,  -187,  -187,    -3,   303,
     179,   757,  -187,   390,   763,  -187,   179,   799,  -187,  -187,
    -187,    19,  -187,   114,  -187,    63,   764,  -187,  -187,   294,
     163,   415,   305,   270,   350,  -187,  -187,   415,   415,  -187,
     353,   157,   159,   -13,   168,  -187,  -187,  -187,  -187,  -187,
      20,  -187,  -187,  -187,  -187,   657,  -187,  -187,   183,  -187,
     210,  -187,   685,  -187,   247,  -187,    87,  -187,  -187,  -187,
    -187,   619,  -187,  -187,  -187,  -187,  -187,  -187,    61,  -187,
     244,  -187,   302,   290,  -187,  -187,  -187,  -187,    47,  -187,
    -187,   268,  -187,  -187,  -187,   390,   390,   390,  -187,   624,
    -187,  -187,  -187,  -187,  -187,  -187,   126,  -187,   179,   415,
      64,  -187,   279,   415,   415,   282,   415,   213,  -187,   820,
    -187,  -187,   118,  -187,  -187,   317,   820,   312,   319,   181,
    -187,   586,  -187,  -187,    50,   820,   820,  -187,  -187,   385,
     385,  -187,   505,   349,   543,   361,   379,    18,   429,   429,
      23,   429,   309,   408,   415,  -187,   -13,   329,  -187,    55,
     -42,  -187,   365,   224,    30,  -187,   830,  -187,   235,   398,
     390,   390,   390,   390,   390,  -187,  -187,   283,   376,  -187,
    -187,    19,   820,    25,   356,   739,   364,  -187,   227,  -187,
     256,   415,  -187,   726,  -187,   415,  -187,   415,   415,   415,
     415,   415,   420,  -187,   372,  -187,  -187,   415,   436,   399,
     317,   141,   164,   382,  -187,  -187,   312,   370,  -187,  -187,
    -187,    97,   581,   734,  -187,   619,   619,   413,   388,  -187,
    -187,   415,  -187,  -187,   820,  -187,   662,  -187,   386,   337,
    -187,    16,  -187,  -187,   179,  -187,    75,  -187,  -187,   438,
    -187,   358,   245,   235,   302,   302,   179,   126,   397,  -187,
     357,  -187,   415,   368,  -187,    76,   402,   404,   744,  -187,
     820,   461,  -187,   381,   606,   256,   471,   820,   415,   485,
     481,  -187,  -187,  -187,  -187,   543,  -187,   379,  -187,  -187,
     440,   104,  -187,  -187,   467,   820,   415,  -187,  -187,  -187,
    -187,    55,   457,  -187,  -187,  -187,  -187,  -187,  -187,  -187,
     445,  -187,   433,   445,  -187,  -187,   415,  -187,   415,   415,
     507,   820,  -187,  -187,   509,  -187,   581,   462,  -187,   429,
    -187,   472,  -187,   179,   456,   510,   548,   820,  -187,   415,
     523,  -187,  -187,  -187,  -187,  -187,   482,   473,  -187,  -187,
    -187,   415,  -187,   820
};

/* YYPGOTO[NTERM-NUM].  */
static const short yypgoto[] =
{
    -187,  -187,  -187,     2,  -187,   513,  -187,   524,    -2,  -187,
    -187,   486,  -187,   489,  -187,   497,   -55,  -186,  -187,  -187,
    -187,  -187,  -187,  -187,   264,  -187,  -187,  -187,   514,  -187,
    -187,  -187,   265,  -187,  -187,   107,   551,   521,   375,  -179,
     -60,  -166,  -158,   506,  -187,  -187,  -187,   -66,  -187,  -187,
    -187,   250,  -187,  -187,  -187,  -187,  -187,  -187,  -187,  -187,
    -187,  -187,  -187,  -187,  -187,  -187,  -187,  -187,  -187,  -187,
    -187,  -187,  -187,  -187,  -187,  -187,  -187,  -187,    21,  -187,
    -187,   -45,  -187,  -187,  -187,  -187,   -48,  -187,   360,  -132,
     -19,   378,   -47,  -187,  -187,  -187,   336,  -187,  -187,   221
};

/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
   positive, shift that token.  If negative, reduce the rule which
   number is the opposite.  If zero, do what YYDEFACT says.
   If YYTABLE_NINF, syntax error.  */
#define YYTABLE_NINF -220
static const short yytable[] =
{
     106,   144,   130,   132,   165,   138,    25,    22,   130,   132,
     270,    42,   272,   280,     1,    49,   253,   340,   282,    47,
      19,   185,   268,   268,   254,   268,   258,   106,    52,   174,
     269,   269,    55,   269,   139,   187,    58,   181,    59,     4,
     -33,    62,   190,   182,     5,    64,    44,    19,   202,    25,
     106,   196,    19,    24,    19,   264,   271,   106,   115,   116,
     117,   118,   119,   147,   186,   223,   106,   115,   116,   117,
     152,   119,   153,   341,   182,    20,    41,   154,   342,   182,
     285,    24,   300,   328,   155,   301,   286,   138,   138,   138,
     159,   236,   166,   221,   171,   -33,   268,   -54,   175,   176,
     130,   132,    51,   -54,   269,   193,   149,    54,   250,    57,
      23,   194,  -207,   195,   122,    24,   207,   208,   209,     7,
     200,   -85,   197,   156,  -194,   -54,   203,    41,   224,    60,
     192,   -54,    24,   300,   251,   252,   355,   106,   138,   106,
     215,   216,   193,   106,   106,    53,   106,   326,   194,   138,
     195,   130,   132,   327,   368,   372,    28,    56,   130,   132,
     182,    29,   138,   138,   138,   138,   138,   365,   351,    49,
     222,   354,   148,   193,   229,   230,   370,   233,   279,   194,
     114,   195,   115,   116,   117,   118,   119,   381,    49,    50,
     383,   289,   290,   291,   292,   293,   193,   155,   120,   121,
     268,   323,   194,   268,   195,   330,   331,    32,   269,   245,
     246,   269,    33,   274,   234,   276,   179,   106,   180,   193,
     106,   106,   188,   299,   324,   194,   184,   195,   305,   343,
     115,   116,   117,   152,   119,   153,   130,   132,   122,  -118,
     154,   347,   123,   210,   211,   212,  -118,   155,   130,   132,
    -118,   189,   308,   210,   211,   212,   310,   214,   311,   312,
     313,   314,   315,  -118,   237,   238,   239,    36,   317,  -118,
     235,   170,    37,   115,   116,   117,   152,   119,   153,   138,
     106,    49,   284,   154,   203,    39,   156,  -194,   191,   106,
      37,   306,   335,   130,   132,   151,   201,   115,   116,   117,
     152,   119,   153,    41,   112,   199,   167,   154,    24,   113,
     273,   168,   115,   116,   117,   152,   119,   153,   385,   206,
    -118,   106,   154,   352,   106,   130,   132,  -118,   155,   156,
     278,  -118,   115,   116,   117,   134,   119,   135,   228,   361,
      49,   296,   136,   231,  -118,   210,   211,   212,   213,   214,
    -118,   172,   242,   156,   177,   149,   173,   371,   350,   178,
     115,   116,   117,   152,   119,   153,   210,   211,   156,   353,
     154,   115,   116,   117,   152,   119,   153,   375,   244,   376,
     377,   154,   115,   116,   117,   134,   119,   135,   137,   237,
     238,   173,   136,   115,   116,   117,   134,   119,   135,   339,
     361,   345,   346,   136,   255,   260,   210,   211,   212,   213,
     214,   259,   393,  -183,   275,   283,   156,   302,   115,   116,
     117,   152,   119,   153,   304,  -183,   316,   156,   154,   150,
      65,  -183,   297,  -183,   320,    66,   224,  -158,   137,   332,
     325,   237,   238,   239,   240,   241,   334,   211,   338,   137,
      67,    68,    69,    70,    71,   -86,    72,   349,   288,    73,
      74,    75,   -86,   356,   357,    76,   -86,    77,   256,    78,
     238,    79,  -219,   257,   156,    80,    81,    82,   266,   -86,
     237,   238,   239,   240,   241,   -86,   363,   364,    67,    68,
      69,    70,    71,   -86,    72,   374,   182,    73,    74,    75,
     -86,   373,   300,    76,   -86,    77,    65,    78,   378,    79,
    -163,    66,   382,    80,    81,    82,   386,   -86,   237,   238,
     239,   240,   241,   -86,   390,   391,    67,    68,    69,    70,
      71,    48,    72,   392,   384,    73,    74,    75,   -86,    46,
     143,    76,   -86,    77,   256,    78,   145,    79,   133,   257,
     344,    80,    81,    82,    63,   -86,   237,   238,   239,   240,
     241,   -86,   348,    40,    67,    68,    69,    70,    71,   111,
      72,   277,   387,    73,    74,    75,   -86,   366,   169,    76,
     -86,    77,    65,    78,   287,    79,   322,    66,   307,    80,
      81,    82,   248,   -86,   237,   238,   239,   240,   241,   -86,
     389,     0,    67,    68,    69,    70,    71,     0,    72,     0,
     388,    73,    74,    75,   237,   238,   239,    76,   241,    77,
      65,    78,     0,    79,     0,    66,     0,    80,    81,    82,
     266,   -86,   210,   211,   212,   213,   214,   -86,     0,     0,
      67,    68,    69,    70,    71,     0,    72,     0,     0,    73,
      74,    75,     0,     0,     0,    76,     0,    77,    65,    78,
       0,    79,     0,    66,     0,    80,    81,    82,     0,   -86,
     237,   238,   239,   240,   241,   -86,     0,     0,    67,    68,
      69,    70,    71,     0,    72,     0,    65,    73,    74,    75,
       0,    66,     0,    76,   -86,    77,     0,    78,     0,    79,
       0,     0,     0,    80,    81,    82,    67,    68,    69,    70,
      71,     0,    72,   -86,     0,    73,    74,    75,   -86,   336,
       0,    76,     0,    77,   337,    78,     0,    79,     0,     0,
       0,    80,    81,    82,   237,   238,   239,   240,   241,     0,
       0,   -86,   210,   211,   212,   213,   214,   237,   238,   239,
     240,   241,   237,   238,   239,   240,   241,     0,    23,     0,
       0,     0,     0,    24,    28,     0,     0,     0,     0,    29,
       0,    -4,    -4,    -4,    -4,    -4,     0,    -4,    -4,    -4,
      -4,    -4,     0,     0,     0,     0,   309,     8,     9,    10,
      11,    12,   329,     0,     0,     0,   303,     0,     0,     0,
      32,   358,    -4,     0,     0,    33,    -4,  -183,    -4,     0,
       0,     0,    -4,    -4,    -4,    -4,    -4,    -4,    13,  -183,
       0,     0,   -84,   150,     0,  -183,     0,  -183,   237,   238,
     239,   240,   241,   115,   116,   117,   134,   119,     0,     0,
       0,     0,     0,     0,    -4,     0,     0,     0,    -4
};

static const short yycheck[] =
{
      45,    56,    50,    50,    70,    53,     8,     5,    56,    56,
     189,    13,   191,   199,    52,    57,   182,     1,    60,    17,
       1,     1,   188,   189,   182,   191,   184,    72,    26,    74,
     188,   189,    30,   191,    53,    95,    34,    50,    36,     1,
       1,    39,   102,    56,     6,    43,    49,     1,     1,    51,
      95,   111,     1,     6,     1,    37,    33,   102,     3,     4,
       5,     6,     7,    61,    44,     1,   111,     3,     4,     5,
       6,     7,     8,    57,    56,    56,     1,    13,    62,    56,
      50,     6,    57,   262,    34,    60,    56,   135,   136,   137,
      69,   157,    71,   148,    73,    56,   262,    50,    77,    78,
     148,   148,    56,    56,   262,    55,    43,    56,   174,    56,
       1,    61,    51,    63,    59,     6,   135,   136,   137,     0,
     122,    58,    61,    59,    60,    50,   128,     1,    64,    59,
      43,    56,     6,    57,   179,   180,    60,   182,   186,   184,
      14,    15,    55,   188,   189,    10,   191,    50,    61,   197,
      63,   199,   199,    56,    50,   341,     1,    10,   206,   206,
      56,     6,   210,   211,   212,   213,   214,   325,   300,    57,
     149,   303,    58,    55,   153,   154,   334,   156,   197,    61,
       1,    63,     3,     4,     5,     6,     7,   366,    57,    58,
     369,   210,   211,   212,   213,   214,    55,    34,    19,    20,
     366,    60,    61,   369,    63,   265,   266,     1,   366,    28,
      29,   369,     6,   192,     1,   194,    59,   262,    59,    55,
     265,   266,    39,   221,    60,    61,    58,    63,     1,   284,
       3,     4,     5,     6,     7,     8,   284,   284,    59,    26,
      13,   296,    63,     8,     9,    10,    33,    34,   296,   296,
      37,    41,   231,     8,     9,    10,   235,    12,   237,   238,
     239,   240,   241,    50,     8,     9,    10,     1,   247,    56,
      57,     1,     6,     3,     4,     5,     6,     7,     8,   327,
     325,    57,    58,    13,   286,     1,    59,    60,    41,   334,
       6,    64,   271,   341,   341,     1,     6,     3,     4,     5,
       6,     7,     8,     1,     1,    61,     1,    13,     6,     6,
       1,     6,     3,     4,     5,     6,     7,     8,   373,    51,
      26,   366,    13,   302,   369,   373,   373,    33,    34,    59,
       1,    37,     3,     4,     5,     6,     7,     8,    59,   318,
      57,    58,    13,    61,    50,     8,     9,    10,    11,    12,
      56,     1,    35,    59,     1,    43,     6,   336,     1,     6,
       3,     4,     5,     6,     7,     8,     8,     9,    59,     1,
      13,     3,     4,     5,     6,     7,     8,   356,    59,   358,
     359,    13,     3,     4,     5,     6,     7,     8,    59,     8,
       9,     6,    13,     3,     4,     5,     6,     7,     8,    62,
     379,   294,   295,    13,    55,    26,     8,     9,    10,    11,
      12,    50,   391,    43,     6,    50,    59,    61,     3,     4,
       5,     6,     7,     8,    60,    55,     6,    59,    13,    59,
       1,    61,    56,    63,    35,     6,    64,     1,    59,    26,
      58,     8,     9,    10,    11,    12,    58,     9,    62,    59,
      21,    22,    23,    24,    25,    26,    27,    60,    60,    30,
      31,    32,    33,    61,    60,    36,    37,    38,     1,    40,
       9,    42,     1,     6,    59,    46,    47,    48,    49,    50,
       8,     9,    10,    11,    12,    56,     1,     6,    21,    22,
      23,    24,    25,    26,    27,    62,    56,    30,    31,    32,
      33,    44,    57,    36,    37,    38,     1,    40,     1,    42,
       1,     6,    50,    46,    47,    48,    60,    50,     8,     9,
      10,    11,    12,    56,     1,    43,    21,    22,    23,    24,
      25,    18,    27,    60,    62,    30,    31,    32,    33,    15,
      54,    36,    37,    38,     1,    40,    57,    42,    51,     6,
     286,    46,    47,    48,    40,    50,     8,     9,    10,    11,
      12,    56,   297,    12,    21,    22,    23,    24,    25,    48,
      27,   196,    62,    30,    31,    32,    33,   327,    72,    36,
      37,    38,     1,    40,   206,    42,   250,     6,   228,    46,
      47,    48,     6,    50,     8,     9,    10,    11,    12,    56,
     379,    -1,    21,    22,    23,    24,    25,    -1,    27,    -1,
      62,    30,    31,    32,     8,     9,    10,    36,    12,    38,
       1,    40,    -1,    42,    -1,     6,    -1,    46,    47,    48,
      49,    50,     8,     9,    10,    11,    12,    56,    -1,    -1,
      21,    22,    23,    24,    25,    -1,    27,    -1,    -1,    30,
      31,    32,    -1,    -1,    -1,    36,    -1,    38,     1,    40,
      -1,    42,    -1,     6,    -1,    46,    47,    48,    -1,    50,
       8,     9,    10,    11,    12,    56,    -1,    -1,    21,    22,
      23,    24,    25,    -1,    27,    -1,     1,    30,    31,    32,
      -1,     6,    -1,    36,    37,    38,    -1,    40,    -1,    42,
      -1,    -1,    -1,    46,    47,    48,    21,    22,    23,    24,
      25,    -1,    27,    56,    -1,    30,    31,    32,    33,    57,
      -1,    36,    -1,    38,    62,    40,    -1,    42,    -1,    -1,
      -1,    46,    47,    48,     8,     9,    10,    11,    12,    -1,
      -1,    56,     8,     9,    10,    11,    12,     8,     9,    10,
      11,    12,     8,     9,    10,    11,    12,    -1,     1,    -1,
      -1,    -1,    -1,     6,     1,    -1,    -1,    -1,    -1,     6,
      -1,    14,    15,    16,    17,    18,    -1,    14,    15,    16,
      17,    18,    -1,    -1,    -1,    -1,    60,    14,    15,    16,
      17,    18,    58,    -1,    -1,    -1,    57,    -1,    -1,    -1,
       1,    57,    45,    -1,    -1,     6,    49,    43,    45,    -1,
      -1,    -1,    49,    14,    15,    16,    17,    18,    45,    55,
      -1,    -1,    58,    59,    -1,    61,    -1,    63,     8,     9,
      10,    11,    12,     3,     4,     5,     6,     7,    -1,    -1,
      -1,    -1,    -1,    -1,    45,    -1,    -1,    -1,    49
};

/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
   symbol of state STATE-NUM.  */
static const unsigned char yystos[] =
{
       0,    52,    66,    67,     1,     6,    69,     0,    14,    15,
      16,    17,    18,    45,    70,    71,    72,    91,    92,     1,
      56,    68,    68,     1,     6,    73,    79,    80,     1,     6,
      75,    76,     1,     6,    77,    78,     1,     6,   101,     1,
     101,     1,    73,    74,    49,   102,    72,    68,    70,    57,
      58,    56,    68,    10,    56,    68,    10,    56,    68,    68,
      59,    93,    68,    93,    68,     1,     6,    21,    22,    23,
      24,    25,    27,    30,    31,    32,    36,    38,    40,    42,
      46,    47,    48,   105,   106,   107,   108,   109,   110,   113,
     114,   117,   118,   119,   120,   122,   124,   125,   126,   129,
     130,   131,   132,   133,   134,   136,   146,   147,   148,   149,
     150,   102,     1,     6,     1,     3,     4,     5,     6,     7,
      19,    20,    59,    63,    81,    82,    84,    86,    87,    90,
     151,   156,   157,    80,     6,     8,    13,    59,   151,   155,
     157,   158,   159,    76,    81,    78,    94,    68,    58,    43,
      59,     1,     6,     8,    13,    34,    59,   111,   112,   143,
     144,   145,   146,   151,   152,   112,   143,     1,     6,   108,
       1,   143,     1,     6,   146,   143,   143,     1,     6,    59,
      59,    50,    56,   103,    58,     1,    44,   105,    39,    41,
     105,    41,    43,    55,    61,    63,   105,    61,    83,    61,
      73,     6,     1,    73,    88,    89,    51,   155,   155,   155,
       8,     9,    10,    11,    12,    14,    15,    73,    96,    97,
     100,    81,   143,     1,    64,   143,   153,   154,    59,   143,
     143,    61,   160,   143,     1,    57,   112,     8,     9,    10,
      11,    12,    35,   161,    59,    28,    29,   135,     6,   137,
     112,   146,   146,   106,   107,    55,     1,     6,   107,    50,
      26,   115,   116,   155,    37,   123,    49,   104,   106,   107,
     104,    33,   104,     1,   143,     6,   143,   103,     1,   155,
      82,    85,    60,    50,    58,    50,    56,   156,    60,   155,
     155,   155,   155,   155,    98,    99,    58,    56,    95,    68,
      57,    60,    61,    57,    60,     1,    64,   153,   143,    60,
     143,   143,   143,   143,   143,   143,     6,   143,   138,   139,
      35,   140,   161,    60,    60,    58,    50,    56,   104,    58,
     105,   105,    26,   127,    58,   143,    57,    62,    62,    62,
       1,    57,    62,    81,    89,   100,   100,    81,    97,    60,
       1,   154,   143,     1,   154,    60,    61,    60,    57,   162,
     163,   143,   164,     1,     6,   107,   116,   121,    50,   128,
     107,   143,    82,    44,    62,   143,   143,   143,     1,   141,
     142,   104,    50,   104,    62,    81,    60,    62,    62,   164,
       1,    43,    60,   143
};

#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
# define YYSIZE_T __SIZE_TYPE__
#endif
#if ! defined (YYSIZE_T) && defined (size_t)
# define YYSIZE_T size_t
#endif
#if ! defined (YYSIZE_T)
# if defined (__STDC__) || defined (__cplusplus)
#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
#  define YYSIZE_T size_t
# endif
#endif
#if ! defined (YYSIZE_T)
# define YYSIZE_T unsigned int
#endif

#define yyerrok		(yyerrstatus = 0)
#define yyclearin	(yychar = YYEMPTY)
#define YYEMPTY		(-2)
#define YYEOF		0

#define YYACCEPT	goto yyacceptlab
#define YYABORT		goto yyabortlab
#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);						\
      yytoken = YYTRANSLATE (yychar);				\
      YYPOPSTACK;						\
      goto yybackup;						\
    }								\
  else								\
    { 								\
      yyerror ("syntax error: cannot back up");\
      YYERROR;							\
    }								\
while (0)

#define YYTERROR	1
#define YYERRCODE	256

/* YYLLOC_DEFAULT -- Compute the default location (before the actions
   are run).  */

#ifndef YYLLOC_DEFAULT
# define YYLLOC_DEFAULT(Current, Rhs, N)         \
  Current.first_line   = Rhs[1].first_line;      \
  Current.first_column = Rhs[1].first_column;    \
  Current.last_line    = Rhs[N].last_line;       \
  Current.last_column  = Rhs[N].last_column;
#endif

/* YYLEX -- calling `yylex' with the right arguments.  */

#ifdef YYLEX_PARAM
# define YYLEX yylex (YYLEX_PARAM)
#else
# define YYLEX yylex ()
#endif

/* Enable debugging if requested.  */
#if YYDEBUG

# ifndef YYFPRINTF
#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
#  define YYFPRINTF fprintf
# endif

# define YYDPRINTF(Args)			\
do {						\
  if (yydebug)					\
    YYFPRINTF Args;				\
} while (0)

# define YYDSYMPRINT(Args)			\
do {						\
  if (yydebug)					\
    yysymprint Args;				\
} while (0)

# define YYDSYMPRINTF(Title, Token, Value, Location)		\
do {								\
  if (yydebug)							\
    {								\
      YYFPRINTF (stderr, "%s ", Title);				\
      yysymprint (stderr, 					\
                  Token, Value);	\
      YYFPRINTF (stderr, "\n");					\
    }								\
} while (0)

/*------------------------------------------------------------------.
| yy_stack_print -- Print the state stack from its BOTTOM up to its |
| TOP (cinluded).                                                   |
`------------------------------------------------------------------*/

#if defined (__STDC__) || defined (__cplusplus)
static void
yy_stack_print (short *bottom, short *top)
#else
static void
yy_stack_print (bottom, top)
    short *bottom;
    short *top;
#endif
{
  YYFPRINTF (stderr, "Stack now");
  for (/* Nothing. */; bottom <= top; ++bottom)
    YYFPRINTF (stderr, " %d", *bottom);
  YYFPRINTF (stderr, "\n");
}

# define YY_STACK_PRINT(Bottom, Top)				\
do {								\
  if (yydebug)							\
    yy_stack_print ((Bottom), (Top));				\
} while (0)


/*------------------------------------------------.
| Report that the YYRULE is going to be reduced.  |
`------------------------------------------------*/

#if defined (__STDC__) || defined (__cplusplus)
static void
yy_reduce_print (int yyrule)
#else
static void
yy_reduce_print (yyrule)
    int yyrule;
#endif
{
  int yyi;
  unsigned int yylineno = yyrline[yyrule];
  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
             yyrule - 1, yylineno);
  /* Print the symbols being reduced, and their result.  */
  for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
}

# define YY_REDUCE_PRINT(Rule)		\
do {					\
  if (yydebug)				\
    yy_reduce_print (Rule);		\
} while (0)

/* Nonzero means print parse trace.  It is left uninitialized so that
   multiple parsers can coexist.  */
int yydebug;
#else /* !YYDEBUG */
# define YYDPRINTF(Args)
# define YYDSYMPRINT(Args)
# define YYDSYMPRINTF(Title, Token, Value, Location)
# define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule)
#endif /* !YYDEBUG */


/* YYINITDEPTH -- initial size of the parser's stacks.  */
#ifndef	YYINITDEPTH
# define YYINITDEPTH 200
#endif

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

   Do not make this value too large; the results are undefined if
   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
   evaluated with infinite-precision integer arithmetic.  */

#if YYMAXDEPTH == 0
# undef YYMAXDEPTH
#endif

#ifndef YYMAXDEPTH
# define YYMAXDEPTH 10000
#endif



#if YYERROR_VERBOSE

# ifndef yystrlen
#  if defined (__GLIBC__) && defined (_STRING_H)
#   define yystrlen strlen
#  else
/* Return the length of YYSTR.  */
static YYSIZE_T
#   if defined (__STDC__) || defined (__cplusplus)
yystrlen (const char *yystr)
#   else
yystrlen (yystr)
     const char *yystr;
#   endif
{
  register const char *yys = yystr;

  while (*yys++ != '\0')
    continue;

  return yys - yystr - 1;
}
#  endif
# endif

# ifndef yystpcpy
#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
#   define yystpcpy stpcpy
#  else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
   YYDEST.  */
static char *
#   if defined (__STDC__) || defined (__cplusplus)
yystpcpy (char *yydest, const char *yysrc)
#   else
yystpcpy (yydest, yysrc)
     char *yydest;
     const char *yysrc;
#   endif
{
  register char *yyd = yydest;
  register const char *yys = yysrc;

  while ((*yyd++ = *yys++) != '\0')
    continue;

  return yyd - 1;
}
#  endif
# endif

#endif /* !YYERROR_VERBOSE */



#if YYDEBUG
/*--------------------------------.
| Print this symbol on YYOUTPUT.  |
`--------------------------------*/

#if defined (__STDC__) || defined (__cplusplus)
static void
yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
#else
static void
yysymprint (yyoutput, yytype, yyvaluep)
    FILE *yyoutput;
    int yytype;
    YYSTYPE *yyvaluep;
#endif
{
  /* Pacify ``unused variable'' warnings.  */
  (void) yyvaluep;

  if (yytype < YYNTOKENS)
    {
      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
# ifdef YYPRINT
      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
# endif
    }
  else
    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);

  switch (yytype)
    {
      default:
        break;
    }
  YYFPRINTF (yyoutput, ")");
}

#endif /* ! YYDEBUG */
/*-----------------------------------------------.
| Release the memory associated to this symbol.  |
`-----------------------------------------------*/

#if defined (__STDC__) || defined (__cplusplus)
static void
yydestruct (int yytype, YYSTYPE *yyvaluep)
#else
static void
yydestruct (yytype, yyvaluep)
    int yytype;
    YYSTYPE *yyvaluep;
#endif
{
  /* Pacify ``unused variable'' warnings.  */
  (void) yyvaluep;

  switch (yytype)
    {

      default:
        break;
    }
}


/* Prevent warnings from -Wmissing-prototypes.  */

#ifdef YYPARSE_PARAM
# if defined (__STDC__) || defined (__cplusplus)
int yyparse (void *YYPARSE_PARAM);
# else
int yyparse ();
# endif
#else /* ! YYPARSE_PARAM */
#if defined (__STDC__) || defined (__cplusplus)
int yyparse (void);
#else
int yyparse ();
#endif
#endif /* ! YYPARSE_PARAM */



/* The lookahead symbol.  */
int yychar;

/* The semantic value of the lookahead symbol.  */
YYSTYPE yylval;

/* Number of syntax errors so far.  */
int yynerrs;



/*----------.
| yyparse.  |
`----------*/

#ifdef YYPARSE_PARAM
# if defined (__STDC__) || defined (__cplusplus)
int yyparse (void *YYPARSE_PARAM)
# else
int yyparse (YYPARSE_PARAM)
  void *YYPARSE_PARAM;
# endif
#else /* ! YYPARSE_PARAM */
#if defined (__STDC__) || defined (__cplusplus)
int
yyparse (void)
#else
int
yyparse ()

#endif
#endif
{
  
  register int yystate;
  register int yyn;
  int yyresult;
  /* Number of tokens to shift before error messages enabled.  */
  int yyerrstatus;
  /* Lookahead token as an internal (translated) token number.  */
  int yytoken = 0;

  /* Three stacks and their tools:
     `yyss': related to states,
     `yyvs': related to semantic values,
     `yyls': related to locations.

     Refer to the stacks thru separate pointers, to allow yyoverflow
     to reallocate them elsewhere.  */

  /* The state stack.  */
  short	yyssa[YYINITDEPTH];
  short *yyss = yyssa;
  register short *yyssp;

  /* The semantic value stack.  */
  YYSTYPE yyvsa[YYINITDEPTH];
  YYSTYPE *yyvs = yyvsa;
  register YYSTYPE *yyvsp;



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

  YYSIZE_T yystacksize = YYINITDEPTH;

  /* The variables used to return semantic value and location from the
     action routines.  */
  YYSTYPE yyval;


  /* When reducing, the number of symbols on the RHS of the reduced
     rule.  */
  int yylen;

  YYDPRINTF ((stderr, "Starting parse\n"));

  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;
  yyvsp = yyvs;

  goto yysetstate;

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

 yysetstate:
  *yyssp = yystate;

  if (yyss + yystacksize - 1 <= yyssp)
    {
      /* Get the current used size of the three stacks, in elements.  */
      YYSIZE_T yysize = yyssp - yyss + 1;

#ifdef yyoverflow
      {
	/* 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;


	/* 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, yysize * sizeof (*yyssp),
		    &yyvs1, yysize * sizeof (*yyvsp),

		    &yystacksize);

	yyss = yyss1;
	yyvs = yyvs1;
      }
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
      goto yyoverflowlab;
# else
      /* Extend the stack our own way.  */
      if (YYMAXDEPTH <= yystacksize)
	goto yyoverflowlab;
      yystacksize *= 2;
      if (YYMAXDEPTH < yystacksize)
	yystacksize = YYMAXDEPTH;

      {
	short *yyss1 = yyss;
	union yyalloc *yyptr =
	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
	if (! yyptr)
	  goto yyoverflowlab;
	YYSTACK_RELOCATE (yyss);
	YYSTACK_RELOCATE (yyvs);

#  undef YYSTACK_RELOCATE
	if (yyss1 != yyssa)
	  YYSTACK_FREE (yyss1);
      }
# endif
#endif /* no yyoverflow */

      yyssp = yyss + yysize - 1;
      yyvsp = yyvs + yysize - 1;


      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
		  (unsigned long int) yystacksize));

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

  YYDPRINTF ((stderr, "Entering state %d\n", yystate));

  goto yybackup;

/*-----------.
| 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 == YYPACT_NINF)
    goto yydefault;

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

  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
  if (yychar == YYEMPTY)
    {
      YYDPRINTF ((stderr, "Reading a token: "));
      yychar = YYLEX;
    }

  if (yychar <= YYEOF)
    {
      yychar = yytoken = YYEOF;
      YYDPRINTF ((stderr, "Now at end of input.\n"));
    }
  else
    {
      yytoken = YYTRANSLATE (yychar);
      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
    }

  /* If the proper action on seeing token YYTOKEN is to reduce or to
     detect an error, take that action.  */
  yyn += yytoken;
  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
    goto yydefault;
  yyn = yytable[yyn];
  if (yyn <= 0)
    {
      if (yyn == 0 || yyn == YYTABLE_NINF)
	goto yyerrlab;
      yyn = -yyn;
      goto yyreduce;
    }

  if (yyn == YYFINAL)
    YYACCEPT;

  /* Shift the lookahead token.  */
  YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));

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

  *++yyvsp = yylval;


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

  yystate = yyn;
  goto yynewstate;


/*-----------------------------------------------------------.
| yydefault -- do the default action for the current state.  |
`-----------------------------------------------------------*/
yydefault:
  yyn = yydefact[yystate];
  if (yyn == 0)
    goto yyerrlab;
  goto yyreduce;


/*-----------------------------.
| yyreduce -- Do a reduction.  |
`-----------------------------*/
yyreduce:
  /* yyn is the number of a rule to reduce with.  */
  yylen = yyr2[yyn];

  /* If YYLEN is nonzero, implement the default value of the action:
     `$$ = $1'.

     Otherwise, the following line sets YYVAL to garbage.
     This behavior is undocumented and Bison
     users should not rely upon it.  Assigning to YYVAL
     unconditionally makes the parser a bit smaller, and it avoids a
     GCC warning that YYVAL may be used uninitialized.  */
  yyval = yyvsp[1-yylen];


  YY_REDUCE_PRINT (yyn);
  switch (yyn)
    {
        case 2:
#line 305 "mglparse.y"
    {
#ifdef PARANOID
			if (curlevel != 0)
				interror(123, "invalid program level");
#endif
			startadr = getlabel(procstack[curlevel]->loc.label);
			YYACCEPT;
		}
    break;

  case 3:
#line 318 "mglparse.y"
    {
			struct sym *sp;

			curlevel = 0;
			if (yyvsp[0].symbol == NULL) {
				error("program identifier expected", FALSE);
				sp = addsym(NULL, SYMBOL_NOREF);
			} else
				sp = newsym(yyvsp[0].symbol, SYMBOL_NOREF);
			sp->type = programsym;
			sp->loc.label = LABEL_NULL;
			sp->def.f.retaddr = 0;
			sp->def.f.varsize = 0;
			sp->def.f.opcode = CMD_NONE;
			sp->def.f.argnum = 0;
			sp->def.f.labels = NULL;
			sp->def.f.ret = NULL;
			sp->def.f.args = NULL;
			procstack[curlevel] = sp;
		}
    break;

  case 5:
#line 343 "mglparse.y"
    { yyerrok; }
    break;

  case 6:
#line 348 "mglparse.y"
    { yyval.symbol = yyvsp[-1].symbol; }
    break;

  case 7:
#line 349 "mglparse.y"
    { yyval.symbol = NULL; yyerrok; }
    break;

  case 17:
#line 382 "mglparse.y"
    {
			ref_t ref;

			/* Determine symbol reference value */
			if (reclevel > 0)
				ref = (ref_t)(recstack[reclevel]);
			else if (inargdef)
				ref = (ref_t)(procstack[curlevel]);
			else
				ref = SYMBOL_NOREF;

			/* Create new symbol list */
			yyval.symlist = NULL;
			if ((yyvsp[0].symbol = newsym(yyvsp[0].symbol, ref)) == NULL)
				error("identifier already defined", TRUE);
			else
				addsymlist(&(yyval.symlist), yyvsp[0].symbol);
		}
    break;

  case 18:
#line 401 "mglparse.y"
    {
			ref_t ref;

			/* Determine symbol reference value */
			if (reclevel > 0)
				ref = (ref_t)(recstack[reclevel]);
			else if (inargdef)
				ref = (ref_t)(procstack[curlevel]);
			else
				ref = SYMBOL_NOREF;

			/* Add symbol to symbol list */
			if ((yyvsp[0].symbol = newsym(yyvsp[0].symbol, ref)) == NULL)
				error("identifier already defined", TRUE);
			else
				addsymlist(&(yyvsp[-2].symlist), yyvsp[0].symbol);
			yyval.symlist = yyvsp[-2].symlist;
		}
    break;

  case 19:
#line 420 "mglparse.y"
    {
			yyval.symlist = yyvsp[-2].symlist;
		}
    break;

  case 20:
#line 424 "mglparse.y"
    {
			yyval.symlist = NULL;
		}
    break;

  case 21:
#line 439 "mglparse.y"
    {
			struct sym *sp;
			struct symlist *slp;

			if (yyvsp[0].symlist == NULL)
				error("one or more labels expected", FALSE);
			else for (slp = yyvsp[0].symlist; slp != NULL; slp = slp->next) {
				sp = slp->sym;
				sp->type = labelsym;
				sp->loc.label = LABEL_NULL;
				docmd(CODE_LABEL, sp, NULL, NULL);
				addsymlist(&(procstack[curlevel]->def.f.labels), sp);
			}
			delsymlist(yyvsp[0].symlist, FALSE);
		}
    break;

  case 24:
#line 472 "mglparse.y"
    {
			if ((yyvsp[0].expr = reorg(yyvsp[0].expr)) == NULL)
				break;
			else if (yyvsp[-1].op != CMD_EQ)
				YYERRPARSE("missing equal sign in constant declaration");
			else if (!isconst(yyvsp[0].expr))
				error("expression not constant", FALSE);
			else if (exprtype(yyvsp[0].expr) != EXPR_NUM &&
			         exprtype(yyvsp[0].expr) != EXPR_STRING &&
			         exprtype(yyvsp[0].expr) != EXPR_CHAR &&
			         exprtype(yyvsp[0].expr) != EXPR_BOOL &&
			         exprtype(yyvsp[0].expr) != EXPR_IPADDR)
				error("invalid constant expression type", FALSE);
			else if ((yyvsp[-2].symbol = newsym(yyvsp[-2].symbol, SYMBOL_NOREF)) == NULL)
				error("name of constant already defined", FALSE);
			else {
				yyvsp[-2].symbol->type = constsym;
				yyvsp[-2].symbol->def.c = yyvsp[0].expr->spec.cval;
				yyvsp[-2].symbol->def.c.t = yyvsp[0].expr->type;
				if (exprtype(yyvsp[0].expr) == EXPR_STRING) {
					yyvsp[-2].symbol->def.c.val.s =
						copy_string(yyvsp[0].expr->spec.cval.val.s);
				}
			}
			delexpr(yyvsp[0].expr);
		}
    break;

  case 25:
#line 499 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("constant declaration expected", FALSE);
		}
    break;

  case 28:
#line 520 "mglparse.y"
    {
			if (yyvsp[-1].op != CMD_EQ)
				YYERRPARSE("missing equal sign in type declaration");
			else if ((yyvsp[-2].symbol = newsym(yyvsp[-2].symbol, SYMBOL_NOREF)) == NULL)
				error("name of type already defined", FALSE);
			else if (yyvsp[0].type == NULL)
				error("type specification expected", FALSE);
			else {
				yyvsp[-2].symbol->type = typesym;
				yyvsp[-2].symbol->def.t = yyvsp[0].type;
			}
		}
    break;

  case 29:
#line 533 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("type declaration expected", FALSE);
		}
    break;

  case 32:
#line 554 "mglparse.y"
    {
			if (yyvsp[-2].symlist == NULL)
				error("missing variable name(s)", FALSE);
			else if (yyvsp[0].type == NULL)
				error("type specification expected", TRUE);
			else
				assignvartype(yyvsp[0].type, yyvsp[-2].symlist);
		}
    break;

  case 33:
#line 563 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("variable declaration expected", FALSE);
		}
    break;

  case 34:
#line 577 "mglparse.y"
    { yyval.type = yyvsp[0].type; }
    break;

  case 35:
#line 578 "mglparse.y"
    { yyval.type = yyvsp[0].type; }
    break;

  case 36:
#line 579 "mglparse.y"
    { yyval.type = yyvsp[0].type; }
    break;

  case 37:
#line 580 "mglparse.y"
    { yyval.type = yyvsp[0].type; }
    break;

  case 38:
#line 581 "mglparse.y"
    { yyval.type = NULL; }
    break;

  case 39:
#line 593 "mglparse.y"
    {
			struct typesdef *tp;

			tp = NULL;
			if (yyvsp[-1].symbol == NULL || isnosym(yyvsp[-1].symbol))
				error("unknown type identifier", FALSE);
			else if (!istypesym(yyvsp[-1].symbol))
				error("identifier is not a type", FALSE);
			else if (yyvsp[-1].symbol->def.t->type == EXPR_NONE)
				error("invalid type identifier", FALSE);
			else if (!isstring(yyvsp[-1].symbol->def.t)) {
				/* Assign non-string type */
				if (yyvsp[0].intarg != 0)
					error("length specification not allowed", FALSE);
				else
					tp = yyvsp[-1].symbol->def.t;
			} else if (yyvsp[-1].symbol->ref != SYMBOL_SYSREF) {
				/* Assign user defined string type */
				if (yyvsp[0].intarg != 0)
					error("cannot redeclare string type", FALSE);
				else
					tp = yyvsp[-1].symbol->def.t;
			} else {
				/*
				 * Strings are a bit special because different
				 * sizes are actually different types. There-
				 * fore we have to create a new type with the
				 * required size.
				 */
				tp = newstrtype(yyvsp[0].intarg);
			}
			yyval.type = tp;
		}
    break;

  case 40:
#line 627 "mglparse.y"
    {
			/* Find a subclass specification of a scalar */

			int submin, submax;
			struct typesdef *tp;

			tp = NULL;
			if ((yyvsp[-2].expr = reorg(yyvsp[-2].expr)) == NULL ||
			    (yyvsp[0].expr = reorg(yyvsp[0].expr)) == NULL)
				goto label1;
			else if (!isconst(yyvsp[-2].expr) || !isconst(yyvsp[0].expr))
				error("subclass specification has to be constant", FALSE);
			else if (!isscalar(yyvsp[-2].expr->type) || !isscalar(yyvsp[0].expr->type))
				error("subclass specification has to be scalar", FALSE);
			else if (exprtype(yyvsp[-2].expr) != exprtype(yyvsp[0].expr) ||
			         yyvsp[-2].expr->type->def.s.min != yyvsp[0].expr->type->def.s.min ||
			         yyvsp[0].expr->type->def.s.max != yyvsp[0].expr->type->def.s.max)
				error("subclass involves different types", FALSE);
			else {
				submin = getord(yyvsp[-2].expr);
				submax = getord(yyvsp[0].expr);
				if (submin > submax ||
				    submin < yyvsp[-2].expr->type->def.s.min ||
				    submax > yyvsp[-2].expr->type->def.s.max)
					error("invalid subclass range", FALSE);
				else {
					/* See if we have the type already */
					for (tp = typetab; tp != NULL;
								tp = tp->next)
						if (tp->type == exprtype(yyvsp[-2].expr) &&
						    tp->def.s.min == submin &&
						    tp->def.s.max == submax)
							break;

					if (tp == NULL) {
						/* No, make a new one */
						tp = newtype();
						tp->size = exprsize(yyvsp[-2].expr);
						tp->type = exprtype(yyvsp[-2].expr);
						tp->def.s.min = submin;
						tp->def.s.max = submax;
						tp->def.s.boundaddr = -1;
						tp->next = typetab;
						typetab = tp;
					}
				}
			}

		label1:
			delexpr(yyvsp[-2].expr);
			delexpr(yyvsp[0].expr);
			yyval.type = tp;
		}
    break;

  case 41:
#line 681 "mglparse.y"
    {
			yyval.type = NULL;
			if (yyvsp[-1].symlist == NULL)
				error("missing names in enumeration", FALSE);
			else
				yyval.type = enumcreate(yyvsp[-1].symlist);
		}
    break;

  case 42:
#line 693 "mglparse.y"
    {
			yyval.intarg = 0;
		}
    break;

  case 43:
#line 697 "mglparse.y"
    {
			yyval.intarg = 0;
			if ((yyvsp[-1].expr = reorg(yyvsp[-1].expr)) == NULL)
				break;
			else if (exprtype(yyvsp[-1].expr) != EXPR_NUM)
				error("length must be a number", FALSE);
			else if (!isconst(yyvsp[-1].expr))
				error("length must be constant", FALSE);
			else if (yyvsp[-1].expr->spec.cval.val.i < 1 ||
			         yyvsp[-1].expr->spec.cval.val.i > MAX_STR_LEN)
				error("invalid length", FALSE);
			else
				yyval.intarg = yyvsp[-1].expr->spec.cval.val.i;
			delexpr(yyvsp[-1].expr);
		}
    break;

  case 44:
#line 713 "mglparse.y"
    {
			yyval.intarg = 0;
			if (!YYRECOVERING())
				error("number expected", FALSE);
		}
    break;

  case 45:
#line 729 "mglparse.y"
    {
			struct typesdef *tp;
			struct typelist *tlp1, *tlp2;

			tp = yyvsp[0].type;
			if (yyvsp[-3].typelist == NULL)
				error("index type for array missing", FALSE);
			else if (tp == NULL)
				error("base type for array missing", FALSE);
			else for (tlp1 = yyvsp[-3].typelist; tlp1 != NULL; tlp1 = tlp1->next) {
				tp = arraycreate(tlp1->t, tp);
				if (tp == NULL)
					break;
			}
			tlp1 = yyvsp[-3].typelist;
			while (tlp1 != NULL) {
				tlp2 = tlp1->next;
				free(tlp1);
				tlp1 = tlp2;
			}
			yyval.type = tp;
		}
    break;

  case 46:
#line 756 "mglparse.y"
    {
			struct typelist *tlp;

			tlp = NULL;
			if (yyvsp[0].type != NULL) {
				tlp = newtypelist();
				tlp->t = yyvsp[0].type;
				tlp->next = NULL;
			}
			yyval.typelist = tlp;
		}
    break;

  case 47:
#line 768 "mglparse.y"
    {
			struct typelist *tlp;

			tlp = NULL;
			if (yyvsp[0].type != NULL) {
				tlp = newtypelist();
				tlp->t = yyvsp[0].type;
				tlp->next = yyvsp[-2].typelist;
			}
			yyval.typelist = tlp;
		}
    break;

  case 48:
#line 780 "mglparse.y"
    {
			struct typelist *tlp1, *tlp2;

			for (tlp1 = yyvsp[-1].typelist; tlp1 != NULL; tlp1 = tlp1->next) {
				tlp2 = tlp1->next;
				free(tlp1);
				tlp1 = tlp2;
			}
			yyval.typelist = NULL;
		}
    break;

  case 49:
#line 801 "mglparse.y"
    {
			struct typesdef *tp;

			tp = NULL;
			if (reclevel > 0) {
				if (recstack[reclevel] != NULL) {
					tp = recordcreate();
					recstack[reclevel] = NULL;
				}
				reclevel--;
			}
			yyval.type = tp;
		}
    break;

  case 50:
#line 815 "mglparse.y"
    {
			if (reclevel > 0) {
				if (recstack[reclevel] != NULL) {
					delsymbols((ref_t)(recstack[reclevel]));
					free(recstack[reclevel]);
					recstack[reclevel] = NULL;
				}
				reclevel--;
			}
			yyval.type = NULL;
		}
    break;

  case 51:
#line 831 "mglparse.y"
    {
			struct typesdef *tp;

			/* Create a new temporary record type */
			tp = newtype();
			tp->type = EXPR_RECORD;
			tp->size = 0;
			tp->def.r.elementnum = 0;
			tp->def.r.elements = NULL;
			tp->next = NULL;

			/* Save record type into symbol stack */
			reclevel++;
			recstack[reclevel] = tp;
		}
    break;

  case 55:
#line 858 "mglparse.y"
    {
			if (yyvsp[-2].symlist == NULL)
				error("missing record element name(s)", FALSE);
			else if (yyvsp[0].type == NULL)
				error("type specification expected", TRUE);
			else
				assignvartype(yyvsp[0].type, yyvsp[-2].symlist);
		}
    break;

  case 56:
#line 877 "mglparse.y"
    {
			struct typesdef *tp = NULL;

			if (yyvsp[0].symbol == NULL)
				error("pointer type expected", TRUE);
			else if (istypesym(yyvsp[0].symbol))
				tp = ptrcreate(yyvsp[0].symbol->def.t);
			else if (!isnosym(yyvsp[0].symbol))
				error("invalid pointer type", FALSE);
			else {
				/* Make new unknown pointer */
				tp = newtype();
				tp->size = pointer_type.size;
				tp->type = EXPR_POINTER;
				tp->def.p.basetype = NULL;
				tp->def.p.unknownsym = yyvsp[0].symbol;
				tp->next = typetab;
				typetab = tp;
			}
			yyval.type = tp;
		}
    break;

  case 58:
#line 914 "mglparse.y"
    {
			procstack[curlevel]->def.f.ret = NULL;
		}
    break;

  case 59:
#line 918 "mglparse.y"
    {
			if (yyvsp[-1].type == NULL)
				error("missing function type", FALSE);
			procstack[curlevel]->def.f.ret = yyvsp[-1].type;
		}
    break;

  case 60:
#line 924 "mglparse.y"
    {
			inargdef = FALSE;
			curclass = CLASS_LOCAL;
			yyerrok;
		}
    break;

  case 61:
#line 930 "mglparse.y"
    {
			inargdef = FALSE;
			curclass = CLASS_LOCAL;
			yyerrok;
		}
    break;

  case 63:
#line 940 "mglparse.y"
    { inargdef = TRUE; }
    break;

  case 64:
#line 940 "mglparse.y"
    { inargdef = FALSE; }
    break;

  case 69:
#line 952 "mglparse.y"
    { curclass = CLASS_REF; }
    break;

  case 70:
#line 952 "mglparse.y"
    { curclass = CLASS_LOCAL; }
    break;

  case 71:
#line 953 "mglparse.y"
    { curclass = CLASS_CONST; }
    break;

  case 72:
#line 953 "mglparse.y"
    { curclass = CLASS_LOCAL; }
    break;

  case 73:
#line 959 "mglparse.y"
    {
			if (yyvsp[-2].symlist == NULL)
				error("missing argument name(s)", FALSE);
			else if (yyvsp[0].type == NULL)
				error("type specification expected", TRUE);
			else
				assignvartype(yyvsp[0].type, yyvsp[-2].symlist);
		}
    break;

  case 74:
#line 972 "mglparse.y"
    {
			if ((yyvsp[0].symbol = newsym(yyvsp[0].symbol, SYMBOL_NOREF)) != NULL) {
				if (curlevel >= MAX_LEVELS)
					error("too many nesting levels", FALSE);
				else {
					curlevel++;
					curclass = CLASS_LOCAL;
					procstack[curlevel] = yyvsp[0].symbol;
					yyvsp[0].symbol->type = funcsym;
					yyvsp[0].symbol->def.f.varsize = 0;
					yyvsp[0].symbol->def.f.argsize = 0;
					yyvsp[0].symbol->def.f.opcode = CMD_USERFUNC;
					yyvsp[0].symbol->def.f.argnum = 0;
					yyvsp[0].symbol->def.f.args = NULL;
					yyvsp[0].symbol->def.f.labels = NULL;
					yyvsp[0].symbol->def.f.ret = NULL;
				}
			} else
				error("invalid procedure/function identifier", TRUE);
		}
    break;

  case 75:
#line 997 "mglparse.y"
    {
			struct sym *sp = procstack[curlevel];

			/*
			 * Count all arguments to the procedure and reverse
			 * the order of the arguments.
			 */
			procargassign(sp);

			/*
			 * For functions care for space for the return value,
			 * if we have a scalar type. Otherwise the space has
			 * to be provided by the caller, and it's address
			 * pushed onto the stack before calling.
			 */
			if (sp->def.f.ret != NULL) {
				if (isscalar(sp->def.f.ret)) {
					sp->def.f.varsize += 2;
					sp->def.f.retaddr = -(sp->def.f.varsize);
				} else {
					sp->def.f.argsize += 4;
					sp->def.f.retaddr = sp->def.f.argsize;
				}
			} else
				sp->def.f.retaddr = 0;
			sp->level = curlevel - 1;
			sp->loc.label = LABEL_NULL;
			docmd(CODE_PROC_START, sp, NULL, NULL);
		}
    break;

  case 76:
#line 1031 "mglparse.y"
    {
			/* Remove any temporary variables */
			procstack[curlevel]->def.f.varsize += freetmpvars();

			/* Delete any labels */
			delsymlist(procstack[curlevel]->def.f.labels, FALSE);

			/* Delete all symbols defined in this nesting level */
			if (curlevel > 0) {
				delsymbols(SYMBOL_ANYREF);
				curlevel--;
				curclass = CLASS_LOCAL;
			}

			/* Return to caller */
			docmd(CODE_PROC_END, NULL, NULL, NULL);
		}
    break;

  case 84:
#line 1074 "mglparse.y"
    {
			if (!islabelsym(yyvsp[0].symbol))
				error("symbol is not a label", TRUE);
			else
				docmd(CODE_LABEL, yyvsp[0].symbol, NULL, NULL);
		}
    break;

  case 85:
#line 1081 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("label identifier expected", FALSE);
		}
    break;

  case 87:
#line 1090 "mglparse.y"
    { docmd(CODE_RESTART, NULL, NULL, NULL); }
    break;

  case 88:
#line 1091 "mglparse.y"
    { docmd(CODE_RETURN, NULL, NULL, NULL); }
    break;

  case 89:
#line 1092 "mglparse.y"
    { docmd(CODE_BREAK, NULL, NULL, NULL); }
    break;

  case 90:
#line 1093 "mglparse.y"
    { delexpr(yyvsp[0].expr); }
    break;

  case 105:
#line 1119 "mglparse.y"
    {
			/* Check for various error conditions */
			if ((yyvsp[0].expr = reorg(yyvsp[0].expr)) == NULL)
				goto label2;
			if (!checkvar(yyvsp[-2].expr))
				goto label2;
			if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type))
				error("variable type doesn't match expression", FALSE);
			else {
				if (isscalar(yyvsp[-2].expr->type) &&
				    isconst(yyvsp[0].expr) &&
				    !isconstrange(yyvsp[0].expr, yyvsp[-2].expr->type))
					warning("subclass range exceeded in scalar assignment");
				docmd(CODE_ASSIGN, NULL, yyvsp[-2].expr, yyvsp[0].expr);
			}

		label2:
			delexpr(yyvsp[0].expr);
			yyval.expr = yyvsp[-2].expr;
		}
    break;

  case 106:
#line 1140 "mglparse.y"
    {
			if ((yyvsp[-4].expr = reorg(yyvsp[-4].expr)) == NULL)
				goto label3;
			else if ((yyvsp[0].expr = reorg(yyvsp[0].expr)) == NULL)
				goto label3;
			else if (exprtype(yyvsp[-4].expr) != EXPR_NUM)
				error("invalid BOOTP index type", FALSE);
			else if (!istypesym(yyvsp[-8].symbol))
				error("missing or invalid BOOTP type", FALSE);
			else if (!checkassign(yyvsp[-8].symbol->def.t, yyvsp[0].expr->type))
				error("BOOTP type doesn't match expression", FALSE);
			else {
				struct expr *ep;

				ep = newexpr();
				ep->type = &int_type;
				ep->opcode = CMD_CONST;
				ep->exprnum = 0;
				ep->spec.cval.t = ep->type;
				ep->spec.cval.val.i =
					exprtype(yyvsp[0].expr) == EXPR_STRING ? 1 : 0;
				ep = genrtfunc(RTCMD_PUTBOOTP, yyvsp[-4].expr, yyvsp[0].expr, ep);
				docmd(CODE_CALL_PROC, NULL, ep, NULL);
				delexpr(ep);
				break;
			}

		label3:
			delexpr(yyvsp[-4].expr);
			delexpr(yyvsp[0].expr);
			yyval.expr = NULL;
		}
    break;

  case 107:
#line 1173 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("variable identifier expected", FALSE);
			delexpr(yyvsp[0].expr);
			yyval.expr = NULL;
		}
    break;

  case 108:
#line 1180 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("expression expected", FALSE);
			yyval.expr = yyvsp[-2].expr;
		}
    break;

  case 109:
#line 1196 "mglparse.y"
    {
			if (!isfuncsym(yyvsp[-3].symbol) || yyvsp[-3].symbol->def.f.ret != NULL)
				error("symbol is not a procedure", FALSE);
			else if (yyvsp[-1].expr != NULL &&
			         (yyvsp[-1].expr = setprocexpr(yyvsp[-3].symbol, yyvsp[-1].expr)) != NULL)
				docmd(CODE_CALL_PROC, NULL, yyvsp[-1].expr, NULL);
			delexpr(yyvsp[-1].expr);
		}
    break;

  case 110:
#line 1205 "mglparse.y"
    {
			/* Special case for procedures without arguments */
			struct expr *ep;

			ep = newexpr();
			ep->exprnum = 0;
			if (!isfuncsym(yyvsp[0].symbol) || yyvsp[0].symbol->def.f.ret != NULL)
				error("symbol is not a procedure", FALSE);
			else if ((ep = setprocexpr(yyvsp[0].symbol, ep)) != NULL)
				docmd(CODE_CALL_PROC, NULL, ep, NULL);
			delexpr(ep);
		}
    break;

  case 111:
#line 1218 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("invalid procedure arguments", FALSE);
		}
    break;

  case 113:
#line 1234 "mglparse.y"
    {
			struct expr *ep;
			int symnum = -1;
			int isipaddr = FALSE;
			int i;

			if (yyvsp[-1].expr == NULL ||
			    yyvsp[-1].expr->type != NULL ||
			    yyvsp[-1].expr->opcode != CMD_NONE) {
				error("expression list expected", TRUE);
				delexpr(yyvsp[-1].expr);
				break;
			}

			for (i = 0; i < yyvsp[-1].expr->exprnum; i++) {
				ep = yyvsp[-1].expr->exprlist[i];
				yyvsp[-1].expr->exprlist[i] = NULL;
				if ((ep = reorg(ep)) == NULL)
					continue;

				switch (exprtype(ep)) {
					case EXPR_NUM:
						symnum = RTCMD_PRINTINT;
						break;
					case EXPR_IPADDR:
						isipaddr = TRUE;
						/* fall through */
					case EXPR_STRING:
						symnum = RTCMD_PRINTSTR;
						break;
					case EXPR_CHAR:
						symnum = RTCMD_PRINTCHR;
						break;
					default:
						break;
				}

				if (symnum < 0)
					error("invalid expression in print command", FALSE);
				else {
					if (isipaddr) {
						ep = genrtfunc(RTCMD_IP2STR,
								ep, NULL, NULL);
						ep = reorg(ep);
					}
					ep = genrtfunc(symnum, ep, NULL, NULL);
					docmd(CODE_CALL_PROC, NULL, ep, NULL);
				}
				delexpr(ep);
			}
			delexpr(yyvsp[-1].expr);
		}
    break;

  case 114:
#line 1287 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("expression expected in print command", FALSE);
		}
    break;

  case 115:
#line 1296 "mglparse.y"
    {
			yyval.expr = newexpr();
			yyval.expr->type = NULL;
			yyval.expr->opcode = CMD_NONE;
			yyval.expr->exprnum = 1;
			yyval.expr->exprlist[0] = yyvsp[0].expr;
		}
    break;

  case 116:
#line 1304 "mglparse.y"
    {
			if (yyvsp[-2].expr == NULL ||
			    yyvsp[-2].expr->type != NULL ||
			    yyvsp[-2].expr->opcode != CMD_NONE)
				error("expression list expected", TRUE);
			else if (yyvsp[-2].expr->exprnum >= MAX_EXPRS)
				error("too many print expressions", FALSE);
			else {
				yyval.expr = yyvsp[-2].expr;
				yyval.expr->exprlist[yyval.expr->exprnum++] = yyvsp[0].expr;
				break;
			}
			delexpr(yyvsp[-2].expr);
			delexpr(yyvsp[0].expr);
		}
    break;

  case 117:
#line 1320 "mglparse.y"
    {
			delexpr(yyvsp[-1].expr);
			if (!YYRECOVERING())
				error("expression list expected", FALSE);
		}
    break;

  case 119:
#line 1330 "mglparse.y"
    { /* everything handled in coordinates */ }
    break;

  case 120:
#line 1342 "mglparse.y"
    {
			docmd(CODE_ENDNEST, NULL, NULL, NULL);
		}
    break;

  case 122:
#line 1351 "mglparse.y"
    {
			docmd(CODE_SELECT, NULL, NULL, NULL);
			if (yyvsp[0].expr == NULL)
				error("timeout value expected with select statement", FALSE);
			else {
				struct expr *ep;

				ep = genrtfunc(RTCMD_SELECT, yyvsp[0].expr, NULL, NULL);
				docmd(CODE_CALL_PROC, NULL, ep, NULL);
				delexpr(ep);
				break;
			}
			delexpr(yyvsp[0].expr);
		}
    break;

  case 126:
#line 1377 "mglparse.y"
    {
			if ((yyvsp[-1].expr = reorg(yyvsp[-1].expr)) == NULL)
				break;
			else if (exprtype(yyvsp[-1].expr) != EXPR_NUM)
				error("numerical value required for item number", FALSE);
			else if (!isconst(yyvsp[-1].expr))
				error("constant value required for item number", FALSE);
			else if (yyvsp[-1].expr->spec.cval.val.i < 0 ||
			         yyvsp[-1].expr->spec.cval.val.i > 9)
				error("item identifier out of range", FALSE);
			else
				docmd(CODE_ITEM, NULL, yyvsp[-1].expr, NULL);
			delexpr(yyvsp[-1].expr);
		}
    break;

  case 127:
#line 1392 "mglparse.y"
    {
			struct expr ep;

			memzero(&ep, sizeof(ep));
			ep.type = &int_type;
			ep.opcode = CMD_CONST;
			ep.exprnum = 0;
			ep.spec.cval.t = ep.type;
			ep.spec.cval.val.i = -1;
			docmd(CODE_ITEM, NULL, &ep, NULL);
		}
    break;

  case 128:
#line 1414 "mglparse.y"
    {
			int symnum = -1;

			/* Check that we really have a variable */
			if (!checkvar(yyvsp[-2].expr))
				goto label9;

			/* Determine name of function to call */
			switch (exprtype(yyvsp[-2].expr)) {
				case EXPR_NUM:
					if (checkassign(yyvsp[-2].expr->type, &int_type))
						symnum = RTCMD_GETINT;
					break;
				case EXPR_IPADDR:
				case EXPR_STRING:
					if (checkassign(yyvsp[-2].expr->type, &string_type))
						symnum = RTCMD_GETSTR;
					break;
				case EXPR_CHAR:
					if (checkassign(yyvsp[-2].expr->type, &char_type))
						symnum = RTCMD_GETCHR;
					break;
				default:
					break;
			}

			/* Check for various error conditions and call 'get' */
			if (symnum < 0)
				error("invalid type in get command", FALSE);
			else {
				struct expr *ep;

				ep = genrtfunc(symnum, yyvsp[0].expr, NULL, NULL);
				if (exprtype(yyvsp[-2].expr) == EXPR_IPADDR)
					ep = genrtfunc(RTCMD_STR2IP, ep, NULL, NULL);
				docmd(CODE_ASSIGN, NULL, yyvsp[-2].expr, ep);
				delexpr(ep);
				yyvsp[0].expr = NULL;
			}

		label9:
			delexpr(yyvsp[-2].expr);
			delexpr(yyvsp[0].expr);
		}
    break;

  case 129:
#line 1459 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("variable expected in get command", FALSE);
		}
    break;

  case 130:
#line 1474 "mglparse.y"
    {
			if (!islabelsym(yyvsp[0].symbol))
				error("symbol is not a label", TRUE);
			else if (yyvsp[0].symbol->level != curlevel)
				error("jump outside of current block", FALSE);
			else
				docmd(CODE_GOTO, yyvsp[0].symbol, NULL, NULL);
		}
    break;

  case 131:
#line 1483 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("jump label expected", TRUE);
		}
    break;

  case 132:
#line 1498 "mglparse.y"
    {
			struct expr *ep;

			if (!inexcept)
				YYERRPARSE("expression expected");
			else {
				ep = newexpr();
				ep->type = &int_type;
				ep->opcode = CMD_CONST;
				ep->exprnum = 0;
				ep->spec.cval.t = ep->type;
				ep->spec.cval.val.i = 0;
				ep = genrtfunc(RTCMD_RAISE, ep, NULL, NULL);
				docmd(CODE_CALL_PROC, NULL, ep, NULL);
				delexpr(ep);
			}
		}
    break;

  case 133:
#line 1516 "mglparse.y"
    {
			struct expr *ep;

			if ((yyvsp[0].expr = reorg(yyvsp[0].expr)) == NULL)
				break;
			else if (exprtype(yyvsp[0].expr) != EXPR_NUM)
				error("exception must be a number", FALSE);
			else {
				ep = genrtfunc(RTCMD_RAISE, yyvsp[0].expr, NULL, NULL);
				docmd(CODE_CALL_PROC, NULL, ep, NULL);
				delexpr(ep);
				break;
			}
			delexpr(yyvsp[0].expr);
		}
    break;

  case 134:
#line 1541 "mglparse.y"
    { inexcept = FALSE; }
    break;

  case 135:
#line 1542 "mglparse.y"
    {
			struct expr *ep;

			/* End try...except nesting */
			docmd(CODE_ENDNEST, NULL, NULL, NULL);

			/* Generate code to delete any exception info */
			ep = genrtfunc(RTCMD_ENDEXCEPT, NULL, NULL, NULL);
			docmd(CODE_CALL_PROC, NULL, ep, NULL);
			delexpr(ep);
		}
    break;

  case 136:
#line 1558 "mglparse.y"
    {
			struct expr *ep1, *ep2;

			/* Create constant zero */
			ep1 = newexpr();
			ep1->type = &int_type;
			ep1->opcode = CMD_CONST;
			ep1->exprnum = 0;
			ep1->spec.cval.t = ep1->type;
			ep1->spec.cval.val.i = 0;

			/*
			 * Create expression to check the return value of
			 * handletry function against 0.
			 */
			ep2 = newexpr();
			ep2->type = &bool_type;
			ep2->opcode = CMD_EQ;
			ep2->exprnum = 2;
			ep2->left = genrtfunc(RTCMD_HANDLETRY,
							NULL, NULL, NULL);
			ep2->right = ep1;

			/* Generate appropriate code */
			if ((ep2 = reorg(ep2)) != NULL) {
				docmd(CODE_IF, NULL, ep2, NULL);
				delexpr(ep2);
			}
		}
    break;

  case 137:
#line 1592 "mglparse.y"
    {
			docmd(CODE_ELSE, NULL, NULL, NULL);
			inexcept = TRUE;
		}
    break;

  case 138:
#line 1607 "mglparse.y"
    {
			struct expr *ep;

			if (!checkvar(yyvsp[-1].expr))
				goto label10;

			if (exprtype(yyvsp[-1].expr) != EXPR_POINTER ||
			    yyvsp[-1].expr->type == NULL ||
			    getptrbase(yyvsp[-1].expr->type) == NULL)
				error("pointer variable expected", FALSE);
			else {
				/* Create expression to allocate memory */
				ep = newexpr();
				ep->opcode = CMD_CONST;
				ep->type = &int_type;
				ep->exprnum = 0;
				ep->spec.cval.t = ep->type;
				ep->spec.cval.val.i =
						getptrbase(yyvsp[-1].expr->type)->size;
				ep = genrtfunc(RTCMD_MALLOC, ep, NULL, NULL);

				/* Assign memory address to pointer */
				docmd(CODE_ASSIGN, NULL, yyvsp[-1].expr, ep);
				delexpr(ep);
			}

		label10:
			delexpr(yyvsp[-1].expr);
		}
    break;

  case 139:
#line 1637 "mglparse.y"
    {
			struct expr *ep;

			if (!checkvar(yyvsp[-1].expr))
				goto label11;

			if (exprtype(yyvsp[-1].expr) != EXPR_POINTER)
				error("pointer variable expected", FALSE);
			else {
				/* Create expression to free memory */
				ep = genrtfunc(RTCMD_FREE, yyvsp[-1].expr, NULL, NULL);
				docmd(CODE_CALL_PROC, NULL, ep, NULL);
				delexpr(ep);
				break;
			}

		label11:
			delexpr(yyvsp[-1].expr);
		}
    break;

  case 140:
#line 1667 "mglparse.y"
    {
			docmd(CODE_ENDNEST, NULL, NULL, NULL);
		}
    break;

  case 141:
#line 1671 "mglparse.y"
    {
			docmd(CODE_ENDNEST, NULL, NULL, NULL);
		}
    break;

  case 142:
#line 1679 "mglparse.y"
    {
			yyvsp[0].expr = makeboolexpr(yyvsp[0].expr);
			docmd(CODE_IF, NULL, yyvsp[0].expr, NULL);
			delexpr(yyvsp[0].expr);
		}
    break;

  case 143:
#line 1688 "mglparse.y"
    { docmd(CODE_ELSE, NULL, NULL, NULL); }
    break;

  case 145:
#line 1700 "mglparse.y"
    {
			docmd(CODE_ENDNEST, NULL, NULL, NULL);
		}
    break;

  case 146:
#line 1708 "mglparse.y"
    {
			yyvsp[0].expr = makeboolexpr(yyvsp[0].expr);
			docmd(CODE_WHILE, NULL, yyvsp[0].expr, NULL);
			delexpr(yyvsp[0].expr);
		}
    break;

  case 147:
#line 1724 "mglparse.y"
    {
			yyvsp[0].expr = makeboolexpr(yyvsp[0].expr);
			docmd(CODE_ENDNEST, NULL, yyvsp[0].expr, NULL);
			delexpr(yyvsp[0].expr);
		}
    break;

  case 148:
#line 1734 "mglparse.y"
    {
			docmd(CODE_REPEAT, NULL, NULL, NULL);
		}
    break;

  case 149:
#line 1748 "mglparse.y"
    {
			struct expr *ep;

			/*
			 * The for_name action passes us a dummy expression
			 * which contains sub-expressions necessary for termi-
			 * nating the loop.
			 */
			if (yyvsp[-2].expr == NULL)
				break;

			/* Create the increment/decrement command */
			ep = newexpr();
			*ep = *(yyvsp[-2].expr->exprlist[0]);
			yyvsp[-2].expr->exprlist[1]->type = yyvsp[-2].expr->type;
			yyvsp[-2].expr->exprlist[1]->exprnum = 1;
			yyvsp[-2].expr->exprlist[1]->exprlist[0] = ep;
			docmd(CODE_ASSIGN, NULL, yyvsp[-2].expr->exprlist[0],
							yyvsp[-2].expr->exprlist[1]);
			free(ep);
			yyvsp[-2].expr->exprlist[1]->exprnum = 0;
			yyvsp[-2].expr->exprlist[1]->exprlist[0] = NULL;

			/* Terminate the while-loop */
			docmd(CODE_ENDNEST, NULL, NULL, NULL);

			/*
			 * This will delete everything, including releasing
			 * any temporary variables.
			 */
			delexpr(yyvsp[-2].expr);
		}
    break;

  case 150:
#line 1785 "mglparse.y"
    {
			struct expr *ep1, *ep2;

			yyval.expr = NULL;
			if (yyvsp[-2].expr == NULL || !isscalar(yyvsp[-2].expr->type))
				error("scalar variable expected in for command", FALSE);
			else if (!isvariable(yyvsp[-2].expr))
				error("variable expected in for command", FALSE);
			else if ((yyvsp[0].expr = reorg(yyvsp[0].expr)) == NULL)
				goto label4;
			else if (!isscalar(yyvsp[0].expr->type))
				error("scalar expression expected as end value", FALSE);
			else if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type))
				error("type of end value doesn't match variable type", FALSE);
			else {
				/* Create assignment of end value to temp variable */
				ep1 = NULL;
				if (!isconst(yyvsp[0].expr)) {
					ep1 = createtmpvar(yyvsp[-2].expr->type,
							procstack[curlevel]);
					docmd(CODE_ASSIGN, NULL, ep1, yyvsp[0].expr);
				} else if (!isconstrange(yyvsp[0].expr, yyvsp[-2].expr->type))
					warning("subclass range exceeded in scalar end value");

				/* Create beginning of while loop */
				ep2 = newexpr();
				ep2->type = &bool_type;
				ep2->opcode = (yyvsp[-1].expr->opcode == CMD_SUCC ?
								CMD_LE : CMD_GE);
				ep2->exprnum = 2;
				ep2->left = yyvsp[-2].expr;
				ep2->right = (ep1 == NULL ? yyvsp[0].expr : ep1);
				docmd(CODE_WHILE, NULL, ep2, NULL);

				/* Dummy expression to pass everything down */
				ep2->type = yyvsp[-2].expr->type;
				ep2->opcode = CMD_NONE;
				ep2->exprnum = (ep1 == NULL ? 2 : 3);
				ep2->exprlist[0] = yyvsp[-2].expr;
				ep2->exprlist[1] = yyvsp[-1].expr;
				ep2->exprlist[2] = ep1;
				delexpr(yyvsp[0].expr);
				yyval.expr = ep2;
				break;
			}

		label4:
			delexpr(yyvsp[-2].expr);
			delexpr(yyvsp[-1].expr);
			delexpr(yyvsp[0].expr);
		}
    break;

  case 151:
#line 1841 "mglparse.y"
    {
			yyval.expr = newexpr();
			yyval.expr->opcode = CMD_SUCC;
		}
    break;

  case 152:
#line 1846 "mglparse.y"
    {
			yyval.expr = newexpr();
			yyval.expr->opcode = CMD_PRED;
		}
    break;

  case 153:
#line 1861 "mglparse.y"
    {
			if ((yyvsp[-2].expr = reorg(yyvsp[-2].expr)) == NULL)
				goto label5;
			else if (exprtype(yyvsp[-2].expr) != EXPR_STRING)
				error("string value expected as filename", FALSE);
			else {
				struct expr *ep;

				if (yyvsp[-1].expr == NULL)
					yyvsp[-1].expr = genrtvar(RTVAR_TFTP);
				if (yyvsp[0].expr == NULL)
					yyvsp[0].expr = genrtvar(RTVAR_GATEWAY);
				ep = genrtfunc(RTCMD_LOAD, yyvsp[-2].expr, yyvsp[-1].expr, yyvsp[0].expr);
				docmd(CODE_CALL_PROC, NULL, ep, NULL);
				delexpr(ep);
				break;
			}

		label5:
			delexpr(yyvsp[-2].expr);
			delexpr(yyvsp[-1].expr);
			delexpr(yyvsp[0].expr);
		}
    break;

  case 154:
#line 1885 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("filename expected in load command", FALSE);
		}
    break;

  case 155:
#line 1894 "mglparse.y"
    {
			yyval.expr = NULL;
		}
    break;

  case 156:
#line 1897 "mglparse.y"
    { YYEXPECT(yyvsp[0].symbol, "from"); }
    break;

  case 157:
#line 1898 "mglparse.y"
    {
			yyval.expr = yyvsp[0].expr;
		}
    break;

  case 158:
#line 1901 "mglparse.y"
    { YYEXPECT(yyvsp[0].symbol, "from"); }
    break;

  case 159:
#line 1902 "mglparse.y"
    {
			yyval.expr = NULL;
			if (!YYRECOVERING())
				error("IP address expected", TRUE);
		}
    break;

  case 160:
#line 1912 "mglparse.y"
    {
			yyval.expr = NULL;
		}
    break;

  case 161:
#line 1915 "mglparse.y"
    { YYEXPECT(yyvsp[0].symbol, "gateway"); }
    break;

  case 162:
#line 1916 "mglparse.y"
    {
			yyval.expr = yyvsp[0].expr;
		}
    break;

  case 163:
#line 1919 "mglparse.y"
    { YYEXPECT(yyvsp[0].symbol, "gateway"); }
    break;

  case 164:
#line 1920 "mglparse.y"
    {
			yyval.expr = NULL;
			if (!YYRECOVERING())
				error("IP address expected", TRUE);
		}
    break;

  case 165:
#line 1936 "mglparse.y"
    {
			yyval.expr = NULL;
			if ((yyvsp[-2].expr = reorg(yyvsp[-2].expr)) == NULL)
				break;
			else if (exprtype(yyvsp[-2].expr) != EXPR_NUM)
				error("invalid BOOTP index type", FALSE);
			else if (!istypesym(yyvsp[-6].symbol))
				error("missing or invalid BOOTP type", FALSE);
			else {
				struct expr *ep;

				ep = newexpr();
				ep->type = &int_type;
				ep->opcode = CMD_CONST;
				ep->exprnum = 0;
				ep->spec.cval.t = ep->type;
				ep->spec.cval.val.i =
						isstring(yyvsp[-6].symbol->def.t) ? 1 : 0;
				yyval.expr = genrtfunc(RTCMD_GETBOOTP, yyvsp[-2].expr, ep, NULL);
				yyval.expr->type = yyvsp[-6].symbol->def.t;
				break;
			}
			delexpr(yyvsp[-2].expr);
		}
    break;

  case 166:
#line 1960 "mglparse.y"
    { yyval.expr = yyvsp[-1].expr; }
    break;

  case 167:
#line 1961 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 168:
#line 1962 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 169:
#line 1963 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 170:
#line 1964 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 171:
#line 1965 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 172:
#line 1977 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[-2].expr, yyvsp[0].expr, TRUE))
				break;
			if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type) ||
			    (exprtype(yyvsp[-2].expr) != EXPR_NUM &&
			     exprtype(yyvsp[-2].expr) != EXPR_BOOL)) {
				error("invalid operation", FALSE);
				delexpr(yyvsp[-2].expr);
				delexpr(yyvsp[0].expr);
			} else {
				ep = newexpr();
				ep->type = (exprtype(yyvsp[-2].expr) == EXPR_NUM ?
							&int_type : &bool_type);
				ep->exprnum = 2;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[-2].expr;
				ep->right = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 173:
#line 2001 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[-2].expr, yyvsp[0].expr, TRUE))
				break;
			if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type) ||
			    (exprtype(yyvsp[-2].expr) != EXPR_NUM &&
			     exprtype(yyvsp[-2].expr) != EXPR_BOOL)) {
				error("invalid operation", FALSE);
				delexpr(yyvsp[-2].expr);
				delexpr(yyvsp[0].expr);
			} else {
				ep = newexpr();
				ep->type = (exprtype(yyvsp[-2].expr) == EXPR_NUM ?
							&int_type : &bool_type);
				ep->exprnum = 2;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[-2].expr;
				ep->right = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 174:
#line 2025 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[-2].expr, yyvsp[0].expr, TRUE))
				break;
			if (yyvsp[-1].op == '+' &&
			    ((exprtype(yyvsp[-2].expr) == EXPR_CHAR ||
			      exprtype(yyvsp[-2].expr) == EXPR_STRING) &&
			     (exprtype(yyvsp[0].expr) == EXPR_CHAR ||
			      exprtype(yyvsp[0].expr) == EXPR_STRING))) {
				int cmdcode;

				if (exprtype(yyvsp[-2].expr) == EXPR_CHAR &&
				    exprtype(yyvsp[0].expr) == EXPR_CHAR)
					cmdcode = RTCMD_STRCATCC;
				else if (exprtype(yyvsp[-2].expr) == EXPR_CHAR &&
				         exprtype(yyvsp[0].expr) == EXPR_STRING)
					cmdcode = RTCMD_STRCATCS;
				else if (exprtype(yyvsp[-2].expr) == EXPR_STRING &&
				         exprtype(yyvsp[0].expr) == EXPR_CHAR)
					cmdcode = RTCMD_STRCATSC;
				else
					cmdcode = RTCMD_STRCAT;
				yyval.expr = genrtfunc(cmdcode, yyvsp[-2].expr, yyvsp[0].expr, NULL);
			} else if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type) ||
			           exprtype(yyvsp[-2].expr) != EXPR_NUM) {
				error("invalid operation", FALSE);
				delexpr(yyvsp[-2].expr);
				delexpr(yyvsp[0].expr);
			} else {
				ep = newexpr();
				ep->type = &int_type;
				ep->exprnum = 2;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[-2].expr;
				ep->right = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 175:
#line 2066 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[-2].expr, yyvsp[0].expr, TRUE))
				break;
			if (yyvsp[-1].op == '*' &&
			    exprtype(yyvsp[-2].expr) == EXPR_CHAR &&
			    exprtype(yyvsp[0].expr) == EXPR_NUM)
				yyval.expr = genrtfunc(RTCMD_STRSET, yyvsp[-2].expr, yyvsp[0].expr, NULL);
			else if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type) ||
			           exprtype(yyvsp[-2].expr) != EXPR_NUM) {
				error("invalid operation", FALSE);
				delexpr(yyvsp[-2].expr);
				delexpr(yyvsp[0].expr);
			} else {
				ep = newexpr();
				ep->type = &int_type;
				ep->exprnum = 2;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[-2].expr;
				ep->right = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 176:
#line 2092 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[-2].expr, yyvsp[0].expr, TRUE))
				break;
			if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type) ||
			    (isnonscalar(yyvsp[-2].expr->type) &&
			     exprtype(yyvsp[-2].expr) != EXPR_STRING) ||
			    (isnonscalar(yyvsp[0].expr->type) &&
			     exprtype(yyvsp[0].expr) != EXPR_STRING)) {
				error("invalid comparison", FALSE);
				delexpr(yyvsp[-2].expr);
				delexpr(yyvsp[0].expr);
			} else if (exprtype(yyvsp[-2].expr) == EXPR_STRING &&
			           exprtype(yyvsp[0].expr) == EXPR_STRING) {
				ep = newexpr();
				ep->type = &int_type;
				ep->opcode = CMD_CONST;
				ep->exprnum = 0;
				ep->spec.cval.t = ep->type;
				ep->spec.cval.val.i = mapcmp((int)yyvsp[-1].op);
				yyval.expr = genrtfunc(RTCMD_STRCMP, yyvsp[-2].expr, yyvsp[0].expr, ep);
			} else if (isnonscalar(yyvsp[-2].expr->type) ||
			           isnonscalar(yyvsp[0].expr->type)) {
				if (yyvsp[-1].op != CMD_EQ && yyvsp[-1].op != CMD_NE) {
					error("invalid non-scalar comparison", FALSE);
					yyvsp[-1].op = CMD_EQ;
				}
				ep = newexpr();
				ep->type = &int_type;
				ep->opcode = CMD_CONST;
				ep->exprnum = 0;
				ep->spec.cval.t = ep->type;
				ep->spec.cval.val.i = mapcmp((int)yyvsp[-1].op);
				yyval.expr = genrtfunc(RTCMD_MEMCMP, yyvsp[-2].expr, yyvsp[0].expr, ep);
			} else {
				if ((ispointer(yyvsp[-2].expr->type) ||
				     ispointer(yyvsp[0].expr->type)) &&
				    (yyvsp[-1].op != CMD_EQ && yyvsp[-1].op != CMD_NE)) {
					error("invalid pointer comparison", FALSE);
					yyvsp[-1].op = CMD_EQ;
				}
				ep = newexpr();
				ep->type = &bool_type;
				ep->exprnum = 2;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[-2].expr;
				ep->right = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 177:
#line 2155 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[0].expr, NULL, FALSE))
				break;
			if (exprtype(yyvsp[0].expr) != EXPR_BOOL &&
			    exprtype(yyvsp[0].expr) != EXPR_NUM) {
				error("NOT operation not allowed", FALSE);
				delexpr(yyvsp[0].expr);
			} else {
				ep = newexpr();
				ep->type = (exprtype(yyvsp[0].expr) == EXPR_NUM ?
							&int_type : &bool_type);
				ep->exprnum = 1;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 178:
#line 2176 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[0].expr, NULL, FALSE))
				break;
			if (exprtype(yyvsp[0].expr) != EXPR_NUM) {
				error("unary operation not allowed", FALSE);
				delexpr(yyvsp[0].expr);
			} else if (yyvsp[-1].op == '-') {
				ep = newexpr();
				ep->type = &int_type;
				ep->exprnum = 1;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[0].expr;
				yyval.expr = ep;
			} else if (yyvsp[-1].op == '+') {
				yyval.expr = yyvsp[0].expr;
			}
		}
    break;

  case 179:
#line 2206 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 180:
#line 2207 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 181:
#line 2208 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 182:
#line 2209 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 183:
#line 2215 "mglparse.y"
    {
			struct expr *ep;
			struct typesdef *tp;
			struct varinfo *vp;

			yyval.expr = NULL;
			if (yyvsp[0].symbol == NULL)
				error ("missing variable name", FALSE);
			else if (inexcept && issymname(yyvsp[0].symbol, "exception"))
				yyval.expr = genrtvar(RTVAR_EXCEPTION);
			else if (isnosym(yyvsp[0].symbol))
				error("symbol not defined", FALSE);
			else if (isconstsym(yyvsp[0].symbol)) {
				ep &bool_type);
				ep->exprnum = 1;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 214:
#line 2865 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[0].expr, NULL, FALSE))
				break;

			if (exprtype(yyvsp[0].expr) != EXPR_NUM) {
				error("unary operation not allowed", FALSE);
				delexpr(yyvsp[0].expr);
			} else if (yyvsp[-1].op == '-') {
				ep = newexpr();
				ep->type = &int_type;
				ep->exprnum = 1;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[0].expr;
				yyval.expr = ep;
			} else if (yyvsp[-1].op == '+') {
				yyval.expr = yyvsp[0].expr;
			}
		}
    break;

  case 215:
#line 2897 "mglparse.y"
    {
			if ((yyvsp[-3].expr = reorg(yyvsp[-3].expr)) == NULL ||
			    (yyvsp[-1].expr = reorg(yyvsp[-1].expr)) == NULL)
				goto label8;
			else if (exprtype(yyvsp[-3].expr) != EXPR_NUM ||
			         exprtype(yyvsp[-1].expr) != EXPR_NUM)
				error("coordinate values have to be numerical", FALSE);
			else {
				struct expr *ep;

				ep = genrtfunc(RTCMD_GOTOXY, yyvsp[-3].expr, yyvsp[-1].expr, NULL);
				docmd(CODE_CALL_PROC, NULL, ep, NULL);
				delexpr(ep);
				break;
			}

		label8:
			delexpr(yyvsp[-3].expr);
			delexpr(yyvsp[-1].expr);
		}
    break;

  case 216:
#line 2922 "mglparse.y"
    {
			struct expr *ep;

			ep = newexpr();
			ep->opcode = CMD_CONST;
			ep->type = &int_type;
			ep->exprnum = 0;
			ep->spec.cval.t = ep->type;
			ep->spec.cval.val.i = 0;
			yyval.expr = ep;
		}
    break;

  case 217:
#line 2933 "mglparse.y"
    { YYEXPECT(yyvsp[0].symbol, "timeout"); }
    break;

  case 218:
#line 2934 "mglparse.y"
    {
			yyval.expr = NULL;
			if ((yyvsp[0].expr = reorg(yyvsp[0].expr)) == NULL)
				break;
			else if (exprtype(yyvsp[0].expr) != EXPR_NUM) {
				error("timeout value has to be a number", FALSE);
				delexpr(yyvsp[0].expr);
			} else
				yyval.expr = yyvsp[0].expr;
		}
    break;

  case 219:
#line 2944 "mglparse.y"
    { YYEXPECT(yyvsp[0].symbol, "timeout"); }
    break;

  case 220:
#line 2945 "mglparse.y"
    {
			yyval.expr = NULL;
			if (!YYRECOVERING())
				error("expression expected for timeout value", FALSE);
		}
    break;

  case 221:
#line 2955 "mglparse.y"
    {
			yyval.expr = NULL;
			if ((yyvsp[0].expr = reorg(yyvsp[0].expr)) == NULL)
				break;
			else if (exprtype(yyvsp[0].expr) == EXPR_STRING) {
				yyval.expr = genrtfunc(RTCMD_STR2IP, yyvsp[0].expr, NULL, NULL);
				break;
			} else if (exprtype(yyvsp[0].expr) == EXPR_IPADDR) {
				yyval.expr = yyvsp[0].expr;
				break;
			} else {
				error("IP address expected", FALSE);
				delexpr(yyvsp[0].expr);
			}
		}
    break;


    }

/* Line 991 of yacc.c.  */
#line 4382 "y.tab.c"

  yyvsp -= yylen;
  yyssp -= yylen;


  YY_STACK_PRINT (yyss, yyssp);

  *++yyvsp = yyval;


  /* 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 - YYNTOKENS] + *yyssp;
  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
    yystate = yytable[yystate];
  else
    yystate = yydefgoto[yyn - YYNTOKENS];

  goto yynewstate;


/*------------------------------------.
| yyerrlab -- here on detecting error |
`------------------------------------*/
yyerrlab:
  /* If not already recovering from an error, report this error.  */
  if (!yyerrstatus)
    {
      ++yynerrs;
#if YYERROR_VERBOSE
      yyn = yypact[yystate];

      if (YYPACT_NINF < yyn && yyn < YYLAST)
	{
	  YYSIZE_T yysize = 0;
	  int yytype = YYTRANSLATE (yychar);
	  char *yymsg;
	  int yyx, yycount;

	  yycount = 0;
	  /* Start YYX at -YYN if negative to avoid negative indexes in
	     YYCHECK.  */
	  for (yyx = yyn < 0 ? -yyn : 0;
	       yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
	      yysize += yystrlen (yytname[yyx]) + 15, yycount++;
	  yysize += yystrlen ("syntax error, unexpected ") + 1;
	  yysize += yystrlen (yytname[yytype]);
	  yymsg = (char *) YY;
				yyval.expr = yyvsp[-2].expr;
				break;
			}

			/* Now handle ordinary records */
			if (exprtype(yyvsp[-2].expr) != EXPR_RECORD) {
				error("record variable expected", FALSE);
				goto label7;
			}
			if (yyvsp[0].symbol == NULL) {
				error("record variant expected", FALSE);
				goto label7;
			}

			/* Find the symbol in the record item list */
			if (yyvsp[0].symbol->ref == (ref_t)(yyvsp[-2].expr->type))
				sp = yyvsp[0].symbol;
			else
				sp = findsym(yyvsp[0].symbol->name, (ref_t)(yyvsp[-2].expr->type));
			if (sp == NULL) {
				error("record variant unknown", FALSE);
				goto label7;
			}
#ifdef PARANOID
			if (!isrecsym(sp))
				interror(102, "invalid symbol list in record specification");
#endif

			/* Generate a new variable info record */
			vp->next = newvarinfo();
			vp = vp->next;
			vp->cmd = recordelement;
			vp->vartype = sp->def.v.t;
			vp->spec.recsym = sp;
			vp->next = NULL;
			yyvsp[-2].expr->type = sp->def.v.t;
			yyval.expr = yyvsp[-2].expr;
			break;

		label7:
			delexpr(yyvsp[-2].expr);
		}
    break;

  case 187:
#line 2411 "mglparse.y"
    {
			struct typesdef *tp;
			struct varinfo *vp;

			/* Check that we have a pointer variable */
			yyval.expr = NULL;
			if (yyvsp[-1].expr == NULL || !isvariable(yyvsp[-1].expr) ||
			    yyvsp[-1].expr->spec.var == NULL ||
			    exprtype(yyvsp[-1].expr) != EXPR_POINTER) {
				error("pointer variable expected", FALSE);
				goto label6;
			}

			/* Determine the type of the variable */
			tp = getptrbase(yyvsp[-1].expr->type);
			if (tp == NULL) {
				error("unknown pointer type", FALSE);
				goto label6;
			}
			if (isanytype(tp)) {
				error("pointer has no type", FALSE);
				goto label6;
			}

			/* Generate a new variable info record */
			vp = yyvsp[-1].expr->spec.var;
			while (vp->next != NULL)
				vp = vp->next;
			vp->next = newvarinfo();
			vp = vp->next;
			vp->cmd = ptrderef;
			vp->vartype = tp;
			vp->next = NULL;
			yyvsp[-1].expr->type = tp;
			yyval.expr = yyvsp[-1].expr;
			break;

		label6:
			delexpr(yyvsp[-1].expr);
		}
    break;

  case 188:
#line 2462 "mglparse.y"
    {
			struct expr *ep;

			ep = newexpr();
			ep->opcode = CMD_CONST;
			ep->type = &int_type;
			ep->exprnum = 0;
			ep->spec.cval.t = ep->type;
			ep->spec.cval.val.i = yyvsp[0].intarg;
			yyval.expr = ep;
		}
    break;

  case 189:
#line 2474 "mglparse.y"
    {
			struct expr *ep;

			ep = newexpr();
			ep->opcode = CMD_CONST;
			ep->type = &string_type;
			ep->exprnum = 0;
			ep->spec.cval.t = ep->type;
			ep->spec.cval.val.s = yyvsp[0].string;
			yyval.expr = ep;
		}
    break;

  case 190:
#line 2486 "mglparse.y"
    {
			struct expr *ep;

			ep = newexpr();
			ep->opcode = CMD_CONST;
			ep->type = &char_type;
			ep->exprnum = 0;
			ep->spec.cval.t = ep->type;
			ep->spec.cval.val.c = yyvsp[0].chrarg;
			yyval.expr = ep;
		}
    break;

  case 191:
#line 2498 "mglparse.y"
    {
			struct expr *ep;

			ep = newexpr();
			ep->opcode = CMD_CONST;
			ep->type = &ipaddr_type;
			ep->exprnum = 0;
			ep->spec.cval.t = ep->type;
			ep->spec.cval.val.a = yyvsp[0].ipaddr;
			yyval.expr = ep;
		}
    break;

  case 192:
#line 2521 "mglparse.y"
    {
			yyval.expr = NULL;
			if (isnosym(yyvsp[-3].symbol)) {
				error("function not defined", FALSE);
				delexpr(yyvsp[-1].expr);
			} else if (!isfuncsym(yyvsp[-3].symbol)) {
				error("symbol in expression is not a function", FALSE);
				delexpr(yyvsp[-1].expr);
			} else if (!iscmdscalar(&(yyvsp[-3].symbol->def.f))) {
				/* Handle normal function call */
				if (yyvsp[-1].expr == NULL)
					error("missing function arguments", FALSE);
				else
					yyval.expr = setprocexpr(yyvsp[-3].symbol, yyvsp[-1].expr);
			} else if (yyvsp[-1].expr == NULL || yyvsp[-1].expr->exprnum != 1) {
				error("invalid number of arguments", FALSE);
				delexpr(yyvsp[-1].expr);
			} else if (!isscalar(yyvsp[-1].expr->left->type)) {
				error("scalar expression required", FALSE);
				delexpr(yyvsp[-1].expr);
			} else {
				/*
				 * General scalar operations need special
				 * handling because they can operate on a
				 * variety of data types. By using the
				 * checks 'iscmdscalar' and 'isscalar' we
				 * should be pretty sure that we have a
				 * correct function call.
				 */
				yyvsp[-1].expr->type = yyvsp[-3].symbol->def.f.opcode == CMD_ORD ?
						&int_type : yyvsp[-1].expr->left->type;
				yyvsp[-1].expr->opcode = yyvsp[-3].symbol->def.f.opcode;
				yyvsp[-1].expr->spec.func = yyvsp[-3].symbol;
				yyval.expr = yyvsp[-1].expr;
			}
		}
    break;

  case 193:
#line 2558 "mglparse.y"
    {
			if (!YYRECOVERING())
				error("invalid function arguments", FALSE);
			yyval.expr = NULL;
		}
    break;

  case 194:
#line 2568 "mglparse.y"
    {
			struct expr *ep;

			ep = newexpr();
			ep->exprnum = 0;
			yyval.expr = ep;
		}
    break;

  case 195:
#line 2576 "mglparse.y"
    {
			yyval.expr = yyvsp[0].expr;
		}
    break;

  case 196:
#line 2584 "mglparse.y"
    {
			struct expr *ep;

			ep = newexpr();
			ep->exprnum = 1;
			ep->exprlist[0] = yyvsp[0].expr;
			yyval.expr = ep;
		}
    break;

  case 197:
#line 2593 "mglparse.y"
    {
			yyvsp[0].expr->exprlist[yyvsp[0].expr->exprnum] = yyvsp[-2].expr;
			yyvsp[0].expr->exprnum++;
			yyval.expr = yyvsp[0].expr;
		}
    break;

  case 198:
#line 2599 "mglparse.y"
    {
			struct expr *ep;

			ep = newexpr();
			ep->exprnum = 1;
			ep->exprlist[0] = yyvsp[-2].expr;
			yyval.expr = ep;
		}
    break;

  case 199:
#line 2608 "mglparse.y"
    {
			yyval.expr = yyvsp[0].expr;
		}
    break;

  case 200:
#line 2621 "mglparse.y"
    { yyval.expr = yyvsp[-1].expr; }
    break;

  case 201:
#line 2622 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 202:
#line 2623 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 203:
#line 2624 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 204:
#line 2625 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 205:
#line 2631 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 206:
#line 2632 "mglparse.y"
    { yyval.expr = yyvsp[0].expr; }
    break;

  case 207:
#line 2638 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (isnosym(yyvsp[0].symbol) || yyvsp[0].symbol == NULL)
				error("symbol not defined", TRUE);
			else if (!isconstsym(yyvsp[0].symbol))
				error("constant symbol expected", TRUE);
			else {
				ep = newexpr();
				ep->opcode = CMD_CONST;
				ep->exprnum = 0;
				ep->type = yyvsp[0].symbol->def.c.t;
				ep->spec.cval = yyvsp[0].symbol->def.c;
				if (isstring(yyvsp[0].symbol->def.c.t))
					ep->spec.cval.val.s =
						copy_string(yyvsp[0].symbol->def.c.val.s);
				yyval.expr = ep;
			}
		}
    break;

  case 208:
#line 2669 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[-2].expr, yyvsp[0].expr, TRUE))
				break;
			if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type) ||
			    (exprtype(yyvsp[-2].expr) != EXPR_NUM &&
			     exprtype(yyvsp[-2].expr) != EXPR_BOOL)) {
				error("invalid operation", FALSE);
				delexpr(yyvsp[-2].expr);
				delexpr(yyvsp[0].expr);
			} else {
				ep = newexpr();
				ep->type = (exprtype(yyvsp[-2].expr) == EXPR_NUM ?
							&int_type : &bool_type);
				ep->exprnum = 2;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[-2].expr;
				ep->right = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 209:
#line 2693 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[-2].expr, yyvsp[0].expr, TRUE))
				break;
			if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type) ||
			    (exprtype(yyvsp[-2].expr) != EXPR_NUM &&
			     exprtype(yyvsp[-2].expr) != EXPR_BOOL)) {
				error("invalid operation", FALSE);
				delexpr(yyvsp[-2].expr);
				delexpr(yyvsp[0].expr);
			} else {
				ep = newexpr();
				ep->type = (exprtype(yyvsp[-2].expr) == EXPR_NUM ?
							&int_type : &bool_type);
				ep->exprnum = 2;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[-2].expr;
				ep->right = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 210:
#line 2717 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[-2].expr, yyvsp[0].expr, TRUE))
				break;
			if (yyvsp[-1].op == '+' &&
			    ((exprtype(yyvsp[-2].expr) == EXPR_CHAR ||
			      exprtype(yyvsp[-2].expr) == EXPR_STRING) &&
			     (exprtype(yyvsp[0].expr) == EXPR_CHAR ||
			      exprtype(yyvsp[0].expr) == EXPR_STRING))) {
				int cmdcode;

				if (exprtype(yyvsp[-2].expr) == EXPR_CHAR &&
				    exprtype(yyvsp[0].expr) == EXPR_CHAR)
					cmdcode = RTCMD_STRCATCC;
				else if (exprtype(yyvsp[-2].expr) == EXPR_CHAR &&
				         exprtype(yyvsp[0].expr) == EXPR_STRING)
					cmdcode = RTCMD_STRCATCS;
				else if (exprtype(yyvsp[-2].expr) == EXPR_STRING &&
				         exprtype(yyvsp[0].expr) == EXPR_CHAR)
					cmdcode = RTCMD_STRCATSC;
				else
					cmdcode = RTCMD_STRCAT;
				yyval.expr = genrtfunc(cmdcode, yyvsp[-2].expr, yyvsp[0].expr, NULL);
			} else if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type) ||
			           exprtype(yyvsp[-2].expr) != EXPR_NUM) {
				error("invalid operation", FALSE);
				delexpr(yyvsp[-2].expr);
				delexpr(yyvsp[0].expr);
			} else {
				ep = newexpr();
				ep->type = &int_type;
				ep->exprnum = 2;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[-2].expr;
				ep->right = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 211:
#line 2758 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[-2].expr, yyvsp[0].expr, TRUE))
				break;
			if (yyvsp[-1].op == '*' &&
			    exprtype(yyvsp[-2].expr) == EXPR_CHAR &&
			    exprtype(yyvsp[0].expr) == EXPR_NUM)
				yyval.expr = genrtfunc(RTCMD_STRSET, yyvsp[-2].expr, yyvsp[0].expr, NULL);
			else if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type) ||
			           exprtype(yyvsp[-2].expr) != EXPR_NUM) {
				error("invalid operation", FALSE);
				delexpr(yyvsp[-2].expr);
				delexpr(yyvsp[0].expr);
			} else {
				ep = newexpr();
				ep->type = &int_type;
				ep->exprnum = 2;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[-2].expr;
				ep->right = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 212:
#line 2784 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[-2].expr, yyvsp[0].expr, TRUE))
				break;
			if (!checkassign(yyvsp[-2].expr->type, yyvsp[0].expr->type)) {
				error("invalid comparison", FALSE);
				delexpr(yyvsp[-2].expr);
				delexpr(yyvsp[0].expr);
			} else if (exprtype(yyvsp[-2].expr) == EXPR_STRING &&
			           exprtype(yyvsp[0].expr) == EXPR_STRING) {
				ep = newexpr();
				ep->type = &int_type;
				ep->opcode = CMD_CONST;
				ep->exprnum = 0;
				ep->spec.cval.t = ep->type;
				ep->spec.cval.val.i = mapcmp((int)yyvsp[-1].op);
				yyval.expr = genrtfunc(RTCMD_STRCMP, yyvsp[-2].expr, yyvsp[0].expr, ep);
			} else if (isnonscalar(yyvsp[-2].expr->type) ||
			           isnonscalar(yyvsp[0].expr->type)) {
				if (yyvsp[-1].op != CMD_EQ && yyvsp[-1].op != CMD_NE) {
					error("invalid non-scalar comparison", FALSE);
					yyvsp[-1].op = CMD_EQ;
				}
				ep = newexpr();
				ep->type = &int_type;
				ep->opcode = CMD_CONST;
				ep->exprnum = 0;
				ep->spec.cval.t = ep->type;
				ep->spec.cval.val.i = mapcmp((int)yyvsp[-1].op);
				yyval.expr = genrtfunc(RTCMD_MEMCMP, yyvsp[-2].expr, yyvsp[0].expr, ep);
			} else {
				if ((ispointer(yyvsp[-2].expr->type) ||
				     ispointer(yyvsp[0].expr->type)) &&
				    (yyvsp[-1].op != CMD_EQ && yyvsp[-1].op != CMD_NE)) {
					error("invalid pointer comparison", FALSE);
					yyvsp[-1].op = CMD_EQ;
				}
				ep = newexpr();
				ep->type = &bool_type;
				ep->exprnum = 2;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[-2].expr;
				ep->right = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 213:
#line 2843 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[0].expr, NULL, FALSE))
				break;

			if (exprtype(yyvsp[0].expr) != EXPR_BOOL &&
			    exprtype(yyvsp[0].expr) != EXPR_NUM) {
				error("NOT operation not allowed", FALSE);
				delexpr(yyvsp[0].expr);
			} else {
				ep = newexpr();
				ep->type = (exprtype(yyvsp[0].expr) == EXPR_NUM ?
							&int_type : &bool_type);
				ep->exprnum = 1;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[0].expr;
				yyval.expr = ep;
			}
		}
    break;

  case 214:
#line 2865 "mglparse.y"
    {
			struct expr *ep;

			yyval.expr = NULL;
			if (!checkexpr(yyvsp[0].expr, NULL, FALSE))
				break;

			if (exprtype(yyvsp[0].expr) != EXPR_NUM) {
				error("unary operation not allowed", FALSE);
				delexpr(yyvsp[0].expr);
			} else if (yyvsp[-1].op == '-') {
				ep = newexpr();
				ep->type = &int_type;
				ep->exprnum = 1;
				ep->opcode = yyvsp[-1].op;
				ep->left = yyvsp[0].expr;
				yyval.expr = ep;
			} else if (yyvsp[-1].op == '+') {
				yyval.expr = yyvsp[0].expr;
			}
		}
    break;

  case 215:
#line 2897 "mglparse.y"
    {
			if ((yyvsp[-3].expr = reorg(yyvsp[-3].expr)) == NULL ||
			    (yyvsp[-1].expr = reorg(yyvsp[-1].expr)) == NULL)
				goto label8;
			else if (exprtype(yyvsp[-3].expr) != EXPR_NUM ||
			         exprtype(yyvsp[-1].expr) != EXPR_NUM)
				error("coordinate values have to be numerical", FALSE);
			else {
				struct expr *ep;

				ep = genrtfunc(RTCMD_GOTOXY, yyvsp[-3].expr, yyvsp[-1].expr, NULL);
				docmd(CODE_CALL_PROC, NULL, ep, NULL);
				delexpr(ep);
				break;
			}

		label8:
			delexpr(yyvsp[-3].expr);
			delexpr(yyvsp[-1].expr);
		}
    break;

  case 216:
#line 2922 "mglparse.y"
    {
			struct expr *ep;

			ep = newexpr();
			ep->opcode = CMD_CONST;
			ep->type = &int_type;
			ep->exprnum = 0;
			ep->spec.cval.t = ep->type;
			ep->spec.cval.val.i = 0;
			yyval.expr = ep;
		}
    break;

  case 217:
#line 2933 "mglparse.y"
    { YYEXPECT(yyvsp[0].symbol, "timeout"); }
    break;

  case 218:
#line 2934 "mglparse.y"
    {
			yyval.expr = NULL;
			if ((yyvsp[0].expr = reorg(yyvsp[0].expr)) == NULL)
				break;
			else if (exprtype(yyvsp[0].expr) != EXPR_NUM) {
				error("timeout value has to be a number", FALSE);
				delexpr(yyvsp[0].expr);
			} else
				yyval.expr = yyvsp[0].expr;
		}
    break;

  case 219:
#line 2944 "mglparse.y"
    { YYEXPECT(yyvsp[0].symbol, "timeout"); }
    break;

  case 220:
#line 2945 "mglparse.y"
    {
			yyval.expr = NULL;
			if (!YYRECOVERING())
				error("expression expected for timeout value", FALSE);
		}
    break;

  case 221:
#line 2955 "mglparse.y"
    {
			yyval.expr = NULL;
			if ((yyvsp[0].expr = reorg(yyvsp[0].expr)) == NULL)
				break;
			else if (exprtype(yyvsp[0].expr) == EXPR_STRING) {
				yyval.expr = genrtfunc(RTCMD_STR2IP, yyvsp[0].expr, NULL, NULL);
				break;
			} else if (exprtype(yyvsp[0].expr) == EXPR_IPADDR) {
				yyval.expr = yyvsp[0].expr;
				break;
			} else {
				error("IP address expected", FALSE);
				delexpr(yyvsp[0].expr);
			}
		}
    break;


    }

/* Line 991 of yacc.c.  */
#line 4382 "y.tab.c"

  yyvsp -= yylen;
  yyssp -= yylen;


  YY_STACK_PRINT (yyss, yyssp);

  *++yyvsp = yyval;


  /* 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 - YYNTOKENS] + *yyssp;
  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
    yystate = yytable[yystate];
  else
    yystate = yydefgoto[yyn - YYNTOKENS];

  goto yynewstate;


/*------------------------------------.
| yyerrlab -- here on detecting error |
`------------------------------------*/
yyerrlab:
  /* If not already recovering from an error, report this error.  */
  if (!yyerrstatus)
    {
      ++yynerrs;
#if YYERROR_VERBOSE
      yyn = yypact[yystate];

      if (YYPACT_NINF < yyn && yyn < YYLAST)
	{
	  YYSIZE_T yysize = 0;
	  int yytype = YYTRANSLATE (yychar);
	  char *yymsg;
	  int yyx, yycount;

	  yycount = 0;
	  /* Start YYX at -YYN if negative to avoid negative indexes in
	     YYCHECK.  */
	  for (yyx = yyn < 0 ? -yyn : 0;
	       yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
	      yysize += yystrlen (yytname[yyx]) + 15, yycount++;
	  yysize += yystrlen ("syntax error, unexpected ") + 1;
	  yysize += yystrlen (yytname[yytype]);
	  yymsg = (char *) YYSTACK_ALLOC (yysize);
	  if (yymsg != 0)
	    {
	      char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
	      yyp = yystpcpy (yyp, yytname[yytype]);

	      if (yycount < 5)
		{
		  yycount = 0;
		  for (yyx = yyn < 0 ? -yyn : 0;
		       yyx < (int) (sizeof (yytname) / sizeof (char *));
		       yyx++)
		    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
		      {
			const char *yyq = ! yycount ? ", expecting " : " or ";
			yyp = yystpcpy (yyp, yyq);
			yyp = yystpcpy (yyp, yytname[yyx]);
			yycount++;
		      }
		}
	      yyerror (yymsg);
	      YYSTACK_FREE (yymsg);
	    }
	  else
	    yyerror ("syntax error; also virtual memory exhausted");
	}
      else
#endif /* YYERROR_VERBOSE */
	yyerror ("syntax error");
    }



  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)
        {
	  /* Pop the error token.  */
          YYPOPSTACK;
	  /* Pop the rest of the stack.  */
	  while (yyss < yyssp)
	    {
	      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
	      yydestruct (yystos[*yyssp], yyvsp);
	      YYPOPSTACK;
	    }
	  YYABORT;
        }

      YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
      yydestruct (yytoken, &yylval);
      yychar = YYEMPTY;

    }

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


/*----------------------------------------------------.
| yyerrlab1 -- error raised explicitly by an action.  |
`----------------------------------------------------*/
yyerrlab1:

  /* Suppress GCC warning that yyerrlab1 is unused when no action
     invokes YYERROR.  */
#if defined (__GNUC_MINOR__) && 2093 <= (__GNUC__ * 1000 + __GNUC_MINOR__) \
    && !defined __cplusplus
  __attribute__ ((__unused__))
#endif


  goto yyerrlab2;


/*---------------------------------------------------------------.
| yyerrlab2 -- pop states until the error token can be shifted.  |
`---------------------------------------------------------------*/
yyerrlab2:
  yyerrstatus = 3;	/* Each real token shifted decrements this.  */

  for (;;)
    {
      yyn = yypact[yystate];
      if (yyn != YYPACT_NINF)
	{
	  yyn += YYTERROR;
	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
	    {
	      yyn = yytable[yyn];
	      if (0 < yyn)
		break;
	    }
	}

      /* Pop the current state because it cannot handle the error token.  */
      if (yyssp == yyss)
	YYABORT;

      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
      yydestruct (yystos[yystate], yyvsp);
      yyvsp--;
      yystate = *--yyssp;

      YY_STACK_PRINT (yyss, yyssp);
    }

  if (yyn == YYFINAL)
    YYACCEPT;

  YYDPRINTF ((stderr, "Shifting error token, "));

  *++yyvsp = yylval;


  yystate = yyn;
  goto yynewstate;


/*-------------------------------------.
| yyacceptlab -- YYACCEPT comes here.  |
`-------------------------------------*/
yyacceptlab:
  yyresult = 0;
  goto yyreturn;

/*-----------------------------------.
| yyabortlab -- YYABORT comes here.  |
`-----------------------------------*/
yyabortlab:
  yyresult = 1;
  goto yyreturn;

#ifndef yyoverflow
/*----------------------------------------------.
| yyoverflowlab -- parser overflow comes here.  |
`----------------------------------------------*/
yyoverflowlab:
  yyerror ("parser stack overflow");
  yyresult = 2;
  /* Fall through.  */
#endif

yyreturn:
#ifndef yyoverflow
  if (yyss != yyssa)
    YYSTACK_FREE (yyss);
#endif
  return yyresult;
}


#line 2972 "mglparse.y"



/*
 *****************************************************************************
 *
 * Check that both parts of a binary expression are available
 */
static int checkexpr(e1, e2, binary)
struct expr *e1;
struct expr *e2;
int binary;
{
  if (e1 == NULL || (e2 == NULL && binary)) {
	if (e1 != NULL)
		delexpr(e1);
	if (e2 != NULL && binary)
		delexpr(e2);
	return(FALSE);
  }
  return(TRUE);
}



/*
 *****************************************************************************
 *
 * Check if an expression is boolean, and make it a boolean constant if
 * it's not. This check is used by the conditional operators to maintain
 * nesting consistency in case of error.
 */
static struct expr *makeboolexpr(ep)
struct expr *ep;
{
  /* Check that the expression is boolean */
  ep = reorg(ep);
  if (ep != NULL && exprtype(ep) != EXPR_BOOL) {
	error("boolean expression expected", FALSE);
	delexpr(ep);
	ep = NULL;
  }

  /* If it's not boolean, make it a boolean constant */
  if (ep == NULL) {
	ep = newexpr();
	ep->type = &bool_type;
	ep->opcode = CMD_CONST;
	ep->exprnum = 0;
	ep->spec.cval.t = ep->type;
	ep->spec.cval.val.b = FALSE;
  }
  return(ep);
}



/*
 *****************************************************************************
 *
 * Scan through the current symbol list and assign a variable type to
 * all symbols.
 */
static void assignvartype(tp, symlist)
struct typesdef *tp;
struct symlist *symlist;
{
  struct sym *sp;
  struct symlist *slp;
  addr_t varsize;

  /* Scan thorugh symbol list and process each symbol */
  for (slp = symlist; slp != NULL; slp = slp->next) {
	if ((sp = slp->sym) == NULL)
		continue;
	sp->type = varsym;
	sp->def.v.t = tp;
	varsize = tp->size;
	if (reclevel > 0) {
		/*
		 * We are preparing a record definition. This has to come
		 * before any procedure argument list handling!
		 */
		sp->type = recsym;
		sp->level = -1;		/* required for code generator */
		sp->loc.addr = recstack[reclevel]->size;
		recstack[reclevel]->size += varsize;
		recstack[reclevel]->def.r.elementnum++;
		addsymlist(&(recstack[reclevel]->def.r.elements), sp);
		sp->def.v.class = CLASS_STATIC;
	} else if (inargdef) {
		/*
		 * We are preparing an argument list to a function or
		 * procedure. There, non-scalars get always passed as
		 * pointers. If they have to be passed by value, the
		 * caller has to provide a copy of the argument value
		 * on the stack before calling the procedure.
		 * Additionally, when a string gets passed by reference,
		 * not only the address but also the string size gets
		 * pushed onto the stack.
		 * We use sp->loc.addr to temporarily save the size of the
		 * argument on the stack. A positive value of sp->loc.addr
		 * marks this as an argument to a function.
		 */
		if (curclass == CLASS_REF)
			sp->loc.addr = (isstring(tp) || isanytype(tp) ? 4 : 2);
		else
			sp->loc.addr = (isscalar(tp) || ispointer(tp) ?
					(varsize + 1) & 0xfffe : 2);
		sp->def.v.class = curclass;
	} else if (curlevel > 0) {
		/*
		 * We are preparing a list of variables local to a
		 * procedure or function.
		 */
		procstack[curlevel]->def.f.varsize += (varsize + 1) & 0xfffe;
		sp->loc.addr = -(procstack[curlevel]->def.f.varsize);
		sp->def.v.class = CLASS_LOCAL;
	} else {
		/*
		 * We are preparing a global variable.
		 */
		sp->loc.addr = dataptr;
		dataptr += varsize;
		sp->def.v.class = CLASS_STATIC;
	}
  }

  /* Finally delete the symbol list, but not the symbols */
  delsymlist(symlist, FALSE);
}



/*
 *****************************************************************************
 *
 * Return a pointer to an enumeration type which has the elements listed
 * in the current symbol list.
 */
static struct typesdef *enumcreate(slist)
struct symlist *slist;
{
  struct symlist *slp;
  struct typesdef *tp = newtype();

  /* Prepare all symbols for constant values */
  for (slp = slist; slp != NULL; slp = slp->next) {
	slp->sym->type = constsym;
	slp->sym->def.c.t = tp;
	slp->sym->def.c.val.e = slp->num;
  }

  /* Create the new enumeration type */
  tp->type = EXPR_ENUM;
  tp->def.s.boundaddr = -1;
  tp->def.s.min = 0;
  tp->def.s.max = slist->num;
  tp->size = int_type.size;
  tp->next = typetab;
  typetab = tp;

  /* Release the symbol list and return the new enumeration type */
  delsymlist(slist, FALSE);
  return(tp);
}



/*
 *****************************************************************************
 *
 * Return a pointer to an array type.
 */
static struct typesdef *arraycreate(index, base)
struct typesdef *index;
struct typesdef *base;
{
  struct typesdef *tp;
  int elementnum;
  addr_t size;

  /* Just for safety */
  if (index == NULL || base == NULL)
	return(NULL);

  /* Find out the number of elements in the array */
  if (!isscalar(index)) {
	error("scalar type required for array index", FALSE);
	return(NULL);
  }
  elementnum = index->def.s.max - index->def.s.min + 1;
#ifdef PARANOID
  if (elementnum < 1)
	interror(3, "number of elements in array < 1");
#endif

  /* Determine the total size of the new array type */
  size = elementnum * base->size;
  if (size > MAX_ARRAY_SIZE) {
	error("array size too large", FALSE);
	return(NULL);
  }

  /* We can now safely create a new enumeration type */
  tp = newtype();
  tp->type = EXPR_ARRAY;
  tp->def.a.indextype = index;
  tp->def.a.basetype = base;
  tp->size = size;
  tp->next = typetab;
  typetab = tp;
  return(tp);
}



/*
 *****************************************************************************
 *
 * Create a record type
 */
static struct typesdef *recordcreate()
{
  /* Just for safety */
  if (recstack[reclevel] == NULL)
	return(NULL);

  /* Check for some errors */
  if (recstack[reclevel]->def.r.elements == NULL ||
      recstack[reclevel]->def.r.elementnum == 0) {
	error("no elements defined in record definition", FALSE);
	goto recdelete;
  }
  if (recstack[reclevel]->size > MAX_REC_SIZE) {
	error("record too large", FALSE);
	goto recdelete;
  }

  /* We can now insert the new record type into the types list */
  recstack[reclevel]->next = typetab;
  typetab = recstack[reclevel];
  return(recstack[reclevel]);

recdelete:
  delsymlist(recstack[reclevel]->def.r.elements, TRUE);
  free(recstack[reclevel]);
  return(NULL);
}



/*
 *****************************************************************************
 *
 * Return a pointer to a pointer type.
 */
static struct typesdef *ptrcreate(base)
struct typesdef *base;
{
  struct typesdef *tp;

  /* See if we have the pointer type already */
  for (tp = typetab; tp != NULL; tp = tp->next)
	if (getptrbase(tp) == base)
		break;

  /* No, make a new one */
  if (tp == NULL) {
	tp = newtype();
	tp->size = pointer_type.size;
	tp->type = EXPR_POINTER;
	tp->def.p.basetype = base;
	tp->def.p.unknownsym = NULL;
	tp->next = typetab;
	typetab = tp;
  }
  return(tp);
}



/*
 *****************************************************************************
 *
 * Determine the base type of a pointer. This is not as easy as it looks
 * because pointers can have a forward type reference. Therefore, if a
 * base type has not been defined for a pointer, we look at the symbol by
 * which the pointer has been defined, and if that's defined, we can
 * use it's type.
 */
static struct typesdef *getptrbase(ptr)
struct typesdef *ptr;
{
  struct sym *sp;

  /* Check that we have a pointer at all */
  if (!ispointer(ptr))
	return(NULL);

  /* Get the base type from the pointer type record if available */
  if (ptr->def.p.basetype != NULL)
	return(ptr->def.p.basetype);

  /* Get the base type from the definition symbol */
  sp = ptr->def.p.unknownsym;
  if (sp == NULL || !istypesym(sp) || sp->def.t == NULL)
	return(NULL);
  ptr->def.p.basetype = sp->def.t;
  ptr->def.p.unknownsym = NULL;
  return(sp->def.t);
}



/*
 *****************************************************************************
 *
 * Lookup the symbol table and assign all symbols, which are arguments to
 * the current procedure or function, to that procedure. It returns the
 * total size of the arguments on the stack.
 */
static void procargassign(proc)
struct sym *proc;
{
  struct symlist *slp, *arglist;
  addr_t argsize, argptr;
  int argnum, i;

  /*
   * Count all arguments to the procedure. This will also reverse the
   * order of the arguments.
   */
  argsize = 0;
  arglist = createsymlist((ref_t)proc);
  for (slp = arglist, i = 0; slp != NULL; slp = slp->next)
	if (isvarsym(slp->sym) && slp->sym->loc.addr > 0) {
		argsize += slp->sym->loc.addr;
		i++;
	}

  /* Check the number of arguments */
  argnum = i;
  if (argnum > MAX_EXPRS) {
	error("Too many function arguments", FALSE);
	argnum = MAX_EXPRS;
  }

  /*
   * Update the procedure symbol definition and the offsets to the procedure
   * arguments.
   */
  proc->def.f.args = NULL;
  proc->def.f.argnum = argnum;
  proc->def.f.argsize = argsize;
  if (i > 0) {
	argptr = argsize + 4;
	proc->def.f.args = (struct vardef *)nbmalloc(sizeof(struct vardef) * i);
	for (slp = arglist, i = 0; slp != NULL && i < argnum; slp = slp->next)
		if (isvarsym(slp->sym) && slp->sym->loc.addr > 0) {
			argptr -= slp->sym->loc.addr;
			slp->sym->loc.addr = argptr;
			proc->def.f.args[i] = slp->sym->def.v;
			i++;
		}
  }

  /* Finally delete the symbol list, but not the symbols themselves */
  delsymlist(arglist, FALSE);
}



/*
 *****************************************************************************
 *
 * Check if two types are assignable to each other
 */
static int checkassign(type1, type2)
struct typesdef *type1;
struct typesdef *type2;
{
  /* This is just for safety */
  if (type1 == NULL || type2 == NULL)
	return(FALSE);

  /*
   * If the types are exactly the same, we can always assign. Also, if the
   * destination type is EXPR_ANY, we can always assign (EXPR_ANY is only
   * used for runtime functions).
   */
  if (type1 == type2 || isanytype(type1))
	return(TRUE);

  /* Enumerations have to be exactly the same */
  if (isenum(type1) || isenum(type2))
	return(type1 == type2);

  /*
   * With pointers, each type the pointers point to have to be assignable.
   * A pointer with any type is always assignable.
   */
  if (ispointer(type1) && ispointer(type2)) {
	struct typesdef *bp1 = getptrbase(type1);
	struct typesdef *bp2 = getptrbase(type2);

	if (isanytype(bp2))
		return(TRUE);
	return(checkassign(bp1, bp2));
  }

  /*
   * With scalars, the types have to be the same, and the ranges must not
   * be disjunct.
   */
  if (isscalar(type1) && isscalar(type2) &&
      type1->type == type2->type &&
      type1->def.s.min < type2->def.s.max &&
      type1->def.s.max > type2->def.s.min)
	return(TRUE);

  /*
   * Strings are always possible regardless of sizes, because the runtime
   * module will care for the sizes and truncate if necessary.
   */
  if (isstring(type1) && isstring(type2))
	return(TRUE);

  /* In all other cases, assignment is not possible */
  return(FALSE);
}



/*
 *****************************************************************************
 *
 * Check if an expression is a valid variable with a given class
 */
static int checkvar(ep)
struct expr *ep;
{
  varclass myclass;

  /* Check if we have a variable expression */
  if (ep == NULL || !isvariable(ep) ||
      ep->spec.var == NULL ||
      ep->spec.var->cmd != basevar ||
      ep->spec.var->spec.basesym == NULL ||
      (!isvarsym(ep->spec.var->spec.basesym) &&
       !isfuncsym(ep->spec.var->spec.basesym))) {
	error("variable expected", FALSE);
	return(FALSE);
  }

  /* Check for valid class */
  myclass = ep->spec.var->spec.basesym->def.v.class;
  if (myclass == CLASS_CONST) {
	error("cannot assign to variable declared constant", FALSE);
	return(FALSE);
  }
  if (myclass == CLASS_STATICRO) {
	error("cannot assign to variable declared read-only", FALSE);
	return(FALSE);
  }
  return(TRUE);
}



/*
 *****************************************************************************
 *
 * Check that an expression has the correct subexpressions for a function
 * or procedure call, and reorder the subexpressions correctly.
 */
static struct expr *setprocexpr(sp, ep)
struct sym *sp;
struct expr *ep;
{
  struct expr *tmpexpr;
  int i, j, maketmp;

  if (!isfuncsym(sp))
	error("unknown procedure or function", FALSE);
  else if (sp->def.f.argnum == ep->exprnum) {
	/* Reverse the expression order */
	j = sp->def.f.argnum - 1;
	for (i = 0; i < (sp->def.f.argnum / 2); i++, j--) {
		tmpexpr = ep->exprlist[i];
		ep->exprlist[i] = ep->exprlist[j];
		ep->exprlist[j] = tmpexpr;
	}

	/* Reorganize all subtrees and check for correct arguments */
	for (i = 0; i < sp->def.f.argnum; i++) {
		varclass argclass = sp->def.f.args[i].class;
		struct typesdef *argtype = sp->def.f.args[i].t;
		struct expr *curarg;

		ep->exprlist[i] = curarg = reorg(ep->exprlist[i]);
		if (curarg == NULL)
			break;
		if (!checkassign(argtype, curarg->type)) {
			error("invalid type for argument in function call", FALSE);
			break;
		}
		if (isscalar(argtype) &&
		    isconst(curarg) &&
		    !isconstrange(curarg, argtype))
			warning("subclass range exceeded in function argument");

		/*
		 * It is not allowed to pass anything not a variable by variable
		 * reference (except for EXPR_ANY arguments).
		 */
		if (argclass == CLASS_REF &&
		    !isanytype(argtype) &&
		    !checkvar(curarg))
			break;

		/*
		 * We have to provide a temporary variable in the following
		 * cases:
		 *
		 *  1.) The parameter gets passed by value and is non-scalar
		 *  2.) The parameter gets passed by constant reference and is
		 *      not a variable and not a stored-constant
		 *  3.) The parameter gets passed by variable reference and is
		 *      not a variable and not a stored-constant for EXPR_ANY
		 *      arguments (these are only used by the runtime library)
		 *
		 * Note: stored-constants are those constants which are stored
		 * in the constant data area. This is true for all non-scalars,
		 * while scalars are usually kept in registers.
		 */
		maketmp =
			/* Handle case 1.) */
			(argclass == CLASS_LOCAL &&
			 isnonscalar(curarg->type)) ||

			/* Handle case 2.) */
			(argclass == CLASS_CONST &&
			 !(isvariable(curarg) ||
			   (isconst(curarg) &&
			    isnonscalar(curarg->type)))) ||

			/* Handle case 3.) */
			(argclass == CLASS_REF && isanytype(argtype) &&
			 !(isvariable(curarg) ||
			   (isconst(curarg) &&
			    isnonscalar(curarg->type))));
		if (maketmp) {
			tmpexpr = createtmpvar(sp->def.f.args[i].t,
							procstack[curlevel]);
			docmd(CODE_ASSIGN, NULL, tmpexpr, curarg);
			delexpr(curarg);
			ep->exprlist[i] = curarg = tmpexpr;
		}
	}

	/* If no error occurred, set the resulting expression correctly */
	if (i >= sp->def.f.argnum) {
		ep->type = sp->def.f.ret;
		ep->opcode = sp->def.f.opcode;
		ep->spec.func = sp;
		return (ep);
	}
  } else
	error("invalid number of arguments to function/procedure call", FALSE);

  /* In case of error delete all expression subtrees */
  delexpr(ep);
  return(NULL);
}



/*
 *****************************************************************************
 *
 * Generate an expression to call a runtime function
 */
static struct expr *genrtfunc(id, ep1, ep2, ep3)
int id;
struct expr *ep1;
struct expr *ep2;
struct expr *ep3;
{
  int num;
  struct sym *sp = rtsymbols[id];
  struct expr *ep = newexpr();

  num = 0;
  ep->exprlist[0] = NULL;
  if (ep3 != NULL) {
	ep->exprlist[num++] = ep3;
	ep->exprlist[num] = NULL;
  }
  if (ep2 != NULL) {
	ep->exprlist[num++] = ep2;
	ep->exprlist[num] = NULL;
  }
  if (ep1 != NULL) {
	ep->exprlist[num++] = ep1;
	ep->exprlist[num] = NULL;
  }
  ep->exprnum = num;
  if ((ep = setprocexpr(sp, ep)) == NULL) {
	prnerr("invalid runtime function %s", sp->name);
	exit(EXIT_MGL_RUNTIME);
  }
  return(ep);
}



/*
 *****************************************************************************
 *
 * Generate an expression to access a runtime variable
 */
static struct expr *genrtvar(id)
int id;
{
  struct sym *sp = rtsymbols[id];
  struct expr *ep = newexpr();
  struct varinfo *vp = newvarinfo();

#ifdef PARANOID
  if (!isvarsym(sp))
	interror(117, "invalid runtime variable");
#endif

  vp->cmd = basevar;
  vp->vartype = sp->def.v.t;
  vp->spec.basesym = sp;
  vp->next = NULL;
  ep->opcode = CMD_VAR;
  ep->exprnum = 0;
  ep->type = sp->def.v.t;
  ep->spec.var = vp;
  return(ep);
}


