431 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			431 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
/* $Header$ */
 | 
						|
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
/* @(#)comm2.y	1.7 */
 | 
						|
 | 
						|
/*
 | 
						|
 * delay inclusion of machine dependent stuff (see comm0.h)
 | 
						|
 */
 | 
						|
#define	_include	#include
 | 
						|
 | 
						|
%{
 | 
						|
#include	"comm0.h"
 | 
						|
#include	"comm1.h"
 | 
						|
 | 
						|
static item_t	*last_it, *o_it;
 | 
						|
%}
 | 
						|
 | 
						|
/* ========== Machine independent Yacc definitions ========== */
 | 
						|
 | 
						|
%union {
 | 
						|
	word_t	y_word;
 | 
						|
	valu_t	y_valu;
 | 
						|
	expr_t	y_expr;
 | 
						|
	item_t	*y_item;
 | 
						|
#ifdef ASLD
 | 
						|
	char	*y_strp;
 | 
						|
#endif
 | 
						|
};
 | 
						|
 | 
						|
#ifdef ASLD
 | 
						|
%token <y_strp> MODULE
 | 
						|
#endif
 | 
						|
%token STRING
 | 
						|
%token <y_item> IDENT
 | 
						|
%token <y_item> FBSYM
 | 
						|
%token <y_valu> CODE1
 | 
						|
%token <y_valu> CODE2
 | 
						|
%token <y_valu> CODE4
 | 
						|
%token NUMBER0		/* keep NUMBER* in this order */
 | 
						|
%token NUMBER1
 | 
						|
%token NUMBER2
 | 
						|
%token NUMBER3
 | 
						|
%token <y_valu> NUMBER
 | 
						|
%token DOT
 | 
						|
%token EXTERN
 | 
						|
%token <y_word> DATA
 | 
						|
%token <y_word> ASCII
 | 
						|
%token SECTION
 | 
						|
%token COMMON
 | 
						|
%token BASE
 | 
						|
%token SYMB
 | 
						|
%token SYMD
 | 
						|
%token ALIGN
 | 
						|
%token ASSERT
 | 
						|
%token SPACE
 | 
						|
%token <y_word> LINE
 | 
						|
%token FILe
 | 
						|
%token <y_word> LIST
 | 
						|
%token OP_EQ
 | 
						|
%token OP_NE
 | 
						|
%token OP_LE
 | 
						|
%token OP_GE
 | 
						|
%token OP_LL
 | 
						|
%token OP_RR
 | 
						|
%token OP_OO
 | 
						|
%token OP_AA
 | 
						|
 | 
						|
%left OP_OO
 | 
						|
%left OP_AA
 | 
						|
%left '|'
 | 
						|
%left '^'
 | 
						|
%left '&'
 | 
						|
%left OP_EQ OP_NE
 | 
						|
%left '<' '>' OP_LE OP_GE
 | 
						|
%left OP_LL OP_RR
 | 
						|
%left '+' '-'
 | 
						|
%left '*' '/' '%' 
 | 
						|
%nonassoc '~'
 | 
						|
 | 
						|
%type <y_valu> absexp optabs1 optabs2
 | 
						|
%type <y_expr> expr
 | 
						|
%type <y_item> id_fb
 | 
						|
 | 
						|
/* ========== Machine dependent Yacc definitions ========== */
 | 
						|
 | 
						|
#include	"mach2.c"
 | 
						|
 | 
						|
%%
 | 
						|
 | 
						|
/* ========== Machine independent rules ========== */
 | 
						|
 | 
						|
#ifdef LISTING
 | 
						|
#define	LISTLINE(n)	if (listflag) listline(n); \
 | 
						|
			else if (listtemp) { listflag = listtemp; listeoln = 1; }
 | 
						|
#else
 | 
						|
#define	LISTLINE(n)	/* empty */
 | 
						|
#endif LISTING
 | 
						|
 | 
						|
#ifdef ASLD
 | 
						|
#define	RELODONE	/* empty */
 | 
						|
#else
 | 
						|
#define	RELODONE	assert(relonami == 0)
 | 
						|
#endif
 | 
						|
 | 
						|
program	:	/* empty */
 | 
						|
#ifdef ASLD
 | 
						|
	|	program MODULE /* not in PASS_1 */
 | 
						|
			{	newmodule($2);}
 | 
						|
#endif
 | 
						|
	|	program IDENT ':'
 | 
						|
			{	newident($2, DOTTYP); newlabel($2);}
 | 
						|
	|	program NUMBER ':'
 | 
						|
			{	if ($2 < 0 || $2 > 9) {
 | 
						|
					serror("bad f/b label");
 | 
						|
					$2 = 0;
 | 
						|
				}
 | 
						|
				newlabel(fb_shift((int)$2));
 | 
						|
			}
 | 
						|
	|	program CODE1
 | 
						|
			{	emit1((int)$2); LISTLINE(0);}
 | 
						|
	|	program CODE2
 | 
						|
			{	emit2((int)$2); LISTLINE(0);}
 | 
						|
	|	program CODE4
 | 
						|
			{	emit4((long)$2); LISTLINE(0);}
 | 
						|
	|	program operation ';'
 | 
						|
	|	program operation '\n'
 | 
						|
			{	lineno++; LISTLINE(1); RELODONE;}
 | 
						|
	|	program '#' NUMBER STRING '\n'
 | 
						|
			{	lineno = $3;
 | 
						|
				if (modulename) strncpy(modulename, stringbuf, STRINGMAX-1);
 | 
						|
				LISTLINE(1); RELODONE;
 | 
						|
			}
 | 
						|
	|	program error '\n'
 | 
						|
			{	serror("syntax error"); yyerrok;
 | 
						|
				lineno++; LISTLINE(1); RELODONE;
 | 
						|
			}
 | 
						|
	;
 | 
						|
#undef LISTLINE
 | 
						|
#undef RELODONE
 | 
						|
operation
 | 
						|
	:	/* empty */
 | 
						|
	|	IDENT '=' expr
 | 
						|
			{
 | 
						|
#ifdef LISTING
 | 
						|
				if (listflag & 1)
 | 
						|
					listcolm += printx(VALWIDTH, $3.val);
 | 
						|
#endif
 | 
						|
				newequate($1, $3.typ);
 | 
						|
				store($1, $3.val);
 | 
						|
			}
 | 
						|
#ifdef LISTING
 | 
						|
	|	LIST
 | 
						|
			{	if ($1)
 | 
						|
					listtemp = listmode;
 | 
						|
				else if ((dflag & 01000) == 0)
 | 
						|
					listtemp = 0;
 | 
						|
			}
 | 
						|
#endif
 | 
						|
	| 	SECTION IDENT
 | 
						|
			{	newsect($2);}
 | 
						|
	|	COMMON IDENT ',' absexp
 | 
						|
			{	newcomm($2, $4);}
 | 
						|
	|	BASE absexp
 | 
						|
			{	if (pass == PASS_1) newbase($2);}
 | 
						|
	|	ASSERT expr
 | 
						|
			{	if ($2.val == 0 && pass == PASS_3)
 | 
						|
					warning("assertion failed");
 | 
						|
			}
 | 
						|
	|	SYMB STRING ',' expr	{ o_it = last_it; }
 | 
						|
		optabs2 optabs2
 | 
						|
			{	if ((sflag & SYM_SMB) && PASS_SYMB) {
 | 
						|
#ifndef ASLD
 | 
						|
					if (
 | 
						|
						pass == PASS_3
 | 
						|
						&&
 | 
						|
						($4.typ & S_TYP) == S_UND
 | 
						|
					   ) {
 | 
						|
						serror("expression undefined");
 | 
						|
						relonami = -1;
 | 
						|
					}
 | 
						|
					if (
 | 
						|
						PASS_SYMB
 | 
						|
						&&
 | 
						|
						($4.typ & S_COM)
 | 
						|
					   ) {
 | 
						|
						/* No value is known at
 | 
						|
						   assembler time.
 | 
						|
						   Generate reference to other
 | 
						|
						   entry in name table
 | 
						|
						*/
 | 
						|
						$4.typ = S_CRS;
 | 
						|
						$4.val = new_string(o_it->i_name);
 | 
						|
						relonami = 0;
 | 
						|
					}
 | 
						|
#endif
 | 
						|
					    
 | 
						|
					newsymb(
 | 
						|
						*stringbuf ? stringbuf : (char *) 0,
 | 
						|
						(short)(
 | 
						|
							($4.typ & (S_EXT|S_TYP))
 | 
						|
							|
 | 
						|
							((ushort)$6<<8)
 | 
						|
						),
 | 
						|
						(short)$7,
 | 
						|
						$4.val
 | 
						|
					);
 | 
						|
				}
 | 
						|
			}
 | 
						|
	|	SYMD STRING ','  absexp ',' absexp
 | 
						|
			{	if ((sflag & SYM_SMB) && PASS_SYMB) {
 | 
						|
					newsymb(
 | 
						|
						*stringbuf ? stringbuf : (char *) 0,
 | 
						|
						(short)(
 | 
						|
							(DOTTYP & (S_EXT|S_TYP))
 | 
						|
							|
 | 
						|
							((ushort)$4<<8)
 | 
						|
						),
 | 
						|
						(short)$6,
 | 
						|
						(valu_t)DOTVAL
 | 
						|
					);
 | 
						|
				}
 | 
						|
			}
 | 
						|
	|	LINE optabs1
 | 
						|
			{	if ((sflag & SYM_LIN) && PASS_SYMB) {
 | 
						|
					if ($2)
 | 
						|
						hllino = (short)$2;
 | 
						|
					else
 | 
						|
						hllino++;
 | 
						|
					newsymb(
 | 
						|
						(char *)0,
 | 
						|
						(DOTTYP | S_LIN),
 | 
						|
						hllino,
 | 
						|
						(valu_t)DOTVAL
 | 
						|
					);
 | 
						|
				}
 | 
						|
			}
 | 
						|
	|	FILe STRING
 | 
						|
			{	if ((sflag & SYM_LIN) && PASS_SYMB) {
 | 
						|
					hllino = 0;
 | 
						|
					newsymb(
 | 
						|
						stringbuf,
 | 
						|
						(DOTTYP | S_FIL),
 | 
						|
						0,
 | 
						|
						(valu_t)DOTVAL
 | 
						|
					);
 | 
						|
				}
 | 
						|
			}
 | 
						|
	|	EXTERN externlist
 | 
						|
	|	ALIGN optabs1
 | 
						|
			{	align($2);}
 | 
						|
	|	SPACE absexp
 | 
						|
			{	if (DOTSCT == NULL)
 | 
						|
					nosect();
 | 
						|
				DOTVAL += $2;
 | 
						|
				DOTSCT->s_zero += $2;
 | 
						|
			}
 | 
						|
	|	DATA datalist
 | 
						|
	|	ASCII STRING
 | 
						|
			{	emitstr($1);}
 | 
						|
	;
 | 
						|
externlist
 | 
						|
	:	IDENT
 | 
						|
			{	$1->i_type |= S_EXT;}
 | 
						|
	|	externlist ',' IDENT
 | 
						|
			{	$3->i_type |= S_EXT;}
 | 
						|
	;
 | 
						|
datalist
 | 
						|
	:	expr
 | 
						|
			{
 | 
						|
#ifdef RELOCATION
 | 
						|
				if (rflag != 0 && PASS_RELO)
 | 
						|
					newrelo($1.typ, (int)$<y_word>0|MACHREL_BWR);
 | 
						|
#endif
 | 
						|
				emitx($1.val, (int)$<y_word>0);
 | 
						|
			}
 | 
						|
	|	datalist ',' expr
 | 
						|
			{
 | 
						|
#ifdef RELOCATION
 | 
						|
				if (rflag != 0 && PASS_RELO)
 | 
						|
					newrelo($3.typ, (int)$<y_word>0|MACHREL_BWR);
 | 
						|
#endif
 | 
						|
				emitx($3.val, (int)$<y_word>0);
 | 
						|
			}
 | 
						|
	;
 | 
						|
expr	:	error
 | 
						|
			{	serror("expr syntax err");
 | 
						|
				$$.val = 0; $$.typ = S_UND;
 | 
						|
			}
 | 
						|
	|	NUMBER
 | 
						|
			{	$$.val = $1; $$.typ = S_ABS;}
 | 
						|
	|	id_fb
 | 
						|
			{	$$.val = load($1); 
 | 
						|
				last_it = $1;
 | 
						|
				$$.typ = $1->i_type & ~S_EXT;
 | 
						|
			}
 | 
						|
	|	STRING
 | 
						|
			{	if (stringlen != 1)
 | 
						|
					serror("too many chars");
 | 
						|
				$$.val = stringbuf[0];
 | 
						|
				$$.typ = S_ABS;
 | 
						|
			}
 | 
						|
	|	ASC_LPAR expr ASC_RPAR
 | 
						|
			{	$$ = $2;}
 | 
						|
	|	expr OP_OO expr
 | 
						|
			{	$$.val = ($1.val || $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, 0);
 | 
						|
			}
 | 
						|
	|	expr OP_AA expr
 | 
						|
			{	$$.val = ($1.val && $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, 0);
 | 
						|
			}
 | 
						|
	|	expr '|' expr
 | 
						|
			{	$$.val = ($1.val | $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, 0);
 | 
						|
			}
 | 
						|
	|	expr '^' expr
 | 
						|
			{	$$.val = ($1.val ^ $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, 0);
 | 
						|
			}
 | 
						|
	|	expr '&' expr
 | 
						|
			{	$$.val = ($1.val & $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, 0);
 | 
						|
			}
 | 
						|
	|	expr OP_EQ expr
 | 
						|
			{	$$.val = ($1.val == $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, '>');
 | 
						|
			}
 | 
						|
	|	expr OP_NE expr
 | 
						|
			{	$$.val = ($1.val != $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, '>');
 | 
						|
			}
 | 
						|
	|	expr '<' expr
 | 
						|
			{	$$.val = ($1.val < $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, '>');
 | 
						|
			}
 | 
						|
	|	expr '>' expr
 | 
						|
			{	$$.val = ($1.val > $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, '>');
 | 
						|
			}
 | 
						|
	|	expr OP_LE expr
 | 
						|
			{	$$.val = ($1.val <= $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, '>');
 | 
						|
			}
 | 
						|
	|	expr OP_GE expr
 | 
						|
			{	$$.val = ($1.val >= $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, '>');
 | 
						|
			}
 | 
						|
	|	expr OP_RR expr
 | 
						|
			{	$$.val = ($1.val >> $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, 0);
 | 
						|
			}
 | 
						|
	|	expr OP_LL expr
 | 
						|
			{	$$.val = ($1.val << $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, 0);
 | 
						|
			}
 | 
						|
	|	expr '+' expr
 | 
						|
			{	$$.val = ($1.val + $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, '+');
 | 
						|
			}
 | 
						|
	|	expr '-' expr
 | 
						|
			{	$$.val = ($1.val - $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, '-');
 | 
						|
			}
 | 
						|
	|	expr '*' expr
 | 
						|
			{	$$.val = ($1.val * $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, 0);
 | 
						|
			}
 | 
						|
	|	expr '/' expr
 | 
						|
			{	if ($3.val == 0) {
 | 
						|
					if (pass == PASS_3)
 | 
						|
						serror("divide by zero");
 | 
						|
					$$.val = 0;
 | 
						|
				} else
 | 
						|
					$$.val = ($1.val / $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, 0);
 | 
						|
			}
 | 
						|
	|	expr '%' expr
 | 
						|
			{	if ($3.val == 0) {
 | 
						|
					if (pass == PASS_3)
 | 
						|
						serror("divide by zero");
 | 
						|
					$$.val = 0;
 | 
						|
				} else
 | 
						|
					$$.val = ($1.val % $3.val);
 | 
						|
				$$.typ = combine($1.typ, $3.typ, 0);
 | 
						|
			}
 | 
						|
	|	'+' expr %prec '*'
 | 
						|
			{	$$.val = $2.val;
 | 
						|
				$$.typ = combine(S_ABS, $2.typ, 0);
 | 
						|
			}
 | 
						|
	|	'-' expr %prec '*'
 | 
						|
			{	$$.val = -$2.val;
 | 
						|
				$$.typ = combine(S_ABS, $2.typ, 0);
 | 
						|
			}
 | 
						|
	|	'~' expr
 | 
						|
			{	$$.val = ~$2.val;
 | 
						|
				$$.typ = combine(S_ABS, $2.typ, 0);
 | 
						|
			}
 | 
						|
	|	DOT
 | 
						|
			{	$$.val = DOTVAL;
 | 
						|
				$$.typ = DOTTYP|S_DOT;
 | 
						|
			}
 | 
						|
	;
 | 
						|
id_fb	:	IDENT
 | 
						|
	|	FBSYM
 | 
						|
	;
 | 
						|
absexp	:	expr
 | 
						|
			{	if (($1.typ & ~S_EXT) != S_ABS)
 | 
						|
					serror("must be absolute");
 | 
						|
				$$ = $1.val;
 | 
						|
			}
 | 
						|
	;
 | 
						|
optabs1
 | 
						|
	:	/* empty */
 | 
						|
			{	$$ = 0;}
 | 
						|
	|	absexp
 | 
						|
			{	$$ = $1;}
 | 
						|
	;
 | 
						|
optabs2
 | 
						|
	:	/* empty */
 | 
						|
			{	$$ = 0;}
 | 
						|
	|	',' absexp
 | 
						|
			{	$$ = $2;}
 | 
						|
	;
 | 
						|
 | 
						|
/* ========== Machine dependent rules ========== */
 | 
						|
 | 
						|
#include	"mach4.c"
 | 
						|
 | 
						|
%%
 |