/*  -*-c-*-
    Clif - A C-like Interpreter Framework
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997 T. Hruz, L. Koren
    1998, 1999, 2000 L. Koren

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
/* 
 * ys.y
 * 
 * grammar for Clif's compiler (yacc specification)
 */

%{
#include <string.h>
#include "global.h"
#include "config.h"
#ifdef STDC_HEADERS
#include <stdlib.h>
#include <stddef.h>
#else
#include <malloc.h>
#endif
#include "instr.h"            /* 
			       * Header of structures.
			       * Defines size of virtual machine 
			       * instructions.
			       */
#include "geninstr.h"         /* 
			       * Header of macros.
			       * Defines instruction set of the
			       * virtual machine.
			       */
#include "control.h"          /* 
			       * Header of fixative structures
			       */
#include "type.h"	      /* 
			       * Header of internal representation
			       * of types.
			       */
#include "struct.h"           /*
			       * Header of globally used structures
			       */
#include "mystdio.h"	      /*
			       * Defining NULL
			       */
#include "ys.h"		      /*
			       * Header of compiler maintenance functions.
			       */
#include "allocx.h"
#include "comp_maint.h"
#include "load.h"
#include "virtual_machine.h"
#include "ls.h"
#include "tables.h"
#include "memmove.h"
#include "remote_call.h"
#include "printfx.h"
#include "s-conv.h"
#include "flags.h"
#include "parser.h"	      /*
			       * Header for parser specific variables.
			       */
#include "pso.h"

#define YYDEBUG 1
void dump_yacc PROTO((void));
%}

%union	{
  int myint;
  unsigned int myuint;
  long int mylint;
  long unsigned int myluint;
  double mydouble;
  long double myldouble;
  float myfloat;
  char *mystring;
  wchar_t *mywstring;
  char mychar;
}
%token <myint> NUMBERI 		/* integer constant */
%token <myuint> NUMBERUI
%token <mylint> NUMBERLI
%token <myluint> NUMBERLUI
%token <mydouble> NUMBERD	/* double precision constant */
%token <myldouble> NUMBERLD
%token <myfloat> NUMBERF	/* float constant */
%token <mystring> STRINGC       /* string constant */
%token <mystring> WSTRINGC	/* wide string constant */
%token <mychar> NUMBERC		/* char constant */
%token AUTO STATIC REGISTER
%token EXTERN REMOTE UNLOAD
%token INTRINSIC RPC
%token <mystring> IDENT			/* identifier type */
%token INT DOUBLE FLOAT CHAR VOID 
%token LONG SHORT SIGNED UNSIGNED
%token CONST VOLATILE
%token ENUM STRUCT UNION
%token EXIT 
%token IF ELSE
%token SIZEOF
%token SWITCH WHILE FOR DO
%token CONTINUE BREAK RETURN GOTO
%token CASE DEFAULT
%token CSUSPEND RESUME		/* Interrupt statements. */
				/*
				 * Keywords
				 */
%token EXPORT_T			/*
				 * Export_t for remote function
				 * now only for cprintf
				 */
%token TYPEDEF
%token <mystring> TYPENAME

%token ':' '?'
%token MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN SUB_ASSIGN
%token LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN

%token '='
%token OR_A
%token AND_A
%token '|'
%token '^'
%token '&'
%token EQ_A NE_A
%token '<' LQ '>' GQ
%token SHIL SHIR
%token '+' '-'
%token '*' '/' '%'
%token NEG_T NEG_B PP MM 
%token '(' ')' '[' ']'
%token '.' PTR

%start list_stat_0
%% /* beginnig of rules section */

/* \verbatim{parser.tex} */

list_stat_0  :   list_stat_0   stat_0 
			/*
			 * Level zero
			 */

		{
		  GEN_STOP; GENCODE;
		  if (handle_main && ! no_compile_only)
		    fix_and_clear_goto_table ();
		  if (no_compile_only
		      && (! handle_main || initialize_only))
		    {
		      /* Code for initialization is executed even if
			 the `main' function option was specified. */
		      fix_and_clear_goto_table ();
#ifndef NOT_MSWIN_AND_YES_DOS
		      VIRTUAL_MACHINE_SUSPENDED_RESET;
#endif
		      if (0 == exec ())
			return 0;
#ifndef NOT_MSWIN_AND_YES_DOS
		      VIRTUAL_MACHINE_SUSPENDED_SET;
#endif
		    }
		  else if (! s)
		    return 0;
		  initialize_only ? initialize_only-- :
		    initialize_only;
		  RESET_CODE_GENERATION_BEGINNING;
#if 0
		  deallocate (BLOCK);
#endif
		}
	|
	;

		/*
		 * Level one
		 */
list_stat    :  list_stat     stat_1  
	|  
	;

		/*
		 * Statements of the level zero
		 */
stat_0	: declarations
	| statement
		{
		  if (handle_main)
		    error_message (7003);
		}
	| RESUME ';'
		{
		  if (handle_main)
		    error_message (7003);
		  GEN_IRET; GENCODE;
		}
	| ';'
	| error ';'
		{
		  yyerrok;
		  /* I changed ";" to text. I don't know, if parse
		     error is always reported correctly. */
		  error_message (1004, text);
		}
	;

		/*
		 * Statements of the level one
		 */
stat_1  : statement
	| GOTO IDENT ';' 
		{
		  if (no_compile_only) 
		    {
		      has_goto ($2);
		      GEN_JMP; GENCODE;
		    }
		}
	|  ';'
	|  error  '}'
		{
		  yyerrok; error_message (1004, "}");
		}
	|  error  ';'
		{
		  yyerrok; error_message (1004, ";");
		}
	;



		/*
		 * NO_ANSI
		 */
jump_statement
/*	:  GOTO IDENT ';' */
	   /* GOTO statement is separeted. It is moved to the stat_1 */
	   /* GOTO statement cannot be used in the level zero. */
	   /* There is no way to interpret a goto statement in */
	   /* the level zero, except goto back in the code (label */
	   /* must had been known if the goto statement appeared). */
	   /* This possibility we leaved out. */
	: BREAK ';'
		{
		  brfix ();
		  GEN_JMP; GENCODE;
		}

	| CONTINUE ';'
		{
		  cofix ();
		  GEN_JMP; GENCODE;
		}

	| RETURN expression ';'
		{
		  if (VID == type_ac[set - 1])
		    error_message (6002);
		  if ((-1 == l_value_cast ()) && (2 < set))
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  if (NULL != kodp3)
		    {
		      memmovex (kodp3 + sizeof(struct OPERAND_0_ma),
				kodp3, (unsigned int)(kodp - kodp3));
		      GEN_CLRTr; GENCODE;
		      kodp3 = NULL;
		    }
		  retfix ();
		  GEN_JMP; GENCODE;
		  is_address = 0;
		}

	| RETURN ';'
		{
		  if (VID != type_ac[set])
		    error_message (6001);
		  retfix ();
		  GEN_JMP; GENCODE;
		}
	;



			/*
			 * Declaration of identifiers
			 */
/*
declaration
	: declaration_specifiers ';'
	| declaration_specifiers init_declarator_list ';'
	;
*/
declaration_specifiers
	: storage_class_specifier
	| storage_class_specifier declaration_specifiers
	| type_specifier
	| type_specifier declaration_specifiers
	| type_qualifier
	| type_qualifier declaration_specifiers
	;

M :
		{
		  typeh[++type_spec_count] = (struct internal_type *) 
		    allocate (sizeof(struct internal_type), 
			      scope_level > PERM ? BLOCK : PERM);
		  init_zero ((char *)typeh[type_spec_count],
			     sizeof(struct internal_type));
		  typeh[type_spec_count]->attribute.function_class =
		    SIMPLE;
		  typeh[type_spec_count]->attribute.type_qualifier =
		    UNDEF_TQ;
		  typeh[type_spec_count]->attribute.arit_class =
		    UNUSED_AC;
		  typeh[type_spec_count]->attribute.storage_class_specifier =
		    UNSPEC_SC;
		  body_flag = 1;
		}
	;

/*
init_declarator_list
	: init_declarator
	| init_declarator_list ',' init_declarator
	;

init_declarator
	: declarator
	| declarator '=' initializer
	;
*/

declarations :
	  M declaration_specifiers first_dekl

/*	| M declaration_specifiers init_declarator_list*/
	| REMOTE '{' INTRINSIC ',' STRINGC '}' IDENT ';' 
		{
		  typeh[++type_spec_count] = (struct internal_type *) 
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)typeh[type_spec_count],
			     sizeof(struct internal_type));
/*		 typeh[type_spec_count]->attribute.arit_class = LIB;*/
		  typeh[type_spec_count]->attribute.function_class =
		    LIB;
		  body_flag = 1;
		  if (-1 == has ($7))
		    COMPILE_ONLY;
		  if (!load_new () &&
		      !load (&remote_ptr_C))
		    has_remote (remote_ptr_C);
		  typeh[type_spec_count--] = NULL;
		}

	| REMOTE '{' RPC ',' STRINGC '}' IDENT ';'
		{}
	| UNLOAD IDENT ';'
		{
		  body_flag = 0; unload ();
		}
	;



			/*
			 * Common statements for the level zero and
			 * the level one.
			 */

statement : labeled_statement

	| compound_statement
		{
		  GEN_ADDss(scope_offset_get ()); GENCODE;
		  exit_scope ();
		}

	|		/*
			 * Expressions, arithmetical stack is cleared
			 */
	  expression ';'
		{
		  if (! LOCAL_P(type_com[set]) &&
		      ! REMOTE_P(type_com[set]) &&
		      ! MOV_P && ! POPA_P)
		    error_message (6027);

		  switch (type_ac[set])
		    {
		      /* No breaks here. */
		    case INTEGER:
		    case SIGNED_AC | INTEGER:
		    case UNSIGNED_AC | INTEGER:
		    case LONG_AC | INTEGER:
		    case LONG_AC | SIGNED_AC | INTEGER:
		    case LONG_AC | UNSIGNED_AC | INTEGER:
		    case SHORT_AC | INTEGER:
		    case SHORT_AC | SIGNED_AC | INTEGER:
		    case SHORT_AC | UNSIGNED_AC | INTEGER:
		    case DOUB:
		    case LONG_AC | DOUB:
		    case FLT:
		    case CHR:
		    case SIGNED_AC | CHR:
		    case UNSIGNED_AC | CHR:
		      GEN_POPAe; GENCODE;
		      break;
		    case VID:
		      break;
		    default:
		      fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
		      error_message (5000); return (0);
		    }
		  GEN_CLRT;GENCODE;kodp3 = NULL;
		  is_address = 0;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		}

	| selection_statement
	| iteration_statement
	| jump_statement
	| EXIT ';' 
		{
		  GEN_HALT; GENCODE;
		} 
			/*
			 * Leaving environment
			 */
			/*
			 * Statement for synchronous interrupt
			 */
	| CSUSPEND ';'
		{
		  GEN_INTER; GENCODE;
		}
	;



			/*
			 * Control flow statements
			 */

			/* The if then else ambiguity can be solved */
			/* using the following grammar: */
  /* <stmt> -> <matched_stmt> */
  /*        |  <unmatched_stmt> */
  /* <matched_stmt> -> if <expr> then <matched_stmt> else <matched_stmt> */
  /*		    | other */
  /* <unmatched_stmt> -> if <expr> then <stmt> */
  /*		      |  if <expr> then <matched_stmt> else <unmatched_stmt> */


selection_statement
	: IF '(' expression ')'
		{
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = NULL; GEN_CLRT; GENCODE; fixp++;
#ifdef DEBUG
		  printfx ("fixp=%u\n",fixp);
#endif
		  fixp->if1.major = IF;
		  fixp->if1.jz = kodp;
		  GEN_JZ;GENCODE;
		  is_address = 0;
		}
	   then

	| SWITCH '(' expression ')' 
		{
		  if (INTEGER != type_ac[set])
		    error_message (1013);
		  kodp3 = NULL; fixp++;
#ifdef DEBUG
		  printfx ("fixp=%u\n",fixp);
#endif
		  fixp->switch1.major = SWITCH;
		  fixp->switch1.jz = NULL;
		  fixp->switch1.def_use.def_flag = 0;
		  fixp->switch1.jmp = kodp; GEN_JMP; GENCODE;
		  is_address = 0;
		}
	  switch_body
		{
		  search_duplicate_labels ();
		  if (fixp->switch1.def_use.def_flag)
			    /* Note: We have to backpatch the address
			       for default label here because we don't
			       know where the default label
			       appeared. (In general case, it can be
			       anywhere in the switch statement.) */
		    ((struct OPERAND_1_ma *)(fixp->switch1.jz))->adr = 
		      fixp->switch1.def_use.adr;
		  else if (NULL != fixp->switch1.jz)
		    ((struct OPERAND_1_ma *)(fixp->switch1.jz))->adr
		      = kodp;
		  fix_break_s ();
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  GEN_CLRT; GENCODE; fixp--;
		}
	;



iteration_statement
	: WHILE
		{
		  fixp++;
		  fixp->while1.major = WHILE;
		  fixp->while1.jmp = kodp;
#ifdef DEBUG
		  printfx ("JMP jump to address=%u\n",
			   fixp->while1.jmp);
#endif		
		}
	  '(' expression ')'
		{
		  promote_type ();
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = NULL; GEN_CLRT; GENCODE;
		  fixp->while1.jz = kodp;
		  GEN_JZ; GENCODE;
		  is_address = 0;
		}
	  while_stat

	| DO
		{
		  fixp++;
		  fixp->while1.major = WHILE;
		  fixp->while1.jmp = kodp;
#ifdef DEBUG
		  printfx ("JMP jump to address=%u\n",
			   fixp->while1.jmp);
#endif		
		}
	  do_while_stat
	  WHILE '(' expression ')' ';'
		{
		  promote_type ();
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = NULL; GEN_CLRT; GENCODE;
		  fixp->while1.jz = kodp;
		  GEN_JZ; GENCODE;
		  ((struct OPERAND_1_ma *)kodp)->adr = fixp->while1.jmp; 
		  GEN_JMP; GENCODE;
		  ((struct OPERAND_1_ma *)(fixp->while1.jz))->adr 
		    = kodp; 
#ifdef DEBUG
		  printfx ("JZ jump to address=%u\n",kodp);
#endif
		  fix_break_w ();
		  fix_cont_w ();
		  fixp--;
		  is_address = 0;
		}

	| FOR for for_stat
		{
		  ((struct OPERAND_1_ma *)kodp)->adr = fixp->for1.jmp3;
		  GEN_JMP; GENCODE;
		  if (NULL != fixp->for1.jn)
		    ((struct OPERAND_1_ma *)(fixp->for1.jn))->adr =
		      kodp;
		  fix_break_f ();
		  fix_cont_f ();
		  fixp--;
		}
	;

			/*
			 * Parsing of while loop body.
			 */

while_stat : stat_1
		{
		  ((struct OPERAND_1_ma *)kodp)->adr =
		    fixp->while1.jmp;
		  GEN_JMP; GENCODE;
		  ((struct OPERAND_1_ma *)(fixp->while1.jz))->adr =
		    kodp; 
#ifdef DEBUG
		  printfx ("JZ jump to address=%u\n", kodp);
#endif
		  fix_break_w ();
		  fix_cont_w ();
		  fixp--;
		}
	;

do_while_stat 
	: stat_1
	;

			/*
			 * Parsing of for statement.
			 */

for_stat : stat_1
	;

for : '(' expression  ';'
		{
		  if (! LOCAL_P(type_com[set]) &&
		      ! REMOTE_P(type_com[set]) &&
		      ! MOV_P && ! POPA_P)
		    error_message (6027);

		  switch (type_ac[set])
		    {
		      /* No breaks here. */
		    case INTEGER:
		    case SIGNED_AC | INTEGER:
		    case UNSIGNED_AC | INTEGER:
		    case LONG_AC | INTEGER:
		    case LONG_AC | SIGNED_AC | INTEGER:
		    case LONG_AC | UNSIGNED_AC | INTEGER:
		    case SHORT_AC | INTEGER:
		    case SHORT_AC | SIGNED_AC | INTEGER:
		    case SHORT_AC | UNSIGNED_AC | INTEGER:
		    case DOUB:
		    case LONG_AC | DOUB:
		    case FLT:
		    case CHR:
		    case SIGNED_AC | CHR:
		    case UNSIGNED_AC | CHR:
		      GEN_POPAe; GENCODE;
		      break;
		    case VID: 
		      break;
		    default:
		      fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
		      error_message (5000); return (0);
		    }
		  kodp3 = NULL;
		  GEN_CLRT; GENCODE; fixp++;
#ifdef DEBUG
		  printfx ("fixp=%u\n", fixp);
#endif
		  fixp->for1.major = FOR;
		  jmp1 = kodp;
		  is_address = 0;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		}
	  for_expr1

	| '(' ';' 
		{
		  fixp++;
#ifdef DEBUG
		  printfx ("fixp=%u\n", fixp);
#endif
		  fixp->for1.major = FOR;
		  jmp1 = kodp;
		}
	  for_expr1
	;

for_expr1: expression  ';'
		{
		  promote_type ();
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = NULL; GEN_CLRT; GENCODE;
		  fixp->for1.jn = kodp;
		  GEN_JZ; GENCODE;
		  fixp->for1.jmp2 = kodp;
		  GEN_JMP; GENCODE;
		  fixp->for1.jmp3 = kodp;
		  is_address = 0;
		}
	  for_expr2

	| ';'
		{
		  fixp->for1.jn = NULL;
		  fixp->for1.jmp2 = NULL;
		  fixp->for1.jmp3 = kodp;
		}
	  for_expr2
	;
 
for_expr2: expression ')'
		{
		  if (! LOCAL_P(type_com[set]) &&
		      ! REMOTE_P(type_com[set]) &&
		      ! MOV_P && ! POPA_P)
		    error_message (6027);

		  switch (type_ac[set])
		    {
		      /* No breaks here. */
		    case INTEGER:
		    case SIGNED_AC | INTEGER:
		    case UNSIGNED_AC | INTEGER:
		    case LONG_AC | INTEGER:
		    case LONG_AC | SIGNED_AC | INTEGER:
		    case LONG_AC | UNSIGNED_AC | INTEGER:
		    case SHORT_AC | INTEGER:
		    case SHORT_AC | SIGNED_AC | INTEGER:
		    case SHORT_AC | UNSIGNED_AC | INTEGER:
		    case DOUB:
		    case LONG_AC | DOUB:
		    case FLT:
		    case CHR:
		    case SIGNED_AC | CHR:
		    case UNSIGNED_AC | CHR:
		      GEN_POPAe; GENCODE;
		      break;
		    case VID:
		      break;
		    default:
		      fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
		      error_message (5000); return (0);
		    }
		  kodp3 = NULL;
		  GEN_CLRT; GENCODE; 
		  if (NULL != fixp->for1.jn)
		    {
		      ((struct OPERAND_1_ma *)kodp)->adr = jmp1;
		      GEN_JMP; GENCODE;
		      ((struct OPERAND_1_ma *)(fixp->for1.jmp2))->adr =
			kodp;
		    }
		  is_address = 0;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		}
 
	| ')'
		{
		  if (NULL != fixp->for1.jn)
		    {
		      fixp->for1.jmp3 = jmp1;
		      ((struct OPERAND_1_ma *)(fixp->for1.jmp2))->adr
			= kodp;
		    }
		  else
		    fixp->for1.jmp3 = kodp;
		}
	;


	/* Type specifiers. */
			/*
			 * Internal types: 
			 */

type_specifier : INT 
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typeh[type_spec_count]->output->attribute.arit_class +=
		      INTEGER;
		  else
		    typeh[type_spec_count]->attribute.arit_class +=
		      INTEGER;
		  typedef_f = 0;
		}

	| DOUBLE 
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typeh[type_spec_count]->output->attribute.arit_class +=
		      DOUB;
		  else
		    typeh[type_spec_count]->attribute.arit_class +=
		      DOUB;
		  typedef_f = 0;
		}

	| FLOAT 
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typeh[type_spec_count]->output->attribute.arit_class +=
		      FLT;
		  else
		    typeh[type_spec_count]->attribute.arit_class +=
		      FLT;
		  typedef_f = 0;
		}

	| CHAR 
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typeh[type_spec_count]->output->attribute.arit_class +=
		      CHR;
		  else
		    typeh[type_spec_count]->attribute.arit_class +=
		      CHR;
		  typedef_f = 0;
		}

	| VOID 
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typeh[type_spec_count]->output->attribute.arit_class +=
		      VID;
		  else
		    typeh[type_spec_count]->attribute.arit_class +=
		      VID;
		  typedef_f = 0;
		}
	| LONG
		{
		  if (LONG_P(typeh[type_spec_count]))
		    error_message (6025, "long");
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      if (LONG_P(typeh[type_spec_count]->output))
			error_message (6025, "long");
		      typeh[type_spec_count]->output->attribute.arit_class +=
			LONG_AC;
		    }
		  else
		    typeh[type_spec_count]->attribute.arit_class +=
		      LONG_AC;
		  typedef_f = 0;
		}
	| SHORT
		{
		  if (SHORT_P(typeh[type_spec_count]))
		    error_message (6025, "short");
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      if (SHORT_P(typeh[type_spec_count]->output))
			error_message (6025, "short");
		      typeh[type_spec_count]->output->attribute.arit_class +=
			SHORT_AC;
		    }
		  else
		    typeh[type_spec_count]->attribute.arit_class +=
		      SHORT_AC;
		  typedef_f = 0;
		}
	| SIGNED
		{
		  if (SIGNED_P(typeh[type_spec_count]))
		    error_message (6025, "signed");
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      if (SIGNED_P(typeh[type_spec_count]->output))
			error_message (6025, "signed");
		      typeh[type_spec_count]->output->attribute.arit_class +=
			SIGNED_AC;
		    }
		  else
		    typeh[type_spec_count]->attribute.arit_class +=
		      SIGNED_AC;
		  typedef_f = 0;
		}
	| UNSIGNED
		{
		  if (UNSIGNED_P(typeh[type_spec_count]))
		    error_message (6025, "unsigned");
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      if (UNSIGNED_P(typeh[type_spec_count]->output))
			error_message (6025, "unsigned");
		      typeh[type_spec_count]->output->attribute.arit_class +=
			UNSIGNED_AC;
		    }
		  else
		    typeh[type_spec_count]->attribute.arit_class +=
		      UNSIGNED_AC;
		  typedef_f = 0;
		}
	| struct_or_union_specifier
	| enum_specifier
	| TYPENAME
		{
		  struct ident_tab_loc *ptr;
		  int unused_p = UNUSED_P(typeh[type_spec_count]);
		  if (! unused_p)
	            {
		      error_message (1001);
		      COMPILE_ONLY;
		    }
		  ptr = point_loc ($1);
		  if (NULL == ptr)
	            {
		      struct ident_tab *ptr1 = point ($1);
		      if (NULL == ptr1)
			COMPILE_ONLY;
		      if (unused_p)
			typeh[type_spec_count] = ptr1->type->output;
		      else
			ptr1->type = typeh[type_spec_count];
		    }
		  else if (unused_p)
		    typeh[type_spec_count] = ptr->type->output;
		  else
		    ptr->type = typeh[type_spec_count];
		  typedef_f = 0;
		}
	;

type_qualifier
	: CONST
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typeh[type_spec_count]->output->attribute.type_qualifier =
		      CONST_TQ;
		  else
		    typeh[type_spec_count]->attribute.type_qualifier =
		      CONST_TQ;
		}

	| VOLATILE
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typeh[type_spec_count]->output->attribute.type_qualifier =
		      VOLATILE_TQ;
		  else
		    typeh[type_spec_count]->attribute.type_qualifier =
		      VOLATILE_TQ;
		}
	;


pointer
	: '*'
		{
		  struct internal_type *help;
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help,
			     sizeof(struct internal_type));
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      help->output = typeh[type_spec_count]->output;
		      typeh[type_spec_count]->output = help;
		      typeh[type_spec_count]->output->attribute.arit_class =
			POINTER;
		    }
		  else
		    {
		      help->output = typeh[type_spec_count];
		      typeh[type_spec_count] = help;
		      typeh[type_spec_count]->attribute.function_class =
			POINTER;
		    }
		}
	| '*' type_qualifier_list
	| '*' pointer
	| '*' type_qualifier_list pointer
	;

type_qualifier_list
	: type_qualifier
	| type_qualifier_list type_qualifier
	;

struct_or_union_specifier
	: struct_or_union IDENT 
		{
		  typedef_f = 0;
		  body_flag = 0;
		  if (-1 == has_tag (0, $2))
                    COMPILE_ONLY;
		  struct_union_enum_name[++suen_count] = text;
		  if (param_flag)
                    error_message (6009);
		}
	  '{' struct_declaration_list '}' 
		{
		  proc_name_text[++proc] =
		  struct_union_enum_name[suen_count];
		  if (-1 == add_spec_to_tag ())
	            COMPILE_ONLY;
		  if (-1 == add_ident_to_tag ())
	            COMPILE_ONLY;
		  proc_name_text[proc--] = NULL;
		  body_flag = 1;
		  text = struct_union_enum_name[suen_count];
		  if (-1 == has_tag (0, text))
	            COMPILE_ONLY;
		  struct_union_enum_name[suen_count--] = NULL;
		}
	| struct_or_union 
		{
		  typedef_f = 0;
		  if (param_flag)
	            error_message (6009);
		}
	  '{' struct_declaration_list '}'
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
	            typeh[type_spec_count]->output->input = l_type_spec;
		  else
		    typeh[type_spec_count]->input = l_type_spec;
		  l_type_spec = NULL;
		  if (param_flag)
                    error_message (6009);
	        }
	| struct_or_union IDENT
		{
		  typedef_f = 0;
		  body_flag = 0;
		  if (-1 == (body_flag = has_tag (1, $2)))
	            COMPILE_ONLY;
		  if (TYPEDEF_P(typeh[type_spec_count]))
	            {
		      if (0 == typeh[type_spec_count]->output->attribute.memory_size)
			struct_union_enum_name[++suen_count] = $2;
		    }
		  else
	            {
		      if (0 == typeh[type_spec_count]->attribute.memory_size)
			struct_union_enum_name[++suen_count] = $2;
		    }
		}
	;

struct_or_union
	: STRUCT
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
                    {
		      typeh[type_spec_count]->output->attribute.arit_class =
			INTEGER;
		      typeh[type_spec_count]->output->attribute.function_class =
			STRUCT_FC;
		    }
		  else
                    {
		      typeh[type_spec_count]->attribute.arit_class =
			INTEGER;
		      typeh[type_spec_count]->attribute.function_class =
			STRUCT_FC;
		    }
		}

	| UNION
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
                    {
		      typeh[type_spec_count]->output->attribute.arit_class =
			INTEGER;
		      typeh[type_spec_count]->output->attribute.function_class =
			UNION_FC;
		    }
		  else
		    {
		      typeh[type_spec_count]->attribute.arit_class =
			INTEGER;
		      typeh[type_spec_count]->attribute.function_class =
			UNION_FC;
		    }
		}
	;

struct_declaration_list
	: struct_declaration 
		{
		  typeh[type_spec_count--] = NULL;
		}
	| struct_declaration_list struct_declaration
		{
		  typeh[type_spec_count--] = NULL;
		}
	;

struct_declaration
	: M specifier_qualifier_list struct_declarator_list ';'
		{
		  if (1 < suen_count)
		    struct_union_enum_name[suen_count--] = NULL;
		}
	;

specifier_qualifier_list
	: type_specifier
	| type_specifier specifier_qualifier_list
	| type_qualifier 
	| type_qualifier specifier_qualifier_list
	;

struct_declarator_list
	: struct_declarator
	| struct_declarator_list ',' struct_declarator
	;

struct_declarator
	: declarator
	| ':' constant_expression
	| declarator ':' constant_expression
	;

enum_specifier
	: ENUM '{' 
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      typeh[type_spec_count]->output->attribute.arit_class =
			INTEGER;
		      typeh[type_spec_count]->output->attribute.function_class =
			ENUM_FC;
		    }
		  else
		    {
		      typeh[type_spec_count]->attribute.arit_class = INTEGER;
		      typeh[type_spec_count]->attribute.function_class =
			ENUM_FC;
		    }
		  if (param_flag)
		    error_message (6009);
		  typedef_f = 0;
		}
	  enumerator_list '}'
		{
		  enum_value = 0;
		}

	| ENUM IDENT '{' 
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      typeh[type_spec_count]->output->attribute.arit_class =
			INTEGER;
		      typeh[type_spec_count]->output->attribute.function_class =
			ENUM_FC;
		    }
		  else
		    {
		      typeh[type_spec_count]->attribute.arit_class =
			INTEGER;
		      typeh[type_spec_count]->attribute.function_class =
			ENUM_FC;
		    }
		  body_flag = 0;
		  if (-1 == has_tag (0, $2))
		    COMPILE_ONLY;
		  struct_union_enum_name[++suen_count] = text;
		  if (param_flag)
		    error_message (6009);
		  typedef_f = 0;
		}
			enumerator_list '}'
		{
		  enum_value = 0;
		  body_flag = 1;
		  text = struct_union_enum_name[suen_count];
		  if (-1 == has_tag (0, text))
		    COMPILE_ONLY;
		  struct_union_enum_name[suen_count--] = NULL;
		}

	| ENUM IDENT 
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      typeh[type_spec_count]->output->attribute.arit_class =
			INTEGER;
		      typeh[type_spec_count]->output->attribute.function_class =
			ENUM_FC;
		    }
		  else
		    {
		      typeh[type_spec_count]->attribute.arit_class =
			INTEGER;
		      typeh[type_spec_count]->attribute.function_class =
			ENUM_FC;
		    }
		  body_flag = 0;
		  if (-1 == (body_flag = has_tag (1, $2)))
	            COMPILE_ONLY;
		  typedef_f = 0;
	        }
	;

enumerator_list
	: enumerator
	| enumerator_list ',' enumerator
	;

enumerator
	: IDENT
		{
		  typeh[++type_spec_count] = (struct internal_type *) 
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)typeh[type_spec_count],
			     sizeof(struct internal_type));
		  typeh[type_spec_count]->attribute.arit_class =
		    INTEGER;
		  typeh[type_spec_count]->attribute.function_class =
		    SIMPLE;
		  typeh[type_spec_count]->attribute.type_qualifier =
		    CONST_TQ;
		  typeh[type_spec_count]->attribute.storage_class_specifier =
		    UNSPEC_SC;
		  typeh[type_spec_count]->attribute.domain =
		    (char *) allocate (sizeof (int), PERM);
		  init_zero ((char *)typeh[type_spec_count]->attribute.domain, 
			     sizeof(struct internal_type));
		  *(int *)typeh[type_spec_count]->attribute.domain =
		    enum_value++;
		  /* The enum_value++ has to be at the end. */
		  put2table ($1, typeh[type_spec_count]);
		  typeh[type_spec_count--] = NULL;
		}
	| IDENT '=' constant_expression
		{fprintfx (stderr, "Assignment in an enumeration not supported yet\n");}
	;

declarator
	: pointer direct_declarator
		{
				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(typeh[type_spec_count]))
		    {
		      typeh[type_spec_count] =
			typeh[type_spec_count]->output;
		    }
		}
	| direct_declarator
	;

		/*
		 * NO_ANSI
		 */
direct_declarator
	/* It has to be all <> here, but definitions of
           functions. */
	: IDENT
		{
		  struct internal_type *type = typeh[type_spec_count];
		  if (TYPEDEF_P(type))
		    type = type->output;
		  if ((STRUCT_P (type) || UNION_P (type)) &&
		      suen_count > 1 &&
		      (0 == type->attribute.memory_size))
		    {
		      error_message (1025);
		      COMPILE_ONLY;
		    }
		  type->field_name = $1;
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  type->field_name = NULL;
		  if (-1 == add_to_ident_list ())
		    COMPILE_ONLY;
		}
	| IDENT list_dim
		{
		  struct internal_type *help, *arch,
		    *type = typeh[type_spec_count];
		  if (TYPEDEF_P(type))
		    type = type->output;
		  if ((STRUCT_P (type) || UNION_P (type)) &&
		      suen_count > 1 &&
		      (0 == type->attribute.memory_size))
		    {
		      error_message (1025);
		      COMPILE_ONLY;
		    }
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help,
			     sizeof(struct internal_type));
		  help->output = type;
		  help->attribute.function_class = ARRAY;
		  help->attribute.storage_class_specifier = UNSPEC_SC;
		  help->field_name = $1;
		  arch = type;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typeh[type_spec_count]->output = help;
		  else
		    typeh[type_spec_count] = help;
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  help->field_name = NULL;
		  if (-1 == add_to_ident_list ())
		    COMPILE_ONLY;
		  count_arr = 1;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (arch);
		  else
		    typeh[type_spec_count] = arch;
		  DELETE_SUBSCRIPT;
		}
	;

initializer
	: assignment_expression
	| '{' 
		{
		  if (! initialize_only && ! full_bracketing)
		    {
		      GEN_MOVaa; GENCODE;
		    }
		  full_bracketing++;
		}
	  initializer_list_complete
	;

initializer_list_complete
	: initializer_list '}'
		{
		  int bracket_initializers;
		  if (dim[poc] >= 0 && full_bracketing == poc)
		    {
		      bracket_initializers =
			initialize_only % dim[poc - 1];
		      if (bracket_initializers)
			initialize_only +=
			  (dim[poc - 1] - bracket_initializers);
		      aggregate_memory_size[full_bracketing] = 0;
		    }
		  if (ARRAY_P(type_com[set]))
		    {
		      int i = initialize_only,
			j = get_field_size (&i, type_com[set]),
			k = aggregate_memory_size[full_bracketing];
		      i = j * initialize_only;
		      while (0 != k && i >= k)
			k += aggregate_memory_size[full_bracketing];
		      
		      for (; i < k; i++)
			{
			  GEN_MOVaa; GENCODE;
			  GEN_PUSHAIi(i); GENCODE;
			  GEN_MOVar; GENCODE;
			  GEN_PUSHAIc((char)0); GENCODE;
			  GEN_MOVc; GENCODE;
			  GEN_POPAe; GENCODE;
			}
		      if (j * initialize_only < k)
			initialize_only = k / j;
		    }
		  if (full_bracketing > 1
		      && ! type_com[set]->attribute.memory_size )
		    type_com[set]->attribute.memory_size +=
		      2 * aggregate_memory_size[full_bracketing];
		  aggregate_memory_size[full_bracketing] = 0;
		  full_bracketing--;
		}
	| initializer_list ',' '}'
		{
		  full_bracketing--;
		}
	;

initializer_list
	: initializer
		{
		  if (set > 1)
		    {
		      initialize_only++;
		      if (-1 == l_value_cast ())
			COMPILE_ONLY;
		      SET_ADDRESS;
		      TYPE_CLEAR;	
		      move2lvalue ();
		      GEN_POPAe; GENCODE;
		    }
		  if (ARRAY_P(type_com[set]) ||
		      STRUCT_P(type_com[set]))
		    {
		      aggregate_memory_size[full_bracketing] =
			get_memory_size (full_bracketing,
					 type_com[set],
					 initialize_only);
		    }
		}
	| initializer_list ','
		{
		  int i = initialize_only,
		    j = get_field_size (&i, type_com[set]);
		  GEN_MOVaa; GENCODE;
		  GEN_PUSHAIi(initialize_only * j);
		  GENCODE;
		  GEN_MOVar; GENCODE;
		}
	  initializer
		{
		  if (set > 1)
		    {
		      initialize_only++;
		      if (-1 == l_value_cast ())
			COMPILE_ONLY;
		      SET_ADDRESS;
		      TYPE_CLEAR;
		      move2lvalue ();
		      GEN_POPAe; GENCODE;
		    }
		}
	;

type_name
	: M specifier_qualifier_list
	| M specifier_qualifier_list abstract_declarator
	;

abstract_declarator
	: pointer
	| direct_abstract_declarator
	| pointer direct_abstract_declarator
	;

direct_abstract_declarator
	: '(' abstract_declarator ')'
	| '[' ']'
	| direct_abstract_declarator '[' ']'
	| '[' constant_expression ']'
	| direct_abstract_declarator '[' constant_expression ']'
	| '(' ')'
	| direct_abstract_declarator '(' ')'
	| '(' list_type_spec ')'
	| direct_abstract_declarator '(' list_type_spec ')'
	;

storage_class_specifier
	: TYPEDEF
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (6025, "typedef");
		  else if (! UNSPEC_P(typeh[type_spec_count]))
		    error_message (2017);
		  typeh[type_spec_count]->attribute.storage_class_specifier
		    = TYPEDEF_SC;
		  typeh[++type_spec_count] = (struct internal_type *) 
		    allocate (sizeof(struct internal_type), 
			      scope_level > PERM ? BLOCK : PERM);
		  init_zero ((char *)typeh[type_spec_count],
			     sizeof(struct internal_type));
		  typeh[type_spec_count]->attribute.function_class =
		    SIMPLE;
		  typeh[type_spec_count]->attribute.type_qualifier =
		    UNDEF_TQ;
		  typeh[type_spec_count]->attribute.arit_class =
		    UNUSED_AC;
		  typeh[type_spec_count]->attribute.storage_class_specifier =
		    UNSPEC_SC;
		  typeh[type_spec_count - 1]->output =
		    typeh[type_spec_count];
		  typeh[type_spec_count--] = NULL;
		}
	| EXTERN
		{	/*
			 * Internal types: 
			 */
		  if (EXTERN_P(typeh[type_spec_count]))
		    error_message (6025, "extern");
		  else if (! UNSPEC_P(typeh[type_spec_count]) &&
			   ! EXPORT_P(typeh[type_spec_count]))
		    error_message (2017);
		  typeh[type_spec_count]->attribute.storage_class_specifier
		    = EXTERN_SC;
		  typeh[type_spec_count]->attribute.function_class =
		    REMOTE_F;
		} 

	| EXPORT_T
		{	/*
			 * Internal types: 
			 */
		 typeh[type_spec_count]->attribute.export_type = YES;
		 typeh[type_spec_count]->attribute.storage_class_specifier
		   = EXPORT_SC;
		 typeh[type_spec_count]->attribute.function_class =
		   REMOTE_F;
		} 

	| STATIC
		{
		  if (STATIC_P(typeh[type_spec_count]))
		    error_message (6025, "static");
		  else if (! UNSPEC_P(typeh[type_spec_count]))
		    error_message (2017);
		  typeh[type_spec_count]->attribute.storage_class_specifier
		    = STATIC_SC;
		}
	| AUTO
		{
		  if (AUTO_P(typeh[type_spec_count]))
		    error_message (6025, "auto");
		  else if (! UNSPEC_P(typeh[type_spec_count]))
		    error_message (2017);
		  typeh[type_spec_count]->attribute.storage_class_specifier
		    = AUTO_SC;
		}
	| REGISTER
		{
		  if (REGISTER_P(typeh[type_spec_count]))
		    error_message (6025, "register");
		  else if (! UNSPEC_P(typeh[type_spec_count]))
		    error_message (2017);
		  typeh[type_spec_count]->attribute.storage_class_specifier
		    = REGISTER_SC;
		}
	;


	/* A list of type specifiers. */

list_type_spec : M declaration_specifiers
		{
		  if (! UNSPEC_P(typeh[type_spec_count]))
		    error_message (2018, "type name");
		  check_spec_constr (typeh[type_spec_count], "type name");
		  if (!body_flag)
		    error_message (6009);
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  typeh[type_spec_count--] = NULL;
		}

	       | M declaration_specifiers ','
		{
		  if (! UNSPEC_P(typeh[type_spec_count]))
		    error_message (2018, "type name");
		  check_spec_constr (typeh[type_spec_count], "type name");
		  if (!body_flag)
		    error_message (6009);
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  typeh[type_spec_count--] = NULL;
		}
	  list_type_spec

	| M declaration_specifiers list_dim_or_pointer

	| M declaration_specifiers list_dim_or_pointer ',' 
	  list_type_spec
	;

list_dim_or_pointer : list_dim
		{
		  struct internal_type *help;
		  if (! UNSPEC_P(typeh[type_spec_count]))
		    error_message (2018, "type name");
		  check_spec_constr (typeh[type_spec_count], "type name");
		  if (!body_flag)
		    error_message (6009);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  help->output = typeh[type_spec_count];
		  typeh[type_spec_count] = help;
		  typeh[type_spec_count]->attribute.function_class =
		    ARRAY;
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  count_arr = 1;
		  typeh[type_spec_count--] = NULL;
		  DELETE_SUBSCRIPT;
		}

	| pointer
		{
		  check_spec_constr (typeh[type_spec_count], "type name");
		  if (!body_flag)
		    error_message (6009);
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  typeh[type_spec_count--] = NULL;
		}

	| '(' pointer ')' '(' ')'
		{
		  typeh[type_spec_count]->attribute.function_class =
		    LOCAL;
		  check_spec_constr (typeh[type_spec_count], "type name");
		  if (!body_flag)
		    error_message (6009);
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  typeh[type_spec_count--] = NULL;
		}

	| '(' pointer ')' '(' list_type_spec ')'
		{
		  check_spec_constr (typeh[type_spec_count], "type name");
		  if (!body_flag)
		    error_message (6009);
		  typeh[type_spec_count]->attribute.function_class =
		    LOCAL;
		  typeh[type_spec_count]->input = l_type_spec;
		  l_type_spec = NULL;
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  typeh[type_spec_count--] = NULL;
		}

	| '(' pointer ')' list_dim
		{
		  struct internal_type *help;
		  typeh[type_spec_count]->attribute.function_class =
		    LOCAL;
		  check_spec_constr (typeh[type_spec_count], "type name");
		  if (!body_flag)
		    error_message (6009);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  help->output = typeh[type_spec_count];
		  typeh[type_spec_count] = help;
		  typeh[type_spec_count]->attribute.function_class =
		    ARRAY;
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  count_arr = 1;
		  typeh[type_spec_count--] = NULL;
		  DELETE_SUBSCRIPT;
		}
	;



		 	/*
			 * Parsing of a list of identifiers,
			 * simple, array or pointer.
			 */
first_dekl : IDENT 
		{
		  if (VOID_P(typeh[type_spec_count]))
		    error_message (1012);
		  check_spec_constr (typeh[type_spec_count], $1);
		  put2table ($1, typeh[type_spec_count]);
		  align_memory (&kodp, sizeof(int));
		  SET_CODE_GENERATION_BEGINNING;
		  body_flag = 0;
		  lookup_tables ($1, variable);
		  typedef_f = 1;
		}
	  initializer_optional 

	| IDENT  list_dim
		{
		  struct internal_type *help, *arch;
		  if (VOID_P(typeh[type_spec_count]))
		    error_message (1012);
		  check_spec_constr (typeh[type_spec_count], $1);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      help->output = typeh[type_spec_count]->output;
		      arch = typeh[type_spec_count]->output;
		      typeh[type_spec_count]->output = help;
		    }
		  else
		    {
		      help->output = typeh[type_spec_count];
		      arch = typeh[type_spec_count];
		      typeh[type_spec_count] = help;
		    }
		  help->attribute.function_class = ARRAY;
		  help->attribute.storage_class_specifier = UNSPEC_SC;
		  put2table ($1, typeh[type_spec_count]);
		  count_arr = 1;
		  SET_CODE_GENERATION_BEGINNING;
		  body_flag = 0;
		  lookup_tables ($1, variable);
		  initialize_only = 0;
		  typedef_f = 1;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (arch);
		  else
		    typeh[type_spec_count] = arch;
		}
	  initializer_optional

	| pointer IDENT
		{
		  struct internal_type *type;
		  check_spec_constr (typeh[type_spec_count], $2);
		  put2table ($2, typeh[type_spec_count]);
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    type = typeh[type_spec_count]->output;
		  else
		    type = typeh[type_spec_count];
				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(type))
		    {
		      type = type->output;
		    }
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (type);
		  else
		    typeh[type_spec_count] = type;
		  align_memory (&kodp, sizeof(int));
		  SET_CODE_GENERATION_BEGINNING;
		  body_flag = 0;
		  lookup_tables ($2, variable);
		  typedef_f = 1;
		}
	  initializer_optional

	| pointer IDENT  list_dim
		{
		  struct internal_type *help, *arch;
		  check_spec_constr (typeh[type_spec_count], $2);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help,
			     sizeof(struct internal_type));
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      help->output = typeh[type_spec_count]->output;
		      arch = typeh[type_spec_count]->output;
		      typeh[type_spec_count]->output = help;
		    }
		  else
		    {
		      help->output = typeh[type_spec_count];
		      arch = typeh[type_spec_count];
		      typeh[type_spec_count] = help;
		    }
		  help->attribute.function_class = ARRAY;
		  help->attribute.storage_class_specifier =
		    UNSPEC_SC;
		  put2table ($2, typeh[type_spec_count]);
		  count_arr = 1;
		  SET_CODE_GENERATION_BEGINNING;
		  body_flag = 0;
		  lookup_tables ($2, variable);
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (arch);
		  else
		    typeh[type_spec_count] = arch;
				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(arch))
		    arch = arch->output;
		  DELETE_SUBSCRIPT;
		  typedef_f = 1;
		}
	  initializer_optional

	| IDENT '('
		{
		  struct internal_type *help, *arch;
				/*
				 * Internal types:
				 */

		  check_spec_constr (typeh[type_spec_count], $1);
		  if (STRUCT_P(typeh[type_spec_count]) ||
		      UNION_P(typeh[type_spec_count]))
		    error_message (6034);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help,
			     sizeof(struct internal_type));
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      help->output = typeh[type_spec_count]->output;
		      arch = typeh[type_spec_count]->output;
		      typeh[type_spec_count]->output = help;
		      if (REMOTE_P(typeh[type_spec_count]->output->output))
			typeh[type_spec_count]->output->attribute.function_class
			  = REMOTE_F;
		      else
			typeh[type_spec_count]->output->attribute.function_class
			  = LOCAL;
		      typeh[type_spec_count]->output->attribute.export_type
			= typeh[type_spec_count]->output->output->attribute.export_type;
		      type_ac[++set]
			= typeh[type_spec_count]->output->output->attribute.arit_class;
		      type_com[set] = typeh[type_spec_count]->output;
		    }
		  else
		    {
		      help->output = typeh[type_spec_count];
		      arch = typeh[type_spec_count];
		      typeh[type_spec_count] = help;
		      if (REMOTE_P(typeh[type_spec_count]->output))
			typeh[type_spec_count]->attribute.function_class
			  = REMOTE_F;
		      else
			typeh[type_spec_count]->attribute.function_class
			  = LOCAL;
		      typeh[type_spec_count]->attribute.export_type
			= typeh[type_spec_count]->output->attribute.export_type;
		      type_ac[++set]
			= typeh[type_spec_count]->output->attribute.arit_class;
		      type_com[set] = typeh[type_spec_count];
		    }
		  body_flag = 0;
		  put2table ($1, typeh[type_spec_count]);
		  variable[set].adr = kodp;
		  variable[set].name = $1;
		  count[++proc] = -(3 * sizeof (char *));
		  proc_name_text[proc] = text;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (arch);
		  else
		    typeh[type_spec_count] = arch;
		  param_flag = 1;
		  enter_scope ();
		  func_def_s ();
		  typedef_f = 1;
		}
	  func_first

	| pointer IDENT '('
		{
		  struct internal_type *help,*arch;
				/*
				 * Internal types:
				 */

		  check_spec_constr (typeh[type_spec_count], $2);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help,
			     sizeof(struct internal_type));
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      help->output = typeh[type_spec_count]->output;
		      arch = typeh[type_spec_count]->output;
		      typeh[type_spec_count]->output = help;
		      if (REMOTE_P(typeh[type_spec_count]->output->output))
			typeh[type_spec_count]->output->attribute.function_class
			  = REMOTE_F;
		      else
			typeh[type_spec_count]->output->attribute.function_class
			  = LOCAL;
		      typeh[type_spec_count]->output->attribute.export_type
			= typeh[type_spec_count]->output->output->attribute.export_type;
		      type_ac[++set]
			= typeh[type_spec_count]->output->output->attribute.arit_class;
		      type_com[set] = typeh[type_spec_count]->output;
		    }
		  else
		    {
		      help->output = typeh[type_spec_count];
		      arch = typeh[type_spec_count];
		      typeh[type_spec_count] = help;
		      if (REMOTE_P(typeh[type_spec_count]->output))
			typeh[type_spec_count]->attribute.function_class
			  = REMOTE_F;
		      else
			typeh[type_spec_count]->attribute.function_class
			  = LOCAL;
		      typeh[type_spec_count]->attribute.export_type
			= typeh[type_spec_count]->output->attribute.export_type;
		      type_ac[++set]
			= typeh[type_spec_count]->output->attribute.arit_class;
		      type_com[set] = typeh[type_spec_count];
		    }
		  body_flag = 0;
		  put2table ($2, typeh[type_spec_count]);
		  variable[set].adr = kodp;
		  variable[set].name = $2;
		  count[++proc] = -(3 * sizeof (char *));
		  proc_name_text[proc] = text;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (arch);
		  else
		    typeh[type_spec_count] = arch;

				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(arch))
		    arch = arch->output;
		  param_flag = 1;
		  enter_scope ();
		  func_def_s ();
		  typedef_f = 1;
		}
	  func_first

	| ';'
		{
		  if (!(ENUM_P (typeh[type_spec_count]) ||
			UNION_P (typeh[type_spec_count]) ||
			STRUCT_P (typeh[type_spec_count])))
		    {
		      error_message (6010);
		      error_message (6011);
		      SET_ADDRESS;
		      TYPE_CLEAR;
		    }
		  typeh[type_spec_count--] = NULL;		  
		  typedef_f = 1;
		}
	;

func_first : ')' 
		{
		  count[proc] = 0;
#if 0
		  SET_ADDRESS;
		  TYPE_CLEAR;
#endif
#if 0
		  free (proc_name_text[proc--]);
#else
		  proc_name_text[proc--] = NULL;
#endif
		  param_flag = 0;
		  func_def_r ();
		  exit_scope ();
		  typedef_f = 1;
		}
	  initializer_optional

	| list_type_spec ')'
		{
		  count[proc] = 0;
		  if (-1 == add_spec_to_has ())
		    COMPILE_ONLY;
#if 0
		  SET_ADDRESS;
		  TYPE_CLEAR;
#endif
#if 0
		  free (proc_name_text[proc--]);
#else
		  proc_name_text[proc--] = NULL;
#endif
		  param_flag = 0;
		  func_def_r ();
		  exit_scope ();
		  typedef_f = 1;
		}
	  initializer_optional

	| list_form_param ')'
		{
		  count[proc] = 0;
		  if (-1 == add_spec_to_has ())
		    COMPILE_ONLY;
		  if (-1 == add_ident_to_has ())
		    COMPILE_ONLY;
		  clear_hash_tab_declaration (); 
#if 0
		  SET_ADDRESS;
		  TYPE_CLEAR;
#endif
#if 0
		  free (proc_name_text[proc--]);
#else
		  proc_name_text[proc--] = NULL;
#endif
		  param_flag = 0;
		  func_def_r ();
		  exit_scope ();
		  typedef_f = 1;
		}
	  initializer_optional

	| list_form_param ')'
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (1036, "typedef");
		  else if (REGISTER_P(typeh[type_spec_count]))
		    error_message (1036, "register");
		  else if (AUTO_P(typeh[type_spec_count]))
		    error_message (1036, "auto");
		  if (-1 == add_spec_to_has ())
		    COMPILE_ONLY;
		  if (-1 == add_ident_to_has ())
		    COMPILE_ONLY;
		  FUNCTION_PROLOGUE;
		  count[proc] = -count[proc];
		  count[proc] %= sizeof (double);
		  count[proc] = -count[proc];
		  typeh[type_spec_count--] = NULL;
		  param_flag = 0;
		  typedef_f = 1;
		} 
	  compound_statement
	   	{
		  text = proc_name_text[proc];
		  fix_ret ();
		  FUNCTION_EPILOGUE;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  body_flag = 1;
		  put2table (text, NULL);
		  body_flag = 0;
		  SET_CODE_GENERATION_BEGINNING;
		  exit_scope ();
#if 0
		  free (proc_name_text[proc--]);
#else
		  proc_name_text[proc] = NULL;
		  count[proc--] = 0;
#endif
		}

	| ')'
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (1036, "typedef");
		  else if (REGISTER_P(typeh[type_spec_count]))
		    error_message (1036, "register");
		  else if (AUTO_P(typeh[type_spec_count]))
		    error_message (1036, "auto");
		  typeh[++type_spec_count] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)typeh[type_spec_count],
			     sizeof(struct internal_type));
		  typeh[type_spec_count]->attribute.arit_class =
		    VID;
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  if (-1 == add_spec_to_has ())
		    COMPILE_ONLY;
		  FUNCTION_PROLOGUE;
		  count[proc] = -count[proc];
		  count[proc] %= sizeof (double);
		  count[proc] = -count[proc];
		  typeh[type_spec_count--] = NULL;
		  param_flag = 0;
		  typedef_f = 1;
		}
	  compound_statement
		{
		  text = proc_name_text[proc];
		  fix_ret ();
		  FUNCTION_EPILOGUE;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  body_flag = 1;
		  put2table (text, NULL);
		  body_flag = 0;
		  SET_CODE_GENERATION_BEGINNING;
		  exit_scope ();
#if 0
		  free (proc_name_text[proc--]);
#else
		  proc_name_text[proc] = NULL;
		  count[proc--] = 0;
#endif
		  typeh[type_spec_count--] = NULL;
		  typedef_f = 1;
		}
	;

func_rest : ')'
		{
		  count[proc] = 0; 
#if 0
		  free (proc_name_text[proc--]);
#else
		  proc_name_text[proc--] = NULL;
#endif
		  param_flag = 0;
		  typedef_f = 1;
		}
	  initializer_optional

	| list_type_spec ')'
		{
		  count[proc] = 0;
		  if (-1 == add_spec_to_has ())
		    COMPILE_ONLY;
#if 0
		  free (proc_name_text[proc--]);
#else
		  proc_name_text[proc--] = NULL;
#endif
		  typedef_f = 1;
		}
	  initializer_optional

	| list_form_param ')'
		{
		  count[proc] = 0;
		  if (-1 == add_spec_to_has ())
		    COMPILE_ONLY;
		  if (-1 == add_ident_to_has ())
		    COMPILE_ONLY;
		  clear_hash_tab_declaration ();
#if 0
		  free (proc_name_text[proc--]);
#else
		  proc_name_text[proc--] = NULL;
#endif
		  param_flag = 0;
		  typedef_f = 1;
		}
	  initializer_optional

	| error '{'
		{
		  yyerrok; proc--;
		  error_message (1004, "{"); proc++;
		}
	;




list_dekl : IDENT
		{
		  if (VOID_P(typeh[type_spec_count]))
		    error_message (1012);
		  check_spec_constr (typeh[type_spec_count], $1);
		  body_flag = 1;
		  put2table ($1, typeh[type_spec_count]);
		  align_memory (&kodp, sizeof(int));
		  SET_CODE_GENERATION_BEGINNING;
		  body_flag = 0;
		  lookup_tables ($1, variable);
		  typedef_f = 1;
		}
	  initializer_optional

	| IDENT  list_dim
		{
		  struct internal_type *help,*arch;
		  if (VOID_P(typeh[type_spec_count]))
		    error_message (1012);
		  check_spec_constr (typeh[type_spec_count], $1);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      help->output = typeh[type_spec_count]->output;
		      arch = typeh[type_spec_count]->output;
		      typeh[type_spec_count]->output = help;
		    }
		  else
		    {
		      help->output = typeh[type_spec_count];
		      arch = typeh[type_spec_count];
		      typeh[type_spec_count] = help;
		    }
		  help->attribute.function_class = ARRAY;
		  help->attribute.storage_class_specifier = UNSPEC_SC;
		  body_flag = 1;
		  put2table ($1, typeh[type_spec_count]);
		  count_arr = 1;
		  SET_CODE_GENERATION_BEGINNING;
		  body_flag = 0;
		  lookup_tables ($1, variable);
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (arch);
		  else
		    typeh[type_spec_count] = arch;
		  DELETE_SUBSCRIPT;
		  typedef_f = 1;
		}
	  initializer_optional

	| IDENT '('
		{
		  struct internal_type *help, *arch;
			/*
			 * Internal types:
			 */

		  check_spec_constr (typeh[type_spec_count], $1);
		  if (STRUCT_P(typeh[type_spec_count]) ||
		      UNION_P(typeh[type_spec_count]))
		    error_message (6034);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help,
			     sizeof(struct internal_type));
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      typedef_copy (typeh[type_spec_count]->output);
		      help->output = typeh[type_spec_count]->output;
		      arch = typeh[type_spec_count]->output;
		      typeh[type_spec_count]->output = help;
		      if (REMOTE_P(typeh[type_spec_count]->output->output))
			typeh[type_spec_count]->output->attribute.function_class
			  = REMOTE_F;
		      else
			typeh[type_spec_count]->output->attribute.function_class
			  = LOCAL;
		      typeh[type_spec_count]->output->attribute.export_type
			= typeh[type_spec_count]->output->output->attribute.export_type;
		      type_ac[++set]
			= typeh[type_spec_count]->output->output->attribute.arit_class;
		      type_com[set] = typeh[type_spec_count]->output;
		    }
		  else
		    {
		      help->output = typeh[type_spec_count];
		      arch = typeh[type_spec_count];
		      typeh[type_spec_count] = help;
		      if (REMOTE_P(typeh[type_spec_count]->output))
			typeh[type_spec_count]->attribute.function_class
			  = REMOTE_F;
		      else
			typeh[type_spec_count]->attribute.function_class
			  = LOCAL;
		      typeh[type_spec_count]->attribute.export_type
			= typeh[type_spec_count]->output->attribute.export_type;
		      type_ac[++set]
			= typeh[type_spec_count]->output->attribute.arit_class;
		      type_com[set] = typeh[type_spec_count];
		    }
		  body_flag = 0;
		  put2table ($1, typeh[type_spec_count]);
		  variable[set].adr = kodp;
		  variable[set].name = $1;
		  count[++proc] = -(3 * sizeof (char *));
		  proc_name_text[proc] = text;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (arch);
		  else
		    typeh[type_spec_count] = arch;
		  typedef_f = 1;
		}
	  func_rest

	| pointer IDENT
		{
		  struct internal_type *type;
		  check_spec_constr (typeh[type_spec_count], $2);
		  body_flag = 1;
		  put2table ($2, typeh[type_spec_count]);
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    type = typeh[type_spec_count]->output;
		  else
		    type = typeh[type_spec_count];
				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(type))
		    type = type->output;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (type);
		  else
		    typeh[type_spec_count] = type;
		  align_memory (&kodp, sizeof(int));
		  SET_CODE_GENERATION_BEGINNING;
		  body_flag = 0;
		  lookup_tables ($2, variable);
		  typedef_f = 1;
		}
	  initializer_optional

	| pointer IDENT  list_dim
		{
		  struct internal_type *help,*arch;
		  check_spec_constr (typeh[type_spec_count], $2);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      help->output = typeh[type_spec_count]->output;
		      arch = typeh[type_spec_count]->output;
		      typeh[type_spec_count]->output = help;
		    }
		  else
		    {
		      help->output = typeh[type_spec_count];
		      arch = typeh[type_spec_count];
		      typeh[type_spec_count] = help;
		    }
		  help->attribute.function_class = ARRAY;
		  help->attribute.storage_class_specifier = UNSPEC_SC;
		  body_flag = 1;
		  put2table ($2, typeh[type_spec_count]);
		  count_arr = 1;
		  SET_CODE_GENERATION_BEGINNING;
		  body_flag = 0;
		  lookup_tables ($2, variable);
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (arch);
		  else
		    typeh[type_spec_count] = arch;
				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(arch))
		    arch = arch->output;
		  DELETE_SUBSCRIPT;
		  typedef_f = 1;
		}
	  initializer_optional

	| pointer IDENT '('
		{
		  struct internal_type *help, *arch;
				/*
				 * Internal types:
				 */

		  check_spec_constr (typeh[type_spec_count], $2);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      help->output = typeh[type_spec_count]->output;
		      arch = typeh[type_spec_count]->output;
		      typeh[type_spec_count]->output = help;
		      if (REMOTE_P(typeh[type_spec_count]->output->output))
			typeh[type_spec_count]->output->attribute.function_class
			  = REMOTE_F;
		      else
			typeh[type_spec_count]->output->attribute.function_class
			  = LOCAL;
		      typeh[type_spec_count]->output->attribute.export_type
			= typeh[type_spec_count]->output->output->attribute.export_type;
		      type_ac[++set]
			= typeh[type_spec_count]->output->output->attribute.arit_class;
		      type_com[set] = typeh[type_spec_count]->output;
		    }
		  else
		    {
		      help->output = typeh[type_spec_count];
		      arch = typeh[type_spec_count];
		      typeh[type_spec_count] = help;
		      if (REMOTE_P(typeh[type_spec_count]->output))
			typeh[type_spec_count]->attribute.function_class
			  = REMOTE_F;
		      else
			typeh[type_spec_count]->attribute.function_class
			  = LOCAL;
		      typeh[type_spec_count]->attribute.export_type
			= typeh[type_spec_count]->output->attribute.export_type;
		      type_ac[++set]
			= typeh[type_spec_count]->output->attribute.arit_class;
		      type_com[set] = typeh[type_spec_count];
		    }
		  body_flag = 0;
		  put2table ($2, typeh[type_spec_count]);
		  variable[set].adr = kodp;
		  variable[set].name = $2;
		  count[++proc] = -(3 * sizeof (char *));
		  proc_name_text[proc] = text;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (arch);
		  else
		    typeh[type_spec_count] = arch;
				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(arch))
		    arch = arch->output;
		  typedef_f = 1;
		}
	  func_rest
	;

initializer_optional
	: ';' R
		{
		  typeh[type_spec_count--] = NULL;
		}
	| initialization ';'
		{
		  typeh[type_spec_count--] = NULL;
		}
	| ',' R list_dekl
	| initialization
		{
				/* The following block looks like
				   semantic of the list_stat_0
				   rule. The code for the
				   initialization of the parsed
				   variable must be executed. */
		  {
		    GEN_STOP; GENCODE;
		    if (no_compile_only
			&& (! handle_main || initialize_only))
		      {
#ifndef NOT_MSWIN_AND_YES_DOS
			VIRTUAL_MACHINE_SUSPENDED_RESET;
#endif
			if (0 == exec ())
			  return 0;
#ifndef NOT_MSWIN_AND_YES_DOS
			VIRTUAL_MACHINE_SUSPENDED_SET;
#endif
		      }
		    else if (! s)
		      return 0;
		    initialize_only ? initialize_only-- :
		      initialize_only;
		    RESET_CODE_GENERATION_BEGINNING;
		  }
		}
	  ',' list_dekl
	;

R	:
		{
		  if (! LOCAL_P(type_com[set])
		      && ! REMOTE_P(type_com[set])
		      && ! TYPEDEF_P(type_com[set]))
		    {
		      switch (type_ac[set])
			{
			  /* No breaks here. */
			case INTEGER:
			case SIGNED_AC | INTEGER:
			case UNSIGNED_AC | INTEGER:
			case LONG_AC | INTEGER:
			case LONG_AC | SIGNED_AC | INTEGER:
			case LONG_AC | UNSIGNED_AC | INTEGER:
			case SHORT_AC | INTEGER:
			case SHORT_AC | SIGNED_AC | INTEGER:
			case SHORT_AC | UNSIGNED_AC | INTEGER:
			case DOUB:
			case LONG_AC | DOUB:
			case FLT:
			case CHR:
			case SIGNED_AC | CHR:
			case UNSIGNED_AC | CHR:
			  GEN_POPAe; GENCODE;
			  break;
			case VID:
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		      GEN_CLRT; GENCODE;
		    }
		  kodp3 = NULL;
		  is_address = 0;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  DELETE_SUBSCRIPT;
		}
	;

initialization
	: '=' initializer
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (1037, text);
#if 0
		  if (! CONST_P(type_com[set]))
		    error_message ();
#endif		  
		  if (SIMPLE_P(type_com[set]))
		    {
		      if (-1 == l_value_cast ())
			COMPILE_ONLY;
		      SET_ADDRESS;
		      TYPE_CLEAR;
		      move2lvalue ();
		    }
		  else if (ARRAY_P(type_com[set]))
		    {
		      DELETE_SUBSCRIPT;
		      if (CONST_P(type_com[set]))
			{
			  type_com[set - 1]->attribute.domain =
			    type_com[set]->attribute.domain;
			  if (! type_com[set - 1]->attribute.memory_size)
			    type_com[set - 1]->attribute.memory_size =
			      type_com[set]->attribute.memory_size;
			  if (CHAR_P(type_com[set]->output))
			    {
			      register int i;
			      
			      for (i = 0;
				   i < type_com[set]->attribute.memory_size;
				   i++)
				{
				  GEN_PUSHAIi(i); GENCODE;
				  GEN_MOVbv; GENCODE;
				}
			    }
			  if (! POINTER_P(type_com[set]))
			    {
			      GEN_POPAe; GENCODE;
			      SET_ADDRESS;
			      TYPE_CLEAR;
			    }
			}
		      else if (! type_com[set]->attribute.memory_size)
			{
			  type_com[set]->attribute.memory_size
			    = initialize_only *
			    type_com[set]->output->attribute.memory_size;
			  dim[++poc] = initialize_only;
			  put_array_subscript (&type_com[set]);
			}
		      kodp1 += type_com[set]->attribute.memory_size;
		      align_memory (&kodp1, sizeof(int));
		      if (set > 1 && POINTER_P(type_com[set - 1]))
			{
				/* MOV two pointers as long ints. */
			  GEN_MOVli; GENCODE;
			  SET_ADDRESS;
			  TYPE_CLEAR;
			}
		    }

		  switch (type_ac[set])
		    {
		      /* No breaks here. */
		    case INTEGER:
		    case SIGNED_AC | INTEGER:
		    case UNSIGNED_AC | INTEGER:
		    case LONG_AC | INTEGER:
		    case LONG_AC | SIGNED_AC | INTEGER:
		    case LONG_AC | UNSIGNED_AC | INTEGER:
		    case SHORT_AC | INTEGER:
		    case SHORT_AC | SIGNED_AC | INTEGER:
		    case SHORT_AC | UNSIGNED_AC | INTEGER:
		    case DOUB:
		    case LONG_AC | DOUB:
		    case FLT:
		    case CHR:
		    case SIGNED_AC | CHR:
		    case UNSIGNED_AC | CHR:
		      GEN_POPAe; GENCODE;
		      break;
		    case VID:
		      break;
		    default:
		      fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
		      error_message (5000); 
		      return 0;
		    }
		  GEN_CLRT; GENCODE; kodp3 = NULL;
		  is_address = 0;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  if (handle_main)
		    initialize_only = 1;
		}
	;


			/*
			 * Finishing up parsing of if statement
			 */
then	: stat_1
		{
		  fixp->if1.jmp = kodp;
		  GEN_JMP; GENCODE;
		  ((struct OPERAND_1_ma *)(fixp->if1.jz))->adr = kodp;
		}
	  ELSE stat_1
		{
		  ((struct OPERAND_1_ma *)(fixp->if1.jmp))->adr = kodp;
		  fixp--;
		}

	| stat_1
		{
		  ((struct OPERAND_1_ma *)(fixp->if1.jz))->adr = kodp;
		  fixp--;
		}
	;

switch_body : stat_1
	;


		/*
		 * NO_ANSI
		 */
labeled_statement 
	: IDENT ':' 
		{
		  if (no_compile_only)
		    has_label ($1);
		}
			/* If we ommit <stat_1> then there can be
			   construction label:} that is non ansi. */

	  stat_1

	| CASE 
		{
		  char *help = fixp->switch1.jmp;
		  /* If in the previous case label was not a break */
		  /* state jump over the next <constant_expression> */
		  /* to the <statements>. */
		  fixp->switch1.jmp = kodp; GEN_JMP; GENCODE;
		  if (fixp->switch1.jz != NULL)
		    /* If previous case label was not successful jump here. */
		    ((struct OPERAND_1_ma *)(fixp->switch1.jz))->adr = kodp;
		  if (help != NULL)
		    /* Backpatch the address for the first case label. */
		    ((struct OPERAND_1_ma *)help)->adr = kodp;
		  GEN_MOVaa; GENCODE; /* Reloading top of the arithmetical */
				/* stack with the same value for */
				/* the purpose of comparing. */
		  it_is_in_case = 1;
		} 
	  constant_expression 
		{
		  if ((CONST_TQ != type_com[set]->attribute.type_qualifier) 
		      || (INTEGER != type_ac[set]))
		    error_message (1014);
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  GEN_EQi; GENCODE;
		  GEN_CLRT; GENCODE; /* Clears arithmetical stack. */
				/* We know that the value is */
				/* still there. */
		  fixp->switch1.jz = kodp;
		  GEN_JZ; GENCODE;
		  /* Jump here if the next statements should apply. */
		  /* In the previous case label there was not */
		  /* the break statement. */
		  ((struct OPERAND_1_ma *)fixp->switch1.jmp)->adr =
		    kodp;
		  fixp->switch1.jmp = NULL;
		  it_is_in_case = 0;
		}
	  ':' stat_1

	| DEFAULT ':' 
		{
		  add_default_to_fixp ();
		}
	  stat_1
	;


		/*
		 * NO_ANSI
		 */
compound_statement
		/* The case '{' '}' is parsed via '{' list_stat '}'. */
		/* list_stat has an empty production. */
	: '{' N list_stat '}'
		/* The case '{' list_loc_dekl '}' is parsed by 
		/* '{' list_loc_dekl list_stat '}' . */
		/* list_stat has an empty production. */
	| '{' N list_loc_dekl 
		{
		  ERROR_P;
		  GEN_SUBss(scope_offset_set (count[proc])); GENCODE;
		  count[proc] = 0;
		}
	  list_stat '}'
	;

N
	:
		{
		  enter_scope ();
		}
	;

			/*
			 * Parsing a list of formal parameters 
			 * of a procedure. 
			 */	
list_form_param	
	: M declaration_specifiers IDENT
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (2018, $3);
		  else if (EXTERN_P(typeh[type_spec_count]))
		    error_message (2018, $3);
		  check_spec_constr (typeh[type_spec_count], $3);
		  if (!body_flag)
		    error_message (6009);
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  if (-1 == has_loc (PAR, $3))
		    COMPILE_ONLY;
		  if (-1 == add_to_ident_list ())
		    COMPILE_ONLY;
		  typeh[type_spec_count--] = NULL;
		  typedef_f = 1;
		}

	| M declaration_specifiers IDENT ','
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (2018, $3);
		  else if (EXTERN_P(typeh[type_spec_count]))
		    error_message (2018, $3);
		  check_spec_constr (typeh[type_spec_count], $3);
		  if (!body_flag)
		    error_message (6009);
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  if (-1 == has_loc (PAR, $3))
		    COMPILE_ONLY;
		  if (-1 == add_to_ident_list ())
		    COMPILE_ONLY;
		  typeh[type_spec_count--] = NULL;
		  typedef_f = 1;
		}
	  list_form_param

	| M declaration_specifiers IDENT list_dim
		{
		  struct internal_type *help;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (2018, $3);
		  else if (EXTERN_P(typeh[type_spec_count]))
		    error_message (2018, $3);
		  check_spec_constr (typeh[type_spec_count], $3);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), BLOCK);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  help->output = typeh[type_spec_count];
		  help->attribute.function_class = ARRAY;
		  help->attribute.storage_class_specifier = UNSPEC_SC;
		  typeh[type_spec_count] = help;
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  if (-1 == has_loc (PAR, $3))
		    COMPILE_ONLY;
		  if (-1 == add_to_ident_list ())
		    COMPILE_ONLY;
		  count_arr = 1;
		  typeh[type_spec_count--] = NULL;
		  DELETE_SUBSCRIPT;
		  typedef_f = 1;
		}

	| M declaration_specifiers IDENT list_dim ',' 
		{
		  struct internal_type *help;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (2018, $3);
		  else if (EXTERN_P(typeh[type_spec_count]))
		    error_message (2018, $3);
		  check_spec_constr (typeh[type_spec_count], $3);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), BLOCK);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  help->output = typeh[type_spec_count];
		  help->attribute.function_class = ARRAY;
		  help->attribute.storage_class_specifier = UNSPEC_SC;
		  typeh[type_spec_count] = help;
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  if (-1 == has_loc (PAR, $3))
		    COMPILE_ONLY;
		  while (-1 != dim[poc])
		    dim[poc--] = -1;
		  if (-1 == add_to_ident_list ())
		    COMPILE_ONLY;
		  count_arr = 1;
		  typeh[type_spec_count--] = NULL;
		  DELETE_SUBSCRIPT;
		  typedef_f = 1;
		}
	  list_form_param

	| M declaration_specifiers pointer IDENT
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (2018, $4);
		  else if (EXTERN_P(typeh[type_spec_count]))
		    error_message (2018, $4);
		  check_spec_constr (typeh[type_spec_count], $4);
		  if (!body_flag)
		    error_message (6009);
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  if (-1 == has_loc (PAR, $4))
		    COMPILE_ONLY;
		  if (-1 == add_to_ident_list ())
		    COMPILE_ONLY;
		  typeh[type_spec_count--] = NULL;
		  typedef_f = 1;
		}

	| M declaration_specifiers pointer IDENT ','
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (2018, $4);
		  else if (EXTERN_P(typeh[type_spec_count]))
		    error_message (2018, $4);
		  check_spec_constr (typeh[type_spec_count], $4);
		  if (!body_flag)
		    error_message (6009);
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  if (-1 == has_loc (PAR, $4))
		    COMPILE_ONLY;
		  if (-1 == add_to_ident_list ())
		    COMPILE_ONLY;
		  typeh[type_spec_count--] = NULL;
		  typedef_f = 1;
		}
	  list_form_param

	| M declaration_specifiers pointer IDENT list_dim
		{
		  struct internal_type *help;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (2018, $4);
		  else if (EXTERN_P(typeh[type_spec_count]))
		    error_message (2018, $4);
		  check_spec_constr (typeh[type_spec_count], $4);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), BLOCK);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  help->output = typeh[type_spec_count];
		  help->attribute.function_class = ARRAY;
		  help->attribute.storage_class_specifier = UNSPEC_SC;
		  typeh[type_spec_count] = help;
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  if (-1 == has_loc (PAR, $4))
		    COMPILE_ONLY;
		  if (-1 == add_to_ident_list ())
		    COMPILE_ONLY;
		  count_arr = 1;
		  typeh[type_spec_count--] = NULL;
		  DELETE_SUBSCRIPT;
		  typedef_f = 1;
		}

	| M declaration_specifiers pointer IDENT list_dim ',' 
		{
		  struct internal_type *help;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (2018, $4);
		  else if (EXTERN_P(typeh[type_spec_count]))
		    error_message (2018, $4);
		  check_spec_constr (typeh[type_spec_count], $4);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), BLOCK);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  help->output = typeh[type_spec_count];
		  help->attribute.function_class = ARRAY;
		  help->attribute.storage_class_specifier = UNSPEC_SC;
		  typeh[type_spec_count] = help;
		  if (-1 == add_to_spec_list ())
		    COMPILE_ONLY;
		  if (-1 == has_loc (PAR, $4))
		    COMPILE_ONLY;
		  while (-1 != dim[poc])
		    dim[poc--] = -1;
		  if (-1 == add_to_ident_list ())
		    COMPILE_ONLY;
		  count_arr = 1;
		  typeh[type_spec_count--] = NULL;
		  DELETE_SUBSCRIPT;
		  typedef_f = 1;
		}
	  list_form_param
	;

			/*
			 * List of dimensions for locals
			 */
list_dim :  '[' ']'
		{
		  dim[++poc] = NOT_DEFINED;
		}

	| '[' NUMBERI ']'
		{
		  count_arr *= $2;
		  dim[++poc] = $2;
		}
	
	| list_dim '[' NUMBERI ']'
		{
		  count_arr *= $3;
		  dim[++poc] = $3;
		} 
	;

			/*
			 * Parsing a list of local variables
			 */
list_loc_dekl
	: M declaration_specifiers list_loc_dekl_1
	| M declaration_specifiers ';'
	  	{
		  if (!(ENUM_P (typeh[type_spec_count]) ||
			UNION_P (typeh[type_spec_count]) ||
			STRUCT_P (typeh[type_spec_count])))
		    {
		      error_message (6010);
		      error_message (6011);
		    }
		  typeh[type_spec_count--] = NULL;		  
		}
	| M declaration_specifiers ';' 
	  	{
		  if (!(ENUM_P (typeh[type_spec_count]) ||
			UNION_P (typeh[type_spec_count]) ||
			STRUCT_P (typeh[type_spec_count])))
		    {
		      error_message (6010);
		      error_message (6011);
		    }
		  typeh[type_spec_count--] = NULL;		  
		}
	  list_loc_dekl
	;

list_loc_dekl_1
	: IDENT
		{
		  check_spec_constr (typeh[type_spec_count], $1);
		  if (VOID_P(typeh[type_spec_count]))
		    error_message (1012);
		  if (STATIC_P(typeh[type_spec_count]))
		    {
		      jmp1 = kodp;
		      GEN_JMP; GENCODE;
		      if (UNUSED_P(typeh[type_spec_count]))
			typeh[type_spec_count]->attribute.arit_class =
			  INTEGER;
		    }
		  if (-1 == has_loc (VAR, $1))
		    COMPILE_ONLY;
		  if (STATIC_P(typeh[type_spec_count]))
		    ((struct OPERAND_1_ma *)jmp1)->adr = kodp;
		  lookup_tables ($1, variable);
		}
	  initializer_optional_loc

  	| IDENT list_dim
		{
		  struct internal_type *help, *arch;
		  check_spec_constr (typeh[type_spec_count], $1);
		  if (VOID_P(typeh[type_spec_count]))
		    error_message (1012);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), BLOCK);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      help->output = typeh[type_spec_count]->output;
		      arch = typeh[type_spec_count]->output;
		      typeh[type_spec_count]->output = help;
		    }
		  else
		    {
		      help->output = typeh[type_spec_count];
		      arch = typeh[type_spec_count];
		      typeh[type_spec_count] = help;
		    }
		  help->attribute.function_class = ARRAY;
		  if (STATIC_P(help->output))
		    {
		      jmp1 = kodp;
		      GEN_JMP; GENCODE;
		      if (help->output->attribute.arit_class
			  == UNUSED_AC)
			help->output->attribute.arit_class =
			  INTEGER;
		      help->attribute.storage_class_specifier =
			STATIC_SC;
		    }
		  if (-1 == has_loc (VAR, $1))
		    COMPILE_ONLY;
		  if (STATIC_P(help->output))
		    ((struct OPERAND_1_ma *)jmp1)->adr = kodp;
		  count_arr = 1;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (arch);
		  else
		    typeh[type_spec_count] = arch;
		  DELETE_SUBSCRIPT;
		  lookup_tables ($1, variable);
		}
	  initializer_optional_loc

	| IDENT '(' ')'
		{}
	  initializer_optional_loc

	| IDENT '(' list_type_spec ')'
		{}
	  initializer_optional_loc

	| IDENT '(' list_form_param ')'
		{}
	  initializer_optional_loc

	| pointer IDENT
		{
		  struct internal_type *type;
		  check_spec_constr (typeh[type_spec_count], $2);
		  if (STATIC_P(typeh[type_spec_count]))
		    {
		      jmp1 = kodp;
		      GEN_JMP; GENCODE;
		      if (typeh[type_spec_count]->attribute.arit_class
			  == UNUSED_AC)
			typeh[type_spec_count]->attribute.arit_class =
			  INTEGER;
		    }
		  if (-1 == has_loc (VAR, $2))
		    COMPILE_ONLY;
		  if (STATIC_P(typeh[type_spec_count]))
		    ((struct OPERAND_1_ma *)jmp1)->adr = kodp;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      type = typeh[type_spec_count]->output;
		      typedef_copy (typeh[type_spec_count]->output);
		    }
		  else
		    type = typeh[type_spec_count];
				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(type))
		    type = type->output;
		  lookup_tables ($2, variable);
		}
	  initializer_optional_loc

  	| pointer IDENT list_dim
		{
		  struct internal_type *help, *arch;
		  check_spec_constr (typeh[type_spec_count], $2);
		  help = (struct internal_type *)
		    allocate (sizeof (struct internal_type), BLOCK);
		  init_zero ((char *)help, sizeof(struct internal_type));
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    {
		      help->output = typeh[type_spec_count]->output;
		      arch = typeh[type_spec_count]->output;
		      typeh[type_spec_count]->output = help;
		    }
		  else
		    {
		      help->output = typeh[type_spec_count];
		      arch = typeh[type_spec_count];
		      typeh[type_spec_count] = help;
		    }
		  help->attribute.function_class = ARRAY;
		  help->attribute.storage_class_specifier = UNSPEC_SC;
		  if (STATIC_P(typeh[type_spec_count]))
		    {
		      jmp1 = kodp;
		      GEN_JMP; GENCODE;
		      if (typeh[type_spec_count]->attribute.arit_class
			  == UNUSED_AC)
			typeh[type_spec_count]->attribute.arit_class =
			  INTEGER;
		    }
		  if (-1 == has_loc (VAR, $2))
		    COMPILE_ONLY;
		  if (STATIC_P(typeh[type_spec_count]))
		    ((struct OPERAND_1_ma *)jmp1)->adr = kodp;
		  count_arr = 1;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (arch);
		  else
		    typeh[type_spec_count] = arch;
				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(typeh[type_spec_count]->output))
		    arch = arch->output;
		  DELETE_SUBSCRIPT;
		  lookup_tables ($2, variable);
		}
	  initializer_optional_loc

	| pointer IDENT '(' ')'
		{
		  struct internal_type *type;
		  check_spec_constr (typeh[type_spec_count], $2);
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    type = typeh[type_spec_count]->output;
		  else
		    type = typeh[type_spec_count];
				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(type))
		    type = type->output;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (type);
		  else
		    typeh[type_spec_count] = type;
		  param_flag = 0;
		  lookup_tables ($2, variable);
		}
	  initializer_optional_loc

	| pointer IDENT '(' list_type_spec ')'
		{
		  struct internal_type *type;
		  check_spec_constr (typeh[type_spec_count], $2);
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    type = typeh[type_spec_count]->output;
		  else
		    type = typeh[type_spec_count];
				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(type))
		    type = type->output;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (type);
		  else
		    typeh[type_spec_count] = type;
		  param_flag = 0;
		  lookup_tables ($2, variable);
		}
	  initializer_optional_loc

	| pointer IDENT '(' list_form_param ')'
		{
		  struct internal_type *type;
		  check_spec_constr (typeh[type_spec_count], $2);
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    type = typeh[type_spec_count]->output;
		  else
		    type = typeh[type_spec_count];
				/* FIXME: here is a memory leakage in
				   the following loop. */
		  while (POINTER_P(type))
		    type = type->output;
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    typedef_copy (type);
		  else
		    typeh[type_spec_count] = type;
		  param_flag = 0;
		  lookup_tables ($2, variable);
		}
	  initializer_optional_loc
	;


initializer_optional_loc
	: ';' P
		{
		  typeh[type_spec_count--] = NULL;
		}
	| ';' P 
		{
		  typeh[type_spec_count--] = NULL;
		}
	  list_loc_dekl
	| local_initialization ';'
		{
		  typeh[type_spec_count--] = NULL;
		}
	| local_initialization ';'
		{
		  typeh[type_spec_count--] = NULL;
		}
	  list_loc_dekl
	| ',' P list_loc_dekl_1
	| local_initialization ',' list_loc_dekl_1
	; 

P	:
		{
		  if (! LOCAL_P(type_com[set])
		      && ! REMOTE_P(type_com[set])
		      && ! TYPEDEF_P(type_com[set]))
		    {
		      switch (type_ac[set])
			{
			  /* No breaks here. */
			case INTEGER:
			case SIGNED_AC | INTEGER:
			case UNSIGNED_AC | INTEGER:
			case LONG_AC | INTEGER:
			case LONG_AC | SIGNED_AC | INTEGER:
			case LONG_AC | UNSIGNED_AC | INTEGER:
			case SHORT_AC | INTEGER:
			case SHORT_AC | SIGNED_AC | INTEGER:
			case SHORT_AC | UNSIGNED_AC | INTEGER:
			case DOUB:
			case LONG_AC | DOUB:
			case FLT:
			case CHR:
			case SIGNED_AC | CHR:
			case UNSIGNED_AC | CHR:
			  GEN_POPAe; GENCODE;
			  break;
			case VID:
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000);
			  return 0;
			}
		      GEN_CLRT; GENCODE;
		      noninitialized_loc (variable[set].name);
		    }
		  is_address = 0;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  DELETE_SUBSCRIPT;
		}
	;

local_initialization
	: '=' initializer
		{
		  if (TYPEDEF_P(typeh[type_spec_count]))
		    error_message (1037, text);
#if 0
		  if (! CONST_P(type_com[set]))
		    error_message ();
#endif		  
		  if (SIMPLE_P(type_com[set]))
		    {
		      if (-1 == l_value_cast ())
			COMPILE_ONLY;
		      SET_ADDRESS;
		      TYPE_CLEAR;
		      move2lvalue ();
		    }
		  else if (ARRAY_P(type_com[set]))
		    {
		      DELETE_SUBSCRIPT;
		      if (CONST_P(type_com[set]))
			{
			  type_com[set - 1]->attribute.domain =
			    type_com[set]->attribute.domain;
			  if (! type_com[set - 1]->attribute.memory_size)
			    type_com[set - 1]->attribute.memory_size =
			      type_com[set]->attribute.memory_size;
			  {
			    register int i;
			    
			    for (i = 0;
				 i < type_com[set]->attribute.memory_size;
				 i++)
			      {
				GEN_PUSHAIi(i); GENCODE;
				GEN_MOVbv; GENCODE;
			      }
			    if (! POINTER_P(type_com[set - 1]))
			      {
				GEN_POPAe; GENCODE;
				SET_ADDRESS;
				TYPE_CLEAR;
			      }
			    if (CHAR_P(type_com[set]->output) && proc)
			      num_args[proc]--;
			  }
			}
		      else if (! type_com[set]->attribute.memory_size)
			{
			  type_com[set]->attribute.memory_size
			    = initialize_only *
			    type_com[set]->output->attribute.memory_size;
			  dim[++poc] = initialize_only;
			  put_array_subscript (&type_com[set]);
			}
		      if (set > 1 && POINTER_P(type_com[set - 1]))
			{
			  /* MOV two pointers as long ints. */
			  GEN_MOVli; GENCODE;
			  SET_ADDRESS;
			  TYPE_CLEAR;
			}
		    }
		  
		  switch (type_ac[set])
		    {
		      /* No breaks here. */
		    case INTEGER:
		    case SIGNED_AC | INTEGER:
		    case UNSIGNED_AC | INTEGER:
		    case LONG_AC | INTEGER:
		    case LONG_AC | SIGNED_AC | INTEGER:
		    case LONG_AC | UNSIGNED_AC | INTEGER:
		    case SHORT_AC | INTEGER:
		    case SHORT_AC | SIGNED_AC | INTEGER:
		    case SHORT_AC | UNSIGNED_AC | INTEGER:
		    case DOUB:
		    case LONG_AC | DOUB:
		    case FLT:
		    case CHR:
		    case SIGNED_AC | CHR:
		    case UNSIGNED_AC | CHR:
		      GEN_POPAe; GENCODE;
		      break;
		    case VID:
		      break;
		    default:
		      fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
		      error_message (5000);
		      return 0;
		    }
		  GEN_CLRT; GENCODE;
		  is_address = 0;
		  if (handle_main)
		    initialize_only = 1;
		  if (STATIC_P(typeh[type_spec_count]))
		    {
		      /* If there is a static variable in block
			 definition or function definition, we need to
			 initialize it only once. The virtual machine
			 must be triggered here. The variable jmp1
			 holds the start of the code generated by
			 initialization. */
		      pc = ((struct OPERAND_1_ma *)jmp1)->adr;
		      GEN_STOP; GENCODE;
		      if (no_compile_only
			  && (! handle_main || initialize_only))
			{
#ifndef NOT_MSWIN_AND_YES_DOS
			  VIRTUAL_MACHINE_SUSPENDED_RESET;
#endif
			  if (0 == exec ())
			    return 0;
#ifndef NOT_MSWIN_AND_YES_DOS
			  VIRTUAL_MACHINE_SUSPENDED_SET;
#endif
			}
		      else if (! s)
			return 0;
		      initialize_only ? initialize_only-- :
			initialize_only;
		      if (ARRAY_P(type_com[set]))
			((struct OPERAND_1_ma *)jmp1)->adr +=
			  type_com[set]->attribute.memory_size;
			kodp = ((struct OPERAND_1_ma *)jmp1)->adr;
		    }
		  set_value (variable[set].name);
		  SET_ADDRESS;
		  TYPE_CLEAR;
		}
	;
	   		/*
			 * List of actual parameters
			 */
call : list_param
	|  ')' 
		{
		  param_flag = 0;
		}
	;


/* The ANSI states this nonterminal as argument_expression_list. */
list_param : assignment_expression ')' 
		{
		  args[proc]++;
		  if (PRINTF_P || SCANF_P)
		    {
#if 0
		      if (!ARRAY_P(type_com[set]) &&
			  !POINTER_P(type_com[set]))
			promote_type ();
#endif
		      compare_format_args
			(format_args[proc][args[proc]],
			 type_com[set], type_ac[set]);
		      format_args[proc][args[proc]] = NULL;
		    }
		  if (STRUCT_P(type_com[set]) ||
		      UNION_P(type_com[set]))
		    error_message (6035);
		  if (call_by_value)
		    {
		      if (ARRAY_P(type_com[set]) ||
			  (POINTER_P(type_com[set])
			   && PRINTF_P))
			{
			  GEN_POPAst(count[proc]);
			  count[proc] += sizeof (char *);
			}
		      else if (STRUCT_P(type_com[set]) ||
			       UNION_P(type_com[set]))
			{
			  register int i;
			  for (i = count[proc];
			       i < type_com[set]->attribute.memory_size;
			       i++)
			    {
			      GEN_POPAb(i); GENCODE;
			    }
			  count[proc] +=
			    type_com[set]->attribute.memory_size;
			  GEN_POPAe;
			}
		      else
			{
			  GEN_POPA(count[proc]);
			  if (LOCAL_P(type_com[set]) ||
			      REMOTE_P(type_com[set]))
			    count[proc] +=
			      type_com[set]->output->attribute.memory_size;
			  else
			    count[proc] +=
			      type_com[set]->attribute.memory_size;
			}
		      if ((count[proc] % sizeof (int)) > 0)
			count[proc] += sizeof (int)
			  - (count[proc] % sizeof (int));
		    }
		  else if (call_by_reference)
		    {
		      GEN_POPAst(count[proc]);
		      count[proc] += sizeof (char *);
		    }
		  GENCODE; param_flag = 0;
				/*
				 * Internal types:
				 */
		  if (YES == type_com[set - 1]->attribute.export_type)
		    {
		      GEN_PUSHAIi(type_transform (type_ac[set],
				  type_com[set]->attribute.function_class,
						  atom_type_flag));
		      GENCODE;
		      if (call_by_value)
			{
			  GEN_POPAi(count[proc]);
			  count[proc] += sizeof (int);
			}
		      else if (call_by_reference)
			{
			  GEN_POPAst(count[proc]);
			  count[proc] += sizeof (char *);
			}
		      GENCODE;
		    }
		  atom_type_flag = 0;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  is_address = 0;
		}

	| assignment_expression ','
		{
		  args[proc]++;
		  if (PRINTF_P || SCANF_P)
		    {
#if 0
		      if (!ARRAY_P(type_com[set]) &&
			  !POINTER_P(type_com[set]))
			promote_type ();
#endif
		      compare_format_args
			(format_args[proc][args[proc]],
			 type_com[set], type_ac[set]);
		      format_args[proc][args[proc]] = NULL;
		    }
		  if (STRUCT_P(type_com[set]) ||
		      UNION_P(type_com[set]))
		    error_message (6035);
		  if (call_by_value)
		    {
		      if (ARRAY_P(type_com[set]) ||
			  (POINTER_P(type_com[set])
			   && PRINTF_P))
			{
			  GEN_POPAst(count[proc]);
			  count[proc] += sizeof (char *);
			}
		      else if (STRUCT_P(type_com[set]) ||
			       UNION_P(type_com[set]))
			{
			  register int i;
			  for (i = count[proc];
			       i < type_com[set]->attribute.memory_size;
			       i++)
			    {
			      GEN_POPAb(i); GENCODE;
			    }
			  count[proc] +=
			    type_com[set]->attribute.memory_size;
			  GEN_POPAe;
			}
		      else
			{
			  GEN_POPA(count[proc]);
			  if (LOCAL_P(type_com[set]) ||
			      REMOTE_P(type_com[set]))
			    count[proc] +=
			      type_com[set]->output->attribute.memory_size;
			  else
			    count[proc] +=
			      type_com[set]->attribute.memory_size;
			}
		      if ((count[proc] % sizeof (int)) > 0)
			count[proc] += sizeof (int)
			  - (count[proc] % sizeof (int));
		    }
		  else if (call_by_reference)
		    {
		      GEN_POPAst(count[proc]);
		      count[proc] += sizeof (char *);
		    }
		  GENCODE; 
		  if (YES == type_com[set-1]->attribute.export_type)
		    {
		      GEN_PUSHAIi(type_transform (type_ac[set],
				  type_com[set]->attribute.function_class,
						  atom_type_flag));
		      GENCODE;
		      if (call_by_value)
			{
			  GEN_POPA(count[proc]);
			  count[proc] += sizeof (int);
			}
		      else if (call_by_reference)
			{
			  GEN_POPAst(count[proc]);
			  count[proc] += sizeof (char *);
			}
		      GENCODE;
		    }
		  atom_type_flag = 0;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  is_address = 0;
		}
	  list_param
	;



		/*
	 	 * Primary expressions
		 */
		/*
		 * NO_ANSI
		 */
primary_expression
	: ident
		{
		  switch (type_com[set]->attribute.function_class)
		    {
		    case ENUM_FC: /* Fall through */
		    case SIMPLE:
		    case ARRAY: 
		    case STRUCT_FC:
		    case UNION_FC:
		    case LOCAL:
		    case REMOTE_F:
		    case POINTER:
		      break;
		    default:
		      fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
		      error_message (5000); return (0);
		    }
		}

		/*
		 * Numeric constants
		 */
	| NUMBERI
		{
		  GEN_PUSHAIi($1); GENCODE; 
		  type_ac[++set] = INTEGER;
		  type_com[set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof(struct internal_type));
		  type_com[set]->attribute.function_class = SIMPLE;
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.arit_class = INTEGER;
		  type_com[set]->attribute.memory_size = sizeof (int);
		  if (it_is_in_case &&
		      -1 == add_constant_to_list ($1))
		    return (0);
		  else
		    type_com[set]->attribute.domain = (char *)
		      &(((struct OPERAND_1_i *)
			 (kodp - sizeof (struct OPERAND_1_i)))->num);
		}

	| NUMBERUI
		{
		  GEN_PUSHAIui($1); GENCODE; 
		  type_ac[++set] = UNSIGNED_AC | INTEGER;
		  type_com[set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof(struct internal_type));
		  type_com[set]->attribute.function_class = SIMPLE;
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.arit_class = type_ac[set];
		  type_com[set]->attribute.memory_size
		    = sizeof (unsigned int);
		  if (it_is_in_case &&
		      -1 == add_constant_to_list ($1))
		    return (0);
		  else
		    type_com[set]->attribute.domain = (char *)
		      &(((struct OPERAND_1_ui *)
			 (kodp - sizeof (struct OPERAND_1_ui)))->num);
		}

	| NUMBERLI
		{
		  GEN_PUSHAIli($1); GENCODE; 
		  type_ac[++set] = LONG_AC | INTEGER;
		  type_com[set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof(struct internal_type));
		  type_com[set]->attribute.function_class = SIMPLE;
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.arit_class = type_ac[set];
		  type_com[set]->attribute.memory_size
		    = sizeof (long int);
		  if (it_is_in_case &&
		      -1 == add_constant_to_list ($1))
		    return (0);
		  else
		    type_com[set]->attribute.domain = (char *)
		      &(((struct OPERAND_1_li *)
			 (kodp - sizeof (struct OPERAND_1_li)))->num);
		}

	| NUMBERLUI
		{
		  GEN_PUSHAIlui($1); GENCODE; 
		  type_ac[++set] = LONG_AC | UNSIGNED_AC | INTEGER;
		  type_com[set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof(struct internal_type));
		  type_com[set]->attribute.function_class = SIMPLE;
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.arit_class = type_ac[set];
		  type_com[set]->attribute.memory_size
		    = sizeof (long unsigned int);
		  if (it_is_in_case &&
		      -1 == add_constant_to_list ($1))
		    return (0);
		  else
		    type_com[set]->attribute.domain = (char *)
		      &(((struct OPERAND_1_lui *)
			 (kodp - sizeof (struct OPERAND_1_lui)))->num);
		}

	| NUMBERD
		{
		  GEN_PUSHAId($1); GENCODE; 
		  type_ac[++set] = DOUB;
		  type_com[set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof(struct internal_type));
		  type_com[set]->attribute.function_class = SIMPLE;
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.arit_class = type_ac[set];
		  type_com[set]->attribute.memory_size
		    = sizeof (double);
		  type_com[set]->attribute.domain = (char *)
		    &(((struct OPERAND_1_id *)
		       (kodp - sizeof (struct OPERAND_1_id)))->num);
		}

	| NUMBERLD
		{
		  GEN_PUSHAIld($1); GENCODE; 
		  type_ac[++set] = LONG_AC | DOUB;
		  type_com[set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof(struct internal_type));
		  type_com[set]->attribute.function_class = SIMPLE;
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.arit_class = type_ac[set];
		  type_com[set]->attribute.memory_size
		    = sizeof (long double);
		  type_com[set]->attribute.domain = (char *)
		    &(((struct OPERAND_1_ild *)
		       (kodp - sizeof (struct OPERAND_1_ild)))->num);
		}

	| NUMBERF
		{
		  GEN_PUSHAIf($1); GENCODE; 
		  type_ac[++set] = FLT;
		  type_com[set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof(struct internal_type));
		  type_com[set]->attribute.function_class = SIMPLE;
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.arit_class = type_ac[set];
		  type_com[set]->attribute.memory_size
		    = sizeof (float);
		  type_com[set]->attribute.domain = (char *)
		    &(((struct OPERAND_1_if *)
		       (kodp - sizeof (struct OPERAND_1_if)))->num);
		}

	| STRINGC
		{
		  GEN_PUSHAIst($1); GENCODE; 
		  type_ac[++set] = CHR;
		  type_com[set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof (struct internal_type));
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.function_class = ARRAY;
		  type_com[set]->output = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set]->output,
			     sizeof (struct internal_type));
		  type_com[set]->output->attribute.arit_class =
		    type_ac[set];
		  type_com[set]->attribute.domain = 
		    ((struct OPERAND_1_mi *)
		     (kodp - sizeof (struct OPERAND_1_mi)))->adr;
		  type_com[set]->attribute.memory_size =
		    strlen ($1) + 1;
		  SET_ADDRESS;
		}

	| WSTRINGC
		{
		  type_com[++set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof (struct internal_type));
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.function_class = ARRAY;
		  type_com[set]->output = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set]->output,
			     sizeof (struct internal_type));
		  if (ARRAY_P(type_com[set - 1]) &&
		      INTEGER_P(type_com[set - 1]->output))
		    {
		      int i, j = strlen ($1);
		      type_ac[set] = INTEGER;
		      for (i = 1; i < j; i++)
			{
			  GEN_MOVaa; GENCODE;
			  GEN_PUSHAIi((i - 1) * sizeof (int));
			  GENCODE;
			  GEN_MOVar; GENCODE;
			  GEN_PUSHAIi($1[i]); GENCODE;
			  move2lvalue ();
			  GEN_POPAe; GENCODE;
			}
		      type_com[set]->attribute.memory_size =
			j * sizeof (int); 
		      /* There is L at the beginning of the string;
			 therefore &$1[1] */
		      type_com[set]->attribute.domain = &$1[1];
		    }
		  else
		    {
		      /* There is L at the beginning of the string;
			 therefore &$1[1] */
		      GEN_PUSHAIst(&$1[1]); GENCODE;
		      type_ac[set] = CHR;
		      type_com[set]->attribute.memory_size =
			strlen ($1) + 1; 
		      type_com[set]->attribute.domain = 
			((struct OPERAND_1_mi *)
			 (kodp - sizeof (struct OPERAND_1_mi)))->adr;
		    }
		  type_com[set]->output->attribute.arit_class =
		    type_ac[set];
		  SET_ADDRESS;
		}

	| NUMBERC
		{
		  GEN_PUSHAIc($1); GENCODE;
		  type_ac[++set] = CHR;
		  type_com[set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof(struct internal_type));
		  type_com[set]->attribute.function_class = SIMPLE;
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.arit_class = type_ac[set];
		  type_com[set]->attribute.memory_size
		    = sizeof (char);
		  type_com[set]->attribute.domain = (char *)
		    &(((struct OPERAND_1_ic *)
		       (kodp - sizeof (struct OPERAND_1_ic)))->num);
		}

	| '('  expression  ')'
	;

ident :	IDENT
		{
		  lookup_tables ($1, variable);
		}
	;

postfix_expression
	: primary_expression
	| postfix_expression
		{
		  if (subscript_flag[set])
		  /* 
		   * Flag for the first subscript 
		   */
		    {
		      atom_type_flag = 1;
		      if (1 == poc)
			{
			  GEN_PUSHAIi(dim[poc]); GENCODE;
			  GEN_MULTi; GENCODE;
			  dim[poc--] = -1;
			}
		      else if (1 < poc)
			{
			  GEN_PUSHAIi(dim[poc]); GENCODE;
			  GEN_MULTi; GENCODE;
			  dim[poc--] = -1;
			}
		      else if (! POINTER_P(type_com[set]))
			error_message (2000);
		    }
		  else
		    {
		      if (poc)
			dim[poc--] = -1;
		      if (! ARRAY_P(type_com[set]) &&
			  ! POINTER_P(type_com[set]))
			error_message (2000);
		      if (POINTER_P(type_com[set])
#if 0
			  && 0 < variable[set].offset
#endif
			)
			{
			  GEN_MOVap; GENCODE;
			}
		    }
		}
	  '[' expression ']'
		{
		  if (INTEGER != type_ac[set])
		    error_message (2002);
		  else
		    {
		      if (subscript_flag[set - 1])
			{
			  GEN_ADDi; GENCODE;
			}
		      subscript_flag[set - 1]++;
		    }
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  if (! poc)
		    {
		      subscript_flag[set]--;
		      GEN_PUSHAIi(type_com[set]->output->attribute.memory_size); 
		      GENCODE;
		      GEN_MULTi; GENCODE;
		      OFFSET_LAST_ADD_ARRAY;
		      GEN_MOVar; GENCODE;
		      kodp3 = kodp;
		      type_com[set] = type_com[set]->output;
		      if (POINTER_P(type_com[set]))
			type_ac[set] = LONG_AC | INTEGER;
		      else
			type_ac[set] =
			  type_com[set]->attribute.arit_class;
		    }
		}

	| postfix_expression '.' IDENT
		{/* offset_aggregate_ident () calls find_member and
		    this function changes the type_ac[set]
		    accordingly. It generates appropriate instructions
		    as well. */
		  int aggr_offset = 0;
		  /* Not in subscript any more.*/
		  if ((STRUCT_P (type_com[set]) ||
		       UNION_P (type_com[set]))
		      && NULL != type_com[set]->input)
		    {
		      type_com[set] = type_com[set]->input;
		      aggr_offset = offset_aggregate_ident ();
		    }
		  else if (NULL != type_com[set]->output
			   && (STRUCT_P (type_com[set]->output)
			       || UNION_P (type_com[set]->output))
			   && NULL != type_com[set]->output->input)
		    {
		      if (subscript_flag[set])
			{
			  GEN_PUSHAIi(type_com[set]->output->attribute.memory_size); 
			  GENCODE;
			  GEN_MULTi; GENCODE;
			}
		      type_com[set] = type_com[set]->output->input;
		      aggr_offset = offset_aggregate_ident ();
		      if (ARRAY_P(type_com[set]))
			{
			  array_subscript (type_com[set]->input);
			  type_ac[set] =
			    type_com[set]->output->attribute.arit_class;
			}
		      else if (POINTER_P(type_com[set]))
			type_ac[set] = LONG_AC | INTEGER;
		    }
		  else
		    {
		      text = $3;
		      error_message (2009);
		    }
		  GEN_PUSHAIi(aggr_offset); GENCODE;
		  if (struct_union_field[set])
		    {
		      GEN_ADDi; GENCODE;
		      struct_union_field[set]--;
		    }
		  if (subscript_flag[set])
		    {
		      GEN_ADDi; GENCODE;
		      subscript_flag[set]--;
		    }
		  struct_union_field[set]++;
		}

	| postfix_expression PTR IDENT
		{
		  int aggr_offset;
		  if (POINTER_P(type_com[set]))
		    {
		      /* Not in subscript any more.*/
		      subscript_flag[set] > 0 ? subscript_flag[set]-- :
			subscript_flag[set];
		      if ((variable[set].adr != NULL
			   || variable[set].offset != 0) &&
			  !(SIMPLE_P(type_com[set]->output)))
			{
			  if (struct_union_field[set])
			    {
			      GEN_MOVar; GENCODE;
			      struct_union_field[set]--;
			    }
			  GEN_MOVap; GENCODE;
			}
		      if (NULL != type_com[set]->output->input)
			{
			  type_com[set] = type_com[set]->output->input;
			  type_ac[set] =
			    type_com[set]->attribute.arit_class;
			  aggr_offset = offset_aggregate_ident ();
			  GEN_PUSHAIi(aggr_offset); GENCODE;
			  
			  if (struct_union_field[set])
			    {
			      GEN_ADDi; GENCODE;
			      struct_union_field[set]--;
			    }
			  struct_union_field[set]++;
			  if (type_ac[set] == UNUSED_AC)
			    type_ac[set] = LONG_AC | INTEGER;
			}
		      else
			fprintfx (stderr, "FIXME:%d\n", __LINE__);
		    }
		  else
		    error_message (1021);
		}

	| postfix_expression PP
		{
		  if (struct_union_field[set])
		    {
		      OFFSET_LAST_ADD;
		      GEN_MOVar; GENCODE;
		      variable[set].adr = NULL;
		      variable[set].offset = 0;
		    }
		  else if (POINTER_P(type_com[set]))
		    {
		      GEN_MOVvli; GENCODE;
		      GEN_XCHG; GENCODE;
		      GEN_MOVaa; GENCODE;
		      GEN_PUSHAIli(type_com[set]->output->attribute.memory_size);
		      GENCODE;
		      GEN_ADDli; GENCODE;
		      GEN_MOVli; GENCODE;
		      GEN_POPAe; GENCODE;
		      break;
		    }
		  if (! PUSHA_P && ! MOV_P)
		    error_message (1035, "increment");
		  
		  GEN_MOVv; GENCODE;
		  GEN_XCHG; GENCODE;
		  GEN_MOVaa; GENCODE;
		  GEN_PUSHAI(1); GENCODE;
		  GEN_ADD; GENCODE;
		  GEN_MOV; GENCODE;
		  GEN_POPAe; GENCODE;
		}

	| postfix_expression MM
		{
		  if (struct_union_field[set])
		    {
		      OFFSET_LAST_ADD;
		      GEN_MOVar; GENCODE;
		      variable[set].adr = NULL;
		      variable[set].offset = 0;
		    }
		  else if (POINTER_P(type_com[set]))
		    {
		      GEN_MOVvli; GENCODE;
		      GEN_XCHG; GENCODE;
		      GEN_MOVaa; GENCODE;
		      GEN_PUSHAIli(type_com[set]->output->attribute.memory_size);
		      GENCODE;
		      GEN_SUBli; GENCODE;
		      GEN_MOVli; GENCODE;
		      GEN_POPAe; GENCODE;
		      break;
		    }
		  if (! PUSHA_P && ! MOV_P)
		    error_message (1035, "decrement");

		  GEN_MOVv; GENCODE;
		  GEN_XCHG; GENCODE;
		  GEN_MOVaa; GENCODE;
		  GEN_PUSHAI(1); GENCODE;
		  GEN_SUB; GENCODE;
		  GEN_MOV; GENCODE;
		  GEN_POPAe; GENCODE;
		}

			/*
			 * Procedure call
			 */ 
	| postfix_expression '('
		{
		  struct ident_tab *help;
		  text = proc_name_text[proc];
		  help = point (text);
		  if (NULL == help)
		    COMPILE_ONLY;
		  if (help->body)
		    proc_name[proc] = help->adr;
		  if (!num_args[proc])
		    num_args[proc] = get_num_args (help->type);
		  param_flag = 1;
			/*
			 * Internal types:
			 */
		  switch (type_com[set]->attribute.function_class)
		    {
		    case REMOTE_F:
		      GEN_PUSHf; GENCODE;
		      GEN_MOVfs; GENCODE;
		      /* type_com[set] =
			 help->type->output->attribute.export_type;*/
		      break;
		    default: /* FIXME: */
		      break;
		    }
		  call_fix[proc] = kodp; GEN_SUBss(0); GENCODE;
		}
	  call
		{
		  text = proc_name_text[proc];
		  if (num_args[proc] != 0)
		    if (num_args[proc] > args[proc])
		      error_message (2010);
		    else if (num_args[proc] < args[proc])
		      error_message (2011);
		  if (-1 == point_call (text))
		    COMPILE_ONLY;
		  if (LOCAL == type_com[set]->attribute.function_class)
		    {
		      GEN_CALL(proc_name[proc]); GENCODE;
		      GEN_ADDss(count[proc]); GENCODE;
		    }
		  else
		    {
		      GEN_XCALL; GENCODE;
		      GEN_MOVsf; GENCODE;
		      GEN_POPf; GENCODE;
		    }
		  ((struct OPERAND_1_i *)call_fix[proc])->num = count[proc];
		  count[proc] = 0;
#if 0
		  free (proc_name_text[proc--]);
#else
		  proc_name[proc] = NULL;
		  num_args[proc] = 0;
		  args[proc] = 0;
		  proc_name_text[proc--] = NULL;
#endif
		}
	;
	
		/*
		 * NO_ANSI
		 */
unary_expression
	: postfix_expression
		{
		  switch (type_com[set]->attribute.function_class)
		    {
		    case POINTER:
		    case ENUM_FC:
		    case SIMPLE:
		      if (NULL != type_com[set]->field_name)
			{
			  OFFSET_LAST_ADD;
			  if (variable[set].offset != 0
			      || variable[set].adr != NULL)
			    {
			      GEN_MOVar; GENCODE;
			    }
			  kodp3 = kodp;
			}
		      break;
		    case ARRAY:
		      if (param_flag && !subscript_flag[set])
			{
			  kodp3 = kodp;
			  DELETE_SUBSCRIPT;
			}
		      break;
		    case STRUCT_FC: /* FIXME: */
		    case UNION_FC:
		      break;
		    case LOCAL:
		    case REMOTE_F:
		      break;
		    default:
		      fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
		      error_message (5000);
		      abort ();
		    }
		}

	| '&' unary_expression
		{
		  if (is_address)
		    error_message (1022);
		  else
		    {
		      struct internal_type *arch;
		      kodp3 = kodp;
		      is_address = 1;
		      switch (type_com[set]->attribute.function_class)
			{
			case SIMPLE:
			case ARRAY:
			case STRUCT_FC:
			case UNION_FC:
			  if ((NULL != type_com[set]->field_name
			       || ARRAY_P(type_com[set])) &&
			      variable[set].adr == NULL
			      && variable[set].offset == 0)
			    {
			      GEN_ADDi; GENCODE;
			    }
			  if (variable[set].adr != NULL
			      || variable[set].offset != 0)
			    {
			      GEN_MOVpa; GENCODE;
			    }
			  arch = (struct internal_type *) 
			    allocate (sizeof(struct internal_type), 
				      scope_level > PERM ? BLOCK : PERM);
			  init_zero ((char *)arch,
				     sizeof(struct internal_type));
			  arch->attribute.function_class = POINTER;
			  arch->attribute.type_qualifier = UNDEF_TQ;
			  arch->attribute.memory_size = POINTER_SIZE;

			  if (ARRAY_P(type_com[set]))
			    arch->output = type_com[set]->output;
			  else
			    arch->output = type_com[set];
			  type_com[set] = arch;
			  type_ac[set] = INTEGER;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			  break;
			}
		    }
		}

	| '*' unary_expression
		{
		  if (POINTER_P(type_com[set]))
		    {
		      type_com[set] = type_com[set]->output;
		      GEN_MOVap; GENCODE;
		      type_ac[set] = type_com[set]->attribute.arit_class;
		    }
		  else if (ARRAY_P(type_com[set]))
		    {
		      type_com[set] = type_com[set]->output;
		      type_ac[set] = type_com[set]->attribute.arit_class;
		    }
		  else
		    error_message (1029);
		}

	| NEG_T unary_expression 
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    {
		      type_com[set] = (struct internal_type *) 
			allocate (sizeof(struct internal_type), 
				  scope_level > PERM ? BLOCK : PERM);
		      init_zero ((char *)type_com[set],
				 sizeof(struct internal_type));
		      type_com[set]->attribute.function_class =
			SIMPLE;
		      type_com[set]->attribute.type_qualifier =
			UNDEF_TQ;
		      type_com[set]->attribute.arit_class =
			INTEGER;
		    }
		  kodp3 = kodp;
		  GEN_NEG;
		  GENCODE; type_ac[set] = INTEGER;
		}

	| NEG_B unary_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    error_message (1030);
		  if (INTEGER == type_ac[set])
		    {
		      switch (type_ac[set])
			{
			case INTEGER:
			  kodp3 = kodp;
			  GEN_NOT;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		      GENCODE; type_ac[set] = INTEGER;
		    }
		  else
		    error_message (1005);
		}

	| '+' unary_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    error_message (1032);
		}
	| '-'
		{
		  kodp3=kodp;
		  GEN_PUSHAI(0); GENCODE;
		}
	  unary_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    error_message (1031);
		  GEN_SUB; GENCODE;
		}

	|  PP unary_expression ae_empty
		{
		  if (POINTER_P(type_com[set]))
		    {
		      GEN_PUSHAIli(type_com[set]->output->attribute.memory_size);
		      GENCODE;
		      GEN_ADDli;
		    }
		  else 
		    {
		      GEN_PUSHAI(1); GENCODE;
		      GEN_ADD;
		    }
		  GENCODE; kodp3 = kodp;
		  move2lvalue ();
		  SET_ADDRESS;
  		}

	| MM unary_expression ae_empty
		{
		  if (POINTER_P(type_com[set]))
		    {
		      GEN_PUSHAIli(type_com[set]->output->attribute.memory_size);
		      GENCODE;
		      GEN_SUBli;
		    }
		  else 
		    {
		      GEN_PUSHAI(1); GENCODE;
		      GEN_SUB;
		    }
		  GENCODE; kodp3 = kodp;
		  move2lvalue ();
		  SET_ADDRESS;
		}

	| SIZEOF unary_expression
		{
		  if (NULL != kodp4)
		    {
		      kodp = kodp4;
		      kodp4 = NULL;
		    }
		  if (type_com[set]->attribute.memory_size)
		    {
		      GEN_PUSHAIi(type_com[set]->attribute.memory_size);
		      GENCODE;
		    }
		  else
		    error_message (1027);
		  type_ac[set] = INTEGER;
		  type_com[set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof(struct internal_type));
		  type_com[set]->attribute.function_class = SIMPLE;
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.memory_size = sizeof (int);
		}

	| SIZEOF '(' type_name ')'
		{
		  if (typeh[type_spec_count]->attribute.memory_size)
		    {
		      GEN_PUSHAIi(typeh[type_spec_count]->attribute.memory_size);
		      GENCODE;
		    }
		  else
		    error_message (1027);
		  type_ac[++set] = INTEGER;
		  type_com[set] = (struct internal_type *)
		    allocate (sizeof (struct internal_type), PERM);
		  init_zero ((char *)type_com[set],
			     sizeof(struct internal_type));
		  type_com[set]->attribute.function_class = SIMPLE;
		  type_com[set]->attribute.type_qualifier = CONST_TQ;
		  type_com[set]->attribute.memory_size = sizeof (int);
		  typeh[type_spec_count--] = NULL;
		}
	;

cast_expression
	: unary_expression
	| '(' type_name ')' cast_expression
		{
		  check_spec_constr (typeh[type_spec_count], "type name");
		  typeh[type_spec_count]->attribute.memory_size =
		    set_memory_size (typeh[type_spec_count]->attribute.arit_class);
		  switch (typeh[type_spec_count]->attribute.function_class)
		    {
		    case SIMPLE:
		      kodp3 = kodp;
		      switch (typeh[type_spec_count]->attribute.arit_class)
			{
			case INTEGER:
			  switch (type_ac[set])
			    {
			    case INTEGER:
			      break;
			    case DOUB:
			      GEN_CVTDI; GENCODE;
			      break;
			    case FLT:
			      GEN_CVTFI; GENCODE;
			      break;
			    case CHR:
			      GEN_CVTCIt; GENCODE;
			      break;
			    default:
			      error_message (1005);
			    }
			  type_ac[set] = INTEGER;
			  break;
			case DOUB:
			  switch (type_ac[set])
			    {
			    case INTEGER:
			      GEN_CVTIDt; GENCODE;
			      break;
			    case DOUB:
			      break;
			    case FLT:
			      GEN_CVTFDt; GENCODE;
			      break;
			    case CHR:
			      GEN_CVTCDt; GENCODE;
			      break;
			    default:
			      error_message (1005);
			    }
			  type_ac[set] = DOUB;
			  break;
			case FLT:
			  switch (type_ac[set])
			    {
			    case INTEGER:
			      GEN_CVTIFt; GENCODE;
			      break;
			    case DOUB:
			      GEN_CVTDF; GENCODE;
			      break;
			    case FLT:
			      break;
			    case CHR:
			      GEN_CVTCFt; GENCODE;
			      break;
			    default:
			      error_message (1005);
			    }
			  type_ac[set] = FLT;
			  break;
			case CHR:
			  switch (type_ac[set])
			    {
			    case INTEGER:
			      GEN_CVTIC; GENCODE;
			      break;
			    case DOUB:
			      GEN_CVTDC; GENCODE;
			      break;
			    case FLT:
			      GEN_CVTFC; GENCODE;
			      break;
			    case CHR:
			      break;
			    default:
			      error_message (1005);
			    }
			  type_ac[set] = CHR;
			  break;
			case VID:
			  switch (type_ac[set])
			    {
			      /* Here are no breaks between. */
			    case INTEGER:
			    case DOUB:
			    case CHR:
			    case VID:
			      break;
			    default:
			      error_message (1005);
			    }
			  type_ac[set] = VID;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n",
				    __FILE__, __LINE__);
			  error_message (5000); 
			  abort ();
			}
		      break;
		    case ARRAY:
		    case STRUCT_FC:
		    case UNION_FC:
		      error_message (1020);
		      break;
		    case POINTER:
		      break;
		    default:
		      fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
		      error_message (5002);
		      abort ();
		    }
		  type_com[set] = typeh[type_spec_count];
		  typeh[type_spec_count--] = NULL;
		}
	;

multiplicative_expression
	: cast_expression
	| multiplicative_expression '*' cast_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "*");
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_MULT;
		  GENCODE;
		}

	| multiplicative_expression '/' cast_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "/");
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_DIV;
		  GENCODE;
		}

	| multiplicative_expression '%' cast_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "%");
		  if (INTEGER == type_ac[set])
		    {
		      switch (type_ac[--set])
			{
			case INTEGER:
			  kodp3 = kodp;
			  GEN_MOD; GENCODE;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		    }
		  else 
		    error_message (1005);
	     	}
	;

additive_expression
	: multiplicative_expression
	| additive_expression '+' multiplicative_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    {
		      GEN_PUSHAIli(type_com[set]->output->attribute.memory_size);
		      GENCODE;
		      GEN_MULTli; GENCODE;
		      type_com[set - 1] = type_com[set];
		    }
		  else if (POINTER_P(type_com[set - 1]) ||
			   ARRAY_P(type_com[set - 1]))
		    {
		      GEN_PUSHAIli(type_com[set - 1]->output->attribute.memory_size);
		      GENCODE;
		      GEN_MULTli; GENCODE;
		    }
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_ADD;
		  GENCODE;
		}

	| additive_expression '-' multiplicative_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    {
		      GEN_PUSHAIli(type_com[set]->output->attribute.memory_size);
		      GENCODE;
		      GEN_MULTli; GENCODE;
		      type_com[set - 1] = type_com[set];
		    }
		  else if (POINTER_P(type_com[set - 1]) ||
			   ARRAY_P(type_com[set - 1]))
		    {
		      GEN_PUSHAIli(type_com[set - 1]->output->attribute.memory_size);
		      GENCODE;
		      GEN_MULTli; GENCODE;
		    }
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_SUB;
		  GENCODE;
		}
	;

shift_expression
	: additive_expression
	| shift_expression SHIL additive_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "<<");
		  ERROR_P;
		  if (INTEGER == type_ac[set])
		    {
		      switch (type_ac[--set])
			{
			case INTEGER:
			  kodp3 = kodp;
			  GEN_SAL;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__,
				    __LINE__); 
			  error_message (5000); return (0);
			}
		    }
		  else
		    error_message (1005);
		  GENCODE;
		}

	| shift_expression SHIR additive_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, ">>");
		  if (INTEGER == type_ac[set])
		    {
		      switch (type_ac[--set])
			{
			case INTEGER:
			  kodp3 = kodp;
			  GEN_SAR;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		    }
		  else
		    error_message (1005);
		  GENCODE;
		}
	;

relational_expression
	: shift_expression
	| relational_expression '<' shift_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    error_message (6024, type_com[set],
				   type_com[set - 1]);
		  else if (POINTER_P(type_com[set - 1]) ||
			   ARRAY_P(type_com[set - 1]))
		    error_message (6024, type_com[set - 1],
				   type_com[set]);
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_LO;
		  GENCODE; type_ac[set] = INTEGER;
		}

	| relational_expression '>' shift_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    error_message (6024, type_com[set],
				   type_com[set - 1]);
		  else if (POINTER_P(type_com[set - 1]) ||
			   ARRAY_P(type_com[set - 1]))
		    error_message (6024, type_com[set - 1],
				   type_com[set]);
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_GR;
		  GENCODE; type_ac[set] = INTEGER;
		}

	| relational_expression LQ shift_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    error_message (6024, type_com[set],
				   type_com[set - 1]);
		  else if (POINTER_P(type_com[set - 1]) ||
			   ARRAY_P(type_com[set - 1]))
		    error_message (6024, type_com[set - 1],
				   type_com[set]);
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_LE;
		  GENCODE; type_ac[set] = INTEGER;
		}

	| relational_expression GQ shift_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    error_message (6024, type_com[set],
				   type_com[set - 1]);
		  else if (POINTER_P(type_com[set - 1]) ||
			   ARRAY_P(type_com[set - 1]))
		    error_message (6024, type_com[set - 1],
				   type_com[set]);
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_GE;
		  GENCODE; type_ac[set] = INTEGER;
		}
	;

equality_expression
	: relational_expression
	| equality_expression EQ_A relational_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    error_message (6024, type_com[set],
				   type_com[set - 1]);
		  else if (POINTER_P(type_com[set - 1]) ||
			   ARRAY_P(type_com[set - 1]))
		    error_message (6024, type_com[set - 1],
				   type_com[set]);
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_EQ;
		  GENCODE; type_ac[set] = INTEGER;
		}

	| equality_expression NE_A relational_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    error_message (6024, type_com[set],
				   type_com[set - 1]);
		  else if (POINTER_P(type_com[set - 1]) ||
			   ARRAY_P(type_com[set - 1]))
		    error_message (6024, type_com[set - 1],
				   type_com[set]);
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_NE;
		  GENCODE; type_ac[set] = INTEGER;
		}
	;

	/* The ANSI specifies nonterminal AND_expression. */
	/* I have added bit_ infront because of filter for */
	/* grammar output in LaTeX. */

bit_AND_expression
	: equality_expression
	| bit_AND_expression '&' equality_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "&");
		  if (INTEGER == type_ac[set])
		    {
		      switch (type_ac[--set])
			{
			case INTEGER:
			  kodp3 = kodp;
			  GEN_ANDB;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		    }
		  else
		    error_message (1005);
		  GENCODE;
		}
	;

exclusive_OR_expression
	: bit_AND_expression
	| exclusive_OR_expression '^' bit_AND_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "^");
		  if (INTEGER == type_ac[set])
		    {
		      switch (type_ac[--set])
			{
			case INTEGER:
			  kodp3 = kodp;
			  GEN_XOR;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		    }
		  else
		    error_message (1005);
		  GENCODE;
		}
	;

inclusive_OR_expression
	: exclusive_OR_expression
	| inclusive_OR_expression '|' exclusive_OR_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "|");
		  if (INTEGER == type_ac[set])
		    {
		      switch (type_ac[--set])
			{
			case INTEGER:
			  kodp3 = kodp;
			  GEN_ORB;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		    }
		  else
		    error_message (1005);
		  GENCODE;
		}
	;

logical_AND_expression
	: inclusive_OR_expression
	| logical_AND_expression AND_A 
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    {
		      type_com[set] = (struct internal_type *) 
			allocate (sizeof(struct internal_type), 
				  scope_level > PERM ? BLOCK : PERM);
		      init_zero ((char *)type_com[set],
				 sizeof(struct internal_type));
		      type_com[set]->attribute.function_class =
			SIMPLE;
		      type_com[set]->attribute.type_qualifier =
			UNDEF_TQ;
		      type_com[set]->attribute.arit_class =
			LONG_AC | INTEGER;
		    }
		  GEN_MOVaa; GENCODE;
		  and_jmp[set] = kodp;
		  GEN_JZ; GENCODE;
		}
	  inclusive_OR_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    {
		      type_com[set] = (struct internal_type *) 
			allocate (sizeof(struct internal_type), 
				  scope_level > PERM ? BLOCK : PERM);
		      init_zero ((char *)type_com[set],
				 sizeof(struct internal_type));
		      type_com[set]->attribute.function_class =
			SIMPLE;
		      type_com[set]->attribute.type_qualifier =
			UNDEF_TQ;
		      type_com[set]->attribute.arit_class =
			LONG_AC | INTEGER;
		    }
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_AND;
		  GENCODE; type_ac[set] = INTEGER;
		  ((struct OPERAND_1_ma *)and_jmp[set])->adr = kodp;
		}
	;

logical_OR_expression
	: logical_AND_expression
	| logical_OR_expression OR_A 
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    {
		      type_com[set] = (struct internal_type *) 
			allocate (sizeof(struct internal_type), 
				  scope_level > PERM ? BLOCK : PERM);
		      init_zero ((char *)type_com[set],
				 sizeof(struct internal_type));
		      type_com[set]->attribute.function_class =
			SIMPLE;
		      type_com[set]->attribute.type_qualifier =
			UNDEF_TQ;
		      type_com[set]->attribute.arit_class =
			LONG_AC | INTEGER;
		    }
		  GEN_MOVaa; GENCODE;
		  or_jmp[set] = kodp;
		  GEN_JNZ; GENCODE;
		}
	  logical_AND_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    {
		      type_com[set] = (struct internal_type *) 
			allocate (sizeof(struct internal_type), 
				  scope_level > PERM ? BLOCK : PERM);
		      init_zero ((char *)type_com[set],
				 sizeof(struct internal_type));
		      type_com[set]->attribute.function_class =
			SIMPLE;
		      type_com[set]->attribute.type_qualifier =
			UNDEF_TQ;
		      type_com[set]->attribute.arit_class =
			LONG_AC | INTEGER;
		    }
		  if (-1 == implicit_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = kodp;
		  GEN_OR;
		  GENCODE; type_ac[set] = INTEGER;
		  ((struct OPERAND_1_ma *)or_jmp[set])->adr = kodp;
		}
	;


conditional_expression
	: logical_OR_expression
	| logical_OR_expression '?' 
		{
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  kodp3 = NULL; GEN_CLRT; GENCODE; fixp++;
#ifdef DEBUG
		  printfx ("fixp=%u\n",fixp);
#endif
		  fixp->if1.major = IF;
		  fixp->if1.jz = kodp;
		  GEN_JZ; GENCODE;
		}
	  expression ':' 
		{
		  fixp->if1.jmp = kodp;
		  GEN_JMP; GENCODE;
		  ((struct OPERAND_1_ma *)(fixp->if1.jz))->adr = kodp;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		}
	  conditional_expression
		{
		  ((struct OPERAND_1_ma *)(fixp->if1.jmp))->adr =
		    kodp; 
		  fixp--;
		}
	;


		/*
		 * NO_ANSI
		 */
assignment_expression
	: conditional_expression
	| unary_expression
		{
		  if (POPA_P)
		    error_message (1034);
		  set_value (variable[set].name);
		  switch (type_com[set]->attribute.function_class)
		    {
		    case SIMPLE:
		    case ARRAY:
		    case STRUCT_FC:
		    case ENUM_FC:
		    case POINTER:
		    case UNION_FC:
		      break;
		    case LOCAL:
		    case REMOTE_F:
		      error_message (1034);
		      break;
		    default:
		      fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
		      error_message (5000); return (0);
		    }
		}
	  '='  assignment_expression 
		{
		  if (-1 == l_value_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  move2lvalue ();
		  SET_ADDRESS;
		}

	| unary_expression assignment_operator
	;

		/*
		 * NO_ANSI
		 */
ae_empty:
		{
				/* The lvalue just parsed is array,
				   structure or union. We need the
				   offset of the field twice. Once for
				   lvalue and MOV instruction and once
				   for right side value. (if there is
				   a side effect in lvalue expression
				   it is evaluated only once as the
				   semantic should be (ANSI)) */
		  GEN_MOVaa; GENCODE;
		} 

	;

assignment_operator
	: MUL_ASSIGN ae_empty assignment_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "*");
		  if (-1 == l_value_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  GEN_MULT;
		  GENCODE; kodp3 = kodp;
		  move2lvalue ();
		  SET_ADDRESS;
		}

	| DIV_ASSIGN ae_empty assignment_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "/");
		  if (-1 == l_value_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  GEN_DIV;
		  GENCODE; kodp3 = kodp;
		  move2lvalue ();
		  SET_ADDRESS;
		}

	| MOD_ASSIGN ae_empty assignment_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "%");
		  if (INTEGER == type_ac[set])
		    {
		      SET_ADDRESS;
		      TYPE_CLEAR;
		      switch (type_ac[set])
			{
			case INTEGER:
			  GEN_MOD;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		      GENCODE; kodp3 = kodp;
		      move2lvalue ();
		      SET_ADDRESS;
		    }
		  else
		    error_message (1005);
		}

	| ADD_ASSIGN ae_empty assignment_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    {
		      GEN_PUSHAIli(type_com[set]->output->attribute.memory_size);
		      GENCODE;
		      GEN_MULTli; GENCODE;
		      type_com[set - 1] = type_com[set];
		    }
		  else if (POINTER_P(type_com[set - 1]) ||
			   ARRAY_P(type_com[set - 1]))
		    {
		      GEN_PUSHAIli(type_com[set - 1]->output->attribute.memory_size);
		      GENCODE;
		      GEN_MULTli; GENCODE;
		      type_com[set] = type_com[set - 1];
		    }
		  if (-1 == l_value_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  GEN_ADD;
		  GENCODE; kodp3 = kodp;
		  move2lvalue ();
		  SET_ADDRESS;
		}

	| SUB_ASSIGN ae_empty assignment_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]))
		    {
		      GEN_PUSHAIli(type_com[set]->output->attribute.memory_size);
		      GENCODE;
		      GEN_MULTli; GENCODE;
		      type_com[set - 1] = type_com[set];
		    }
		  else if (POINTER_P(type_com[set - 1]) ||
			   ARRAY_P(type_com[set - 1]))
		    {
		      GEN_PUSHAIli(type_com[set - 1]->output->attribute.memory_size);
		      GENCODE;
		      GEN_MULTli; GENCODE;
		      type_com[set] = type_com[set - 1];
		    }
		  if (-1 == l_value_cast ())
		    COMPILE_ONLY;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		  GEN_SUB;
		  GENCODE; kodp3 = kodp;
		  move2lvalue ();
		  SET_ADDRESS;
		}

	| LEFT_ASSIGN ae_empty assignment_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "<<");
		  if (INTEGER == type_ac[set])
		    {
		      SET_ADDRESS;
		      TYPE_CLEAR;
		      switch (type_ac[set])
			{
			case INTEGER:
			  GEN_SAL;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		      GENCODE; kodp3 = kodp;
		      move2lvalue ();
		      SET_ADDRESS;
		    }
		  else
		    error_message (1005);
		}

	| RIGHT_ASSIGN ae_empty assignment_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, ">>");
		  if (INTEGER == type_ac[set])
		    {
		      SET_ADDRESS;
		      TYPE_CLEAR;
		      switch (type_ac[set])
			{
			case INTEGER:
			  GEN_SAR;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		      GENCODE; kodp3 = kodp;
		      move2lvalue ();
		      SET_ADDRESS;
		    }
		  else
		    error_message (1005);
		}

	| AND_ASSIGN ae_empty assignment_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "&");
		  ERROR_P;
		  if (INTEGER == type_ac[set])
		    {
		      SET_ADDRESS;
		      TYPE_CLEAR;
		      switch (type_ac[set])
			{
			case INTEGER:
			  GEN_ANDB;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		      GENCODE; kodp3 = kodp;
		      move2lvalue ();
		      SET_ADDRESS;
		    }
		  else
		    error_message (1005);
		}

	| XOR_ASSIGN ae_empty assignment_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "^");
		  ERROR_P;
		  if (INTEGER == type_ac[set])
		    {
		      SET_ADDRESS;
		      TYPE_CLEAR;
		      switch (type_ac[set])
			{
			case INTEGER:
			  GEN_XOR;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		      GENCODE; kodp3 = kodp;
		      move2lvalue ();
		      SET_ADDRESS;
		    }
		  else
		    error_message (1005);
		}

	| OR_ASSIGN ae_empty assignment_expression
		{
		  if (POINTER_P(type_com[set]) ||
		      ARRAY_P(type_com[set]) ||
		      POINTER_P(type_com[set - 1]) ||
		      ARRAY_P(type_com[set - 1]))
		    error_message (1033, "|");
		  ERROR_P;
		  if (INTEGER == type_ac[set])
		    {
		      SET_ADDRESS;
		      TYPE_CLEAR;
		      switch (type_ac[set])
			{
			case INTEGER:
			  GEN_ORB;
			  break;
			default:
			  fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
			  error_message (5000); return (0);
			}
		      GENCODE; kodp3 = kodp;
		      move2lvalue ();
		      SET_ADDRESS;
		    }
		  else
		    error_message (1005);
		}
	;


expression
	: assignment_expression
	| expression ',' 
		{
#if 0
		  /* Exact copy of the top level expression. Now it is
		     left-hand operand of comma expression for warning*/
		  if (! LOCAL_P(type_com[set]) &&
		      ! REMOTE_P(type_com[set]) &&
		      ! MOV_P && ! POPA_P)
		    error_message (6027);
#else
		  if (! MOV_P)
		    error_message (6029);
#endif		  
		  switch (type_ac[set])
		    {
		      /* No breaks here. */
		    case INTEGER:
		    case SIGNED_AC | INTEGER:
		    case UNSIGNED_AC | INTEGER:
		    case LONG_AC | INTEGER:
		    case LONG_AC | SIGNED_AC | INTEGER:
		    case LONG_AC | UNSIGNED_AC | INTEGER:
		    case SHORT_AC | INTEGER:
		    case SHORT_AC | SIGNED_AC | INTEGER:
		    case SHORT_AC | UNSIGNED_AC | INTEGER:
		    case DOUB:
		    case LONG_AC | DOUB:
		    case FLT:
		    case CHR:
		    case SIGNED_AC | CHR:
		    case UNSIGNED_AC | CHR:
		      GEN_POPAe; GENCODE;
		      break;
		    case VID:
		      break;
		    default:
		      fprintfx (stderr, "%s:%d:\n", __FILE__, __LINE__);
		      error_message (5000); return (0);
		    }
		  kodp3 = NULL;
		  is_address = 0;
		  SET_ADDRESS;
		  TYPE_CLEAR;
		}
	  assignment_expression
	;

constant_expression
	: conditional_expression
	;

/* \verbatim */

%%    
void
dump_yacc ()
{
#if YYDEBUG
  yydebug = 1;
#else
  fprintfx (stderr, "YYDEBUG not defined\n");
#endif
}
