@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 /* global defs for CC65 */ #define NULL 0 /* added by jrd. don't generate arg counts here */ #define NOARGC /* ... and geT}nerate entries with fixed arg counts */ #define FIXARGC #ifdef M6502 #define EOL 155 #define TABCHAR 127 #else #define EOL 'U}\n' #define TABCHAR '\t' #endif /* #define CRITIC 0x42 #define SDMCTL 0x22F #define DMACTL 0xD400 #define CH 0x2FC #defiV}ne MEMLO 0x2E7 */ #define HTABSZ 128 #define MACARGSZ 64 #define MAXFILES 3 #define MAXTYPELEN 30 #define N_IFDEF 5 /* #dW}efine LITLAB 1 */ extern int litlab; /* current one */ extern int litspace; /* total string space used */ #ifdef M6502 /X}* native compiler */ /* #define GSPACE 7000 */ /* #define GSPACE 2200 -- now it's dynamically allocated */ #define LSPACE Y}256 #define HTSTART 0x0500 #define MASTART 0x0480 #define MHTSTART 0x0600 #define OUTQSZ 500 /* declare some vars to be Z}on page 0. see ccpage0.m65 */ #define CCPAGE0 1 #else /* cross-compiler... */ #define GSPACE 10000 #define LSPACE 4800 #[}define OUTQSZ 8000 #define printmsg printf #endif /* * storage classes */ #define SC_STATIC 0x00 #define SC_STACK 0x01 \}#define SC_STORAGE 0x02 #define SC_ONSTACK 0x03 #define SC_INMEM 0x02 #define SC_DEFINED 0x04 #define SC_EXTERN 0x08 #define ]}SC_ENUM 0x10 #define SC_DEFAULT 0x40 #define SC_STRUCT 0x80 #define SC_SFLD 0x80 #define SC_STAG 0x81 /* data types */ ^}#define T_END '\0' #define T_CHAR 0x11 #define T_INT 0x12 #define T_SHORT 0x13 #define T_LONG 0x14 #define T_ENUM 0x15 _}#define T_UCHAR 0x19 #define T_UINT 0x1A #define T_FLOAT 0x25 #define T_DOUBLE 0x26 #define T_FUNC 0x07 #define T_UNSIGNE`}D 0x08 #define T_INTEGER 0x10 #define T_REAL 0x20 #define T_POINTER 0x40 #define T_PTR 0x49 #define T_ARRAY 0x4A #define Ta}_STRUCT 0x80 #define T_UNION 0xC0 #define T_SMASK 0x3F #define E_MGLOBAL 0x80 #define E_MLOCAL 0x40 #define E_MCONST 0x20 b}#define E_MEXPR 0x10 #define E_MEOFFS 0x11 #define E_MCTYPE 0x07 #define E_TCONST 0 #define E_TGLAB 1 #define E_TLIT 2 #dec}fine E_TLOFFS 3 /* jrd added these defs as values for the e_test field of a struct expent. The idea is that internals ofd} the expr parsers will set the e_test slot of a struct expent to one of these values. 0 means no specific test info, de}o it the old way. */ /* expr has already set cond codes apropos result value */ #define E_CC 1 /* if expr has NOT sef}t CC, force a test-style access */ #define E_TEST 2 /* expr has left a logical value (1 or 0) in AX */ #define E_LOGL 4 g} /* flip this bit to invert sense of test */ #define E_XINV 8 #define NAMESIZE 9 #define NAMEMAX 8 #define wqtabsz 128h} #define wqsiz 6 #define wqmax wq+wqtabsz-wqsiz #define wqsym 0 #define wqsp 1 #define wqloop 2 #define wqlab 3 #definei} wqinc 4 #define wqstat 5 #define litabsz 512 #define litmax litabsz-1 #ifdef M6502 #define linesize 100 #else #define lj}inesize 200 #endif #define linemax linesize-1 #define mpmax linemax struct hashent { struct hashent * h_ptr; char h_k}glb; char h_loc; char * h_gtptr; char * h_ltptr; struct hashent * h_link; int h_gdata; int h_ldata; char h_namel}[1]; }; /* not used anymore?... struct kw { char * t_sym; char t_value; char t_next; }; */ /* used by newpm}re.c and newcmd.c. sort of like op_alist... */ struct tok_elt { char * toknam; int toknbr; }; struct expent { /* thn}is used to be just an int. jrd split it into two bytes, in order to have an extra field for tests without taking up o} any more space ... int e_flags; */ unsigned char e_flags; unsigned char e_test; char * e_tptr; int e_conp}st; }; struct filent { #ifdef old_cruft int f_iocb; #else FILE * f_iocb; #endif char * f_name; int f_ln; }; externq} char litq[]; extern char macltab[256]; extern int wq[wqtabsz]; extern struct hashent * lvtab[128]; extern char outq[OUTQr}SZ]; #ifdef M6502 #define htab ((struct hashent ** ) HTSTART) #define macarg ((char ** ) MASTART) #define machtab ((chars} ** ) MHTSTART) #else extern struct hashent * htab[HTABSZ]; extern char * macarg[MACARGSZ]; extern char * machtab[HTABSZ]t}; #endif extern int absdecl; /* extern int critic; */ extern int glblbl; /* extern char glbspace[GSPACE]; */ extern char *u} gblspace; /* global heap */ extern char * gblend; /* gblspace limit */ extern struct hashent * glvptr; extern char * gsptrv}; extern int hashval; extern int i_ifdef; extern char locspace[LSPACE]; extern int lovptr; extern char * lsptr; extern char mw}acdef; /* T if any defines defined */ extern char * outqi; extern int outqsz; /* extern int ret_addr; */ extern char s_ifdefx}[N_IFDEF]; extern int tbllen; extern char * tblptr; extern char * type_char; extern char * type_int; extern char * type_ifuncy}; extern int * wqptr; extern char * line; extern char * mline; extern int litptr; extern char * lptr; extern char * mptr; exz}tern int nxtlab, oursp, argstk, ncmp, errcnt, eof, glbflag; extern struct filent filetab[MAXFILES]; extern int ifile; {} /* #ifdef M6502 extern int inp; extern int output; #else */ extern FILE * inp; extern FILE * output; /* #endif */ extern in|}t ln; extern char * fin; #ifdef M6502 extern char fname[20]; #else extern char fname[80]; #endif extern int curtok; extern }}int curval; extern int nxttok; extern int nxtval; extern char optimize; /* optimize flag */ extern char verbose; /* verbose ~}flag */ extern int n_funargs; /* n args in function def */ extern int asm_kludge; /* kludge for #asm processing */ extern cha}r * incl_dir; /* dir for include files */ /* extern char get_test; /* flag for getmem */ #ifndef M6502 extern char source; }/* put source in m65 file as comments */ #endif char * Gmalloc(); char * Lmalloc(); #ifdef M6502 /* use jrd's hand-coded ti}ny printf */ #define printf tprintf #endif #ifndef M6502 #define dbgprintf(foo,bar) {} #endif /* this struct added by jrd, }used in unified code-generation stuff. see exp1, exp2, exp3. */ struct op_alist { int tok; /* token representing op }*/ int (* gen)(); /* generator function that goes with it */ }; /* end of global file for cc */ /* token representing op d /* cclex.h - token definitions */ #define CEOF 0 /* #define ASM 40 */ #define CASE 41 #define DEFAULT 42 #defin }e BREAK 43 #define CONTINUE 44 #define ELSE 45 /* what the fuck's this? #define ENTRY 46 */ #define DO 30 #define }FOR 31 #define GOTO 32 #define IF 33 #define RETURN 34 #define SWITCH 35 #define WHILE 36 #define SIZEOF 100 # }define IDENT 50 #define SEMI 51 /* * primary operators */ #define LBRACK 52 #define LPAREN 53 #define DOT 54 #de }fine PREF 55 #define LCURLY 56 #define RBRACK 57 #define COMP 58 #define INC 59 #define PASGN 60 #define PLUS 61 # }define COMMA 62 #define DEC 63 #define SASGN 64 #define RCURLY 65 #define MINUS 66 #define MASGN 67 #define STAR 68 #d }efine DASGN 69 #define DIV 70 #define DAMP 71 #define AASGN 72 #define AMP 73 #define NE 74 #define BANG 75 #define DB }AR 76 #define OASGN 77 #define BAR 78 #define EQ 79 #define ASGN 80 #define SLASGN 81 #define ASL 82 /* * inequaliti }es */ #define LE 83 #define LT 84 #define GE 85 #define GT 86 #define SRASGN 87 #define ASR 88 #define XOASGN }89 #define XOR 90 #define MOASGN 91 #define MOD 92 #define QUEST 93 #define COLON 94 #define RPAREN 95 #define SCONST }96 #define ICONST 97 #define CCONST 98 #define FCONST 99 #define CHAR 20 #define INT 21 #define DOUBLE 22 #define } FLOAT 23 #define LONG 24 #define UNSIGNED 25 #define SHORT 26 #define STRUCT 27 #define UNION 28 #define VOID 29 } #define ENUM 101 #define FNAME 102 #define LINENO 103 #ifndef M6502 #define AUTO 10 #endif #define EXTERN }11 #define REGISTER 12 #define STATIC 13 /* never used? #define TYPEDEF 14 */ #define ERROR (-1) ine EXTERN q; ; misc hand-coded things ; .globl _abtchk ; no-op for now _abtchk: rts ; ; bzero(ptr, nbytes) ; .globl _bz}ero _bzero: jsr popax ; get nbytes sta tmp1 stx tmp2 jsr popax ; get ptr sta ptr1 stx ptr1+1 lda #0 bz1: }ldx tmp2 ; get nbytes^ beq bz3 ; zero, try lo ldy #0 bz2: sta (ptr1),y ; zap a byte iny bne bz2 inc ptr1+1 ; }bump ptr^ dec tmp2 ; dec nbytes^ bne bz1 ; around again bz3: ldy tmp1 beq bz5 ldy #0 bz4: sta (ptr1),y ; zap }a byte iny cpy tmp1 ; done? bne bz4 bz5: rts ; ; our own isalpha routine, cloned from the library one, accepts } ; underbars too ; .globl _is_alpha _is_alpha: jsr popax ; get the char cmp #'_' ; underbar? beq yup cmp #'A' } bcc nope ; if less than 'A', return 0 cmp #'Z+1 bcc yup cmp #'a bcc nope cmp #'z+1 bcs nope yup: lda #1 rt}s nope: lda #0 rts A', return 0 cmp #'Z+1 bcc yup cmp #'a bcc nope cmp #'z+1 bcs nope yup: lda #1 rt; ; defs for some popular vars on page 0 for CC65. doing things this ; way reduces code volume, and increases speed slight}ly. ; ; #define CCPAGE0 in ccg.h to make this happen. assemble cc65 modules ; with this file, as "ra65 -o foo.obj ccpag}e0.m65 foo.m65" ; ; update this file if global.m65 changes!! ; _curtok = $98 _curval = $9A _nxttok = $9C _nxtval = $9E} _absdecl = $A0 _glblbl = $A2 _gsptr = $A4 _hashval = $A6 _lovptr = $A8 _lsptr = $AA _macdef = $AC _outqi = $AE _out}qsz = $B0 _tbllen = $B2 _tblptr = $B4 _wqptr = $B6 _litptr = $B8 _lptr = $BA _mptr = $BC _oursp = $C0 _argstk = $}C2 ; ; defs for things in global.m65. keep them in sync!!! ; ptr1 = $8C ptr2 = $8E ptr3 = $90 tmp1 = $92 tmp2 = $9}3 tmp3 = $94 tmp4 = $95 ; ; temps usable in hand-bummed compiler routines ; ptr4 = $C4 ; ; that's all for now... ; } tmp3 = $94 tmp4 = $95 ; ; temps usable in hand-bummed compiler routines ; ptr4 = $C4 ; ; that's all for now... ;  Nov 18 00:29:36 1989 (Jrd at local) * Version 1.1 released. * make8 Put base address back at #x2600. Teach how t}o make cc65-src.arc. * main.c (main) Teach arg parser about -I, for include dir. Nov 17 20:45:02 1989 (Jrd at loca}l) * main.c (ptype) Teach this about T_UCHAR and T_UINT. * symtab.c (SizeOf) Include T_UCHAR in case. * main.c (getty}pe) Return T_UCHAR for unsigned char. * glb.c (parseinit) Use char_t_p. Include unsigned char and int types in case. *} code-gen.c (getmem) Use char_t_p. Nov 17 09:58:38 1989 (unknown at local) * code-gen.c Add new fun lda_helper, t}o generate signed/unsigned loads correctly. * Start exp version 1.1. at local) * code-gen.c Add new fun lda_helper, tJ/* Code generator routines for CC65. These are called by various parts of the compiler to generate primitive operation}s. */ #include #include "cc65.h" #define UNSIGNED_FIX /* output a string */ #ifdef not_M6502 /* defined in xobj.}m65 */ #else static char xxc; ot(str) char * str; { while (xxc = *str) { outchar(xxc); ++str; } } #end}if #ifdef M6502 /* defined in xobj.m65 */ #else nl() { outchar('\n'); } #endif /* output a string, add a newline */ #ifd}ef M6502 /* defined in xobj.m65 */ #else ol(str) { ot(str); nl(); } #endif #ifdef M6502 /* defined in xobj.m65 */ #else} oljsr(str) char * str; { ot("\tjsr\t"); ol(str); } #endif oljsrpop(str) char * str; { oljsr(str); popsp(); } /* h}elper for konst1 */ olstrdnl(str, num) char * str; int num; { ot(str); outdecnl(num); } static char lda[] = "\tlda\t#"; }static char ldx[] = "\tldx\t#"; #ifdef M6502 extern int xxint; extern char xxhi, xxlo; #asm _xxint: _xxlo: .byte 0 _xxhi: .}byte 0 #endasm #else static char xxhi, xxlo; #endif /* load konst into AX in such a way as to set cond codes correctly */ ol}xxxhi() { olstrdnl(ldx, xxhi); } olxxxlo() { olstrdnl(lda, xxlo); } konst1(k) int k; { #ifdef M6502 xxint = k; #else } xxhi = k >> 8; xxlo = k & 0xFF; #endif if (xxhi == xxlo) { olxxxlo(); ol("\ttax"); } else if (xxh}i) { olxxxlo(); olxxxhi(); } else { olxxxhi(); olxxxlo(); /* this loses some; generates} spurious negative... */ } } konst3(k) int k; { #ifdef M6502 flushout(); /* keep output buf from filling up */ #endi}f olstrdnl("\tldy\t#", k); } char efn[] = {'e', 'n', 't', 'e', 'r', 'f', 'u', 'n'}; char efn_n = ' '; char efn_0 = 0; sta}rtfun(name) char * name; { #ifndef M6502 if (n_funargs == -1) printf("Internal error! no argcount?\n"); #endif outgbl}c(name); /* print a global name with colon */ if (findmac("FIXARGC")) efn_n = n_funargs + '0'; else efn_n = 0; }oljsr(efn); } /* util function */ int char_t_p(tptr) char * tptr; { return ((tptr[0] & ~T_UNSIGNED) == T_CHAR); } /* Fetc}h a static memory cell into the primary register */ getmem(lbl, tptr, test_p) /* jrd added test_p */ char * lbl; char * tptr;} char test_p; { if (char_t_p(tptr)) { /* load X with a 0. later deal with sgn ext */ /* if (test_p) /* only load} 0 in X if not testing */ { ol("\tldx\t#0"); } ot("\tlda\t"); /* load A from the label */ outgblnl(}lbl); } else /* loading word-sized thing */ { ot("\tlda\t"); outgblnl(lbl); if (test_p) } ot("\tora\t"); else { ot("\tldx\t"); } outgbl(lbl); ol("+1"); } } /* and a}nother... */ static konst3s(offs) int offs; { konst3(offs - oursp); } #ifdef UNSIGNED_FIX /* this is another helper fu}n for generating the right variant of ldaxxx frob. given a typespec and an extension, generate "lda" followed by } for signed char, 'u' for unsigned char, or 'x' for fixnum */ lda_helper(typestring, ext) unsigned char * type}string; char * ext; { ot("\tjsr\tlda"); if (char_t_p(typestring)) /* some kind of char-sized thing? */ { if (ty}pestring[0] & T_UNSIGNED) outchar('u'); /* call unsigned variant */ } else outchar('x'); /* call word-sized vari}ant */ ol(ext); } #endif /* getladr( offs ) Fetch the address of the specified symbol into the primary register */ g}etladr(offs) int offs; { konst3s(offs); /* load Y with offset value */ oljsr("locysp"); /* and compute location of SP@(}Y) */ } /* getloc( offs, tptr ) Fetch specified local object (local var). */ getloc(offs, tptr) int offs; char * tptr; {} konst3s(offs); /* load Y with offset value */ #ifdef old_way if (tptr[0] == T_CHAR) oljsr("ldaysp"); /* load a byt}e from SP@(Y) */ else oljsr("ldaxysp"); /* load a word from SP@(Y) */ #else #ifdef UNSIGNED_FIX lda_helper(tptr, "ys}p"); #else oljsr((char_t_p(tptr) ? "ldaysp" : "ldaxysp")); #endif #endif } /* putloc( offs, tptr ) Put data into local} object. */ putloc(offs, tptr) int offs; char * tptr; { konst3s(offs); /* load Y with offset value */ #ifdef old_way if }(tptr[0] == T_CHAR) oljsr("staysp"); /* load a byte from SP@(Y) */ else oljsr("staxysp"); /* load a word from SP@}(Y) */ #else oljsr((char_t_p(tptr) ? "staysp" : "staxysp")); #endif } /* Store the primary register into the specified } static memory cell */ putmem(lab, tptr) char * lab; char * tptr; { ot("\tsta\t"); outgblnl(lab); if (!char_t_p(tptr))} { ot("\tstx\t"); outgbl(lab); ol("+1"); } } /* putstk( tptr ) Store the specified object type} in the primary register at the address on the top of the stack */ putstk(lval) struct expent * lval; { if ((lval->e_flag}s == E_MEOFFS) && /* some kind of structure */ (lval->e_const != 0)) /* and not first slot... */ { konst3(lva}l->e_const); /* load Y with structure offset */ #ifdef old_way if (lval->e_tptr[0] == T_CHAR) oljsr("staspidx"); /* st}ore A at ((SP))+Y */ else oljsr("staxspidx"); /* store AX at ((SP))+Y */ #else oljsr((char_t_p(lval->e_tptr) ? "}staspidx" : "staxspidx")); #endif } else { #ifdef old_way if (lval->e_tptr[0] == T_CHAR) oljsr("staspp"); /*} store A at ((SP)) */ else oljsr("staxspp"); /* store AX at ((SP)) */ #else oljsr((char_t_p(lval->e_tptr) ? "sta}spp" : "staxspp")); #endif } popsp(); } /* indirect( lval ) Fetch the specified object type indirect through the } primary register into the primary register */ indirect(lval) struct expent * lval; { if ((lval->e_flags == E_MEOFFS) && /*} some kind of structure */ (lval->e_const != 0)) /* and not slot 0 */ { konst3(lval->e_const); /* load Y with} offset */ #ifdef old_way if (lval->e_tptr[0] == T_CHAR) oljsr("ldaidx"); /* load A from AX@(Y) */ else oljsr("}ldaxidx"); /* load AX from AX@(Y) */ #else #ifdef UNSIGNED_FIX lda_helper(lval->e_tptr, "idx"); #else oljsr((char}_t_p(lval->e_tptr) ? "ldaidx" : "ldaxidx")); #endif #endif } else { #ifdef old_way if (lval->e_tptr[0] == T_C}HAR) oljsr("ldai"); /* load A from AX@ */ else oljsr("ldaxi"); /* load AX from AX@ */ #else #ifdef UNSIGNED_FIX } lda_helper(lval->e_tptr, "i"); #else oljsr((char_t_p(lval->e_tptr) ? "ldai" : "ldaxi")); #endif #endif } } /* } swap() Swap the primary and secondary registers */ #if 0 /* not used? */ #ifdef M6502 /* defined in xobj.m65 */ #else swa}p() { oljsr("swaptos"); } #endif #endif /* save() Copy AX to hold register. */ #ifdef M6502 /* defined in xobj.m65 */} #else save() { oljsr("saveax"); } #endif /* rstr() Copy hold register to P. */ #ifdef M6502 /* defined in xobj.m65 *}/ #else rstr() { oljsr("restax"); } #endif /* immed() Print partial instruction to get an immediate value into the }primary register. */ immed() { ot("\tldax\t#"); } /* added by jrd. force a test to set cond codes right */ #ifdef M6502 /}* defined in xobj.m65 */ #else tst() { oljsr("tstax"); } #endif /* push() Push the primary register onto the stack */} push() { oljsr("pushax"); pushsp(); } push1() { /* what's the difference? */ #ifndef M6502 ol(";; push1"); #endif p}ush(); } /* Swap the primary register and the top of the stack */ #ifdef M6502 /* defined in xobj.m65 */ #else swapstk() { } oljsr("swapstk"); } #endif /* Call the specified subroutine name */ call(lbl, narg) /* int lbl; -- not any more */ char *} lbl; int narg; { if (!findmac("NOARGC")) /* don't generate argc if suppressed */ konst3(narg >> 1); /* want n args, n}ot nbytes args */ ot("\tjsr\t"); outgblnl(lbl); oursp = oursp + narg; /* callee pops args */ #ifdef M6502 flushout(}); /* keep output buf from filling up */ #endif } /* Return from subroutine */ ret() { ol("\tjmp\texitfun"); } /* Per}form subroutine call to value on top of stack. This really calls value in AX */ callstk(narg) int narg; { if (!findmac("}NOARGC")) /* don't generate argc if suppressed */ konst3(narg >> 1); /* load Y with arg count */ oljsr("callax"); /* }do the call */ oursp = oursp + narg; /* callee pops args */ /* popsp(); /* pop subr addr */ #ifdef M6502 flushout(); } /* keep output buf from filling up */ #endif } /* Jump to specified internal label number */ jump(label) int label; { ot}("\tjmp\t"); outlabnl(label); } /* output case-jump preample */ #ifdef M6502 /* defined in xobj.m65 */ #else casejump() { } oljsr("casejump"); } #endif /* truejump -- jump to lable if p nz */ truejump(label, invert) int label; int invert; /*} jrd added this */ { #ifndef M6502 ol(";;; truejump"); #endif if (invert) falsejump(label, 0); else { ot(}"\tlbne\t"); outlabnl(label); } } /* falsejump -- jump to lable if AX is zero */ falsejump(label, invert) int la}bel; int invert; /* jrd added this */ { #ifndef M6502 ol(";;; falsejump"); #endif if (invert) truejump(label, 0); e}lse { ot("\tlbeq\t"); outlabnl(label); } } /* cmpjump -- compare p to constant and jump not-equal to} label */ /* cmpjump(constant, label) int constant; int label; { ol(";;; cmpjump"); } */ /* Modify the stack pointer to }the new value indicated */ otx(str) char * str; { ot("\tjsr\t"); ot(str); ot("sp"); } mod_internal(k, verb1, verb2) }int k; char * verb1, * verb2; { if (k <= 8) { otx(verb1); outchar(k + '0'); } else { konst3}(k); otx(verb2); } nl(); } modstk(newsp) int newsp; { int k; if ((k = (newsp - oursp)) > 0) { mod_i}nternal(k, "inc", "addy"); } else if (k < 0) { mod_internal(-k, "dec", "suby"); } return (newsp); } /*} Double the primary register */ #ifdef M6502 /* defined in xobj.m65 */ #else doublereg() { oljsr("aslax"); } #endif /* }Add the primary and secondary registers (results in primary) */ #ifdef M6502 /* defined in xobj.m65 */ #else add() { /* } oljsr("addtos"); popsp(); /* zzz is this still right??? */ oljsrpop("addtos"); } #endif /* Subtract the primary r}egister from the secondary (results in primary) */ #ifdef M6502 /* defined in xobj.m65 */ #else sub() { /* oljsr("subtos}"); popsp(); */ oljsrpop("subtos"); } #endif /* Multiply the primary and secondary registers (results in primary }*/ #ifdef M6502 /* defined in xobj.m65 */ #else mult() { /* oljsr("multos"); popsp(); */ oljsrpop("multos"); } #endif } /* Divide the secondary register by the primary (quotient in primary, remainder in secondary) */ #ifdef M6502 /* defin}ed in xobj.m65 */ #else div() { /* oljsr("divtos"); popsp(); */ oljsrpop("divtos"); } #endif /* Compute remainder (}mod) of secondary register divided by the primary (remainder in primary, quotient in secondary) */ #ifdef M6502 /* defined }in xobj.m65 */ #else mod() { /* oljsr("modtos"); popsp(); */ oljsrpop("modtos"); } #endif /* Inclusive 'or' the pr}imary and the secondary registers (results in primary) */ #ifdef M6502 /* defined in xobj.m65 */ #else or() { /* oljsr(}"ortos"); popsp(); */ oljsrpop("ortos"); } #endif /* Exclusive 'or' the primary and seconday registers (results in} primary) */ #ifdef M6502 /* defined in xobj.m65 */ #else xor() { /* oljsr("xortos"); popsp(); */ oljsrpop("xortos"); }} #endif /* 'And' the primary and secondary registers (results in primary) */ #ifdef M6502 /* defined in xobj.m65 */} #else and() { /* oljsr("andtos"); popsp(); */ oljsrpop("andtos"); } #endif /* Arithmetic shift right the secondary} register number of times in primary (results in primary) */ #ifdef M6502 /* defined in xobj.m65 */ #else asr() { /* ol}jsr("asrtos"); popsp(); */ oljsrpop("asrtos"); } #endif /* Arithmetic left shift the secondary register number of }times in primary (results in primary) */ #ifdef M6502 /* defined in xobj.m65 */ #else asl() { /* oljsr("asltos"); popsp( }); */ oljsrpop("asltos"); } #endif /* Form two's complement of primary register */ #ifdef M6502 /* defined in xobj.m65 */ } #else neg() { oljsr("negax"); } #endif /* Form logical complement of primary register */ #ifdef M6502 /* defined in xobj }.m65 */ #else lneg() { oljsr("lnegax"); } #endif /* Form one's complement of primary register */ #ifdef M6502 /* defined  }in xobj.m65 */ #else com() { oljsr("complax"); } #endif /* Increment the primary register by one */ #ifdef M6502 /* defin }ed in xobj.m65 */ #else inc() { oljsr("incax1"); } #endif /* Decrement the primary register by one */ #ifdef M6502 /* def}ined in xobj.m65 */ #else dec() { oljsr("decax1"); } #endif /* Following are the conditional operators They compare} the secondary register against the primary and put a literal 1 in the primary if the condition is true, otherwise they} clear the primary register */ /* Test for equal */ #ifdef M6502 /* defined in xobj.m65 */ #else eq() { /* oljsr("toseqax}"); popsp(); */ oljsrpop("toseqax"); } #endif /* zero-p */ #ifdef M6502 /* defined in xobj.m65 */ #else eq0() { /* ol}jsr("axzerop"); popsp(); ... bug??? */ oljsr("axzerop"); } #endif /* Test for not equal */ #ifdef M6502 /* defined in x}obj.m65 */ #else ne() { /* oljsr("tosneax"); popsp(); */ oljsrpop("tosneax"); } #endif /* Test for less than */ lt(un}s) int uns; /* unsigned_p */ { /* oljsr(uns ? "tosultax" : "tosltax"); popsp(); */ oljsrpop(uns ? "tosultax" : "toslt}ax"); } /* Test for less than or equal to */ le(uns) int uns; /* unsigned_p */ { /* oljsr(uns ? "tosuleax" : "tosleax"); } popsp(); */ oljsrpop(uns ? "tosuleax" : "tosleax"); } /* Test for greater than */ gt(uns) int uns; /* unsigned_p */ { /}* oljsr(uns ? "tosugtax" : "tosgtax"); popsp(); */ oljsrpop(uns ? "tosugtax" : "tosgtax"); } /* Test for greater than }or equal to */ ge(uns) int uns; /* unsigned_p */ { /* oljsr(uns ? "tosugeax" : "tosgeax"); popsp(); */ oljsrpop(uns ? }"tosugeax" : "tosgeax"); } #ifdef old_cruft ...no longer need unsigned stuff... /* Test for less than (unsigned) */ ult() { } oljsr("tosultax"); popsp(); } /* Test for less than or equal to (unsigned) */ ule() { oljsr("tosuleax"); popsp(); } } /* Test for greater than (unsigned) */ ugt() { oljsr("tosugtax"); popsp(); } /* Test for greater than or equal to (unsi}gned) */ uge() { oljsr("tosugeax"); popsp(); } #endif #ifdef busted static char dollr = '$'; static char xdig[4]; stati}c char xd0 = '\0'; #endif outdec(numbr) int numbr; { char digit[8]; int i; #ifdef busted /* use bummed assembler routine */ }/* OOps! Can't use itoa here, cause it uses the FP routines, and they trash page 5, which we use for the symbol table. pr}int it in hex. itoa(numbr, digit); */ digit[0] = '$'; for (i = 3; i >= 0; --i) { xdig[i] = (numbr & 0x0F) + ' }0'; numbr >> = 4; } /* ot(digit); */ ot(&dollr); #else if (numbr < 0) { numbr = -numbr; outch!}ar('-'); } digit[0] = 0; for (i = 0; numbr > 0;) { digit[i] = numbr % 10; numbr = numbr / 10; +"}+i; } if (i == 0) i = 1; while (i > 0) outchar(digit[--i] + '0'); #endif } outdecnl(n) int n; { outdec(n);#} nl(); } outcch(numbr) int numbr; { outdec(numbr); } outlab(lbl) int lbl; { outchar('L'); outdec(lbl); } outlabnl($}lbl) char * lbl; { outlab(lbl); nl(); } outcdf(labl) int labl; { outlab(labl); ol(":"); } outdat(n) int n; { ol("%};;; outdat"); } outslt(n) int n; { /* this seems to get used for constant string values? */ outlab(litlab); /* output curr&}ent lit pool labl */ outchar('+'); outdec(n); nl(); } /* reserve static storage, n bytes */ outsp(n) int n; { ot("\t'}.blkb\t"); outdec(n); nl(); #ifdef M6502 flushout(); #endif } /* output a row of bytes as a constant */ outbv(bytes, n(}bytes) char * bytes; int nbytes; { int bpl; while (nbytes) { flushout(); /* keep output buf from overflowing */ )} nbytes -= (bpl = (nbytes > 16) ? 16 : nbytes); bytepref(); kludge1: outdec(*bytes++); if (--bpl) *} { outchar(','); goto kludge1; } outchar('\n'); } } /* prefix for word-sized constant */ wordpref() { ot(+}"\t.word\t"); } /* prefix for byte-sized constant */ bytepref() { ot("\t.byte\t"); } /* print a global name into the asm ,}file. This probly supercedes the one below... */ outgbl(name) char * name; { outchar('_'); ot(name); } outgblnl(name-}) { outgbl(name); nl(); } outgblc(name) char * name; { outgbl(name); ol(":"); } /* output a global or external name.} */ outgoe(sname) char * sname; { ot("\t.globl\t"); outgblnl(sname); #ifdef M6502 flushout(); #endif } #ifdef M6502 //}* defined in xobj.m65 */ #else popsp() { return (oursp += 2); } #endif #ifdef M6502 /* defined in xobj.m65 */ #else pushs0}p() { return (oursp -= 2); } #endif { return (oursp += 2); } #endif #ifdef M6502 /* defined in xobj.m65 */ #else pushs'-*- Mode: Text -*- This is the copyright notice for RA65, LINK65, LIBR65, and other Atari 8-bit programs. Said progra!2}ms are Copyright 1989, by John R. Dunning. All rights reserved, with the following exceptions: Anyone may copy or re!3}distribute these programs, provided that: 1: You don't charge anything for the copy. It is permissable to charge a!4} nominal fee for media, etc. 2: All source code and documentation for the programs is made available as part of the !5}distribution. 3: This copyright notice is preserved verbatim, and included in the distribution. You are allo!6}wed to modify these programs, and redistribute the modified versions, provided that the modifications are clearly noted. !7} There is NO WARRANTY with this software, it comes as is, and is distributed in the hope that it may be useful. T!8}his copyright notice applies to any program which contains this text, or the refers to this file. This copyright noti!9}ce is based on the one published by the Free Software Foundation, sometimes known as the GNU project. The idea is the same!:} as theirs, ie the software is free, and is intended to stay that way. Everybody has the right to copy, modify, and re- di!;}stribute this software. Nobody has the right to prevent anyone else from copying, modifying or redistributing it. re- di u /* Misc cruft used by cross-compiler variant of CC65 */ #include #include "cc65.h" #include "cclex.h" FILE * %=}copen(file, mode) char * file; char mode; { char m[5]; FILE * p; m[0] = mode; m[1] = '\0'; if ((p = fopen(file, m)) ==%>} NULL) { return ((FILE *) 0); /* was -1 -- jrd */ } else { return (p); } } cclose(x) FILE * x;%?} { return(fclose(x)); } cprints(s) char * s; { fputs(s, stdout); } cputc(c, fp) int c; FILE * fp; { fputc(c, fp); } %@}clear(ptr, len) char * ptr; int len; { while (--len >= 0) *ptr++ = '\0'; } int is_alpha(c) int c; { if (((c >= 'a') %A}&& (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || (c == '_')) return(1); else return(0); } int isdigit(c%B}) int c; { if ((c >= '0') && (c <= '9')) return(1); else return(0); } int tolower(c) int c; { if ((c >= 'A') &%C}& (c <= 'Z')) return(c + 32); else return(c); } int toupper(c) int c; { if ((c >= 'a') && (c <= 'z')) return%D}(c - 32); else return(c); } else return(c); } int toupper(c) int c; { if ((c >= 'a') && (c <= 'z')) return$" /* This software is copyright 1989 by John Dunning. See the file 'COPYLEFT.JRD' for the full copyright notice. */)F} This software is copyright 1989 by John Dunning. See the file 'COPYLEFT.JRD' for the full copyright notice. */( /* Error reporting code */ #include #include "cclex.h" #include "cc65.h" /* Error( msg ) Print error with-H} no prefix. */ Error(msg) char * msg; { PError("", msg); } /* Syntax() Flag a syntax error. */ Syntax() { Error("syn-I}tax error"); } /* Illegal( msg ) Handle "illegal ..." messages. */ Illegal(msg) { PError("illegal ", msg); } /* Mis-J}sing( msg ) Handle "missing ..." messages. */ Missing(msg) char * msg; { PError("missing ", msg); } /* MultDef( msg ) -K} Handle "multipy defined ..." messages. */ MultDef(msg) char * msg; { PError("multiply defined ", msg); } /* Need( msg -L}) Handle "need ..." messages. */ Need(msg) char * msg; { PError("need ", msg); } /* needlval() Handle "need lvalue" -M}messages. */ needlval() { Need("lvalue"); } /* from here on down, we want to generate argcounts, so we undefine the mag-N}ic symbol */ #undef NOARGC /* ersum() Report errors for user */ ersum() { /* see if anything left hanging... */ if -O}(ncmp) Missing("closing bracket"); if (errcnt == 0) { printf("No errors.\n"); } } /* PError( pfx, msg -P}) Print prefix message pfx followed by error message msg. */ PError(pfx, msg) char * msg; { #ifdef M6502 tprintf("\n%s: l-Q}ine %d:\n%s%s\nline:%s\n", fin, ln, pfx, msg, line); #else printf("%s, line %d : %s%s\n", fin, ln, pfx, msg); printf("lin-R}e: %s\n", line); printf("curtok = %d\n", curtok); printf("nxttok = %d\n", nxttok); #endif if (++errcnt > 6) fatal("-S}too many errors"); } /* fatal( msg ) Fatal error - print message and die */ fatal(msg) char * msg; { #ifdef M6502 tpri-T}ntf("fatal error: %s\nline: %s\n", msg, line); exit(2); #else printf("fatal error: %s\n", msg); printf("line: %s\n", li-U}ne); printf("curtok = %d\n", curtok); printf("nxttok = %d\n", nxttok); printf("Can't recover from previous errors: Goo-V}d-bye!\n"); exit(2); #endif } /* Warning( msg ) Print warning message. */ Warning(msg) char * msg; { #ifdef M6502 tp-W}rintf("Warning: %s\n", msg); #else printf("warning: %s\n", msg); printf("line: %s\n", line); printf("curtok = %d\n", cu-X}rtok); printf("nxttok = %d\n", nxttok); #endif } g: %s\n", msg); printf("line: %s\n", line); printf("curtok = %d\n", cu,3 /* expression parser, part 1 */ #include #include "cc65.h" #include "cclex.h" extern char * lsptr; int hie0(1Z}); int hie1(); int hie2(); int hie3(); int hie4(); int hie5(); int hie6(); int add(); int sub(); int mult(); int div(); int m1[}od(); int asl(); int asr(); int and(); int xor(); int or(); int lt(); /* int ult(); */ int gt(); /* int ugt(); */ int le(); /1\}* int ule(); */ int ge(); /* int uge(); */ int eq(); int ne(); /* needtok( token, msg ) Token is expected next. Print "1]}missing " if not found. */ needtok(token, msg) int token; char * msg; { if (curtok == token) { gettok(); 1^} return; } else { Missing(msg); } } /* needcol() Colon enforcer. */ needcol() { needtok(COLON, "1_}colon"); } /* getoprnd( func, lval ) Subroutine of commonly executed sequence of statements; */ getoprnd(func, lval) int1`} (*func) (); struct expent * lval; { gettok(); push(); exprhs((*func) (lval), lval); } /* isconst( lval1, lval2 ) 1a}Test to see if both lval1 and lval2 are constant expressions. */ isconst(lval1, lval2, svptr) struct expent * lval1; struct e1b}xpent * lval2; char * svptr; { if (lval1->e_flags == E_MCONST && lval2->e_flags == E_MCONST) { popsp(); out1c}qi = svptr; return (1); } else { return (0); } } /* added by jrd. return T if value describes con1d}stant 0 */ const0(lval) struct expent * lval; { return ((lval->e_flags == E_MCONST) && (lval->e_const == 0)); } /* expre1e}ssion() P = value of expression. */ expression() { struct expent lval; #ifndef M6502 bzero(&lval, sizeof(lval)); #endif 1f} exprhs(expr(hie0, &lval), &lval); } /* expr( func, lval ) Expression parser; func is either hie0 or hie1. */ expr(func1g}, lval) int (*func) (); struct expent * lval; { int k; char * locptr; int savsp; savsp = oursp; locptr = lsptr; /* #ifd1q}B%DOS SYSB*)DUP SYSB1SCC65 H BCCLEX H BCCMISC M65BCCPAGE0 M65BCHANGELO BCODE_GENC B 1COPYLEFTJRDB <CRUFT C BEDISCLAIMH BGERROR C B]YEXPR1 C B5EXPR2 C BbEXPR3 C BVEXTRA M65B dFUNCTIONC BGLB C BGLOBLVARC 'IO C ef M6502 -- jrd */ flushout(); /* #endif */ k = (*func) (lval); lsptr = locptr; #ifndef M6502 if (savsp != oursp)1r} { char errbuf[100]; sprintf(errbuf, "oursp [%d] != savsp [%d]", oursp, savsp); Error(errbuf); } #1s}endif return (k); } /* hie0( lval ) Parse comma operator. */ hie0(lval) struct expent * lval; { int k; k = hie1(lva1t}l); while (curtok == COMMA) { gettok(); k = hie1(lval); } return (k); } /* hie1( lval ) Parse fi1u}rst level of expression hierarchy. */ hie1(lval) struct expent * lval; { int (*func) (); int k; k = hieQuest(lval); swit1v}ch (curtok) { case RPAREN: case SEMI: return (k); case ASGN: { struct expent lval2; gettok(); 1w} if (k == 0) { needlval(); return (0); } if (lval->e_flags & E_MEXPR) push(); exprhs(hie1(&lval2), &lval1x}2); store(lval); lval->e_flags = E_MEXPR; /* if either the source expression of the target generated condition codes, s1y}et the cond-codes bit in the returned expr */ lval->e_test |= (lval2.e_test & E_CC); return (0); } case PASGN: 1z} func = add; break; case SASGN: func = sub; break; case MASGN: func = mult; break; 1{} case DASGN: func = div; break; case MOASGN: func = mod; break; case SLASGN: func = 1|}asl; break; case SRASGN: func = asr; break; case AASGN: func = and; break; case XOA1}}SGN: func = xor; break; case OASGN: func = or; break; default: return (k); } opeq1~}(func, lval, k); return (0); } /* opeq( func, lval, k) Process "op=" operators. */ opeq(func, lval, k) int (*func) ();1} struct expent * lval; int k; { char * ptr; struct expent lval2; gettok(); if (k == 0) { needlval(); ret1}urn; } if (lval->e_flags & E_MEXPR) push1(); exprhs(k, lval); push(); exprhs(hie1(&lval2), &lval2); if (fun1}c == add || func == sub) { if (lval->e_tptr[0] == T_PTR) { scale(SizeOf(lval->e_tptr + 1)); } } (*func) 1}(); store(lval); lval->e_flags = E_MEXPR; } /* hieQuest( lval ) Parse "lvalue ? exp : exp" */ hieQuest(lval) struct 1}expent * lval; { int k; k = hieOr(lval); if (curtok != QUEST) { return (k); } else { int lab1}f; int labt; gettok(); exprhs(k, lval); labf = getlabel(); falsejump(labf, 0); expressio1}n(); labt = getlabel(); needcol(); jump(labt); outcdf(labf); expression(); outcdf(labt); 1} lval->e_flags = E_MEXPR; return (0); } } /* hieOr( lval ) Process "exp || exp". */ hieOr(lval) struct ex1}pent * lval; { int k; k = hieAnd(lval); /* do higher-precedence exprs */ if (curtok != DBAR) /* if not ||, return */1} { return (k); } else { int lab1; /* labl to exit expr w/ 1 */ int lab2; /* labl to exit 1}expr w/ 0 */ struct expent lval2; int loadk; /* flag if load 1 at end */ loadk = ((lval->e_test & E_LOGL)1} == 0); /* need to load 1 if not already */ exprhs(k, lval); /* get first expr */ lab2 = getlabel(); /* get inte1}rnal label. for tests, this is the only label */ truejump(lab1 = getlabel(), 0); /* get lab and gen 1st 1}bne to it */ while (curtok == DBAR) /* while there's more expr */ { gettok(); /* skip the || */ exprhs(hieAnd(&1}lval2), &lval2); /* get a subexpr */ loadk |= ((lval2.e_test & E_LOGL) == 0); /* need to load 1 if not already */ if (c1}urtok == DBAR) /* if still more, ... */ { truejump(lab1, lval->e_test & E_XINV); /* bne out */ } else 1} { if (loadk) /* only generate branch around load if we're loading */ falsejump(lab2, lval->e_test & E_XINV)1}; /* else beq out */ } } outcdf(lab1); /* define lab1 */ if (loadk) /* if need a load-const 1 ... */ { 1} konst1(1); /* ... do it */ } outcdf(lab2); /* define lab2 */ lval->e_flags = E_MEXPR; return (0); 1} } } /* hieAnd( lval ) Process "exp && exp" */ hieAnd(lval) struct expent * lval; { int k; k = hie2(lval); if (cu1}rtok != DAMP) { return (k); } else { int lab; struct expent lval2; exprhs(k, lval); 1} falsejump(lab = getlabel(), 0); while (curtok == DAMP) { gettok(); exprhs(hie2(&lval2), &lval2); falsejum1}p(lab, 0); /* zzz finish later */ } /* immed(); outdec(1); */ konst1(1); outcdf(lab); lval->e_fla1}gs = E_MEXPR; return (0); } } /* utils used by hie2, 3, and 4. it's the guts of those 3 guys, extracted and pa1}rameterized */ static int kcalc(tok, val1, val2) int tok, val1, val2; { #ifdef M6502 /* hand bummed version of what this com1}piles into, to avoid extraneous pushes. */ #asm ldy #6 ; get 'tok' jsr ldaysp ; this is safe cause theyre all byte-siz1}ed sta tmp4 ; save the value here ; common preamble ldy #4 ; offset for val1 jsr pushwysp ; push it ldy #4 ; offset fo1}r val2 jsr ldaxysp ; load it ldy tmp4 ; get token number back cpy #78 ; BAR bne *+6 ; nope, try next jsr ortos ; d1}o an OR jmp exitfun ; and return the value cpy #79 ; EQ bne *+6 ; nope, try next jsr toseqax ; do an == jmp exitfun1} ; and return the value cpy #90 ; XOR bne *+6 ; nope, try next jsr xortos ; do an XOR jmp exitfun ; and return the 1}value cpy #73 ; AMP bne *+6 ; nope, try next jsr andtos ; do an AND jmp exitfun ; and return the value cpy #88 ; 1}ASR bne *+6 ; nope, try next jsr asrtos ; do an ASR jmp exitfun ; and return the value cpy #82 ; ASL bne *+6 ; nop1}e, try next jsr asltos ; do an ASL jmp exitfun ; and return the value cpy #68 ; STAR bne *+6 ; nope, try next jsr m1}ultos ; do a multiply jmp exitfun ; and return the value cpy #70 ; DIV bne *+6 ; nope, try next jsr divtos ; do a d1}ivide jmp exitfun ; and return the value cpy #92 ; MOD bne *+6 ; nope, try next jsr modtos ; do a MOD jmp exitfun 1}; and return the value ; if we get here its an internal error. ignore for now jsr popax ; flush dead value on stack #endas1}m #else switch (tok) { case BAR: return (val1 | val2); case EQ: return (val1 == val2); case XOR1}: return (val1 ^ val2); case AMP: return (val1 & val2); case ASR: return (val1 >> val2); case A1}SL: return (val1 << val2); case STAR: return (val1 * val2); case DIV: return (val1 / val2); cas1}e MOD: return (val1 % val2); #ifndef M6502 default: printf("Internal error: kcalc: got token %X\n", tok); #en1}dif } #endif } int op_assoc(tok, ops) int tok; struct op_alist * ops; { while (ops->tok && (ops->tok != tok)) ++op1}s; return (ops->gen); } /* helper fun for various hie frobs */ int hie_internal(ops, lval, hienext) struct op_alist * ops1}; /* alist of ops we'll take here */ struct expent * lval; /* parent expr's lval */ int (*hienext) (); /* next higher leve1}l parser */ { int k; k = (*hienext) (lval); if (!op_assoc(curtok, ops)) /* sufficient to test if it's there... */ 1}{ return (k); } else { struct expent lval2; char * svptr; int (*gen) (); int this_tok1}; svptr = outqi; exprhs(k, lval); while (1) { if (gen = op_assoc((this_tok = curtok), ops)) { 1} getoprnd(hienext, &lval2); if (isconst(lval, &lval2, svptr)) { liconst(lval->e_const = kcalc(this_tok, 1}lval->e_const, lval2.e_const)); lval->e_test &= ~E_CC; /* cc not set right */ } else { (*gen) (); lval1}->e_flags = E_MEXPR; lval->e_test |= E_CC; /* say we set cc */ } } else { if (lval->e_flags == E_MC1}ONST) { outqi = svptr; } return (0); } } } } /* hie2( lval ) */ struct op_alist hie2_ops[] = { 1}{BAR, or}, {0, 0} }; hie2(lval) struct expent * lval; { return (hie_internal(hie2_ops, lval, hie3)); } /* hie3( lval 1}) */ struct op_alist hie3_ops[] = { {XOR, xor}, {0, 0} }; hie3(lval) struct expent * lval; { return (hie_internal(hie31}_ops, lval, hie4)); } /* hie4( lval ) */ struct op_alist hie4_ops[] = { {AMP, and}, {0, 0} }; hie4(lval) struct expen1}t * lval; { return (hie_internal(hie4_ops, lval, hie5)); } /* hie5( lval ) */ struct op_alist hie5_ops[] = { {EQ, eq},1} {NE, ne}, {0, 0} }; hie5(lval) struct expent * lval; { return (hie_internal(hie5_ops, lval, hie6)); } /* hie6( lva1}l ) process greater-than type comparators */ /* helper fun for hie6. Where's FLET when you need it? */ static hie6_intern1}al(isptr1, lval, gen) int isptr1; /* other value is ptr */ struct expent * lval; int (*gen) (); /* code generator fun */ 1}{ gettok(); push(); exprhs(hie7(lval), lval); (*gen) ((isptr1 || (lval->e_tptr[0] & T_UNSIGNED))); } hie6(lval) stru1}ct expent * lval; { int k; k = hie7(lval); if ((curtok < LE) || (curtok > GT)) { return (k); } else 1} { struct expent lval2; int isptr1; exprhs(k, lval); isptr1 = lval->e_tptr[0] & T_UNSIGNED; l1}val->e_test = E_LOGL | E_CC; /* say we returned a logl val, and set cc */ while (1) { switch (curtok) { c1}ase LE: hie6_internal(isptr1, &lval2, le); break; case GE: hie6_internal(isptr1, &lval2, ge); 1} break; case LT: hie6_internal(isptr1, &lval2, lt); break; case GT: hie6_internal(isptr1, &lv1}al2, gt); break; default: lval->e_flags = E_MEXPR; return (0); } } } } ternal(isptr1, &lv0k /* Expression parsing, part 2 */ #include #include "cc65.h" #include "cclex.h" int hie8(); int hie9(); int hi5}e10(); int increm(); int decrem(); int inc(); int dec(); /* hie7( lval ) Parse << and >>. */ extern asl(); extern asr(5}); struct op_alist hie7_ops[] = { {ASL, asl}, {ASR, asr}, {0, 0} }; hie7(lval) struct expent * lval; { return (hie_i5}nternal(hie7_ops, lval, hie8)); } /* hie8( lval ) Process + and - binary operators. */ hie8(lval) struct expent * lval; 5}{ int k; k = hie9(lval); if ((curtok != PLUS) && (curtok != MINUS)) { return (k); } else { s5}truct expent lval2; char * svptr; char * tptr1; char * tptr2; svptr = outqi; exprhs(k, lval); 5} while (1) { if (curtok == PLUS) { getoprnd(hie9, &lval2); tptr1 = lval->e_tptr; tptr2 = l5}val2.e_tptr; if ((tptr1[0] & T_POINTER) && (tptr2[0] & T_INTEGER)) { cscale(&lval2, PSizeOf(tptr1)); } 5} else if ((tptr1[0] & T_INTEGER) && (tptr2[0] & T_POINTER)) { swapstk(); scale(PSizeOf(tptr2)); lva5}l->e_tptr = lval2.e_tptr; } if (isconst(lval, &lval2, svptr)) { liconst(lval->e_const += lval2.e_const); } 5} else { add(); lval->e_flags = E_MEXPR; } } else if (curtok == MINUS) { getoprnd(hie9, &5}lval2); tptr1 = lval->e_tptr; tptr2 = lval2.e_tptr; if ((tptr1[0] & T_POINTER) && (tptr2[0] & T_INTEGER)5}) { cscale(&lval2, PSizeOf(tptr1)); } sub(); if ((tptr1[0] & tptr2[0] & T_POINTER) && (strcmp(tptr15}, tptr2) == 0)) { k = PSizeOf(tptr1); if (k > 1) { push(); /* immed(); outdec(k); 5} */ konst1(1); div(); lval->e_flags = E_MEXPR; } lval->e_tptr = type_int; } if 5}(lval->e_flags == E_MCONST && lval2.e_flags == E_MCONST) { outqi = svptr; liconst(lval->e_const -= lval2.e_const); 5} } else { lval->e_flags = E_MEXPR; } } else { if (lval->e_flags == E_MCONST) { outq5}i = svptr; } else { lval->e_flags = E_MEXPR; } return (0); } } } } /* hie9( lval ) Pro5}cess * and / operators. */ extern mult(); extern div(); extern mod(); struct op_alist hie9_ops[] = { {STAR, mult}, {DIV,5} div}, {MOD, mod}, {0, 0} }; hie9(lval) struct expent * lval; { return (hie_internal(hie9_ops, lval, hie10)); } /* 5}hie10( lval ) Parse unary operators. */ /* various internal functions */ static int hie10a(lval, incptr, incint) /* guts o5}f inc, dec */ struct expent * lval; int (*incptr) (); /* for inc'ing ptrs */ int (*incint) (); /* for inc'ing ints */ { int k5}; gettok(); if ((k = hie10(lval)) == 0) { needlval(); return (0); } if (lval->e_flags & E_MEXPR) 5} push1(); exprhs(k, lval); if (lval->e_tptr[0] == T_PTR) { (*incptr) (SizeOf(lval->e_tptr + 1)); } else5} { (*incint) (); } store(lval); lval->e_flags = E_MEXPR; } static int hie10b(lval, k, incptr, incint) /* g5}uts of second inc, dec */ struct expent * lval; int k; int (*incptr) (); /* for inc'ing ptrs */ int (*incint) (); /* for inc'5}ing ints */ { gettok(); if (k == 0) { needlval(); return (0); } if (lval->e_flags & E_MEXPR) pu5}sh1(); exprhs(1, lval); save(); if (lval->e_tptr[0] == T_PTR) { (*incptr) (SizeOf(lval->e_tptr + 1)); } 5} else { (*incint) (); } store(lval); rstr(); lval->e_flags = E_MEXPR; } static hie10c(tok, lval) /* guts5} of minus, comp */ int tok; struct expent * lval; { int k; gettok(); k = hie10(lval); if (lval->e_flags == E_MCONST)5} { lval->e_const = (tok == MINUS ? -lval->e_const : ~lval->e_const); return (0); } exprhs(k, lval); i5}f (tok == MINUS) neg(); else com(); lval->e_flags = E_MEXPR; } hie10(lval) struct expent * lval; { int k; ch5}ar * ptr; struct hashent * sadr; int type; if (curtok != IDENT) { switch (curtok) { case INC: { hi5}e10a(lval, increm, inc); return (0); } case DEC: { hie10a(lval, decrem, dec); return (0); } case MI5}NUS: case COMP: { hie10c(curtok, lval); return (0); } case BANG: { gettok(); k = hie10(lval); 5}/* decode the expr */ exprhs(k, lval); /* load the value */ #ifdef busted if (lval->e_test) /* somebody doing a te5}st of this exp? */ { lval->e_test ^= E_XINV; /* flip sense of test */ } else /* normal expr */ 5} { #ifdef old_cruft push(); konst1(0); eq(); #else lneg(); #endif } #else lneg(); /* sheesh */ #endi5}f lval->e_flags = E_MEXPR; /* say it's an expr */ return (0); /* expr not storable */ } case STAR: { g5}ettok(); exprhs(hie10(lval), lval); if (((ptr = lval->e_tptr)[0] & T_POINTER) == 0) { Illegal("indirection5}"); } else { if (ptr[0] == T_ARRAY) { ptr += 4; } else { ++ptr; } lval->5}e_tptr = ptr; } lval->e_flags = E_MEXPR; return (1); } case AMP: { gettok(); k = hie10(lval5}); if (k == 0) { Illegal("address"); return (0); } ptr = Lmalloc(strlen(lval->e_tptr) + 2); 5}ptr[0] = T_PTR; strcpy(ptr + 1, lval->e_tptr); lval->e_tptr = ptr; return (0); } case SIZEOF: { ge5}ttok(); if ((curtok == LPAREN) && (nxttok >= 20) && (nxttok <= 29)) { char tarray1[MAXTYPELEN]; gettok(); 5}type = gettype(-1, &sadr); absdecl = 1; declare(tarray1, type, sadr); needbrack(RPAREN); lval->e_const = SizeOf(tarra5}y1); } else { hie10(lval); lval->e_const = SizeOf(lval->e_tptr); } lval->e_flags = E_MCONS5}T | E_TCONST; lval->e_tptr = type_int; return (0); } default: if ((curtok == LPAREN) && (nxttok >= 20) && (n5}xttok <= 29)) { char tarray2[MAXTYPELEN]; gettok(); type = gettype(-1, &sadr); absdecl = 1;5} declare(tarray2, type, sadr); needbrack(RPAREN); k = hie10(lval); strcpy(lval->e_tptr = Lmalloc(5}strlen(tarray2) + 1), tarray2); return (k); } } /* end switch */ } /* end curtok != ident */ k = hie15}1(lval); switch (curtok) { case INC: { hie10b(lval, k, increm, inc); return (0); } case DEC: 5} { hie10b(lval, k, decrem, dec); return (0); } default: return (k); } } 0); } case DEC: 4_ /* Expression parsing, part 3 */ #include #include "cc65.h" #include "cclex.h" int hie0(); /* hie11( lval 9}) */ hie11(lval) struct expent * lval; { int k; k = primary(lval); if ((curtok < LBRACK) || (curtok > PREF)) { 9} return (k); } else { struct expent lval2; char * svptr; char * tptr; char * tptr2; 9} while (1) { if (curtok == LBRACK) { gettok(); exprhs(k, lval); svptr = outqi; push(); 9} /* TOS now contains ptr to array elements. */ exprhs(hie0(&lval2), &lval2); needbrack(RB9}RACK); if ((tptr = lval->e_tptr)[0] & T_POINTER) { if (tptr[0] == T_ARRAY) lval->e_tptr += 3; cscale(&9}lval2, SizeOf(++lval->e_tptr)); if ((lval2.e_flags == E_MCONST) && (lval2.e_const == 0)) { popsp();9} outqi = svptr; goto end_array; } } else if ((tptr2 = lval2.e_tptr)[0] & T_POINTER) { if9} (tptr2[0] == T_ARRAY) lval2.e_tptr += 3; swapstk(); scale(SizeOf(++lval2.e_tptr)); lval->e_tptr = lval2.e_9}tptr; } else { Error("cannot subscript"); } add(); end_array: lval->e_flags = E_MEXPR; 9} k = lval->e_tptr[0] != T_ARRAY; } else if (curtok == LPAREN) { gettok(); if (lval->e_tptr[0] 9}!= T_FUNC) { Illegal("function call"); } callfunction(k, lval); lval->e_test = E_CC; /* funs always ret:}urn cond codes */ lval->e_flags = E_MEXPR; ++lval->e_tptr; k = 0; } else if (curtok == DOT) :} { k = opref(k, lval); } else if (curtok == PREF) { k = oppref(k, lval); } else retur:}n (k); } } } /* primary( lval ) This is the lowest level of the expression parser. */ int primary(lval) struct expe:}nt * lval; { int k; struct hashent * psym; char * tptr; int type; lval->e_test = 0; /* not a test at all, yet */ :} if (curtok == IDENT) { psym = (struct hashent *) curval; gettok(); /* check local symbol tabl:}e. */ if (psym->h_loc != 0) { lval->e_tptr = tptr = psym->h_ltptr; if (psym->h_loc & SC_STACK) { #ifd:}ef oldM6502 getladr(psym->h_ldata); lval->e_flags = E_MEXPR; #else lval->e_flags = E_MLOCAL | E_TLOFFS; :}#endif } else { lval->e_flags = E_MGLOBAL | E_TGLAB; } lval->e_const = psym->h_ldata; if ((tpt:}r[0] == T_FUNC) || (tptr[0] == T_ARRAY)) { return (0); } return (1); } /* check global sym: }bol table. */ if (psym->h_glb != 0) { if ((type = psym->h_glb) & SC_STRUCT) { Error("struct tag/f: }ld cannot be primary"); return (0); } lval->e_tptr = tptr = psym->h_gtptr; lval->e_const = psym->h_gdata; #: }ifndef M6502 /* don't do enums in the native compiler, to save space */ if (type == SC_ENUM) { lval->e_flag: }s = E_MCONST; return (0); } else #endif { lval->e_flags = E_MGLOBAL | E_MCONST | E_TGLAB; } : } if ((tptr[0] == T_FUNC) || (tptr[0] == T_ARRAY)) { return (0); } return (1); } /* IDENT :}is either an auto-declared function or an undefined variable. */ if (curtok == LPAREN) { /* decl:}are function returning int. */ addglb(psym, type_ifunc, SC_EXTERN); lval->e_tptr = Lmalloc(3); strcpy(lval->e_tpt:}r, type_ifunc); lval->e_flags = E_MGLOBAL | E_TGLAB; lval->e_const = psym->h_gdata; return (0); } addloc(psym:}, type_int, SC_STACK, 0); lval->e_flags = E_MLOCAL | E_TLOFFS; lval->e_tptr = type_int; lval->e_const = 0; :} Error("undefined symbol"); return (1); } /* Character and integer constants. */ if ((curtok == ICO:}NST) || (curtok == CCONST)) { lval->e_flags = E_MCONST | E_TCONST; lval->e_tptr = type_int; lval->e_con:}st = curval; gettok(); return (0); } /* Process parenthesized subexpression by calling the whole parse:}r recursively. */ if (curtok == LPAREN) { gettok(); k = hie0(lval); needbrack(RPAREN); re:}turn (k); } /* String literals. */ if (curtok == SCONST) { char tarray[6]; lval->e_flags = E_:}MCONST | E_TLIT; tarray[0] = T_ARRAY; encode(tarray + 1, strlen(litq + curval) + 1); tarray[4] = T_CHAR; :} tarray[5] = '\0'; lval->e_tptr = Lmalloc(strlen(tarray) + 1); strcpy(lval->e_tptr, tarray); lval->e_con:}st = curval; gettok(); return (0); } /* Illegal primary. */ Error("invalid expression"); lval->e:}_flags = E_MCONST; lval->e_tptr = type_int; return (0); } /* true if val1 -> int pointer or int array and val2 not p:}tr or array. used to decide whether to shift value left 1 when indexing. */ scale(n) int n; { if (n == 2) { do:}ublereg(); } else if (n != 1) { push(); immed(); #ifndef M6502 if (n == 4) { outdecnl(2); :}asl(); return; } else if (n == 8) { outdecnl(3); asl(); return; } #endif outdecnl(n); mult():}; } } cscale(lval, n) struct expent * lval; int n; { /* if (lval->e_flags == E_MCONST) { lval->e_const *= n; rmvby:}te(4); lconst(E_TCONST, lval->e_const); } else { */ scale(n); /* } */ } decrem(n) int n; { #ifdef old_cruft if (n : }<= 4) { while (n--) dec(); } else { push(); immed(); outdecnl(n); sub(); } #:!}else if (n <= 2) { oljsr((n == 1) ? "decax1" : "decax2"); } else { push(); immed(); o:"}utdecnl(n); sub(); } #endif } increm(n) int n; { #ifdef old_cruft if (n <= 4) { while (n--) inc(); :#} } else { push(); immed(); outdecnl(n); add(); } #else if (n <= 8) { ot("\tjsr:$}\tincax"); /* use the canned incax1..8 ops */ outdecnl(n); } else { konst3(n); /* load Y with number *:%}/ oljsr("indexax"); /* use indexing op */ } #endif } #ifdef old_cruft /* determine type of binary operation */:&} result(lval, lval2) struct expent * lval; struct expent * lval2; { } #endif /* store( lval ) Store primary reg into this :'}reference */ store(lval) struct expent * lval; { int f; f = lval->e_flags; #ifndef M6502 if (f == 0) { fatal(":(}e_flags == 0"); } #endif if (f & E_MGLOBAL) { putmem(lval->e_const, lval->e_tptr); } else if (f & E_MLO:)}CAL) { putloc(lval->e_const, lval->e_tptr); } else if (f & E_MEXPR) { putstk(lval); } else :*} { #ifdef M6502 fatal("err 1"); #else fatal("trying to store into constant"); #endif } } /* exprhs( k, lv:+}al ) */ exprhs(k, lval) int k; struct expent * lval; { int f; int immed(); f = lval->e_flags; if (k) /* reference :,}storable-p */ { if (f & E_MGLOBAL) /* ref to globalvar */ { /* getmem(lval->e_const, lval->e_tptr); -- jrd :-}*/ getmem(lval->e_const, lval->e_tptr, lval->e_test); } else if (f & E_MLOCAL) /* ref to localvar */ { getloc(l:.}val->e_const, lval->e_tptr); } else if (f & E_MCONST) /* ref to constant */ { #ifdef M6502 fatal("err 2"); #else :/} fatal("Constant with k = 1"); #endif } else { indirect(lval); /* else must be locative */ } /* lval->e_te:0}st |= E_CC; .. say we set cc (all those do...) */ } else /* reference not storable */ if (f == E_MEOFFS) :1} { push(); immed(); /* outdec(lval->e_const); */ outdecnl(lval->e_const); /* -- jrd */ add(); } else if (f:2} != E_MEXPR) { lconst(f & E_MCTYPE, lval->e_const); } /* lval->e_test &= ~E_CC; /* say cc not set right */ :3} if (lval->e_test & E_TEST) /* we testing this value? */ { #ifndef M6502 /* debug... */ ol(";;; force test");:4} #endif tst(); /* yes, force a test */ } } /* liconst( const ) Load primary reg with integer constant. */ lic:5}onst(cnst) int cnst; { immed(); outdecnl(cnst); } /* lconst( func, ctype, const ) Load primary reg with some constant :6}value. */ lconst(ctype, cnst) int ctype; int cnst; { ctype &= E_MCTYPE; if (ctype == E_TLOFFS) { getladr(cnst);:7} } else { immed(); outconst(ctype, cnst, 0); } } /* outconst(ctype, const, ischar) Output psuedo:8}-op appropriate to type of constant. */ outconst(ctype, cnst, ischar) int ctype; int cnst; int ischar; { switch (ctype & E_:9}MCTYPE) { case E_TCONST: /* fixnum constant */ outdecnl(cnst); return; case E_TGLAB: /* some kind o::}f global */ outgbl(cnst); nl(); return; case E_TLIT: /* a literal of some kind */ outslt(cnst); :;} return; default: #ifdef M6502 fatal("err 3"); #else printf("unknown constant: %d\n", ctype & E_MCTYPE);:<} fatal("compiler error: unknown constant type"); #endif } } /* test( label ) Generate code to perform test and j:=}ump if false. */ test(label) int label; { int k; struct expent lval; #ifndef M6502 bzero(&lval, sizeof(lval)); #endif ne:>}edbrack(LPAREN); k = expr(hie0, &lval); /* generate code to eval the expr */ /* #ifndef M6502 */ if (lval.e_flags == E_MC:?}ONST) { if (lval.e_const == 0) { jump(label); Warning("unreachable code"); } needbrack(RPAREN); :@} return; } /* #endif */ /* if the expr hasn't set condition codes, set the force-test flag */ if (!(lval.e_test :A}& E_CC)) lval.e_test |= E_TEST; exprhs(k, &lval); /* load the value as apropriate */ needbrack(RPAREN); #ifndef M650:B}2 if (lval.e_test & E_XINV) ol(";;; test inverted"); #endif falsejump(label, lval.e_test & E_XINV); } /* needbrack(:C} btype ) Enforce closing bracket type. */ needbrack(btype) int btype; { needtok(btype, "bracket"); } /* callfunction(ptr:D}) Perform a function call. Called from hie11, this routine will either call the named function, or if the supplied ptr is :E}zero, will call the contents of P. */ callfunction(k, lval) int k; struct expent * lval; { char * dptr; struct expent lval2;:F} int nargs; nargs = 0; if (lval->e_flags & E_MEXPR) { save(); } while (curtok != RPAREN) { exp:G}rhs(hie1(&lval2), &lval2); push(); nargs += 2; if (curtok != COMMA) break; gettok(); } needbra:H}ck(RPAREN); if (lval->e_flags & E_MEXPR) { rstr(); /* push(); not needed -- jrd. we call (AX) */ callstk(:I}nargs); } else { call(lval->e_const, nargs); } } /* opref( lval ) Process . operator. */ int opref(k, :J}lval) int k; struct expent * lval; { if (!(lval->e_tptr[0] & T_STRUCT)) { Need("struct"); } if (!(lval->e_f:K}lags & E_MEXPR)) { lconst(lval->e_flags & E_MCTYPE, lval->e_const); } return (structref(lval)); } /* oppref:L}( k, lval ) Process -> operator. */ int oppref(k, lval) int k; struct expent * lval; { char * tptr; tptr = (char *) lval-:M}>e_tptr; if ((tptr[0] != T_PTR) || !(tptr[1] & T_STRUCT)) { Need("struct pointer"); } exprhs(k, lval); re:N}turn (structref(lval)); } /* structref( lval ) Process struct field after . or ->. */ int structref(lval) struct expent * :O}lval; { struct hashent * psym; gettok(); if (curtok != IDENT) { Syntax(); lval->e_tptr = type_int; :P} return (0); } psym = (struct hashent *) curval; gettok(); #ifdef M6502 /* until such time as we fix cc65 to gener:Q}ate fetches of unsigned chars correctly, must mask here... if (psym->h_glb != SC_SFLD) */ if ((psym->h_glb & 0xFF) != :R}SC_SFLD) #else if ((psym->h_glb & 0xFF) != SC_SFLD) #endif { Need("struct field"); lval->e_tptr = type_int;:S} return (0); } lval->e_const = psym->h_gdata; lval->e_tptr = Lmalloc(strlen(psym->h_gtptr) + 1); strcpy(lval:T}->e_tptr, psym->h_gtptr); lval->e_flags = E_MEOFFS; if (psym->h_gtptr[0] == T_ARRAY) { return (0); } retu:U}rn (1); } /* getlabel() Get next unused label. */ getlabel() { return (++nxtlab); } { return (0); } retu8Y;#define FIXARGC ;/* stuff that should make it into the library? */ ;printmsg(str, arg) ;char * str; _printmsg: jsr ent>W}erfun2 ;int arg; ;{ ; tprintf(str, arg); jsr pushwysp4 jsr pushwysp4 ;} ldy #2 jsr _tprintf ;#define NOARGC; ;>X}/* check for break key, abort if user pressed it */ ;extern char BRK; jmp exitfun ;#asm ;_BRK = $11 _BRK = $11 ;#endas>Y}m ;chkbrk() ;{ ; if (BRK == 0) /* break key not pressed? */ _chkbrk: jsr enterfun0 ldx #0 lda _BRK jsr pushax >Z}; { ldax #0 jsr toseqax ; closeall(); /* close all open files */ ;;; falsejump lbeq L2 ; BRK = -1; jsr _closeall >[} ; printmsg("Aborted!\n", 0); ldax #-1 sta _BRK ldax #L1+0 jsr pushax jsr push0 ; exit(0); jsr _printmsg jsr p>\}ush0 ; } jsr _exit ;} ;/* check for stack overflow */ ;extern int _himem; L2: jmp exitfun L1: .byte 65,98,111,114>]},116,101,100,33,-101,0 ;chkstk() ;{ ; int dummy; _chkstk: jsr enterfun0 ; if (((int)&dummy - _himem) < 16) jsr dec>^}sp2 ldy #0 jsr plocysp lda __himem ldx __himem+1 jsr subtos jsr pushax ; { ldax #16 jsr tosltax ; PError("!>_}!", "Stack overflow"); ;;; falsejump lbeq L4 ldax #L3+0 jsr pushax ldax #L3+3 jsr pushax ; fatal("Giving up"); >`}jsr _PError ldax #L3+18 jsr pushax ; } jsr _fatal ;} L4: jsr incsp2 jmp exitfun L3: .byte 33,33,0,83,116,97,9>a}9,107,32,111,118,101,114,102,108,111 .byte 119,0,71,105,118,105,110,103,32,117,112,0 .globl _fatal .globl _PError .gl>b}obl _chkstk .globl __himem .globl _exit .globl _closeall .globl _chkbrk .globl _BRK .globl _tprintf .globl _pri>c}ntmsg kstk .globl __himem .globl _exit .globl _closeall .globl _chkbrk .globl _BRK .globl _tprintf .globl _pri< /* C functions definitions */ #include #include "cc65.h" #include "cclex.h" extern char * Lmalloc(); extern struBe}ct hashent * decl(); extern struct hashent * declare(); #ifndef M6502 extern int outcnt; extern int stats; #endif /* ParseBf} function dummy arguments. */ funargs() { n_funargs = 0; /* -- jrd */ if (curtok == RPAREN) { gettok(); Bg} return; } if (lovptr != 0) { fatal("err 4"); } while (1) { if (curtok == IDENT) { addloBh}c((struct hashent *) curval, NULL, SC_STACK, 0); ++n_funargs; /* -- jrd. count the arg */ gettok(); } else { Bi} Syntax(); } if (curtok == COMMA) { gettok(); } else if (curtok == RPAREN) { gettok(); break; } Bj} else { Syntax(); } } } /* declargs( ) Process argument declarations. */ declargs() { int i; char * p; Bk} struct hashent * psym; struct hashent * sadr; int stoff; char tarray[MAXTYPELEN]; char * tptr; int type; whileBl} ((curtok != LCURLY) /* && (curtok != ASM) */ ) { getsclass(1, SC_STACK); type = gettype(INT, &sadr); wBm}hile (1) { absdecl = 0; if ((psym = declare(tarray, type, sadr)) != NULL) { if (psym->h_loc == 0) { Bn}Error("declaration of parameter not in argument list"); addloc(psym, tarray, SC_STACK, 0); } else { tptr =Bo} Lmalloc(strlen(tarray) + 1); strcpy(tptr, tarray); if (tptr[0] == T_ARRAY) { (tptr += 3)[0] = T_PTR; Bp} } psym->h_ltptr = tptr; } } if (curtok != COMMA) break; gettok(); } if (curtok == SEMI) {Bq} gettok(); } } /* Assign offsets and default undeclared arguments to int. */ tarray[0] = T_INT; tarray[1Br}] = '\0'; stoff = 2; for (i = lovptr - 1; i >= 0; --i) { psym = lvtab[i]; tptr = psym->h_ltptr; if Bs}(tptr == NULL) { /* * default to "int" */ tptr = Lmalloc(2); strcpy(tptr, tarray); psym->h_ltptr = tptr;Bt} } psym->h_ldata = stoff; stoff += (SizeOf(tarray) + 1) & (~1); } } /* newfunc( psym ) Parse argument dBu}eclarations and function body. */ newfunc(psym) struct hashent * psym; { #ifndef M6502 int sbyte; #endif #ifdef M6502 if Bv}(verbose) { printmsg("\034\n\234%s\n", psym->h_name); } #endif psym->h_glb |= SC_DEFINED; /* this busted?? Bw} outcdf(psym->h_gdata); -- jrd */ startfun(psym->h_name); /* start a function preamble */ declargs(); #ifdef old_cruBx}ft if (curtok == ASM) { struct expent lval; gettok(); /* outbyte(0); constexp(&lval); outconst(lvBy}al.e_flags, lval.e_const, 0); */ ns(); } else #endif { if (curtok != LCURLY) { Syntax(); } Bz}oursp = 0; #ifndef M6502 sbyte = outcnt; #endif if (!compound()) { ret(); dumplits(); n_funargs = -1; /B{}* reset arg counter */ } #ifndef M6502 if (stats) { printf("%s: %d bytes\n", psym->h_name, outcnt - sbyte); } #enB|}dif } } /* declloc() Declare local variables. */ declloc() { int offs; int lab; int varlab; char * p; struB}}ct hashent * psym; struct hashent * sadr; int sc; char tarray[MAXTYPELEN]; int type; offs = oursp; while (1) B~} { sc = getsclass(1, SC_STACK); if ((type = gettype(0, &sadr)) == 0) break; while (1) { absdecl = 0; B} psym = declare(tarray, type, sadr); { int siz; if (tarray[0] != T_FUNC) siz = SizeOf(tarray); eB}lse siz = 2; addloc(psym, tarray, sc, offs - siz); } if (tarray[0] != T_FUNC) { if (sc & SC_STAB}CK) { offs -= SizeOf(tarray); } else if (sc == SC_STATIC) { jump(lab = getlabel()); outcdf(psym->h_lB}data = getlabel()); outsp(SizeOf(tarray)); outcdf(lab); } } if (curtok != COMMA) break; gettok(); B} } if (curtok == SEMI) { gettok(); } } oursp = modstk(offs); } f (curtok != COMMA) break; gettok(); @P /* Level 0 parsing */ #include #include "cc65.h" #include "cclex.h" int hie1(); /* parseinit() */ parseinitF}(tptr) char * tptr; { int count; int i; struct expent lval; struct hashent * p; struct hashent * q; char * str; F} int sz; switch (tptr[0]) { case T_INT: case T_UINT: case T_CHAR: case T_UCHAR: case T_PTR: F}constexp(&lval); /* if (tptr[0] == T_CHAR) */ if (char_t_p(tptr)) bytepref(); else wordpref(); /* oF}utconst(lval.e_flags, lval.e_const, tptr[0] == T_CHAR); */ outconst(lval.e_flags, lval.e_const, char_t_p(tptr)); F}break; case T_ARRAY: sz = decode(tptr + 1); if ((tptr[4] == T_CHAR) && (curtok == SCONST)) { str = &litq[F}curval]; count = strlen(str) + 1; /* outdat(count); i = 0; while (++i <= count) outbyte(*str++); */F} outbv(str, count); litptr -= count; gettok(); } else { needbrack(LCURLY); count = 0; while (curtoF}k != RCURLY) { parseinit(tptr + 4); ++count; if (curtok != COMMA) break; gettok(); } F} needbrack(RCURLY); } if (sz == 0) { encode(tptr + 1, count); } else if (count < sz) { outzero((sz - F}count) * SizeOf(tptr + 4)); } else if (count > sz) { toomany(); } break; default: if (tptr[0] & TF}_STRUCT) { needbrack(LCURLY); /* jrd hacked this */ #ifdef M6502 q = (struct hashent *) decode(tptr); /* old way *F}/ #else q = (struct hashent *) (((int) decode(tptr)) + (int) gblspace); /* decode offset from glbspace*/ #endif p =F} q->h_link; while (curtok != RCURLY) { if (p == NULL) { toomany(); return; } parseinit(p->hF}_gtptr); p = p->h_link; if (curtok != COMMA) break; gettok(); } needbrack(RCURLY); while (pF} != NULL) { outzero(SizeOf(p->h_gtptr)); p = p->h_link; } } #ifndef M6502 else { fprintf(sF}tderr, "unknown type: %02x\n", tptr[0]); } #endif } } outzero(n) int n; { /* outdat(n); while (--n >= 0) { ouF}tbyte(0); } */ ot("\t.blkb\t"); outdec(n); nl(); } constexp(lval) struct expent * lval; { expr(hie1, lval); if ((F}lval->e_flags & E_MCONST) == 0) { Need("constant expression"); } } toomany() { Error("too many initializers"F}); } >e_flags & E_MCONST) == 0) { Need("constant expression"); } } toomany() { Error("too many initializers"D /* CC65 global var declarations. These are extern'ed in cc65.h */ #include #include "cc65.h" #ifndef CCPAGJ}E0 /* only declare these of not doing page 0 stuff */ int curtok; /* current token seen by parser */ int curval; /* somethJ}ing or other, depending on curtok */ int nxttok; int nxtval; int absdecl; /* int critic; */ int glblbl; char * gsptr; int haJ}shval; int lovptr; char * lsptr; char macdef; /* T if any defines defined */ char * outqi; int outqsz; int tbllen; char * tbJ}lptr; int * wqptr; /* ptr to next entry */ int litptr; /* ptr to next entry in literal pool */ char * lptr; char * mptr; J}/* ptrs into each */ #endif /* ccpage0 */ /* char glbspace[GSPACE]; */ char * gblspace; /* global heap */ char * gblend; /J}* global space limit */ struct hashent * glvptr; int i_ifdef; char locspace[LSPACE]; char outq[OUTQSZ]; /* buf for asm stuffJ} being output */ /* int ret_addr; */ char s_ifdef[N_IFDEF]; int litlab; /* current lit pool labl */ int litspace = 0; /* toJ}tal lit space used */ /* Misc storage */ int nxtlab, /* next avail label # */ /* compiler relative stk ptr */ #ifndef CCPAJ}GE0 oursp, argstk, /* function arg sp */ #endif /* # open compound statements */ ncmp, /* # errors in compilation */ J} errcnt, /* set non-zero on final input eof */ eof, /* non-zero if internal globals */ glbflag; struct filent filJ}etab[MAXFILES]; int ifile; FILE * inp; FILE * output; int ln; char * fin; char fname[80]; /* Canned typespecs */ /* chaJ}r * type_char = "\021"; unused? */ char * type_int = "\022"; char * type_ifunc = "\007\022"; char linebuf[linesize]; char * J}line = linebuf; char mlinebuf[linesize]; char * mline = mlinebuf; char macltab[256]; int wq[wqtabsz]; /* while queue */ char J}litq[litabsz]; struct hashent * lvtab[128]; int * kwptr; #ifdef M6502 #else struct hashent * htab[HTABSZ]; char * macarg[MAJ}CARGSZ]; char * machtab[HTABSZ]; #endif char optimize = 0; /* optimize flag */ char verbose = 0; /* verbose flag */ int n_J}funargs = 0; /* for use by funarg parser */ int asm_kludge = 0; /* see preproc, lex */ char * incl_dir = 0; /* dir for incJ}lude files */ /* char get_test = 0; /* flag for doif etc to tell getmem to generate a test, not a load */ #ifndef M650J}2 char source = 0; /* include source in m65 */ #endif tc to tell getmem to generate a test, not a load */ #ifndef M650H7 /* C I/O functions */ #include #ifndef M6502 /* every time I thing some C weenie someplace might have opted to doN} something in a regular fashion, I get disappointed... */ #include #endif #include "cc65.h" #include "cclex.h" N}#ifndef M6502 int outcnt = 0; #endif /* not used? char ascii_tab[128] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, N}0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2,N} 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,N} 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };N} */ /* alpha( c ) Test if given character is alpha. */ /* not used... alpha(c) int c; { return( ascii_tab[c] & 1 ); N}} */ /* numeric( c ) Test if given character is numeric */ /* not used numeric(c) int c; { return( ascii_tab[c] & 2 N}); } */ /* an( c ) Test if given character is alphanumeric */ /* not used an(c) int c; { return( ascii_tab[c] ); } *N}/ /* pl( str ) Print a string followed by a carriage return. */ /* not used? pl(str) char * str; { printf("%s\n", stN}r); } */ /* apparently, all callers of this have been redefined with defines.... ch() { #ifdef M6502 return( *lptr );N} #else return( *lptr & 0xFF ); #endif } */ #ifdef M6502 #asm .globl _nch _nch: ldx #0 ldy #0 lda (_lptr),y beq nch1N} iny lda (_lptr),y nch1: rts #endasm #else nch() { if (*lptr == '\0') { return (0); } else { #ifdef N}M6502 return (lptr[1]); #else return (lptr[1] & 0xFF); #endif } } #endif /* cgch() Get the current charN}acter in the input stream and advance line pointer (unless already at end of line). */ #ifdef M6502 #asm .globl _cgch _cgcN}h: ldx #0 ldy #0 lda (_lptr),y bne cgch1 rts cgch1: inc _lptr bne cgch2 inc _lptr+1 cgch2: cmp #0 ; return cond codN}es rts #endasm #else cgch() { if (*lptr == '\0') { return (0); } else { #ifdef M6502 return (*lpN}tr++); #else return (*lptr++ & 0xFF); #endif } } #endif /* gch() Get the current character in the input streaN}m and advance line pointer (no end of line check is performed). */ #ifdef M6502 #asm .globl _gch _gch: ldx #0 lda (_lptrN},x) inc _lptr bne gch1 inc _lptr+1 gch1: cmp #0 ; return cond codes rts #endasm #else gch() { #ifdef M6502 return (*lN}ptr++); #else return (*lptr++ & 0xFF); #endif } #endif #ifdef M6502 #asm .globl _kill _kill: lda _line sta _lptr lda N}_line+1 sta _lptr+1 ldx #0 txa sta (_lptr,x) rts #endasm #else kill() { lptr = line; *lptr = '\0'; } #endif /* rN}eadline() Get a line from the current input. Returns -1 on end of file. */ readline() { int k; int len; struct filent * pfN}tab; while (1) { kill(); if (inp == 0) { eof = 1; return (0); } #ifdef old_cruft k = ciov(inN}p, 5, line, linesize, -1, -1); poke(CRITIC, critic); len = dpeek(0x348 + (inp << 4)); #else k = (int) fgetsN}(line, linesize, inp); len = strlen(line); #endif ++ln; if (k <= 0) /* eof? */ { line[len] = '\0'; cN}close(inp); /* fclose(inp); */ if (ifile > 0) { inp = (pftab = &filetab[--ifile])->f_iocb; ln = pfN}tab->f_ln; fin = pftab->f_name; } else { inp = 0; } } else { line[len - 1] = '\0';N} #ifndef M6502 if (source && (strlen(line) > 0)) { /* flushout(); this is broken... */ /* cout(';'); sout(line)N}; cout('\n'); */ ot(";"); ol(line); } #endif } if (len) { lptr = line; return (1); } N}} } /* flushout() Flush output queue */ flushout() { *outqi = '\0'; peephole(outq); outqi = outq; } /* Output cN}har c to assembler file. Really just goes out to buffer, so the optimizer can work on it. */ #ifdef M6502 #asm .globl _ouN}tchar _outchar: jsr popax ldy #0 sta (_outqi),y inc _outqi bne *+4 inc _outqi+1 rts #endasm #else outchar(c) char c; {N} #ifndef M6502 ++outcnt; #endif *outqi++ = c; } #endif #ifdef old_cruft /* rmvbyte( n ) Remove n bytes from output N}stream. */ rmvbyte(n) int n; { outqi -= n; } #endif /* out char to real output file */ cout(ch) char ch; { errno = 0; N} fputc(ch, output); if (errno != 0) { printmsg("IO error #x%x\n", errno); #ifdef M6502 closeall(); #endif N} exit(1); } } /* out string to real output file */ #ifdef M6502 #asm .globl _sout _sout: jsr popax sta ptr4 stx N}ptr4+1 sout1: ldy #0 lda (ptr4),y beq sout2 ldx #0 jsr pushax ldy #1 jsr _cout inc ptr4 bne sout1 inc ptr4+1 jmp sN}out1 sout2: rts #endasm #else sout(s) char * s; { while (*s) cout(*s++); } #endif ptr4 bne sout1 inc ptr4+1 jmp sLZ?.