home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
messroms.de
/
2007-01-13_www.messroms.de.zip
/
CGENIE
/
TOOLS
/
AZ80.ZIP
/
az80.y
< prev
next >
Wrap
Text File
|
1999-12-09
|
22KB
|
1,050 lines
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define CGENIE 1
#if CGENIE
#define TAPE_EXT ".cas"
#else
#define TAPE_EXT ".vz"
#endif
typedef unsigned char byte;
typedef unsigned short word;
typedef struct tagSYM {
struct tagSYM * next;
int pass_no;
int value;
int refs;
int * line_no;
char * name;
} SYM;
void emit(void);
void addsym(char * name, int value);
int getsym(char * name);
int symb_no = 0;
int line_no = 1;
int pass_no = 1;
byte pre = 0x00;
byte xcb = 0x00;
byte cmd = 0x00;
int ofs = 0x00;
byte arg[4096] = {0, };
int expflg = 0;
int cmdflg = 0;
int ofsflg = 0;
int argcnt = 0;
word exp = 0;
word PC = 0;
word end = 0;
char lstbuff[256+1] = "";
char *plst = NULL;
SYM *sym = NULL;
SYM *sym0 = NULL;
char inpname[256+1] = "";
char outname[256+1] = "";
char lstname[256+1] = "";
FILE *inpfile = NULL;
FILE *outfile = NULL;
FILE *lstfile = NULL;
int f_list = 0;
int f_tape = 0;
int f_syms = 0;
int f_xref = 0;
int f_first = 0;
char tape_name[6+1];
byte tape_buf[256];
byte tape_crc = 0;
byte tape_cnt = 0;
word tape_adr = 0;
word tape_pc = 0;
%}
%start file
%union {
int i;
char* s;
}
%token EOL,COMMA,COLON,LPAREN,RPAREN,PLUS,MINUS,MUL,DIV,SHL,SHR,AND,OR,XOR,NOT
%token _B,_C,_D,_E,_H,_L,_M,_A,_F,_I,_R
%token _BC,_DE,_HL,_AF,_SP,_IX,_IY
%token _cNZ,_cZ,_cNC,_cC,_cPO,_cPE,_cP,_cM
%token _PORTC
%token <i> _MX,_MY
%token <i> _VAL
%token <s> _SYM
%token <s> _STR
%token _ADC,_ADD,_AND
%token _BIT
%token _CALL,_CCF,_CP,_CPD,_CPDR,_CPI,_CPIR,_CPL
%token _DAA,_DEC,_DI,_DJNZ
%token _EI,_EX,_EXX
%token _HALT
%token _IM,_IN,_INC,_IND,_INDR,_INI,_INIR
%token _JP,_JR
%token _LD,_LDD,_LDDR,_LDI,_LDIR
%token _NEG,_NOP
%token _OR,_OTDR,_OTIR,_OUT,_OUTD,_OUTI
%token _POP,_PUSH
%token _RES,_RET,_RETI,_RETN,_RL,_RLA,_RLC,_RLCA,_RLD,_RR,_RRA,_RRC,_RRCA,_RRD,_RST
%token _SBC,_SCF,_SET,_SLA,_SLL,_SRA,_SRL,_SUB
%token _XOR
%token _DEFB,_DEFL,_DEFM,_DEFS,_DEFW,_END,_EQU,_ORG
%type <i> expr,simple,term,factor
%%
file : line
| line error
;
line : line token { emit(); }
| token { emit(); }
;
token : EOL
{ cmdflg = 0; }
| _SYM
{ cmdflg = 0; addsym($1, PC); free($1); }
| _SYM COLON
{ cmdflg = 0; addsym($1, PC); free($1); }
| _SYM _EQU i16 EOL
{
cmdflg = 0;
argcnt = 0;
exp = *(word*)arg;
expflg = 1;
addsym($1,exp);
free($1);
}
| _SYM _DEFL i16 EOL
{
cmdflg = 0;
argcnt = 0;
expflg = 1;
exp = *(word*)arg;
addsym($1, exp);
free($1);
}
| _ADC _A COMMA s08 EOL
{ cmd |= 0x88; }
| _ADC _A COMMA i08 EOL
{ cmd = 0xCE; }
| _ADC _HL COMMA r16 EOL
{ pre = 0xED; cmd |= 0x4A; }
| _ADD _A COMMA s08 EOL
{ cmd |= 0x80; }
| _ADD _A COMMA i08 EOL
{ cmd = 0xC6; }
| _ADD _HL COMMA r16 EOL
{ cmd |= 0x09; }
| _ADD _IX COMMA r16x EOL
{ pre = 0xDD; cmd |= 0x09; }
| _ADD _IY COMMA r16y EOL
{ pre = 0xFD; cmd |= 0x09; }
| _AND s08 EOL
{ cmd |= 0xA0; }
| _AND i08 EOL
{ cmd = 0xE6; }
| _BIT bit COMMA s08 EOL
{ xcb = 0xCB; cmd |= 0x40; }
| _CALL i16 EOL
{ cmd = 0xCD; }
| _CALL cond COMMA i16 EOL
{ cmd |= 0xC4; }
| _CCF EOL
{ cmd = 0x3F; }
| _CP s08 EOL
{ cmd |= 0xB8; }
| _CP i08 EOL
{ cmd = 0xFE; }
| _CPD EOL
{ pre = 0xED; cmd = 0xA9; }
| _CPDR EOL
{ pre = 0xED; cmd = 0xB9; }
| _CPI EOL
{ pre = 0xED; cmd = 0xA1; }
| _CPIR EOL
{ pre = 0xED; cmd = 0xB1; }
| _CPL EOL
{ cmd = 0x2F; }
| _DAA EOL
{ cmd = 0x27; }
| _DEC s08 EOL
{ cmd = (cmd << 3) | 0x05; }
| _DEC r16xy EOL
{ cmd |= 0x0B; }
| _DI EOL
{ cmd = 0xF3; }
| _DJNZ ofs8 EOL
{ cmd = 0x10; }
| _EI EOL
{ cmd = 0xFB; }
| _EX _AF COMMA _AF EOL
{ cmd = 0x08; }
| _EX _DE COMMA _HL EOL
{ cmd = 0xEB; }
| _EX LPAREN _SP RPAREN COMMA _HL EOL
{ cmd = 0xE3; }
| _EX LPAREN _SP RPAREN COMMA _IX EOL
{ pre = 0xDD; cmd = 0xE3; }
| _EX LPAREN _SP RPAREN COMMA _IY EOL
{ pre = 0xFD; cmd = 0xE3; }
| _EXX EOL
{ cmd = 0xD9; }
| _HALT EOL
{ cmd = 0x76; }
| _IM imode EOL
{ pre = 0xED; cmd |= 0x56 }
| _IN LPAREN i08 RPAREN EOL
{ cmd = 0xDB; }
| _IN r08 COMMA _PORTC EOL
{ pre = 0xED; cmd |= 0x40; }
| _INC s08 EOL
{ cmd = (cmd << 3) | 0x04; }
| _INC r16xy EOL
{ cmd |= 0x03; }
| _IND EOL
{ pre = 0xED; cmd = 0xAA; }
| _INDR EOL
{ pre = 0xED; cmd = 0xBA; }
| _INI EOL
{ pre = 0xED; cmd = 0xA2; }
| _INIR EOL
{ pre = 0xED; cmd = 0xB2; }
| _JP _M EOL
{ cmd = 0xE9; }
| _JP _MX EOL
{ pre = 0xDD; cmd = 0xE9; }
| _JP _MY EOL
{ pre = 0xFD; cmd = 0xE9; }
| _JP i16 EOL
{ cmd = 0xC3; }
| _JP cond COMMA i16 EOL
{ cmd |= 0xC2; }
| _JR ofs8 EOL
{ cmd = 0x18; }
| _JR cond1 COMMA ofs8 EOL
{ cmd |= 0x20; }
| _LD _BC COMMA i16 EOL
{ cmd = 0x01; }
| _LD LPAREN i16 RPAREN COMMA _BC EOL
{ pre = 0xED; cmd = 0x43; }
| _LD _BC COMMA LPAREN i16 RPAREN EOL
{ pre = 0xED; cmd = 0x4B; }
| _LD _DE COMMA i16 EOL
{ cmd = 0x11; }
| _LD LPAREN i16 RPAREN COMMA _DE EOL
{ pre = 0xED; cmd = 0x53; }
| _LD _DE COMMA LPAREN i16 RPAREN EOL
{ pre = 0xED; cmd = 0x5B; }
| _LD _HL COMMA i16 EOL
{ cmd = 0x21; }
| _LD LPAREN i16 RPAREN COMMA _HL EOL
{ cmd = 0x22; }
| _LD _HL COMMA LPAREN i16 RPAREN EOL
{ cmd = 0x2A; }
| _LD _SP COMMA i16 EOL
{ cmd = 0x31; }
| _LD LPAREN i16 RPAREN COMMA _SP EOL
{ pre = 0xED; cmd = 0x73; }
| _LD _SP COMMA LPAREN i16 RPAREN EOL
{ pre = 0xED; cmd = 0x7B; }
| _LD _SP COMMA _HL EOL
{ cmd = 0xE3; }
| _LD _SP COMMA _IX EOL
{ pre = 0xDD; cmd = 0xE3; }
| _LD _SP COMMA _IY EOL
{ pre = 0xFD; cmd = 0xE3; }
| _LD _IX COMMA i16 EOL
{ pre = 0xDD; cmd = 0x21; }
| _LD LPAREN i16 RPAREN COMMA _IX EOL
{ pre = 0xDD; cmd = 0x22; }
| _LD _IX COMMA LPAREN i16 RPAREN EOL
{ pre = 0xDD; cmd = 0x2A; }
| _LD _IY COMMA i16 EOL
{ pre = 0xFD; cmd = 0x21; }
| _LD LPAREN i16 RPAREN COMMA _IY EOL
{ pre = 0xFD; cmd = 0x22; }
| _LD _IY COMMA LPAREN i16 RPAREN EOL
{ pre = 0xFD; cmd = 0x2A; }
| _LD _B COMMA s08 EOL
{ cmd |= 0x40; }
| _LD _C COMMA s08 EOL
{ cmd |= 0x48; }
| _LD _D COMMA s08 EOL
{ cmd |= 0x50; }
| _LD _E COMMA s08 EOL
{ cmd |= 0x58; }
| _LD _H COMMA s08 EOL
{ cmd |= 0x60; }
| _LD _L COMMA s08 EOL
{ cmd |= 0x68; }
| _LD _M COMMA s08 EOL
{ cmd |= 0x70; }
| _LD _A COMMA s08 EOL
{ cmd |= 0x78; }
| _LD _MX COMMA s08 EOL
{ pre = 0xDD; cmd |= 0x70; ofs = $2; ofsflg = 1; }
| _LD _MY COMMA s08 EOL
{ pre = 0xFD; cmd |= 0x70; ofs = $2; ofsflg = 1; }
| _LD _B COMMA i08 EOL
{ cmd = 0x06; }
| _LD _C COMMA i08 EOL
{ cmd = 0x0E; }
| _LD _D COMMA i08 EOL
{ cmd = 0x16; }
| _LD _E COMMA i08 EOL
{ cmd = 0x1E; }
| _LD _H COMMA i08 EOL
{ cmd = 0x26; }
| _LD _L COMMA i08 EOL
{ cmd = 0x2E; }
| _LD _M COMMA i08 EOL
{ cmd = 0x36; }
| _LD _A COMMA i08 EOL
{ cmd = 0x3E; }
| _LD _MX COMMA i08 EOL
{ pre = 0xDD; cmd = 0x36; ofs = $2; ofsflg = 1; }
| _LD _MY COMMA i08 EOL
{ pre = 0xFD; cmd = 0x36; ofs = $2; ofsflg = 1; }
| _LD _I COMMA _A EOL
{ pre = 0xED; cmd = 0x47; }
| _LD _R COMMA _A EOL
{ pre = 0xED; cmd = 0x4F; }
| _LD _A COMMA _I EOL
{ pre = 0xED; cmd = 0x57; }
| _LD _A COMMA _R EOL
{ pre = 0xED; cmd = 0x5F; }
| _LD LPAREN _BC RPAREN COMMA _A EOL
{ cmd = 0x02; }
| _LD _A COMMA LPAREN _BC RPAREN EOL
{ cmd = 0x0A; }
| _LD LPAREN _DE RPAREN COMMA _A EOL
{ cmd = 0x12; }
| _LD _A COMMA LPAREN _DE RPAREN EOL
{ cmd = 0x1A; }
| _LD LPAREN i16 RPAREN COMMA _A EOL
{ cmd = 0x32; }
| _LD _A COMMA LPAREN i16 RPAREN EOL
{ cmd = 0x3A; }
| _LDD EOL
{ pre = 0xED; cmd = 0xA8; }
| _LDDR EOL
{ pre = 0xED; cmd = 0xB8; }
| _LDI EOL
{ pre = 0xED; cmd = 0xA0; }
| _LDIR EOL
{ pre = 0xED; cmd = 0xB0; }
| _NEG EOL
{ pre = 0xED; cmd = 0x44; }
| _NOP EOL
{ cmd = 0x00; }
| _OR s08 EOL
{ cmd |= 0xB0; }
| _OR i08 EOL
{ cmd = 0xF6; }
| _OTDR EOL
{ pre = 0xED; cmd = 0xBB; }
| _OTIR EOL
{ pre = 0xED; cmd = 0xB3; }
| _OUT LPAREN i08 RPAREN EOL
{ cmd = 0xD3; }
| _OUT _PORTC COMMA r08 EOL
{ pre = 0xED; cmd = 0x41; }
| _OUTD EOL
{ pre = 0xED; cmd = 0xAB; }
| _OUTI EOL
{ pre = 0xED; cmd = 0xA3; }
| _POP r16pp EOL
{ cmd |= 0xC1; }
| _PUSH r16pp EOL
{ cmd |= 0xC5; }
| _RES bit COMMA s08 EOL
{ xcb = 0xCB; cmd |= 0x80; }
| _RET EOL
{ cmd = 0xC9; }
| _RET cond EOL
{ cmd |= 0xC0; }
| _RETI EOL
{ pre = 0xED; cmd = 0x45; }
| _RETN EOL
{ pre = 0xED; cmd = 0x4D; }
| _RL s08 EOL
{ xcb = 0xCB; cmd |= 0x10; }
| _RLA EOL
{ cmd = 0x17; }
| _RLC s08 EOL
{ xcb = 0xCB; cmd |= 0x00; }
| _RLCA EOL
{ cmd = 0x07; }
| _RLD EOL
{ pre = 0xED; cmd = 0x6F; }
| _RR s08 EOL
{ xcb = 0xCB; cmd |= 0x18; }
| _RRA EOL
{ cmd = 0x1F; }
| _RRC s08 EOL
{ xcb = 0xCB; cmd |= 0x08; }
| _RRCA EOL
{ cmd = 0x0F; }
| _RRD EOL
{ pre = 0xED; cmd = 0x67; }
| _RST rst EOL
{ cmd |= 0xC7; }
| _SBC _A COMMA s08 EOL
{ cmd |= 0x98; }
| _SBC _A COMMA i08 EOL
{ cmd = 0xDE; }
| _SBC _HL COMMA r16 EOL
{ pre = 0xED; cmd |= 0x42; }
| _SCF EOL
{ cmd = 0x37; }
| _SET bit COMMA s08 EOL
{ xcb = 0xCB; cmd |= 0xC0; }
| _SLA s08 EOL
{ xcb = 0xCB; cmd |= 0x20; }
| _SLL s08 EOL
{ xcb = 0xCB; cmd |= 0x30; }
| _SRA s08 EOL
{ xcb = 0xCB; cmd |= 0x28; }
| _SRL s08 EOL
{ xcb = 0xCB; cmd |= 0x38; }
| _SUB s08 EOL
{ cmd |= 0x90; }
| _SUB i08 EOL
{ cmd |= 0xD6; }
| _XOR s08 EOL
{ cmd |= 0xA8; }
| _XOR i08 EOL
{ cmd = 0xEE; }
| _DEFB i08list EOL
{ cmdflg = 0; }
| _DEFS i08 EOL
{ cmdflg = 0; argcnt = arg[0]; arg[0] = 0x00; }
| _DEFM strlist EOL
{ cmdflg = 0; }
| _DEFW i16list EOL
{ cmdflg = 0; }
| _ORG i16 EOL
{
cmdflg = 0;
argcnt = 0;
expflg = 1;
exp = *(word *)arg;
PC = exp;
}
| _END i16 EOL
{
cmdflg = 0;
argcnt = 0;
expflg = 1;
exp = *(word *)arg;
end = exp;
}
;
s08 : _B { cmd |= 0x00; }
| _C { cmd |= 0x01; }
| _D { cmd |= 0x02; }
| _E { cmd |= 0x03; }
| _H { cmd |= 0x04; }
| _L { cmd |= 0x05; }
| _M { cmd |= 0x06; }
| _A { cmd |= 0x07; }
| _MX { pre = 0xDD; cmd |= 0x06; ofs = $1; ofsflg = 1; }
| _MY { pre = 0xFD; cmd |= 0x06; ofs = $1; ofsflg = 1; }
;
r08 : _B { cmd |= 0x00; }
| _C { cmd |= 0x08; }
| _D { cmd |= 0x10; }
| _E { cmd |= 0x18; }
| _H { cmd |= 0x20; }
| _L { cmd |= 0x28; }
| _F { cmd |= 0x30; }
| _A { cmd |= 0x38; }
;
r16 : _BC { cmd |= 0x00; }
| _DE { cmd |= 0x10; }
| _HL { cmd |= 0x20; }
| _SP { cmd |= 0x30; }
;
r16x : _BC { cmd |= 0x00; }
| _DE { cmd |= 0x10; }
| _IX { cmd |= 0x20; }
| _SP { cmd |= 0x30; }
;
r16y : _BC { cmd |= 0x00; }
| _DE { cmd |= 0x10; }
| _IY { cmd |= 0x20; }
| _SP { cmd |= 0x30; }
;
r16xy : _BC { cmd |= 0x00; }
| _DE { cmd |= 0x10; }
| _HL { cmd |= 0x20; }
| _SP { cmd |= 0x30; }
| _IX { pre = 0xDD; cmd |= 0x20; }
| _IY { pre = 0xFD; cmd |= 0x20; }
;
r16pp : _BC { cmd |= 0x00; }
| _DE { cmd |= 0x10; }
| _HL { cmd |= 0x20; }
| _AF { cmd |= 0x30; }
| _IX { pre = 0xDD; cmd |= 0x20; }
| _IY { pre = 0xFD; cmd |= 0x20; }
;
cond : _cNZ { cmd |= 0x00; }
| _cZ { cmd |= 0x08; }
| _cNC { cmd |= 0x10; }
| _cC { cmd |= 0x18; }
| _cPO { cmd |= 0x20; }
| _cPE { cmd |= 0x28; }
| _cP { cmd |= 0x30; }
| _cM { cmd |= 0x38; }
;
cond1 : _cNZ { cmd |= 0x00; }
| _cZ { cmd |= 0x08; }
| _cNC { cmd |= 0x10; }
| _cC { cmd |= 0x18; }
;
expr : simple
{ $$ = $1; }
| expr SHL simple
{ $$ = $1 << $3; }
| expr SHR simple
{ $$ = $1 >> $3; }
;
simple : term
{ $$ = $1; }
| simple PLUS term
{ $$ = $1 + $3; }
| simple MINUS term
{ $$ = $1 - $3; }
| simple AND term
{ $$ = $1 & $3; }
;
term : factor
{ $$ = $1; }
| PLUS factor
{ $$ = $2; }
| MINUS factor
{ $$ = -$2; }
| NOT factor
{ $$ = ~$2; }
| term MUL factor
{ $$ = $1 * $3; }
| term DIV factor
{ $$ = $1 / $3; }
| term OR factor
{ $$ = $1 | $3; }
| term XOR factor
{ $$ = $1 ^ $3; }
;
factor : _VAL
{ $$ = $1; }
| _SYM
{ $$ = getsym($1); free($1); }
;
i08 : expr
{
if( $1 < -255 || $1 > 255 )
fprintf(stderr, "line (%d) warning: size exceeds BYTE (%d)\n", line_no, $1);
arg[argcnt++] = $1;
}
;
i08list : i08 COMMA i08list
| i08
;
i16 : expr
{
if( $1 < -65535 || $1 > 65535 )
fprintf(stderr, "line (%d) warning: size exceeds WORD (%d)\n", line_no, $1);
arg[argcnt++] = $1 & 255;
arg[argcnt++] = $1 / 256;
}
;
i16list : i16 COMMA i16list
| i16
;
str : _STR
{
strcpy(arg + argcnt, $1);
argcnt += strlen($1);
free($1);
}
| i08
;
strlist : str COMMA strlist
| str
;
ofs8 : expr
{
ofs = $1 - PC - 2;
ofsflg = 1;
if( pass_no > 1 && (ofs < -128 || ofs > +127) )
fprintf(stderr, "line (%d) warning: JR out of range (%d)\n", line_no, $1 - PC - 2);
}
;
bit : expr
{
if( $1 < 0 || $1 > 7 )
fprintf(stderr, "line (%d) invalid bit number %d\n", line_no, $1);
cmd |= ($1 & 7) << 3;
}
;
rst : expr
{
if( $1 < 0 || $1 > 0x38 || $1 & 0x07 )
fprintf(stderr, "line (%d) invalid rst vector %04XH\n", line_no, $1);
cmd |= ($1 & 0x38);
}
;
imode : expr
{
if( $1 < 0 || $1 > 2 )
fprintf(stderr, "line (%d) invalid interrupt mode %d\n", line_no, $1);
cmd |= ($1 % 3) << 3;
}
%%
int list(char * fmt, ...)
{
va_list arg;
int rc = 0;
if( !f_list )
return rc;
if( pass_no < 2 )
return rc;
va_start(arg, fmt);
rc = vfprintf(lstfile, fmt, arg);
va_end(arg);
return rc;
}
void tape_flush(void)
{
if( !tape_cnt )
return;
#if CGENIE
fputc(0x3C, outfile);
fputc(tape_cnt, outfile);
fputc(tape_adr & 255, outfile);
fputc(tape_adr / 256, outfile);
fwrite(tape_buf, 1, tape_cnt, outfile);
fputc(tape_crc, outfile);
tape_crc = 0;
#else
if( f_first )
{
fputc(tape_adr & 255, outfile);
fputc(tape_adr / 256, outfile);
f_first = 0;
}
fwrite(tape_buf, 1, tape_cnt, outfile);
#endif
tape_cnt = 0;
}
int outch(byte c)
{
int rc = 0;
if( pass_no == 1 )
{
PC++;
return rc;
}
rc = list("%02X ", c);
if( f_tape )
{
if( PC != tape_pc || tape_cnt == 128 )
{
tape_flush();
tape_pc = PC;
tape_adr = PC;
tape_crc = (tape_adr & 255) + (tape_adr / 256);
}
tape_buf[tape_cnt++] = c;
tape_crc += c;
tape_pc += 1;
}
else
{
fputc(c, outfile);
}
PC++;
return rc;
}
void emit(void)
{
int i;
int x = 0;
if( cmdflg || argcnt )
x += list("%04X: ", PC);
if( pre )
x += outch(pre);
if( xcb )
x += outch(xcb);
if( pre && xcb && ofsflg )
{
x += outch(ofs);
x += outch(cmd);
}
else
{
if( cmdflg )
x += outch(cmd);
if( ofsflg )
x += outch(ofs);
}
for( i = 0; (i < argcnt) && (i < 8); i++ )
x += outch(arg[i]);
if( strchr(lstbuff, '\n') )
{
if( !(cmdflg || argcnt) && expflg )
x += list("=%04X ", exp);
if( x >= 0 && x < 32 )
list("%*s", 32 - x, " ");
list("%s", lstbuff);
}
if( argcnt > 8 )
{
for( i = 8; i < argcnt; i++ )
{
if( (i & 7) == 0 )
x = list("%04X: ", PC);
x += outch(arg[i]);
if( (i & 7) == 7 )
x += list("\n");
}
if( i & 7 )
x += list("\n");
}
pre = 0;
xcb = 0;
cmd = 0;
ofs = 0;
expflg = 0;
cmdflg = 1;
ofsflg = 0;
argcnt = 0;
}
void addsym(char * name, int value)
{
SYM *s, *s0, *s1;
for( s = sym; (s); s = s->next )
{
if( strcasecmp(name, s->name) == 0 )
{
if( s->pass_no == pass_no )
fprintf(stderr, "line (%d) warning: double defined symbol %s\n", line_no, name);
s->line_no[0] = line_no;
s->pass_no = pass_no;
if( s->value != value )
fprintf(stderr, "line (%d) warning: %s has different value on pass 2\n", line_no, name);
s->value = value;
return;
}
}
for( s0 = NULL, s1 = sym; (s1); s0 = s1, s1 = s1->next )
if( stricmp(name, s1->name) <= 0 )
break;
s = (SYM *) calloc(1, sizeof(SYM));
if( !s )
{
fprintf(stderr, "error: out of memory!\n");
exit(1);
}
s->next = s1;
s->pass_no = pass_no;
s->refs = 0;
s->line_no = malloc(sizeof(int));
*s->line_no = line_no;
s->value = value;
s->name = strdup(name);
if( s0 )
s0->next = s;
else
sym = s;
symb_no++;
}
int getsym(char * name)
{
SYM *s;
for( s = sym; (s); s = s->next )
{
if( strcasecmp(name, s->name) == 0 )
{
if( pass_no > 1 )
{
s->refs += 1;
s->line_no = (int *) realloc(s->line_no, (s->refs + 1) * sizeof(int));
s->line_no[s->refs] = line_no;
}
return s->value;
}
}
if( pass_no > 1 )
fprintf(stderr, "line (%d) undefined symbol: %s\n", line_no, name);
return 0;
}
void prtsym(FILE * filp)
{
SYM * s;
int i;
for( s = sym; (s); s = s->next )
{
fprintf(filp, "%-32.32s%04X line %d, %d references\n", s->name, s->value, s->line_no[0], s->refs);
if( f_xref )
{
if( s->refs > 0 )
{
for( i = 0; i < s->refs; i++ )
{
if( (i & 7) == 0 )
fprintf(filp, " ");
fprintf(filp, "%d ", s->line_no[i+1]);
if( (i & 7) == 7 )
fprintf(filp,"\n");
}
if( i & 7 )
fprintf(filp, "\n");
}
}
}
}
int main(int ac, char ** av)
{
int i;
char * p;
if( ac < 2 )
{
fprintf(stderr, "usage:\taz80 [options] input[.z80] [output[.bin]] [listing[.lst]]\n");
fprintf(stderr, "options can be one or more of:\n");
fprintf(stderr, "-d\tgenerate parser debug output to stderr\n");
fprintf(stderr, "-l\tgenerate listing (to file input.lst)\n");
fprintf(stderr, "-s\toutput symbol table\n");
#if CGENIE
fprintf(stderr, "-t[name]\tgenerate Colour Genie tape with load addresses\n");
#else
fprintf(stderr, "-t[name]\tgenerate VZ200/VZ300 tape with load address\n");
#endif
fprintf(stderr, "-x\toutput cross reference with symbol table\n");
exit(1);
}
for( i = 1; i < ac; i++ )
{
if( av[i][0] == '-' )
{
switch (av[i][1])
{
case 'd': case 'D':
yydebug = 1;
break;
case 'l': case 'L':
f_list = 1;
break;
case 's': case 'S':
f_syms = 1;
break;
case 'x': case 'X':
f_xref = 1;
break;
case 't': case 'T':
f_tape = 1;
strncpy(tape_name, av[i]+2, 6);
tape_name[6] = '\0';
break;
default:
fprintf(stderr, "illegal option %s\n", av[i]);
exit(1);
}
}
else
{
if( strlen(inpname) )
{
if( strlen(outname) )
{
if( strlen(lstname) )
{
fprintf(stderr, "additional argument %s ignored\n", av[i]);
}
else
{
strcpy(lstname, av[i]);
}
}
else
{
strcpy(outname, av[i]);
}
}
else
{
strcpy(inpname, av[i]);
}
}
}
if( !strlen(inpname) )
{
fprintf(stderr, "input filename missing!\n");
exit(1);
}
if( !strlen(outname) )
{
strcpy(outname, inpname);
p = strrchr(outname, '.');
if( p )
strcpy(p, (f_tape) ? TAPE_EXT : ".bin");
else
strcat(outname, (f_tape) ? TAPE_EXT : ".bin");
}
if( f_list )
{
if( !strlen(lstname) )
{
strcpy(lstname, inpname);
p = strrchr(lstname, '.');
if( p )
strcpy(p, ".lst");
else
strcat(lstname, ".lst");
}
}
else
if( strlen(lstname) )
{
f_list = 1;
p = strrchr(lstname, '.');
if( p )
strcpy(p, ".lst");
else
strcat(lstname, ".lst");
}
p = strrchr(inpname, '.');
if( !p )
strcat(inpname, ".z80");
inpfile = fopen(inpname, "r");
if( !inpfile )
{
fprintf(stderr, "can't open %s\n", inpname);
exit(1);
}
outfile = fopen(outname, "wb");
if( !outfile )
{
fprintf(stderr, "can't create %s\n", outname);
exit(1);
}
if( f_list )
{
lstfile = fopen(lstname, "w");
if( !lstfile )
{
fprintf(stderr, "can't create %s\n", outname);
exit(1);
}
plst = lstbuff;
*plst = '\0';
}
if( f_tape )
{
#if CGENIE
fputc(0x66, outfile);
fputc(0x55, outfile);
p = tape_name;
for( i = 0; i < 6; i++ )
fputc((*p) ? toupper(*p++) : ' ', outfile);
#else
char vz_name[16+1], *src = tape_name, *dst = vz_name;
int i;
memset(vz_name, 0, sizeof(vz_name));
while( *src && *src != '.' )
*dst++ = toupper(*src);
fputc(0x20, outfile); /* magic */
fputc(0x20, outfile);
fputc(0x00, outfile);
fputc(0x00, outfile);
for( i = 0; i < sizeof(vz_name); i++ )
fputc(vz_name[i], outfile);
fputc(0xf1, outfile); /* magic value */
f_first = 1;
#endif
}
printf("assembling %s\npass 1\n", inpname);
yyrestart(inpfile);
yyparse();
list("\n");
if( f_syms )
prtsym((f_list) ? lstfile : stdout);
if( f_tape )
{
tape_flush();
#if CGENIE
fputc(0x78, outfile);
fputc(end & 255, outfile);
fputc(end / 256, outfile);
#endif
}
fclose(inpfile);
fclose(outfile);
if( f_list )
fclose(lstfile);
printf("%d lines, %d symbols\n", line_no, symb_no);
return 0;
}