mirror of
https://github.com/fachat/xa65.git
synced 2025-02-12 12:30:27 +00:00
added first listing feature!
This commit is contained in:
parent
eae097c73a
commit
1691f5fb46
@ -57,6 +57,11 @@ use the special filename
|
||||
.BR \-
|
||||
to output to standard output.
|
||||
.TP
|
||||
.B \-P filename
|
||||
Set listing filename, default is none. use the special filename
|
||||
.BR \-
|
||||
to print the listing to standard output.
|
||||
.TP
|
||||
.B \-e filename
|
||||
Set errorlog filename, default is none.
|
||||
.TP
|
||||
|
33
xa/src/xa.c
33
xa/src/xa.c
@ -77,7 +77,7 @@ char altppchar;
|
||||
|
||||
static char out[MAXLINE];
|
||||
static time_t tim1, tim2;
|
||||
static FILE *fpout, *fperr, *fplab;
|
||||
static FILE *fpout, *fperr, *fplab, *fplist;
|
||||
static int ner = 0;
|
||||
static int ner_max = 20;
|
||||
|
||||
@ -123,9 +123,10 @@ int main(int argc,char *argv[])
|
||||
int no_link = 0;
|
||||
|
||||
char **ifiles;
|
||||
char *ofile;
|
||||
char *efile;
|
||||
char *lfile;
|
||||
char *printfile; /* print listing to this file */
|
||||
char *ofile; /* output file */
|
||||
char *efile; /* error listing goes there */
|
||||
char *lfile; /* labels go here */
|
||||
char *ifile;
|
||||
|
||||
char old_e[MAXLINE];
|
||||
@ -179,6 +180,7 @@ int main(int argc,char *argv[])
|
||||
ofile="a.o65";
|
||||
efile=NULL;
|
||||
lfile=NULL;
|
||||
printfile=NULL;
|
||||
|
||||
if(pp_init()) {
|
||||
logout("fatal: pp: no memory!");
|
||||
@ -298,6 +300,13 @@ int main(int argc,char *argv[])
|
||||
reg_include(argv[i]+2);
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
if(argv[i][2]==0) {
|
||||
printfile=argv[++i];
|
||||
} else {
|
||||
printfile=argv[i]+2;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if(argv[i][2]==0) {
|
||||
ofile=argv[++i];
|
||||
@ -378,6 +387,12 @@ int main(int argc,char *argv[])
|
||||
if(setfext(old_l,".lab")==0) lfile = old_l;
|
||||
}
|
||||
|
||||
if (printfile!=NULL && !strcmp(printfile, "-")) {
|
||||
printfile=NULL;
|
||||
fplist = stdout;
|
||||
} else {
|
||||
fplist= printfile ? xfopen(printfile,"w") : NULL;
|
||||
}
|
||||
fplab= lfile ? xfopen(lfile,"w") : NULL;
|
||||
fperr= efile ? xfopen(efile,"w") : NULL;
|
||||
if(!strcmp(ofile,"-")) {
|
||||
@ -393,6 +408,7 @@ int main(int argc,char *argv[])
|
||||
|
||||
if(verbose) fprintf(stderr, "%s\n",copyright);
|
||||
|
||||
|
||||
if(1 /*!m_init()*/)
|
||||
{
|
||||
if(1 /*!b_init()*/)
|
||||
@ -406,6 +422,8 @@ int main(int argc,char *argv[])
|
||||
if(fperr) fprintf(fperr,"%s\n",copyright);
|
||||
if(verbose) logout(ctime(&tim1));
|
||||
|
||||
list_setfile(fplist);
|
||||
|
||||
/* Pass 1 */
|
||||
|
||||
pc[SEG_ABS]= 0; /* abs addressing */
|
||||
@ -498,9 +516,10 @@ int main(int argc,char *argv[])
|
||||
|
||||
if((!er) && relmode) seg_end(fpout); /* write reloc/label info */
|
||||
|
||||
if(fplist && fplist!=stdout) fclose(fplist);
|
||||
if(fperr) fclose(fperr);
|
||||
if(fplab) fclose(fplab);
|
||||
if(fpout) fclose(fpout);
|
||||
if(fpout && fpout!=stdout) fclose(fpout);
|
||||
|
||||
} else {
|
||||
logout("fatal: x: no memory!\n");
|
||||
@ -673,7 +692,7 @@ static int pass2(void)
|
||||
} else
|
||||
{
|
||||
/* do not attempt address mode optimization on pass 2 */
|
||||
er=t_p2(afile->mn.tmp+afile->mn.tmpe,&ll,1,&al);
|
||||
er=t_p2_l(afile->mn.tmp+afile->mn.tmpe,&ll,1,&al);
|
||||
|
||||
if(er==E_NOLINE)
|
||||
{
|
||||
@ -779,7 +798,7 @@ fprintf(stderr, "offset = %i length = %i fstart = %i flen = %i charo = %c\n",
|
||||
|
||||
static int pass1(void)
|
||||
{
|
||||
signed char o[MAXLINE];
|
||||
signed char o[2*MAXLINE]; /* doubled for token listing */
|
||||
int l,er,temp_er,al;
|
||||
|
||||
memode=0;
|
||||
|
29
xa/src/xah.h
29
xa/src/xah.h
@ -53,6 +53,7 @@ typedef struct {
|
||||
*/
|
||||
int afl; /* 0 = no address (no relocation), 1 = address label */
|
||||
int nextindex;
|
||||
int is_cll; /* 0 is normal label, 1 is cheap local label (used for listing) */
|
||||
char *n;
|
||||
struct LabOcc *occlist;
|
||||
} Labtab;
|
||||
@ -134,18 +135,24 @@ typedef struct {
|
||||
#define W_OVER16M -73 /* included binary over 16M in 65816 mode */
|
||||
/* warnings 74-76 are placeholders */
|
||||
|
||||
#define T_VALUE -1
|
||||
#define T_LABEL -2
|
||||
#define T_OP -3
|
||||
#define T_END -4
|
||||
#define T_LINE -5
|
||||
#define T_FILE -6
|
||||
#define T_POINTER -7
|
||||
/* Meta-values for the token list. Note must not overlap with the
|
||||
* K* definitions in xat.c, which have outgrown the positive numbers
|
||||
* and are now growing up from -128 ... */
|
||||
#define T_VALUE -1 /* following is a 24 bit value in the token list */
|
||||
#define T_LABEL -2 /* referring to a label, following the token is the 16bit label number */
|
||||
#define T_OP -3 /* label oriented operation; following is the label number (16bit), plus the operation char (e.g. '+') */
|
||||
#define T_END -4 /* end of line marker */
|
||||
#define T_LINE -5 /* new line indicator; following is the 16 bit line number */
|
||||
#define T_FILE -6 /* new file indicator; following is the 16 bit line number, then the file name (zero-term) */
|
||||
#define T_POINTER -7 /* ??? */
|
||||
#define T_COMMENT -8 /* unused */
|
||||
#define T_DEFINE -9 /* define a label; inserted at conversion and discarded in pass1, only used in listing output */
|
||||
#define T_LISTING -10 /* meta token, inserted after conversion before pass1, used after pass2 to create listing */
|
||||
|
||||
#define P_START 0 /* Prioritaeten fuer Arithmetik */
|
||||
#define P_LOR 1 /* Von zwei Operationen wird immer */
|
||||
#define P_LAND 2 /* die mit der hoeheren Prioritaet */
|
||||
#define P_OR 3 /* zuerst ausgefuehrt */
|
||||
#define P_START 0 /* arithmetic operation priorities */
|
||||
#define P_LOR 1 /* of any two operations, the one with */
|
||||
#define P_LAND 2 /* the higher priority will be done first */
|
||||
#define P_OR 3
|
||||
#define P_XOR 4
|
||||
#define P_AND 5
|
||||
#define P_EQU 6
|
||||
|
14
xa/src/xal.c
14
xa/src/xal.c
@ -313,6 +313,7 @@ int l_def(char *s, int *l, int *x, int *f)
|
||||
ltp=afile->la.lt+n;
|
||||
*l=ltp->len+i;
|
||||
ltp->fl=0;
|
||||
ltp->is_cll=cll_fl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,7 +364,8 @@ int l_search(char *s, int *l, int *x, int *v, int *afl)
|
||||
er=ll_def(s,x,b); /* ll_def(...,*v); */
|
||||
|
||||
ltp=afile->la.lt+(*x);
|
||||
|
||||
ltp->is_cll = cll_fl;
|
||||
|
||||
*l=ltp->len + cll_fl;
|
||||
|
||||
if(!er)
|
||||
@ -411,6 +413,13 @@ void l_addocc(int n, int *v, int *afl) {
|
||||
}
|
||||
}
|
||||
|
||||
/* for the list functionality */
|
||||
char *l_get_name(int n, int *is_cll) {
|
||||
ltp=afile->la.lt+n;
|
||||
*is_cll = ltp->is_cll;
|
||||
return ltp->n;
|
||||
}
|
||||
|
||||
int l_get(int n, int *v, int *afl)
|
||||
{
|
||||
if(crossref) l_addocc(n,v,afl);
|
||||
@ -495,6 +504,7 @@ static int ll_def(char *s, int *n, int b) /* definiert naechstes Label
|
||||
ltp->blk=b;
|
||||
ltp->fl=0;
|
||||
ltp->afl=0;
|
||||
ltp->is_cll=0;
|
||||
ltp->occlist=NULL;
|
||||
hash=hashcode(s,j);
|
||||
ltp->nextindex=afile->la.hashindex[hash];
|
||||
@ -689,7 +699,7 @@ int b_close(void)
|
||||
} else {
|
||||
return E_BLOCK;
|
||||
}
|
||||
|
||||
cll_clear();
|
||||
return(E_OK);
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,10 @@
|
||||
|
||||
#include <stdio.h> /* for FILE */
|
||||
|
||||
/* nasty stuff - "lz" is exported from xal.c so xa.c can print the name
|
||||
* of the label that was last searched for in the error message that the
|
||||
* label was not found...
|
||||
*/
|
||||
extern char *lz;
|
||||
|
||||
int l_init(void);
|
||||
@ -42,6 +46,7 @@ int ga_blk(void);
|
||||
int l_def(char *s, int* l, int *x, int *f);
|
||||
int l_search(char *s, int *l, int *x, int *v, int *afl);
|
||||
void l_set(int n, int v, int afl);
|
||||
char* l_get_name(int n, int *is_cll);
|
||||
int l_get(int n, int *v, int *afl);
|
||||
int l_vget(int n, int *v, char **s);
|
||||
int ll_search(char *s, int *n, int cll_fl);
|
||||
|
@ -66,7 +66,7 @@ void o_write(FILE *fp) {
|
||||
l=afile->fo.olist[i].len;
|
||||
t=afile->fo.olist[i].text;
|
||||
/* do not optimize */
|
||||
t_p2(t, &l, 1, &afl);
|
||||
t_p2_l(t, &l, 1, &afl);
|
||||
|
||||
if(l>254) {
|
||||
errout(E_OPTLEN);
|
||||
|
465
xa/src/xat.c
465
xa/src/xat.c
@ -25,6 +25,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xad.h"
|
||||
#include "xah.h"
|
||||
@ -48,6 +49,8 @@ static void tg_dez(signed char*,int*,int*);
|
||||
static void tg_hex(signed char*,int*,int*);
|
||||
static void tg_oct(signed char*,int*,int*);
|
||||
static void tg_bin(signed char*,int*,int*);
|
||||
static int t_p2(signed char *t, int *ll, int fl, int *al);
|
||||
static void do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len);
|
||||
|
||||
/* assembly mnemonics and pseudo-op tokens */
|
||||
/* ina and dea don't work yet */
|
||||
@ -148,7 +151,7 @@ static int lp[]= { 0,1,1,1,1,2,2,1,1,1,2,2,2,1,1,1,2,2 };
|
||||
|
||||
|
||||
#define Kreloc (Anzkey-256) /* *= (relocation mode) */
|
||||
#define Ksegment (Anzkey+1-256) /* this actually now is 129, which might be a problem as char is signed ... */
|
||||
#define Ksegment (Anzkey+1-256) /* this actually now is above 127, which might be a problem as char is signed ... */
|
||||
|
||||
/* array used for hashing tokens (26 entries, a-z) */
|
||||
|
||||
@ -347,11 +350,14 @@ static int le[] ={ 1,2,2,2,2,2,2,2,3,3,3,2,3,3,3,2,
|
||||
static int opt[] ={ -1,-1,-1,-1,-1,-1,-1,-1,1,2,3,-1,4,5,-1,-1,
|
||||
/*new*/ -1,8,9,-1,-1,-1,-1,-1 }; /* abs -> zp */
|
||||
|
||||
/*********************************************************************************************/
|
||||
/* pass 1 */
|
||||
int t_p1(signed char *s, signed char *t, int *ll, int *al)
|
||||
{
|
||||
static int er,l,n,v,nk,na1,na2,bl,am,sy,i,label,byte; /*,j,v2 ;*/
|
||||
int afl = 0;
|
||||
int tlen; /* token listing length, to adjust length that is returned */
|
||||
int inp; /* input pointer in t[] */
|
||||
|
||||
/* notes and typical conventions ... er = error code
|
||||
am = addressing mode in use
|
||||
@ -366,18 +372,68 @@ int t_p1(signed char *s, signed char *t, int *ll, int *al)
|
||||
#ifdef DEBUG_AM
|
||||
fprintf(stderr, "- p1 %d starting -\n", pc[segment]);
|
||||
#endif
|
||||
er=t_conv(s,t,&l,pc[segment],&nk,&na1,&na2,0,&byte);
|
||||
/* leaving our token sequence in t */
|
||||
|
||||
/* As the t_p1 code below always works through the tokens
|
||||
* from t_conv in such a way that it always produces a shorter
|
||||
* result, the conversion below takes place "in place".
|
||||
* This, however, means that the original token sequence, which
|
||||
* would be useful for some assembler listing, is overwritten.
|
||||
* While the original assumption was ok for a constrained
|
||||
* environment like the Atari ST, this is no longer true.
|
||||
* Converting the code below to have separate input and output
|
||||
* areas would be error-prone, so we do some copy-magic here
|
||||
* instead...*/
|
||||
/* we keep three bytes buffer for "T_LISTING" and the length of the
|
||||
* token list
|
||||
*/
|
||||
t[0]=T_LISTING;
|
||||
er=t_conv(s,t+6,&l,pc[segment],&nk,&na1,&na2,0,&byte);
|
||||
tlen = l+6;
|
||||
t[1]=tlen&255;
|
||||
t[2]=(tlen>>8)&255;
|
||||
t[3]=segment;
|
||||
t[4]=pc[segment]&255;
|
||||
t[5]=(pc[segment]>>8)&255;
|
||||
/* now duplicate the token sequence from the T_LISTING buffer
|
||||
* to the end of "t", so we can then in-place convert it
|
||||
* below. Non-overlapping, size is known in advance, so
|
||||
* using memcpy is fine here
|
||||
*/
|
||||
memcpy(t+tlen, t+6, l);
|
||||
t=t+tlen;
|
||||
|
||||
/* the result of this is that we always have a Klisting entry in the buffer
|
||||
* for each tokenization call */
|
||||
/* here continue as before, except for adjusting the returne *ll length
|
||||
* in the end, just before return */
|
||||
|
||||
inp = 0;
|
||||
/* discard label definitions */
|
||||
while (inp<l && t[inp]==T_DEFINE) {
|
||||
inp+=3;
|
||||
}
|
||||
if (inp) {
|
||||
/* sorry, anything else would be way to risky below */
|
||||
l -= inp;
|
||||
if (l != 0) {
|
||||
printf("t=%p, inp=%d, l=%d\n", t, inp, l);
|
||||
memmove(t, t+inp, l);
|
||||
}
|
||||
}
|
||||
|
||||
/* return length default is input length */
|
||||
*ll=l;
|
||||
/*
|
||||
|
||||
#if 0
|
||||
printf("t_conv (er=%d):",er);
|
||||
for(i=0;i<l;i++)
|
||||
printf("%02x,",t[i]);
|
||||
printf("\n");
|
||||
*/
|
||||
#endif
|
||||
|
||||
/* if text/data produced, then no more fopt allowed in romable mode */
|
||||
/* TODO: need to check, Kbyte is being remapped to Kbyt. What is the effect here? */
|
||||
if((romable>1) && (t[0]<Kopen || t[0]==Kbyte || t[0]==Kpcdef)) {
|
||||
if((romable>1) && (t[inp]<Kopen || t[inp]==Kbyte || t[inp]==Kpcdef)) {
|
||||
afile->base[SEG_TEXT] = pc[SEG_TEXT] = romaddr + h_length();
|
||||
romable=1;
|
||||
}
|
||||
@ -705,6 +761,8 @@ printf(" wrote %02x %02x %02x %02x %02x %02x\n",
|
||||
#ifdef DEBUG_AM
|
||||
fprintf(stderr, "E_OK ... t_p2 xat.c\n");
|
||||
#endif
|
||||
/* this actually calls pass2 on the current tokenization stream,
|
||||
* but without including the Klisting token listing */
|
||||
er=t_p2(t,ll,(0 | byte), al);
|
||||
}
|
||||
|
||||
@ -732,7 +790,7 @@ fprintf(stderr, "E_NODEF pass1 xat.c\n");
|
||||
|
||||
if(n>=0 && n<=Lastbef)
|
||||
{
|
||||
if(t[1]==T_END)
|
||||
if(t[1]==T_END || t[1]==T_COMMENT)
|
||||
{
|
||||
sy=0; /* implied */
|
||||
} else
|
||||
@ -906,10 +964,75 @@ fprintf(stderr, "guessing instruction length is %d\n", bl);
|
||||
if(segment==SEG_TEXT) pc[SEG_ABS]+=bl;
|
||||
if(segment==SEG_ABS) pc[SEG_TEXT]+=bl;
|
||||
|
||||
/* adjust length by token listing buffer length */
|
||||
*ll = *ll + tlen;
|
||||
return(er);
|
||||
}
|
||||
|
||||
/*t_pass 2*/
|
||||
/*********************************************************************************************/
|
||||
/* t_pass 2
|
||||
*
|
||||
* *t is the token list as given from pass1
|
||||
* *ll is the returned length of bytes (doubles as
|
||||
* input for whether OK or OKDEF status from pass1)
|
||||
* fl defines if we allow zeropage optimization
|
||||
*
|
||||
* Conversion takes place "in place" in the *t array.
|
||||
*/
|
||||
|
||||
/**
|
||||
* function called from the main loop, where "only" the
|
||||
* undefined labels have to be resolved and the affected
|
||||
* opcodes are assembled, the rest is passed through from
|
||||
* pass1 (pass-through is done in t_p2, when *ll<0)
|
||||
*
|
||||
* *t is the input token list
|
||||
* *ll is the input length of the token list,
|
||||
* and the output of how many bytes of the buffer are to be taken
|
||||
* into the file
|
||||
*/
|
||||
int t_p2_l(signed char *t, int *ll, int fl, int *al)
|
||||
{
|
||||
int er = E_OK;
|
||||
|
||||
if (t[0] == T_LISTING) {
|
||||
int tlen;
|
||||
tlen=((t[2]&255)<<8) | (t[1]&255);
|
||||
if (*ll<0) {
|
||||
*ll=(*ll) + tlen;
|
||||
} else {
|
||||
*ll=(*ll) - tlen;
|
||||
}
|
||||
|
||||
if (*ll != 0) {
|
||||
er = t_p2(t+tlen, ll, fl, al);
|
||||
}
|
||||
|
||||
/* do the actual listing (*ll-2 as we need to substract the place for the tlen value */
|
||||
do_listing(t+3, tlen-3, t+tlen, *ll);
|
||||
|
||||
/* adapt back, i.e. remove token listing */
|
||||
if (*ll != 0) {
|
||||
memmove(t, t+tlen, abs(*ll));
|
||||
}
|
||||
} else {
|
||||
er = t_p2(t, ll, fl, al);
|
||||
}
|
||||
return er;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does not handle a token list. Thus it
|
||||
* is called internally from pass1 without the token listing, and
|
||||
* from the t_p2_l() method that strips the token listing
|
||||
* as well
|
||||
*
|
||||
* *t is the input token list
|
||||
* *ll is the input length of the token list,
|
||||
* and the output of how many bytes of the buffer are to be taken
|
||||
* into the file
|
||||
*
|
||||
*/
|
||||
int t_p2(signed char *t, int *ll, int fl, int *al)
|
||||
{
|
||||
static int afl,nafl, i,j,k,er,v,n,l,bl,sy,am,c,vv[3],v2,label;
|
||||
@ -924,11 +1047,12 @@ int t_p2(signed char *t, int *ll, int fl, int *al)
|
||||
|
||||
er=E_OK;
|
||||
bl=0;
|
||||
if(*ll<0) /* <0 bei E_OK, >0 bei E_OKDEF */
|
||||
if(*ll<0) /* <0 when E_OK, >0 when E_OKDEF */
|
||||
{
|
||||
*ll=-*ll;
|
||||
bl=*ll;
|
||||
er=E_OK;
|
||||
|
||||
} else
|
||||
{
|
||||
n=t[0];
|
||||
@ -1591,10 +1715,11 @@ fprintf(stderr, "address mode: %i address: %i\n", am, vv[0]);
|
||||
er=E_SYNTAX;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else
|
||||
er=E_SYNTAX;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_AM
|
||||
fprintf(stderr, "-- endof P2\n");
|
||||
#endif
|
||||
@ -1605,6 +1730,11 @@ fprintf(stderr, "-- endof P2\n");
|
||||
return(er);
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
/* helper function for the preprocessor, to compute an arithmetic value
|
||||
* (e.g. for #if or #print).
|
||||
* First tokenizes it, then calculates the value
|
||||
*/
|
||||
int b_term(char *s, int *v, int *l, int pc)
|
||||
{
|
||||
static signed char t[MAXLINE];
|
||||
@ -1618,10 +1748,14 @@ int b_term(char *s, int *v, int *l, int pc)
|
||||
return(er);
|
||||
}
|
||||
|
||||
/* translate a string into a first-pass sequence of tokens */
|
||||
/*********************************************************************************************/
|
||||
/* translate a string into a first-pass sequence of tokens;
|
||||
* Take the text from *s (stopping at \0 or ';'), tokenize it
|
||||
* and write the result to *t, returning the length of the
|
||||
* token sequence in *l
|
||||
*/
|
||||
static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk,
|
||||
int *na1, int *na2, int af, int *bytep) /* Pass1 von s nach t */
|
||||
/* tr. pass1, from s to t */
|
||||
int *na1, int *na2, int af, int *bytep)
|
||||
{
|
||||
static int v,f;
|
||||
static int operand,o;
|
||||
@ -1712,10 +1846,17 @@ static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk,
|
||||
p++;
|
||||
while(s[p]==' ') p++;
|
||||
l_set(n,pc,segment); /* set as address value */
|
||||
t[q++]=T_DEFINE;
|
||||
t[q++]=n&255;
|
||||
t[q++]=(n>>8)&255;
|
||||
n=0;
|
||||
|
||||
} else { /* label ... syntax */
|
||||
l_set(n,pc,segment); /* set as address value */
|
||||
n=0;
|
||||
t[q++]=T_DEFINE;
|
||||
t[q++]=n&255;
|
||||
t[q++]=(n>>8)&255;
|
||||
n=0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -2017,13 +2158,17 @@ fprintf(stderr, "could not find %s\n", (char *)s+p);
|
||||
}
|
||||
}
|
||||
/* FIXME: this is an unholy union of two "!" implementations :-( */
|
||||
t[q++]='\0';
|
||||
t[q++]=cast;
|
||||
/* FIXME FIXME FIXME ... */
|
||||
if (operand==1) {
|
||||
t[q++]='\0';
|
||||
t[q++]=cast;
|
||||
}
|
||||
*l=q;
|
||||
if(bytep) *bytep=byte;
|
||||
return(er);
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
static int t_keyword(signed char *s, int *l, int *n)
|
||||
{
|
||||
int i = 0, j = 0, hash;
|
||||
@ -2206,3 +2351,291 @@ fprintf(stderr, "tg_asc token = %i\n", n);
|
||||
return(er);
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
/* this is the listing code
|
||||
*
|
||||
* Unfortunately this code has to go here (for now), as this file is the only one
|
||||
* where we have access to the tables that allow to convert the tokens back to
|
||||
* a listing
|
||||
*/
|
||||
|
||||
static FILE *listfp = NULL;
|
||||
|
||||
static int list_string(char *buf, char *string);
|
||||
static int list_tokens(char *buf, signed char *input, int len);
|
||||
static int list_value(char *buf, int val);
|
||||
static int list_nchar(char *buf, signed char c, int n);
|
||||
static int list_char(char *buf, signed char c);
|
||||
static int list_sp(char *buf);
|
||||
static int list_word(char *buf, int outword);
|
||||
static int list_byte(char *buf, int outbyte);
|
||||
static int list_nibble(char *buf, int outnib);
|
||||
|
||||
void list_setfile(FILE *fp) {
|
||||
listfp = fp;
|
||||
}
|
||||
|
||||
/**
|
||||
* listing/listing_len give the buffer address and length respectively that contains
|
||||
* the token as they are produced by the tokenizer.
|
||||
* bincode/bincode_len give the buffer address and length that contain the binary code
|
||||
* that is produced from the token listing
|
||||
*
|
||||
* Note that both lengths may be zero
|
||||
*/
|
||||
void do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len) {
|
||||
|
||||
int i, n_hexb;
|
||||
|
||||
char outline[MAXLINE];
|
||||
char *buf = outline;
|
||||
|
||||
int lst_seg = listing[0];
|
||||
int lst_pc = (listing[2]<<8) | (listing[1] & 255);
|
||||
|
||||
signed char c = '?';
|
||||
|
||||
/* no output file (not even stdout) */
|
||||
if (listfp == NULL) return;
|
||||
|
||||
/*printf("do_listing: listing=%p (%d), bincode=%p (%d)\n", listing, listing_len, bincode, bincode_len);*/
|
||||
|
||||
if (bincode_len < 0) bincode_len = -bincode_len;
|
||||
|
||||
/* preamble <segment>':'<address>' ' */
|
||||
switch(lst_seg) {
|
||||
case SEG_ABS: c='A'; break;
|
||||
case SEG_TEXT: c='T'; break;
|
||||
case SEG_BSS: c='B'; break;
|
||||
case SEG_DATA: c='D'; break;
|
||||
case SEG_UNDEF: c='U'; break;
|
||||
case SEG_ZERO: c='Z'; break;
|
||||
}
|
||||
buf = buf + list_char(buf, c);
|
||||
buf = buf + list_char(buf, ':');
|
||||
buf = buf + list_word(buf, lst_pc);
|
||||
buf = buf + list_sp(buf);
|
||||
|
||||
/* binary output (up to 8 byte. If more than 8 byte, print 7 plus "..." */
|
||||
n_hexb = bincode_len;
|
||||
if (n_hexb >= 8) {
|
||||
n_hexb = 7;
|
||||
}
|
||||
for (i = 0; i < n_hexb; i++) {
|
||||
buf = buf + list_byte(buf, bincode[i]);
|
||||
buf = buf + list_sp(buf);
|
||||
}
|
||||
if ((n_hexb == 7) && (bincode_len > 7)) {
|
||||
buf = buf + list_nchar(buf, '.', 3);
|
||||
} else {
|
||||
/* can move loop into nchar ... */
|
||||
for (; i < 8; i++) {
|
||||
buf = buf + list_nchar(buf, ' ', 3);
|
||||
}
|
||||
}
|
||||
buf = buf + list_sp(buf);
|
||||
|
||||
buf += list_tokens(buf, listing + 3, listing_len - 3);
|
||||
|
||||
/* for now only do a hex dump so we see what actually happens */
|
||||
i = buf - outline;
|
||||
if (i<80) buf += list_nchar(buf, ' ', 80-i);
|
||||
|
||||
buf += list_string(buf, " >>");
|
||||
for (i = 3; i < listing_len; i++) {
|
||||
buf = buf + list_byte(buf, listing[i]);
|
||||
buf = buf + list_sp(buf);
|
||||
}
|
||||
buf[0] = 0;
|
||||
|
||||
|
||||
fprintf(listfp, "%s\n", outline);
|
||||
}
|
||||
|
||||
int list_tokens(char *buf, signed char *input, int len) {
|
||||
int outp = 0;
|
||||
int inp = 0;
|
||||
int tmp;
|
||||
char *name;
|
||||
signed char c;
|
||||
int is_cll;
|
||||
int tabval;
|
||||
|
||||
if (inp >= len) return 0;
|
||||
|
||||
tmp = input[inp] & 255;
|
||||
|
||||
tabval = 0;
|
||||
if (tmp == (T_DEFINE & 255)) {
|
||||
while (tmp == (T_DEFINE & 255)) {
|
||||
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||
name=l_get_name(tmp, &is_cll);
|
||||
if (is_cll) outp += list_char(buf+outp, '@');
|
||||
tmp = list_string(buf+outp, name);
|
||||
tabval += tmp + 1 + is_cll;
|
||||
outp += tmp;
|
||||
outp += list_char(buf+outp, ' ');
|
||||
inp += 3;
|
||||
tmp = input[inp] & 255;
|
||||
}
|
||||
if (tabval < 10) {
|
||||
outp += list_nchar(buf+outp, ' ', 10-tabval);
|
||||
}
|
||||
} else {
|
||||
if (tmp >= 0 && tmp < Anzkey) {
|
||||
outp += list_string(buf+outp, " ");
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp >= 0 && tmp < Anzkey) {
|
||||
/* assembler keyword */
|
||||
/*printf("tmp=%d, kt[tmp]=%p\n", tmp, kt[tmp]);*/
|
||||
if (kt[tmp] != NULL) {
|
||||
outp += list_string(buf+outp, kt[tmp]);
|
||||
}
|
||||
outp += list_sp(buf + outp);
|
||||
inp += 1;
|
||||
}
|
||||
|
||||
while (inp < len) {
|
||||
switch(input[inp]) {
|
||||
case T_VALUE:
|
||||
/*outp += list_char(buf+outp, 'V');*/
|
||||
/* 24 bit value */
|
||||
tmp = ((input[inp+3]&255)<<16) | ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||
outp += list_value(buf+outp, tmp);
|
||||
inp += 4;
|
||||
break;
|
||||
case T_LABEL:
|
||||
/*outp += list_char(buf+outp, 'L');*/
|
||||
/* 16 bit label number */
|
||||
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||
name=l_get_name(tmp, &is_cll);
|
||||
if (is_cll) outp += list_char(buf+outp, '@');
|
||||
outp += list_string(buf+outp, name);
|
||||
inp += 3;
|
||||
break;
|
||||
case T_OP:
|
||||
/* arithmetic operation; inp[3] is operation like '=' or '+' */
|
||||
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||
name=l_get_name(tmp, &is_cll);
|
||||
if (is_cll) outp += list_char(buf+outp, '@');
|
||||
outp += list_string(buf+outp, name);
|
||||
outp += list_char(buf+outp, input[inp+3]);
|
||||
inp += 4;
|
||||
break;
|
||||
case T_END:
|
||||
/* end of operation */
|
||||
/*outp += list_string(buf+outp, ";");*/
|
||||
inp += 1;
|
||||
goto end;
|
||||
break;
|
||||
case T_LINE:
|
||||
/* newline marker - ignored? */
|
||||
outp += list_string(buf+outp, "\\n ");
|
||||
/* line number */
|
||||
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||
outp += list_word(buf+outp, tmp);
|
||||
inp += 3;
|
||||
break;
|
||||
case T_FILE:
|
||||
/* new file marker - ignored? */
|
||||
outp += list_string(buf+outp, "\\f ");
|
||||
/* line number */
|
||||
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||
outp += list_word(buf+outp, tmp);
|
||||
/* file name */
|
||||
tmp = list_string(buf+outp, (char*)input+inp+3);
|
||||
outp += tmp;
|
||||
inp += tmp + 3;
|
||||
break;
|
||||
case T_POINTER:
|
||||
/* what is this? It's actually resolved during token conversion */
|
||||
outp += list_byte(buf+outp, input[inp+1]);
|
||||
outp += list_char(buf+outp, '#');
|
||||
tmp = ((input[inp+3]&255)<<8) | (input[inp+2]&255);
|
||||
outp += list_value(buf+outp, tmp);
|
||||
inp += 4;
|
||||
break;
|
||||
default:
|
||||
c = input[inp];
|
||||
if (c > 31) {
|
||||
outp += list_char(buf+outp, input[inp]);
|
||||
} else {
|
||||
outp += list_char(buf+outp, '\'');
|
||||
outp += list_byte(buf+outp, input[inp]);
|
||||
}
|
||||
inp += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
end:
|
||||
return outp;
|
||||
}
|
||||
|
||||
int list_string(char *buf, char *string) {
|
||||
int p = 0;
|
||||
while (string[p] != 0) {
|
||||
buf[p] = string[p];
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int list_value(char *buf, int val) {
|
||||
int p = 0;
|
||||
p += list_char(buf + p, '$');
|
||||
if (val & (255<<16)) {
|
||||
p += list_byte(buf+p, val>>16);
|
||||
p += list_word(buf+p, val);
|
||||
} else
|
||||
if (val & (255<<8)) {
|
||||
p += list_word(buf+p, val);
|
||||
} else {
|
||||
p += list_byte(buf+p, val);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int list_nchar(char *buf, signed char c, int n) {
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
buf[i]=c;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int list_char(char *buf, signed char c) {
|
||||
buf[0] = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int list_sp(char *buf) {
|
||||
buf[0] = ' ';
|
||||
return 1;
|
||||
}
|
||||
|
||||
int list_word(char *buf, int outword) {
|
||||
buf = buf + list_byte(buf, outword >> 8);
|
||||
list_byte(buf, outword);
|
||||
return 4;
|
||||
}
|
||||
|
||||
int list_byte(char *buf, int outbyte) {
|
||||
buf = buf + list_nibble(buf, (outbyte >> 4));
|
||||
list_nibble(buf, outbyte);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int list_nibble(char *buf, int outnib) {
|
||||
outnib = outnib & 0xf;
|
||||
if (outnib < 10) {
|
||||
buf[0]='0'+outnib;
|
||||
} else {
|
||||
buf[0]='a'-10+outnib;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -21,8 +21,9 @@
|
||||
|
||||
extern int dsb_len;
|
||||
|
||||
void list_setfile(FILE *fp);
|
||||
int t_p1(signed char *s, signed char *t, int *ll, int *al);
|
||||
int t_p2(signed char *t, int *ll, int fl, int *al);
|
||||
int t_p2_l(signed char *t, int *ll, int fl, int *al);
|
||||
int b_term(char *s, int *v, int *l, int pc);
|
||||
|
||||
#endif /* __XA65_XAT_H__ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user