
/* 
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/
%term NAME  2
%term STRING  3
%term ICON  4
%term FCON  5
%term PLUS   6
%term MINUS   8
%term MUL   11
%term AND   14
%term OR   17
%term ER   19
%term QUEST  21
%term COLON  22
%term ANDAND  23
%term OROR  24

/*	special interfaces for yacc alone */
/*	These serve as abbreviations of 2 or more ops:
	ASOP	=, = ops
	RELOP	LE,LT,GE,GT
	EQUOP	EQ,NE
	DIVOP	DIV,MOD
	SHIFTOP	LS,RS
	ICOP	ICR,DECR
	UNOP	NOT,COMPL
	STROP	DOT,STREF

	*/
%term ASOP  25
%term RELOP  26
%term EQUOP  27
%term DIVOP  28
%term SHIFTOP  29
%term INCOP  30
%term UNOP  31
%term STROP  32

/*	reserved words, etc */
%term TYPE  33
%term CLASS  34
%term STRUCT  35
%term RETURN  36
%term GOTO  37
%term IF  38
%term ELSE  39
%term SWITCH  40
%term BREAK  41
%term CONTINUE  42
%term WHILE  43
%term DO  44
%term FOR  45
%term DEFAULT  46
%term CASE  47
%term SIZEOF  48
%term ENUM 49

/*	little symbols, etc. */
/*	namely,

	LP	(
	RP	)

	LC	{
	RC	}

	LB	[
	RB	]

	CM	,
	SM	;

	*/

%term LP  50
%term RP  51
%term LC  52
%term RC  53
%term LB  54
%term RB  55
%term CM  56
%term SM  57
%term ASSIGN  58
%term ASM 59

/* at last count, there were 7 shift/reduce, 1 reduce/reduce conflicts
/* these involved:
	if/else
	recognizing functions in various contexts, including declarations
	error recovery
	*/

%left CM
%right ASOP ASSIGN
%right QUEST COLON
%left OROR
%left ANDAND
%left OR
%left ER
%left AND
%left EQUOP
%left RELOP
%left SHIFTOP
%left PLUS MINUS
%left MUL DIVOP
%right UNOP
%right INCOP SIZEOF
%left LB LP STROP
%{
#include "xs.h"
#include "names.h"
#include "stack.h"
#include "types.h"
#include "anal.h"
#include "mfile1.h"
#include "args.h"
#include "body.h"
#include "sizeof.h"
#include "init.h"
#include "string.h"
#include "xdefs.h"
extern char *gettxt();
%}

	/* define types */
%start ext_def_list

%type <node> e term attributes oattributes type enum_dcl struct_dcl
		cast_type null_decl funct_idn declarator fdeclarator
		nfdeclarator elist enum_head str_head name_lp
		declarator_list con_e class type moe_list
		optcomma moe type_dcl_list optsemi type_declaration
		declarator_list dcl_stat_list type_list template ellipsis
		basic_type derived_type opt_type_list begin

%token <node> CLASS NAME STRUCT RELOP CM DIVOP PLUS MINUS SHIFTOP MUL AND OR
		ER ANDAND OROR ASSIGN STROP INCOP UNOP ICON COLON EQUOP
		QUEST ASOP FCON STRING SIZEOF
%token <node> TYPE LC RC LP RP ENUM SM LB RB

%%

%{
%}

ext_def_list:	   ext_def_list external_def
		|	/* EMPTY */
		;
external_def:	   data_def
		|  error
			{ uerror(gettxt("xs:80","syntax error in external definition")); }
		|  ASM SM
		;
data_def:	   oattributes  SM
		|  oattributes init_dcl_list  SM
		|  oattributes fdeclarator
			{ func_def($2);types_push();repl_push(); do_main($2); }
		        function_body
			{ do_function(); types_pop();repl_pop(); }
		;

function_body:	   arg_dcl_list { args_def(); } compoundstmt
		;

arg_dcl_list:	   arg_dcl_list attributes declarator_list SM
			{ args_decl($2, $3); }
		|  arg_dcl_list attributes SM
			/* to permit structs in decl. lists */
		|  /* EMPTY */
		;


type_list:      template CM type_list
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  template
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			}
		|  template ellipsis
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  ellipsis
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			}
		;
template:	basic_type derived_type
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		;

basic_type:	TYPE
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			}
		|  TYPE TYPE
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  TYPE TYPE TYPE
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  STRUCT NAME
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			  no_type = FALSE;
			}
		|  ENUM NAME
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			  no_type = FALSE;
			}
		;

derived_type:	/*VOID*/
			{ if (is_init){
				$$.t_len = 0;
			  }
			}
		|  derived_type LB RB
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  derived_type LB ICON RB
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
					   $4.t_len;
			  }
			}
		|  derived_type LP opt_type_list RP
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
					$4.t_len;
			  }
			}
		|  MUL derived_type
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  LP derived_type RP
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		;
ellipsis:	STROP STROP STROP
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		;

stmt_list:	   stmt_list statement
		|  /* EMPTY */
		;

dcl_stat_list	:  dcl_stat_list attributes SM
			{ $$ = $3; }
		|  dcl_stat_list attributes init_dcl_list SM
			{ $$ = $4; }
		|  /* EMPTY */
			{ $$ = NIL; }
		;

oattributes:	  attributes
			{ $$ = $1; }
		|  /* empty */ 
			{ $$ = NIL; curattr = def_attr(); }
		;
attributes:	   class type
			{  $$ = attr_ct($1, $2); curattr = $$; 
			   no_type = is_typedef;
			}
		|  type class
			{ $$ = attr_ct($2, $1); curattr = $$; 
			  no_type = is_typedef;
			}
		|  class
			{ $$ = attr_c($1); curattr = $$; 
			  no_type = is_typedef;
			}
		|  type
			{ $$ = attr_t($1); curattr = $$; 
			  no_type = is_typedef;
			}
 		|  type class type
 			{ $$ = attr_tct($1, $2, $3); curattr = $$; 
			  no_type = is_typedef;
			}
		;

class:		  CLASS
			{ $$ = $1; }
		;

type:		   TYPE
			{ $$ = $1; }
		|  TYPE TYPE
			{ $$ = is_char($1) ? $1 : $2;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  TYPE TYPE TYPE
			{ $$ = is_char($1) ? $1 : is_char($2) ? $2 : $3;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  struct_dcl
			{ $$ = $1; }
		|  enum_dcl
			{ $$ = enum_type();
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			}
		;
enum_dcl:	   enum_head LC moe_list optcomma RC
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len + $5.t_len;
			  }
			}
		|  ENUM NAME
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			  no_type = FALSE;
			}
		;

enum_head:	   ENUM
			{ if(is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			  no_type = FALSE;
			}
		|  ENUM NAME
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			  no_type = FALSE;
			}
		;

moe_list:	   moe
			{ if(is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			}
		|  moe_list CM moe
			{ if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		;

moe:		   NAME
			{ moe_dcl($1);
			  if(is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			}
		|  NAME ASSIGN con_e
			{ moe_dcl($1);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		;

struct_dcl:	   str_head LC type_dcl_list optsemi RC
			{ $$ = struct_def($1, $3);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len + $5.t_len;
			  }
			}
		|  STRUCT NAME
			{  $$ = struct_decl($1, $2);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			  no_type = FALSE;
			}
		;

str_head:	   STRUCT
			{ $$ = struct_head($1, NIL);
			  if(is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			  no_type = FALSE;
			}
		|  STRUCT NAME
			{  $$ = struct_head($1, $2);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			  no_type = FALSE;
			}
		;

type_dcl_list:	   type_declaration
			{ $$ = $1; }
		|  type_dcl_list SM type_declaration
			{ $$ = tdl_append($1, $3);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		;

type_declaration:  type { TYPEP tptr; curattr.t_type = typ_attr;
			  at_ty_new(typ_attr, $1.t_type);
			}
			 declarator_list
			{ $$ = tdl_create($1, $3);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $3.t_len;
			  }
			}
		|  type
			{ $$ = NIL;
			  if(is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			}
		;

declarator_list:   declarator
			{ $$ = delist_decl($1);
			  if(is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			}
		|  declarator_list  CM declarator
			{ $$ = delist_append($1, $3);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		;

declarator:	   nfdeclarator
			{ is_index = FALSE; $$ = $1;
			  if(is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			  no_type = is_typedef = FALSE;
			}
		|  nfdeclarator COLON { is_index = FALSE; } con_e %prec CM
			{ $$ = $1;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $4.t_len;
			  }
			  no_type = is_typedef = FALSE;
			}
		|  COLON con_e
			%prec CM
			{ $$ = decl_fake(); is_index = FALSE;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			  no_type = is_typedef = FALSE;
			}
		|  error
			{ uerror(gettxt("xs:81","syntax error in declarator")); $$ = NIL; 
			  no_type = is_typedef = FALSE;
			}
		;

		/* int (a)();   is not a function --- sorry! */
nfdeclarator:	   MUL nfdeclarator		
			{  $$ = decl_ptr($2) ;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  nfdeclarator  LP opt_type_list RP
			{ $$ = decl_fct($1);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
					$4.t_len;
			  }
			}
		|  nfdeclarator LB RB	
			{ int aux = $1.t_len + $2.t_len + $3.t_len; 
			  $$ = decl_usize($1, aux);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = aux;
			  }
			}
		|  nfdeclarator LB con_e RB
			{ $$ = decl_size($1, $3.t_val);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						$4.t_len;
			  }
			}
		|  NAME  		
			{ is_index = TRUE; $$ = decl_name($1);
			  if(is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			  no_type = is_typedef = FALSE;
			}
		|   LP  nfdeclarator  RP 		
			{ $$ = $2;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		;
fdeclarator:	   MUL fdeclarator
			{ $$ = decl_ptr($2);}
		|  fdeclarator  LP   RP
			{ $$ = decl_fct($1); }
		|  fdeclarator LB RB
			{ $$ = decl_usize($1, $1.t_len + $2.t_len + $3.t_len); }
		|  fdeclarator LB con_e RB
			{ $$ = decl_size($1, 0); }
		|   LP  fdeclarator  RP
			{ $$ = $2; }
		|  name_lp name_list  RP
			{ $$ = $1; }
		|  name_lp opt_type_list RP
			{ $$ = $1; args_free(); }
		;

opt_type_list:	type_list
			{ $$ = $1; }
		|	/*VOID*/
			{ $$ = NIL; }
		;

name_lp:	  NAME LP
			{ $$ = decl_fname($1, $2); 
			  no_type = is_typedef = FALSE;
			}
		;

name_list:	   NAME			
			{ args_add($1); }
		|  name_list  CM  NAME 
			{ args_add($3); }
		| error
			{ uerror(gettxt("xs:82","syntax error in name list")); }
		;
		/* always preceeded by attributes */
init_dcl_list:	   init_declarator
			%prec CM
		|  init_dcl_list  CM init_declarator
		;
		/* always preceeded by attributes */
xnfdeclarator:	   nfdeclarator
			{ TYPEP aux; aux = ident_nf($1); is_index = FALSE; 
			  init_start(aux); }
		|  error
			{ uerror(gettxt("xs:83","syntax error in initialized declarator"));
                          do_init = FALSE;}
		;
		/* always preceeded by attributes */
init_declarator:   nfdeclarator
			{ is_index = FALSE; ident_nf($1); }
		|  fdeclarator
			{ args_free(); ident_f($1); }
		|  xnfdeclarator ASSIGN e
			%prec CM
			{  init_expr($3); init_end(); }
		|  xnfdeclarator ASSIGN LC init_list 
			optcomma RC
			{ init_end(); }
		| error
			{ uerror(gettxt("xs:84","syntax error in init declarator(2)\n"));}
		;

init_list:	   initializer
			%prec CM
		|  init_list  CM  initializer
		;
initializer:	   e
			%prec CM
			{  init_expr($1); }
		|  ibrace init_list optcomma RC
			{  init_rbrace(); }
		;

optcomma	:	/* empty */
			{ $$ = NIL; }
		|  CM
			{ $$ = $1; }
		;

optsemi		:	/* empty */
			{ $$ = NIL; }
		|  SM
			{ $$ = $1; }
		;

ibrace		: LC
			{  init_lbrace(); }
		;

/*	STATEMENTS	*/

compoundstmt:	   begin dcl_stat_list stmt_list RC
			{ do_body($1, $2); repl_pop(); types_pop(); }
		;

begin:		  LC
			{ do_main2($1); types_push(); repl_push(); }
		;

statement:	   simplestmt
		|  compoundstmt
		|  SM
		|  label statement

simplestmt:	e SM
		|  ASM SM
		|  ifprefix statement
		|  ifelprefix statement
		|  WHILE LP e RP statement
		|  doprefix statement WHILE  LP  e  RP   SM
		|  FOR LP .e SM .e SM .e RP statement
		|  switchpart statement
		|  BREAK  SM
		|  CONTINUE  SM
		|  RETURN  SM
		|  RETURN e  SM
		|  GOTO NAME SM
		|  error  SM
		   { uerror(gettxt("xs:85","syntax error ';'")); }
		|  error RC
		   { uerror(gettxt("xs:86","syntax error '}'")); }
		;
label:		   NAME COLON
		|  CASE e COLON
		|  DEFAULT COLON
		;
doprefix:	DO
		;
ifprefix:	IF LP e RP
		;
ifelprefix:	  ifprefix statement ELSE
		;

switchpart:	   SWITCH  LP  e  RP
		;
/*	EXPRESSIONS	*/
con_e:		   e %prec CM
			{ $$ = $1; }
		;
.e:		   e
		|
		;
elist:		   e %prec CM
			{ $$ = $1; }
		|  elist  CM  e
			{ $$ = $1;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		;

e:		   e RELOP e
			{ $$.t_val = is_index ?
				expr_relop($2.t_val, $1.t_val, $3.t_val) : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e CM e
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
			 	$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e DIVOP e
			{ $$.t_val = is_index ? 
				expr_divop($2.t_val, $1.t_val, $3.t_val) : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e PLUS e
			{ $$.t_val = is_index ? $1.t_val + $3.t_val : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e MINUS e
			{ $$.t_val = is_index ?	$1.t_val - $3.t_val : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e SHIFTOP e
			{ $$.t_val = is_index ?
				expr_shiftop($2.t_val, $1.t_val, $3.t_val) : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e MUL e
			{ $$.t_val = is_index ? $1.t_val * $3.t_val : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e EQUOP  e
			{ $$.t_val = is_index ?
				expr_equop($2.t_val, $1.t_val, $3.t_val) : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e AND e
			{ $$.t_val = is_index ?	$1.t_val & $3.t_val : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e OR e
			{ $$.t_val = is_index ?	$1.t_val | $3.t_val : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e ER e
			{ $$.t_val = is_index ?	$1.t_val ^ $3.t_val : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e ANDAND e
			{ $$.t_val = is_index ?	$1.t_val && $3.t_val : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e OROR e
			{ $$.t_val = is_index ?	$1.t_val || $3.t_val : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e MUL ASSIGN e
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			  }
			}
		|  e DIVOP ASSIGN e
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			  }
			}
		|  e PLUS ASSIGN e
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			  }
			}
		|  e MINUS ASSIGN e
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			  }
			}
		|  e SHIFTOP ASSIGN e
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			  }
			}
		|  e AND ASSIGN e
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			  }
			}
		|  e OR ASSIGN e
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			  }
			}
		|  e ER ASSIGN e
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			  }
			}
		|  e QUEST e COLON e
			{ $$.t_val = is_index ?
				($1.t_val ? $3.t_val :$5.t_val) : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len + $5.t_len;
			  }
			}
		|  e ASOP e
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  e ASSIGN e
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  term
			{ $$ = $1; }
		;

term:		   term INCOP
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  MUL term
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  AND term
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  MINUS term
			{ $$.t_val = is_index ? (-$2.t_val) : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  UNOP term
			{ $$.t_val = is_index ?
				expr_unop($1.t_val, $2.t_val): 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  INCOP term
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  SIZEOF term
			{ $$.t_val = 0;
			  do_sizeof($1, $2);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  LP cast_type RP term  %prec INCOP
			{ $$.t_val = is_index ? $4.t_val : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			  }
			}
		|  SIZEOF LP cast_type RP %prec SIZEOF
			{ $$.t_val = 0;
			  is_sizeof = FALSE;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			  }
			}
		|  term LB e RB
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			  }
			}
		|  term LB e COLON e RB
                       { $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len + $5.t_len;
			  }
			}
		|  funct_idn  RP
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		|  funct_idn elist  RP
			{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  term STROP NAME
		    	{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  term STROP TYPE
		    	{ $$.t_val = 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		|  NAME
			{ use_name($1);
			  $$.t_val = 0;
			  if (is_init || is_sizeof){
				if (is_init)
					init_name($1);
			  	if (is_sizeof)
					sizeof_check($1);
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			}
		|  ICON
			{ $$.t_val = is_index ? lastcon : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			}
		|  FCON
			{ $$.t_val = is_index ? (int)dcon : 0;
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
			  }
			}
		|  STRING
			{  $$.t_val = 0;
			   if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len;
				init_string($1);
			   } else
				stmt_string($1);
			}
		|   LP  e  RP
			{ $$.t_val = $2.t_val;
			  if (is_init || is_sizeof){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			  }
			}
		;

cast_type:	  type null_decl
			{
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			  }
			}
		;

null_decl:	   /* EMPTY */
			{
			  if (is_init)
				$$.t_len = 0;
			}
		|  LP RP
			{
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			 }
			}
		|  LP null_decl RP LP RP
			{
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len + $5.t_len;
			 }
			}
		|  MUL null_decl
			{
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			 }
			}
		|  null_decl LB RB
			{
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			 }
			}
		|  null_decl LB con_e RB
			{
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len +
						 $4.t_len;
			 }
			}
		|  LP null_decl RP
			{
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len + $3.t_len;
			 }
			}
		;

funct_idn:	   NAME  LP 
			{ use_func($1);
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			 }
			}
		|  term  LP 
			{
			  if (is_init){
				$$.t_off = $1.t_off;
				$$.t_len = $1.t_len + $2.t_len;
			 }
			}
		;
%%
#ident "$Header: cgram.y 1.1 90/01/19 $@(#)cgram.y	1.1 89/12/01"
