/* $Id$ */ /* * (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 MODULE #endif %token STRING %token IDENT %token FBSYM %token CODE1 %token CODE2 %token CODE4 %token NUMBER0 /* keep NUMBER[0-4] in this order */ %token NUMBER1 %token NUMBER2 %token NUMBER3 %token NUMBER4 %token NUMBER8 %token NUMBERF %token DOT %token EXTERN %token DATA %token DATA8 %token DATAF %token ASCII %token SECTION %token COMMON %token BASE %token SYMB %token SYMD %token ALIGN %token ASSERT %token SPACE %token SEEK %token LINE %token FILe %token LIST %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 absexp optabs1 optabs2 %type expr %type 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 NUMBER8 ':' { 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 '#' NUMBER8 STRING '\n' { lineno = $3; /* long = int64_t */ 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)) | ((unsigned short)$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)) | ((unsigned short)$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; } | SEEK absexp { if (DOTSCT == NULL) nosect(); if ($2 < DOTVAL) serror("cannot move location counter backwards"); if (pass == PASS_1) DOTSCT->s_flag |= SOUGHT; DOTSCT->s_zero += $2 - DOTVAL; DOTVAL = $2; } | DATA datalist | DATA8 data8list | DATAF dataflist | 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)$0|MACHREL_BWR); #endif emitx($1.val, (int)$0); } | datalist ',' expr { #ifdef RELOCATION if (rflag != 0 && PASS_RELO) newrelo($3.typ, (int)$0|MACHREL_BWR); #endif emitx($3.val, (int)$0); } ; data8list : absexp { emit8($1);} | data8list ',' absexp { emit8($3);} ; numberf : NUMBERF { emitf((int)$-1, 0); } | '-' NUMBERF { emitf((int)$-1, 1); } ; dataflist : numberf | dataflist ',' numberf ; expr : error { serror("expr syntax err"); $$.val = 0; $$.typ = S_UND; } | NUMBER8 { $$.val = $1; /* valu_t = int64_t */ $$.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" %%