@L}5 _$% l0$)$$Hȱ$ UhL" `e$$%`$%`  R@P!( L(1   Y I`  d  Ld M * @  $ % CC$$)%1 Udߥ$9%: !0 S$% DD˙`  }J)Lr d M * @  $ % CC$$)%1 Udߥ$9%: !0 S$%} DD˙`  }J)Lr J  ((  p L ()   J}L= ( L 0q A    IB JC;? D W } LL  ` W )LA!  ߰")-݆ p" } $G@LL 08`Q")<2Q0 -G$Ș݆ UL# ; p8(()(0ʥ)NQ` }$GȘ݆LU )L ݆ L GȘ ݆LL )W>Z   HH)H }p h  hyhy D L> L JJ    ! LA*` BF }7'8  M HN H` 8 Z  \LdJJ!"! GFE@F (!L }EE !E^ ^ E E7EȩEdE/EȩE  D } .L }  ;F d  ;?F7F? ( .   Z D LL d } . D  L    p  E` , d)  D L) 0BM݊L݉} ML  N݆ L NLML [ TEqEHȱEqEh 0Gȹ G} HLL GɛL  LFREE SECTORS G) *Gȩ GȽG GȌ*jj >G} C8jJ3j2CD( C202C ԠBX` N 1? l LlD:RAMDISK}.COMLu L1 L ;LHL  T`  `1  ɐ     `TU  } L ? .  t`GBJ ~DEHI B V0dV!}QDEHI VF9 ,0 ,0 s0hhL  L` H hDHEh"}DEL8HI4 0 HI,0 0  9 .G VLO#},0 L4*IJ`llD1:AUTORUN.SYSNEED MEM.SAV TO LOAD THIS FILE.D1:MEM.SAV J y08 B|DEHI$} V0 0`B;DEL`?<0LV`@ʆ v s? F0Ξ05: [ BDEHI%} VY8 B V  @  /DE `E:D1:DUP.SYSERROR-SAVING USER MEMORY ON DISKTYPE Y TO &}STILL RUN DOS B;DE J  (` 9 V⪍ ઍ  -'}LLu ÝDEHILV 9 .l 9 .l  `` s$B BH(}I|DE V BLV nB,DE JLV B V BLVDEIʩ BꭝLu  } 3E:}DISK OPERATING SYSTEM II VERSION COPYRIGHT 1984 ATARI CORP.A. DISK DIRECTORY I. FORMAT DISKB. RUN CARTRIDG*}E J. DUPLICATE DISKC. COPY FILE K. BINARY SAVED. DELETE FILE(S) L. BINARY LOADE. RENAME FILE M. RUN AT ADDRES+}SF. LOCK FILE N. CREATE MEM.SAVG. UNLOCK FILE O. DUPLICATE FILEH. WRITE DOS FILES P. FORMAT SINGLEL !N',}#"&))9(&*)/h)''-&؆莟R'S  vL/ˢ L }Insert DOS 2.0s, type Y Λx -}DEfHI 1莏#q! @ y0ɛ8A0,' ȅ 1 1ild! 1L!NO SUCH ITEMSELECT.} ITEM OR FOR MENU! 0 .z:*{}.|{ 1 0 0JB 18L%|DL/}%DIRECTORY--SEARCH SPEC,LIST FILE?[# 0 0 &|D3" 1L!NOT A DISK FILEN !B 1L!E# 1 !BD0}ED:}:1BJ|DE 1DEBHI 1 h0ߢ 0.1}  0?詛 1 y0YЛ 1 ;#L" ;#L! BL1TYPE "Y" TO DELETE...DELETE FILE SPEC2}COPY--FROM, TO?OPTION NOT ALLOWED736 FREE SECTORS COPYING---D1:DIRECK.COMl# 0|D .L/%#3}##JB|DE 1BHID#E 1#0: B 1L!#͑### B 1#c$0SY4}S1}:## # # .#Ƚ# # 𩛙## 1,#PD#ELJ- <.BJD#E 5}1 1HH 0hh|DL%1}:̳# L% #D#EL% 1 0 . .0O% 1L!WILD CARDS NOT A6}LLOWED IN DESTINATION 0 <.|K}N 2 FORMAT. t* 5) 1L!`) 0NΞ 0 L1) 1 L!BAD LOAD FILELOAD FROM WHAT FILE?) 0 ?}0#B 1L!WHAT FILE TO LOCK?) 0 0$B 1L!WHAT FILE TO UNLOCK?DUP DISK-SOURCE,DEST DRIVES?TYPE "Y" IF OK TO US@}E PROGRAM AREACAUTION: A "Y" INVALIDATES MEM.SAV.FE! +L1   `*  70 2 2A} 0.* 1 y0 0)INSERT BOTH DISKS, TYPE RETURN^, 1 y038逍 N, 1L! ,B}C, t*  Lx+, 0 ^, 1 y0 , ,0,0 ,L+ ,I0 ,Vǭ0C}Ξ, 0 }, 1 y0C,ШC, 0K'!" H H 'h h Lx+!EF 5L1L!D,I,HhD}` NOT ENOUGH ROOMINSERT SOURCE DISK,TYPE RETURNINSERT DESTINATION DISK,TYPE RETURNE}`  `8 rL1`-* 1P* 1 y0Y`hhL!NAME OF FILE TO MOVE?- 0 0|DL% <.F},^ 1 70 0 .@L# .BJ 1  DEHIB V L1 ,} 1 70,L.  G}JB|,#P#DE 1 HI BDEHHII 1 B 1 ,^ 1 70,0La- B V,#PH},^ 1 70 0L#L!-* 1P* 1 y0Yj383}mm ݭI}}`8}``|* ? ɛ,`|:-)| / 1L!`DESTINATION CANT BE DOJ}S.SYS0 0H{ 24Δ 28/L!/) 2 Π 2 0 ξK}hAΞB,0 J 1 BDEHI,HÝDE 1HIHIDELSAVE-GIVE L}FILE,START,END(,INIT,RUN)O S0 1`BDEPHI V` S0H 1 L!M}0 0 1L~0`PLEASE TYPE 1 LETTER,0`hhL! 70 1L0L<1 ,;ɛ7,"ɛ:ݦ1ݥN}A"D|ݤD|ȩ:|ȩ|ɛ,,(/+.ީ1 1,ɛ`轤{NAMEO} TOO LONG B VL!` L1I H1EΝDL1|mDiE` V0`8d/8 i:222 1 LP}!ERROR- 138ɛ+,' 20*.. өr2 1``2TOO MANY DIGITSINVALID HEXAQ}DECIMAL PARAMETER800 0 8 00`,0'D800 H,ɛh`2L1NEED D1 THRU D8uR} ECIMAL PARAMETER800 0 8 00`,0'D800 H,ɛh`2L1NEED D1 THRU D8u /* cclex.c - lexical analyzer for compiler */ #include #ifndef M6502 /* every time I thing some C weenie someplacT}e might have opted to do something in a regular fashion, I get disappointed... */ #include #endif #include "cc65U}.h" #include "cclex.h" #define ch() (*lptr) int amp(); int bang(); int bar(); int caret(); int dollar(); int equal(); int iV}dent(); int langle(); int minus(); int number(); int percent(); int plus(); int pstr(); int qstr(); int rangle(); int slash()W}; int star(); int symbol(); #ifndef M6502 int under(); #endif int unkn(); int (*stab[128]) () = { unkn, unkn, unkn, unkn, X}unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, Y} unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, unkn, /* */ bang, /* ! */ qstr, /* " */ unkn, /* # */ Z} 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, #a}endif unkn, /* ` */ symbol, symbol, symbol, symbol, symbol, symbol, symbol, symbol, /* a - h */ symbol, symbol, symbol,b} symbol, symbol, symbol, symbol, symbol, /* i - p */ symbol, symbol, symbol, symbol, symbol, symbol, symbol, symbol, /* q -c} x */ symbol, symbol, LCURLY, bar, /* | */ RCURLY, COMP, unkn /* */ }; /* gettok() Make next toked}n current token. And read another token from the input stream. */ static char * pp_line = ";;"; static char * old_lptr; se}tatic int asm_unkludge() /* return t if still kludged */ { if (asm_kludge > 0) { if (--asm_kludge == 1) /* down tf}o 1? */ { lptr = old_lptr; /* restore old line */ doasm(); /* do the asm stuff */ kill(); } else { lptrg} = pp_line; return (1); } } return (0); } gettok() { int (*f) (); #ifdef M6502 chkbrk(); /* check for user hih}tting break key */ #endif curtok = nxttok; curval = nxtval; if (asm_unkludge()) { curtok = SEMI; returni}; } /* * pick up next token from input stream. */ while (1) { while (ch() == 0) { if (readline() j}== 0) { nxttok = CEOF; return; } preprocess(); /* kludge added by jrd. if see a #asm directive cok}ming up, force a semicolon token, to terminate previous stmt. This'll lose if you do it in the middle of something likl}e a for stmt. big deal... */ if (matchstr(lptr, "#asm")) /* see a #asm dir? */ { asm_kludge = 3; /* force 2m} semicolons */ old_lptr = lptr; lptr = pp_line; break; } } if (ch() == ' ') ++lptr; en}lse break; } #ifdef M6502 if ((nxttok = (int) stab[ch()]) & 0xFF00) #else if ((nxttok = (int) stab[ch()]) & 0xFFFFFo}F00) #endif { (*((int (*) ()) nxttok)) (); } else { ++lptr; } } #ifndef M6502 /* only grok spep}cial symbols if not native compiler */ under() { char * q; char token[NAMESIZE]; symname(token); if (token[1] == '_') q} { if (strcmp(token, "__FILE__") == 0) { nxtval = litptr; q = fin; while (*q) litq[litptr++] = *q++; r} litq[litptr++] = '\0'; nxttok = SCONST; return; } else if (strcmp(token, "__LINE__") == 0) { nxttok = ICONSs}T; nxtval = ln; return; } } nxtval = addsym(token); nxttok = IDENT; } #endif symbol() { char token[NAMESIZE]t}; symname(token); if (nxttok = Search(token)) { return; } else { nxtval = addsym(token); u} nxttok = IDENT; } } ident() { char token[NAMESIZE]; symname(token); nxtval = addsym(token); nxttok = IDENT; } /v}* util fun used by dollar(). set nxttok and bump line ptr */ rettok(tok) int tok; { nxttok = tok; ++lptr; } dollar() { w}int c; switch (c = *++lptr) { case '(': rettok(LCURLY); break; case ')': rettok(RCURLY); x} break; case '-': rettok(COMP); break; #ifdef old_cruft else if (c == '<') { gch(); nxtty}ok = 201; } else if (c == '>') { gch(); nxttok = 202; } else if (c == '+') { gch(); nxttok = 203;z} } 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; } }} slash() { if (*++lptr == '=') { rettok(DASGN); } else { nxttok = DIV; } } amp() { int c; } switch (c = *++lptr) { case '&': rettok(DAMP); break; case '=': rettok(AASGN); break; } default: nxttok = AMP; } } bar() { int c; switch (c = *++lptr) { case '|': rettok(DBAR); } break; case '=': rettok(OASGN); break; default: nxttok = BAR; } } bang() { if (*++lptr == '}=') { rettok(NE); } else { nxttok = BANG; } } equal() { if (*++lptr == '=') { rett}ok(EQ); } else { nxttok = ASGN; } } langle() { int c; switch (c = *++lptr) { case '=': }rettok(LE); break; case '<': if (*++lptr == '=') { rettok(SLASGN); } else { nxttok = ASL; } } break; default: nxttok = LT; } } rangle() { int c; switch (c = *++lptr) { case '=': rett}ok(GE); break; case '>': if (*++lptr == '=') { rettok(SRASGN); } else { nxttok = ASR; } } 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; } if (toupper(c) == 'X') { base = 16; ++lptr; /* gobble "x" */ } else { base = 8; } } while (1) } { if (isdigit(c = toupper(ch()))) { k = k * base + (c - '0'); } else if (base == 16) { if (c >= 'A' &}& c <= 'F') c -= 55; else /* if (c >= 'a' && c <= 'f') c -= 87; else */ break; /* not hex */ k} = k * base + c; } else break; /* not digit */ ++lptr; /* gobble char */ } nxtval = k; nxttok = IC}ONST; } /* pstr( val ) Parse a character constant. */ pstr() { int k; int c; k = 0; ++lptr; while ((c = cgch()) !}= 39 && c != '\0') { k = ((k & 0xFF) << 8) + parsech(c); } nxtval = k; nxttok = CCONST; } /* qstr( val )} Parse a quoted string */ qstr() { ++lptr; nxtval = litptr; nxttok = SCONST; while (ch() != '"') { if (ch}() == 0) { Error("new-line in string constant"); break; } if (litptr >= 512) { fatal("string space exhauste}d"); /* while (gch() != '"') if (ch() == 0) break; return; */ } litq[litptr++]} = parsech(gch()); } cgch(); litq[litptr++] = 0; } /* Parse a character. * converts \n into EOL, etc. */ parsech(c}hr) int chr; { int c; int i; int oct; /* pass through unless backslash */ if (chr != 92) return (chr); switch (c }= ch()) { case 'b': c = 126; break; case 'f': c = 125; break; /* CLEAR */ case 'g':} c = 253; break; /* Bell */ case 'n': c = 155; break; /* EOL */ case 't': c = 127; } break; /* TAB */ default: if (c >= '0' && c <= '7') { /* * octal (yuk) constant *}/ oct = c - '0'; gch(); i = 1; while (i <= 2) { if ((c = ch()) <'0' || c > '7') break; oct =} (oct << 3) + c - '0'; gch(); ++i; } return (oct); } } cgch(); /* skip code char */ return (}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 s }tats; int htabstats; int maxloc = 0; int tmpx, tmpy, tmpz; extern int outcnt; #endif #ifdef atarist extern long _stksize = 3 }2768; #endif struct hashent * decl(); struct hashent * declare(); /* char openerr[] = "Couldn't open: "; */ #ifdef pathope }n /* util function for opening files */ FILE * pathopen(name, ext, force, mode, truename) char * name; /* filename */ char }* ext; /* default extension */ int force; /* force extension */ char * mode; /* open mode */ char * truename; /* resultant } pathname */ { FILE * f; char * extp; strcpy(truename, name); if (!(extp = strchr(truename, '.'))) strcpy(truename + } strlen(truename), ext); else if (force) strcpy(extp, ext); if ((f = fopen(truename, mode)) <= 0) { PError( }"Can't open ", truename); PError(" mode ", mode); fatal(" Giving up"); } return(f); } #else #ifdef M6502 } 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 * fout }; #endif /* set up global heap */ #ifdef M6502 #define LOMEM 0x02E7 extern int _start; /* program start address */ }gblspace = *((char ** )LOMEM); /* start heap here */ gblend = &_start; /* end it here */ #else /* cross-compiler */ gb }lspace = malloc(GSPACE); gblend = gblspace + GSPACE; #endif #ifdef M6502 /* later, put all this stuff in a loop */ if }(argc < 2) /* under some kind of system that doesn't do args? */ argc = readargs("CC65>", argbuf, argv + 1) + 1; } #endif fin = NULL; #ifndef M6502 atari = 0; debug = 0; stats = 0; htabstats = 0; #endif for (i = 1; i < argc; i }++) { if (*(argp = argv[i]) == '-') { switch (toupper(argp[1])) { #ifndef M6502 case 'A': /* hot-wir }e M6502 def */ atari = 1; break; case 'D': /* print debug msgs */ debug = 1; break; ca }se 'S': /* print storage statistics */ stats = 1; break; case 'H': /* print hashtab stats */ htab }stats = 1; break; case 'C': /* include source as comments */ source = 1; break; #endif case ' }O': /* optimize */ optimize = 1; break; case 'V': /* verbosity */ ++verbose; break; c }ase 'I': /* where to include <> things */ incl_dir = argp + 2; break; default: printf("Invalid opt }ion %s\n", argp); } } else { #ifdef pathopen inp = pathopen(argp, ".c", 0, "r", (fin = argp)); #else fin = } frob_name(argp, (strchr(argp, '.') ? NULL : ".c"), in_name); inp = fopen(fin, "r"); #endif } } if (!fin) { } inp = stdin; fin = "stdin.c"; } #ifdef pathopen output = pathopen(fin, ".m65", 1, "w", fout); #else fout = f }rob_name(fin, ".m65", out_name); output = fopen(fout, "w"); #endif #ifndef M6502 if (!incl_dir) incl_dir = (char * )g }etenv("CC65LIB"); #endif if (verbose) printf("CC65 v 1.1\n"); compile(); clout(); } /* compile() Compiler beg }ins execution here inp is input fd, output is output fd (called multiple times from main) */ compile() { char dummy; li }tptr = /* clear literal pool */ oursp = /* stack ptr (relative) */ errcnt = /* no errors */ eof = /* not }eof yet */ ncmp = /* no open compound states */ macdef = /* no macros defined yet */ ifile = /* index into }include file array */ lovptr = /* index into local variable array */ glblbl = /* initial global label number */ } ln = /* initial line number */ 0; /* ...all set to zero.... */ filetab[0].f_iocb = inp; gsptr = gblspace; } lsptr = locspace; wqptr = wq; /* clear while queue */ outqi = outq; outqsz = OUTQSZ; glvptr = NULL; i_ifdef = } -1; litlab = /* hotwire literal pool label */ nxtlab = 1; /* #ifdef M6502 ret_addr = &dummy - 2; #endif */ bz }ero(machtab, 256); bzero(macltab, 256); bzero(htab, 256); kill(); /* empty input line */ #ifndef M6502 if (atari) } { strcpy(line, "M6502"); addmac(); kill(); } #endif /* process ALL input */ parse(); }#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 p0}ostdent.ttp : postdent.c cc -s -o postdent.ttp postdent.c indents : predent.ttp postdent.ttp $(C_SRCS) indents clean : 1}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, 3}c) if see jsr a followed by jsr b, replace with jsr c */ #ifdef smallc extern int triples[]; /* defined in ccmisc.m654} */ #else #ifdef COMMENTS char * triples[] = { "locysp", "ldaxi", "ldaxysp\t\t; Load AX from SP@(Y)", "locysp", "5}ldai", "ldaysp\t\t; Load A from SP@(Y)", "ldaxysp", "pushax", "pushwysp\t\t; Push word SP@(Y)", "ldaysp", "pushax", "pu6}shbysp\t\t; Push byte SP@(Y)", "ldaxysp", "swapsreg", "ldsrysp\t\t; Load SREG from SP@(Y)", "indexax", "ldaxi", "ldaxid7}x\t\t; Load AX from AX@(Y)", "indexax", "ldai", "ldaidx\t\t; Load A from AX@(Y)", "ldaxidx", "pushax", "pushwidx\t\t; P8}ush word at AX@(Y)", "ldaidx", "pushax", "pushbidx\t\t; Push byte at AX@(Y)", "indexax", "pushax", "plocidx\t\t; Push l9}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 ldaidA}x[] = "ldaidx"; static char pushwidx[] = "pushwidx"; static char pushbidx[] = "pushbidx"; static char plocidx[] = "plocidxB}"; static char pushwaxi[] = "pushwaxi"; static char pushbaxi[] = "pushbaxi"; static char plocysp[] = "plocysp"; char * C}triples[] = { locysp, ldaxi, ldaxysp, locysp, ldai, ldaysp, ldaxysp, pushax, pushwysp, ldaysp, pushax, pushbysp,D} /* "ldaxysp", "swapsreg", "ldsrysp", */ indexax, ldaxi, ldaxidx, indexax, ldai, ldaidx, ldaxidx, pushax, pushE}widx, ldaidx, pushax, pushbidx, indexax, pushax, plocidx, ldaxi, pushax, pushwaxi, ldai, pushax, pushbaxi, /* "pF}opsreg", "staxsreg", "staxspp", */ /* "popsreg", "stasreg", "staspp", */ locysp, pushax, plocysp, /* ldaxi, "incax1",G} "incaxi1", ldaxi, "incax2", "incaxi2", ldaxi, "decax1", "decaxi1", ldaxi, "decax2", "decaxi2", */ 0}; #endif /H}* 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] = { J}"addsreg", "subsreg", "aslsreg", "asrsreg", "andsreg", "orsreg", "xorsreg", "sregeqax", "sregneax", K} "sreggtax", "sreggeax", "sregltax", "sregleax", "sregugtax", "sregugeax", "sregultax", "sreguleax", L} NULL}; char * autotest[29] = { "staspp", "staxspp", "staxsreg", "incax1", "incax2", "decax1", "decaM}x2", "ldaxidx", "ldaidx", "ldaxi", "lnegax", "addsreg", "subsreg", "aslsreg", "asrsreg", "andsreg"N}, "orsreg", "xorsreg", "sregeqax", "sregneax", "sreggtax", "sreggeax", "sregltax", "sregleax", "srO}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!Q}g parts of the optimizer. mostly so jrd can figure out the most effective combination... */ /* #define OPT12 */ /!R}* return t if if line matches str */ #ifdef M6502 #asm .globl _matchstr _matchstr: jsr popax ; get str sta ptr1 s!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!T} cmp (ptr2),y ; compare to char from line bne match3 iny bne match1 match2: ldx #0 lda #1 rts match3: lda #!U}0 tax rts #endasm #else matchstr(line, str) char * line; char * str; { for (; *str; ++line, ++str) if (*lin!V}e != *str) return (0); return (1); } #endif /* return t if line looks like " jsr