@L}5 _$% l0$)$$Hȱ$ UhL" `e$$%`$%`  R@P!( L(1   Y I`  d  Ld M * @  $ % CC$$)%1 Udߥ$9%: !0 S$% DD˙`  }J)Lr  /* cclex.c - lexical analyzer for compiler */ #include #ifndef M6502 /* every time I thing some C weenie someplac}e might have opted to do something in a regular fashion, I get disappointed... */ #include #endif #include "cc65}.h" #include "cclex.h" #define ch() (*lptr) int amp(); int bang(); int bar(); int caret(); int dollar(); int equal(); int i}dent(); int langle(); int minus(); int number(); int percent(); int plus(); int pstr(); int qstr(); int rangle(); int slash()}; int star(); int symbol(); #ifndef M6502 int under(); #endif int unkn(); int (*stab[128]) () = { unkn, unkn, unkn, unkn, }unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, } unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, /* */ bang, /* ! */ qstr, /* " */ unkn, /* # */ } dollar, /* $ */ percent, /* % */ amp, /* & */ pstr, /* 'character const' */ LPAREN, /* ( */ RPAREN, /* ) }*/ star, /* * */ plus, /* + */ COMMA, /* , */ minus, /* - */ DOT, /* . */ slash, /* / */ number, numbe }r, number, number, number, /* 0 - 4 */ number, number, number, number, number, /* 5 - 9 */ COLON, SEMI, langle, /* <} */ equal, /* = */ rangle, /* > */ QUEST, unkn, ident, ident, ident, ident, ident, ident, ident, ident, /* A - H }*/ ident, ident, ident, ident, ident, ident, ident, ident, /* I - P */ ident, ident, ident, ident, ident, ident, ident, i}dent, /* Q - X */ ident, ident, LBRACK, unkn, /* \ */ RBRACK, caret, /* ^ */ #ifndef M6502 /* only include this }in cross compiler */ under, /* _ */ #else /* save space by not treating underbars special in native compiler */ ident, #}endif unkn, /* ` */ symbol, symbol, symbol, symbol, symbol, symbol, symbol, symbol, /* a - h */ symbol, symbol, symbol,} symbol, symbol, symbol, symbol, symbol, /* i - p */ symbol, symbol, symbol, symbol, symbol, symbol, symbol, symbol, /* q -} x */ symbol, symbol, LCURLY, bar, /* | */ RCURLY, COMP, unkn /* */ }; /* gettok() Make next toke}n current token. And read another token from the input stream. */ static char * pp_line = ";;"; static char * old_lptr; s}tatic int asm_unkludge() /* return t if still kludged */ { if (asm_kludge > 0) { if (--asm_kludge == 1) /* down t}o 1? */ { lptr = old_lptr; /* restore old line */ doasm(); /* do the asm stuff */ kill(); } else { lptr} = pp_line; return (1); } } return (0); } gettok() { int (*f) (); #ifdef M6502 chkbrk(); /* check for user hi}tting break key */ #endif curtok = nxttok; curval = nxtval; if (asm_unkludge()) { curtok = SEMI; return}; } /* * pick up next token from input stream. */ while (1) { while (ch() == 0) { if (readline() }== 0) { nxttok = CEOF; return; } preprocess(); /* kludge added by jrd. if see a #asm directive co}ming up, force a semicolon token, to terminate previous stmt. This'll lose if you do it in the middle of something lik}e a for stmt. big deal... */ if (matchstr(lptr, "#asm")) /* see a #asm dir? */ { asm_kludge = 3; /* force 2} semicolons */ old_lptr = lptr; lptr = pp_line; break; } } if (ch() == ' ') ++lptr; e}lse break; } #ifdef M6502 if ((nxttok = (int) stab[ch()]) & 0xFF00) #else if ((nxttok = (int) stab[ch()]) & 0xFFFFF }F00) #endif { (*((int (*) ()) nxttok)) (); } else { ++lptr; } } #ifndef M6502 /* only grok spe!}cial symbols if not native compiler */ under() { char * q; char token[NAMESIZE]; symname(token); if (token[1] == '_') "} { if (strcmp(token, "__FILE__") == 0) { nxtval = litptr; q = fin; while (*q) litq[litptr++] = *q++; #} litq[litptr++] = '\0'; nxttok = SCONST; return; } else if (strcmp(token, "__LINE__") == 0) { nxttok = ICONS$}T; nxtval = ln; return; } } nxtval = addsym(token); nxttok = IDENT; } #endif symbol() { char token[NAMESIZE]%}; symname(token); if (nxttok = Search(token)) { return; } else { nxtval = addsym(token); &} nxttok = IDENT; } } ident() { char token[NAMESIZE]; symname(token); nxtval = addsym(token); nxttok = IDENT; } /'}* util fun used by dollar(). set nxttok and bump line ptr */ rettok(tok) int tok; { nxttok = tok; ++lptr; } dollar() { (}int c; switch (c = *++lptr) { case '(': rettok(LCURLY); break; case ')': rettok(RCURLY); )} break; case '-': rettok(COMP); break; #ifdef old_cruft else if (c == '<') { gch(); nxtt*}ok = 201; } else if (c == '>') { gch(); nxttok = 202; } else if (c == '+') { gch(); nxttok = 203;+} } else if (c == '#') { gch(); nxttok = 204; } #endif default: unkn(); } } plus() { int c; s,}witch (c = *++lptr) { case '+': rettok(INC); break; case '=': rettok(PASGN); break; d-}efault: nxttok = PLUS; } } minus() { int c; switch (c = *++lptr) { case '-': rettok(DEC); b.}reak; case '=': rettok(SASGN); break; case '>': rettok(PREF); break; default: nxtto/}k = MINUS; } } star() { if (*++lptr == '=') { rettok(MASGN); } else { nxttok = STAR; } }0} slash() { if (*++lptr == '=') { rettok(DASGN); } else { nxttok = DIV; } } amp() { int c; 1} switch (c = *++lptr) { case '&': rettok(DAMP); break; case '=': rettok(AASGN); break; 2} default: nxttok = AMP; } } bar() { int c; switch (c = *++lptr) { case '|': rettok(DBAR); 3} break; case '=': rettok(OASGN); break; default: nxttok = BAR; } } bang() { if (*++lptr == '4}=') { rettok(NE); } else { nxttok = BANG; } } equal() { if (*++lptr == '=') { rett5}ok(EQ); } else { nxttok = ASGN; } } langle() { int c; switch (c = *++lptr) { case '=': 6}rettok(LE); break; case '<': if (*++lptr == '=') { rettok(SLASGN); } else { nxttok = ASL; } 7} break; default: nxttok = LT; } } rangle() { int c; switch (c = *++lptr) { case '=': rett8}ok(GE); break; case '>': if (*++lptr == '=') { rettok(SRASGN); } else { nxttok = ASR; } 9} break; default: nxttok = GT; } } caret() { if (*++lptr == '=') { rettok(XOASGN); } else :} { nxttok = XOR; } } percent() { if (*++lptr == '=') { rettok(MOASGN); } else { nxttok;} = MOD; } } /* issym( s ) Get symbol from input stream or return 0 if not a symbol. */ issym(s) char * s; { /* ex<}tern char ascii_tab[128]; */ if (is_alpha(ch())) { symname(s); return (1); } else { return=} (0); } } /* symname( s ) Get symbol from input stream or return 0 if not a symbol. */ symname(s) char * s; { /* >}extern char ascii_tab[128]; */ int k; k = 0; do { if (k != NAMEMAX) { ++k; *s++ = * lptr++; } else?} { ++lptr; } } while (is_alpha(ch()) || isdigit(ch())); *s = '\0'; } number() { int base; char c; int k; @}k = 0; base = 10; if (ch() == '0') { /* * gobble 0 and examin next char */ c = *++lptr; A} if (toupper(c) == 'X') { base = 16; ++lptr; /* gobble "x" */ } else { base = 8; } } while (1) B} { if (isdigit(c = toupper(ch()))) { k = k * base + (c - '0'); } else if (base == 16) { if (c >= 'A' &C}& c <= 'F') c -= 55; else /* if (c >= 'a' && c <= 'f') c -= 87; else */ break; /* not hex */ kD} = k * base + c; } else break; /* not digit */ ++lptr; /* gobble char */ } nxtval = k; nxttok = ICE}ONST; } /* pstr( val ) Parse a character constant. */ pstr() { int k; int c; k = 0; ++lptr; while ((c = cgch()) !F}= 39 && c != '\0') { k = ((k & 0xFF) << 8) + parsech(c); } nxtval = k; nxttok = CCONST; } /* qstr( val )G} Parse a quoted string */ qstr() { ++lptr; nxtval = litptr; nxttok = SCONST; while (ch() != '"') { if (chH}() == 0) { Error("new-line in string constant"); break; } if (litptr >= 512) { fatal("string space exhausteI}d"); /* while (gch() != '"') if (ch() == 0) break; return; */ } litq[litptr++]J} = parsech(gch()); } cgch(); litq[litptr++] = 0; } /* Parse a character. * converts \n into EOL, etc. */ parsech(cK}hr) int chr; { int c; int i; int oct; /* pass through unless backslash */ if (chr != 92) return (chr); switch (c L}= ch()) { case 'b': c = 126; break; case 'f': c = 125; break; /* CLEAR */ case 'g':M} c = 253; break; /* Bell */ case 'n': c = 155; break; /* EOL */ case 't': c = 127; N} break; /* TAB */ default: if (c >= '0' && c <= '7') { /* * octal (yuk) constant *O}/ oct = c - '0'; gch(); i = 1; while (i <= 2) { if ((c = ch()) <'0' || c > '7') break; oct =P} (oct << 3) + c - '0'; gch(); ++i; } return (oct); } } cgch(); /* skip code char */ return (Q}c); } unkn() { fatal("unknown character"); } } return (oct); } } cgch(); /* skip code char */ return (0 /* CC65 main program */ #include #include "cclex.h" #include "cc65.h" #ifndef M6502 int atari; int debug; int sS}tats; int htabstats; int maxloc = 0; int tmpx, tmpy, tmpz; extern int outcnt; #endif #ifdef atarist extern long _stksize = 3T}2768; #endif struct hashent * decl(); struct hashent * declare(); /* char openerr[] = "Couldn't open: "; */ #ifdef pathopeU}n /* util function for opening files */ FILE * pathopen(name, ext, force, mode, truename) char * name; /* filename */ char V}* ext; /* default extension */ int force; /* force extension */ char * mode; /* open mode */ char * truename; /* resultantW} pathname */ { FILE * f; char * extp; strcpy(truename, name); if (!(extp = strchr(truename, '.'))) strcpy(truename +X} strlen(truename), ext); else if (force) strcpy(extp, ext); if ((f = fopen(truename, mode)) <= 0) { PError(Y}"Can't open ", truename); PError(" mode ", mode); fatal(" Giving up"); } return(f); } #else #ifdef M6502 Z} char * frob_name(name, ext, buf) char * name; char * ext; char * buf; { char tmp[40]; char * p; if (!strchr(name, ':'[})) /* no device? */ { strcpy(tmp, "D:"); strcat(tmp, name); } else strcpy(tmp, name); if (ext) \} { if (p = strchr(tmp, '.')) *p = '\0'; strcat(tmp, ext); } strcpy(buf, tmp); return(buf); } #else cha]}r * frob_name(name, ext, buf) char * name; char * ext; char * buf; { char * p = strchr(name, '.'); if (ext) { if^} (p) *p = '\0'; } strcpy(buf, name); if (ext) strcat(buf, ext); return(buf); } #endif #endif static char arg_}buf[40]; static char * argp; #ifdef M6502 char in_name[20]; char out_name[20]; #else char in_name[80]; char out_name[80]; #e`}ndif #undef NOARGC main(argc, argv) int argc; char ** argv; { int i; #ifdef pathopen char fout[20]; #else char * fouta}; #endif /* set up global heap */ #ifdef M6502 #define LOMEM 0x02E7 extern int _start; /* program start address */ b}gblspace = *((char ** )LOMEM); /* start heap here */ gblend = &_start; /* end it here */ #else /* cross-compiler */ gbc}lspace = malloc(GSPACE); gblend = gblspace + GSPACE; #endif #ifdef M6502 /* later, put all this stuff in a loop */ if d}(argc < 2) /* under some kind of system that doesn't do args? */ argc = readargs("CC65>", argbuf, argv + 1) + 1;e} #endif fin = NULL; #ifndef M6502 atari = 0; debug = 0; stats = 0; htabstats = 0; #endif for (i = 1; i < argc; if}++) { if (*(argp = argv[i]) == '-') { switch (toupper(argp[1])) { #ifndef M6502 case 'A': /* hot-wirg}e M6502 def */ atari = 1; break; case 'D': /* print debug msgs */ debug = 1; break; cah}se 'S': /* print storage statistics */ stats = 1; break; case 'H': /* print hashtab stats */ htabi}stats = 1; break; case 'C': /* include source as comments */ source = 1; break; #endif case 'j}O': /* optimize */ optimize = 1; break; case 'V': /* verbosity */ ++verbose; break; ck}ase 'I': /* where to include <> things */ incl_dir = argp + 2; break; default: printf("Invalid optl}ion %s\n", argp); } } else { #ifdef pathopen inp = pathopen(argp, ".c", 0, "r", (fin = argp)); #else fin =m} frob_name(argp, (strchr(argp, '.') ? NULL : ".c"), in_name); inp = fopen(fin, "r"); #endif } } if (!fin) { n} inp = stdin; fin = "stdin.c"; } #ifdef pathopen output = pathopen(fin, ".m65", 1, "w", fout); #else fout = fo}rob_name(fin, ".m65", out_name); output = fopen(fout, "w"); #endif #ifndef M6502 if (!incl_dir) incl_dir = (char * )gp}etenv("CC65LIB"); #endif if (verbose) printf("CC65 v 1.1\n"); compile(); clout(); } /* compile() Compiler begq}ins execution here inp is input fd, output is output fd (called multiple times from main) */ compile() { char dummy; lir}tptr = /* clear literal pool */ oursp = /* stack ptr (relative) */ errcnt = /* no errors */ eof = /* not s}eof yet */ ncmp = /* no open compound states */ macdef = /* no macros defined yet */ ifile = /* index into t}include file array */ lovptr = /* index into local variable array */ glblbl = /* initial global label number */ u} ln = /* initial line number */ 0; /* ...all set to zero.... */ filetab[0].f_iocb = inp; gsptr = gblspace; v} lsptr = locspace; wqptr = wq; /* clear while queue */ outqi = outq; outqsz = OUTQSZ; glvptr = NULL; i_ifdef =w} -1; litlab = /* hotwire literal pool label */ nxtlab = 1; /* #ifdef M6502 ret_addr = &dummy - 2; #endif */ bzx}ero(machtab, 256); bzero(macltab, 256); bzero(htab, 256); kill(); /* empty input line */ #ifndef M6502 if (atari)y} { strcpy(line, "M6502"); addmac(); kill(); } #endif /* process ALL input */ parse(); z}#ifndef M6502 /* Dump global symbols */ dumpglbs(); /* Dump struct/unions */ dumpstruct(); #endif /{}* Dump literal pool. */ dumplits(); /* Dump external names. */ dumpnams(); #ifndef M6502 if (stats) |} { struct hashent * p; int cnt; for (cnt = 0, p = glvptr; p != NULL; p = p->h_link) ++cnt; printf("\n%d globa}}ls, space used: %d bytes\n", cnt, gsptr - gblspace); printf("Max local space used: %d bytes\n", maxloc); printf("~}Literal space used: %d bytes\n", litspace); printf("Object file: %d bytes\n", outcnt); printf("hash: %d calls, %d} bytes\n", tmpx, tmpy); } if (htabstats) { int i; struct hashent * p; char * q; printf("\n\nSymbol Hash Tabl}e Summary\n"); for (i = 0; i < 128; ++i) { printf("%3d : ", i); if (htab[i]) { for (p = htab[i]; p !}= NULL; p = p->h_ptr) { printf("%s ", p->h_name); } printf("\n"); } else { printf("empty\n}"); } } printf("\n\nMacro Hash Table Summary\n"); for (i = 0; i < 128; ++i) { printf("%3d : ", i); i}f (machtab[i]) { for (q = machtab[i]; q != NULL; q = *((char ** )q)) { printf("%s ", q + sizeof(char *)); } } printf("\n"); } else { printf("empty\n"); } } } #endif ersum(); } /* parse() Pro}cess all input text At this level, only static declarations, defines, includes, and function definitions are legal.... *}/ parse() { int comma; struct hashent * psym; struct hashent * sadr; int sc; char tarray[MAXTYPELEN]; int tmpsc; int type; } gettok(); /* "prime" the pump */ gettok(); while (curtok != CEOF) { /* #ifdef M6502 abtchk(); #endif */ sc }= getsclass(0, SC_EXTERN | SC_STATIC); type = gettype(T_INT, &sadr); if (curtok == SEMI) { gettok(); cont}inue; } comma = 0; while (1) { absdecl = 0; if ((psym = declare(tarray, type, sadr)) == NULL) { } gettok(); break; } if ((tarray[0] != T_FUNC) && ((sc & SC_DEFAULT) || !(sc & SC_EXTERN))) { } tmpsc = sc | SC_DEFINED | SC_STORAGE; } else { tmpsc = sc; } addglb(psym, tarray, tmpsc); } if (tmpsc & SC_STORAGE) { /* outcdf(psym->h_gdata); */ outgblc(psym->h_gdata); /* -- jrd */ if (curtok} == ASGN) { gettok(); parseinit(psym->h_gtptr); } else { outsp(SizeOf(psym->h_gtptr)); } } } if (curtok != COMMA) break; gettok(); comma = 1; } if (curtok == CEOF) { break; } else if (cu}rtok == SEMI) { gettok(); } else { /* Possible function. */ if (comma) { } Syntax(); } if (tarray[0] != T_FUNC) { Illegal("function"); } if (psym != NULL) { ne}wfunc(psym); } #ifndef M6502 /* print local symbols. */ dumploc(psym); #endif eraseloc()}; } } } /* declare( ptyp, type ) Construct a type array. */ struct hashent * declare(ptyp, type, sadr) char * ptyp; }int type; struct hashent * sadr; { struct hashent * psym; psym = decl(&ptyp); if (type & T_STRUCT) { /* jrd hacked t}his part */ #ifdef M6502 encode(ptyp, sadr); /* the old way */ #else encode(ptyp, (int )sadr - (int )gblspace); /}* encode offset in glb mem */ #endif *ptyp |= type; ptyp += 3; } else { *ptyp++ = type; } }*ptyp = '\0'; return (psym); } /* decl() Process declarators. */ struct hashent * decl(ptyp) char ** ptyp; { struct expe}nt lval; struct hashent * psym; int sz; if (curtok == STAR) { gettok(); psym = decl(ptyp); *(*ptyp)+}+ = T_PTR; return(psym); } else if (curtok == LPAREN) { gettok(); psym = decl(ptyp); needbr}ack(RPAREN); } else { if (absdecl) { psym = NULL; } else if (curtok == IDENT) { gettok(); p}sym = (struct hashent * )curval; } else { Syntax(); return(NULL); } } while (curtok == LBRACK || curtok} == LPAREN) { if (curtok == LPAREN) { gettok(); funargs(); *(*ptyp)++ = T_FUNC; } else { getto}k(); sz = 0; if (curtok != RBRACK) { constexp(&lval); sz = lval.e_const; } needbrack(RBRACK)}; *(*ptyp)++ = T_ARRAY; encode(*ptyp, sz); *ptyp += 3; } } return(psym); } /* getsclass( lv, dflt ) Proces}s "" */ int getsclass(lv, dflt) int lv; int dflt; { #ifdef old_cruft if (curtok == EXTERN) { getto}k(); return(SC_EXTERN | SC_STATIC); } else if (curtok == STATIC) { gettok(); return(SC_STATIC); } } #ifndef M6502 /* save a little space */ else if (curtok == AUTO) { gettok(); if (lv == 0) { Warnin}g("auto not allowed here"); return (SC_STATIC); } return(SC_STACK); } #endif else { if (curtok == R}EGISTER) { gettok(); } return(dflt | SC_DEFAULT); } #else switch (curtok) { case EXTERN: { g}ettok(); return(SC_EXTERN | SC_STATIC); break; } case STATIC: { gettok(); return(SC_STATIC); break; } } #ifndef M6502 /* save a little space */ case AUTO: { gettok(); if (lv == 0) { Warning("auto not allow}ed here"); return(SC_STATIC); } return(SC_STACK); } #endif case REGISTER: { gettok(); /* and fall }thru... */ } default: return(dflt | SC_DEFAULT); } #endif } /* gettype( dflt ) Process "" */ int} gettype(dflt, sptr) int dflt; struct hashent ** sptr; { int sindex; int strtype; int sz; int type; switch (curtok}) { case CHAR: gettok(); return(T_CHAR); case LONG: Warning("long == short"); /* fall thr}ough */ case SHORT: if (nxttok == INT) gettok(); /* fall through */ case INT: gettok(); retu}rn(T_INT); case UNSIGNED: gettok(); if (curtok == CHAR) { gettok(); return(T_UCHAR); } if (curt}ok == INT) gettok(); return(T_UINT); case STRUCT: case UNION: strtype = curtok == STRUCT ? T_STRUCT : T_}UNION; gettok(); if (curtok == IDENT) { *sptr = (struct hashent * )curval; gettok(); } else { *}sptr = (struct hashent * )Gmalloc(sizeof(struct hashent)); bzero(*sptr, sizeof(struct hashent)); } sz = declstruct(}*sptr, strtype); addstag(*sptr, sz); return(strtype); #ifndef M6502 /* leave enums out of native compiler, }to save space */ case ENUM: gettok(); needtok(IDENT, "tag"); declenum(); return(T_INT); #endif } default: if (dflt < 0) { Missing("type"); } return(dflt); } } #ifndef M6502 /* declenum() Process b}ody of enum. */ declenum() { int enumval; struct expent lval; struct hashent * psym; if (curtok != LCURLY) { ret}urn; } gettok(); enumval = 0; while (curtok != RCURLY) { if (curtok != IDENT) { Missing("identifier")}; continue; } psym = (struct hashent * )curval; gettok(); if (curtok == ASGN) { gettok(); conste}xp(&lval); enumval = lval.e_const; } addglb(psym, type_int, SC_ENUM); psym->h_gdata = enumval++; if (cu}rtok != COMMA) break; gettok(); } needbrack(RCURLY); } #endif /* declstruct() Process body of struct/union d}eclaration. */ int declstruct(last, strtype) struct hashent * last; int strtype; { int offset; struct hashent * psym; struct }hashent * sadr; int sz; char tarray[MAXTYPELEN]; int type; if (curtok != LCURLY) { return(0); } gettok(); } sz = 0; while (curtok != RCURLY) { type = gettype(-1, &sadr); while (1) { absdecl = 0; psym = decl}are(tarray, type, sadr); last->h_link = psym; last = psym; offset = strtype == T_STRUCT ? sz : 0; addsfld(psym, }tarray, offset); offset = SizeOf(tarray); if (strtype == T_STRUCT) { sz += offset; } else { } if (offset > sz) sz = offset; } if (curtok != COMMA) break; gettok(); } ns(); } gettok()}; return(sz); } #ifndef M6502 /* ptype( psym, tarray ) Output translation of type array. */ ptype(psym, tarray) struct h}ashent * psym; char * tarray; { char * p; printf("%s: ", psym ? psym->h_name : "<>"); for (p = tarray; *p != '\0'; ++p}) { if (*p & T_STRUCT) { /* jrd here ... printf("struct/union of %s\n", ((struct hashent * )decode(}p))->h_name); */ printf("struct/union of %s\n", ((struct hashent * )(((int) decode(p) + (int) gblspace)))->h_name); } p += 2; } else { if (*p & T_UNSIGNED) { printf("unsigned "); } switch (*p) { case T}_CHAR: case T_UCHAR: printf("char\n"); break; case T_INT: case T_UINT: printf("int\n"); } break; case T_SHORT: printf("short\n"); break; case T_LONG: printf("long\n"); bre}ak; case T_FLOAT: printf("float\n"); break; case T_DOUBLE: printf("double\n"); break; } case T_PTR: printf("ptr to "); break; case T_ARRAY: printf("array[%d] of ", decode(p + 1)); } p += 3; break; case T_FUNC: printf("function returning "); break; default: printf("}unknown type: %X\n", *p); } } } } #endif /* Dump the literal pool */ dumplits() { int k; /* if nothing ther}e, exit...*/ if (litptr == 0) return; /* print literal label */ /* outcdf(LITLAB); */ outcdf(litlab); /* data fo}r next n bytes */ /* outdat(litptr); */ /* init an index... */ /* k = 0; /* while (k < litptr) /* to loop with */ /* o}utbyte(litq[k++]); */ outbv(litq, litptr); litspace += litptr; /* account for space */ litlab = getlabel(); /* get} next lit pool label */ litptr = 0; } /* clout() Flush the output buffer and close the output file. */ clout() { #ifdef }old_cruft int len; if ((len = outqi - outq) != 0) { ciov(output, 11, outq, len, -1, -1); } #else /* char} * p; for (p = outq; p != outqi; ++p) cout(*p); */ flushout(); #endif /* fclose(output); */ cclose(output); } #i}fdef old_cruft /* abtchk() check if user pressed break */ abtchk() { #ifdef M6502 char i; if (peek(17)) return; pok}e(17, 255); i = 8; while (i > 1) cclose(--i); usr(dpeek(10)); /* jmp (DOS) */ #endif } #endif #ifdef old_cruft /*} fast() Turn off screen, turn on CRITIC for speed. */ fast() { poke(SDMCTL, 0); poke(CRITIC, 0xff); critic = 0xff; } } /* slow() Return screen and CRITIC to normal. */ slow() { poke(SDMCTL, 0x22); poke(CRITIC, 0); critic = 0; } #endif} /* slow() Return screen and CRITIC to normal. */ slow() { poke(SDMCTL, 0x22); poke(CRITIC, 0); critic = 0; } #endif# # Makefile for CC65.COM. # .SUFFIXES: .com .ttp .o .obj .m65 .c .c.m65: cc65 -O -a $< xopt $*.m65 .m65.obj: ra65 -o $}@ ccpage0.m65 $< C_SRCS = code-gen.c error.c expr1.c expr2.c expr3.c function.c glb.c \ globlvar.c io.c lexer.c main.c opta}b1.c optab2.c optimize.c preproc.c \ rwords.c stmt1.c stmt2.c symtab.c H_SRCS = cc65.h cclex.h disclaim.h M65_FILES = ccm}isc.m65 extra.m65 rtextra.m65 xobj.m65 OBJS = code-gen.obj error.obj expr1.obj expr2.obj expr3.obj function.obj \ glb.obj g}loblvar.obj io.obj lexer.obj main.obj optab1.obj optab2.obj \ optimize.obj preproc.obj rwords.obj stmt1.obj stmt2.obj symtab}.obj \ ccmisc.obj extra.obj rtextra.obj xobj.obj cc65.com : $(OBJS) link65 -v -b2600 -m -o cc65.com runtime.obj $(OBJS) c.}olb $(OBJS) : $(H_SRCS) cc65-src.arc: $(C_SRCS) $(H_SRCS) $(M65_FILES) makefile make8 copyleft.jrd \ changelo arc u cc65}-src $^ clean : Rm $(OBJS) 5-src.arc: $(C_SRCS) $(H_SRCS) $(M65_FILES) makefile make8 copyleft.jrd \ changelo arc u cc65# # Makefile for cross-compiler version of CC65. # CFLAGS = -g -O C_SRCS = code-gen.c error.c expr1.c expr2.c expr3.c funct }ion.c glb.c \ globlvar.c io.c lexer.c main.c optab1.c optab2.c optimize.c \ preproc.c rwords.c stmt1.c stmt2.c symtab.c H }_SRCS = cc65.h cclex.h OBJS = code-gen.o error.o expr1.o expr2.o expr3.o function.o glb.o globlvar.o \ io.o lexer.o main.o } optab1.o optab2.o optimize.o preproc.o rwords.o \ stmt1.o stmt2.o symtab.o XOBJS = cruft.o all : cc65.ttp xopt.ttp preden }t.ttp postdent.ttp cc65.ttp : $(OBJS) $(XOBJS) ld -s -o cc65.ttp $(GNULIB)\gcrt0.o $(OBJS) $(XOBJS) -lgnu # cc -s -o cc65. }ttp $(OBJS) $(XOBJS) cc65.sym : cc65.ttp sym-ld -o cc65.sym $(GNULIB)\gcrt0.o $(OBJS) $(XOBJS) -lgnu $(OBJS) : $(H_SRCS) }$(XOBJS) : $(H_SRCS) xopt.ttp : xopt.c cc -s -o xopt.ttp xopt.c predent.ttp : predent.c cc -s -o predent.ttp predent.c p }ostdent.ttp : postdent.c cc -s -o postdent.ttp postdent.c indents : predent.ttp postdent.ttp $(C_SRCS) indents clean : }Rm *.o *.bak *.tmp ent.c cc -s -o postdent.ttp postdent.c indents : predent.ttp postdent.ttp $(C_SRCS) indents clean :  /* table of triples for optimizer. see optimize.c */ #define NULL 0 /* triples for generic optimizer. given (a, b, }c) if see jsr a followed by jsr b, replace with jsr c */ #ifdef smallc extern int triples[]; /* defined in ccmisc.m65} */ #else #ifdef COMMENTS char * triples[] = { "locysp", "ldaxi", "ldaxysp\t\t; Load AX from SP@(Y)", "locysp", "}ldai", "ldaysp\t\t; Load A from SP@(Y)", "ldaxysp", "pushax", "pushwysp\t\t; Push word SP@(Y)", "ldaysp", "pushax", "pu}shbysp\t\t; Push byte SP@(Y)", "ldaxysp", "swapsreg", "ldsrysp\t\t; Load SREG from SP@(Y)", "indexax", "ldaxi", "ldaxid}x\t\t; Load AX from AX@(Y)", "indexax", "ldai", "ldaidx\t\t; Load A from AX@(Y)", "ldaxidx", "pushax", "pushwidx\t\t; P}ush word at AX@(Y)", "ldaidx", "pushax", "pushbidx\t\t; Push byte at AX@(Y)", "indexax", "pushax", "plocidx\t\t; Push l}ocation AX@(Y)", "ldaxi", "pushax", "pushwaxi\t\t; Push word at AX@", "ldai", "pushax", "pushbaxi\t\t; Push byte at AX@}", "popsreg", "staxsreg", "staxspp\t\t; Store AX thru (SP)@+", "popsreg", "stasreg", "staspp\t\t; Store A thru (SP)@+",} "locysp", "pushax", "plocysp\t\t; Push location SP@(Y)", "ldaxi", "incax1", "incaxi1\t\t; Ldax indirect and inc", "}ldaxi", "incax2", "incaxi2\t\t; Ldax indirect and inc", "ldaxi", "decax1", "decaxi1\t\t; Ldax indirect and dec", "ldaxi}", "decax2", "decaxi2\t\t; Ldax indirect and dec", 0}; #else /* save a little space by avoiding duplicates of string kon}sts */ static char locysp[] = "locysp"; static char ldaxi[] = "ldaxi"; static char ldaxysp[] = "ldaxysp"; static char l}dai[] = "ldai"; static char ldaysp[] = "ldaysp"; static char pushax[] = "pushax"; static char pushwysp[] = "pushwysp"; st}atic char pushbysp[] = "pushbysp"; static char indexax[] = "indexax"; static char ldaxidx[] = "ldaxidx"; static char ldaid}x[] = "ldaidx"; static char pushwidx[] = "pushwidx"; static char pushbidx[] = "pushbidx"; static char plocidx[] = "plocidx}"; static char pushwaxi[] = "pushwaxi"; static char pushbaxi[] = "pushbaxi"; static char plocysp[] = "plocysp"; char * }triples[] = { locysp, ldaxi, ldaxysp, locysp, ldai, ldaysp, ldaxysp, pushax, pushwysp, ldaysp, pushax, pushbysp,} /* "ldaxysp", "swapsreg", "ldsrysp", */ indexax, ldaxi, ldaxidx, indexax, ldai, ldaidx, ldaxidx, pushax, push}widx, ldaidx, pushax, pushbidx, indexax, pushax, plocidx, ldaxi, pushax, pushwaxi, ldai, pushax, pushbaxi, /* "p}opsreg", "staxsreg", "staxspp", */ /* "popsreg", "stasreg", "staspp", */ locysp, pushax, plocysp, /* ldaxi, "incax1",} "incaxi1", ldaxi, "incax2", "incaxi2", ldaxi, "decax1", "decaxi1", ldaxi, "decax2", "decaxi2", */ 0}; #endif /}* comments */ #endif /* smallc */ axi2", ldaxi, "decax1", "decaxi1", ldaxi, "decax2", "decaxi2", */ 0}; #endif /$ #ifdef AUTOPOP /* table of auto-frobs for optimizer. see optimize.c */ #define NULL 0 char * autopop[18] = { }"addsreg", "subsreg", "aslsreg", "asrsreg", "andsreg", "orsreg", "xorsreg", "sregeqax", "sregneax", } "sreggtax", "sreggeax", "sregltax", "sregleax", "sregugtax", "sregugeax", "sregultax", "sreguleax", } NULL}; char * autotest[29] = { "staspp", "staxspp", "staxsreg", "incax1", "incax2", "decax1", "deca}x2", "ldaxidx", "ldaidx", "ldaxi", "lnegax", "addsreg", "subsreg", "aslsreg", "asrsreg", "andsreg"}, "orsreg", "xorsreg", "sregeqax", "sregneax", "sreggtax", "sreggeax", "sregltax", "sregleax", "sr}egugtax", "sregugeax", "sregultax", "sreguleax", NULL}; #endif reggeax", "sregltax", "sregleax", "srO /* all this stuff is new for the 6502 version */ #include #include "cc65.h" /* flags for enabling/disablin}g parts of the optimizer. mostly so jrd can figure out the most effective combination... */ /* #define OPT12 */ /}* return t if if line matches str */ #ifdef M6502 #asm .globl _matchstr _matchstr: jsr popax ; get str sta ptr1 s}tx ptr1+1 jsr popax ; get line sta ptr2 stx ptr2+1 ldy #0 match1: lda (ptr1),y ; get a char from str beq match2} cmp (ptr2),y ; compare to char from line bne match3 iny bne match1 match2: ldx #0 lda #1 rts match3: lda #}0 tax rts #endasm #else matchstr(line, str) char * line; char * str; { for (; *str; ++line, ++str) if (*lin}e != *str) return (0); return (1); } #endif /* return t if line looks like " jsr