Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/c/fcgen/main.c
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

419 lines
7.4 KiB
C

/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
char *version "@(#) c168 code generator 4.0 - Feb 10, 1983";
#include "cgen.h"
#include "cskel.h"
char *opap;
int errflg;
int nextlabel 10000;
char *readtree();
char *readsym();
/* main - main routine, handles arguments and files*/
main(argc,argv) /* returns - none*/
int argc; /* arg count*/
char **argv; /* arg pointers*/
{
register char *q;
register int i;
#ifdef VERSADOS
lflag++;
#endif
for( i = 3; i < argc; i++ ) {
q = argv[i];
if( *q++ != '-' )
usage(argc,argv,1);
while( 1 ) {
switch( *q++ ) {
case 'D':
case 'd':
dflag++;
continue;
case 'L':
case 'l':
lflag++;
continue;
case 'E':
case 'e':
eflag++;
continue;
case 'F':
case 'f':
fflag++;
continue;
case 'M':
case 'm':
mflag++;
continue;
case 'O':
case 'o':
oflag++;
continue;
case 'C':
case 'c':
cflag++;
continue;
case '\0':
break;
default:
usage(argc,argv,2);
}
break;
}
}
if( argc < 3 )
usage(argc,argv,3);
if( fopen(argv[1],&ibuf,0) < 0 ) /* 3rd arg for versados */
ferror("can't open %s\n",argv[1]);
if( fcreat(argv[2],&obuf,0) < 0 ) /* 3rd arg for versados */
ferror("can't create %s\n",argv[2]);
readicode();
v6flush(&obuf);
exit(errcnt!=0);
}
/* readicode - read intermediate code and dispatch output*/
/* This copies assembler lines beginning with '(' to assembler*/
/* output and builds trees starting with '.' line.*/
readicode() /*returns - none*/
{
register int c;
register struct tnode *tp;
while( (c=getc(&ibuf)) > 0 ) {
switch(c) {
case '.':
lineno = readint();
opap = exprarea;
if( tp = readtree() ) {
#ifndef NODEBUG
if( cflag )
putexpr("readicode",tp);
#endif
switch( tp->t_op ) {
case INIT:
outinit(tp->t_left);
break;
case CFORREG:
outcforreg(tp->t_left);
break;
case IFGOTO:
outifgoto(tp->t_left,tp->t_type,tp->t_su);
break;
default:
outexpr(tp);
break;
}
}
break;
case '(':
while( (c=getc(&ibuf)) != '\n' )
putchar(c);
putchar(c);
break;
default:
error("intermediate code error %c,%d",c,c);
break;
}
}
}
/* readtree - recursive intermediate code tree read*/
char *readtree() /* returns ptr to expression tree*/
{
register int op, type, sc;
register struct tnode *tp, *rtp;
char sym[SSIZE];
long l;
if( (op=readint()) <= 0 )
return(0);
type = readint();
switch( op ) {
case SYMBOL:
if( (sc=readint()) == EXTERNAL )
tp = cenalloc(type,sc,readsym(sym));
else
tp = snalloc(type,sc,readint(),0,0);
break;
case CINT:
tp = cnalloc(type,readint());
break;
case CLONG:
l.hiword = readint();
l.loword = readint();
tp = lcnalloc(type,l);
break;
case CFLOAT: /* [vlh] 3.4 */
l.hiword = readint();
l.loword = readint();
tp = fpcnalloc(type,l);
break;
case IFGOTO:
case BFIELD:
sc = readint();
if( tp = readtree() )
tp = tnalloc(op,type,sc,0,tp,null);
break;
default:
if( binop(op) ) {
if( !(tp=readtree()) )
return(0);
if( !(rtp=readtree()) )
return(0);
tp = tnalloc(op,type,0,0,tp,rtp);
}
else if( tp = readtree() )
tp = tnalloc(op,type,0,0,tp,null);
break;
}
return(tp);
}
/* readint - reads an integer value from intermediate code*/
readint()
{
register int i, c;
i = 0;
while(1) {
switch( c = getc(&ibuf) ) {
case '.':
case '\n':
return(i);
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
i =<< 4;
i =+ (c-'0');
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
i =<< 4;
i =+ (c-('a'-10));
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
i =<< 4;
i =+ (c-('A'-10));
break;
default:
error("intermediate code error - %c,%d",c,c);
}
}
}
/* readsym - read a symbol from intermediate code*/
char *readsym(sym)
char *sym;
{
register int i, c;
register char *s;
for( i = SSIZE, s = sym; (c=getc(&ibuf)) != '\n'; )
if( --i >= 0 )
*s++ = c;
if( i > 0 )
*s = '\0';
return(sym);
}
/* error - output an error message*/
error(s,x1,x2,x3,x4,x5,x6)
char *s;
int x1, x2, x3, x4, x5, x6;
{
errcnt++;
errflg++;
if( lineno != 0 )
printf("** %d: ",lineno);
printf(s,x1,x2,x3,x4,x5,x6);
putchar('\n');
errflg--;
}
/* ferror - output error message and die*/
ferror(s,x1,x2,x3,x4,x5,x6)
char *s;
int x1, x2, x3, x4, x5, x6;
{
error(s,x1,x2,x3,x4,x5,x6);
exit(1);
}
/* tnalloc - allocate binary expression tree node*/
/* returns ptr to node made.*/
char *tnalloc(op,type,info,dummy,left,right)
int op; /* operator*/
int type; /* resultant node type*/
int info; /* info field*/
int dummy; /* dummy field - used to match pass1 args*/
struct tnode *left; /* left sub-tree*/
struct tnode *right; /* righst sub-tree*/
{
register struct tnode *tp;
tp = talloc(sizeof(*tp));
tp->t_op = op;
tp->t_type = type;
tp->t_su = info; /* info for bit-field & condbr's*/
tp->t_left = left;
tp->t_right = right;
return(tp);
}
/* cnalloc - allocate constant expression tree node*/
char *cnalloc(type,value) /* returns pointer to node alloced*/
int type; /* type of constant*/
int value; /* value of constant*/
{
register struct conode *cp;
cp = talloc(sizeof(*cp));
cp->t_op = CINT;
cp->t_type = type;
cp->t_value = value;
return(cp);
}
/* lcnalloc - allocate constant expression tree node*/
char *lcnalloc(type,value) /* returns pointer to node alloced*/
int type; /* type of constant*/
long value; /* value of constant*/
{
register struct lconode *cp;
cp = talloc(sizeof(*cp));
cp->t_op = CLONG;
cp->t_type = type;
cp->t_lvalue = value;
return(cp);
}
/* fpcnalloc - allocate constant expression tree node*/
char *fpcnalloc(type,value) /* returns pointer to node alloced*/
int type; /* type of constant*/
long value; /* value of constant*/
{ /* [vlh] 3.4 */
register struct lconode *cp;
cp = talloc(sizeof(*cp));
cp->t_op = CFLOAT;
cp->t_type = type;
cp->t_lvalue = value;
return(cp);
}
/* talloc - allocate expression tree area*/
char *talloc(size) /* returns pointer to area alloced*/
int size; /* number of bytes to alloc*/
{
register char *p;
p = opap;
if( p + size >= &exprarea[EXPSIZE] )
ferror("expression too complex");
opap = p + size;
return(p);
}
/* symcopy - copy symbol*/
symcopy(sym1,sym2) /* returns - none*/
char *sym1; /* from symbol*/
char *sym2; /* to symbol*/
{
register char *p, *q;
register int i;
for( p = sym1, q = sym2, i = SSIZE; --i >= 0; )
*q++ = (*p ? *p++ : '\0');
}
/* usage - ouput usage message*/
usage(argc,argv,n)
char *argv[];
{
register int i;
error("usage call #%d:\n",n);
for (i=0; i<argc; i++) error(" argv[%d] = %s\n",i,argv[i]);
ferror("usage: c168 icode asm [-DLmec]");
}
/* putchar - special version*/
/* This allows the use of printf for error messages, debugging*/
/* output and normal output.*/
putchar(c) /* returns - none*/
char c; /* character to output*/
{
if( errflg ) /*error message?*/
write(1,&c,1); /*write to standard output*/
else {
if( dflag > 1 )
write(1,&c,1); /*to standard output*/
putc(c,&obuf); /*put to assembler file*/
}
}
v6flush(v6b)
struct iobuf *v6b;
{
register i;
i = BLEN - v6b->nunused;
v6b->nunused = BLEN;
v6b->xfree = &(v6b->buff[0]);
if(write(v6b->fildes,v6b->xfree,i) != i)
return(-1);
return(0);
}