diff --git a/.gitignore b/.gitignore index 150806c6c..1d5928af7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ /bin/ /emd/ +/html/ +/info/ /joy/ /lib/ +/libwrk/ /mou/ /ser/ /targetutil/ diff --git a/.travis.yml b/.travis.yml index ffec9e605..a11412230 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,16 @@ -language: c -script: make +language: + - c +install: + - sudo apt-get install linuxdoc-tools linuxdoc-tools-info binutils-mingw-w64-i686 gcc-mingw-w64-i686 sshpass +script: + - make bin USER_CFLAGS=-Werror + - make lib QUIET=1 + - make -C src clean + - make bin USER_CFLAGS=-Werror CROSS_COMPILE=i686-w64-mingw32- + - make doc zip +after_success: + - make -f Makefile.travis +env: + global: + - secure: "h+hoQdEHGPLNwaqGKmSaM8NBRDLc2X+W05VsnNG2Feq/wPv/AiBjONNlzN7jRf6D6f3aoPXaQ2Lc3bYWdxGvFRCmwiofdxkJI9n5L8HPHLZ2lf37MQsXmGJzoTFOvjPLj73H6HlbI9Ux0El3zO6hvalxiXj6TfoZ41dbhNyvpYk=" + - secure: "A4hMEe5RRfUtYjFGbT7QAvT1Tyo434N+/TiuQeQ4q0L46c79LnXuGQzbFLOFZshZiplLkJr7lFg466CoI1bf2L0cQOew/LesMhE75v0HQ7tZnExWhdpAk0ri6nWixbjn/dmQ0+HxjzJ48A44DMMBYcvSIsO4vflvuJ8etfSg42k=" diff --git a/Makefile b/Makefile index d5a522871..e0530e9f0 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,11 @@ -all mostlyclean clean: +.PHONY: all mostlyclean clean install zip avail unavail bin lib doc + +.SUFFIXES: + +all mostlyclean clean install zip: @$(MAKE) -C src --no-print-directory $@ @$(MAKE) -C libsrc --no-print-directory $@ + @$(MAKE) -C doc --no-print-directory $@ avail unavail bin: @$(MAKE) -C src --no-print-directory $@ @@ -8,12 +13,11 @@ avail unavail bin: lib: @$(MAKE) -C libsrc --no-print-directory $@ +doc: + @$(MAKE) -C doc --no-print-directory $@ + %65: @$(MAKE) -C src --no-print-directory $@ %: @$(MAKE) -C libsrc --no-print-directory $@ - -.PHONY: all mostlyclean clean avail unavail bin lib - -.SUFFIXES: diff --git a/Makefile.travis b/Makefile.travis new file mode 100644 index 000000000..6f83e2439 --- /dev/null +++ b/Makefile.travis @@ -0,0 +1,37 @@ +.PHONY: all gh-pages sf-files + +.SUFFIXES: + +all: gh-pages sf-files + +GH_NAME = Oliver Schmidt +GH_MAIL = ol.sc@web.de +GH_PATH = ../gh-pages + +gh-pages: +ifdef GH_TOKEN + @echo 'git clone --branch=gh-pages https://$$(GH_TOKEN)@github.com/cc65/cc65.git $(GH_PATH)' + @git clone --branch=gh-pages https://$(GH_TOKEN)@github.com/cc65/cc65.git $(GH_PATH) + cd $(GH_PATH) && git config user.name "$(GH_NAME)" + cd $(GH_PATH) && git config user.email "$(GH_MAIL)" + cd $(GH_PATH) && git config push.default simple + cd $(GH_PATH) && $(RM) -r doc + cd $(GH_PATH) && mkdir doc + cp html/*.* $(GH_PATH)/doc + cd $(GH_PATH) && git add -A doc + -cd $(GH_PATH) && git commit -m "Updated from commit $(TRAVIS_COMMIT)." + cd $(GH_PATH) && git push +endif + +SF_USER = oliverschmidt +SF_HOST = frs.sourceforge.net +SF_FILE = /home/frs/project/cc65/cc65-snapshot-win64.zip + +SCPFLAGS = -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -q + +sf-files: +ifdef SF_PASS + echo $(TRAVIS_COMMIT) | zip -z cc65 + @echo 'sshpass -p $$(SF_PASS) scp $(SCPFLAGS) cc65.zip $(SF_USER)@$(SF_HOST):$(SF_FILE)' + @sshpass -p $(SF_PASS) scp $(SCPFLAGS) cc65.zip $(SF_USER)@$(SF_HOST):$(SF_FILE) +endif diff --git a/README b/README deleted file mode 100644 index 0bb161677..000000000 --- a/README +++ /dev/null @@ -1,32 +0,0 @@ -cc65 is a complete cross development package for 65(C)02 systems, including -a powerful macro assembler, a C compiler, linker, librarian and several -other tools. - -cc65 has C and runtime library support for many of the old 6502 machines, -including - - - the following Commodore machines: - VIC20 - C16/C116 and Plus/4 - C64 - C128 - CBM 510 (aka P500) - the 600/700 family - newer PET machines (not 2001). - - - the Apple ][+ and successors. - - - the Atari 8 bit machines. - - - GEOS for the C64 and C128. - - - the Nintendo Entertainment System (NES). - - - the Supervision console. - - - the Oric Atmos. - - - the Lynx console. - -The libraries are fairly portable, so creating a version for other 6502s -shouldn't be too much work. diff --git a/README.md b/README.md new file mode 100644 index 000000000..81805f03b --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +[documentation](http://cc65.github.io/cc65/doc) + +[wiki](https://github.com/cc65/wiki/wiki) + +[![build status](https://travis-ci.org/cc65/cc65.png)](https://travis-ci.org/cc65/cc65/builds) + +cc65 is a complete cross development package for 65(C)02 systems, including +a powerful macro assembler, a C compiler, linker, librarian and several +other tools. + +cc65 has C and runtime library support for many of the old 6502 machines, +including + +- the following Commodore machines: + - VIC20 + - C16/C116 and Plus/4 + - C64 + - C128 + - CBM 510 (aka P500) + - the 600/700 family + - newer PET machines (not 2001). +- the Apple ][+ and successors. +- the Atari 8 bit machines. +- the Atari 5200 console. +- GEOS for the C64, C128 and Apple //e. +- the Nintendo Entertainment System (NES) console. +- the Supervision console. +- the Oric Atmos. +- the Lynx console. + +The libraries are fairly portable, so creating a version for other 6502s +shouldn't be too much work. diff --git a/asminc/atari.inc b/asminc/atari.inc index c60f6642d..3cce03046 100644 --- a/asminc/atari.inc +++ b/asminc/atari.inc @@ -318,7 +318,7 @@ APPMHI = $0E ;APPLICATIONS MEMORY HI LIMIT INTZBS = $10 ;INTERRUPT HANDLER -POKMSK = $10 ;SYSTEM MASK FOR POKEY IRG ENABLE +POKMSK = $10 ;SYSTEM MASK FOR POKEY IRQ ENABLE (shadow of IRQEN) BRKKEY = $11 ;BREAK KEY FLAG RTCLOK = $12 ;REAL TIME CLOCK (IN 16 MSEC UNITS> BUFADR = $15 ;INDIRECT BUFFER ADDRESS REGISTER @@ -485,10 +485,10 @@ VKEYBD = $0208 ;POKEY KEYBOARD IRQ VECTOR VSERIN = $020A ;POKEY SERIAL INPUT READY IRQ VSEROR = $020C ;POKEY SERIAL OUTPUT READY IRQ VSEROC = $020E ;POKEY SERIAL OUTPUT COMPLETE IRQ -VTIMR1 = $0210 ;POKEY TIMER 1 IRG -VTIMR2 = $0212 ;POKEY TIMER 2 IRG -VTIMR4 = $0214 ;POKEY TIMER 4 IRG -VIMIRQ = $0216 ;IMMEDIATE IRG VECTOR +VTIMR1 = $0210 ;POKEY TIMER 1 IRQ +VTIMR2 = $0212 ;POKEY TIMER 2 IRQ +VTIMR4 = $0214 ;POKEY TIMER 4 IRQ +VIMIRQ = $0216 ;IMMEDIATE IRQ VECTOR CDTMV1 = $0218 ;COUNT DOWN TIMER 1 CDTMV2 = $021A ;COUNT DOWN TIMER 2 CDTMV3 = $021C ;COUNT DOWN TIMER 3 @@ -762,7 +762,15 @@ DOS = $0700 CARTCS = $BFFA ;##rev2## 2-byte cartridge coldstart address CART = $BFFC ;##rev2## 1-byte cartridge present indicator + ;0=Cart Exists CARTFG = $BFFD ;##rev2## 1-byte cartridge flags + ;D7 0=Not a Diagnostic Cart + ; 1=Is a Diagnostic cart and control is + ; given to cart before any OS is init. + ;D2 0=Init but Do not Start Cart + ; 1=Init and Start Cart + ;D0 0=Do not boot disk + ; 1=Boot Disk CARTAD = $BFFE ;##rev2## 2-byte cartridge start vector ;------------------------------------------------------------------------- @@ -770,83 +778,7 @@ CARTAD = $BFFE ;##rev2## 2-byte cartridge start vector ;------------------------------------------------------------------------- GTIA = $D000 ;CTIA/GTIA area - -; Read/Write Addresses - -CONSOL = $D01F ;console switches and speaker control - -; Read Addresses - -M0PF = $D000 ;missile 0 and playfield collision -M1PF = $D001 ;missile 1 and playfield collision -M2PF = $D002 ;missile 2 and playfield collision -M3PF = $D003 ;missile 3 and playfield collision - -P0PF = $D004 ;player 0 and playfield collision -P1PF = $D005 ;player 1 and playfield collision -P2PF = $D006 ;player 2 and playfield collision -P3PF = $D007 ;player 3 and playfield collision - -M0PL = $D008 ;missile 0 and player collision -M1PL = $D009 ;missile 1 and player collision -M2PL = $D00A ;missile 2 and player collision -M3PL = $D00B ;missile 3 and player collision - -P0PL = $D00C ;player 0 and player collision -P1PL = $D00D ;player 1 and player collision -P2PL = $D00E ;player 2 and player collision -P3PL = $D00F ;player 3 and player collision - -TRIG0 = $D010 ;joystick trigger 0 -TRIG1 = $D011 ;joystick trigger 1 - -TRIG2 = $D012 ;cartridge interlock -TRIG3 = $D013 ;ACMI module interlock - -PAL = $D014 ;##rev2## PAL/NTSC indicator - -; Write Addresses - -HPOSP0 = $D000 ;player 0 horizontal position -HPOSP1 = $D001 ;player 1 horizontal position -HPOSP2 = $D002 ;player 2 horizontal position -HPOSP3 = $D003 ;player 3 horizontal position - -HPOSM0 = $D004 ;missile 0 horizontal position -HPOSM1 = $D005 ;missile 1 horizontal position -HPOSM2 = $D006 ;missile 2 horizontal position -HPOSM3 = $D007 ;missile 3 horizontal position - -SIZEP0 = $D008 ;player 0 size -SIZEP1 = $D009 ;player 1 size -SIZEP2 = $D00A ;player 2 size -SIZEP3 = $D00B ;player 3 size - -SIZEM = $D00C ;missile sizes - -GRAFP0 = $D00D ;player 0 graphics -GRAFP1 = $D00E ;player 1 graphics -GRAFP2 = $D00F ;player 2 graphics -GRAFP3 = $D010 ;player 3 graphics - -GRAFM = $D011 ;missile graphics - -COLPM0 = $D012 ;player-missile 0 color/luminance -COLPM1 = $D013 ;player-missile 1 color/luminance -COLPM2 = $D014 ;player-missile 2 color/luminance -COLPM3 = $D015 ;player-missile 3 color/luminance - -COLPF0 = $D016 ;playfield 0 color/luminance -COLPF1 = $D017 ;playfield 1 color/luminance -COLPF2 = $D018 ;playfield 2 color/luminance -COLPF3 = $D019 ;playfield 3 color/luminance - -COLBK = $D01A ;background color/luminance - -PRIOR = $D01B ;priority select -VDELAY = $D01C ;vertical delay -GRACTL = $D01D ;graphic control -HITCLR = $D01E ;collision clear +.include "atari_gtia.inc" ;------------------------------------------------------------------------- ; PBI Address Equates @@ -862,6 +794,20 @@ PDVI = $D1FF ;##rev2## parallel device IRQ status PDVS = $D1FF ;##rev2## parallel device select +;------------------------------------------------------------------------- +; POKEY Address Equates +;------------------------------------------------------------------------- + +POKEY = $D200 ;POKEY area +.include "atari_pokey.inc" + +;------------------------------------------------------------------------- +; ANTIC Address Equates +;------------------------------------------------------------------------- + +ANTIC = $D400 ;ANTIC area +.include "atari_antic.inc" + ; PBI RAM Address Equates PBIRAM = $D600 ;##rev2## parallel bus interface RAM area @@ -874,52 +820,6 @@ PDIRQV = $D808 ;##rev2## parallel device IRQ vector PDID2 = $D80B ;##rev2## parallel device ID 2 PDVV = $D80D ;##rev2## parallel device vector table -;------------------------------------------------------------------------- -; POKEY Address Equates -;------------------------------------------------------------------------- - -POKEY = $D200 ;POKEY area - -; Read Addresses - -POT0 = $D200 ;potentiometer 0 -POT1 = $D201 ;potentiometer 1 -POT2 = $D202 ;potentiometer 2 -POT3 = $D203 ;potentiometer 3 -POT4 = $D204 ;potentiometer 4 -POT5 = $D205 ;potentiometer 5 -POT6 = $D206 ;potentiometer 6 -POT7 = $D207 ;potentiometer 7 - -ALLPOT = $D208 ;potentiometer port status -KBCODE = $D209 ;keyboard code -RANDOM = $D20A ;random number generator -SERIN = $D20D ;serial port input -IRQST = $D20E ;IRQ interrupt status -SKSTAT = $D20F ;serial port and keyboard status - -; Write Addresses - -AUDF1 = $D200 ;channel 1 audio frequency -AUDC1 = $D201 ;channel 1 audio control - -AUDF2 = $D202 ;channel 2 audio frequency -AUDC2 = $D203 ;channel 2 audio control - -AUDF3 = $D204 ;channel 3 audio frequency -AUDC3 = $D205 ;channel 3 audio control - -AUDF4 = $D206 ;channel 4 audio frequency -AUDC4 = $D207 ;channel 4 audio control - -AUDCTL = $D208 ;audio control -STIMER = $D209 ;start timers -SKRES = $D20A ;reset SKSTAT status -POTGO = $D20B ;start potentiometer scan sequence -SEROUT = $D20D ;serial port output -IRQEN = $D20E ;IRQ interrupt enable -SKCTL = $D20F ;serial port and keyboard control - ;------------------------------------------------------------------------- ; PIA Address Equates ;------------------------------------------------------------------------- @@ -932,33 +832,6 @@ PORTB = $D301 ;port B direction register or memory management PACTL = $D302 ;port A control PBCTL = $D303 ;port B control -;------------------------------------------------------------------------- -; ANTIC Address Equates -;------------------------------------------------------------------------- - -ANTIC = $D400 ;ANTIC area - -; Read Addresses - -VCOUNT = $D40B ;vertical line counter -PENH = $D40C ;light pen horizontal position -PENV = $D40D ;light pen vertical position -NMIST = $D40F ;NMI interrupt status - -; Write Addresses - -DMACTL = $D400 ;DMA control -CHACTL = $D401 ;character control -DLISTL = $D402 ;low display list address -DLISTH = $D403 ;high display list address -HSCROL = $D404 ;horizontal scroll -VSCROL = $D405 ;vertical scroll -PMBASE = $D407 ;player-missile base address -CHBASE = $D409 ;character base address -WSYNC = $D40A ;wait for HBLANK synchronization -NMIEN = $D40E ;NMI enable -NMIRES = $D40F ;NMI interrupt reset - ;------------------------------------------------------------------------- ; Floating Point Package Address Equates ;------------------------------------------------------------------------- @@ -1131,74 +1004,6 @@ MYDOS = 3 XDOS = 4 NODOS = 255 -;------------------------------------------------------------------------- -; Antic opcodes -;------------------------------------------------------------------------- - -; usage example: -; -; ScreenDL: -; .byte DL_BLK8 -; .byte DL_BLK8 -; .byte DL_CHR40x8x1 + DL_LMS + DL_DLI -; .word ScreenAlignment -; .byte DL_BLK1 + DL_DLI -; .byte DL_MAP320x1x1 + DL_LMS -; .word Screen -; -; .repeat 99 -; .byte DL_MAP320x1x1 -; .endrepeat -; .byte DL_MAP320x1x1 + DL_LMS -; .word Screen + 40 * 100 ; 100 lines a 40 byte, 'Screen' has to be aligned correctly! -; .repeat 92 -; .byte DL_MAP320x1x1 -; .endrepeat -; -; .byte DL_JVB - -; absolute instructions (non mode lines) - -DL_JMP = 1 -DL_JVB = 65 - -DL_BLK1 = 0 -DL_BLK2 = 16 -DL_BLK3 = 32 -DL_BLK4 = 48 -DL_BLK5 = 64 -DL_BLK6 = 80 -DL_BLK7 = 96 -DL_BLK8 = 112 - -; absolute instructions (mode lines) - -DL_CHR40x8x1 = 2 ; monochrome, 40 character & 8 scanlines per mode line (GR. 0) -DL_CHR40x10x1 = 3 ; monochrome, 40 character & 10 scanlines per mode line -DL_CHR40x8x4 = 4 ; colour, 40 character & 8 scanlines per mode line (GR. 12) -DL_CHR40x16x4 = 5 ; colour, 40 character & 16 scanlines per mode line (GR. 13) -DL_CHR20x8x2 = 6 ; colour (duochrome per character), 20 character & 8 scanlines per mode line (GR. 1) -DL_CHR20x16x2 = 7 ; colour (duochrome per character), 20 character & 16 scanlines per mode line (GR. 2) - -DL_MAP40x8x4 = 8 ; colour, 40 pixel & 8 scanlines per mode line (GR. 3) -DL_MAP80x4x2 = 9 ; 'duochrome', 80 pixel & 4 scanlines per mode line (GR.4) -DL_MAP80x4x4 = 10 ; colour, 80 pixel & 4 scanlines per mode line (GR.5) -DL_MAP160x2x2 = 11 ; 'duochrome', 160 pixel & 2 scanlines per mode line (GR.6) -DL_MAP160x1x2 = 12 ; 'duochrome', 160 pixel & 1 scanline per mode line (GR.14) -DL_MAP160x2x4 = 13 ; 4 colours, 160 pixel & 2 scanlines per mode line (GR.7) -DL_MAP160x1x4 = 14 ; 4 colours, 160 pixel & 1 scanline per mode line (GR.15) -DL_MAP320x1x1 = 15 ; monochrome, 320 pixel & 1 scanline per mode line (GR.8) - -; modifiers on mode lines... - -DL_HSCROL = 16 -DL_VSCROL = 32 -DL_LMS = 64 - -; general modifier... - -DL_DLI = 128 - ;------------------------------------------------------------------------- ; End of atari.inc ;------------------------------------------------------------------------- diff --git a/asminc/atari5200.inc b/asminc/atari5200.inc new file mode 100644 index 000000000..b67c9a8db --- /dev/null +++ b/asminc/atari5200.inc @@ -0,0 +1,116 @@ +;------------------------------------------------------------------------- +; Atari 5200 System Equates +; by Christian Groessler +; taken from EQUATES.INC from Atari Inc. +;------------------------------------------------------------------------- + +;------------------------------------------------------------------------- +; ATASCII CHARACTER DEFS +;------------------------------------------------------------------------- + +ATEOL = $9B ;END-OF-LINE, used by CONIO + + +;------------------------------------------------------------------------- +; Zero Page +;------------------------------------------------------------------------- + +POKMSK = $00 ;Mask for Pokey IRQ enable +RTCLOK = $01 ;60 hz. clock +JUMP = $01 +CRITIC = $03 ;Critical section +ATRACT = $04 ;Attract Mode + +SDLSTL = $05 ;DLISTL Shadow +SDLSTH = $06 ;DLISTH " +SDMCTL = $07 ;DMACTL " + +PCOLR0 = $08 ;COLPM0 Shadow +PCOLR1 = $09 ;COLPM1 " +PCOLR2 = $0A ;COLPM2 " +PCOLR3 = $0B ;COLPM3 " + +COLOR0 = $0C ;COLPF0 Shadow +COLOR1 = $0D ;COLPF1 " +COLOR2 = $0E ;COLPF2 " +COLOR3 = $0F ;COLPF3 " +COLOR4 = $10 ;COLBK " + +PADDL0 = $11 ;POT0 Shadow +PADDL1 = $12 ;POT1 " +PADDL2 = $13 ;POT2 " +PADDL3 = $14 ;POT3 " +PADDL4 = $15 ;POT4 " +PADDL5 = $16 ;POT5 " +PADDL6 = $17 ;POT6 " +PADDL7 = $18 ;POT7 " + +; cc65 runtime zero page variables + +ROWCRS_5200 = $19 +COLCRS_5200 = $1A +SAVMSC = $1B ; pointer to screen memory (conio) + +;------------------------------------------------------------------------- +; Page #2 +;------------------------------------------------------------------------- + +;Interrupt Vectors + +VIMIRQ = $0200 ;Immediate IRQ + ;Preset $FC03 (SYSIRQ) +VVBLKI = $0202 ;Vblank immediate + ;Preset $FCB8 (SYSVBL) +VVBLKD = $0204 ;Vblank deferred + ;Preset $FCB2 (XITVBL) +VDSLST = $0206 ;Display List + ;Preset $FEA1 (OSDLI) +VKYBDI = $0208 ;Keyboard immediate + ;Preset $FD02 (SYSKBD) +VKYBDF = $020A ;Deferred Keyboard + ;Preset $FCB2 (XITVBL) +VTRIGR = $020C ;Soft Trigger +VBRKOP = $020E ;BRK Opcode +VSERIN = $0210 ;Serial in Ready +VSEROR = $0212 ;Serial Out Ready +VSEROC = $0214 ;Serial Output complete +VTIMR1 = $0216 ;Pokey Timer 1 +VTIMR2 = $0218 ;Pokey Timer 2 +VTIMR4 = $021A ;Pokey Timer 4 + + + +;------------------------------------------------------------------------- +; CTIA/GTIA Address Equates +;------------------------------------------------------------------------- + +GTIA = $C000 ;CTIA/GTIA area +.include "atari_gtia.inc" + +;------------------------------------------------------------------------- +; ANTIC Address Equates +;------------------------------------------------------------------------- + +ANTIC = $D400 ;ANTIC area +.include "atari_antic.inc" + +;------------------------------------------------------------------------- +; POKEY Address Equates +;------------------------------------------------------------------------- + +POKEY = $E800 ;POKEY area +.include "atari_pokey.inc" + + +;------------------------------------------------------------------------- +; Cartridge Parameters +;------------------------------------------------------------------------- + +CARTNM = $BFE8 ;Cartridge Name Area +COPYD = $BFFC ;Copyright Decade in Cart +COPYR = $BFFD ;Copyright Year in Cart + ; $FF=Diagnostic Cart +GOCART = $BFFE ;Cartridge Start Vector + + +CHRORG = $F800 ;Character Generator Base diff --git a/asminc/atari_antic.inc b/asminc/atari_antic.inc new file mode 100644 index 000000000..1eb4c87ef --- /dev/null +++ b/asminc/atari_antic.inc @@ -0,0 +1,93 @@ +;------------------------------------------------------------------------- +; ANTIC Address Equates +;------------------------------------------------------------------------- + +; Read Addresses + +VCOUNT = ANTIC + $0B ;vertical line counter +PENH = ANTIC + $0C ;light pen horizontal position +PENV = ANTIC + $0D ;light pen vertical position +NMIST = ANTIC + $0F ;NMI interrupt status + +; Write Addresses + +DMACTL = ANTIC + $00 ;DMA control +CHACTL = ANTIC + $01 ;character control +DLISTL = ANTIC + $02 ;low display list address +DLISTH = ANTIC + $03 ;high display list address +HSCROL = ANTIC + $04 ;horizontal scroll +VSCROL = ANTIC + $05 ;vertical scroll +PMBASE = ANTIC + $07 ;player-missile base address +CHBASE = ANTIC + $09 ;character base address +WSYNC = ANTIC + $0A ;wait for HBLANK synchronization +NMIEN = ANTIC + $0E ;NMI enable +NMIRES = ANTIC + $0F ;NMI interrupt reset + + +;------------------------------------------------------------------------- +; Antic opcodes +;------------------------------------------------------------------------- + +; usage example: +; +; ScreenDL: +; .byte DL_BLK8 +; .byte DL_BLK8 +; .byte DL_CHR40x8x1 + DL_LMS + DL_DLI +; .word ScreenAlignment +; .byte DL_BLK1 + DL_DLI +; .byte DL_MAP320x1x1 + DL_LMS +; .word Screen +; +; .repeat 99 +; .byte DL_MAP320x1x1 +; .endrepeat +; .byte DL_MAP320x1x1 + DL_LMS +; .word Screen + 40 * 100 ; 100 lines a 40 byte, 'Screen' has to be aligned correctly! +; .repeat 92 +; .byte DL_MAP320x1x1 +; .endrepeat +; +; .byte DL_JVB + +; absolute instructions (non mode lines) + +DL_JMP = 1 +DL_JVB = 65 + +DL_BLK1 = 0 +DL_BLK2 = 16 +DL_BLK3 = 32 +DL_BLK4 = 48 +DL_BLK5 = 64 +DL_BLK6 = 80 +DL_BLK7 = 96 +DL_BLK8 = 112 + +; absolute instructions (mode lines) + +DL_CHR40x8x1 = 2 ; monochrome, 40 character & 8 scanlines per mode line (GR. 0) +DL_CHR40x10x1 = 3 ; monochrome, 40 character & 10 scanlines per mode line +DL_CHR40x8x4 = 4 ; colour, 40 character & 8 scanlines per mode line (GR. 12) +DL_CHR40x16x4 = 5 ; colour, 40 character & 16 scanlines per mode line (GR. 13) +DL_CHR20x8x2 = 6 ; colour (duochrome per character), 20 character & 8 scanlines per mode line (GR. 1) +DL_CHR20x16x2 = 7 ; colour (duochrome per character), 20 character & 16 scanlines per mode line (GR. 2) + +DL_MAP40x8x4 = 8 ; colour, 40 pixel & 8 scanlines per mode line (GR. 3) +DL_MAP80x4x2 = 9 ; 'duochrome', 80 pixel & 4 scanlines per mode line (GR.4) +DL_MAP80x4x4 = 10 ; colour, 80 pixel & 4 scanlines per mode line (GR.5) +DL_MAP160x2x2 = 11 ; 'duochrome', 160 pixel & 2 scanlines per mode line (GR.6) +DL_MAP160x1x2 = 12 ; 'duochrome', 160 pixel & 1 scanline per mode line (GR.14) +DL_MAP160x2x4 = 13 ; 4 colours, 160 pixel & 2 scanlines per mode line (GR.7) +DL_MAP160x1x4 = 14 ; 4 colours, 160 pixel & 1 scanline per mode line (GR.15) +DL_MAP320x1x1 = 15 ; monochrome, 320 pixel & 1 scanline per mode line (GR.8) + +; modifiers on mode lines... + +DL_HSCROL = 16 +DL_VSCROL = 32 +DL_LMS = 64 + +; general modifier... + +DL_DLI = 128 diff --git a/asminc/atari_gtia.inc b/asminc/atari_gtia.inc new file mode 100644 index 000000000..f50583271 --- /dev/null +++ b/asminc/atari_gtia.inc @@ -0,0 +1,81 @@ +;------------------------------------------------------------------------- +; CTIA/GTIA Address Equates +;------------------------------------------------------------------------- + +; Read/Write Addresses + +CONSOL = GTIA + $1F ;console switches and speaker control + +; Read Addresses + +M0PF = GTIA + $00 ;missile 0 and playfield collision +M1PF = GTIA + $01 ;missile 1 and playfield collision +M2PF = GTIA + $02 ;missile 2 and playfield collision +M3PF = GTIA + $03 ;missile 3 and playfield collision + +P0PF = GTIA + $04 ;player 0 and playfield collision +P1PF = GTIA + $05 ;player 1 and playfield collision +P2PF = GTIA + $06 ;player 2 and playfield collision +P3PF = GTIA + $07 ;player 3 and playfield collision + +M0PL = GTIA + $08 ;missile 0 and player collision +M1PL = GTIA + $09 ;missile 1 and player collision +M2PL = GTIA + $0A ;missile 2 and player collision +M3PL = GTIA + $0B ;missile 3 and player collision + +P0PL = GTIA + $0C ;player 0 and player collision +P1PL = GTIA + $0D ;player 1 and player collision +P2PL = GTIA + $0E ;player 2 and player collision +P3PL = GTIA + $0F ;player 3 and player collision + +TRIG0 = GTIA + $10 ;joystick trigger 0 +TRIG1 = GTIA + $11 ;joystick trigger 1 + +TRIG2 = GTIA + $12 ;cartridge interlock +TRIG3 = GTIA + $13 ;ACMI module interlock + +PAL = GTIA + $14 ;##rev2## PAL/NTSC indicator + +; Write Addresses + +HPOSP0 = GTIA + $00 ;player 0 horizontal position +HPOSP1 = GTIA + $01 ;player 1 horizontal position +HPOSP2 = GTIA + $02 ;player 2 horizontal position +HPOSP3 = GTIA + $03 ;player 3 horizontal position + +HPOSM0 = GTIA + $04 ;missile 0 horizontal position +HPOSM1 = GTIA + $05 ;missile 1 horizontal position +HPOSM2 = GTIA + $06 ;missile 2 horizontal position +HPOSM3 = GTIA + $07 ;missile 3 horizontal position + +SIZEP0 = GTIA + $08 ;player 0 size +SIZEP1 = GTIA + $09 ;player 1 size +SIZEP2 = GTIA + $0A ;player 2 size +SIZEP3 = GTIA + $0B ;player 3 size + +SIZEM = GTIA + $0C ;missile sizes + +GRAFP0 = GTIA + $0D ;player 0 graphics +GRAFP1 = GTIA + $0E ;player 1 graphics +GRAFP2 = GTIA + $0F ;player 2 graphics +GRAFP3 = GTIA + $10 ;player 3 graphics + +GRAFM = GTIA + $11 ;missile graphics + +COLPM0 = GTIA + $12 ;player-missile 0 color/luminance +COLPM1 = GTIA + $13 ;player-missile 1 color/luminance +COLPM2 = GTIA + $14 ;player-missile 2 color/luminance +COLPM3 = GTIA + $15 ;player-missile 3 color/luminance + +COLPF0 = GTIA + $16 ;playfield 0 color/luminance +COLPF1 = GTIA + $17 ;playfield 1 color/luminance +COLPF2 = GTIA + $18 ;playfield 2 color/luminance +COLPF3 = GTIA + $19 ;playfield 3 color/luminance + +COLBK = GTIA + $1A ;background color/luminance + +PRIOR = GTIA + $1B ;priority select +VDELAY = GTIA + $1C ;vertical delay +GRACTL = GTIA + $1D ;graphic control +HITCLR = GTIA + $1E ;collision clear + diff --git a/asminc/atari_pokey.inc b/asminc/atari_pokey.inc new file mode 100644 index 000000000..99d192fbd --- /dev/null +++ b/asminc/atari_pokey.inc @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------- +; POKEY Address Equates +;------------------------------------------------------------------------- + +; Read Addresses + +POT0 = POKEY + $00 ;potentiometer 0 +POT1 = POKEY + $01 ;potentiometer 1 +POT2 = POKEY + $02 ;potentiometer 2 +POT3 = POKEY + $03 ;potentiometer 3 +POT4 = POKEY + $04 ;potentiometer 4 +POT5 = POKEY + $05 ;potentiometer 5 +POT6 = POKEY + $06 ;potentiometer 6 +POT7 = POKEY + $07 ;potentiometer 7 + +ALLPOT = POKEY + $08 ;potentiometer port status +KBCODE = POKEY + $09 ;keyboard code +RANDOM = POKEY + $0A ;random number generator +SERIN = POKEY + $0D ;serial port input +IRQST = POKEY + $0E ;IRQ interrupt status +SKSTAT = POKEY + $0F ;serial port and keyboard status + +; Write Addresses + +AUDF1 = POKEY + $00 ;channel 1 audio frequency +AUDC1 = POKEY + $01 ;channel 1 audio control + +AUDF2 = POKEY + $02 ;channel 2 audio frequency +AUDC2 = POKEY + $03 ;channel 2 audio control + +AUDF3 = POKEY + $04 ;channel 3 audio frequency +AUDC3 = POKEY + $05 ;channel 3 audio control + +AUDF4 = POKEY + $06 ;channel 4 audio frequency +AUDC4 = POKEY + $07 ;channel 4 audio control + +AUDCTL = POKEY + $08 ;audio control +STIMER = POKEY + $09 ;start timers +SKRES = POKEY + $0A ;reset SKSTAT status +POTGO = POKEY + $0B ;start potentiometer scan sequence +SEROUT = POKEY + $0D ;serial port output +IRQEN = POKEY + $0E ;IRQ interrupt enable +SKCTL = POKEY + $0F ;serial port and keyboard control + diff --git a/asminc/atmos.inc b/asminc/atmos.inc index 6534a2ef0..4c3c442fa 100644 --- a/asminc/atmos.inc +++ b/asminc/atmos.inc @@ -90,6 +90,7 @@ SCREEN := $BB80 ; --------------------------------------------------------------------------- ; ROM entries +GETLINE := $C592 TEXT := $EC21 HIRES := $EC33 CURSET := $F0C8 diff --git a/asminc/c128.inc b/asminc/c128.inc index aac8678bf..6e3078297 100644 --- a/asminc/c128.inc +++ b/asminc/c128.inc @@ -32,6 +32,7 @@ FETCH := $2A2 ; Fetch subroutine in RAM FETVEC := $2AA ; Vector patch location for FETCH STASH := $2AF ; Stash routine in RAM STAVEC := $2B9 ; Vector patch location for STASH +IRQInd := $2FD ; JMP $0000 -- used as indirect IRQ vector PALFLAG := $A03 ; $FF=PAL, $00=NTSC INIT_STATUS := $A04 ; Flags: Reset/Restore initiation status FKEY_LEN := $1000 ; Function key lengths diff --git a/asminc/cbm510.inc b/asminc/cbm510.inc index abc363728..e1a86c487 100644 --- a/asminc/cbm510.inc +++ b/asminc/cbm510.inc @@ -4,7 +4,7 @@ ; Taken from a kernal disassembly done by myself in 2000/2001. ; ; 2001-09-13, Ullrich von Bassewitz -; 2013-08-26, Greg King +; 2014-04-02, Greg King ;----------------------------------------------------------------------------- @@ -14,6 +14,8 @@ ExecReg := $00 ; Controls execution memory bank IndReg := $01 ; Controls indirect indexed load-store bank TXTPTR := $85 ; Far pointer into BASIC source code +FNAM := $90 ; Far pointer to LOAD/SAVE file-name +FNAM_LEN := $9D ; Holds length of file-name ; --------------------------------------------------------------------------- ; Screen size diff --git a/asminc/cbm610.inc b/asminc/cbm610.inc index f442f5da8..b1b03eb1d 100644 --- a/asminc/cbm610.inc +++ b/asminc/cbm610.inc @@ -4,7 +4,7 @@ ; Taken from a kernal disassembly done by myself in 1987. ; ; 1998-09-28, Ullrich von Bassewitz -; 2013-08-26, Greg King +; 2014-04-02, Greg King ; --------------------------------------------------------------------------- @@ -14,6 +14,8 @@ ExecReg := $00 ; Controls execution memory bank IndReg := $01 ; Controls indirect indexed load-store bank TXTPTR := $85 ; Far pointer into BASIC source code +FNAM := $90 ; Far pointer to LOAD/SAVE file-name +FNAM_LEN := $9D ; Holds length of file-name ; --------------------------------------------------------------------------- ; Screen size diff --git a/asminc/cpu.mac b/asminc/cpu.mac index 43c9e160f..6b8aa6d7b 100644 --- a/asminc/cpu.mac +++ b/asminc/cpu.mac @@ -1,4 +1,3 @@ - ; CPU bitmask constants CPU_ISET_NONE = $0001 CPU_ISET_6502 = $0002 @@ -6,9 +5,8 @@ CPU_ISET_6502X = $0004 CPU_ISET_65SC02 = $0008 CPU_ISET_65C02 = $0010 CPU_ISET_65816 = $0020 -CPU_ISET_SUNPLUS = $0040 -CPU_ISET_SWEET16 = $0080 -CPU_ISET_HUC6280 = $0100 +CPU_ISET_SWEET16 = $0040 +CPU_ISET_HUC6280 = $0080 ; CPU capabilities CPU_NONE = CPU_ISET_NONE @@ -17,8 +15,5 @@ CPU_6502X = CPU_ISET_6502|CPU_ISET_6502X CPU_65SC02 = CPU_ISET_6502|CPU_ISET_65SC02 CPU_65C02 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02 CPU_65816 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65816 -CPU_SUNPLUS = CPU_ISET_SUNPLUS CPU_SWEET16 = CPU_ISET_SWEET16 CPU_HUC6280 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02|CPU_ISET_HUC6280 - - diff --git a/asminc/module.mac b/asminc/module.mac new file mode 100644 index 000000000..d844ec104 --- /dev/null +++ b/asminc/module.mac @@ -0,0 +1,13 @@ +.ifndef DYN_DRV + DYN_DRV = 1 +.endif + +.macro module_header module_label + .if DYN_DRV + .segment "HEADER" + .else + .data + .export module_label + module_label: + .endif +.endmacro diff --git a/asminc/mouse-kernel.inc b/asminc/mouse-kernel.inc index d3ec9b30f..3eebca244 100644 --- a/asminc/mouse-kernel.inc +++ b/asminc/mouse-kernel.inc @@ -78,6 +78,10 @@ .byte CSHOW .addr .byte + CPREP .addr + .byte + CDRAW .addr + .byte CMOVEX .addr .byte CMOVEY .addr @@ -90,14 +94,16 @@ .struct MOUSE_CALLBACKS HIDE .addr ; Hide the mouse cursor SHOW .addr ; Show the mouse cursor - MOVEX .addr ; Move the mouse cursor - MOVEY .addr ; Dito for Y + PREP .addr ; Prepare to move the mouse cursor + DRAW .addr ; Draw the mouse cursor + MOVEX .addr ; Move the mouse cursor to X coord + MOVEY .addr ; Move the mouse cursor to Y coord .endstruct ;------------------------------------------------------------------------------ ; The mouse API version, stored in MOUSE_HDR::VERSION -MOUSE_API_VERSION = $04 +MOUSE_API_VERSION = $05 ;------------------------------------------------------------------------------ ; Bitmapped mouse driver flags, stored in MOUSE_HDR::FLAGS. @@ -169,12 +175,10 @@ MOUSE_BTN_RIGHT = $01 .global mouse_uninstall .global mouse_hide .global mouse_show - .global mouse_setbox + .global mouse_setbox .global mouse_getbox .global mouse_move .global mouse_buttons .global mouse_pos .global mouse_info .global mouse_ioctl - - diff --git a/asminc/ser-error.inc b/asminc/ser-error.inc index f1592876b..ff4e2b448 100644 --- a/asminc/ser-error.inc +++ b/asminc/ser-error.inc @@ -48,6 +48,7 @@ SER_ERR_INIT_FAILED ; Initialization failed SER_ERR_INV_IOCTL ; IOCTL not supported SER_ERR_INSTALLED ; A driver is already installed + SER_ERR_NOT_OPEN ; Driver not open SER_ERR_COUNT ; Special: Number of error codes .endenum diff --git a/asminc/ser-kernel.inc b/asminc/ser-kernel.inc index e59501da6..3ddb7f300 100644 --- a/asminc/ser-kernel.inc +++ b/asminc/ser-kernel.inc @@ -96,6 +96,7 @@ SER_BAUD_115200 = $12 SER_BAUD_230400 = $13 SER_BAUD_31250 = $14 SER_BAUD_62500 = $15 +SER_BAUD_56_875 = $16 ; Data bit settings SER_BITS_5 = $00 diff --git a/cfg/apple2-asm.cfg b/cfg/apple2-asm.cfg index e70ed4484..1e187764c 100644 --- a/cfg/apple2-asm.cfg +++ b/cfg/apple2-asm.cfg @@ -8,13 +8,15 @@ SYMBOLS { __LOADSIZE__: type = weak, value = __BSS_RUN__ - __CODE_RUN__; } MEMORY { + ZP: start = $0080, size = $001A, define = yes; HEADER: file = %O, start = $0000, size = $0004; RAM: file = %O, start = %S, size = $C000 - %S; } SEGMENTS { - EXEHDR: load = HEADER, type = ro, optional = yes; - CODE: load = RAM, type = rw, optional = yes, define = yes; - RODATA: load = RAM, type = ro, optional = yes; - DATA: load = RAM, type = rw, optional = yes; - BSS: load = RAM, type = bss, optional = yes, define = yes; + ZEROPAGE: load = ZP, type = zp, optional = yes; + EXEHDR: load = HEADER, type = ro, optional = yes; + CODE: load = RAM, type = rw, optional = yes, define = yes; + RODATA: load = RAM, type = ro, optional = yes; + DATA: load = RAM, type = rw, optional = yes; + BSS: load = RAM, type = bss, optional = yes, define = yes; } diff --git a/cfg/apple2-overlay.cfg b/cfg/apple2-overlay.cfg index 9216aa7c7..d0b34692f 100644 --- a/cfg/apple2-overlay.cfg +++ b/cfg/apple2-overlay.cfg @@ -41,13 +41,13 @@ SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro; STARTUP: load = RAM, type = ro, define = yes; - LOWCODE: load = RAM, type = ro; + LOWCODE: load = RAM, type = ro, optional = yes; CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; ZPSAVE: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; - INIT: load = MOVE, run = RAM, type = ro, define = yes; + INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; LC: load = MOVE, run = LC, type = ro, optional = yes; OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes; OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes; diff --git a/cfg/apple2-system.cfg b/cfg/apple2-system.cfg index d3df44d05..33ab04f5e 100644 --- a/cfg/apple2-system.cfg +++ b/cfg/apple2-system.cfg @@ -17,14 +17,14 @@ MEMORY { SEGMENTS { ZEROPAGE: load = ZP, type = zp; STARTUP: load = RAM, type = ro, define = yes; - LOWCODE: load = RAM, type = ro; + LOWCODE: load = RAM, type = ro, optional = yes; CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; ZPSAVE: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; - INIT: load = MOVE, run = RAM, type = ro, define = yes; - LC: load = MOVE, run = LC, type = ro, optional = yes; + INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; + LC: load = MOVE, run = LC, type = ro, optional = yes; } FEATURES { CONDES: type = constructor, diff --git a/cfg/apple2.cfg b/cfg/apple2.cfg index 701716d97..5673302d1 100644 --- a/cfg/apple2.cfg +++ b/cfg/apple2.cfg @@ -24,14 +24,14 @@ SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro; STARTUP: load = RAM, type = ro, define = yes; - LOWCODE: load = RAM, type = ro; + LOWCODE: load = RAM, type = ro, optional = yes; CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; ZPSAVE: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; - INIT: load = MOVE, run = RAM, type = ro, define = yes; - LC: load = MOVE, run = LC, type = ro, optional = yes; + INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; + LC: load = MOVE, run = LC, type = ro, optional = yes; } FEATURES { CONDES: type = constructor, diff --git a/cfg/apple2enh-overlay.cfg b/cfg/apple2enh-overlay.cfg index 9216aa7c7..d0b34692f 100644 --- a/cfg/apple2enh-overlay.cfg +++ b/cfg/apple2enh-overlay.cfg @@ -41,13 +41,13 @@ SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro; STARTUP: load = RAM, type = ro, define = yes; - LOWCODE: load = RAM, type = ro; + LOWCODE: load = RAM, type = ro, optional = yes; CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; ZPSAVE: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; - INIT: load = MOVE, run = RAM, type = ro, define = yes; + INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; LC: load = MOVE, run = LC, type = ro, optional = yes; OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes; OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes; diff --git a/cfg/apple2enh-system.cfg b/cfg/apple2enh-system.cfg index d3df44d05..33ab04f5e 100644 --- a/cfg/apple2enh-system.cfg +++ b/cfg/apple2enh-system.cfg @@ -17,14 +17,14 @@ MEMORY { SEGMENTS { ZEROPAGE: load = ZP, type = zp; STARTUP: load = RAM, type = ro, define = yes; - LOWCODE: load = RAM, type = ro; + LOWCODE: load = RAM, type = ro, optional = yes; CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; ZPSAVE: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; - INIT: load = MOVE, run = RAM, type = ro, define = yes; - LC: load = MOVE, run = LC, type = ro, optional = yes; + INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; + LC: load = MOVE, run = LC, type = ro, optional = yes; } FEATURES { CONDES: type = constructor, diff --git a/cfg/apple2enh.cfg b/cfg/apple2enh.cfg index 701716d97..5673302d1 100644 --- a/cfg/apple2enh.cfg +++ b/cfg/apple2enh.cfg @@ -24,14 +24,14 @@ SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro; STARTUP: load = RAM, type = ro, define = yes; - LOWCODE: load = RAM, type = ro; + LOWCODE: load = RAM, type = ro, optional = yes; CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; ZPSAVE: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; - INIT: load = MOVE, run = RAM, type = ro, define = yes; - LC: load = MOVE, run = LC, type = ro, optional = yes; + INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; + LC: load = MOVE, run = LC, type = ro, optional = yes; } FEATURES { CONDES: type = constructor, diff --git a/cfg/atari-asm.cfg b/cfg/atari-asm.cfg index 4e87a8884..4ff7c3173 100644 --- a/cfg/atari-asm.cfg +++ b/cfg/atari-asm.cfg @@ -24,6 +24,7 @@ SEGMENTS { RODATA: load = RAM, type = ro optional = yes; DATA: load = RAM, type = rw optional = yes; BSS: load = RAM, type = bss, define = yes, optional = yes; - ZEROPAGE: load = ZP, type = zp; + ZEROPAGE: load = ZP, type = zp, optional = yes; + EXTZP: load = ZP, type = zp, optional = yes; # to enable modules to be able to link to C and assembler programs AUTOSTRT: load = TRAILER, type = ro, optional = yes; } diff --git a/cfg/atari-cart.cfg b/cfg/atari-cart.cfg new file mode 100644 index 000000000..db9486a9f --- /dev/null +++ b/cfg/atari-cart.cfg @@ -0,0 +1,44 @@ +FEATURES { + STARTADDRESS: default = $2000; +} +SYMBOLS { + __CARTSIZE__: type = weak, value = $2000; # possible values: $2000 and $4000 + __CART_HEADER__: type = import; + __STACKSIZE__: type = weak, value = $0800; # 2k stack + __STARTADDRESS__: type = export, value = %S; + __RESERVED_MEMORY__: type = export, value = $0000; + __CARTFLAGS__: type = weak, value = $01; # see documentation for other possible values +} +MEMORY { + ZP: file = "", define = yes, start = $0082, size = $007E; + RAM: file = "", define = yes, start = %S, size = __CARTSIZE__; + ROM: file = %O, define = yes, start = $C000 - __CARTSIZE__, size = __CARTSIZE__ - 6, fill = yes, fillval = $FF; + CARTID: file = %O, start = $BFFA, size = $0006; +} +SEGMENTS { + STARTUP: load = ROM, type = ro, define = yes, optional = yes; + LOWCODE: load = ROM, type = ro, define = yes, optional = yes; + INIT: load = ROM, type = ro, optional = yes; + CODE: load = ROM, type = ro, define = yes; + RODATA: load = ROM, type = ro, optional = yes; + DATA: load = ROM, run = RAM, type = rw, define = yes, optional = yes; + BSS: load = RAM, type = bss, define = yes, optional = yes; + CARTHDR: load = CARTID, type = ro; + ZEROPAGE: load = ZP, type = zp, optional = yes; + EXTZP: load = ZP, type = zp, optional = yes; +} +FEATURES { + CONDES: type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__, + segment = INIT; + CONDES: type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__, + segment = RODATA; + CONDES: type = interruptor, + label = __INTERRUPTOR_TABLE__, + count = __INTERRUPTOR_COUNT__, + segment = RODATA, + import = __CALLIRQ__; +} diff --git a/cfg/atari-cassette.cfg b/cfg/atari-cassette.cfg new file mode 100644 index 000000000..2116aecd0 --- /dev/null +++ b/cfg/atari-cassette.cfg @@ -0,0 +1,40 @@ +FEATURES { + STARTADDRESS: default = $0900; +} +SYMBOLS { + __STACKSIZE__: type = weak, value = $0800; # 2k stack + __RESERVED_MEMORY__: type = weak, value = $0000; + __STARTADDRESS__: type = export, value = %S; + _cas_hdr: type = import; +} +MEMORY { + ZP: file = "", define = yes, start = $0082, size = $007E; + RAM: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; +} +SEGMENTS { + CASHDR: load = RAM, type = ro; + STARTUP: load = RAM, type = ro, define = yes, optional = yes; + LOWCODE: load = RAM, type = ro, define = yes, optional = yes; + INIT: load = RAM, type = ro, optional = yes; + CODE: load = RAM, type = ro, define = yes; + RODATA: load = RAM, type = ro, optional = yes; + DATA: load = RAM, type = rw, optional = yes; + BSS: load = RAM, type = bss, define = yes, optional = yes; + ZEROPAGE: load = ZP, type = zp, optional = yes; + EXTZP: load = ZP, type = zp, optional = yes; +} +FEATURES { + CONDES: type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__, + segment = INIT; + CONDES: type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__, + segment = RODATA; + CONDES: type = interruptor, + label = __INTERRUPTOR_TABLE__, + count = __INTERRUPTOR_COUNT__, + segment = RODATA, + import = __CALLIRQ__; +} diff --git a/cfg/atari5200.cfg b/cfg/atari5200.cfg new file mode 100644 index 000000000..4a90303cf --- /dev/null +++ b/cfg/atari5200.cfg @@ -0,0 +1,43 @@ +SYMBOLS { + __CARTSIZE__: type = weak, value = $4000; # possible values: $4000 and $8000 + __CART_ENTRY__: type = import; + __STACKSIZE__: type = weak, value = $0400; # 4 pages stack + __RESERVED_MEMORY__: type = export, value = $01E0; # space for 20x24 screen buffer (default display list is in ROM) +} +MEMORY { + ZP: file = "", start = $001D, size = $00E3, define = yes; + RAM: file = "", start = $021C, size = $4000 - __STACKSIZE__ - __RESERVED_MEMORY__ - $021C, define = yes; + ROM: file = %O, start = $C000 - __CARTSIZE__, size = __CARTSIZE__ - $18, define = yes, fill = yes, fillval = $FF; + CARTNAME: file = %O, start = $BFE8, size = $0014 fill = yes, fillval = $40; + CARTYEAR: file = %O, start = $BFFC, size = $0002 fill = yes, fillval = $59; + CARTENTRY: file = %O, start = $BFFE, size = $0002; +} +SEGMENTS { + STARTUP: load = ROM, type = ro, define = yes, optional = yes; + LOWCODE: load = ROM, type = ro, define = yes, optional = yes; + INIT: load = ROM, type = ro, optional = yes; + CODE: load = ROM, type = ro, define = yes; + RODATA: load = ROM, type = ro, optional = yes; + DATA: load = ROM, run = RAM, type = rw, define = yes, optional = yes; + BSS: load = RAM, type = bss, define = yes, optional = yes; + CARTNAME: load = CARTNAME, type = ro, define = yes; + CARTYEAR: load = CARTYEAR, type = ro, define = yes; + CARTENTRY: load = CARTENTRY, type = ro, define = yes; + ZEROPAGE: load = ZP, type = zp, optional = yes; + EXTZP: load = ZP, type = zp, optional = yes; +} +FEATURES { + CONDES: type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__, + segment = INIT; + CONDES: type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__, + segment = RODATA; + CONDES: type = interruptor, + label = __INTERRUPTOR_TABLE__, + count = __INTERRUPTOR_COUNT__, + segment = RODATA, + import = __CALLIRQ__; +} diff --git a/cfg/c64-asm.cfg b/cfg/c64-asm.cfg index 0924cdb56..1ab80be8e 100644 --- a/cfg/c64-asm.cfg +++ b/cfg/c64-asm.cfg @@ -5,6 +5,7 @@ SYMBOLS { __LOADADDR__: type = import; } MEMORY { + ZP: file = "", start = $0002, size = $001A, define = yes; LOADADDR: file = %O, start = %S - 2, size = $0002; RAM: file = %O, start = %S, size = $D000 - %S; } @@ -15,4 +16,5 @@ SEGMENTS { RODATA: load = RAM, type = ro, optional = yes; DATA: load = RAM, type = rw, optional = yes; BSS: load = RAM, type = bss, optional = yes; + ZEROPAGE: load = ZP, type = zp, optional = yes; } diff --git a/cfg/lynx-bll.cfg b/cfg/lynx-bll.cfg index 3d6cf19aa..21967752f 100644 --- a/cfg/lynx-bll.cfg +++ b/cfg/lynx-bll.cfg @@ -12,7 +12,7 @@ MEMORY { SEGMENTS { BLLHDR: load = HEADER, type = ro; STARTUP: load = RAM, type = ro, define = yes; - LOWCODE: load = RAM, type = ro, optional = yes; + LOWCODE: load = RAM, type = ro, define = yes, optional = yes; INIT: load = RAM, type = ro, define = yes, optional = yes; CODE: load = RAM, type = ro, define = yes; RODATA: load = RAM, type = ro, define = yes; diff --git a/cfg/lynx-coll.cfg b/cfg/lynx-coll.cfg index e7a220fb3..b7fd787e7 100644 --- a/cfg/lynx-coll.cfg +++ b/cfg/lynx-coll.cfg @@ -18,7 +18,7 @@ SEGMENTS { BOOTLDR: load = BOOT, type = ro; DIRECTORY: load = DIR, type = ro; STARTUP: load = RAM, type = ro, define = yes; - LOWCODE: load = RAM, type = ro, optional = yes; + LOWCODE: load = RAM, type = ro, define = yes, optional = yes; INIT: load = RAM, type = ro, define = yes, optional = yes; CODE: load = RAM, type = ro, define = yes; RODATA: load = RAM, type = ro, define = yes; diff --git a/cfg/lynx-uploader.cfg b/cfg/lynx-uploader.cfg index 4a1e87bee..740a18b0a 100644 --- a/cfg/lynx-uploader.cfg +++ b/cfg/lynx-uploader.cfg @@ -20,7 +20,7 @@ SEGMENTS { BOOTLDR: load = BOOT, type = ro; DIRECTORY:load = DIR, type = ro; STARTUP: load = RAM, type = ro, define = yes; - LOWCODE: load = RAM, type = ro, optional = yes; + LOWCODE: load = RAM, type = ro, define = yes, optional = yes; INIT: load = RAM, type = ro, define = yes, optional = yes; CODE: load = RAM, type = ro, define = yes; RODATA: load = RAM, type = ro, define = yes; diff --git a/cfg/lynx.cfg b/cfg/lynx.cfg index 77345bf49..2c9e76207 100644 --- a/cfg/lynx.cfg +++ b/cfg/lynx.cfg @@ -18,7 +18,7 @@ SEGMENTS { BOOTLDR: load = BOOT, type = ro; DIRECTORY: load = DIR, type = ro; STARTUP: load = RAM, type = ro, define = yes; - LOWCODE: load = RAM, type = ro, optional = yes; + LOWCODE: load = RAM, type = ro, define = yes, optional = yes; INIT: load = RAM, type = ro, define = yes, optional = yes; CODE: load = RAM, type = ro, define = yes; RODATA: load = RAM, type = ro, define = yes; diff --git a/cfg/module.cfg b/cfg/module.cfg index 349197eb0..452491eb4 100644 --- a/cfg/module.cfg +++ b/cfg/module.cfg @@ -1,16 +1,16 @@ MEMORY { - ZP: file = %O, start = $0000, size = $0100, type = rw, define = yes; + ZP: start = $0000, size = $0100; COMBINED: file = %O, start = $0000, size = $FFFF; } SEGMENTS { - JUMPTABLE: load = COMBINED, type = ro; - INIT: load = COMBINED, type = ro, optional = yes; - CODE: load = COMBINED, type = ro; - RODATA: load = COMBINED, type = ro; - DATA: load = COMBINED, type = rw, define = yes; - BSS: load = COMBINED, type = bss, define = yes; - ZEROPAGE: load = ZP, type = zp; - EXTZP: load = ZP, type = zp, optional = yes; + ZEROPAGE: load = ZP, type = zp; + EXTZP: load = ZP, type = zp, optional = yes; + HEADER: load = COMBINED, type = ro; + INIT: load = COMBINED, type = ro, optional = yes; + CODE: load = COMBINED, type = ro; + RODATA: load = COMBINED, type = ro; + DATA: load = COMBINED, type = rw; + BSS: load = COMBINED, type = bss; } FILES { %O: format = o65; diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 000000000..02ed6b1d3 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,64 @@ +ifneq ($(shell echo),) + CMD_EXE = 1 +endif + +.PHONY: all mostlyclean clean install zip doc html info gh-pages + +.SUFFIXES: + +htmldir = $(prefix)/share/doc/cc65$(DESTPACKAGE_SUFFIX)/html +infodir = $(prefix)/share/info + +all mostlyclean: + +ifdef CMD_EXE + +clean install zip doc: + +else # CMD_EXE + +SGMLS := $(wildcard *.sgml) + +../html/coding.html ../html/index.html: \ +TOC_LEVEL = 0 + +TOC_LEVEL = 2 + +INSTALL = install + +clean: + $(RM) -r ../html ../info + +install: + $(if $(prefix),,$(error variable `prefix' must be set)) +ifeq ($(wildcard ../html),../html) + $(INSTALL) -d $(DESTDIR)$(htmldir) + $(INSTALL) -m644 ../html/*.* $(DESTDIR)$(htmldir) +endif +ifeq ($(wildcard ../info),../info) + $(INSTALL) -d $(DESTDIR)$(infodir) + $(INSTALL) -m644 ../info/*.* $(DESTDIR)$(infodir) +endif + +zip: + @cd .. && zip cc65 html/*.* + +doc: html info + +html: $(addprefix ../html/,$(SGMLS:.sgml=.html) doc.css doc.png) + +info: $(addprefix ../info/,$(SGMLS:.sgml=.info)) + +../html ../info: + @mkdir $@ + +../html/%.html: %.sgml header.html | ../html + @cd ../html && linuxdoc -B html -s 0 -T $(TOC_LEVEL) -H ../doc/header.html ../doc/$< + +../html/doc.%: doc.% | ../html + cp $< ../html + +../info/%.info: %.sgml | ../info + @cd ../info && linuxdoc -B info ../doc/$< + +endif # CMD_EXE diff --git a/doc/apple2.sgml b/doc/apple2.sgml new file mode 100644 index 000000000..e58565359 --- /dev/null +++ b/doc/apple2.sgml @@ -0,0 +1,531 @@ + + +
+ +Apple ][ specific information for cc65 +<author><url url="mailto:ol.sc@web.de" name="Oliver Schmidt"> +<date>2014-04-10 + +<abstract> +An overview over the Apple ][ runtime system as it is +implemented for the cc65 C compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the Apple ][ runtime system +as it comes with the cc65 C compiler. It describes the memory layout, +Apple ][ specific header files, available drivers, and any +pitfalls specific to that platform. + +Please note that Apple ][ specific functions are just mentioned +here, they are described in detail in the separate <url url="funcref.html" +name="function reference">. Even functions marked as "platform dependent" may +be available on more than one platform. Please see the function reference for +more information. + + + +<sect>Binary format<p> + +The standard binary file format generated by the linker for the +Apple ][ target is a binary program with a 4 byte DOS 3.3 header +containing the load address and load length. The default load address is +$803. + +<bf/AppleCommander 1.3.5/ or later (available at <url +url="http://applecommander.sourceforge.net/">) includes the option <tt/-cc65/ +that allows to put binary files with a DOS 3.3 header onto disk images +containing DOS 3.3 as well as ProDOS 8. + +For ProDOS 8 system programs the load address is fixed to $2000 so there +is no need for a header. Thus the linker configuration +<ref id="apple-sys-cfg" name="apple2-system.cfg"> for those programs +omits the DOS 3.3 header. The right AppleCommander option to put system files +without a header on a ProDOS 8 disk image is <tt/-p/. + + +<sect>Memory layout<p> + +In the standard setup, cc65 generated programs use the memory from +$803 to $95FF, so 35.5 KB of RAM are available. + +Special locations: + +<descrip> + + <tag/Stack/ + The C runtime stack is located at HIMEM and grows downwards, regardless of + how your linker config file is setup. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + +While running <tt/main()/ the Language Card bank 2 is enabled for read access. +However while running module constructors/destructors the Language Card is disabled. + +Enabling the Language Card allows to use it as additional memory for cc65 +generated code. However code is never automatically placed there. Rather code +needs to be explicitly placed in the Language Card either per file by compiling +with <tt/--code-name HIGHCODE/ or per function by enclosing in <tt/#pragma +code-name (push, "HIGHCODE")/ and <tt/#pragma code-name (pop)/. In either case the +cc65 runtime system takes care of actually moving the code into the Language +Card. + +The amount of memory available in the Language Card for generated code depends +on the chosen <ref id="link-configs" name="linker configuration">. + + + +<sect>Linker configurations<label id="link-configs"><p> + +The ld65 linker comes with a default config file for the Apple ][, +which is used via <tt/-t apple2/. +The apple2 package comes with additional secondary linker config files, which +are used via <tt/-t apple2 -C <configfile>/. + + +<sect1>default config file (<tt/apple2.cfg/)<p> + +Default configuration optimized for a binary program running on ProDOS 8 with +BASIC.SYSTEM. A plain vanilla ProDOS 8 doesn't actually use the Language Card +bank 2 memory from $D400 to $DFFF. + +<descrip> + + <tag><tt/RAM:/ Main memory area</tag> + From $803 to $95FF (35.5 KB) + + <tag><tt/LC:/ Language Card memory area</tag> + From $D400 to $DFFF (3 KB) + + <tag><tt/STARTADDRESS:/ Program start address</tag> + Variable (default: $803) + + <tag><tt/HEADER:/ Binary file header</tag> + DOS 3.3 header (address and length) + +</descrip><p> + + +<sect1><tt/apple2-dos33.cfg/<p> + +Configuration optimized for a binary program running on DOS 3.3. A plain +vanilla DOS 3.3 doesn't make use of the Language Card at all. + +<descrip> + + <tag><tt/RAM:/ Main memory area</tag> + From $803 to $95FF (35.5 KB) + + <tag><tt/LC:/ Language Card memory area</tag> + From $D000 to $FFFF (12 KB) + + <tag><tt/STARTADDRESS:/ Program start address</tag> + Variable (default: $803) + + <tag><tt/HEADER:/ Binary file header</tag> + DOS 3.3 header (address and length) + +</descrip><p> + + +<sect1><tt/apple2-system.cfg/<label id="apple-sys-cfg"><p> + +Configuration for a system program running on ProDOS 8. + +<descrip> + + <tag><tt/RAM:/ Main memory area</tag> + From $2000 to $BEFF (39.75 KB) + + <tag><tt/LC:/ Language Card memory area</tag> + From $D400 to $DFFF (3 KB) + + <tag><tt/STARTADDRESS:/ Program start address</tag> + Fixed ($2000) + + <tag><tt/HEADER:/ Binary file header</tag> + None + +</descrip><p> + + +<sect1><tt/apple2-loader.cfg/<label id="apple-load-cfg"><p> + +Configuration optimized for a binary program running on ProDOS 8 without +BASIC.SYSTEM. Intended to be used with <bf/LOADER.SYSTEM - an +Apple ][ ProDOS 8 loader for cc65 programs/, which is available +in the cc65 User Contributions section. + +A program loaded by LOADER.SYSTEM works like a ProDOS 8 system program but +isn't tied to the start address $2000. Thus with the default start +address $800 the main memory area is increased by 6 KB. + +<descrip> + + <tag><tt/RAM:/ Main memory area</tag> + From $800 to $BEFF (45.75 KB) + + <tag><tt/LC:/ Language Card memory area</tag> + From $D400 to $DFFF (3 KB) + + <tag><tt/STARTADDRESS:/ Program start address</tag> + Variable (default: $800) + + <tag><tt/HEADER:/ Binary file header</tag> + DOS 3.3 header (address and length) + +</descrip><p> + + +<sect1><tt/apple2-reboot.cfg/<p> + +Configuration optimized for a binary program running on ProDOS 8 without +BASIC.SYSTEM. Intended to be used with <bf/LOADER.SYSTEM - an +Apple ][ ProDOS 8 loader for cc65 programs/ (see above) together +with the function <tt/rebootafterexit()/. + +If a ProDOS 8 system program doesn't quit to the ProDOS 8 dispatcher but rather +reboots the machine after exit then a plain vanilla ProDOS 8 doesn't make use of +the Language Card bank 2 at all. + +This setup makes nearly 50 KB available to a cc65 program - on a 64 KB machine! + +<descrip> + + <tag><tt/RAM:/ Main memory area</tag> + From $800 to $BEFF (45.75 KB) + + <tag><tt/LC:/ Language Card memory area</tag> + From $D000 to $DFFF (4 KB) + + <tag><tt/STARTADDRESS:/ Program start address</tag> + Variable (default: $800) + + <tag><tt/HEADER:/ Binary file header</tag> + DOS 3.3 header (address and length) + +</descrip><p> + + + +<sect>ProDOS 8 system programs<p> + +ProDOS 8 system programs are always loaded to the start address $2000. +For cc65 programs this means that the 6 KB from $800 to $2000 are +by default unused. There are however several options to make use of that memory +range. + + +<sect1>LOADER.SYSTEM<p> + +The easiest (and for really large programs in fact the only) way to have a cc65 +program use the memory from $800 to $2000 is to link it as binary +(as opposed to system) program using the linker configuration +<ref id="apple-load-cfg" name="apple2-loader.cfg"> with start address +$803 and load it with the targetutil LOADER.SYSTEM. The program then works +like a system program (i.e. quits to the ProDOS dispatcher). + +Using LOADER.SYSTEM is as simple as copying it to the ProDOS 8 directory of the +program to load under name <program>.SYSTEM as a system program. For +example the program <tt/MYPROG/ is loaded by <tt/MYPROG.SYSTEM/. + + +<sect1>Heap<p> + +If the cc65 program can be successfully linked as system program using the linker +configuration <ref id="apple-sys-cfg" name="apple2-system.cfg">, but +uses the heap either explicitly or implicitly (i.e. by loading a driver) then +the memory from $800 to $2000 can be added to the heap by calling +<tt/_heapadd ((void *) 0x0800, 0x1800);/ at the beginning of <tt/main()/. + + +<sect1>ProDOS 8 I/O buffers<p> + +ProDOS 8 requires for every open file a page-aligned 1 KB I/O buffer. By default +these buffers are allocated by the cc65 runtime system on the heap using +<tt/posix_memalign()/. While this is generally the best solution it means quite +some overhead for (especially rather small) cc65 programs which do open files +but don't make use of the heap otherwise. + +The apple2 package comes with the alternative ProDOS 8 I/O buffer allocation +module <tt/apple2-iobuf-0800.o/ which uses the memory between $800 and +the program start address for the 1 KB I/O buffers. For system programs (with +start address $2000) this results in up to 6 I/O buffers and thus up to 6 +concurrently open files. + +While using <tt/_heapadd()/ as described in the section above together with the +default I/O buffer allocation basically yields the same placement of I/O buffers +in memory the primary benefit of <tt/apple2-iobuf-0800.o/ is a reduction in code +size - and thus program file size - of more than 1400 bytes. + +Using <tt/apple2-iobuf-0800.o/ is as simple as placing it on the linker command +line like this: + +<tscreen><verb> +cl65 -t apple2 -C apple2-system.cfg myprog.c apple2-iobuf-0800.o +</verb></tscreen> + + + +<sect>Platform specific header files<p> + +Programs containing Apple ][ specific code may use the +<tt/apple2.h/ header file. + + +<sect1>Apple ][ specific functions<p> + +The functions listed below are special for the Apple ][. See +the <url url="funcref.html" name="function reference"> for declaration and +usage. + +<itemize> +<item>_auxtype +<item>_dos_type +<item>_filetype +<item>get_ostype +<item>rebootafterexit +<item>ser_apple2_slot +<item>tgi_apple2_mix +</itemize> + + +<sect1>Hardware access<p> + +There's currently no support for direct hardware access. This does not mean +you cannot do it, it just means that there's no help. + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +<descrip> + + <tag><tt/a2.lo.tgi (a2_lo_tgi)/</tag> + This driver features a resolution of 40×48 with 16 colors. + + The function <tt/tgi_apple2_mix()/ allows to activate 4 lines of text. The + function clears the corresponding area at the bottom of the screen. + + <tag><tt/a2.hi.tgi (a2_hi_tgi)/</tag> + This driver features a resolution of 280×192 with 8 colors and two + hires pages. Note that programs using this driver will have to be linked + with <tt/--start-addr $4000/ to reserve the first hires page or with + <tt/--start-addr $6000/ to reserve both hires pages. + + The function <tt/tgi_apple2_mix()/ allows to activate 4 lines of text. The + function doesn't clear the corresponding area at the bottom of the screen. + + In memory constrained situations the memory from $803 to $1FFF + can be made available to a program by calling <tt/_heapadd ((void *) 0x0803, 0x17FD);/ + at the beginning of <tt/main()/. Doing so is beneficial even if the program + doesn't use the the heap explicitly because loading the driver (and in fact + already opening the driver file) uses the heap implicitly. + +</descrip><p> + + +<sect1>Extended memory drivers<p> + +<descrip> + + <tag><tt/a2.auxmem.emd (a2_auxmem_emd)/</tag> + Gives access to 47.5 KB RAM (190 pages of 256 bytes each) on an Extended + 80-Column Text Card. + + Note that this driver doesn't check for the actual existence of the memory + and that it doesn't check for ProDOS 8 RAM disk content! + +</descrip><p> + + +<sect1>Joystick drivers<p> + +<descrip> + + <tag><tt/a2.stdjoy.joy (a2_stdjoy_joy)/</tag> + Supports up to two standard analog joysticks connected to the game port of + the Apple ][. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +<descrip> + + <tag><tt/a2.stdmou.mou (a2_stdmou_mou)/</tag> + Driver for the AppleMouse II Card. Searches all Apple II slots + for an AppleMouse II Card compatible firmware. The default bounding + box is [0..279,0..191]. + + Programs using this driver will have to be linked with <tt/--start-addr $4000/ + to reserve the first hires page if they are intended to run on an + Apple ][ (in contrast to an Apple //e) because the + AppleMouse II Card firmware writes to the hires page when initializing + on that machine. + + Note that the Apple ][ default mouse callbacks support text + mode only. + +</descrip><p> + + +<sect1>RS232 device drivers<p> + +<descrip> + + <tag><tt/a2.ssc.ser (a2_ssc_ser)/</tag> + Driver for the Apple II Super Serial Card. Supports up to 19200 baud, + hardware flow control (RTS/CTS) and interrupt driven receives. Note + that because of the peculiarities of the 6551 chip transmits are not + interrupt driven, and the transceiver blocks if the receiver asserts + flow control because of a full buffer. + + The driver defaults to slot 2. Call <tt/ser_apple2_slot()/ prior to + <tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/ + succeeds for all Apple II slots, but <tt/ser_open()/ fails with + <tt/SER_ERR_NO_DEVICE/ if there's no SSC firmware found in the selected slot. + +</descrip><p> + + + +<sect>Limitations<p> + + +<sect1>DOS 3.3<p> + +Although the standard binaries generated by the linker for the Apple ][ +generally run both on DOS 3.3 (with Applesoft BASIC) and on ProDOS 8 (with +BASIC.SYSTEM) there are some limitations for DOS 3.3: + +<descrip> + + <tag>Disk File I/O</tag> + There's no disk file I/O support. Any attempt to use it yields an error with + <tt/errno/ set to <tt/ENOSYS/. This implicitly means that loadable drivers + are in general not functional as they depend on disk file I/O. Therefore the statically + linked drivers have to be used instead. + + <tag/Interrupts/ + There's no <tt/interruptor/ support. Any attempt to use it yields the message + 'FAILED TO ALLOC INTERRUPT' on program startup. This implicitly means that + <tt/a2.stdmou.mou/ and <tt/a2.ssc.ser/ are not functional as they depend on + interrupts. + +</descrip><p> + + +<sect1>Direct console I/O<p> + +<descrip> + + <tag/Color/ + The Apple ][ has no color text mode. Therefore the functions textcolor(), + bgcolor() and bordercolor() have no effect. + + <tag/Cursor/ + The Apple ][ has no hardware cursor. Therefore the function cursor() has + no effect. + +</descrip><p> + + + +<sect>Other hints<p> + + +<sect1>Passing arguments to the program<p> + +Command line arguments can be passed to <tt/main()/ after BLOAD. Since this is not +supported by BASIC, the following syntax was chosen: + +<tscreen><verb> +]CALL2051:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 +</verb></tscreen> + +<enum> +<item>Arguments are separated by spaces. +<item>Arguments may be quoted. +<item>Leading and trailing spaces around an argument are ignored. Spaces within + a quoted argument are allowed. +<item>The first argument passed to <tt/main/ is the program name. +<item>A maximum number of 10 arguments (including the program name) are + supported. +</enum> + + +<sect1>Interrupts<p> + +The runtime for the Apple ][ uses routines marked as +<tt/.INTERRUPTOR/ for ProDOS 8 interrupt handlers. Such routines must be +written as simple machine language subroutines and will be called +automatically by the interrupt handler code when they are linked into a +program. See the discussion of the <tt/.CONDES/ feature in the <url +url="ca65.html" name="assembler manual">. + + +<sect1>DIO<p> + +<descrip> + + <tag/Drive ID/ + The function <url url="dio.html#s1" name="dio_open()"> has the single + parameter <tt/device/ to identify the device to be opened. Therefore an + Apple II slot and drive pair is mapped to that <tt/device/ according + to the formula + + <tscreen> + device = slot + (drive - 1) * 8 + </tscreen> + + so that for example slot 6 drive 2 is mapped to <tt/device/ 14. + + <tag/Sector count/ + The function <url url="dio.html#s3" name="dio_query_sectcount()"> returns + the correct sector count for all ProDOS 8 disks. However for any non-ProDOS 8 + disk it simply always returns 280 (which is only correct for a 140 KB disk). + This condition is indicated by the <tt/_oserror/ value 82. + +</descrip><p> + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/apple2enh.sgml b/doc/apple2enh.sgml new file mode 100644 index 000000000..215c6d384 --- /dev/null +++ b/doc/apple2enh.sgml @@ -0,0 +1,537 @@ +<!doctype linuxdoc system> + +<article> + +<title>Enhanced Apple //e specific information for cc65 +<author><url url="mailto:ol.sc@web.de" name="Oliver Schmidt"> +<date>2014-04-10 + +<abstract> +An overview over the enhanced Apple //e runtime system as it is +implemented for the cc65 C compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the enhanced Apple //e runtime system +as it comes with the cc65 C compiler. It describes the memory layout, +enhanced Apple //e specific header files, available drivers, and any +pitfalls specific to that platform. + +Please note that enhanced Apple //e specific functions are just mentioned +here, they are described in detail in the separate <url url="funcref.html" +name="function reference">. Even functions marked as "platform dependent" may +be available on more than one platform. Please see the function reference for +more information. + + + +<sect>Binary format<p> + +The standard binary file format generated by the linker for the +enhanced Apple //e target is a binary program with a 4 byte DOS 3.3 header +containing the load address and load length. The default load address is +$803. + +<bf/AppleCommander 1.3.5/ or later (available at <url +url="http://applecommander.sourceforge.net/">) includes the option <tt/-cc65/ +that allows to put binary files with a DOS 3.3 header onto disk images +containing DOS 3.3 as well as ProDOS 8. + +For ProDOS 8 system programs the load address is fixed to $2000 so there +is no need for a header. Thus the linker configuration +<ref id="apple-sys-cfg" name="apple2enh-system.cfg"> for those programs +omits the DOS 3.3 header. The right AppleCommander option to put system files +without a header on a ProDOS 8 disk image is <tt/-p/. + + +<sect>Memory layout<p> + +In the standard setup, cc65 generated programs use the memory from +$803 to $95FF, so 35.5 KB of RAM are available. + +Special locations: + +<descrip> + + <tag/Stack/ + The C runtime stack is located at HIMEM and grows downwards, regardless of + how your linker config file is setup. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + +While running <tt/main()/ the Language Card bank 2 is enabled for read access. +However while running module constructors/destructors the Language Card is disabled. + +Enabling the Language Card allows to use it as additional memory for cc65 +generated code. However code is never automatically placed there. Rather code +needs to be explicitly placed in the Language Card either per file by compiling +with <tt/--code-name HIGHCODE/ or per function by enclosing in <tt/#pragma +code-name (push, "HIGHCODE")/ and <tt/#pragma code-name (pop)/. In either case the +cc65 runtime system takes care of actually moving the code into the Language +Card. + +The amount of memory available in the Language Card for generated code depends +on the chosen <ref id="link-configs" name="linker configuration">. + + + +<sect>Linker configurations<label id="link-configs"><p> + +The ld65 linker comes with a default config file for the enhanced Apple //e, +which is used via <tt/-t apple2enh/. +The apple2enh package comes with additional secondary linker config files, which +are used via <tt/-t apple2enh -C <configfile>/. + + +<sect1>default config file (<tt/apple2enh.cfg/)<p> + +Default configuration optimized for a binary program running on ProDOS 8 with +BASIC.SYSTEM. A plain vanilla ProDOS 8 doesn't actually use the Language Card +bank 2 memory from $D400 to $DFFF. + +<descrip> + + <tag><tt/RAM:/ Main memory area</tag> + From $803 to $95FF (35.5 KB) + + <tag><tt/LC:/ Language Card memory area</tag> + From $D400 to $DFFF (3 KB) + + <tag><tt/STARTADDRESS:/ Program start address</tag> + Variable (default: $803) + + <tag><tt/HEADER:/ Binary file header</tag> + DOS 3.3 header (address and length) + +</descrip><p> + + +<sect1><tt/apple2enh-dos33.cfg/<p> + +Configuration optimized for a binary program running on DOS 3.3. A plain +vanilla DOS 3.3 doesn't make use of the Language Card at all. + +<descrip> + + <tag><tt/RAM:/ Main memory area</tag> + From $803 to $95FF (35.5 KB) + + <tag><tt/LC:/ Language Card memory area</tag> + From $D000 to $FFFF (12 KB) + + <tag><tt/STARTADDRESS:/ Program start address</tag> + Variable (default: $803) + + <tag><tt/HEADER:/ Binary file header</tag> + DOS 3.3 header (address and length) + +</descrip><p> + + +<sect1><tt/apple2enh-system.cfg/<label id="apple-sys-cfg"><p> + +Configuration for a system program running on ProDOS 8. + +<descrip> + + <tag><tt/RAM:/ Main memory area</tag> + From $2000 to $BEFF (39.75 KB) + + <tag><tt/LC:/ Language Card memory area</tag> + From $D400 to $DFFF (3 KB) + + <tag><tt/STARTADDRESS:/ Program start address</tag> + Fixed ($2000) + + <tag><tt/HEADER:/ Binary file header</tag> + None + +</descrip><p> + + +<sect1><tt/apple2enh-loader.cfg/<label id="apple-load-cfg"><p> + +Configuration optimized for a binary program running on ProDOS 8 without +BASIC.SYSTEM. Intended to be used with <bf/LOADER.SYSTEM - an +Apple ][ ProDOS 8 loader for cc65 programs/, which is available +in the cc65 User Contributions section. + +A program loaded by LOADER.SYSTEM works like a ProDOS 8 system program but +isn't tied to the start address $2000. Thus with the default start +address $800 the main memory area is increased by 6 KB. + +<descrip> + + <tag><tt/RAM:/ Main memory area</tag> + From $800 to $BEFF (45.75 KB) + + <tag><tt/LC:/ Language Card memory area</tag> + From $D400 to $DFFF (3 KB) + + <tag><tt/STARTADDRESS:/ Program start address</tag> + Variable (default: $800) + + <tag><tt/HEADER:/ Binary file header</tag> + DOS 3.3 header (address and length) + +</descrip><p> + + +<sect1><tt/apple2enh-reboot.cfg/<p> + +Configuration optimized for a binary program running on ProDOS 8 without +BASIC.SYSTEM. Intended to be used with <bf/LOADER.SYSTEM - an +Apple ][ ProDOS 8 loader for cc65 programs/ (see above) together +with the function <tt/rebootafterexit()/. + +If a ProDOS 8 system program doesn't quit to the ProDOS 8 dispatcher but rather +reboots the machine after exit then a plain vanilla ProDOS 8 doesn't make use of +the Language Card bank 2 at all. + +This setup makes nearly 50 KB available to a cc65 program - on a 64 KB machine! + +<descrip> + + <tag><tt/RAM:/ Main memory area</tag> + From $800 to $BEFF (45.75 KB) + + <tag><tt/LC:/ Language Card memory area</tag> + From $D000 to $DFFF (4 KB) + + <tag><tt/STARTADDRESS:/ Program start address</tag> + Variable (default: $800) + + <tag><tt/HEADER:/ Binary file header</tag> + DOS 3.3 header (address and length) + +</descrip><p> + + + +<sect>ProDOS 8 system programs<p> + +ProDOS 8 system programs are always loaded to the start address $2000. +For cc65 programs this means that the 6 KB from $800 to $2000 are +by default unused. There are however several options to make use of that memory +range. + + +<sect1>LOADER.SYSTEM<p> + +The easiest (and for really large programs in fact the only) way to have a cc65 +program use the memory from $800 to $2000 is to link it as binary +(as opposed to system) program using the linker configuration +<ref id="apple-load-cfg" name="apple2enh-loader.cfg"> with start address +$803 and load it with the targetutil LOADER.SYSTEM. The program then works +like a system program (i.e. quits to the ProDOS dispatcher). + +Using LOADER.SYSTEM is as simple as copying it to the ProDOS 8 directory of the +program to load under name <program>.SYSTEM as a system program. For +example the program <tt/MYPROG/ is loaded by <tt/MYPROG.SYSTEM/. + + +<sect1>Heap<p> + +If the cc65 program can be successfully linked as system program using the linker +configuration <ref id="apple-sys-cfg" name="apple2enh-system.cfg">, but +uses the heap either explicitly or implicitly (i.e. by loading a driver) then +the memory from $800 to $2000 can be added to the heap by calling +<tt/_heapadd ((void *) 0x0800, 0x1800);/ at the beginning of <tt/main()/. + + +<sect1>ProDOS 8 I/O buffers<p> + +ProDOS 8 requires for every open file a page-aligned 1 KB I/O buffer. By default +these buffers are allocated by the cc65 runtime system on the heap using +<tt/posix_memalign()/. While this is generally the best solution it means quite +some overhead for (especially rather small) cc65 programs which do open files +but don't make use of the heap otherwise. + +The apple2enh package comes with the alternative ProDOS 8 I/O buffer allocation +module <tt/apple2enh-iobuf-0800.o/ which uses the memory between $800 and +the program start address for the 1 KB I/O buffers. For system programs (with +start address $2000) this results in up to 6 I/O buffers and thus up to 6 +concurrently open files. + +While using <tt/_heapadd()/ as described in the section above together with the +default I/O buffer allocation basically yields the same placement of I/O buffers +in memory the primary benefit of <tt/apple2enh-iobuf-0800.o/ is a reduction in code +size - and thus program file size - of more than 1400 bytes. + +Using <tt/apple2enh-iobuf-0800.o/ is as simple as placing it on the linker command +line like this: + +<tscreen><verb> +cl65 -t apple2enh -C apple2enh-system.cfg myprog.c apple2enh-iobuf-0800.o +</verb></tscreen> + + + +<sect>Platform specific header files<p> + +Programs containing enhanced Apple //e specific code may use the +<tt/apple2enh.h/ header file. + + +<sect1>Enhanced Apple //e specific functions<p> + +The functions listed below are special for the enhanced Apple //e. See +the <url url="funcref.html" name="function reference"> for declaration and +usage. + +<itemize> +<item>_auxtype +<item>_dos_type +<item>_filetype +<item>get_ostype +<item>rebootafterexit +<item>ser_apple2_slot +<item>textframe +<item>textframexy +<item>tgi_apple2_mix +<item>videomode +</itemize> + + +<sect1>Hardware access<p> + +There's currently no support for direct hardware access. This does not mean +you cannot do it, it just means that there's no help. + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +<descrip> + + <tag><tt/a2e.lo.tgi (a2e_lo_tgi)/</tag> + This driver features a resolution of 40×48 with 16 colors. + + The function <tt/tgi_apple2_mix()/ allows to activate 4 lines of text. The + function clears the corresponding area at the bottom of the screen. + + <tag><tt/a2e.hi.tgi (a2e_hi_tgi)/</tag> + This driver features a resolution of 280×192 with 8 colors and two + hires pages. Note that programs using this driver will have to be linked + with <tt/--start-addr $4000/ to reserve the first hires page or with + <tt/--start-addr $6000/ to reserve both hires pages. + + Note that the second hires page is only available if the text display is not in + 80 column mode. This can be asserted by calling <tt/videomode (VIDEOMODE_40COL);/ + before installing the driver. + + The function <tt/tgi_apple2_mix()/ allows to activate 4 lines of text. The + function doesn't clear the corresponding area at the bottom of the screen. + + In memory constrained situations the memory from $803 to $1FFF + can be made available to a program by calling <tt/_heapadd ((void *) 0x0803, 0x17FD);/ + at the beginning of <tt/main()/. Doing so is beneficial even if the program + doesn't use the the heap explicitly because loading the driver (and in fact + already opening the driver file) uses the heap implicitly. + +</descrip><p> + + +<sect1>Extended memory drivers<p> + +<descrip> + + <tag><tt/a2e.auxmem.emd (a2e_auxmem_emd)/</tag> + Gives access to 47.5 KB RAM (190 pages of 256 bytes each) on an Extended + 80-Column Text Card. + + Note that this driver doesn't check for the actual existence of the memory + and that it doesn't check for ProDOS 8 RAM disk content! + +</descrip><p> + + +<sect1>Joystick drivers<p> + +<descrip> + + <tag><tt/a2e.stdjoy.joy (a2e_stdjoy_joy)/</tag> + Supports up to two standard analog joysticks connected to the game port of + the enhanced Apple //e. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +<descrip> + + <tag><tt/a2e.stdmou.mou (a2e_stdmou_mou)/</tag> + Driver for the AppleMouse II Card. Searches all Apple II slots + for an AppleMouse II Card compatible firmware. The default bounding + box is [0..279,0..191]. + + Note that the enhanced Apple //e default mouse callbacks support + text mode only. + +</descrip><p> + + +<sect1>RS232 device drivers<p> + +<descrip> + + <tag><tt/a2e.ssc.ser (a2e_ssc_ser)/</tag> + Driver for the Apple II Super Serial Card. Supports up to 19200 baud, + hardware flow control (RTS/CTS) and interrupt driven receives. Note + that because of the peculiarities of the 6551 chip transmits are not + interrupt driven, and the transceiver blocks if the receiver asserts + flow control because of a full buffer. + + The driver defaults to slot 2. Call <tt/ser_apple2_slot()/ prior to + <tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/ + succeeds for all Apple II slots, but <tt/ser_open()/ fails with + <tt/SER_ERR_NO_DEVICE/ if there's no SSC firmware found in the selected slot. + +</descrip><p> + + + +<sect>Limitations<p> + + +<sect1>DOS 3.3<p> + +Although the standard binaries generated by the linker for the enhanced Apple //e +generally run both on DOS 3.3 (with Applesoft BASIC) and on ProDOS 8 (with +BASIC.SYSTEM) there are some limitations for DOS 3.3: + +<descrip> + + <tag>Disk File I/O</tag> + There's no disk file I/O support. Any attempt to use it yields an error with + <tt/errno/ set to <tt/ENOSYS/. This implicitly means that loadable drivers + are in general not functional as they depend on disk file I/O. Therefore the statically + linked drivers have to be used instead. + + <tag/Interrupts/ + There's no <tt/interruptor/ support. Any attempt to use it yields the message + 'Failed to alloc interrupt' on program startup. This implicitly means that + <tt/a2e.stdmou.mou/ and <tt/a2e.ssc.ser/ are not functional as they depend on + interrupts. + +</descrip><p> + + +<sect1>Direct console I/O<p> + +<descrip> + + <tag/Color/ + The enhanced Apple //e has no color text mode. Therefore the functions + textcolor(), bgcolor() and bordercolor() have no effect. + + <tag/Cursor/ + The enhanced Apple //e has no hardware cursor. Therefore the function + cursor() has no effect. + +</descrip><p> + + + +<sect>Other hints<p> + + +<sect1>Passing arguments to the program<p> + +Command line arguments can be passed to <tt/main()/ after BLOAD. Since this is not +supported by BASIC, the following syntax was chosen: + +<tscreen><verb> +]CALL2051:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 +</verb></tscreen> + +<enum> +<item>Arguments are separated by spaces. +<item>Arguments may be quoted. +<item>Leading and trailing spaces around an argument are ignored. Spaces within + a quoted argument are allowed. +<item>The first argument passed to <tt/main/ is the program name. +<item>A maximum number of 10 arguments (including the program name) are + supported. +</enum> + + +<sect1>Function keys<p> + +These are defined to be OpenApple + number key. + + +<sect1>Interrupts<p> + +The runtime for the enhanced Apple //e uses routines marked as +<tt/.INTERRUPTOR/ for ProDOS 8 interrupt handlers. Such routines must be +written as simple machine language subroutines and will be called +automatically by the interrupt handler code when they are linked into a +program. See the discussion of the <tt/.CONDES/ feature in the <url +url="ca65.html" name="assembler manual">. + + +<sect1>DIO<p> + +<descrip> + + <tag/Drive ID/ + The function <url url="dio.html#s1" name="dio_open()"> has the single + parameter <tt/device/ to identify the device to be opened. Therefore an + Apple II slot and drive pair is mapped to that <tt/drive_id/ according + to the formula + + <tscreen> + device = slot + (drive - 1) * 8 + </tscreen> + + so that for example slot 6 drive 2 is mapped to <tt/device/ 14. + + <tag/Sector count/ + The function <url url="dio.html#s3" name="dio_query_sectcount()"> returns + the correct sector count for all ProDOS 8 disks. However for any non-ProDOS 8 + disk it simply always returns 280 (which is only correct for a 140 KB disk). + This condition is indicated by the <tt/_oserror/ value 82. + +</descrip><p> + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/ar65.sgml b/doc/ar65.sgml new file mode 100644 index 000000000..136defd40 --- /dev/null +++ b/doc/ar65.sgml @@ -0,0 +1,148 @@ +<!doctype linuxdoc system> + +<article> + +<title>ar65 Users Guide +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>19.07.2000 + +<abstract> +ar65 is an archiver for object files generated by ca65. It allows to create +archives, add or remove modules from archives, and to extract modules from +existing archives. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + + +ar65 is a replacement for the libr65 archiver that was part of the cc65 C +compiler suite developed by John R. Dunning. libr65 had some problems and +the copyright does not permit some things which I wanted to be possible, +so I decided to write a completely new assembler/linker/archiver suite +for the cc65 compiler. ar65 is part of this suite. + +<sect>Usage<p> + + +The archiver is called as follows: + +<tscreen><verb> + Usage: ar65 <operation> lib file|module ... + Operation is one of: + a Add modules + d Delete modules + l List library contents + x Extract modules + V Print the archiver version +</verb></tscreen> + +You may add modules to a library using the `a' command. If the library +does not exist, it is created (and a warning message is printed which you +may ignore if creation of the library was your intention). You may +specify any number of modules on the command line following the library. + +If a module with the same name exists in the library, it is replaced by +the new one. The archiver prints a warning, if the module in the library +has a newer timestamp than the one to add. + +Here's an example: + +<tscreen><verb> + ar65 a mysubs.lib sub1.o sub2.o +</verb></tscreen> + +This will add two modules to the library `mysubs.lib' creating the +library if necessary. If the library contains modules named sub1.o or +sub2.o, they are replaced by the new ones. + +Modules names in the library are stored without the path, so, using + +<tscreen><verb> + ar65 a mysubs.lib ofiles/sub1.o ofiles/sub2.o +</verb></tscreen> + +will add two modules named `sub1.o' and `sub2.o' to the library. + +Deleting modules from a library is done with the `d' command. You may not +give a path when naming the modules. + +Example: + +<tscreen><verb> + ar65 d mysubs.lib sub1.o +</verb></tscreen> + +This will delete the module named `sub1.o' from the library, printing an +error if the library does not contain that module. + + +The `l' command prints a list of all modules in the library. Any module +names on the command line are ignored. + +Example: + +<tscreen><verb> + ar65 l mysubs.lib +</verb></tscreen> + + +Using the `x' command, you may extract modules from the library. The +modules named on the command line are extracted from the library and put +into the current directory. + +Note: Because of the indexing done by the archiver, the modules may have +a changed binary layout, that is, a binary compare with the old module +(before importing it into the library) may yield differences. The +extracted modules are accepted by the linker and archiver, however, so +this is not a problem. + +Example for extracting a module from the library: + +<tscreen><verb> + ar65 x mysubs.lib sub1.o +</verb></tscreen> + + +The `V' command prints the version number of the assembler. If you send +any suggestions or bugfixes, please include your version number. + +In addition to these operations, the archiver will check for, and warn +about duplicate external symbols in the library, every time when an +operation does update the library. This is only a warning, the linker +will ignore one of the duplicate symbols (which one is unspecified). + + +<sect>Copyright<p> + +ar65 (and all cc65 binutils) are (C) Copyright 1998-2000 Ullrich von +Bassewitz. For usage of the binaries and/or sources the following conditions +do apply: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> + + + diff --git a/doc/atari.sgml b/doc/atari.sgml new file mode 100644 index 000000000..47ce050e1 --- /dev/null +++ b/doc/atari.sgml @@ -0,0 +1,1015 @@ +<!doctype linuxdoc system> + +<article> + +<title>Atari specific information for cc65 +<author> +<url url="mailto:shawnjefferson@24fightingchickens.com" name="Shawn Jefferson"> and<newline> +<url url="mailto:chris@groessler.org" name="Christian Groessler"> +<date>2014-04-24 + +<abstract> +An overview over the Atari runtime system as it is implemented for the cc65 C +compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the Atari runtime system as it comes +with the cc65 C compiler. It describes the memory layout, Atari specific +header files, available drivers, and any pitfalls specific to that +platform. + +The Atari runtime support comes in two flavors: <tt/atari/ and <tt/atarixl/. +The <tt/atari/ target supports all Atari 8-bit computers, the <tt/atarixl/ only +supports XL type or newer machines (excluding the 600XL). + +The <tt/atarixl/ runtime makes the whole 64K of memory available, with the +exception of the I/O area at $D000 - $D7FF. Since the +<tt/atarixl/ runtime has some <ref name="limitations" id="limitations">, it is +recommended to use the <tt/atari/ target unless lack of memory dictates the +use of the <tt/atarixl/ target. + +Please note that Atari specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + + +<sect>Binary format<p> + +The Atari DOS executable file format supports more than one load block (<it/chunk/). + +The default binary output format generated by the linker for the +Atari target is a machine language program with a standard executable +header (FF FF <load chunk #1> ... <load chunk #n>). +A load chunk has the format [<2 byte start address> <2 bytes end address> +<chunk data>]. +A run vector is added to the end of the +file ($02E0 $02E1 <run vector>) and is calculated using +the <tt/start/ label in crt0.s. (Technically the run vector is also a load chunk, +but is not regarded as such here.) + +An <tt/atari/ program has two load chunks, an <tt/atarixl/ program has three load +chunks. The load chunks are defined in the linker configuration files. For more +detailed information about the load chunks see the chapter +<ref name="Technical details" id="techdetail">. For the discussion here it's +sufficient to know that the first load chunk(s) do preparation work and the +main part of the program is in the last load chunk. + +The values determining the size of the main part of the program (the second load +chunk for <tt/atari/, the third load chunk for <tt/atarixl/) are calculated in +the crt0.s file from the __STARTUP_LOAD__ and __BSS_LOAD__ values. +Be aware of that if you create a custom linker config file and start moving segments around (see section +<ref name="Reserving a memory area inside the program" id="memhole">). + + +<sect>Memory layout<p> + +<sect1><tt/atari/ target<p> + +The default linker config file assumes that the BASIC ROM is disabled (or +the BASIC cartridge unplugged). This gives a usable memory range of +[$2000-$BC1F]. The library startup code examines the +current memory configuration, which depends on the size of the +installed memory and cartridges. It does so by using the value in +the MEMTOP ($2E5) variable as highest memory address the program +can use. The initial stack pointer, which is the upper bound of +memory used by the program, is set to this value, minus an optionally +defined __RESERVED_MEMORY__ value. + +The default load address of $2000 can be changed by creating a custom +linker config file or by using the "--start-addr" cl65 command line +argument or the "--start-addr" or "-S" ld65 command line arguments. + +Please note that the first load chunk (which checks the available memory) +will always be loaded at $2E00, regardless of the specified start +address. This address can only be changed by a custom linker config file. + +Special locations: + +<descrip> + <tag/Text screen/ + The text screen depends on the installed memory size and cartridges + and can be obtained from the SAVMSC variable ($58). + + <tag/Stack/ + The C runtime stack is located at MEMTOP and grows downwards, + regardless of how your linker config file is setup. This + accommodates the different memory configurations of the Atari + machines, as well as having a cartridge installed. You can override + this behaviour by writing your own crt0.s file and linking it to + your program (see also <ref name="Final note" + id="memhole_final_note">). + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + +<sect1><tt/atarixl/ target<p> + +The startup code rearranges the memory as follows: + +<enum> +<item>Sceen memory and display list are moved below the program start address. +<item>The ROM is disabled, making the memory in the areas [$C000-$CFFF] +and [$D800-$FFF9] available. +<item>Character generator data is copied from ROM to the CHARGEN location specified in the +linker config file. This is (in the default <tt/atarixl.cfg/ file) at the same address as +where it is in ROM ($E000, it can be changed, see <ref name="atarixl chargen location" +id="chargenloc">). With the character generator at $E000, there are two upper memory +areas available, [$D800-$DFFF] and [$E400-$FFF9]. +</enum> + +With the default load address of $2400 this gives a usable memory range of +[$2400-$CFFF]. + +Please note that the first load chunk (which checks the system +compatibilty and available memory) will always be loaded at +$2E00, regardless of the specified start address. This address +can only be changed by a custom linker config file. + +Special locations: + +<descrip> + <tag/Text screen/ + The text screen depends on the selected load address ($2400 + by default), and resides directly before that address, rounded to the next + lower page boundary. + The screen memory's start address can be obtained from the SAVMSC variable + ($58). + + <tag/Stack/ + The C runtime stack is located at end of the RAM memory area ($CFFF) + and grows downwards. + + <tag/Heap/ + The C heap is located at the end of the program (end of BSS segment) and + grows towards the C runtime stack. + +</descrip><p> + +<sect>Linker configurations<p> + +The ld65 linker comes with default config files for the Atari. There +are two targets for the Atari, <tt/atari/ and <tt/atarixl/. +The default config file for <tt/atari/ is selected with +<tt/-t atari/, and the default config file for <tt/atarixl/ is selected with +<tt/-t atarixl/. +The Atari package comes with additional secondary linker config files which +can be used via <tt/-t atari -C <configfile>/ (for <tt/atari/ target) or +<tt/-t atarixl -C <configfile>/ (for <tt/atarixl/ target). + +<sect1><tt/atari/ config files<p> + +<sect2>default config file (<tt/atari.cfg/)<p> + +The default configuration is tailored to C programs. It creates files +which have a default load address of $2000. + +The files generated by this config file include the +<ref name="&dquot;system check&dquot;" id="syschk"> load chunk. It can +optionally be left out, see <ref name="Getting rid of the &dquot;system check&dquot; load chunk" id="nosyschk">. + +<sect2><tt/atari-asm.cfg/<p> + +This config file aims to give the assembler programmer maximum +flexibility. All program segments (<tt/CODE/, <tt/DATA/, etc.) are +optional. + +By default it creates regular DOS executable files, which have a default +load address of $2E00. It's also possible to generate an image of +just the program data without EXE header, load address, or (auto-)start address. +To you so, you have to define the symbols <tt/__AUTOSTART__/ and <tt/__EXEHDR__/ +when linking the program. Therefore, to generate a "plain" binary file, pass the +options "<tt/-D__AUTOSTART__=1 -D__EXEHDR__=1/" to the linker. +It's also possible to create a non auto-starting program file, by defining +only the <tt/__AUTOSTART__/ symbol. Such a program has to be run manually +after being loaded by DOS (for example by using the "M" option of DOS 2.5). +Defining only the <tt/__EXEHDR__/ symbol will create a (useless) file which +doesn't conform to the DOS executable file format (like a "plain" binary file) +but still has the "autostart" load chunk appended. + +The sections of the file which the defines refer to (<tt/__AUTOSTART__/ for +the autostart trailer, <tt/__EXEHDR__/ for the EXE header and load address) +is <it/left out/, keep this in mind. + +The values you assign to the two symbols <tt/__AUTOSTART__/ and <tt/__EXEHDR__/ +don't matter. + +<sect2><tt/atari-cart.cfg/<p> + +This config file can be used to create 8K or 16K cartridges. It's suited both +for C and assembly language programs. + +By default, an 8K cartridge is generated. To create a 16K cartridge, pass the +size of the cartridge to the linker, like "<tt/-D__CARTSIZE__=0x4000/". +The only valid values for <tt/__CARTSIZE__/ are 0x2000 and 0x4000. + +The option byte of the cartridge can be set with the <tt/__CARTFLAGS__/ +value, passed to the linker. The default value is $01, which means +that the cartridge doesn't prevent the booting of DOS. + +The option byte will be located at address $BFFD. For more information +about its use, see e.g. "Mapping the Atari". + +<sect2><tt/atari-cassette.cfg/<p> + +This config file can be used to create cassette boot files. It's suited both +for C and assembly language programs. + +The size of a cassette boot file is restricted to 32K. Larger programs +would need to be split in more parts and the parts to be loaded manually. + +To write the generated file to a cassette, a utility to run +on an Atari is provided in the <tt/targetutil/ directory (<tt/w2cas.com/). + +<sect1><tt/atarixl/ config files<p> + +<sect2>default config file (<tt/atarixl.cfg/)<p> + +The default configuration is tailored to C programs. It creates files +which have a default load address of $2400. + +The files generated by this config file include the +<ref name="&dquot;system check&dquot;" id="syschkxl"> load chunk. It can +optionally be left out, see <ref name="Getting rid of the &dquot;system check&dquot; load chunk" id="nosyschk">. + +<sect2><tt/atarixl-largehimem.cfg/<p> + +This is the same as the default config file, but it rearranges the +high memory beneath the ROM into one large block. In order for this +config file to work, the runtime library has to be recompiled with a +special define. See the file <tt/libsrc/atari/Makefile.inc/ in the +source distribution. + +The files generated by this config file include the +<ref name="&dquot;system check&dquot;" id="syschkxl"> load chunk. It can +optionally be left out, see <ref name="Getting rid of the &dquot;system check&dquot; load chunk" id="nosyschk">. + + +<sect>Platform specific header files<p> + +Programs containing Atari specific code may use the <tt/atari.h/ +header file. + + +<sect1>Atari specific functions<p> + +The functions and global variable listed below are special for the Atari. +See the <url url="funcref.html" name="function reference"> for declaration and usage. + +<itemize> +<item>get_ostype +<item>get_tv +<item>_dos_type +<item>_gtia_mkcolor +<item>_getcolor +<item>_getdefdev +<item>_graphics +<item>_rest_vecs +<item>_save_vecs +<item>_scroll +<item>_setcolor +<item>_setcolor_low +</itemize> + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/atari.h/ header +file do allow access to hardware located in the address space. Some +variables are structures, accessing the struct fields will access the +chip registers. + +<descrip> + + <tag><tt/GTIA_READ/ and <tt/GTIA_WRITE/</tag> + The <tt/GTIA_READ/ structure allows read access to the GTIA. The + <tt/GTIA_WRITE/ structure allows write access to the GTIA. + See the <tt/_gtia.h/ header file located in the include directory + for the declaration of the structure. + + <tag><tt/POKEY_READ/ and <tt/POKEY_WRITE/</tag> + The <tt/POKEY_READ/ structure allows read access to the POKEY. The + <tt/POKEY_WRITE/ structure allows write access to the POKEY. + See the <tt/_pokey.h/ header file located in the include directory + for the declaration of the structure. + + <tag><tt/ANTIC/</tag> + The <tt/ANTIC/ structure allows read access to the ANTIC. + See the <tt/_antic.h/ header file located in the include directory + for the declaration of the structure. + + <tag><tt/PIA/</tag> + The <tt/PIA/ structure allows read access to the PIA 6520. + See the <tt/_pia.h/ header file located in the include directory + for the declaration of the structure. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +<table><tabular ca="rrrr"> +<tt/atari/|<tt/atarixl/|screen resolution|display pages@<hline> +<tt/atr3.tgi (atr3_tgi)/|<tt/atrx3.tgi (atrx3_tgi)/|40x24x4 (CIO mode 3, ANTIC mode 8)|1@ +<tt/atr4.tgi (atr4_tgi)/|<tt/atrx4.tgi (atrx4_tgi)/|80x48x2 (CIO mode 4, ANTIC mode 9)|1@ +<tt/atr5.tgi (atr5_tgi)/|<tt/atrx5.tgi (atrx5_tgi)/|80x48x4 (CIO mode 5, ANTIC mode A)|1@ +<tt/atr6.tgi (atr6_tgi)/|<tt/atrx6.tgi (atrx6_tgi)/|160x96x2 (CIO mode 6, ANTIC mode B)|1@ +<tt/atr7.tgi (atr7_tgi)/|<tt/atrx7.tgi (atrx7_tgi)/|160x96x4 (CIO mode 7, ANTIC mode D)|1@ +<tt/atr8.tgi (atr8_tgi)/|<tt/atrx8.tgi (atrx8_tgi)/|320x192x2 (CIO mode 8, ANTIC mode F)|1@ +<tt/atr8p2.tgi (atr8p2_tgi)/|<tt/atrx8p2.tgi (atrx8p2_tgi)/|320x192x2 (CIO mode 8, ANTIC mode F)|2@ +<tt/atr9.tgi (atr9_tgi)/|<tt/atrx9.tgi (atrx9_tgi)/|80x192x16b (CIO mode 9, ANTIC mode F, GTIA mode $40)|1@ +<tt/atr9p2.tgi (atr9p2_tgi)/|<tt/atrx9p2.tgi (atrx9p2_tgi)/|80x192x16b (CIO mode 9, ANTIC mode F, GTIA mode $40)|2@ +<tt/atr10.tgi (atr10_tgi)/|<tt/atrx10.tgi (atrx10_tgi)/|80x192x9 (CIO mode 10, ANTIC mode F, GTIA mode $80)|1@ +<tt/atr10p2.tgi (atr10p2_tgi)/|<tt/atrx10p2.tgi (atrx10p2_tgi)/|80x192x9 (CIO mode 10, ANTIC mode F, GTIA mode $80)|2@ +<tt/atr11.tgi (atr11_tgi)/|<tt/atrx11.tgi (atrx11_tgi)/|80x192x16h (CIO mode 11, ANTIC mode F, GTIA mode $C0)|1@ +<tt/atr14.tgi (atr14_tgi)/|<tt/atrx14.tgi (atrx14_tgi)/|160x192x2 (CIO mode 14, ANTIC mode C)|1@ +<tt/atr15.tgi (atr15_tgi)/|<tt/atrx15.tgi (atrx15_tgi)/|160x192x4 (CIO mode 15, ANTIC mode E)|1@ +<tt/atr15p2.tgi (atr15p2_tgi)/|<tt/atrx15p2.tgi (atrx15p2_tgi)/|160x192x4 (CIO mode 15, ANTIC mode E)|2 +</tabular> +<!-- <caption>bla bla --> +</table> + + +Many graphics modes require more memory than the text screen which is +in effect when the program starts up. Therefore the programmer has to +tell the program beforehand the memory requirements of the graphics +modes the program intends to use. + +On the <tt/atari/ target his can be done by using the __RESERVED_MEMORY__ +linker config variable. The number specified there describes the number +of bytes to subtract from the top of available memory as seen from the +runtime library. This memory is then used by the screen buffer. + +On the <tt/atarixl/ target the screen memory resides below the program +load address. In order to reserve memory for a graphics mode, one +simply uses a higher program load address. There are restrictions on +selectable load addresses, +see <ref name="Selecting a good program load address" id="loadaddr">. + +The numbers for the different graphics modes presented below should +only be seen as a rule of thumb. Since the screen buffer memory needs +to start at specific boundaries, the numbers depend on the current top +of available memory. +The following numbers were determined by a BASIC program. + +<table> +<tabular ca="rr"> +graphics mode|reserved memory@<hline> +0|1@ +1|1@ +2|1@ +3|1@ +4|1@ +5|182@ +6|1182@ +7|3198@ +8|7120@ +9|7146@ +10|7146@ +11|7146@ +12|162@ +13|1@ +14|3278@ +15|7120@ +16|1@ +17|1@ +18|1@ +19|1@ +20|1@ +21|184@ +22|1192@ +23|3208@ +24|7146@ +25|7146@ +26|7146@ +27|7146@ +28|162@ +29|1@ +30|3304@ +31|7146 +</tabular> +<caption>reserved memory required for different graphics modes +</table> + +The values of "1" are needed because the graphics command crashes if +it doesn't have at least one byte available. This seems to be a bug of +the Atari ROM code. + +Default drivers: <tt/atr8.tgi (atr8_tgi)/ and <tt/atrx8.tgi (atrx8_tgi)/. + +<sect1>Extended memory drivers<p> + +Currently there is only one extended memory driver. It manages the second 64K of a 130XE. + +<table> +<tabular ca="rr"> +<tt/atari/|<tt/atarixl/@<hline> +<tt/atr130.emd (atr130_emd)/|<tt/atrx130.emd (atrx130_emd)/ +</tabular> +</table> + +<sect1>Joystick drivers<p> + +Currently there are two joystick drivers available: + +<table> +<tabular ca="rrr"> +<tt/atari/|<tt/atarixl/|description@<hline> +<tt/atrstd.joy (atrstd_joy)/|<tt/atrxstd.joy (atrxstd_joy)/|Supports up to two/four standard joysticks connected to the joystick ports of the Atari. (Four on the pre-XL systems, two on XL or newer.)@ +<tt/atrmj8.joy (atrmj8_joy)/|<tt/atrxmj8.joy (atrxmj8_joy)/|Supports up to eight standard joysticks connected to a MultiJoy adapter. +</tabular> +</table> + +Default drivers: <tt/atrstd.joy (atrstd_joy)/ and <tt/atrxstd.joy (atrxstd_joy)/. + +<sect1>Mouse drivers<p> + +Currently there are five mouse drivers available: + +<table> +<tabular ca="rrr"> +<tt/atari/|<tt/atarixl/|description@<hline> +<tt/atrjoy.mou (atrjoy_mou)/|<tt/atrxjoy.mou (atrxjoy_mou)/|Supports a mouse emulated by a standard joystick.@ +<tt/atrst.mou (atrst_mou)/|<tt/atrxst.mou (atrxst_mou)/|Supports an Atari ST mouse.@ +<tt/atrami.mou (atrami_mou)/|<tt/atrxami.mou (atrxami_mou)/|Supports an Amiga mouse.@ +<tt/atrtrk.mou (atrtrk_mou)/|<tt/atrxtrk.mou (atrxtrk_mou)/|Supports an Atari trakball.@ +<tt/atrtt.mou (atrtt_mou)/|<tt/atrxtt.mou (atrxtt_mou)/|Supports an Atari touch tablet. +</tabular> +</table> + +All mouse devices connect to joystick port #0. + +Default drivers: <tt/atrst.mou (atrst_mou)/ and <tt/atrxst.mou (atrxst_mou)/. + +<sect2>Mouse callbacks<p> + +There are two mouse callbacks available. +<p> +The "text mode" callbacks (<tt/mouse_txt_callbacks/) display the mouse cursor as a "diamond" character +on the standard "GRAPHICS 0" text mode screen. The mouse cursor character can be changed by an +assembly file defining the character by exporting the zeropage symbol <tt/mouse_txt_char/. +The default file looks like this: +<tscreen><verb> + .export mouse_txt_char : zp = 96 ; 'diamond' screen code +</verb></tscreen> +<p> +The "P/M" callbacks (<tt/mouse_pm_callbacks/) use Player-Missile graphics for the mouse cursor. +The cursor shape can be changed, too, by an assembly file. Here's the default shape definition: +<tscreen><verb> + .export mouse_pm_bits + .export mouse_pm_height : zeropage + .export mouse_pm_hotspot_x : zeropage + .export mouse_pm_hotspot_y : zeropage + .rodata +mouse_pm_bits: + .byte %11110000 + .byte %11000000 + .byte %10100000 + .byte %10010000 + .byte %10001000 + .byte %00000100 + .byte %00000010 +mouse_pm_height = * - mouse_pm_bits +; hot spot is upper left corner +mouse_pm_hotspot_x = 0 +mouse_pm_hotspot_y = 0 +</verb></tscreen> +<p> +<tt/mouse_pm_bits/ defines the shape of the cursor, <tt/mouse_pm_height/ defines the number of +bytes in <tt/mouse_pm_bits/. <tt/mouse_pm_hotspot_x/ and <tt/mouse_pm_hotspot_y/ define the +position in the shape where "the mouse points to". When using this callback page #6 ($600 + - $6FF) is used for the P/M graphics data and no P/M graphics can otherwise be used +by the program. The height of the shape (<tt/mouse_pm_height/) +must not exceed 32 lines since the callback routines cannot handle more than 32 lines. +<p> +The default callbacks definition (<tt/mouse_def_callbacks/) is an alias for the "P/M" callbacks. + +<sect1>RS232 device drivers<p> + +Currently there is one RS232 driver. It uses the R: device (therefore +an R: driver needs to be installed) and was tested with the 850 +interface module. + +<table> +<tabular ca="rr"> +<tt/atari/|<tt/atarixl/@<hline> +<tt/atrrdev.ser (atrrdev_ser)/|<tt/atrxrdev.ser (atrxrdev_ser)/ +</tabular> +</table> + + +<sect>Limitations<p> + +<sect1><tt/atarixl/<#if output="info|latex2e"> limitations</#if><label id="limitations"<p> + +<itemize> +<item>The display is cleared at program start and at program termination. This is a side +effect of relocating the display memory below the program start address. +<item>Not all possible CIO and SIO functions are handled by the runtime stub code which banks +the ROM in and out. All functions used by the runtime library are handled, though. +<item>The <tt/_sys()/ function is not supported. +<item>It is not compatible with DOSes or other programs using the memory below the ROM. +</itemize> + +<sect>DIO implementation<label id="dio"><p> + +The Atari supports disk drives with either 128 or 256 byte sectors. +The first three sectors of any disk are always 128 bytes long though. This is +because the system can only boot from 128 bytes sectors. + +Therefore the DIO read and write functions transfer only 128 bytes +for sectors 1 to 3, regardless of the type of diskette. + + +<sect>CONIO implementation<label id="conio"><p> + +The console I/O is speed optimized therefore support for XEP80 hardware +or f80.com software is missing. Of course you may use stdio.h functions. + + +<sect>Technical details<label id="techdetail"><p> + +<sect1><tt/atari/<#if output="info|latex2e"> details</#if><p> + +<sect2><#if output="info|latex2e"><tt/atari/ </#if>Load chunks<p> + +An <tt/atari/ program contains two load chunks. + +<enum> +<item>"system check"<label id="syschk">&nl; +This load chunk is always loaded at address $2E00, and checks if the system has +enough memory to run the program. It also checks if the program start address is not +below MEMLO. If any of the checks return false, the loading of the program is aborted.&nl; +The contents of this chunk come from the SYSCHKCHNK memory area of the linker config file. +<item>main program&nl; +This load chunk is loaded at the selected program start address (default $2000) and +contains all of the code and data of the program.&nl; +The contents of this chunk come from the RAM memory area of the linker config file. +</enum> + + +<sect1><tt/atarixl/<#if output="info|latex2e"> details</#if><p> + +<sect2>General operation<p> + +The <tt/atarixl/ target banks out the ROM while the program is running in +order to make more memory available to the program. + +The screen memory is by default located at the top of available memory, +$BFFF if BASIC is not enabled, $9FFF if BASIC is enabled. +Therefore, in order to create a largest possible continuous memory area, +the screen memory is moved below the program load address. This gives +a memory area from <program load addr> to $CFFF. + +The startup code installs wrappers for interrupt handlers and ROM routines. +When an interrupt or call to a ROM routine happens, the wrappers enable the +ROM, call the handler or routine, and disable the ROM again. + +The "wrapping" of the ROM routines is done by changing the ROM entry +point symbols in <tt/atari.inc/ to point to the wrapper functions. + +For ROM functions which require input or output buffers, the wrappers +copy the data as required to buffers in low memory. + +<sect2><#if output="info|latex2e"><tt/atarixl/ </#if>Load chunks<label id="xlchunks"><p> + +An <tt/atarixl/ program contains three load chunks. + +<enum> +<item>"system check"<label id="syschkxl">&nl; +This load chunk is always loaded at address $2E00, and checks if the system is +suitable for running the program. It also checks if there is enough room between MEMLO +and the program start address to move the text mode screen buffer there. If any of the +checks return false, the loading of the program is aborted.&nl; +The contents of this chunk come from the SYSCHKCHNK memory area of the linker config file. +<item>"shadow RAM prepare"&nl; +The second load chunk gets loaded to the selected program load address (default $2400). +It moves the screen memory below the program load address, copies the character generator +from ROM to its new place in RAM, and copies the parts of the program which reside in +high memory below the ROM to their place. The high memory parts are included in this load chunk.&nl; +At the beginning of this load chunk there is a .bss area, which is not part of the +EXE file. Therefore the on-disk start address of this load chunk will be higher than the +selected start address. This .bss area (segment LOWBSS) contains the buffers for the +double buffering of ROM input and output data. If you add contents to this segment be aware +that the contents won't be zero initialized by the startup code.&nl; +The contents of this chunk come from the SRPREPCHNK memory area of the linker config file. +<item>main program&nl; +This load chunk is loaded just above the LOWBSS segment, replacing the code of +the previous load chunk. It contains all remaining code and data sections of the program, +including the startup code.&nl; +The contents of this chunk come from the RAM memory area of the linker config file. +</enum> + +<sect2>Moving screen memory below the program start address<p> + +When setting a graphics mode, the ROM looks at the RAMTOP location. RAMTOP +describes the amount of installed memory in pages (RAMTOP is only one byte). +The screen memory and display list are placed immediately below RAMTOP. + +Now in order to relocate the screen memory to lower memory, the startup code +puts a value into RAMTOP which causes the ROM routines to allocate the display +memory below the program start address and then it issues a ROM call to setup +the regular text mode. + +<sect2>Selecting a good program load address<label id="loadaddr"><p> + +Due to the movement of the screen memory below the program start, there are some +load addresses which are sub-optimal because they waste memory or prevent a +higher resolution graphics mode from being enabled. + +There are restrictions at which addresses screen memory (display buffer and display +list) can be placed. The display buffer cannot cross a 4K boundary and a display +list cannot cross a 1K boundary. + +The startup code takes this into account when moving the screen memory down. +If the program start address (aligned to the next lower page boundary) minus +the screen buffer size would result in a screen buffer which spans a 4K +boundary, the startup code lowers RAMTOP to this 4K boundary.&nl; +The size of the screen buffer in text mode is 960 ($3C0) bytes. So, for +example, a selected start address of $2300 would span the 4K boundary +at $2000. The startup code would adjust the RAMTOP value in such way that +the screen memory would be located just below this boundary (at $1C40). +This results in the area [$2000-$22FF] being wasted. +Additionally, the program might fail to load since the lowest address used +by the screen memory could be below MEMLO. (The lowest address used in this +example would be at $1C20, where the display list would allocated.) + +These calculations are performed by the startup code (in the first two +load chunks), but the startup code only takes the default 40x24 text mode +into account. If the program later wants to load TGI drivers which set +a more memory consuming graphics mode, the user has to pick a higher +load address. +Using higher resolution modes there is a restriction in the ROM that it +doesn't expect RAMTOP to be at arbitrary values. The Atari memory modules +came only in 8K or 16K sizes, so the ROM expects RAMTOP to only have +values in 8K steps. Therefore, when using the highest resolution modes +the program start address must be at an 8K boundary. + + +<sect2>Character generator location<label id="chargenloc"><p> + +The default <tt/atarixl/ linker config file (<tt/atarixl.cfg/) leaves the +character generator location at the same address where it is in ROM +($E000). This has the disadvatage to split the upper memory into +two parts ([$D800-$DFFF] and +[$E400-$FFF9]). For applications which +require a large continuous upper memory area, an alternative linker +config file (<tt/atarixl-largehimem.cfg/) is provided. It relocates the +character generator to $D800, providing a single big upper +memory area at [$DC00-$FFF9]. + +With the character generator at a different address than in ROM, the routines +which enable and disable the ROM also have to update the chargen pointer. +This code is not enabled by default. In order to enable it, +uncomment the line which sets CHARGEN_RELOC in <tt/libsrc/atari/Makefile.inc/ +and recompile the <tt/atarixl/ runtime library. + +<sect>Other hints<p> + + +<sect1>Function keys<p> + +Function keys are mapped to Atari + number key. + + +<sect1>Passing arguments to the program<p> + +Command line arguments can be passed to <tt/main()/ when the used DOS supports it. + +<enum> +<item>Arguments are separated by spaces. +<item>Leading and trailing spaces around an argument are ignored. +<item>The first argument passed to <tt/main/ is the program name. +<item>A maximum number of 16 arguments (including the program name) are + supported. +</enum> + + +<sect1>Interrupts<p> + +The runtime for the Atari uses routines marked as <tt/.INTERRUPTOR/ for +interrupt handlers. Such routines must be written as simple machine language +subroutines and will be called automatically by the VBI handler code +when they are linked into a program. See the discussion of the <tt/.CONDES/ +feature in the <url url="ca65.html" name="assembler manual">. + +Please note that on the Atari targets the <tt/.INTERRUPTOR/s are being +run in NMI context. The other targets run them in IRQ context. + +<sect1>Reserving a memory area inside a program<label id="memhole"><p> + +(This section is primarily applicable to the <tt/atari/ target, but the +principles apply to <tt/atatixl/ as well.) + +The Atari 130XE maps its additional memory into CPU memory in 16K +chunks at address $4000 to $7FFF. One might want to +prevent this memory area from being used by cc65. Other reasons to +prevent the use of some memory area could be to reserve space for the +buffers for display lists and screen memory. +<p> +The Atari executable format allows holes inside a program, e.g. one +part loads into $2E00 to $3FFF, going below the reserved +memory area (assuming a reserved area from $4000 to +$7FFF), and another part loads into $8000 to +$BC1F. +<p> +Each load chunk of the executable starts with a 4 byte header which +defines its load address and size. In the following linker config files +these headers are named HEADER and SECHDR (for the MEMORY layout), and +accordingly NEXEHDR and CHKHDR (for the SEGMENTS layout). +<p> +<sect2>Low code and high data example<p> +Goal: Create an executable with 2 load chunks which doesn't use the +memory area from $4000 to $7FFF. The CODE segment of +the program should go below $4000 and the DATA and RODATA +segments should go above $7FFF. +<p> +The main problem is that the EXE header generated by the cc65 runtime +lib is wrong. It defines a single load chunk with the sizes/addresses +of the STARTUP, LOWCODE, INIT, CODE, RODATA, and DATA segments, in +fact, the whole user program (we're disregarding the "system check" +load chunk here). +<p> +The contents of the EXE header come from the EXEHDR and MAINHDR segments. +The EXEHDR segment just contains the $FFFF value which is required +to be the first bytes of the EXE file.&nl; +The MAINHDR are defined in in crt0.s. This cannot be changed without +modifying and recompiling the cc65 atari runtime library. Therefore +the original contents of this segment must be discarded and be +replaced by a user created one. This discarding is done by assigning the +MAINHDR segment to the (new introduced) DISCARD memory area. The DISCARD memory area is +thrown away in the new linker config file (written to file ""). +We add a new FSTHDR segment for the chunk header of the first chunk. +<p> +The user needs to create a customized linker config file which adds +new memory areas and segments to hold the new header data for the first load +chunk and the header data for the second load chunk. Also an assembly source file +needs to be created which defines the contents of the new header data +for the two load chunks. +<p> +<p> +This is an example of a modified cc65 Atari linker configuration file +(split.cfg): +<tscreen><verb> +SYMBOLS { + __STACKSIZE__: value = $800 type = weak; # 2K stack + __RESERVED_MEMORY__: value = $0000, type = weak; +} +FEATURES { + STARTADDRESS: default = $2E00; +} +MEMORY { + ZP: start = $82, size = $7E, type = rw, define = yes; + + HEADER: start = $0000, size = $2, file = %O; # first load chunk + + FSTHDR: start = $0000, size = $4, file = %O; # second load chunk + RAMLO: start = %S, size = $4000 - %S, file = %O; + + DISCARD: start = $4000, size = $4000, file = ""; + + SECHDR: start = $0000, size = $4, file = %O; # second load chunk + RAM: start = $8000, size = $3C20, file = %O; # $3C20: matches upper bound $BC1F +} +SEGMENTS { + EXEHDR: load = HEADER, type = ro; + + MAINHDR: load = DISCARD, type = ro; + + NEXEHDR: load = FSTHDR, type = ro; # first load chunk + STARTUP: load = RAMLO, type = ro, define = yes; + LOWCODE: load = RAMLO, type = ro, define = yes, optional = yes; + INIT: load = RAMLO, type = ro, optional = yes; + CODE: load = RAMLO, type = ro, define = yes; + + CHKHDR: load = SECHDR, type = ro; # second load chunk + RODATA: load = RAM, type = ro, define = yes; + DATA: load = RAM, type = rw, define = yes; + BSS: load = RAM, type = bss, define = yes; + + ZEROPAGE: load = ZP, type = zp; + AUTOSTRT: load = RAM, type = ro; # defines program entry point +} +FEATURES { + CONDES: segment = RODATA, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = RODATA, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} +</verb></tscreen> +<p> + +A new memory area DISCARD was added. +It gets loaded with the contents of the (now unused) MAINHDR segment. But the +memory area isn't written to the output file. This way the contents of +the MAINHDR segment get discarded. +<p> +The newly added NEXEHDR segment defines the correct chunk header for the +first intended load chunk. It +puts the STARTUP, LOWCODE, INIT, and CODE segments, which are the +segments containing only code, into load chunk #1 (RAMLO memory area). +<p> +The header for the second load chunk comes from the new CHKHDR +segment. It puts the RODATA, DATA, BSS, and ZPSAVE segments into load +chunk #2 (RAM memory area). +<p> +<p> +The contents of the new NEXEHDR and CHKHDR segments come from this +file (split.s): +<tscreen><verb> + .import __CODE_LOAD__, __BSS_LOAD__, __CODE_SIZE__ + .import __DATA_LOAD__, __RODATA_LOAD__, __STARTUP_LOAD__ + + .segment "NEXEHDR" + .word __STARTUP_LOAD__ + .word __CODE_LOAD__ + __CODE_SIZE__ - 1 + + .segment "CHKHDR" + .word __RODATA_LOAD__ + .word __BSS_LOAD__ - 1 +</verb></tscreen> +<p> +Compile with +<tscreen><verb> +cl65 -t atari -C split.cfg -o prog.com prog.c split.s +</verb></tscreen> + +<sect2>Low data and high code example<p> + + +Goal: Put RODATA and DATA into low memory and STARTUP, LOWCODE, INIT, +CODE, BSS, ZPSAVE into high memory (split2.cfg): + +<tscreen><verb> +SYMBOLS { + __STACKSIZE__: value = $800 type = weak; # 2K stack + __RESERVED_MEMORY__: value = $0000, type = weak; +} +FEATURES { + STARTADDRESS: default = $2E00; +} +MEMORY { + ZP: start = $82, size = $7E, type = rw, define = yes; + + HEADER: start = $0000, size = $2, file = %O; # first load chunk + + FSTHDR: start = $0000, size = $4, file = %O; # second load chunk + RAMLO: start = %S, size = $4000 - %S, file = %O; + + DISCARD: start = $4000, size = $4000, file = ""; + + SECHDR: start = $0000, size = $4, file = %O; # second load chunk + RAM: start = $8000, size = $3C20, file = %O; # $3C20: matches upper bound $BC1F +} +SEGMENTS { + EXEHDR: load = HEADER, type = ro; # discarded old EXE header + + MAINHDR: load = DISCARD, type = ro; + + NEXEHDR: load = FSTHDR, type = ro; # first load chunk + RODATA: load = RAMLO, type = ro, define = yes; + DATA: load = RAMLO, type = rw, define = yes; + + CHKHDR: load = SECHDR, type = ro; # second load chunk + STARTUP: load = RAM, type = ro, define = yes; + INIT: load = RAM, type = ro, optional = yes; + CODE: load = RAM, type = ro, define = yes; + BSS: load = RAM, type = bss, define = yes; + + ZEROPAGE: load = ZP, type = zp; + AUTOSTRT: load = RAM, type = ro; # defines program entry point +} +FEATURES { + CONDES: segment = RODATA, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = RODATA, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} +</verb></tscreen> + +New contents for NEXEHDR and CHKHDR are needed (split2.s): +<tscreen><verb> + .import __STARTUP_LOAD__, __BSS_LOAD__, __DATA_SIZE__ + .import __DATA_LOAD__, __RODATA_LOAD__ + + .segment "NEXEHDR" + .word __RODATA_LOAD__ + .word __DATA_LOAD__ + __DATA_SIZE__ - 1 + + .segment "CHKHDR" + .word __STARTUP_LOAD__ + .word __BSS_LOAD__ - 1 +</verb></tscreen> + +Compile with +<tscreen><verb> +cl65 -t atari -C split2.cfg -o prog.com prog.c split2.s +</verb></tscreen> + +<sect2>Final note<label id="memhole_final_note"><p> + +There are two other memory areas which don't appear directly in the +linker config file. They are the stack and the heap. + +The cc65 runtime lib places the stack location at the end of available +memory. This is dynamically set from the MEMTOP system variable at +startup. The heap is located in the area between the end of the BSS +segment and the top of the stack as defined by __STACKSIZE__. + +If BSS and/or the stack shouldn't stay at the end of the program, +some parts of the cc65 runtime lib need to be replaced/modified. + +common/_heap.s defines the location of the heap and atari/crt0.s +defines the location of the stack by initializing sp. + + +<sect1>Upgrading from an older cc65 version<p> + +If you are using a customized linker config file you might get some errors +regarding the MAINHDR segment. Like this: + +<tscreen><verb> +ld65: Error: Missing memory area assignment for segment `MAINHDR' +</verb></tscreen> + +The old "HEADER" memory description contained six bytes: $FFFF +and the first and last memory addess of the program. For the "system +check" load chunk this had to be split into two memory assigments. The +"HEADER" now only contains the $FFFF. The main program's first +and last memory address were moved to a new segment, called "MAINHDR", +which in the new linker config file goes into its own memory area (also +called "MAINHDR").&nl;&nl; +A simple way to adapt your old linker config file is to add the +following line to the "SEGMENTS" section: + +<tscreen><verb> +MAINHDR: load = HEADER, type = ro; +</verb></tscreen> + + + +<sect1>Getting rid of the "system check" load chunk<label id="nosyschk"><p> + +If, for some reason, you don't want to include the "system check" load +chunk, you can do so by defining the symbol <tt/__SYSTEM_CHECK__/ when linking the +program. The "system check" chunk doesn't include vital parts of the +program. So if you don't want the system checks, it is save to leave them out. +This is probably mostly interesting for debugging. + +When using cl65, you can leave it out with this command line: + +<tscreen><verb> +cl65 -Wl -D__SYSTEM_CHECK__=1 <arguments> +</verb></tscreen> + +The value you assign to <tt/__SYSTEM_CHECK_/ doesn't matter. If the +<tt/__SYSTEM_CHECK__/ symbol is defined, the load chunk won't be included. + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/atari5200.sgml b/doc/atari5200.sgml new file mode 100644 index 000000000..a19641fe7 --- /dev/null +++ b/doc/atari5200.sgml @@ -0,0 +1,199 @@ +<!doctype linuxdoc system> + +<article> + +<title>Atari 5200 specific information for cc65 +<author> +<url url="mailto:chris@groessler.org" name="Christian Groessler"><newline> +<date>2014-05-27 + +<abstract> +An overview over the Atari 5200 runtime system as it is implemented for the +cc65 C compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the Atari 5200 runtime system as it comes +with the cc65 C compiler. It describes the memory layout, Atari 5200 specific header +files, available drivers, and any pitfalls specific to that platform. + +Please note that Atari 5200 specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the Atari 5200 target +is a cartridge image. It is of course +possible to change this behaviour by using a modified startup file and linker +config. + +<sect>Memory layout<p> + +cc65 generated programs with the default setup use the RAM space from $021C to +$3FFF. If you want to reserve memory for the display list and screen buffer +you should define the __RESERVED_MEMORY__ linker variable. The number +of bytes specified by __RESERVED_MEMORY__ are lowering the top of +memory, therefore the available +RAM memory for the program is $021C to $3FFF-__RESERVED_MEMORY__. +The default linker config file sets __RESERVED_MEMORY__ to $1E0 +to reserve space for an optional CONIO text screen. + +Special locations: + +<descrip> + <tag/Text screen/ + The text screen is only enabled if any of the CONIO output functions + is used in the program. Its size is 20x24 characters (Antic mode 6, + BASIC mode 1). The text screen is located at $3E00. The + address of the screen memory is available at runtime in the variable + SAVMSC ($001B).<p> + If the program doesn't use any CONIO output functions it needs to setup its own + display list. + + <tag/Stack/ + The C runtime stack is located at $3FFF-__RESERVED_MEMORY__ and growing downwards. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + + + +<sect>Platform specific header files<p> + +Programs containing Atari 5200 specific code may use the <tt/atari5200.h/ header file. + + +<sect1>Atari 5200 specific functions<p> + +<itemize> +<item>TBD. +</itemize> + + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/atari5200.h/ header +file do allow access to hardware located in the address space. Some +variables are structures, accessing the struct fields will access the +chip registers. + +<descrip> + + <tag><tt/GTIA_READ/ and <tt/GTIA_WRITE/</tag> + The <tt/GTIA_READ/ structure allows read access to the GTIA. The + <tt/GTIA_WRITE/ structure allows write access to the GTIA. + See the <tt/_gtia.h/ header file located in the include directory + for the declaration of the structure. + + <tag><tt/POKEY_READ/ and <tt/POKEY_WRITE/</tag> + The <tt/POKEY_READ/ structure allows read access to the POKEY. The + <tt/POKEY_WRITE/ structure allows write access to the POKEY. + See the <tt/_pokey.h/ header file located in the include directory + for the declaration of the structure. + + <tag><tt/ANTIC/</tag> + The <tt/ANTIC/ structure allows read access to the ANTIC. + See the <tt/_antic.h/ header file located in the include directory + for the declaration of the structure. + +</descrip><p> + + +<sect>Loadable drivers<p> + +All drivers must be statically linked because no disk I/O is available. +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +No graphics drivers are currently available for the Atari 5200. + + +<sect1>Extended memory drivers<p> + +No extended memory drivers are available for the Atari 5200. + + +<sect1>Joystick drivers<p> + +<descrip> + + <tag><tt/atr5200std.joy (atr5200std_joy)/</tag> + A joystick driver for the standard Atari 5200 joystick is + available. Depending on the version of the 5200 console, two or four joysticks can be attached. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +No mouse drivers are available for the Atari 5200. + + +<sect1>RS232 device drivers<p> + +No serial drivers are available for the Atari 5200. + + + +<sect>Limitations<p> + +<sect1>Disk I/O<p> + +Disk I/O is not supported by the <tt/atari5200/ target. This means that +you cannot use any of the following functions (and a few others): + +<itemize> +<item>fclose +<item>fopen +<item>fread +<item>fprintf +<item>fputc +<item>fscanf +<item>fwrite +<item>... +</itemize> + + + +<sect>Other hints<p> + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/atmos.sgml b/doc/atmos.sgml new file mode 100644 index 000000000..805fc7a03 --- /dev/null +++ b/doc/atmos.sgml @@ -0,0 +1,259 @@ +<!doctype linuxdoc system> + +<article> + +<title>Oric Atmos-specific information for cc65 +<author> +<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> +<url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal">,<newline> +<url url="mailto:greg.king5@verizon.net" name="Greg King"> +<date>2014-03-27 + +<abstract> +An overview over the Atmos runtime system as it is implemented for the cc65 C +compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the Atmos runtime system as it comes with the +cc65 C compiler. It describes the memory layout, Atmos-specific header files, +available drivers, and any pitfalls specific to that platform. + +Please note that Atmos-specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the Atmos target +is a machine language program with a 17 byte tape header including a cc65 tag. +The standard load and autostart address is $500. + + +<sect>Memory layout<p> + +In the standard setup, cc65 generated programs use the memory from +$500 to $9800, so nearly 37K of memory (including the stack) is +available. ROM calls are possible without further precautions. + +Special locations: + +<descrip> + <tag/Stack/ + The C runtime stack is located at $97FF and growing downwards. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + + + +<sect>Platform-specific header files<p> + +Programs containing Atmos-specific code may use the <tt/atmos.h/ header file. + + +<sect1>Atmos-specific functions<p> + +The functions listed below are special for the Atmos. See the <url +url="funcref.html" name="function reference"> for declaration and usage. + +<itemize> +<item>atmos_load +<item>atmos_save +<item>atmos_explode +<item>atmos_ping +<item>atmos_shoot +<item>atmos_tick +<item>atmos_tock +<item>atmos_zap +</itemize> + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/atmos.h/ header file do allow +access to hardware located in the address space. Some variables are +structures; accessing the struct fields will access the chip registers. + +<descrip> + + <tag><tt/VIA/</tag> + Access to the VIA (versatile interface adapter) chip is available via the + <tt/VIA/ variable. The structure behind this variable is explained in <tt/_6522.h/. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +<em>Note:</em> Since the Atmos doesn't have working disk I/O +(see <ref id="limitations" name="section "Limitations"">), the +available drivers cannot be loaded at runtime (so the term "loadable drivers" +is somewhat misleading). Instead, the drivers have to be statically linked. While +this may seem overhead, it has two advantages: + +<enum> +<item>The interface is identical to the one used for other platforms + and to the one for the Atmos once it has disk I/O. +<item>Once disk I/O is available, existing code can be changed to load drivers + at runtime with almost no effort. +</enum> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +The default drivers, <tt/tgi_stddrv (tgi_static_stddrv)/, point to <tt/atmos-240-200-2.tgi (atmos_240_200_2_tgi)/. + +<descrip> + + <tag><tt/atmos-228-200-3.tgi (atmos_228_200_3_tgi)/</tag> + This driver was written by Greg King and Stefan Haubenthal. + It features a resolution of 228×200 with a palette of two colors that + can be chosen from the Atmos's eight colors. The driver supports a third + palette-"color" that actually "flips" the pixel (it becomes the other color) + that is on the screen under the graphics cursor. + + <tag><tt/atmos-240-200-2.tgi (atmos_240_200_2_tgi)/</tag> + This driver was written by Stefan Haubenthal and Greg King. + It features a resolution of 240×200 with black and white colors. + It is the default graphics driver for the Atmos. + +</descrip><p> + + +<sect1>Extended memory drivers<p> + +No extended memory drivers are currently available for the Atmos. + + +<sect1>Joystick drivers<p> + +<descrip> + + <tag><tt/atmos-pase.joy (atmos_pase_joy)/</tag> + Supports two standard joysticks connected to the P.A.S.E. interface of the Atmos. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +No mouse drivers are currently available for the Atmos. + + +<sect1>RS232 device drivers<p> + +<descrip> + + <tag><tt/atmos-acia.ser (atmos_acia_ser)/</tag> + Driver for the Telestrat integrated serial controller and the Atmos with a + serial add-on. + Note that, because of the peculiarities of the 6551 chip, together with the + use of the NMI, transmits are not interrupt driven; and, the transceiver + blocks if the receiver asserts flow control because of a full buffer. + +</descrip><p> + + + +<sect>Limitations<label id="limitations"><p> + +<sect1>Disk I/O<p> + +The existing library for the Atmos doesn't implement C file +I/O. There are hacks for the <tt/read()/ and <tt/write()/ routines in +place, which will make functions work that read from and write to <tt/stdout/ +(like <tt/printf()/). However, those functions have some shortcomings which +won't be fixed, because they're going to be replaced anyway. + +To be more concrete, the limitation means that you cannot use any of the +following functions (and a few others): + +<itemize> +<item>fclose +<item>fopen +<item>fread +<item>fprintf +<item>fputc +<item>fscanf +<item>fwrite +<item>... +</itemize> + + + +<sect>Other hints<p> + + +<sect1>Function keys<p> + +These are defined to be FUNCT + number key. + + +<sect1>Passing arguments to the program<p> + +Command-line arguments can be passed to <tt/main()/. Since that is not +supported directly by BASIC, the following syntax was chosen: + +<tscreen><verb> + CALL#500:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 +</verb></tscreen> + +<enum> +<item>Arguments are separated by spaces. +<item>Arguments may be quoted. +<item>Leading and trailing spaces around an argument are ignored. Spaces within + a quoted argument are allowed. +<item>The first argument passed to <tt/main()/ is the program name. +<item>A maximum number of 10 arguments (including the program name) are + supported. +</enum> + + +<sect1>Interrupts<p> + +The runtime for the Atmos uses routines marked as <tt/.INTERRUPTOR/ for +interrupt handlers. Such routines must be written as simple machine language +subroutines and will be called automatically by the interrupt handler code +when they are linked into a program. See the discussion of the <tt/.CONDES/ +feature in the <url url="ca65.html" name="assembler manual">. + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/c128.sgml b/doc/c128.sgml new file mode 100644 index 000000000..4154c0a8d --- /dev/null +++ b/doc/c128.sgml @@ -0,0 +1,359 @@ +<!doctype linuxdoc system> + +<article> + +<title>Commodore 128-specific information for cc65 +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2014-04-12 + +<abstract> +An overview over the C128 runtime system as it is implemented for the cc65 C +compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the C128 runtime system as it comes with the +cc65 C compiler. It describes the memory layout, C128-specific header files, +available drivers, and any pitfalls specific to that platform. + +Please note that C128-specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the C128 target +is a machine language program with a one line BASIC stub, which calls the +machine language part via SYS. This means that a program can be loaded as +BASIC program and started with RUN. It is of course possible to change this +behaviour by using a modified startup file and linker config. + + +<sect>Memory layout<p> + +cc65 generated programs with the default setup run with the I/O area and the +kernal ROM enabled. Note that this is a non standard memory layout, and that +there is no "memory configuration index" for this layout. This means that +special care has to be taken when changing the configuration, or calling any +code that does this. The memory configuration register at $FF00 should +be saved and restored instead of relying on the memory configuration index +stored in the zero page. + +The setup gives a usable memory range of $1C00 - $BFFF. Having +just the kernal ROM mapped in means, that kernal entry points may be called +directly, but using the BASIC ROM is not possible without additional code. + +Special locations: + +<descrip> + <tag/Text screen/ + The text screen is located at $400 (as in the standard setup). + + <tag/Stack/ + The C runtime stack is located at $BFFF, and growing downwards. + + <tag/Heap/ + The C heap is located at the end of the program, and grows towards the C + runtime stack. + +</descrip><p> + + + +<sect>Platform-specific header files<p> + +Programs containing C128-specific code may use the <tt/c128.h/ or <tt/cbm.h/ +header files. Using the later may be an option when writing code for more than +one CBM platform, since it includes <tt/c128.h/ and declares several functions +common to all CBM platforms. + + +<sect1>C128-specific functions<p> + +The functions listed below are special for the C128. See the <url +url="funcref.html" name="function reference"> for declaration and usage. + +<itemize> +<item>videomode +<item>c64mode +<item>fast +<item>slow +</itemize> + + +<sect1>CBM-specific functions<p> + +Some functions are available for all (or at least most) of the Commodore +machines. See the <url url="funcref.html" name="function reference"> for +declaration and usage. + +<itemize> +<item>cbm_close +<item>cbm_closedir +<item>cbm_k_setlfs +<item>cbm_k_setnam +<item>cbm_k_load +<item>cbm_k_save +<item>cbm_k_open +<item>cbm_k_close +<item>cbm_k_readst +<item>cbm_k_chkin +<item>cbm_k_ckout +<item>cbm_k_basin +<item>cbm_k_bsout +<item>cbm_k_clrch +<item>cbm_load +<item>cbm_open +<item>cbm_opendir +<item>cbm_read +<item>cbm_readdir +<item>cbm_save +<item>cbm_write +<item>get_tv +</itemize> + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/c128.h/ header file do +allow access to hardware located in the address space. Some variables are +structures, accessing the struct fields will access the chip registers. + +<descrip> + + <tag><tt/VIC/</tag> + The <tt/VIC/ structure allows access to the VIC II (the graphics + controller). See the <tt/_vic2.h/ header file located in the include + directory for the declaration of the structure. + + <tag><tt/SID/</tag> + The <tt/SID/ structure allows access to the SID (the sound interface + device). See the <tt/_sid.h/ header file located in the include directory + for the declaration of the structure. + + <tag><tt/VDC/</tag> + The <tt/VDC/ structure allows access to the VDC (the video display + controller). See the <tt/_vdc.h/ header file located in the include + directory for the declaration of the structure. + + <tag><tt/CIA1, CIA2/</tag> + Access to the two CIA (complex interface adapter) chips is available via + the <tt/CIA1/ and <tt/CIA2/ variables. The structure behind these variables + is explained in <tt/_6526.h/. + + <tag><tt/COLOR_RAM/</tag> + A character array that mirrors the color RAM of the C128 at $D800. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +The default drivers, <tt/tgi_stddrv (tgi_static_stddrv)/, point to <tt/c128-vdc.tgi (c128_vdc_tgi)/. + +Note: The graphics drivers for the VDC are incompatible with the extended +memory drivers using the VDC memory! + +<descrip> + <tag><tt/c128-vdc.tgi (c128_vdc_tgi)/</tag> + This driver was written by Maciej Witkowiak. It uses the 80-column display, + and features a resolution of 640*200 with two colors and an adjustable + palette (that means that the two colors can be chosen out of the 16 VDC + colors). + + <tag><tt/c128-vdc2.tgi (c128_vdc2_tgi)/</tag> + This driver was written by Maciej Witkowiak. This driver uses the 80-column + display, and features a resolution of 640*480 with two colors and an + adjustable palette (that means that the two colors can be chosen out of the + 16 VDC colors). The driver requires 64KB VDC RAM. +</descrip><p> + +Note: The colors are translated from definitions in headers to correct VDC values; +so, please use definitions or VIC color numbers only. Colors <tt/GRAY3/ and <tt/BROWN/ are +missing on VDC, and are translated to the two colors missing from the VIC palette. + +<sect1>Extended memory drivers<p> + +<descrip> + + <tag><tt/c128-georam.emd (c128_georam_emd)/</tag> + A driver for the GeoRam cartridge. The driver will always assume 2048 pages + of 256 bytes each. There are no checks, so if your program knows better, + just go ahead. + + <tag><tt/c128-ram.emd (c128_ram_emd)/</tag> + An extended memory driver for the RAM in page 1. The common memory area is + excluded, so this driver supports 251 pages of 256 bytes each. + + <tag><tt/c128-ram2.emd (c128_ram2_emd)/</tag> + An extended memory driver for the RAM in pages 1-3. The common memory area + is excluded, so this driver supports up to 731 pages of 256 bytes each. The + driver can be used as a full replacement for <tt/c128-ram.emd/, because RAM + in pages 2+3 is autodetected, but it's larger and there are not many + machines with RAM in banks 2+3, so it has been made a separate driver. The + additional code was contributed by Marco van den Heuvel. + + <tag><tt/c128-ramcart.emd (c128_ramcart_emd)/</tag> + A driver for the RamCart 64/128 written and contributed by Maciej Witkowiak. + Will test the hardware for the available RAM. + + <tag><tt/c128-reu.emd (c128_reu_emd)/</tag> + A driver for the CBM REUs. The driver will determine from the connected REU + if it supports 128KB of RAM or more. In the latter case, 256KB are assumed, + but since there are no range checks, the application can use more memory if + it has better knowledge about the hardware than the driver. + + <tag><tt/c128-vdc.emd (c128_vdc_emd)/</tag> + A driver for the VDC memory of the C128, written and contributed by Maciej + Witkowiak. Autodetects the amount of memory available (16 or 64K), and offers + 64 or 256 pages of 256 bytes each. Note: This driver is incompatible with + any of the graphics drivers using the VDC! + +</descrip><p> + + +<sect1>Joystick drivers<p> + +The default drivers, <tt/joy_stddrv (joy_static_stddrv)/, point to <tt/c128-stdjoy.joy (c128_stdjoy_joy)/. + +<descrip> + + <tag><tt/c128-ptvjoy.joy (c128_ptvjoy_joy)/</tag> + Driver for the Protovision 4-player adapter originally written by Groepaz + for the C64, and converted for the C128 by Uz. See <url + url="http://www.protovision-online.de/hardw/hardwstart.htm"> for prices and + building instructions. Up to four joysticks are supported. + + <tag><tt/c128-stdjoy.joy (c128_stdjoy_joy)/</tag> + Supports up to two joysticks connected to the standard joysticks ports of + the C128. + +</descrip><p> + + + +<sect1>Mouse drivers<p> + +The default drivers, <tt/mouse_stddrv (mouse_static_stddrv)/, point to <tt/c128-1351.mou (c128_1351_mou)/. + +<descrip> + + <tag><tt/c128-1351.mou (c128_1351_mou)/</tag> + Supports a standard mouse connected to port #0 of the C128. + + <tag><tt/c128-inkwell.mou (c128_inkwell_mou)/</tag> + Supports the Inkwell Systems lightpens, connected to port #0 of the + C128. It can read both the one-button 170-C and the two-button 184-C pens. + (It can read other lightpens and light-guns that send their button signal to + the joystick left-button pin or the paddle Y [up/down] pin.) It works on + only the 40-column screen. + + <tag><tt/c128-joy.mou (c128_joy_mou)/</tag> + Supports a mouse emulated by a standard joystick, e.g. 1350 mouse, in port + #1 of the C128. + + <tag><tt/c128-pot.mou (c128_pot_mou)/</tag> + Supports a potentiometer device, e.g. Koala Pad, connected to port #1 of + the C128. + +</descrip><p> + + +<sect1>RS232 device drivers<p> + +<descrip> + + <tag><tt/c128-swlink.ser (c128_swlink_ser)/</tag> + Driver for the SwiftLink cartridge. Supports up to 38400 BPS, hardware flow + control (RTS/CTS), and interrupt-driven receives. Note that, because of the + peculiarities of the 6551 chip, together with the use of the NMI, transmits + are not interrupt driven; and, the transceiver blocks if the receiver asserts + flow control because of a full buffer. + + The driver uses the RS232 variables and buffers of the kernal (buffers at + $C00 and $D00). + +</descrip><p> + + + +<sect>Limitations<p> + + + +<sect>Other hints<p> + + +<sect1>Passing arguments to the program<p> + +Command-line arguments can be passed to <tt/main()/. Since this is not +supported directly by BASIC, the following syntax was chosen: + +<tscreen><verb> + RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 +</verb></tscreen> + +<enum> +<item>Arguments are separated by spaces. +<item>Arguments may be quoted. +<item>Leading and trailing spaces around an argument are ignored. Spaces within + a quoted argument are allowed. +<item>The first argument passed to <tt/main()/ is the program name. +<item>A maximum number of 10 arguments (including the program name) are + supported. +</enum> + + +<sect1>Program return code<p> + +The program return code (low byte) is passed back to BASIC by use of the +<tt/ST/ variable. + + +<sect1>Interrupts<p> + +The runtime for the C128 uses routines marked as <tt/.INTERRUPTOR/ for +interrupt handlers. Such routines must be written as simple machine language +subroutines and will be called automatically by the interrupt handler code +when they are linked into a program. See the discussion of the <tt/.CONDES/ +feature in the <url url="ca65.html" name="assembler manual">. + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/c16.sgml b/doc/c16.sgml new file mode 100644 index 000000000..1614516b7 --- /dev/null +++ b/doc/c16.sgml @@ -0,0 +1,264 @@ +<!doctype linuxdoc system> + +<article> + +<title>Commodore 16/116 specific information for cc65 +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2014-04-10 + +<abstract> +An overview over the C16 runtime system as it is implemented for the cc65 C +compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the C16 runtime system as it comes with the +cc65 C compiler. It describes the memory layout, C16/116 specific header +files, available drivers, and any pitfalls specific to that platform. + +Please note that C16 specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + +Since the C16/C116 and the Commodore Plus/4 are almost identical (the former +don't have the 6551 ACIA and only 16KB of memory), the <url +url="plus4.html" name="Plus/4 documentation"> is also worth a look. The +difference between both cc65 targets is that the Plus/4 runtime uses banking +to support full 64K RAM, while the C16 does not use banking and supports up to +32K RAM. Because banking is not needed, most C16 programs will be somewhat +smaller than the same program compiled for the Plus/4. However, programs C16 +will always run on the Plus/4, while the reverse is not necessarily true. + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the C16/116 +target is a machine language program with a one line BASIC stub which, calls +the machine language part via SYS. This means that a program can be loaded as +BASIC program and started with RUN. It is of course possible to change this +behaviour by using a modified startup file and linker config. + + +<sect>Memory layout<p> + +cc65 generated programs with the default setup run with the kernal and basic +banked in. This gives a usable memory range of $1000 - $4000 +(or $8000 if the machine is equipped with 32K RAM or more). Having the +kernal and basic ROMs banked in means, that ROM entry points may be called +directly from user code. + +Special locations: + +<descrip> + <tag/Text screen/ + The text screen is located at $C00 (as in the standard setup). + + <tag/Color RAM/ + The color RAM is located at $800 (standard location). + + <tag/Stack/ + The C runtime stack is located at $3FFF ($7FFF in case of a + machine with 32K of memory or more) and growing downwards. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + + + +<sect>Platform specific header files<p> + +Programs containing C16 specific code may use the <tt/c16.h/ or <tt/cbm.h/ +header files. Using the later may be an option when writing code for more than +one CBM platform, since it includes <tt/c16.h/ and declares several functions +common to all CBM platforms. + +Please note that most of the header file declarations from the <tt/c16.h/ +header file are shared between the C16 and Plus/4 configurations. For this +reason, most of it is located in a common header file named <tt/cbm264.h/. + + + +<sect1>C16/C116 specific functions<p> + +There are currently no special C16/C116 functions. + + +<sect1>CBM specific functions<p> + +Some functions are available for all (or at least most) of the Commodore +machines. See the <url url="funcref.html" name="function reference"> for +declaration and usage. + +<itemize> +<item>cbm_close +<item>cbm_closedir +<item>cbm_k_setlfs +<item>cbm_k_setnam +<item>cbm_k_load +<item>cbm_k_save +<item>cbm_k_open +<item>cbm_k_close +<item>cbm_k_readst +<item>cbm_k_chkin +<item>cbm_k_ckout +<item>cbm_k_basin +<item>cbm_k_bsout +<item>cbm_k_clrch +<item>cbm_load +<item>cbm_open +<item>cbm_opendir +<item>cbm_read +<item>cbm_readdir +<item>cbm_save +<item>cbm_write +<item>get_tv +</itemize> + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/c16.h/ header file do +allow access to hardware located in the address space. Some variables are +structures, accessing the struct fields will access the chip registers. + +<descrip> + + <tag><tt/TED/</tag> + The <tt/TED/ structure allows access to the TED chip. See the + <tt/_ted.h/ header file located in the include directory for the + declaration of the structure. + + <tag><tt/COLOR_RAM/</tag> + A character array that mirrors the color RAM of the C16 at $0800. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +No graphics drivers are currently available for the C16/C116. + + +<sect1>Extended memory drivers<p> + +<descrip> + + <tag><tt/c16-ram.emd (c16_ram_emd)/</tag> + A driver for the hidden RAM below the BASIC and KERNAL ROMs. Supports 125 + pages with 256 bytes each if the machine is equipped with 64K of memory + (a Plus/4 or a memory extended C16/116). + +</descrip><p> + + + +<sect1>Joystick drivers<p> + +<descrip> + + <tag><tt/c16-stdjoy.joy (c16_stdjoy_joy)/</tag> + Supports up to two joysticks connected to the standard joysticks port of + the Commodore 16/116. + +</descrip><p> + + + +<sect1>Mouse drivers<p> + +No mouse drivers are currently available for the C16/C116. + + +<sect1>RS232 device drivers<p> + +The Commodore 16 does not have a builtin ACIA and no RS232 extensions are +known. For this reason, there are no RS232 drivers available. Please note that +the standard Plus/4 driver will <em>not</em> run together with the C16 +library, because the latter does not support interrupts needed by the driver. + + +<sect>Limitations<p> + + + +<sect>Other hints<p> + +<sect1>Passing arguments to the program<p> + +Command line arguments can be passed to <tt/main()/. Since this is not +supported by BASIC, the following syntax was chosen: + +<tscreen><verb> + RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 +</verb></tscreen> + +<enum> +<item>Arguments are separated by spaces. +<item>Arguments may be quoted. +<item>Leading and trailing spaces around an argument are ignored. Spaces within + a quoted argument are allowed. +<item>The first argument passed to <tt/main/ is the program name. +<item>A maximum number of 10 arguments (including the program name) are + supported. +</enum> + + +<sect1>Program return code<p> + +The program return code (low byte) is passed back to BASIC by use of the +<tt/ST/ variable. + + +<sect1>Interrupts<p> + +The runtime for the C16 uses routines marked as <tt/.INTERRUPTOR/ for +interrupt handlers. Such routines must be written as simple machine language +subroutines and will be called automatically by the interrupt handler code +when they are linked into a program. See the discussion of the <tt/.CONDES/ +feature in the <url url="ca65.html" name="assembler manual">. + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> + + + + diff --git a/doc/c64.sgml b/doc/c64.sgml new file mode 100644 index 000000000..ca99e0061 --- /dev/null +++ b/doc/c64.sgml @@ -0,0 +1,406 @@ +<!doctype linuxdoc system> + +<article> + +<title>Commodore 64-specific information for cc65 +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2014-04-14 + +<abstract> +An overview over the C64 runtime system as it is implemented for the cc65 C +compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the C64 runtime system as it comes with the +cc65 C compiler. It describes the memory layout, C64-specific header files, +available drivers, and any pitfalls specific to that platform. + +Please note that C64-specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the C64 target +is a machine language program with a one line BASIC stub, which calls the +machine language part via SYS. This means that a program can be loaded as +BASIC program and started with RUN. It is of course possible to change this +behaviour by using a modified startup file and linker config. + + +<sect>Memory layout<p> + +cc65 generated programs with the default setup run with the I/O area and the +kernal ROM enabled (memory under the kernal may be used for graphics or as +extended memory - see the sections about graphics and extended memory +drivers). The BASIC ROM is disabled, which gives a usable memory range of +$0800 - $CFFF. This means that kernal entry points may be called +directly, but using the BASIC ROM is not possible without additional code. + +Special locations: + +<descrip> + <tag/Text screen/ + The text screen is located at $400 (as in the standard setup). + + <tag/Stack/ + The C runtime stack is located at $CFFF and growing downwards. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + + +<sect>Linker configurations<p> + +The ld65 linker comes with a default config file for the Commodore 64, +which is used via <tt/-t c64/. The +c64 package comes with additional secondary linker config files, which are +used via <tt/-t c64 -C <configfile>/. + + +<sect1>default config file (<tt/c64.cfg/)<p> + +The default configuration is tailored to C programs. It supplies the load +address and a small BASIC stub that starts the compiled program using a SYS +command. + + +<sect1><tt/c64-asm.cfg/<p> + +This configuration is made for assembler programmers who don't need a special +setup. The default start address is $801. It can be changed with the +linker command line option <tt/--start-addr/. All standard segments with the +exception of <tt/zeropage/ are written to the output file and a two byte load +address is prepended. + +To use this config file, assemble with <tt/-t c64/ and link with <tt/-C +c64-asm.cfg/. The former will make sure that correct character translation is +in effect, while the latter supplies the actual config. When using <tt/cl65/, +use both command line options. + +Sample command line for <tt/cl65/: + +<tscreen><verb> +cl65 -o file.prg -t c64 -C c64-asm.cfg source.s +</verb></tscreen> + +To generate code that loads to $C000: + +<tscreen><verb> +cl65 -o file.prg --start-addr $C000 -t c64 -C c64-asm.cfg source.s +</verb></tscreen> + +It is also possible to add a small BASIC header to the program, that uses SYS +to jump to the program entry point (which is the start of the code segment). +The advantage is that the program can be started using RUN. + +To generate a program with a BASIC SYS header, use + +<tscreen><verb> +cl65 -o file.prg -u __EXEHDR__ -t c64 -C c64-asm.cfg source.s +</verb></tscreen> + +Please note that in this case a changed start address doesn't make sense, +since the program must be loaded to the BASIC start address. + + +<sect>Platform-specific header files<p> + +Programs containing C64-specific code may use the <tt/c64.h/ or <tt/cbm.h/ +header files. Using the later may be an option when writing code for more than +one CBM platform, since it includes <tt/c64.h/ and declares several functions +common to all CBM platforms. + + +<sect1>C64-specific functions<p> + +The functions listed below are special for the C64. See the <url +url="funcref.html" name="function reference"> for declaration and usage. + +<itemize> +<item>get_ostype +</itemize> + + +<sect1>CBM-specific functions<p> + +Some functions are available for all (or at least most) of the Commodore +machines. See the <url url="funcref.html" name="function reference"> for +declaration and usage. + +<itemize> +<item>cbm_close +<item>cbm_closedir +<item>cbm_k_setlfs +<item>cbm_k_setnam +<item>cbm_k_load +<item>cbm_k_save +<item>cbm_k_open +<item>cbm_k_close +<item>cbm_k_readst +<item>cbm_k_chkin +<item>cbm_k_ckout +<item>cbm_k_basin +<item>cbm_k_bsout +<item>cbm_k_clrch +<item>cbm_load +<item>cbm_open +<item>cbm_opendir +<item>cbm_read +<item>cbm_readdir +<item>cbm_save +<item>cbm_write +<item>get_tv +</itemize> + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/c64.h/ header file do allow +access to hardware located in the address space. Some variables are +structures, accessing the struct fields will access the chip registers. + +<descrip> + + <tag><tt/VIC/</tag> + The <tt/VIC/ structure allows access to the VIC II (the graphics + controller). See the <tt/_vic2.h/ header file located in the include + directory for the declaration of the structure. + + <tag><tt/SID/</tag> + The <tt/SID/ structure allows access to the SID (the sound interface + device). See the <tt/_sid.h/ header file located in the include directory + for the declaration of the structure. + + <tag><tt/CIA1, CIA2/</tag> + Access to the two CIA (complex interface adapter) chips is available via + the <tt/CIA1/ and <tt/CIA2/ variables. The structure behind these variables + is explained in <tt/_6526.h/. + + <tag><tt/COLOR_RAM/</tag> + A character array that mirrors the color RAM of the C64 at $D800. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +<em>Note:</em> All available graphics drivers for the TGI interface will use +the space below the I/O area and kernal ROM, so you can have hires graphics in +the standard setup without any memory loss or need for a changed +configuration. + +<descrip> + <tag><tt/c64-hi.tgi (c64_hi_tgi)/</tag> + This driver features a resolution of 320*200 with two colors and an + adjustable palette (that means that the two colors can be chosen out of a + palette of the 16 C64 colors). +</descrip><p> + + +<sect1>Extended memory drivers<p> + +<descrip> + + <tag><tt/c64-c256k.emd (c64_c256k_emd)/</tag> + A driver for the C64 256K memory expansion. This driver offers 768 pages of + 256 bytes each. Written and contributed by Marco van den Heuvel. + + <tag><tt/c64-dqbb.emd (c64_dqbb_emd)/</tag> + A driver for the Double Quick Brown Box cartridge. This driver offers + 64 pages of 256 bytes each. Written and contributed by Marco van den Heuvel. + + <tag><tt/c64-georam.emd (c64_georam_emd)/</tag> + A driver for the Berkeley Softworks GeoRam cartridge. The driver will + determine the available RAM from the connected cartridge. It supports 64KB + up to 2048KB of RAM. + + <tag><tt/c64-isepic.emd (c64_isepic_emd)/</tag> + A driver for the ISEPIC cartridge. This driver offers just 8 pages of 256 + bytes each. Written and contributed by Marco van den Heuvel. + + <tag><tt/c64-ram.emd (c64_ram_emd)/</tag> + A driver for the hidden RAM below the I/O area and kernal ROM. Supports 48 + 256 byte pages. Please note that this driver is incompatible with any of the + graphics drivers! + + <tag><tt/c64-ramcart.emd (c64_ramcart_emd)/</tag> + A driver for the RamCart 64/128 written and contributed by Maciej Witkowiak. + Will test the hardware for the available RAM. + + <tag><tt/c64-reu.emd (c64_reu_emd)/</tag> + A driver for the CBM REUs. The driver will determine from the connected REU + if it supports 128KB of RAM or more. In the latter case, 256KB are assumed, + but since there are no range checks, the application can use more memory if + it has better knowledge about the hardware than the driver. + + <tag><tt/c64-vdc.emd (c64_vdc_emd)/</tag> + A driver for the VDC memory of the C128. Written and contributed by Maciej + Witkowiak. Can be used if the program is running in C64 mode of the C128. + Autodetects the amount of memory available (16 or 64K) and offers 64 or 256 + pages of 256 bytes each. + + <tag><tt/dtv-himem.emd (dtv_himem_emd)/</tag> + A driver for the C64 D2TV (the second or PAL version). This driver offers + indeed 7680 pages of 256 bytes each. + +</descrip><p> + + +<sect1>Joystick drivers<p> + +The default drivers, <tt/joy_stddrv (joy_static_stddrv)/, point to <tt/c64-stdjoy.joy (c64_stdjoy_joy)/. + +<descrip> + + <tag><tt/c64-hitjoy.joy (c64_hitjoy_joy)/</tag> + Driver for the Digital Excess & Hitmen adapter contributed by Groepaz. + See <url url="http://www.digitalexcess.de/downloads/productions.php"> on + instructions how to build one. Up to four joysticks are supported. + + <tag><tt/c64-ptvjoy.joy (c64_ptvjoy_joy)/</tag> + Driver for the Protovision 4-player adapter contributed by Groepaz. See + <url url="http://www.protovision-online.de/hardw/hardwstart.htm"> for prices and + building instructions. Up to four joysticks are supported. + + <tag><tt/c64-stdjoy.joy (c64_stdjoy_joy)/</tag> + Supports up to two standard joysticks connected to the joysticks port of + the C64. + + <tag><tt/c64-numpad.joy (c64_numpad_joy)/</tag> + Supports one joystick emulated by the numberpad of the C128 in C64 mode, + the firebutton is labeled &dquot;5&dquot; and ENTER. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +The default drivers, <tt/mouse_stddrv (mouse_static_stddrv)/, point to <tt/c64-1351.mou (c64_1351_mou)/. + +<descrip> + + <tag><tt/c64-1351.mou (c64_1351_mou)/</tag> + Supports a standard mouse connected to port #0 of the C64. + + <tag><tt/c64-inkwell.mou (c64_inkwell_mou)/</tag> + Supports the Inkwell Systems lightpens, connected to port #0 of the C64. + It can read both the one-button 170-C and the two-button 184-C pens. (It can + read other lightpens and light-guns that send their button signal to the + joystick left-button pin or the paddle Y [up/down] pin.) + + <tag><tt/c64-joy.mou (c64_joy_mou)/</tag> + Supports a mouse emulated by a standard joystick, e.g. 1350 mouse, in port + #1 of the C64. + + <tag><tt/c64-pot.mou (c64_pot_mou)/</tag> + Supports a potentiometer device, e.g. Koala Pad, connected to port #1 of + the C64. + +</descrip><p> + + +<sect1>RS232 device drivers<p> + +<descrip> + + <tag><tt/c64-swlink.ser (c64_swlink_ser)/</tag> + Driver for the SwiftLink cartridge. Supports up to 38400 BPS, hardware flow + control (RTS/CTS), and interrupt-driven receives. Note that, because of the + peculiarities of the 6551 chip, together with the use of the NMI, transmits + are not interrupt driven; and, the transceiver blocks if the receiver asserts + flow control because of a full buffer. + +</descrip><p> + + + +<sect>Limitations<p> + + + +<sect>Other hints<p> + + +<sect1>Escape code<p> + +For an Esc, press CTRL and the <tt/[/ key. + + +<sect1>Passing arguments to the program<p> + +Command-line arguments can be passed to <tt/main()/. Since this is not +supported directly by BASIC, the following syntax was chosen: + +<tscreen><verb> + RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 +</verb></tscreen> + +<enum> +<item>Arguments are separated by spaces. +<item>Arguments may be quoted. +<item>Leading and trailing spaces around an argument are ignored. Spaces within + a quoted argument are allowed. +<item>The first argument passed to <tt/main()/ is the program name. +<item>A maximum number of 10 arguments (including the program name) are + supported. +</enum> + + +<sect1>Program return code<p> + +The program return code (low byte) is passed back to BASIC by use of the +<tt/ST/ variable. + + +<sect1>Interrupts<p> + +The runtime for the C64 uses routines marked as <tt/.INTERRUPTOR/ for +interrupt handlers. Such routines must be written as simple machine language +subroutines and will be called automatically by the interrupt handler code +when they are linked into a program. See the discussion of the <tt/.CONDES/ +feature in the <url url="ca65.html" name="assembler manual">. + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/ca65.sgml b/doc/ca65.sgml new file mode 100644 index 000000000..32cf0b80b --- /dev/null +++ b/doc/ca65.sgml @@ -0,0 +1,4753 @@ +<!doctype linuxdoc system> <!-- -*- text-mode -*- --> + +<article> +<title>ca65 Users Guide +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2014-04-24 + +<abstract> +ca65 is a powerful macro assembler for the 6502, 65C02 and 65816 CPUs. It is +used as a companion assembler for the cc65 crosscompiler, but it may also be +used as a standalone product. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +ca65 is a replacement for the ra65 assembler that was part of the cc65 C +compiler, originally developed by John R. Dunning. I had some problems with +ra65 and the copyright does not permit some things which I wanted to be +possible, so I decided to write a completely new assembler/linker/archiver +suite for the cc65 compiler. ca65 is part of this suite. + +Some parts of the assembler (code generation and some routines for symbol +table handling) are taken from an older crossassembler named a816 written +by me a long time ago. + + +<sect1>Design criteria<p> + +Here's a list of the design criteria, that I considered important for the +development: + +<itemize> + +<item> The assembler must support macros. Macros are not essential, but they + make some things easier, especially when you use the assembler in the + backend of a compiler. +<item> The assembler must support the newer 65C02 and 65816 CPUs. I have been + thinking about a 65816 backend for the C compiler, and even my old + a816 assembler had support for these CPUs, so this wasn't really a + problem. +<item> The assembler must produce relocatable code. This is necessary for the + compiler support, and it is more convenient. +<item> Conditional assembly must be supported. This is a must for bigger + projects written in assembler (like Elite128). +<item> The assembler must support segments, and it must support more than + three segments (this is the count, most other assemblers support). + Having more than one code segments helps developing code for systems + with a divided ROM area (like the C64). +<item> The linker must be able to resolve arbitrary expressions. It should + be able to get things like +<tscreen><verb> + .import S1, S2 + .export Special + Special = 2*S1 + S2/7 +</verb></tscreen> + right. +<item> True lexical nesting for symbols. This is very convenient for larger + assembly projects. +<item> "Cheap" local symbols without lexical nesting for those quick, late + night hacks. +<item> I liked the idea of "options" as Anre Fachats .o65 format has it, so I + introduced the concept into the object file format use by the new cc65 + binutils. +<item> The assembler will be a one pass assembler. There was no real need for + this decision, but I've written several multipass assemblers, and it + started to get boring. A one pass assembler needs much more elaborated + data structures, and because of that it's much more fun:-) +<item> Non-GPLed code that may be used in any project without restrictions or + fear of "GPL infecting" other code. +</itemize> +<p> + + +<sect>Usage<p> + + +<sect1>Command line option overview<p> + +The assembler accepts the following options: + +<tscreen><verb> +--------------------------------------------------------------------------- +Usage: ca65 [options] file +Short options: + -D name[=value] Define a symbol + -I dir Set an include directory search path + -U Mark unresolved symbols as import + -V Print the assembler version + -W n Set warning level n + -d Debug mode + -g Add debug info to object file + -h Help (this text) + -i Ignore case of symbols + -l name Create a listing file if assembly was ok + -mm model Set the memory model + -o name Name the output file + -s Enable smart mode + -t sys Set the target system + -v Increase verbosity + +Long options: + --auto-import Mark unresolved symbols as import + --bin-include-dir dir Set a search path for binary includes + --cpu type Set cpu type + --create-dep name Create a make dependency file + --create-full-dep name Create a full make dependency file + --debug Debug mode + --debug-info Add debug info to object file + --feature name Set an emulation feature + --help Help (this text) + --ignore-case Ignore case of symbols + --include-dir dir Set an include directory search path + --large-alignment Don't warn about large alignments + --listing name Create a listing file if assembly was ok + --list-bytes n Maximum number of bytes per listing line + --memory-model model Set the memory model + --pagelength n Set the page length for the listing + --relax-checks Relax some checks (see docs) + --smart Enable smart mode + --target sys Set the target system + --verbose Increase verbosity + --version Print the assembler version +--------------------------------------------------------------------------- +</verb></tscreen> + + +<sect1>Command line options in detail<p> + +Here is a description of all the command line options: + +<descrip> + + <label id="option--bin-include-dir"> + <tag><tt>--bin-include-dir dir</tt></tag> + + Name a directory which is searched for binary include files. The option + may be used more than once to specify more than one directory to search. The + current directory is always searched first before considering any + additional directories. See also the section about <ref id="search-paths" + name="search paths">. + + + <label id="option--cpu"> + <tag><tt>--cpu type</tt></tag> + + Set the default for the CPU type. The option takes a parameter, which + may be one of + + 6502, 65SC02, 65C02, 65816, sweet16, HuC6280 + + + <label id="option-create-dep"> + <tag><tt>--create-dep name</tt></tag> + + Tells the assembler to generate a file containing the dependency list for + the assembled module in makefile syntax. The output is written to a file + with the given name. The output does not include files passed via debug + information to the assembler. + + + <label id="option-create-full-dep"> + <tag><tt>--create-full-dep name</tt></tag> + + Tells the assembler to generate a file containing the dependency list for + the assembled module in makefile syntax. The output is written to a file + with the given name. The output does include files passed via debug + information to the assembler. + + + <tag><tt>-d, --debug</tt></tag> + + Enables debug mode, something that should not be needed for mere + mortals:-) + + + <label id="option--feature"> + <tag><tt>--feature name</tt></tag> + + Enable an emulation feature. This is identical as using <tt/.FEATURE/ + in the source with two exceptions: Feature names must be lower case, and + each feature must be specified by using an extra <tt/--feature/ option, + comma separated lists are not allowed. + + See the discussion of the <tt><ref id=".FEATURE" name=".FEATURE"></tt> + command for a list of emulation features. + + + <label id="option-g"> + <tag><tt>-g, --debug-info</tt></tag> + + When this option (or the equivalent control command <tt/.DEBUGINFO/) is + used, the assembler will add a section to the object file that contains + all symbols (including local ones) together with the symbol values and + source file positions. The linker will put these additional symbols into + the VICE label file, so even local symbols can be seen in the VICE + monitor. + + + <label id="option-h"> + <tag><tt>-h, --help</tt></tag> + + Print the short option summary shown above. + + + <label id="option-i"> + <tag><tt>-i, --ignore-case</tt></tag> + + This option makes the assembler case insensitive on identifiers and labels. + This option will override the default, but may itself be overridden by the + <tt><ref id=".CASE" name=".CASE"></tt> control command. + + + <label id="option-l"> + <tag><tt>-l name, --listing name</tt></tag> + + Generate an assembler listing with the given name. A listing file will + never be generated in case of assembly errors. + + + <label id="option--large-alignment"> + <tag><tt>--large-alignment</tt></tag> + + Disable warnings about a large combined alignment. See the discussion of the + <tt><ref id=".ALIGN" name=".ALIGN"></tt> directive for futher information. + + + <label id="option--list-bytes"> + <tag><tt>--list-bytes n</tt></tag> + + Set the maximum number of bytes printed in the listing for one line of + input. See the <tt><ref id=".LISTBYTES" name=".LISTBYTES"></tt> directive + for more information. The value zero can be used to encode an unlimited + number of printed bytes. + + + <label id="option-mm"> + <tag><tt>-mm model, --memory-model model</tt></tag> + + Define the default memory model. Possible model specifiers are near, far and + huge. + + + <label id="option-o"> + <tag><tt>-o name</tt></tag> + + The default output name is the name of the input file with the extension + replaced by ".o". If you don't like that, you may give another name with + the -o option. The output file will be placed in the same directory as + the source file, or, if -o is given, the full path in this name is used. + + + <label id="option--pagelength"> + <tag><tt>--pagelength n</tt></tag> + + sets the length of a listing page in lines. See the <tt><ref + id=".PAGELENGTH" name=".PAGELENGTH"></tt> directive for more information. + + + <label id="option--relax-checks"> + <tag><tt>--relax-checks</tt></tag> + + Relax some checks done by the assembler. This will allow code that is an + error in most cases and flagged as such by the assembler, but can be valid + in special situations. + + Examples are: +<itemize> +<item>Short branches between two different segments. +<item>Byte sized address loads where the address is not a zeropage address. +</itemize> + + + <label id="option-s"> + <tag><tt>-s, --smart-mode</tt></tag> + + In smart mode (enabled by -s or the <tt><ref id=".SMART" name=".SMART"></tt> + pseudo instruction) the assembler will track usage of the <tt/REP/ and + <tt/SEP/ instructions in 65816 mode and update the operand sizes + accordingly. If the operand of such an instruction cannot be evaluated by + the assembler (for example, because the operand is an imported symbol), a + warning is issued. + + Beware: Since the assembler cannot trace the execution flow this may + lead to false results in some cases. If in doubt, use the .ixx and .axx + instructions to tell the assembler about the current settings. Smart + mode is off by default. + + + <label id="option-t"> + <tag><tt>-t sys, --target sys</tt></tag> + + Set the target system. This will enable translation of character strings and + character constants into the character set of the target platform. The + default for the target system is "none", which means that no translation + will take place. The assembler supports the same target systems as the + compiler, see there for a list. + + Depending on the target, the default CPU type is also set. This can be + overriden by using the <tt/<ref id="option--cpu" name="--cpu">/ option. + + + <label id="option-v"> + <tag><tt>-v, --verbose</tt></tag> + + Increase the assembler verbosity. Usually only needed for debugging + purposes. You may use this option more than one time for even more + verbose output. + + + <label id="option-D"> + <tag><tt>-D</tt></tag> + + This option allows you to define symbols on the command line. Without a + value, the symbol is defined with the value zero. When giving a value, + you may use the '$' prefix for hexadecimal symbols. Please note + that for some operating systems, '$' has a special meaning, so + you may have to quote the expression. + + + <label id="option-I"> + <tag><tt>-I dir, --include-dir dir</tt></tag> + + Name a directory which is searched for include files. The option may be + used more than once to specify more than one directory to search. The + current directory is always searched first before considering any + additional directories. See also the section about <ref id="search-paths" + name="search paths">. + + + <label id="option-U"> + <tag><tt>-U, --auto-import</tt></tag> + + Mark symbols that are not defined in the sources as imported symbols. This + should be used with care since it delays error messages about typos and such + until the linker is run. The compiler uses the equivalent of this switch + (<tt><ref id=".AUTOIMPORT" name=".AUTOIMPORT"></tt>) to enable auto imported + symbols for the runtime library. However, the compiler is supposed to + generate code that runs through the assembler without problems, something + which is not always true for assembler programmers. + + + <label id="option-V"> + <tag><tt>-V, --version</tt></tag> + + Print the version number of the assembler. If you send any suggestions + or bugfixes, please include the version number. + + + <label id="option-W"> + <tag><tt>-Wn</tt></tag> + + Set the warning level for the assembler. Using -W2 the assembler will + even warn about such things like unused imported symbols. The default + warning level is 1, and it would probably be silly to set it to + something lower. + +</descrip> +<p> + + + +<sect>Search paths<label id="search-paths"><p> + +Normal include files are searched in the following places: + +<enum> +<item>The current file's directory. +<item>Any directory added with the <tt/<ref id="option-I" name="-I">/ option +on the command line. +<item>The value of the environment variable <tt/CA65_INC/ if it is defined. +<item>A subdirectory named <tt/asminc/ of the directory defined in the + environment variable <tt/CC65_HOME/, if it is defined. +<item>An optionally compiled-in directory. +</enum> + +Binary include files are searched in the following places: + +<enum> +<item>The current file's directory. +<item>Any directory added with the <tt/<ref id="option--bin-include-dir" +name="--bin-include-dir">/ option on the command line. +</enum> + + + +<sect>Input format<p> + +<sect1>Assembler syntax<p> + +The assembler accepts the standard 6502/65816 assembler syntax. One line may +contain a label (which is identified by a colon), and, in addition to the +label, an assembler mnemonic, a macro, or a control command (see section <ref +id="control-commands" name="Control Commands"> for supported control +commands). Alternatively, the line may contain a symbol definition using +the '=' token. Everything after a semicolon is handled as a comment (that is, +it is ignored). + +Here are some examples for valid input lines: + +<tscreen><verb> + Label: ; A label and a comment + lda #$20 ; A 6502 instruction plus comment + L1: ldx #$20 ; Same with label + L2: .byte "Hello world" ; Label plus control command + mymac $20 ; Macro expansion + MySym = 3*L1 ; Symbol definition + MaSym = Label ; Another symbol +</verb></tscreen> + +The assembler accepts + +<itemize> +<item>all valid 6502 mnemonics when in 6502 mode (the default or after the + <tt><ref id=".P02" name=".P02"></tt> command was given). +<item>all valid 6502 mnemonics plus a set of illegal instructions when in + <ref id="6502X-mode" name="6502X mode">. +<item>all valid 65SC02 mnemonics when in 65SC02 mode (after the + <tt><ref id=".PSC02" name=".PSC02"></tt> command was given). +<item>all valid 65C02 mnemonics when in 65C02 mode (after the + <tt><ref id=".PC02" name=".PC02"></tt> command was given). +<item>all valid 65618 mnemonics when in 65816 mode (after the + <tt><ref id=".P816" name=".P816"></tt> command was given). +</itemize> + + +<sect1>65816 mode<p> + +In 65816 mode several aliases are accepted in addition to the official +mnemonics: + +<tscreen><verb> + BGE is an alias for BCS + BLT is an alias for BCC + CPA is an alias for CMP + DEA is an alias for DEC A + INA is an alias for INC A + SWA is an alias for XBA + TAD is an alias for TCD + TAS is an alias for TCS + TDA is an alias for TDC + TSA is an alias for TSC +</verb></tscreen> + + + +<sect1>6502X mode<label id="6502X-mode"><p> + +6502X mode is an extension to the normal 6502 mode. In this mode, several +mnemonics for illegal instructions of the NMOS 6502 CPUs are accepted. Since +these instructions are illegal, there are no official mnemonics for them. The +unofficial ones are taken from <url +url="http://www.oxyron.de/html/opcodes02.html">. Please note that only the +ones marked as "stable" are supported. The following table uses information +from the mentioned web page, for more information, see there. + +<itemize> +<item><tt>ALR: A:=(A and #{imm})/2;</tt> +<item><tt>ANC: A:=A and #{imm};</tt> Generates opcode $0B. +<item><tt>ARR: A:=(A and #{imm})/2;</tt> +<item><tt>AXS: X:=A and X-#{imm};</tt> +<item><tt>DCP: {adr}:={adr}-1; A-{adr};</tt> +<item><tt>ISC: {adr}:={adr}+1; A:=A-{adr};</tt> +<item><tt>LAS: A,X,S:={adr} and S;</tt> +<item><tt>LAX: A,X:={adr};</tt> +<item><tt>RLA: {adr}:={adr}rol; A:=A and {adr};</tt> +<item><tt>RRA: {adr}:={adr}ror; A:=A adc {adr};</tt> +<item><tt>SAX: {adr}:=A and X;</tt> +<item><tt>SLO: {adr}:={adr}*2; A:=A or {adr};</tt> +<item><tt>SRE: {adr}:={adr}/2; A:=A xor {adr};</tt> +</itemize> + + + +<sect1>sweet16 mode<label id="sweet16-mode"><p> + +SWEET 16 is an interpreter for a pseudo 16 bit CPU written by Steve Wozniak +for the Apple ][ machines. It is available in the Apple ][ ROM. ca65 can +generate code for this pseudo CPU when switched into sweet16 mode. The +following is special in sweet16 mode: + +<itemize> + +<item>The '@' character denotes indirect addressing and is no longer available +for cheap local labels. If you need cheap local labels, you will have to +switch to another lead character using the <tt/<ref id=".LOCALCHAR" +name=".LOCALCHAR">/ command. + +<item>Registers are specified using <tt/R0/ .. <tt/R15/. In sweet16 mode, +these identifiers are reserved words. + +</itemize> + +Please note that the assembler does neither supply the interpreter needed for +SWEET 16 code, nor the zero page locations needed for the SWEET 16 registers, +nor does it call the interpreter. All this must be done by your program. Apple +][ programmers do probably know how to use sweet16 mode. + +For more information about SWEET 16, see +<url url="http://www.6502.org/source/interpreters/sweet16.htm">. + + +<sect1>Number format<p> + +For literal values, the assembler accepts the widely used number formats: A +preceding '$' or a trailing 'h' denotes a hex value, a preceding '%' +denotes a binary value, and a bare number is interpreted as a decimal. There +are currently no octal values and no floats. + + +<sect1>Conditional assembly<p> + +Please note that when using the conditional directives (<tt/.IF/ and friends), +the input must consist of valid assembler tokens, even in <tt/.IF/ branches +that are not assembled. The reason for this behaviour is that the assembler +must still be able to detect the ending tokens (like <tt/.ENDIF/), so +conversion of the input stream into tokens still takes place. As a consequence +conditional assembly directives may <bf/not/ be used to prevent normal text +(used as a comment or similar) from being assembled. <p> + + +<sect>Expressions<p> + + +<sect1>Expression evaluation<p> + +All expressions are evaluated with (at least) 32 bit precision. An +expression may contain constant values and any combination of internal and +external symbols. Expressions that cannot be evaluated at assembly time +are stored inside the object file for evaluation by the linker. +Expressions referencing imported symbols must always be evaluated by the +linker. + + +<sect1>Size of an expression result<p> + +Sometimes, the assembler must know about the size of the value that is the +result of an expression. This is usually the case, if a decision has to be +made, to generate a zero page or an absolute memory references. In this +case, the assembler has to make some assumptions about the result of an +expression: + +<itemize> +<item> If the result of an expression is constant, the actual value is + checked to see if it's a byte sized expression or not. +<item> If the expression is explicitly casted to a byte sized expression by + one of the '>', '<' or '^' operators, it is a byte expression. +<item> If this is not the case, and the expression contains a symbol, + explicitly declared as zero page symbol (by one of the .importzp or + .exportzp instructions), then the whole expression is assumed to be + byte sized. +<item> If the expression contains symbols that are not defined, and these + symbols are local symbols, the enclosing scopes are searched for a + symbol with the same name. If one exists and this symbol is defined, + its attributes are used to determine the result size. +<item> In all other cases the expression is assumed to be word sized. +</itemize> + +Note: If the assembler is not able to evaluate the expression at assembly +time, the linker will evaluate it and check for range errors as soon as +the result is known. + + +<sect1>Boolean expressions<p> + +In the context of a boolean expression, any non zero value is evaluated as +true, any other value to false. The result of a boolean expression is 1 if +it's true, and zero if it's false. There are boolean operators with extreme +low precedence with version 2.x (where x > 0). The <tt/.AND/ and <tt/.OR/ +operators are shortcut operators. That is, if the result of the expression is +already known, after evaluating the left hand side, the right hand side is +not evaluated. + + +<sect1>Constant expressions<p> + +Sometimes an expression must evaluate to a constant without looking at any +further input. One such example is the <tt/<ref id=".IF" name=".IF">/ command +that decides if parts of the code are assembled or not. An expression used in +the <tt/.IF/ command cannot reference a symbol defined later, because the +decision about the <tt/.IF/ must be made at the point when it is read. If the +expression used in such a context contains only constant numerical values, +there is no problem. When unresolvable symbols are involved it may get harder +for the assembler to determine if the expression is actually constant, and it +is even possible to create expressions that aren't recognized as constant. +Simplifying the expressions will often help. + +In cases where the result of the expression is not needed immediately, the +assembler will delay evaluation until all input is read, at which point all +symbols are known. So using arbitrary complex constant expressions is no +problem in most cases. + + + +<sect1>Available operators<label id="operators"><p> + +<table> +<tabular ca="clc"> +<bf/Operator/| <bf/Description/| <bf/Precedence/@<hline> +| Built-in string functions| 0@ +||~@ +| Built-in pseudo-variables| 1@ +| Built-in pseudo-functions| 1@ ++| Unary positive| 1@ +-| Unary negative| 1@ +˜<newline> +.BITNOT| Unary bitwise not| 1@ +<<newline> +.LOBYTE| Unary low-byte operator| 1@ +><newline> +.HIBYTE| Unary high-byte operator| 1@ +^<newline> +.BANKBYTE| Unary bank-byte operator| 1@ +||~@ +*| Multiplication| 2@ +/| Division| 2@ +.MOD| Modulo operator| 2@ +&<newline> +.BITAND| Bitwise and| 2@ +^<newline> +.BITXOR| Binary bitwise xor| 2@ +<<<newline> +.SHL| Shift-left operator| 2@ +>><newline> +.SHR| Shift-right operator| 2@ +||~@ ++| Binary addition| 3@ +-| Binary subtraction| 3@ +|<newline> +.BITOR| Bitwise or| 3@ +||~@ += | Compare operator (equal)| 4@ +<>| Compare operator (not equal)| 4@ +<| Compare operator (less)| 4@ +>| Compare operator (greater)| 4@ +<=| Compare operator (less or equal)| 4@ +>=| Compare operator (greater or equal)| 4@ +||~@ +&&<newline> +.AND| Boolean and| 5@ +.XOR| Boolean xor| 5@ +||~@ +||<newline> +.OR| Boolean or| 6@ +||~@ +!<newline> +.NOT| Boolean not| 7@<hline> +</tabular> +<caption>Available operators, sorted by precedence +</table> + +To force a specific order of evaluation, parentheses may be used, as usual. + + + +<sect>Symbols and labels<p> + +A symbol or label is an identifier that starts with a letter and is followed +by letters and digits. Depending on some features enabled (see +<tt><ref id="at_in_identifiers" name="at_in_identifiers"></tt>, +<tt><ref id="dollar_in_identifiers" name="dollar_in_identifiers"></tt> and +<tt><ref id="leading_dot_in_identifiers" name="leading_dot_in_identifiers"></tt>) +other characters may be present. Use of identifiers consisting of a single +character will not work in all cases, because some of these identifiers are +reserved keywords (for example "A" is not a valid identifier for a label, +because it is the keyword for the accumulator). + +The assembler allows you to use symbols instead of naked values to make +the source more readable. There are a lot of different ways to define and +use symbols and labels, giving a lot of flexibility. + +<sect1>Numeric constants<p> + +Numeric constants are defined using the equal sign or the label assignment +operator. After doing + +<tscreen><verb> + two = 2 +</verb></tscreen> + +may use the symbol "two" in every place where a number is expected, and it is +evaluated to the value 2 in this context. The label assignment operator is +almost identical, but causes the symbol to be marked as a label, so it may be +handled differently in a debugger: + +<tscreen><verb> + io := $d000 +</verb></tscreen> + +The right side can of course be an expression: + +<tscreen><verb> + four = two * two +</verb></tscreen> + + +<label id="variables"> +<sect1>Numeric variables<p> + +Within macros and other control structures (<tt><ref id=".REPEAT" +name=".REPEAT"></tt>, ...) it is sometimes useful to have some sort of +variable. This can be achieved by the <tt>.SET</tt> operator. It creates a +symbol that may get assigned a different value later: + +<tscreen><verb> + four .set 4 + lda #four ; Loads 4 into A + four .set 3 + lda #four ; Loads 3 into A +</verb></tscreen> + +Since the value of the symbol can change later, it must be possible to +evaluate it when used (no delayed evaluation as with normal symbols). So the +expression used as the value must be constant. + +Following is an example for a macro that generates a different label each time +it is used. It uses the <tt><ref id=".SPRINTF" name=".SPRINTF"></tt> function +and a numeric variable named <tt>lcount</tt>. + +<tscreen><verb> + .lcount .set 0 ; Initialize the counter + + .macro genlab + .ident (.sprintf ("L%04X", lcount)): + lcount .set lcount + 1 + .endmacro +</verb></tscreen> + + +<sect1>Standard labels<p> + +A label is defined by writing the name of the label at the start of the line +(before any instruction mnemonic, macro or pseudo directive), followed by a +colon. This will declare a symbol with the given name and the value of the +current program counter. + + +<sect1>Local labels and symbols<p> + +Using the <tt><ref id=".PROC" name=".PROC"></tt> directive, it is possible to +create regions of code where the names of labels and symbols are local to this +region. They are not known outside of this region and cannot be accessed from +there. Such regions may be nested like PROCEDUREs in Pascal. + +See the description of the <tt><ref id=".PROC" name=".PROC"></tt> +directive for more information. + + +<sect1>Cheap local labels<p> + +Cheap local labels are defined like standard labels, but the name of the +label must begin with a special symbol (usually '@', but this can be +changed by the <tt><ref id=".LOCALCHAR" name=".LOCALCHAR"></tt> +directive). + +Cheap local labels are visible only between two non cheap labels. As soon as a +standard symbol is encountered (this may also be a local symbol if inside a +region defined with the <tt><ref id=".PROC" name=".PROC"></tt> directive), the +cheap local symbol goes out of scope. + +You may use cheap local labels as an easy way to reuse common label +names like "Loop". Here is an example: + +<tscreen><verb> + Clear: lda #$00 ; Global label + ldy #$20 + @Loop: sta Mem,y ; Local label + dey + bne @Loop ; Ok + rts + Sub: ... ; New global label + bne @Loop ; ERROR: Unknown identifier! +</verb></tscreen> + +<sect1>Unnamed labels<p> + +If you really want to write messy code, there are also unnamed labels. These +labels do not have a name (you guessed that already, didn't you?). A colon is +used to mark the absence of the name. + +Unnamed labels may be accessed by using the colon plus several minus or plus +characters as a label designator. Using the '-' characters will create a back +reference (use the n'th label backwards), using '+' will create a forward +reference (use the n'th label in forward direction). An example will help to +understand this: + +<tscreen><verb> + : lda (ptr1),y ; #1 + cmp (ptr2),y + bne :+ ; -> #2 + tax + beq :+++ ; -> #4 + iny + bne :- ; -> #1 + inc ptr1+1 + inc ptr2+1 + bne :- ; -> #1 + + : bcs :+ ; #2 -> #3 + ldx #$FF + rts + + : ldx #$01 ; #3 + : rts ; #4 +</verb></tscreen> + +As you can see from the example, unnamed labels will make even short +sections of code hard to understand, because you have to count labels +to find branch targets (this is the reason why I for my part do +prefer the "cheap" local labels). Nevertheless, unnamed labels are +convenient in some situations, so it's your decision. + +<em/Note:/ <ref id="scopes" name="Scopes"> organize named symbols, not +unnamed ones, so scopes don't have an effect on unnamed labels. + + + +<sect1>Using macros to define labels and constants<p> + +While there are drawbacks with this approach, it may be handy in a few rare +situations. Using <tt><ref id=".DEFINE" name=".DEFINE"></tt>, it is possible +to define symbols or constants that may be used elsewhere. One of the +advantages is that you can use it to define string constants (this is not +possible with the other symbol types). + +Please note: <tt/.DEFINE/ style macros do token replacements on a low level, +so the names do not adhere to scoping, diagnostics may be misleading, there +are no symbols to look up in the map file, and there is no debug info. +Especially the first problem in the list can lead to very nasty programming +errors. Because of these problems, the general advice is, <bf/NOT/ do use +<tt/.DEFINE/ if you don't have to. + +Example: + +<tscreen><verb> + .DEFINE two 2 + .DEFINE version "SOS V2.3" + + four = two * two ; Ok + .byte version ; Ok + + .PROC ; Start local scope + two = 3 ; Will give "2 = 3" - invalid! + .ENDPROC +</verb></tscreen> + + +<sect1>Symbols and <tt>.DEBUGINFO</tt><p> + +If <tt><ref id=".DEBUGINFO" name=".DEBUGINFO"></tt> is enabled (or <ref +id="option-g" name="-g"> is given on the command line), global, local and +cheap local labels are written to the object file and will be available in the +symbol file via the linker. Unnamed labels are not written to the object file, +because they don't have a name which would allow to access them. + + + +<sect>Scopes<label id="scopes"><p> + +ca65 implements several sorts of scopes for symbols. + +<sect1>Global scope<p> + +All (non cheap local) symbols that are declared outside of any nested scopes +are in global scope. + + +<sect1>Cheap locals<p> + +A special scope is the scope for cheap local symbols. It lasts from one non +local symbol to the next one, without any provisions made by the programmer. +All other scopes differ in usage but use the same concept internally. + + +<sect1>Generic nested scopes<p> + +A nested scoped for generic use is started with <tt/<ref id=".SCOPE" +name=".SCOPE">/ and closed with <tt/<ref id=".ENDSCOPE" name=".ENDSCOPE">/. +The scope can have a name, in which case it is accessible from the outside by +using <ref id="scopesyntax" name="explicit scopes">. If the scope does not +have a name, all symbols created within the scope are local to the scope, and +aren't accessible from the outside. + +A nested scope can access symbols from the local or from enclosing scopes by +name without using explicit scope names. In some cases there may be +ambiguities, for example if there is a reference to a local symbol that is not +yet defined, but a symbol with the same name exists in outer scopes: + +<tscreen><verb> + .scope outer + foo = 2 + .scope inner + lda #foo + foo = 3 + .endscope + .endscope +</verb></tscreen> + +In the example above, the <tt/lda/ instruction will load the value 3 into the +accumulator, because <tt/foo/ is redefined in the scope. However: + +<tscreen><verb> + .scope outer + foo = $1234 + .scope inner + lda foo,x + foo = $12 + .endscope + .endscope +</verb></tscreen> + +Here, <tt/lda/ will still load from <tt/$12,x/, but since it is unknown to the +assembler that <tt/foo/ is a zeropage symbol when translating the instruction, +absolute mode is used instead. In fact, the assembler will not use absolute +mode by default, but it will search through the enclosing scopes for a symbol +with the given name. If one is found, the address size of this symbol is used. +This may lead to errors: + +<tscreen><verb> + .scope outer + foo = $12 + .scope inner + lda foo,x + foo = $1234 + .endscope + .endscope +</verb></tscreen> + +In this case, when the assembler sees the symbol <tt/foo/ in the <tt/lda/ +instruction, it will search for an already defined symbol <tt/foo/. It will +find <tt/foo/ in scope <tt/outer/, and a close look reveals that it is a +zeropage symbol. So the assembler will use zeropage addressing mode. If +<tt/foo/ is redefined later in scope <tt/inner/, the assembler tries to change +the address in the <tt/lda/ instruction already translated, but since the new +value needs absolute addressing mode, this fails, and an error message "Range +error" is output. + +Of course the most simple solution for the problem is to move the definition +of <tt/foo/ in scope <tt/inner/ upwards, so it precedes its use. There may be +rare cases when this cannot be done. In these cases, you can use one of the +address size override operators: + +<tscreen><verb> + .scope outer + foo = $12 + .scope inner + lda a:foo,x + foo = $1234 + .endscope + .endscope +</verb></tscreen> + +This will cause the <tt/lda/ instruction to be translated using absolute +addressing mode, which means changing the symbol reference later does not +cause any errors. + + +<sect1>Nested procedures<p> + +A nested procedure is created by use of <tt/<ref id=".PROC" name=".PROC">/. It +differs from a <tt/<ref id=".SCOPE" name=".SCOPE">/ in that it must have a +name, and a it will introduce a symbol with this name in the enclosing scope. +So + +<tscreen><verb> + .proc foo + ... + .endproc +</verb></tscreen> + +is actually the same as + +<tscreen><verb> + foo: + .scope foo + ... + .endscope +</verb></tscreen> + +This is the reason why a procedure must have a name. If you want a scope +without a name, use <tt/<ref id=".SCOPE" name=".SCOPE">/. + +<em/Note:/ As you can see from the example above, scopes and symbols live in +different namespaces. There can be a symbol named <tt/foo/ and a scope named +<tt/foo/ without any conflicts (but see the section titled <ref +id="scopesearch" name=""Scope search order"">). + + +<sect1>Structs, unions and enums<p> + +Structs, unions and enums are explained in a <ref id="structs" name="separate +section">, I do only cover them here, because if they are declared with a +name, they open a nested scope, similar to <tt/<ref id=".SCOPE" +name=".SCOPE">/. However, when no name is specified, the behaviour is +different: In this case, no new scope will be opened, symbols declared within +a struct, union, or enum declaration will then be added to the enclosing scope +instead. + + +<sect1>Explicit scope specification<label id="scopesyntax"><p> + +Accessing symbols from other scopes is possible by using an explicit scope +specification, provided that the scope where the symbol lives in has a name. +The namespace token (<tt/::/) is used to access other scopes: + +<tscreen><verb> + .scope foo + bar: .word 0 + .endscope + + ... + lda foo::bar ; Access foo in scope bar +</verb></tscreen> + +The only way to deny access to a scope from the outside is to declare a scope +without a name (using the <tt/<ref id=".SCOPE" name=".SCOPE">/ command). + +A special syntax is used to specify the global scope: If a symbol or scope is +preceded by the namespace token, the global scope is searched: + +<tscreen><verb> + bar = 3 + + .scope foo + bar = 2 + lda #::bar ; Access the global bar (which is 3) + .endscope +</verb></tscreen> + + +<sect1>Scope search order<label id="scopesearch"><p> + +The assembler searches for a scope in a similar way as for a symbol. First, it +looks in the current scope, and then it walks up the enclosing scopes until +the scope is found. + +However, one important thing to note when using explicit scope syntax is, that +a symbol may be accessed before it is defined, but a scope may <bf/not/ be +used without a preceding definition. This means that in the following +example: + +<tscreen><verb> + .scope foo + bar = 3 + .endscope + + .scope outer + lda #foo::bar ; Will load 3, not 2! + .scope foo + bar = 2 + .endscope + .endscope +</verb></tscreen> + +the reference to the scope <tt/foo/ will use the global scope, and not the +local one, because the local one is not visible at the point where it is +referenced. + +Things get more complex if a complete chain of scopes is specified: + +<tscreen><verb> + .scope foo + .scope outer + .scope inner + bar = 1 + .endscope + .endscope + .scope another + .scope nested + lda #outer::inner::bar ; 1 + .endscope + .endscope + .endscope + + .scope outer + .scope inner + bar = 2 + .endscope + .endscope +</verb></tscreen> + +When <tt/outer::inner::bar/ is referenced in the <tt/lda/ instruction, the +assembler will first search in the local scope for a scope named <tt/outer/. +Since none is found, the enclosing scope (<tt/another/) is checked. There is +still no scope named <tt/outer/, so scope <tt/foo/ is checked, and finally +scope <tt/outer/ is found. Within this scope, <tt/inner/ is searched, and in +this scope, the assembler looks for a symbol named <tt/bar/. + +Please note that once the anchor scope is found, all following scopes +(<tt/inner/ in this case) are expected to be found exactly in this scope. The +assembler will search the scope tree only for the first scope (if it is not +anchored in the root scope). Starting from there on, there is no flexibility, +so if the scope named <tt/outer/ found by the assembler does not contain a +scope named <tt/inner/, this would be an error, even if such a pair does exist +(one level up in global scope). + +Ambiguities that may be introduced by this search algorithm may be removed by +anchoring the scope specification in the global scope. In the example above, +if you want to access the "other" symbol <tt/bar/, you would have to write: + +<tscreen><verb> + .scope foo + .scope outer + .scope inner + bar = 1 + .endscope + .endscope + .scope another + .scope nested + lda #::outer::inner::bar ; 2 + .endscope + .endscope + .endscope + + .scope outer + .scope inner + bar = 2 + .endscope + .endscope +</verb></tscreen> + + +<sect>Address sizes and memory models<label id="address-sizes"><p> + +<sect1>Address sizes<p> + +ca65 assigns each segment and each symbol an address size. This is true, even +if the symbol is not used as an address. You may also think of a value range +of the symbol instead of an address size. + +Possible address sizes are: + +<itemize> +<item>Zeropage or direct (8 bits) +<item>Absolute (16 bits) +<item>Far (24 bits) +<item>Long (32 bits) +</itemize> + +Since the assembler uses default address sizes for the segments and symbols, +it is usually not necessary to override the default behaviour. In cases, where +it is necessary, the following keywords may be used to specify address sizes: + +<itemize> +<item>DIRECT, ZEROPAGE or ZP for zeropage addressing (8 bits). +<item>ABSOLUTE, ABS or NEAR for absolute addressing (16 bits). +<item>FAR for far addressing (24 bits). +<item>LONG or DWORD for long addressing (32 bits). +</itemize> + + +<sect1>Address sizes of segments<p> + +The assembler assigns an address size to each segment. Since the +representation of a label within this segment is "segment start + offset", +labels will inherit the address size of the segment they are declared in. + +The address size of a segment may be changed, by using an optional address +size modifier. See the <tt/<ref id=".SEGMENT" name="segment directive">/ for +an explanation on how this is done. + + +<sect1>Address sizes of symbols<p> + + + + +<sect1>Memory models<p> + +The default address size of a segment depends on the memory model used. Since +labels inherit the address size from the segment they are declared in, +changing the memory model is an easy way to change the address size of many +symbols at once. + + + + +<sect>Pseudo variables<label id="pseudo-variables"><p> + +Pseudo variables are readable in all cases, and in some special cases also +writable. + +<sect1><tt>*</tt><p> + + Reading this pseudo variable will return the program counter at the start + of the current input line. + + Assignment to this variable is possible when <tt/<ref id=".FEATURE" + name=".FEATURE pc_assignment">/ is used. Note: You should not use + assignments to <tt/*/, use <tt/<ref id=".ORG" name=".ORG">/ instead. + + +<sect1><tt>.CPU</tt><label id=".CPU"><p> + + Reading this pseudo variable will give a constant integer value that + tells which CPU is currently enabled. It can also tell which instruction + set the CPU is able to translate. The value read from the pseudo variable + should be further examined by using one of the constants defined by the + "cpu" macro package (see <tt/<ref id=".MACPACK" name=".MACPACK">/). + + It may be used to replace the .IFPxx pseudo instructions or to construct + even more complex expressions. + + Example: + + <tscreen><verb> + .macpack cpu + .if (.cpu .bitand CPU_ISET_65816) + phx + phy + .else + txa + pha + tya + pha + .endif + </verb></tscreen> + + +<sect1><tt>.PARAMCOUNT</tt><label id=".PARAMCOUNT"><p> + + This builtin pseudo variable is only available in macros. It is replaced by + the actual number of parameters that were given in the macro invocation. + + Example: + + <tscreen><verb> + .macro foo arg1, arg2, arg3 + .if .paramcount <> 3 + .error "Too few parameters for macro foo" + .endif + ... + .endmacro + </verb></tscreen> + + See section <ref id="macros" name="Macros">. + + +<sect1><tt>.TIME</tt><label id=".TIME"><p> + + Reading this pseudo variable will give a constant integer value that + represents the current time in POSIX standard (as seconds since the + Epoch). + + It may be used to encode the time of translation somewhere in the created + code. + + Example: + + <tscreen><verb> + .dword .time ; Place time here + </verb></tscreen> + + +<sect1><tt>.VERSION</tt><label id=".VERSION"><p> + + Reading this pseudo variable will give the assembler version according to + the following formula: + + VER_MAJOR*$100 + VER_MINOR*$10 + + It may be used to encode the assembler version or check the assembler for + special features not available with older versions. + + Example: + + Version 2.14 of the assembler will return $2E0 as numerical constant when + reading the pseudo variable <tt/.VERSION/. + + + +<sect>Pseudo functions<label id="pseudo-functions"><p> + +Pseudo functions expect their arguments in parenthesis, and they have a result, +either a string or an expression. + + +<sect1><tt>.BANK</tt><label id=".BANK"><p> + + The <tt/.BANK/ function is used to support systems with banked memory. The + argument is an expression with exactly one segment reference - usually a + label. The function result is the value of the <tt/bank/ attribute assigned + to the run memory area of the segment. Please see the linker documentation + for more information about memory areas and their attributes. + + The value of <tt/.BANK/ can be used to switch memory so that a memory bank + containing specific data is available. + + The <tt/bank/ attribute is a 32 bit integer and so is the result of the + <tt/.BANK/ function. You will have to use <tt><ref id=".LOBYTE" + name=".LOBYTE"></tt> or similar functions to address just part of it. + + Please note that <tt/.BANK/ will always get evaluated in the link stage, so + an expression containing <tt/.BANK/ can never be used where a constant known + result is expected (for example with <tt/.RES/). + + Example: + + <tscreen><verb> + .segment "BANK1" + .proc banked_func_1 + ... + .endproc + + .segment "BANK2" + .proc banked_func_2 + ... + .endproc + + .proc bank_table + .addr banked_func_1 + .byte <.BANK (banked_func_1) + + .addr banked_func_2 + .byte <.BANK (banked_func_2) + .endproc + </verb></tscreen> + + + +<sect1><tt>.BANKBYTE</tt><label id=".BANKBYTE"><p> + + The function returns the bank byte (that is, bits 16-23) of its argument. + It works identical to the '^' operator. + + See: <tt><ref id=".HIBYTE" name=".HIBYTE"></tt>, + <tt><ref id=".LOBYTE" name=".LOBYTE"></tt> + + +<sect1><tt>.BLANK</tt><label id=".BLANK"><p> + + Builtin function. The function evaluates its argument in braces and yields + "false" if the argument is non blank (there is an argument), and "true" if + there is no argument. The token list that makes up the function argument + may optionally be enclosed in curly braces. This allows the inclusion of + tokens that would otherwise terminate the list (the closing right + parenthesis). The curly braces are not considered part of the list, a list + just consisting of curly braces is considered to be empty. + + As an example, the <tt/.IFBLANK/ statement may be replaced by + + <tscreen><verb> + .if .blank({arg}) + </verb></tscreen> + + + +<sect1><tt>.CONCAT</tt><label id=".CONCAT"><p> + + Builtin string function. The function allows to concatenate a list of string + constants separated by commas. The result is a string constant that is the + concatenation of all arguments. This function is most useful in macros and + when used together with the <tt/.STRING/ builtin function. The function may + be used in any case where a string constant is expected. + + Example: + + <tscreen><verb> + .include .concat ("myheader", ".", "inc") + </verb></tscreen> + + This is the same as the command + + <tscreen><verb> + .include "myheader.inc" + </verb></tscreen> + + +<sect1><tt>.CONST</tt><label id=".CONST"><p> + + Builtin function. The function evaluates its argument in braces and + yields "true" if the argument is a constant expression (that is, an + expression that yields a constant value at assembly time) and "false" + otherwise. As an example, the .IFCONST statement may be replaced by + + <tscreen><verb> + .if .const(a + 3) + </verb></tscreen> + + +<sect1><tt>.HIBYTE</tt><label id=".HIBYTE"><p> + + The function returns the high byte (that is, bits 8-15) of its argument. + It works identical to the '>' operator. + + See: <tt><ref id=".LOBYTE" name=".LOBYTE"></tt>, + <tt><ref id=".BANKBYTE" name=".BANKBYTE"></tt> + + +<sect1><tt>.HIWORD</tt><label id=".HIWORD"><p> + + The function returns the high word (that is, bits 16-31) of its argument. + + See: <tt><ref id=".LOWORD" name=".LOWORD"></tt> + + +<sect1><tt>.IDENT</tt><label id=".IDENT"><p> + + The function expects a string as its argument, and converts this argument + into an identifier. If the string starts with the current <tt/<ref + id=".LOCALCHAR" name=".LOCALCHAR">/, it will be converted into a cheap local + identifier, otherwise it will be converted into a normal identifier. + + Example: + + <tscreen><verb> + .macro makelabel arg1, arg2 + .ident (.concat (arg1, arg2)): + .endmacro + + makelabel "foo", "bar" + + .word foobar ; Valid label + </verb></tscreen> + + +<sect1><tt>.LEFT</tt><label id=".LEFT"><p> + + Builtin function. Extracts the left part of a given token list. + + Syntax: + + <tscreen><verb> + .LEFT (<int expr>, <token list>) + </verb></tscreen> + + The first integer expression gives the number of tokens to extract from + the token list. The second argument is the token list itself. The token + list may optionally be enclosed into curly braces. This allows the + inclusion of tokens that would otherwise terminate the list (the closing + right paren in the given case). + + Example: + + To check in a macro if the given argument has a '#' as first token + (immediate addressing mode), use something like this: + + <tscreen><verb> + .macro ldax arg + ... + .if (.match (.left (1, {arg}), #)) + + ; ldax called with immediate operand + ... + + .endif + ... + .endmacro + </verb></tscreen> + + See also the <tt><ref id=".MID" name=".MID"></tt> and <tt><ref id=".RIGHT" + name=".RIGHT"></tt> builtin functions. + + +<sect1><tt>.LOBYTE</tt><label id=".LOBYTE"><p> + + The function returns the low byte (that is, bits 0-7) of its argument. + It works identical to the '<' operator. + + See: <tt><ref id=".HIBYTE" name=".HIBYTE"></tt>, + <tt><ref id=".BANKBYTE" name=".BANKBYTE"></tt> + + +<sect1><tt>.LOWORD</tt><label id=".LOWORD"><p> + + The function returns the low word (that is, bits 0-15) of its argument. + + See: <tt><ref id=".HIWORD" name=".HIWORD"></tt> + + +<sect1><tt>.MATCH</tt><label id=".MATCH"><p> + + Builtin function. Matches two token lists against each other. This is + most useful within macros, since macros are not stored as strings, but + as lists of tokens. + + The syntax is + + <tscreen><verb> + .MATCH(<token list #1>, <token list #2>) + </verb></tscreen> + + Both token list may contain arbitrary tokens with the exception of the + terminator token (comma resp. right parenthesis) and + + <itemize> + <item>end-of-line + <item>end-of-file + </itemize> + + The token lists may optionally be enclosed into curly braces. This allows + the inclusion of tokens that would otherwise terminate the list (the closing + right paren in the given case). Often a macro parameter is used for any of + the token lists. + + Please note that the function does only compare tokens, not token + attributes. So any number is equal to any other number, regardless of the + actual value. The same is true for strings. If you need to compare tokens + <em/and/ token attributes, use the <tt><ref id=".XMATCH" + name=".XMATCH"></tt> function. + + Example: + + Assume the macro <tt/ASR/, that will shift right the accumulator by one, + while honoring the sign bit. The builtin processor instructions will allow + an optional "A" for accu addressing for instructions like <tt/ROL/ and + <tt/ROR/. We will use the <tt><ref id=".MATCH" name=".MATCH"></tt> function + to check for this and print and error for invalid calls. + + <tscreen><verb> + .macro asr arg + + .if (.not .blank(arg)) .and (.not .match ({arg}, a)) + .error "Syntax error" + .endif + + cmp #$80 ; Bit 7 into carry + lsr a ; Shift carry into bit 7 + + .endmacro + </verb></tscreen> + + The macro will only accept no arguments, or one argument that must be the + reserved keyword "A". + + See: <tt><ref id=".XMATCH" name=".XMATCH"></tt> + + +<sect1><tt>.MAX</tt><label id=".MAX"><p> + + Builtin function. The result is the larger of two values. + + The syntax is + + <tscreen><verb> + .MAX (<value #1>, <value #2>) + </verb></tscreen> + + Example: + + <tscreen><verb> + ; Reserve space for the larger of two data blocks + savearea: .max (.sizeof (foo), .sizeof (bar)) + </verb></tscreen> + + See: <tt><ref id=".MIN" name=".MIN"></tt> + + +<sect1><tt>.MID</tt><label id=".MID"><p> + + Builtin function. Takes a starting index, a count and a token list as + arguments. Will return part of the token list. + + Syntax: + + <tscreen><verb> + .MID (<int expr>, <int expr>, <token list>) + </verb></tscreen> + + The first integer expression gives the starting token in the list (the first + token has index 0). The second integer expression gives the number of tokens + to extract from the token list. The third argument is the token list itself. + The token list may optionally be enclosed into curly braces. This allows the + inclusion of tokens that would otherwise terminate the list (the closing + right paren in the given case). + + Example: + + To check in a macro if the given argument has a '<tt/#/' as first token + (immediate addressing mode), use something like this: + + <tscreen><verb> + .macro ldax arg + ... + .if (.match (.mid (0, 1, {arg}), #)) + + ; ldax called with immediate operand + ... + + .endif + ... + .endmacro + </verb></tscreen> + + See also the <tt><ref id=".LEFT" name=".LEFT"></tt> and <tt><ref id=".RIGHT" + name=".RIGHT"></tt> builtin functions. + + +<sect1><tt>.MIN</tt><label id=".MIN"><p> + + Builtin function. The result is the smaller of two values. + + The syntax is + + <tscreen><verb> + .MIN (<value #1>, <value #2>) + </verb></tscreen> + + Example: + + <tscreen><verb> + ; Reserve space for some data, but 256 bytes minimum + savearea: .min (.sizeof (foo), 256) + </verb></tscreen> + + See: <tt><ref id=".MAX" name=".MAX"></tt> + + +<sect1><tt>.REF, .REFERENCED</tt><label id=".REFERENCED"><p> + + Builtin function. The function expects an identifier as argument in braces. + The argument is evaluated, and the function yields "true" if the identifier + is a symbol that has already been referenced somewhere in the source file up + to the current position. Otherwise the function yields false. As an example, + the <tt><ref id=".IFREF" name=".IFREF"></tt> statement may be replaced by + + <tscreen><verb> + .if .referenced(a) + </verb></tscreen> + + See: <tt><ref id=".DEFINED" name=".DEFINED"></tt> + + +<sect1><tt>.RIGHT</tt><label id=".RIGHT"><p> + + Builtin function. Extracts the right part of a given token list. + + Syntax: + + <tscreen><verb> + .RIGHT (<int expr>, <token list>) + </verb></tscreen> + + The first integer expression gives the number of tokens to extract from the + token list. The second argument is the token list itself. The token list + may optionally be enclosed into curly braces. This allows the inclusion of + tokens that would otherwise terminate the list (the closing right paren in + the given case). + + See also the <tt><ref id=".LEFT" name=".LEFT"></tt> and <tt><ref id=".MID" + name=".MID"></tt> builtin functions. + + +<sect1><tt>.SIZEOF</tt><label id=".SIZEOF"><p> + + <tt/.SIZEOF/ is a pseudo function that returns the size of its argument. The + argument can be a struct/union, a struct member, a procedure, or a label. In + case of a procedure or label, its size is defined by the amount of data + placed in the segment where the label is relative to. If a line of code + switches segments (for example in a macro) data placed in other segments + does not count for the size. + + Please note that a symbol or scope must exist, before it is used together with + <tt/.SIZEOF/ (this may get relaxed later, but will always be true for scopes). + A scope has preference over a symbol with the same name, so if the last part + of a name represents both, a scope and a symbol, the scope is chosen over the + symbol. + + After the following code: + + <tscreen><verb> + .struct Point ; Struct size = 4 + xcoord .word + ycoord .word + .endstruct + + P: .tag Point ; Declare a point + @P: .tag Point ; Declare another point + + .code + .proc Code + nop + .proc Inner + nop + .endproc + nop + .endproc + + .proc Data + .data ; Segment switch!!! + .res 4 + .endproc + </verb></tscreen> + + <descrip> + <tag><tt/.sizeof(Point)/</tag> + will have the value 4, because this is the size of struct <tt/Point/. + + <tag><tt/.sizeof(Point::xcoord)/</tag> + will have the value 2, because this is the size of the member <tt/xcoord/ + in struct <tt/Point/. + + <tag><tt/.sizeof(P)/</tag> + will have the value 4, this is the size of the data declared on the same + source line as the label <tt/P/, which is in the same segment that <tt/P/ + is relative to. + + <tag><tt/.sizeof(@P)/</tag> + will have the value 4, see above. The example demonstrates that <tt/.SIZEOF/ + does also work for cheap local symbols. + + <tag><tt/.sizeof(Code)/</tag> + will have the value 3, since this is amount of data emitted into the code + segment, the segment that was active when <tt/Code/ was entered. Note that + this value includes the amount of data emitted in child scopes (in this + case <tt/Code::Inner/). + + <tag><tt/.sizeof(Code::Inner)/</tag> + will have the value 1 as expected. + + <tag><tt/.sizeof(Data)/</tag> + will have the value 0. Data is emitted within the scope <tt/Data/, but since + the segment is switched after entry, this data is emitted into another + segment. + </descrip> + + +<sect1><tt>.STRAT</tt><label id=".STRAT"><p> + + Builtin function. The function accepts a string and an index as + arguments and returns the value of the character at the given position + as an integer value. The index is zero based. + + Example: + + <tscreen><verb> + .macro M Arg + ; Check if the argument string starts with '#' + .if (.strat (Arg, 0) = '#') + ... + .endif + .endmacro + </verb></tscreen> + + +<sect1><tt>.SPRINTF</tt><label id=".SPRINTF"><p> + + Builtin function. It expects a format string as first argument. The number + and type of the following arguments depend on the format string. The format + string is similar to the one of the C <tt/printf/ function. Missing things + are: Length modifiers, variable width. + + The result of the function is a string. + + Example: + + <tscreen><verb> + num = 3 + + ; Generate an identifier: + .ident (.sprintf ("%s%03d", "label", num)): + </verb></tscreen> + + +<sect1><tt>.STRING</tt><label id=".STRING"><p> + + Builtin function. The function accepts an argument in braces and converts + this argument into a string constant. The argument may be an identifier, or + a constant numeric value. + + Since you can use a string in the first place, the use of the function may + not be obvious. However, it is useful in macros, or more complex setups. + + Example: + + <tscreen><verb> + ; Emulate other assemblers: + .macro section name + .segment .string(name) + .endmacro + </verb></tscreen> + + +<sect1><tt>.STRLEN</tt><label id=".STRLEN"><p> + + Builtin function. The function accepts a string argument in braces and + evaluates to the length of the string. + + Example: + + The following macro encodes a string as a pascal style string with + a leading length byte. + + <tscreen><verb> + .macro PString Arg + .byte .strlen(Arg), Arg + .endmacro + </verb></tscreen> + + +<sect1><tt>.TCOUNT</tt><label id=".TCOUNT"><p> + + Builtin function. The function accepts a token list in braces. The function + result is the number of tokens given as argument. The token list may + optionally be enclosed into curly braces which are not considered part of + the list and not counted. Enclosement in curly braces allows the inclusion + of tokens that would otherwise terminate the list (the closing right paren + in the given case). + + Example: + + The <tt/ldax/ macro accepts the '#' token to denote immediate addressing (as + with the normal 6502 instructions). To translate it into two separate 8 bit + load instructions, the '#' token has to get stripped from the argument: + + <tscreen><verb> + .macro ldax arg + .if (.match (.mid (0, 1, {arg}), #)) + ; ldax called with immediate operand + lda #<(.right (.tcount ({arg})-1, {arg})) + ldx #>(.right (.tcount ({arg})-1, {arg})) + .else + ... + .endif + .endmacro + </verb></tscreen> + + +<sect1><tt>.XMATCH</tt><label id=".XMATCH"><p> + + Builtin function. Matches two token lists against each other. This is + most useful within macros, since macros are not stored as strings, but + as lists of tokens. + + The syntax is + + <tscreen><verb> + .XMATCH(<token list #1>, <token list #2>) + </verb></tscreen> + + Both token list may contain arbitrary tokens with the exception of the + terminator token (comma resp. right parenthesis) and + + <itemize> + <item>end-of-line + <item>end-of-file + </itemize> + + The token lists may optionally be enclosed into curly braces. This allows + the inclusion of tokens that would otherwise terminate the list (the closing + right paren in the given case). Often a macro parameter is used for any of + the token lists. + + The function compares tokens <em/and/ token values. If you need a function + that just compares the type of tokens, have a look at the <tt><ref + id=".MATCH" name=".MATCH"></tt> function. + + See: <tt><ref id=".MATCH" name=".MATCH"></tt> + + + +<sect>Control commands<label id="control-commands"><p> + +Here's a list of all control commands and a description, what they do: + + +<sect1><tt>.A16</tt><label id=".A16"><p> + + Valid only in 65816 mode. Switch the accumulator to 16 bit. + + Note: This command will not emit any code, it will tell the assembler to + create 16 bit operands for immediate accumulator addressing mode. + + See also: <tt><ref id=".SMART" name=".SMART"></tt> + + +<sect1><tt>.A8</tt><label id=".A8"><p> + + Valid only in 65816 mode. Switch the accumulator to 8 bit. + + Note: This command will not emit any code, it will tell the assembler to + create 8 bit operands for immediate accu addressing mode. + + See also: <tt><ref id=".SMART" name=".SMART"></tt> + + +<sect1><tt>.ADDR</tt><label id=".ADDR"><p> + + Define word sized data. In 6502 mode, this is an alias for <tt/.WORD/ and + may be used for better readability if the data words are address values. In + 65816 mode, the address is forced to be 16 bit wide to fit into the current + segment. See also <tt><ref id=".FARADDR" name=".FARADDR"></tt>. The command + must be followed by a sequence of (not necessarily constant) expressions. + + Example: + + <tscreen><verb> + .addr $0D00, $AF13, _Clear + </verb></tscreen> + + See: <tt><ref id=".FARADDR" name=".FARADDR"></tt>, <tt><ref id=".WORD" + name=".WORD"></tt> + + +<sect1><tt>.ALIGN</tt><label id=".ALIGN"><p> + + Align data to a given boundary. The command expects a constant integer + argument in the range 1 ... 65536, plus an optional second argument + in byte range. If there is a second argument, it is used as fill value, + otherwise the value defined in the linker configuration file is used + (the default for this value is zero). + + <tt/.ALIGN/ will insert fill bytes, and the number of fill bytes depend of + the final address of the segment. <tt/.ALIGN/ cannot insert a variable + number of bytes, since that would break address calculations within the + module. So each <tt/.ALIGN/ expects the segment to be aligned to a multiple + of the alignment, because that allows the number of fill bytes to be + calculated in advance by the assembler. You are therefore required to + specify a matching alignment for the segment in the linker config. The + linker will output a warning if the alignment of the segment is less than + what is necessary to have a correct alignment in the object file. + + Example: + + <tscreen><verb> + .align 256 + </verb></tscreen> + + Some unexpected behaviour might occur if there are multiple <tt/.ALIGN/ + commands with different arguments. To allow the assembler to calculate the + number of fill bytes in advance, the alignment of the segment must be a + multiple of each of the alignment factors. This may result in unexpectedly + large alignments for the segment within the module. + + Example: + + <tscreen><verb> + .align 15 + .byte 15 + .align 18 + .byte 18 + </verb></tscreen> + + For the assembler to be able to align correctly, the segment must be aligned + to the least common multiple of 15 and 18 which is 90. The assembler will + calculate this automatically and will mark the segment with this value. + + Unfortunately, the combined alignment may get rather large without the user + knowing about it, wasting space in the final executable. If we add another + alignment to the example above + + <tscreen><verb> + .align 15 + .byte 15 + .align 18 + .byte 18 + .align 251 + .byte 0 + </verb></tscreen> + + the assembler will force a segment alignment to the least common multiple of + 15, 18 and 251 - which is 22590. To protect the user against errors, the + assembler will issue a warning when the combined alignment exceeds 256. The + command line option <tt><ref id="option--large-alignment" + name="--large-alignment"></tt> will disable this warning. + + Please note that with alignments that are a power of two (which were the + only alignments possible in older versions of the assembler), the problem is + less severe, because the least common multiple of powers to the same base is + always the larger one. + + + +<sect1><tt>.ASCIIZ</tt><label id=".ASCIIZ"><p> + + Define a string with a trailing zero. + + Example: + + <tscreen><verb> + Msg: .asciiz "Hello world" + </verb></tscreen> + + This will put the string "Hello world" followed by a binary zero into + the current segment. There may be more strings separated by commas, but + the binary zero is only appended once (after the last one). + + +<sect1><tt>.ASSERT</tt><label id=".ASSERT"><p> + + Add an assertion. The command is followed by an expression, an action + specifier, and an optional message that is output in case the assertion + fails. If no message was given, the string "Assertion failed" is used. The + action specifier may be one of <tt/warning/, <tt/error/, <tt/ldwarning/ or + <tt/lderror/. In the former two cases, the assertion is evaluated by the + assembler if possible, and in any case, it's also passed to the linker in + the object file (if one is generated). The linker will then evaluate the + expression when segment placement has been done. + + Example: + + <tscreen><verb> + .assert * = $8000, error, "Code not at $8000" + </verb></tscreen> + + The example assertion will check that the current location is at $8000, + when the output file is written, and abort with an error if this is not + the case. More complex expressions are possible. The action specifier + <tt/warning/ outputs a warning, while the <tt/error/ specifier outputs + an error message. In the latter case, generation of the output file is + suppressed in both the assembler and linker. + + +<sect1><tt>.AUTOIMPORT</tt><label id=".AUTOIMPORT"><p> + + Is followed by a plus or a minus character. When switched on (using a + +), undefined symbols are automatically marked as import instead of + giving errors. When switched off (which is the default so this does not + make much sense), this does not happen and an error message is + displayed. The state of the autoimport flag is evaluated when the + complete source was translated, before outputting actual code, so it is + <em/not/ possible to switch this feature on or off for separate sections + of code. The last setting is used for all symbols. + + You should probably not use this switch because it delays error + messages about undefined symbols until the link stage. The cc65 + compiler (which is supposed to produce correct assembler code in all + circumstances, something which is not true for most assembler + programmers) will insert this command to avoid importing each and every + routine from the runtime library. + + Example: + + <tscreen><verb> + .autoimport + ; Switch on auto import + </verb></tscreen> + +<sect1><tt>.BANKBYTES</tt><label id=".BANKBYTES"><p> + + Define byte sized data by extracting only the bank byte (that is, bits 16-23) from + each expression. This is equivalent to <tt><ref id=".BYTE" name=".BYTE"></tt> with + the operator '^' prepended to each expression in its list. + + Example: + + <tscreen><verb> + .define MyTable TableItem0, TableItem1, TableItem2, TableItem3 + + TableLookupLo: .lobytes MyTable + TableLookupHi: .hibytes MyTable + TableLookupBank: .bankbytes MyTable + </verb></tscreen> + + which is equivalent to + + <tscreen><verb> + TableLookupLo: .byte <TableItem0, <TableItem1, <TableItem2, <TableItem3 + TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3 + TableLookupBank: .byte ^TableItem0, ^TableItem1, ^TableItem2, ^TableItem3 + </verb></tscreen> + + See also: <tt><ref id=".BYTE" name=".BYTE"></tt>, + <tt><ref id=".HIBYTES" name=".HIBYTES"></tt>, + <tt><ref id=".LOBYTES" name=".LOBYTES"></tt> + + +<sect1><tt>.BSS</tt><label id=".BSS"><p> + + Switch to the BSS segment. The name of the BSS segment is always "BSS", + so this is a shortcut for + + <tscreen><verb> + .segment "BSS" + </verb></tscreen> + + See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command. + + +<sect1><tt>.BYT, .BYTE</tt><label id=".BYTE"><p> + + Define byte sized data. Must be followed by a sequence of (byte ranged) + expressions or strings. + + Example: + + <tscreen><verb> + .byte "Hello " + .byt "world", $0D, $00 + </verb></tscreen> + + +<sect1><tt>.CASE</tt><label id=".CASE"><p> + + Switch on or off case sensitivity on identifiers. The default is off + (that is, identifiers are case sensitive), but may be changed by the + -i switch on the command line. + The command must be followed by a '+' or '-' character to switch the + option on or off respectively. + + Example: + + <tscreen><verb> + .case - ; Identifiers are not case sensitive + </verb></tscreen> + + +<sect1><tt>.CHARMAP</tt><label id=".CHARMAP"><p> + + Apply a custom mapping for characters. The command is followed by two + numbers. The first one is the index of the source character (range 1..255), + the second one is the mapping (range 0..255). The mapping applies to all + character and string constants when they generate output, and overrides a + mapping table specified with the <tt><ref id="option-t" name="-t"></tt> + command line switch. + + Example: + + <tscreen><verb> + .charmap $41, $61 ; Map 'A' to 'a' + </verb></tscreen> + + +<sect1><tt>.CODE</tt><label id=".CODE"><p> + + Switch to the CODE segment. The name of the CODE segment is always + "CODE", so this is a shortcut for + + <tscreen><verb> + .segment "CODE" + </verb></tscreen> + + See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command. + + +<sect1><tt>.CONDES</tt><label id=".CONDES"><p> + + Export a symbol and mark it in a special way. The linker is able to build + tables of all such symbols. This may be used to automatically create a list + of functions needed to initialize linked library modules. + + Note: The linker has a feature to build a table of marked routines, but it + is your code that must call these routines, so just declaring a symbol with + <tt/.CONDES/ does nothing by itself. + + All symbols are exported as an absolute (16 bit) symbol. You don't need to + use an additional <tt><ref id=".EXPORT" name=".EXPORT"></tt> statement, this + is implied by <tt/.CONDES/. + + <tt/.CONDES/ is followed by the type, which may be <tt/constructor/, + <tt/destructor/ or a numeric value between 0 and 6 (where 0 is the same as + specifying <tt/constructor/ and 1 is equal to specifying <tt/destructor/). + The <tt><ref id=".CONSTRUCTOR" name=".CONSTRUCTOR"></tt>, <tt><ref + id=".DESTRUCTOR" name=".DESTRUCTOR"></tt> and <tt><ref id=".INTERRUPTOR" + name=".INTERRUPTOR"></tt> commands are actually shortcuts for <tt/.CONDES/ + with a type of <tt/constructor/ resp. <tt/destructor/ or <tt/interruptor/. + + After the type, an optional priority may be specified. Higher numeric values + mean higher priority. If no priority is given, the default priority of 7 is + used. Be careful when assigning priorities to your own module constructors + so they won't interfere with the ones in the cc65 library. + + Example: + + <tscreen><verb> + .condes ModuleInit, constructor + .condes ModInit, 0, 16 + </verb></tscreen> + + See the <tt><ref id=".CONSTRUCTOR" name=".CONSTRUCTOR"></tt>, <tt><ref + id=".DESTRUCTOR" name=".DESTRUCTOR"></tt> and <tt><ref id=".INTERRUPTOR" + name=".INTERRUPTOR"></tt> commands and the separate section <ref id="condes" + name="Module constructors/destructors"> explaining the feature in more + detail. + + +<sect1><tt>.CONSTRUCTOR</tt><label id=".CONSTRUCTOR"><p> + + Export a symbol and mark it as a module constructor. This may be used + together with the linker to build a table of constructor subroutines that + are called by the startup code. + + Note: The linker has a feature to build a table of marked routines, but it + is your code that must call these routines, so just declaring a symbol as + constructor does nothing by itself. + + A constructor is always exported as an absolute (16 bit) symbol. You don't + need to use an additional <tt/.export/ statement, this is implied by + <tt/.constructor/. It may have an optional priority that is separated by a + comma. Higher numeric values mean a higher priority. If no priority is + given, the default priority of 7 is used. Be careful when assigning + priorities to your own module constructors so they won't interfere with the + ones in the cc65 library. + + Example: + + <tscreen><verb> + .constructor ModuleInit + .constructor ModInit, 16 + </verb></tscreen> + + See the <tt><ref id=".CONDES" name=".CONDES"></tt> and <tt><ref + id=".DESTRUCTOR" name=".DESTRUCTOR"></tt> commands and the separate section + <ref id="condes" name="Module constructors/destructors"> explaining the + feature in more detail. + + +<sect1><tt>.DATA</tt><label id=".DATA"><p> + + Switch to the DATA segment. The name of the DATA segment is always + "DATA", so this is a shortcut for + + <tscreen><verb> + .segment "DATA" + </verb></tscreen> + + See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command. + + +<sect1><tt>.DBYT</tt><label id=".DBYT"><p> + + Define word sized data with the hi and lo bytes swapped (use <tt/.WORD/ to + create word sized data in native 65XX format). Must be followed by a + sequence of (word ranged) expressions. + + Example: + + <tscreen><verb> + .dbyt $1234, $4512 + </verb></tscreen> + + This will emit the bytes + + <tscreen><verb> + $12 $34 $45 $12 + </verb></tscreen> + + into the current segment in that order. + + +<sect1><tt>.DEBUGINFO</tt><label id=".DEBUGINFO"><p> + + Switch on or off debug info generation. The default is off (that is, + the object file will not contain debug infos), but may be changed by the + -g switch on the command line. + The command must be followed by a '+' or '-' character to switch the + option on or off respectively. + + Example: + + <tscreen><verb> + .debuginfo + ; Generate debug info + </verb></tscreen> + + +<sect1><tt>.DEFINE</tt><label id=".DEFINE"><p> + + Start a define style macro definition. The command is followed by an + identifier (the macro name) and optionally by a list of formal arguments + in braces. + + Please note that <tt/.DEFINE/ shares most disadvantages with its C + counterpart, so the general advice is, <bf/NOT/ do use <tt/.DEFINE/ if you + don't have to. + + See also the <tt><ref id=".UNDEFINE" name=".UNDEFINE"></tt> command and + section <ref id="macros" name="Macros">. + + +<sect1><tt>.DELMAC, .DELMACRO</tt><label id=".DELMACRO"><p> + + Delete a classic macro (defined with <tt><ref id=".MACRO" + name=".MACRO"></tt>) . The command is followed by the name of an + existing macro. Its definition will be deleted together with the name. + If necessary, another macro with this name may be defined later. + + See: <tt><ref id=".ENDMACRO" name=".ENDMACRO"></tt>, + <tt><ref id=".EXITMACRO" name=".EXITMACRO"></tt>, + <tt><ref id=".MACRO" name=".MACRO"></tt> + + See also section <ref id="macros" name="Macros">. + + +<sect1><tt>.DEF, .DEFINED</tt><label id=".DEFINED"><p> + + Builtin function. The function expects an identifier as argument in braces. + The argument is evaluated, and the function yields "true" if the identifier + is a symbol that is already defined somewhere in the source file up to the + current position. Otherwise the function yields false. As an example, the + <tt><ref id=".IFDEF" name=".IFDEF"></tt> statement may be replaced by + + <tscreen><verb> + .if .defined(a) + </verb></tscreen> + + +<sect1><tt>.DESTRUCTOR</tt><label id=".DESTRUCTOR"><p> + + Export a symbol and mark it as a module destructor. This may be used + together with the linker to build a table of destructor subroutines that + are called by the startup code. + + Note: The linker has a feature to build a table of marked routines, but it + is your code that must call these routines, so just declaring a symbol as + constructor does nothing by itself. + + A destructor is always exported as an absolute (16 bit) symbol. You don't + need to use an additional <tt/.export/ statement, this is implied by + <tt/.destructor/. It may have an optional priority that is separated by a + comma. Higher numerical values mean a higher priority. If no priority is + given, the default priority of 7 is used. Be careful when assigning + priorities to your own module destructors so they won't interfere with the + ones in the cc65 library. + + Example: + + <tscreen><verb> + .destructor ModuleDone + .destructor ModDone, 16 + </verb></tscreen> + + See the <tt><ref id=".CONDES" name=".CONDES"></tt> and <tt><ref + id=".CONSTRUCTOR" name=".CONSTRUCTOR"></tt> commands and the separate + section <ref id="condes" name="Module constructors/destructors"> explaining + the feature in more detail. + + +<sect1><tt>.DWORD</tt><label id=".DWORD"><p> + + Define dword sized data (4 bytes) Must be followed by a sequence of + expressions. + + Example: + + <tscreen><verb> + .dword $12344512, $12FA489 + </verb></tscreen> + + +<sect1><tt>.ELSE</tt><label id=".ELSE"><p> + + Conditional assembly: Reverse the current condition. + + +<sect1><tt>.ELSEIF</tt><label id=".ELSEIF"><p> + + Conditional assembly: Reverse current condition and test a new one. + + +<sect1><tt>.END</tt><label id=".END"><p> + + Forced end of assembly. Assembly stops at this point, even if the command + is read from an include file. + + +<sect1><tt>.ENDENUM</tt><label id=".ENDENUM"><p> + + End a <tt><ref id=".ENUM" name=".ENUM"></tt> declaration. + + +<sect1><tt>.ENDIF</tt><label id=".ENDIF"><p> + + Conditional assembly: Close a <tt><ref id=".IF" name=".IF..."></tt> or + <tt><ref id=".ELSE" name=".ELSE"></tt> branch. + + +<sect1><tt>.ENDMAC, .ENDMACRO</tt><label id=".ENDMACRO"><p> + + Marks the end of a macro definition. + + See: <tt><ref id=".DELMACRO" name=".DELMACRO"></tt>, + <tt><ref id=".EXITMACRO" name=".EXITMACRO"></tt>, + <tt><ref id=".MACRO" name=".MACRO"></tt> + + See also section <ref id="macros" name="Macros">. + + +<sect1><tt>.ENDPROC</tt><label id=".ENDPROC"><p> + + End of local lexical level (see <tt><ref id=".PROC" name=".PROC"></tt>). + + +<sect1><tt>.ENDREP, .ENDREPEAT</tt><label id=".ENDREPEAT"><p> + + End a <tt><ref id=".REPEAT" name=".REPEAT"></tt> block. + + +<sect1><tt>.ENDSCOPE</tt><label id=".ENDSCOPE"><p> + + End of local lexical level (see <tt/<ref id=".SCOPE" name=".SCOPE">/). + + +<sect1><tt>.ENDSTRUCT</tt><label id=".ENDSTRUCT"><p> + + Ends a struct definition. See the <tt/<ref id=".STRUCT" name=".STRUCT">/ + command and the separate section named <ref id="structs" name=""Structs + and unions"">. + + +<sect1><tt>.ENDUNION</tt><label id=".ENDUNION"><p> + + Ends a union definition. See the <tt/<ref id=".UNION" name=".UNION">/ + command and the separate section named <ref id="structs" name=""Structs + and unions"">. + + +<sect1><tt>.ENUM</tt><label id=".ENUM"><p> + + Start an enumeration. This directive is very similar to the C <tt/enum/ + keyword. If a name is given, a new scope is created for the enumeration, + otherwise the enumeration members are placed in the enclosing scope. + + In the enumeration body, symbols are declared. The first symbol has a value + of zero, and each following symbol will get the value of the preceding plus + one. This behaviour may be overridden by an explicit assignment. Two symbols + may have the same value. + + Example: + + <tscreen><verb> + .enum errorcodes + no_error + file_error + parse_error + .endenum + </verb></tscreen> + + Above example will create a new scope named <tt/errorcodes/ with three + symbols in it that get the values 0, 1 and 2 respectively. Another way + to write this would have been: + + <tscreen><verb> + .scope errorcodes + no_error = 0 + file_error = 1 + parse_error = 2 + .endscope + </verb></tscreen> + + Please note that explicit scoping must be used to access the identifiers: + + <tscreen><verb> + .word errorcodes::no_error + </verb></tscreen> + + A more complex example: + + <tscreen><verb> + .enum + EUNKNOWN = -1 + EOK + EFILE + EBUSY + EAGAIN + EWOULDBLOCK = EAGAIN + .endenum + </verb></tscreen> + + In this example, the enumeration does not have a name, which means that the + members will be visible in the enclosing scope and can be used in this scope + without explicit scoping. The first member (<tt/EUNKNOWN/) has the value -1. + The value for the following members is incremented by one, so <tt/EOK/ would + be zero and so on. <tt/EWOULDBLOCK/ is an alias for <tt/EGAIN/, so it has an + override for the value using an already defined symbol. + + +<sect1><tt>.ERROR</tt><label id=".ERROR"><p> + + Force an assembly error. The assembler will output an error message + preceded by "User error". Assembly is continued but no object file will + generated. + + This command may be used to check for initial conditions that must be + set before assembling a source file. + + Example: + + <tscreen><verb> + .if foo = 1 + ... + .elseif bar = 1 + ... + .else + .error "Must define foo or bar!" + .endif + </verb></tscreen> + + See also: <tt><ref id=".FATAL" name=".FATAL"></tt>, + <tt><ref id=".OUT" name=".OUT"></tt>, + <tt><ref id=".WARNING" name=".WARNING"></tt> + + +<sect1><tt>.EXITMAC, .EXITMACRO</tt><label id=".EXITMACRO"><p> + + Abort a macro expansion immediately. This command is often useful in + recursive macros. + + See: <tt><ref id=".DELMACRO" name=".DELMACRO"></tt>, + <tt><ref id=".ENDMACRO" name=".ENDMACRO"></tt>, + <tt><ref id=".MACRO" name=".MACRO"></tt> + + See also section <ref id="macros" name="Macros">. + + +<sect1><tt>.EXPORT</tt><label id=".EXPORT"><p> + + Make symbols accessible from other modules. Must be followed by a comma + separated list of symbols to export, with each one optionally followed by an + address specification and (also optional) an assignment. Using an additional + assignment in the export statement allows to define and export a symbol in + one statement. The default is to export the symbol with the address size it + actually has. The assembler will issue a warning, if the symbol is exported + with an address size smaller than the actual address size. + + Examples: + + <tscreen><verb> + .export foo + .export bar: far + .export foobar: far = foo * bar + .export baz := foobar, zap: far = baz - bar + </verb></tscreen> + + As with constant definitions, using <tt/:=/ instead of <tt/=/ marks the + symbols as a label. + + See: <tt><ref id=".EXPORTZP" name=".EXPORTZP"></tt> + + +<sect1><tt>.EXPORTZP</tt><label id=".EXPORTZP"><p> + + Make symbols accessible from other modules. Must be followed by a comma + separated list of symbols to export. The exported symbols are explicitly + marked as zero page symbols. An assignment may be included in the + <tt/.EXPORTZP/ statement. This allows to define and export a symbol in one + statement. + + Examples: + + <tscreen><verb> + .exportzp foo, bar + .exportzp baz := $02 + </verb></tscreen> + + See: <tt><ref id=".EXPORT" name=".EXPORT"></tt> + + +<sect1><tt>.FARADDR</tt><label id=".FARADDR"><p> + + Define far (24 bit) address data. The command must be followed by a + sequence of (not necessarily constant) expressions. + + Example: + + <tscreen><verb> + .faraddr DrawCircle, DrawRectangle, DrawHexagon + </verb></tscreen> + + See: <tt><ref id=".ADDR" name=".ADDR"></tt> + + +<sect1><tt>.FATAL</tt><label id=".FATAL"><p> + + Force an assembly error and terminate assembly. The assembler will output an + error message preceded by "User error" and will terminate assembly + immediately. + + This command may be used to check for initial conditions that must be + set before assembling a source file. + + Example: + + <tscreen><verb> + .if foo = 1 + ... + .elseif bar = 1 + ... + .else + .fatal "Must define foo or bar!" + .endif + </verb></tscreen> + + See also: <tt><ref id=".ERROR" name=".ERROR"></tt>, + <tt><ref id=".OUT" name=".OUT"></tt>, + <tt><ref id=".WARNING" name=".WARNING"></tt> + + +<sect1><tt>.FEATURE</tt><label id=".FEATURE"><p> + + This directive may be used to enable one or more compatibility features + of the assembler. While the use of <tt/.FEATURE/ should be avoided when + possible, it may be useful when porting sources written for other + assemblers. There is no way to switch a feature off, once you have + enabled it, so using + + <tscreen><verb> + .FEATURE xxx + </verb></tscreen> + + will enable the feature until end of assembly is reached. + + The following features are available: + + <descrip> + + <tag><tt>at_in_identifiers</tt><label id="at_in_identifiers"></tag> + + Accept the at character (`@') as a valid character in identifiers. The + at character is not allowed to start an identifier, even with this + feature enabled. + + <tag><tt>c_comments</tt><label id="c_comments"></tag> + + Allow C like comments using <tt>/*</tt> and <tt>*/</tt> as left and right + comment terminators. Note that C comments may not be nested. There's also a + pitfall when using C like comments: All statements must be terminated by + "end-of-line". Using C like comments, it is possible to hide the newline, + which results in error messages. See the following non working example: + + <tscreen><verb> + lda #$00 /* This comment hides the newline +*/ sta $82 + </verb></tscreen> + + <tag><tt>dollar_in_identifiers</tt><label id="dollar_in_identifiers"></tag> + + Accept the dollar sign (`$') as a valid character in identifiers. The + dollar character is not allowed to start an identifier, even with this + feature enabled. + + <tag><tt>dollar_is_pc</tt><label id="dollar_is_pc"></tag> + + The dollar sign may be used as an alias for the star (`*'), which + gives the value of the current PC in expressions. + Note: Assignment to the pseudo variable is not allowed. + + <tag><tt>force_range</tt><label id="force_range"></tag> + + Force expressions into their valid range for immediate addressing and + storage operators like <tt><ref id=".BYTE" name=".BYTE"></tt> and + <tt><ref id=".WORD" name=".WORD"></tt>. Be very careful with this one, + since it will completely disable error checks. + + <tag><tt>labels_without_colons</tt><label id="labels_without_colons"></tag> + + Allow labels without a trailing colon. These labels are only accepted, + if they start at the beginning of a line (no leading white space). + + <tag><tt>leading_dot_in_identifiers</tt><label id="leading_dot_in_identifiers"></tag> + + Accept the dot (`.') as the first character of an identifier. This may be + used for example to create macro names that start with a dot emulating + control directives of other assemblers. Note however, that none of the + reserved keywords built into the assembler, that starts with a dot, may be + overridden. When using this feature, you may also get into trouble if + later versions of the assembler define new keywords starting with a dot. + + <tag><tt>loose_char_term</tt><label id="loose_char_term"></tag> + + Accept single quotes as well as double quotes as terminators for char + constants. + + <tag><tt>loose_string_term</tt><label id="loose_string_term"></tag> + + Accept single quotes as well as double quotes as terminators for string + constants. + + <tag><tt>missing_char_term</tt><label id="missing_char_term"></tag> + + Accept single quoted character constants where the terminating quote is + missing. + <tscreen><verb> + lda #'a + </verb></tscreen> + <em/Note:/ This does not work in conjunction with <tt/.FEATURE + loose_string_term/, since in this case the input would be ambiguous. + + <tag><tt>org_per_seg</tt><label id="org_per_seg"></tag> + + This feature makes relocatable/absolute mode local to the current segment. + Using <tt><ref id=".ORG" name=".ORG"></tt> when <tt/org_per_seg/ is in + effect will only enable absolute mode for the current segment. Dito for + <tt><ref id=".RELOC" name=".RELOC"></tt>. + + <tag><tt>pc_assignment</tt><label id="pc_assignment"></tag> + + Allow assignments to the PC symbol (`*' or `$' if <tt/dollar_is_pc/ + is enabled). Such an assignment is handled identical to the <tt><ref + id=".ORG" name=".ORG"></tt> command (which is usually not needed, so just + removing the lines with the assignments may also be an option when porting + code written for older assemblers). + + <tag><tt>ubiquitous_idents</tt><label id="ubiquitous_idents"></tag> + + Allow the use of instructions names as names for macros and symbols. This + makes it possible to "overload" instructions by defining a macro with the + same name. This does also make it possible to introduce hard to find errors + in your code, so be careful! + + <tag><tt>underline_in_numbers</tt><label id="underline_in_numbers"></tag> + + Allow underlines within numeric constants. These may be used for grouping + the digits of numbers for easier reading. + Example: + <tscreen><verb> + .feature underline_in_numbers + .word %1100001110100101 + .word %1100_0011_1010_0101 ; Identical but easier to read + </verb></tscreen> + + </descrip> + + It is also possible to specify features on the command line using the + <tt><ref id="option--feature" name="--feature"></tt> command line option. + This is useful when translating sources written for older assemblers, when + you don't want to change the source code. + + As an example, to translate sources written for Andre Fachats xa65 + assembler, the features + + <verb> + labels_without_colons, pc_assignment, loose_char_term + </verb> + + may be helpful. They do not make ca65 completely compatible, so you may not + be able to translate the sources without changes, even when enabling these + features. However, I have found several sources that translate without + problems when enabling these features on the command line. + + +<sect1><tt>.FILEOPT, .FOPT</tt><label id=".FOPT"><p> + + Insert an option string into the object file. There are two forms of + this command, one specifies the option by a keyword, the second + specifies it as a number. Since usage of the second one needs knowledge + of the internal encoding, its use is not recommended and I will only + describe the first form here. + + The command is followed by one of the keywords + + <tscreen><verb> + author + comment + compiler + </verb></tscreen> + + a comma and a string. The option is written into the object file + together with the string value. This is currently unidirectional and + there is no way to actually use these options once they are in the + object file. + + Examples: + + <tscreen><verb> + .fileopt comment, "Code stolen from my brother" + .fileopt compiler, "BASIC 2.0" + .fopt author, "J. R. User" + </verb></tscreen> + + +<sect1><tt>.FORCEIMPORT</tt><label id=".FORCEIMPORT"><p> + + Import an absolute symbol from another module. The command is followed by a + comma separated list of symbols to import. The command is similar to <tt> + <ref id=".IMPORT" name=".IMPORT"></tt>, but the import reference is always + written to the generated object file, even if the symbol is never referenced + (<tt><ref id=".IMPORT" name=".IMPORT"></tt> will not generate import + references for unused symbols). + + Example: + + <tscreen><verb> + .forceimport needthisone, needthistoo + </verb></tscreen> + + See: <tt><ref id=".IMPORT" name=".IMPORT"></tt> + + +<sect1><tt>.GLOBAL</tt><label id=".GLOBAL"><p> + + Declare symbols as global. Must be followed by a comma separated list of + symbols to declare. Symbols from the list, that are defined somewhere in the + source, are exported, all others are imported. Additional <tt><ref + id=".IMPORT" name=".IMPORT"></tt> or <tt><ref id=".EXPORT" + name=".EXPORT"></tt> commands for the same symbol are allowed. + + Example: + + <tscreen><verb> + .global foo, bar + </verb></tscreen> + + +<sect1><tt>.GLOBALZP</tt><label id=".GLOBALZP"><p> + + Declare symbols as global. Must be followed by a comma separated list of + symbols to declare. Symbols from the list, that are defined somewhere in the + source, are exported, all others are imported. Additional <tt><ref + id=".IMPORTZP" name=".IMPORTZP"></tt> or <tt><ref id=".EXPORTZP" + name=".EXPORTZP"></tt> commands for the same symbol are allowed. The symbols + in the list are explicitly marked as zero page symbols. + + Example: + + <tscreen><verb> + .globalzp foo, bar + </verb></tscreen> + +<sect1><tt>.HIBYTES</tt><label id=".HIBYTES"><p> + + Define byte sized data by extracting only the high byte (that is, bits 8-15) from + each expression. This is equivalent to <tt><ref id=".BYTE" name=".BYTE"></tt> with + the operator '>' prepended to each expression in its list. + + Example: + + <tscreen><verb> + .lobytes $1234, $2345, $3456, $4567 + .hibytes $fedc, $edcb, $dcba, $cba9 + </verb></tscreen> + + which is equivalent to + + <tscreen><verb> + .byte $34, $45, $56, $67 + .byte $fe, $ed, $dc, $cb + </verb></tscreen> + + Example: + + <tscreen><verb> + .define MyTable TableItem0, TableItem1, TableItem2, TableItem3 + + TableLookupLo: .lobytes MyTable + TableLookupHi: .hibytes MyTable + </verb></tscreen> + + which is equivalent to + + <tscreen><verb> + TableLookupLo: .byte <TableItem0, <TableItem1, <TableItem2, <TableItem3 + TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3 + </verb></tscreen> + + See also: <tt><ref id=".BYTE" name=".BYTE"></tt>, + <tt><ref id=".LOBYTES" name=".LOBYTES"></tt>, + <tt><ref id=".BANKBYTES" name=".BANKBYTES"></tt> + + +<sect1><tt>.I16</tt><label id=".I16"><p> + + Valid only in 65816 mode. Switch the index registers to 16 bit. + + Note: This command will not emit any code, it will tell the assembler to + create 16 bit operands for immediate operands. + + See also the <tt><ref id=".I8" name=".I8"></tt> and <tt><ref id=".SMART" + name=".SMART"></tt> commands. + + +<sect1><tt>.I8</tt><label id=".I8"><p> + + Valid only in 65816 mode. Switch the index registers to 8 bit. + + Note: This command will not emit any code, it will tell the assembler to + create 8 bit operands for immediate operands. + + See also the <tt><ref id=".I16" name=".I16"></tt> and <tt><ref id=".SMART" + name=".SMART"></tt> commands. + + +<sect1><tt>.IF</tt><label id=".IF"><p> + + Conditional assembly: Evaluate an expression and switch assembler output + on or off depending on the expression. The expression must be a constant + expression, that is, all operands must be defined. + + A expression value of zero evaluates to FALSE, any other value evaluates + to TRUE. + + +<sect1><tt>.IFBLANK</tt><label id=".IFBLANK"><p> + + Conditional assembly: Check if there are any remaining tokens in this line, + and evaluate to FALSE if this is the case, and to TRUE otherwise. If the + condition is not true, further lines are not assembled until an <tt><ref + id=".ELSE" name=".ESLE"></tt>, <tt><ref id=".ELSEIF" name=".ELSEIF"></tt> or + <tt><ref id=".ENDIF" name=".ENDIF"></tt> directive. + + This command is often used to check if a macro parameter was given. Since an + empty macro parameter will evaluate to nothing, the condition will evaluate + to TRUE if an empty parameter was given. + + Example: + + <tscreen><verb> + .macro arg1, arg2 + .ifblank arg2 + lda #arg1 + .else + lda #arg2 + .endif + .endmacro + </verb></tscreen> + + See also: <tt><ref id=".BLANK" name=".BLANK"></tt> + + +<sect1><tt>.IFCONST</tt><label id=".IFCONST"><p> + + Conditional assembly: Evaluate an expression and switch assembler output + on or off depending on the constness of the expression. + + A const expression evaluates to to TRUE, a non const expression (one + containing an imported or currently undefined symbol) evaluates to + FALSE. + + See also: <tt><ref id=".CONST" name=".CONST"></tt> + + +<sect1><tt>.IFDEF</tt><label id=".IFDEF"><p> + + Conditional assembly: Check if a symbol is defined. Must be followed by + a symbol name. The condition is true if the the given symbol is already + defined, and false otherwise. + + See also: <tt><ref id=".DEFINED" name=".DEFINED"></tt> + + +<sect1><tt>.IFNBLANK</tt><label id=".IFNBLANK"><p> + + Conditional assembly: Check if there are any remaining tokens in this line, + and evaluate to TRUE if this is the case, and to FALSE otherwise. If the + condition is not true, further lines are not assembled until an <tt><ref + id=".ELSE" name=".ELSE"></tt>, <tt><ref id=".ELSEIF" name=".ELSEIF"></tt> or + <tt><ref id=".ENDIF" name=".ENDIF"></tt> directive. + + This command is often used to check if a macro parameter was given. + Since an empty macro parameter will evaluate to nothing, the condition + will evaluate to FALSE if an empty parameter was given. + + Example: + + <tscreen><verb> + .macro arg1, arg2 + lda #arg1 + .ifnblank arg2 + lda #arg2 + .endif + .endmacro + </verb></tscreen> + + See also: <tt><ref id=".BLANK" name=".BLANK"></tt> + + +<sect1><tt>.IFNDEF</tt><label id=".IFNDEF"><p> + + Conditional assembly: Check if a symbol is defined. Must be followed by + a symbol name. The condition is true if the the given symbol is not + defined, and false otherwise. + + See also: <tt><ref id=".DEFINED" name=".DEFINED"></tt> + + +<sect1><tt>.IFNREF</tt><label id=".IFNREF"><p> + + Conditional assembly: Check if a symbol is referenced. Must be followed + by a symbol name. The condition is true if if the the given symbol was + not referenced before, and false otherwise. + + See also: <tt><ref id=".REFERENCED" name=".REFERENCED"></tt> + + +<sect1><tt>.IFP02</tt><label id=".IFP02"><p> + + Conditional assembly: Check if the assembler is currently in 6502 mode + (see <tt><ref id=".P02" name=".P02"></tt> command). + + +<sect1><tt>.IFP816</tt><label id=".IFP816"><p> + + Conditional assembly: Check if the assembler is currently in 65816 mode + (see <tt><ref id=".P816" name=".P816"></tt> command). + + +<sect1><tt>.IFPC02</tt><label id=".IFPC02"><p> + + Conditional assembly: Check if the assembler is currently in 65C02 mode + (see <tt><ref id=".PC02" name=".PC02"></tt> command). + + +<sect1><tt>.IFPSC02</tt><label id=".IFPSC02"><p> + + Conditional assembly: Check if the assembler is currently in 65SC02 mode + (see <tt><ref id=".PSC02" name=".PSC02"></tt> command). + + +<sect1><tt>.IFREF</tt><label id=".IFREF"><p> + + Conditional assembly: Check if a symbol is referenced. Must be followed + by a symbol name. The condition is true if if the the given symbol was + referenced before, and false otherwise. + + This command may be used to build subroutine libraries in include files + (you may use separate object modules for this purpose too). + + Example: + + <tscreen><verb> + .ifref ToHex ; If someone used this subroutine + ToHex: tay ; Define subroutine + lda HexTab,y + rts + .endif + </verb></tscreen> + + See also: <tt><ref id=".REFERENCED" name=".REFERENCED"></tt> + + +<sect1><tt>.IMPORT</tt><label id=".IMPORT"><p> + + Import a symbol from another module. The command is followed by a comma + separated list of symbols to import, with each one optionally followed by + an address specification. + + Example: + + <tscreen><verb> + .import foo + .import bar: zeropage + </verb></tscreen> + + See: <tt><ref id=".IMPORTZP" name=".IMPORTZP"></tt> + + +<sect1><tt>.IMPORTZP</tt><label id=".IMPORTZP"><p> + + Import a symbol from another module. The command is followed by a comma + separated list of symbols to import. The symbols are explicitly imported + as zero page symbols (that is, symbols with values in byte range). + + Example: + + <tscreen><verb> + .importzp foo, bar + </verb></tscreen> + + See: <tt><ref id=".IMPORT" name=".IMPORT"></tt> + + +<sect1><tt>.INCBIN</tt><label id=".INCBIN"><p> + + Include a file as binary data. The command expects a string argument + that is the name of a file to include literally in the current segment. + In addition to that, a start offset and a size value may be specified, + separated by commas. If no size is specified, all of the file from the + start offset to end-of-file is used. If no start position is specified + either, zero is assumed (which means that the whole file is inserted). + + Example: + + <tscreen><verb> + ; Include whole file + .incbin "sprites.dat" + + ; Include file starting at offset 256 + .incbin "music.dat", $100 + + ; Read 100 bytes starting at offset 200 + .incbin "graphics.dat", 200, 100 + </verb></tscreen> + + +<sect1><tt>.INCLUDE</tt><label id=".INCLUDE"><p> + + Include another file. Include files may be nested up to a depth of 16. + + Example: + + <tscreen><verb> + .include "subs.inc" + </verb></tscreen> + + +<sect1><tt>.INTERRUPTOR</tt><label id=".INTERRUPTOR"><p> + + Export a symbol and mark it as an interruptor. This may be used together + with the linker to build a table of interruptor subroutines that are called + in an interrupt. + + Note: The linker has a feature to build a table of marked routines, but it + is your code that must call these routines, so just declaring a symbol as + interruptor does nothing by itself. + + An interruptor is always exported as an absolute (16 bit) symbol. You don't + need to use an additional <tt/.export/ statement, this is implied by + <tt/.interruptor/. It may have an optional priority that is separated by a + comma. Higher numeric values mean a higher priority. If no priority is + given, the default priority of 7 is used. Be careful when assigning + priorities to your own module constructors so they won't interfere with the + ones in the cc65 library. + + Example: + + <tscreen><verb> + .interruptor IrqHandler + .interruptor Handler, 16 + </verb></tscreen> + + See the <tt><ref id=".CONDES" name=".CONDES"></tt> command and the separate + section <ref id="condes" name="Module constructors/destructors"> explaining + the feature in more detail. + + +<sect1><tt>.LINECONT</tt><label id=".LINECONT"><p> + + Switch on or off line continuations using the backslash character + before a newline. The option is off by default. + Note: Line continuations do not work in a comment. A backslash at the + end of a comment is treated as part of the comment and does not trigger + line continuation. + The command must be followed by a '+' or '-' character to switch the + option on or off respectively. + + Example: + + <tscreen><verb> + .linecont + ; Allow line continuations + + lda \ + #$20 ; This is legal now + </verb></tscreen> + + +<sect1><tt>.LIST</tt><label id=".LIST"><p> + + Enable output to the listing. The command must be followed by a boolean + switch ("on", "off", "+" or "-") and will enable or disable listing + output. + The option has no effect if the listing is not enabled by the command line + switch -l. If -l is used, an internal counter is set to 1. Lines are output + to the listing file, if the counter is greater than zero, and suppressed if + the counter is zero. Each use of <tt/.LIST/ will increment or decrement the + counter. + + Example: + + <tscreen><verb> + .list on ; Enable listing output + </verb></tscreen> + + +<sect1><tt>.LISTBYTES</tt><label id=".LISTBYTES"><p> + + Set, how many bytes are shown in the listing for one source line. The + default is 12, so the listing will show only the first 12 bytes for any + source line that generates more than 12 bytes of code or data. + The directive needs an argument, which is either "unlimited", or an + integer constant in the range 4..255. + + Examples: + + <tscreen><verb> + .listbytes unlimited ; List all bytes + .listbytes 12 ; List the first 12 bytes + .incbin "data.bin" ; Include large binary file + </verb></tscreen> + + +<sect1><tt>.LOBYTES</tt><label id=".LOBYTES"><p> + + Define byte sized data by extracting only the low byte (that is, bits 0-7) from + each expression. This is equivalent to <tt><ref id=".BYTE" name=".BYTE"></tt> with + the operator '<' prepended to each expression in its list. + + Example: + + <tscreen><verb> + .lobytes $1234, $2345, $3456, $4567 + .hibytes $fedc, $edcb, $dcba, $cba9 + </verb></tscreen> + + which is equivalent to + + <tscreen><verb> + .byte $34, $45, $56, $67 + .byte $fe, $ed, $dc, $cb + </verb></tscreen> + + Example: + + <tscreen><verb> + .define MyTable TableItem0, TableItem1, TableItem2, TableItem3 + + TableLookupLo: .lobytes MyTable + TableLookupHi: .hibytes MyTable + </verb></tscreen> + + which is equivalent to + + <tscreen><verb> + TableLookupLo: .byte <TableItem0, <TableItem1, <TableItem2, <TableItem3 + TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3 + </verb></tscreen> + + See also: <tt><ref id=".BYTE" name=".BYTE"></tt>, + <tt><ref id=".HIBYTES" name=".HIBYTES"></tt>, + <tt><ref id=".BANKBYTES" name=".BANKBYTES"></tt> + + +<sect1><tt>.LOCAL</tt><label id=".LOCAL"><p> + + This command may only be used inside a macro definition. It declares a + list of identifiers as local to the macro expansion. + + A problem when using macros are labels: Since they don't change their name, + you get a "duplicate symbol" error if the macro is expanded the second time. + Labels declared with <tt><ref id=".LOCAL" name=".LOCAL"></tt> have their + name mapped to an internal unique name (<tt/___ABCD__/) with each macro + invocation. + + Some other assemblers start a new lexical block inside a macro expansion. + This has some drawbacks however, since that will not allow <em/any/ symbol + to be visible outside a macro, a feature that is sometimes useful. The + <tt><ref id=".LOCAL" name=".LOCAL"></tt> command is in my eyes a better way + to address the problem. + + You get an error when using <tt><ref id=".LOCAL" name=".LOCAL"></tt> outside + a macro. + + +<sect1><tt>.LOCALCHAR</tt><label id=".LOCALCHAR"><p> + + Defines the character that start "cheap" local labels. You may use one + of '@' and '?' as start character. The default is '@'. + + Cheap local labels are labels that are visible only between two non + cheap labels. This way you can reuse identifiers like "<tt/loop/" without + using explicit lexical nesting. + + Example: + + <tscreen><verb> + .localchar '?' + + Clear: lda #$00 ; Global label + ?Loop: sta Mem,y ; Local label + dey + bne ?Loop ; Ok + rts + Sub: ... ; New global label + bne ?Loop ; ERROR: Unknown identifier! + </verb></tscreen> + + +<sect1><tt>.MACPACK</tt><label id=".MACPACK"><p> + + Insert a predefined macro package. The command is followed by an + identifier specifying the macro package to insert. Available macro + packages are: + + <tscreen><verb> + atari Defines the scrcode macro. + cbm Defines the scrcode macro. + cpu Defines constants for the .CPU variable. + generic Defines generic macros like add and sub. + longbranch Defines conditional long jump macros. + </verb></tscreen> + + Including a macro package twice, or including a macro package that + redefines already existing macros will lead to an error. + + Example: + + <tscreen><verb> + .macpack longbranch ; Include macro package + + cmp #$20 ; Set condition codes + jne Label ; Jump long on condition + </verb></tscreen> + + Macro packages are explained in more detail in section <ref + id="macropackages" name="Macro packages">. + + +<sect1><tt>.MAC, .MACRO</tt><label id=".MACRO"><p> + + Start a classic macro definition. The command is followed by an identifier + (the macro name) and optionally by a comma separated list of identifiers + that are macro parameters. A macro definition is terminated by <tt><ref + id=".ENDMACRO" name=".ENDMACRO"></tt>. + + Example: + + <tscreen><verb> + .macro ldax arg ; Define macro ldax + lda arg + ldx arg+1 + </verb></tscreen> + + See: <tt><ref id=".DELMACRO" name=".DELMACRO"></tt>, + <tt><ref id=".ENDMACRO" name=".ENDMACRO"></tt>, + <tt><ref id=".EXITMACRO" name=".EXITMACRO"></tt> + + See also section <ref id="macros" name="Macros">. + + +<sect1><tt>.ORG</tt><label id=".ORG"><p> + + Start a section of absolute code. The command is followed by a constant + expression that gives the new PC counter location for which the code is + assembled. Use <tt><ref id=".RELOC" name=".RELOC"></tt> to switch back to + relocatable code. + + By default, absolute/relocatable mode is global (valid even when switching + segments). Using <tt>.FEATURE <ref id="org_per_seg" name="org_per_seg"></tt> + it can be made segment local. + + Please note that you <em/do not need/ <tt/.ORG/ in most cases. Placing + code at a specific address is the job of the linker, not the assembler, so + there is usually no reason to assemble code to a specific address. + + Example: + + <tscreen><verb> + .org $7FF ; Emit code starting at $7FF + </verb></tscreen> + + +<sect1><tt>.OUT</tt><label id=".OUT"><p> + + Output a string to the console without producing an error. This command + is similar to <tt/.ERROR/, however, it does not force an assembler error + that prevents the creation of an object file. + + Example: + + <tscreen><verb> + .out "This code was written by the codebuster(tm)" + </verb></tscreen> + + See also: <tt><ref id=".ERROR" name=".ERROR"></tt>, + <tt><ref id=".FATAL" name=".FATAL"></tt>, + <tt><ref id=".WARNING" name=".WARNING"></tt> + + +<sect1><tt>.P02</tt><label id=".P02"><p> + + Enable the 6502 instruction set, disable 65SC02, 65C02 and 65816 + instructions. This is the default if not overridden by the + <tt><ref id="option--cpu" name="--cpu"></tt> command line option. + + See: <tt><ref id=".PC02" name=".PC02"></tt>, <tt><ref id=".PSC02" + name=".PSC02"></tt> and <tt><ref id=".P816" name=".P816"></tt> + + +<sect1><tt>.P816</tt><label id=".P816"><p> + + Enable the 65816 instruction set. This is a superset of the 65SC02 and + 6502 instruction sets. + + See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PSC02" + name=".PSC02"></tt> and <tt><ref id=".PC02" name=".PC02"></tt> + + +<sect1><tt>.PAGELEN, .PAGELENGTH</tt><label id=".PAGELENGTH"><p> + + Set the page length for the listing. Must be followed by an integer + constant. The value may be "unlimited", or in the range 32 to 127. The + statement has no effect if no listing is generated. The default value is -1 + (unlimited) but may be overridden by the <tt/--pagelength/ command line + option. Beware: Since ca65 is a one pass assembler, the listing is generated + after assembly is complete, you cannot use multiple line lengths with one + source. Instead, the value set with the last <tt/.PAGELENGTH/ is used. + + Examples: + + <tscreen><verb> + .pagelength 66 ; Use 66 lines per listing page + + .pagelength unlimited ; Unlimited page length + </verb></tscreen> + + +<sect1><tt>.PC02</tt><label id=".PC02"><p> + + Enable the 65C02 instructions set. This instruction set includes all + 6502 and 65SC02 instructions. + + See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PSC02" + name=".PSC02"></tt> and <tt><ref id=".P816" name=".P816"></tt> + + +<sect1><tt>.POPCPU</tt><label id=".POPCPU"><p> + + Pop the last CPU setting from the stack, and activate it. + + This command will switch back to the CPU that was last pushed onto the CPU + stack using the <tt><ref id=".PUSHCPU" name=".PUSHCPU"></tt> command, and + remove this entry from the stack. + + The assembler will print an error message if the CPU stack is empty when + this command is issued. + + See: <tt><ref id=".CPU" name=".CPU"></tt>, <tt><ref id=".PUSHCPU" + name=".PUSHCPU"></tt>, <tt><ref id=".SETCPU" name=".SETCPU"></tt> + + +<sect1><tt>.POPSEG</tt><label id=".POPSEG"><p> + + Pop the last pushed segment from the stack, and set it. + + This command will switch back to the segment that was last pushed onto the + segment stack using the <tt><ref id=".PUSHSEG" name=".PUSHSEG"></tt> + command, and remove this entry from the stack. + + The assembler will print an error message if the segment stack is empty + when this command is issued. + + See: <tt><ref id=".PUSHSEG" name=".PUSHSEG"></tt> + + +<sect1><tt>.PROC</tt><label id=".PROC"><p> + + Start a nested lexical level with the given name and adds a symbol with this + name to the enclosing scope. All new symbols from now on are in the local + lexical level and are accessible from outside only via <ref id="scopesyntax" + name="explicit scope specification">. Symbols defined outside this local + level may be accessed as long as their names are not used for new symbols + inside the level. Symbols names in other lexical levels do not clash, so you + may use the same names for identifiers. The lexical level ends when the + <tt><ref id=".ENDPROC" name=".ENDPROC"></tt> command is read. Lexical levels + may be nested up to a depth of 16 (this is an artificial limit to protect + against errors in the source). + + Note: Macro names are always in the global level and in a separate name + space. There is no special reason for this, it's just that I've never + had any need for local macro definitions. + + Example: + + <tscreen><verb> + .proc Clear ; Define Clear subroutine, start new level + lda #$00 + L1: sta Mem,y ; L1 is local and does not cause a + ; duplicate symbol error if used in other + ; places + dey + bne L1 ; Reference local symbol + rts + .endproc ; Leave lexical level + </verb></tscreen> + + See: <tt/<ref id=".ENDPROC" name=".ENDPROC">/ and <tt/<ref id=".SCOPE" + name=".SCOPE">/ + + +<sect1><tt>.PSC02</tt><label id=".PSC02"><p> + + Enable the 65SC02 instructions set. This instruction set includes all + 6502 instructions. + + See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PC02" + name=".PC02"></tt> and <tt><ref id=".P816" name=".P816"></tt> + + +<sect1><tt>.PUSHCPU</tt><label id=".PUSHCPU"><p> + + Push the currently active CPU onto a stack. The stack has a size of 8 + entries. + + <tt/.PUSHCPU/ allows together with <tt><ref id=".POPCPU" + name=".POPCPU"></tt> to switch to another CPU and to restore the old CPU + later, without knowledge of the current CPU setting. + + The assembler will print an error message if the CPU stack is already full, + when this command is issued. + + See: <tt><ref id=".CPU" name=".CPU"></tt>, <tt><ref id=".POPCPU" + name=".POPCPU"></tt>, <tt><ref id=".SETCPU" name=".SETCPU"></tt> + + +<sect1><tt>.PUSHSEG</tt><label id=".PUSHSEG"><p> + + Push the currently active segment onto a stack. The entries on the stack + include the name of the segment and the segment type. The stack has a size + of 16 entries. + + <tt/.PUSHSEG/ allows together with <tt><ref id=".POPSEG" name=".POPSEG"></tt> + to switch to another segment and to restore the old segment later, without + even knowing the name and type of the current segment. + + The assembler will print an error message if the segment stack is already + full, when this command is issued. + + See: <tt><ref id=".POPSEG" name=".POPSEG"></tt> + + +<sect1><tt>.RELOC</tt><label id=".RELOC"><p> + + Switch back to relocatable mode. See the <tt><ref id=".ORG" + name=".ORG"></tt> command. + + +<sect1><tt>.REPEAT</tt><label id=".REPEAT"><p> + + Repeat all commands between <tt/.REPEAT/ and <tt><ref id=".ENDREPEAT" + name=".ENDREPEAT"></tt> constant number of times. The command is followed by + a constant expression that tells how many times the commands in the body + should get repeated. Optionally, a comma and an identifier may be specified. + If this identifier is found in the body of the repeat statement, it is + replaced by the current repeat count (starting with zero for the first time + the body is repeated). + + <tt/.REPEAT/ statements may be nested. If you use the same repeat count + identifier for a nested <tt/.REPEAT/ statement, the one from the inner + level will be used, not the one from the outer level. + + Example: + + The following macro will emit a string that is "encrypted" in that all + characters of the string are XORed by the value $55. + + <tscreen><verb> + .macro Crypt Arg + .repeat .strlen(Arg), I + .byte .strat(Arg, I) ^ $55 + .endrep + .endmacro + </verb></tscreen> + + See: <tt><ref id=".ENDREPEAT" name=".ENDREPEAT"></tt> + + +<sect1><tt>.RES</tt><label id=".RES"><p> + + Reserve storage. The command is followed by one or two constant + expressions. The first one is mandatory and defines, how many bytes of + storage should be defined. The second, optional expression must by a + constant byte value that will be used as value of the data. If there + is no fill value given, the linker will use the value defined in the + linker configuration file (default: zero). + + Example: + + <tscreen><verb> + ; Reserve 12 bytes of memory with value $AA + .res 12, $AA + </verb></tscreen> + + +<sect1><tt>.RODATA</tt><label id=".RODATA"><p> + + Switch to the RODATA segment. The name of the RODATA segment is always + "RODATA", so this is a shortcut for + + <tscreen><verb> + .segment "RODATA" + </verb></tscreen> + + The RODATA segment is a segment that is used by the compiler for + readonly data like string constants. + + See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command. + + +<sect1><tt>.SCOPE</tt><label id=".SCOPE"><p> + + Start a nested lexical level with the given name. All new symbols from now + on are in the local lexical level and are accessible from outside only via + <ref id="scopesyntax" name="explicit scope specification">. Symbols defined + outside this local level may be accessed as long as their names are not used + for new symbols inside the level. Symbols names in other lexical levels do + not clash, so you may use the same names for identifiers. The lexical level + ends when the <tt><ref id=".ENDSCOPE" name=".ENDSCOPE"></tt> command is + read. Lexical levels may be nested up to a depth of 16 (this is an + artificial limit to protect against errors in the source). + + Note: Macro names are always in the global level and in a separate name + space. There is no special reason for this, it's just that I've never + had any need for local macro definitions. + + Example: + + <tscreen><verb> + .scope Error ; Start new scope named Error + None = 0 ; No error + File = 1 ; File error + Parse = 2 ; Parse error + .endscope ; Close lexical level + + ... + lda #Error::File ; Use symbol from scope Error + </verb></tscreen> + + See: <tt/<ref id=".ENDSCOPE" name=".ENDSCOPE">/ and <tt/<ref id=".PROC" + name=".PROC">/ + + +<sect1><tt>.SEGMENT</tt><label id=".SEGMENT"><p> + + Switch to another segment. Code and data is always emitted into a + segment, that is, a named section of data. The default segment is + "CODE". There may be up to 254 different segments per object file + (and up to 65534 per executable). There are shortcut commands for + the most common segments ("CODE", "DATA" and "BSS"). + + The command is followed by a string containing the segment name (there are + some constraints for the name - as a rule of thumb use only those segment + names that would also be valid identifiers). There may also be an optional + address size separated by a colon. See the section covering <tt/<ref + id="address-sizes" name="address sizes">/ for more information. + + The default address size for a segment depends on the memory model specified + on the command line. The default is "absolute", which means that you don't + have to use an address size modifier in most cases. + + "absolute" means that the is a segment with 16 bit (absolute) addressing. + That is, the segment will reside somewhere in core memory outside the zero + page. "zeropage" (8 bit) means that the segment will be placed in the zero + page and direct (short) addressing is possible for data in this segment. + + Beware: Only labels in a segment with the zeropage attribute are marked + as reachable by short addressing. The `*' (PC counter) operator will + work as in other segments and will create absolute variable values. + + Please note that a segment cannot have two different address sizes. A + segment specified as zeropage cannot be declared as being absolute later. + + Examples: + + <tscreen><verb> + .segment "ROM2" ; Switch to ROM2 segment + .segment "ZP2": zeropage ; New direct segment + .segment "ZP2" ; Ok, will use last attribute + .segment "ZP2": absolute ; Error, redecl mismatch + </verb></tscreen> + + See: <tt><ref id=".BSS" name=".BSS"></tt>, <tt><ref id=".CODE" + name=".CODE"></tt>, <tt><ref id=".DATA" name=".DATA"></tt> and <tt><ref + id=".RODATA" name=".RODATA"></tt> + + +<sect1><tt>.SET</tt><label id=".SET"><p> + + <tt/.SET/ is used to assign a value to a variable. See <ref id="variables" + name="Numeric variables"> for a full description. + + +<sect1><tt>.SETCPU</tt><label id=".SETCPU"><p> + + Switch the CPU instruction set. The command is followed by a string that + specifies the CPU. Possible values are those that can also be supplied to + the <tt><ref id="option--cpu" name="--cpu"></tt> command line option, + namely: 6502, 6502X, 65SC02, 65C02, 65816 and HuC6280. + + See: <tt><ref id=".CPU" name=".CPU"></tt>, + <tt><ref id=".IFP02" name=".IFP02"></tt>, + <tt><ref id=".IFP816" name=".IFP816"></tt>, + <tt><ref id=".IFPC02" name=".IFPC02"></tt>, + <tt><ref id=".IFPSC02" name=".IFPSC02"></tt>, + <tt><ref id=".P02" name=".P02"></tt>, + <tt><ref id=".P816" name=".P816"></tt>, + <tt><ref id=".PC02" name=".PC02"></tt>, + <tt><ref id=".PSC02" name=".PSC02"></tt> + + +<sect1><tt>.SMART</tt><label id=".SMART"><p> + + Switch on or off smart mode. The command must be followed by a '+' or '-' + character to switch the option on or off respectively. The default is off + (that is, the assembler doesn't try to be smart), but this default may be + changed by the -s switch on the command line. + + In smart mode the assembler will do the following: + + <itemize> + <item>Track usage of the <tt/REP/ and <tt/SEP/ instructions in 65816 mode + and update the operand sizes accordingly. If the operand of such an + instruction cannot be evaluated by the assembler (for example, because + the operand is an imported symbol), a warning is issued. Beware: Since + the assembler cannot trace the execution flow this may lead to false + results in some cases. If in doubt, use the <tt/.Inn/ and <tt/.Ann/ + instructions to tell the assembler about the current settings. + <item>In 65816 mode, replace a <tt/RTS/ instruction by <tt/RTL/ if it is + used within a procedure declared as <tt/far/, or if the procedure has + no explicit address specification, but it is <tt/far/ because of the + memory model used. + </itemize> + + Example: + + <tscreen><verb> + .smart ; Be smart + .smart - ; Stop being smart + </verb></tscreen> + + See: <tt><ref id=".A16" name=".A16"></tt>, + <tt><ref id=".A8" name=".A8"></tt>, + <tt><ref id=".I16" name=".I16"></tt>, + <tt><ref id=".I8" name=".I8"></tt> + + +<sect1><tt>.STRUCT</tt><label id=".STRUCT"><p> + + Starts a struct definition. Structs are covered in a separate section named + <ref id="structs" name=""Structs and unions"">. + + See also: <tt><ref id=".ENDSTRUCT" name=".ENDSTRUCT"></tt>, + <tt><ref id=".ENDUNION" name=".ENDUNION"></tt>, + <tt><ref id=".UNION" name=".UNION"></tt> + + +<sect1><tt>.TAG</tt><label id=".TAG"><p> + + Allocate space for a struct or union. + + Example: + + <tscreen><verb> + .struct Point + xcoord .word + ycoord .word + .endstruct + + .bss + .tag Point ; Allocate 4 bytes + </verb></tscreen> + + +<sect1><tt>.UNDEF, .UNDEFINE</tt><label id=".UNDEFINE"><p> + + Delete a define style macro definition. The command is followed by an + identifier which specifies the name of the macro to delete. Macro + replacement is switched of when reading the token following the command + (otherwise the macro name would be replaced by its replacement list). + + See also the <tt><ref id=".DEFINE" name=".DEFINE"></tt> command and + section <ref id="macros" name="Macros">. + + +<sect1><tt>.UNION</tt><label id=".UNION"><p> + + Starts a union definition. Unions are covered in a separate section named + <ref id="structs" name=""Structs and unions"">. + + See also: <tt><ref id=".ENDSTRUCT" name=".ENDSTRUCT"></tt>, + <tt><ref id=".ENDUNION" name=".ENDUNION"></tt>, + <tt><ref id=".STRUCT" name=".STRUCT"></tt> + + +<sect1><tt>.WARNING</tt><label id=".WARNING"><p> + + Force an assembly warning. The assembler will output a warning message + preceded by "User warning". This warning will always be output, even if + other warnings are disabled with the <tt><ref id="option-W" name="-W0"></tt> + command line option. + + This command may be used to output possible problems when assembling + the source file. + + Example: + + <tscreen><verb> + .macro jne target + .local L1 + .ifndef target + .warning "Forward jump in jne, cannot optimize!" + beq L1 + jmp target + L1: + .else + ... + .endif + .endmacro + </verb></tscreen> + + See also: <tt><ref id=".ERROR" name=".ERROR"></tt>, + <tt><ref id=".FATAL" name=".FATAL"></tt>, + <tt><ref id=".OUT" name=".OUT"></tt> + + +<sect1><tt>.WORD</tt><label id=".WORD"><p> + + Define word sized data. Must be followed by a sequence of (word ranged, + but not necessarily constant) expressions. + + Example: + + <tscreen><verb> + .word $0D00, $AF13, _Clear + </verb></tscreen> + + +<sect1><tt>.ZEROPAGE</tt><label id=".ZEROPAGE"><p> + + Switch to the ZEROPAGE segment and mark it as direct (zeropage) segment. + The name of the ZEROPAGE segment is always "ZEROPAGE", so this is a + shortcut for + + <tscreen><verb> + .segment "ZEROPAGE", zeropage + </verb></tscreen> + + Because of the "zeropage" attribute, labels declared in this segment are + addressed using direct addressing mode if possible. You <em/must/ instruct + the linker to place this segment somewhere in the address range 0..$FF + otherwise you will get errors. + + See: <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> + + + +<sect>Macros<label id="macros"><p> + + +<sect1>Introduction<p> + +Macros may be thought of as "parametrized super instructions". Macros are +sequences of tokens that have a name. If that name is used in the source +file, the macro is "expanded", that is, it is replaced by the tokens that +were specified when the macro was defined. + + +<sect1>Macros without parameters<p> + +In its simplest form, a macro does not have parameters. Here's an +example: + +<tscreen><verb> + .macro asr ; Arithmetic shift right + cmp #$80 ; Put bit 7 into carry + ror ; Rotate right with carry + .endmacro +</verb></tscreen> + +The macro above consists of two real instructions, that are inserted into +the code, whenever the macro is expanded. Macro expansion is simply done +by using the name, like this: + +<tscreen><verb> + lda $2010 + asr + sta $2010 +</verb></tscreen> + + +<sect1>Parametrized macros<p> + +When using macro parameters, macros can be even more useful: + +<tscreen><verb> + .macro inc16 addr + clc + lda addr + adc #$01 + sta addr + lda addr+1 + adc #$00 + sta addr+1 + .endmacro +</verb></tscreen> + +When calling the macro, you may give a parameter, and each occurrence of +the name "addr" in the macro definition will be replaced by the given +parameter. So + +<tscreen><verb> + inc16 $1000 +</verb></tscreen> + +will be expanded to + +<tscreen><verb> + clc + lda $1000 + adc #$01 + sta $1000 + lda $1000+1 + adc #$00 + sta $1000+1 +</verb></tscreen> + +A macro may have more than one parameter, in this case, the parameters +are separated by commas. You are free to give less parameters than the +macro actually takes in the definition. You may also leave intermediate +parameters empty. Empty parameters are replaced by empty space (that is, +they are removed when the macro is expanded). If you have a look at our +macro definition above, you will see, that replacing the "addr" parameter +by nothing will lead to wrong code in most lines. To help you, writing +macros with a variable parameter list, there are some control commands: + +<tt><ref id=".IFBLANK" name=".IFBLANK"></tt> tests the rest of the line and +returns true, if there are any tokens on the remainder of the line. Since +empty parameters are replaced by nothing, this may be used to test if a given +parameter is empty. <tt><ref id=".IFNBLANK" name=".IFNBLANK"></tt> tests the +opposite. + +Look at this example: + +<tscreen><verb> + .macro ldaxy a, x, y + .ifnblank a + lda #a + .endif + .ifnblank x + ldx #x + .endif + .ifnblank y + ldy #y + .endif + .endmacro +</verb></tscreen> + +This macro may be called as follows: + +<tscreen><verb> + ldaxy 1, 2, 3 ; Load all three registers + + ldaxy 1, , 3 ; Load only a and y + + ldaxy , , 3 ; Load y only +</verb></tscreen> + +There's another helper command for determining, which macro parameters are +valid: <tt><ref id=".PARAMCOUNT" name=".PARAMCOUNT"></tt> This command is +replaced by the parameter count given, <em/including/ intermediate empty macro +parameters: + +<tscreen><verb> + ldaxy 1 ; .PARAMCOUNT = 1 + ldaxy 1,,3 ; .PARAMCOUNT = 3 + ldaxy 1,2 ; .PARAMCOUNT = 2 + ldaxy 1, ; .PARAMCOUNT = 2 + ldaxy 1,2,3 ; .PARAMCOUNT = 3 +</verb></tscreen> + +Macro parameters may optionally be enclosed into curly braces. This allows the +inclusion of tokens that would otherwise terminate the parameter (the comma in +case of a macro parameter). + +<tscreen><verb> + .macro foo arg1, arg2 + ... + .endmacro + + foo ($00,x) ; Two parameters passed + foo {($00,x)} ; One parameter passed +</verb></tscreen> + +In the first case, the macro is called with two parameters: '<tt/($00/' +and 'x)'. The comma is not passed to the macro, since it is part of the +calling sequence, not the parameters. + +In the second case, '($00,x)' is passed to the macro, this time +including the comma. + + +<sect1>Detecting parameter types<p> + +Sometimes it is nice to write a macro that acts differently depending on the +type of the argument supplied. An example would be a macro that loads a 16 bit +value from either an immediate operand, or from memory. The <tt/<ref +id=".MATCH" name=".MATCH">/ and <tt/<ref id=".XMATCH" name=".XMATCH">/ +functions will allow you to do exactly this: + +<tscreen><verb> + .macro ldax arg + .if (.match (.left (1, {arg}), #)) + ; immediate mode + lda #<(.right (.tcount ({arg})-1, {arg})) + ldx #>(.right (.tcount ({arg})-1, {arg})) + .else + ; assume absolute or zero page + lda arg + ldx 1+(arg) + .endif + .endmacro +</verb></tscreen> + +Using the <tt/<ref id=".MATCH" name=".MATCH">/ function, the macro is able to +check if its argument begins with a hash mark. If so, two immediate loads are +emitted, Otherwise a load from an absolute zero page memory location is +assumed. Please note how the curly braces are used to enclose parameters to +pseudo functions handling token lists. This is necessary, because the token +lists may include commas or parens, which would be treated by the assembler +as end-of-list. + +The macro can be used as + +<tscreen><verb> + foo: .word $5678 + ... + ldax #$1234 ; X=$12, A=$34 + ... + ldax foo ; X=$56, A=$78 +</verb></tscreen> + + +<sect1>Recursive macros<p> + +Macros may be used recursively: + +<tscreen><verb> + .macro push r1, r2, r3 + lda r1 + pha + .if .paramcount > 1 + push r2, r3 + .endif + .endmacro +</verb></tscreen> + +There's also a special macro to help writing recursive macros: <tt><ref +id=".EXITMACRO" name=".EXITMACRO"></tt> This command will stop macro expansion +immediately: + +<tscreen><verb> + .macro push r1, r2, r3, r4, r5, r6, r7 + .ifblank r1 + ; First parameter is empty + .exitmacro + .else + lda r1 + pha + .endif + push r2, r3, r4, r5, r6, r7 + .endmacro +</verb></tscreen> + +When expanding this macro, the expansion will push all given parameters +until an empty one is encountered. The macro may be called like this: + +<tscreen><verb> + push $20, $21, $32 ; Push 3 ZP locations + push $21 ; Push one ZP location +</verb></tscreen> + + +<sect1>Local symbols inside macros<p> + +Now, with recursive macros, <tt><ref id=".IFBLANK" name=".IFBLANK"></tt> and +<tt><ref id=".PARAMCOUNT" name=".PARAMCOUNT"></tt>, what else do you need? +Have a look at the inc16 macro above. Here is it again: + +<tscreen><verb> + .macro inc16 addr + clc + lda addr + adc #$01 + sta addr + lda addr+1 + adc #$00 + sta addr+1 + .endmacro +</verb></tscreen> + +If you have a closer look at the code, you will notice, that it could be +written more efficiently, like this: + +<tscreen><verb> + .macro inc16 addr + inc addr + bne Skip + inc addr+1 + Skip: + .endmacro +</verb></tscreen> + +But imagine what happens, if you use this macro twice? Since the label "Skip" +has the same name both times, you get a "duplicate symbol" error. Without a +way to circumvent this problem, macros are not as useful, as they could be. +One possible solution is the command <tt><ref id=".LOCAL" name=".LOCAL"></tt>. +It declares one or more symbols as local to the macro expansion. The names of +local variables are replaced by a unique name in each separate macro +expansion. So we can solve the problem above by using <tt/.LOCAL/: + +<tscreen><verb> + .macro inc16 addr + .local Skip ; Make Skip a local symbol + inc addr + bne Skip + inc addr+1 + Skip: ; Not visible outside + .endmacro +</verb></tscreen> + +Another solution is of course to start a new lexical block inside the macro +that hides any labels: + +<tscreen><verb> + .macro inc16 addr + .proc + inc addr + bne Skip + inc addr+1 + Skip: + .endproc + .endmacro +</verb></tscreen> + + +<sect1>C style macros<p> + +Starting with version 2.5 of the assembler, there is a second macro type +available: C style macros using the <tt/.DEFINE/ directive. These macros are +similar to the classic macro type described above, but behaviour is sometimes +different: + +<itemize> + +<item> Macros defined with <tt><ref id=".DEFINE" name=".DEFINE"></tt> may not + span more than a line. You may use line continuation (see <tt><ref + id=".LINECONT" name=".LINECONT"></tt>) to spread the definition over + more than one line for increased readability, but the macro itself + may not contain an end-of-line token. + +<item> Macros defined with <tt><ref id=".DEFINE" name=".DEFINE"></tt> share + the name space with classic macros, but they are detected and replaced + at the scanner level. While classic macros may be used in every place, + where a mnemonic or other directive is allowed, <tt><ref id=".DEFINE" + name=".DEFINE"></tt> style macros are allowed anywhere in a line. So + they are more versatile in some situations. + +<item> <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros may take + parameters. While classic macros may have empty parameters, this is + not true for <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros. + For this macro type, the number of actual parameters must match + exactly the number of formal parameters. + + To make this possible, formal parameters are enclosed in braces when + defining the macro. If there are no parameters, the empty braces may + be omitted. + +<item> Since <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros may not + contain end-of-line tokens, there are things that cannot be done. They + may not contain several processor instructions for example. So, while + some things may be done with both macro types, each type has special + usages. The types complement each other. + +</itemize> + +Let's look at a few examples to make the advantages and disadvantages +clear. + +To emulate assemblers that use "<tt/EQU/" instead of "<tt/=/" you may use the +following <tt/.DEFINE/: + +<tscreen><verb> + .define EQU = + + foo EQU $1234 ; This is accepted now +</verb></tscreen> + +You may use the directive to define string constants used elsewhere: + +<tscreen><verb> + ; Define the version number + .define VERSION "12.3a" + + ; ... and use it + .asciiz VERSION +</verb></tscreen> + +Macros with parameters may also be useful: + +<tscreen><verb> + .define DEBUG(message) .out message + + DEBUG "Assembling include file #3" +</verb></tscreen> + +Note that, while formal parameters have to be placed in braces, this is +not true for the actual parameters. Beware: Since the assembler cannot +detect the end of one parameter, only the first token is used. If you +don't like that, use classic macros instead: + +<tscreen><verb> + .macro DEBUG message + .out message + .endmacro +</verb></tscreen> + +(This is an example where a problem can be solved with both macro types). + + +<sect1>Characters in macros<p> + +When using the <ref id="option-t" name="-t"> option, characters are translated +into the target character set of the specific machine. However, this happens +as late as possible. This means that strings are translated if they are part +of a <tt><ref id=".BYTE" name=".BYTE"></tt> or <tt><ref id=".ASCIIZ" +name=".ASCIIZ"></tt> command. Characters are translated as soon as they are +used as part of an expression. + +This behaviour is very intuitive outside of macros but may be confusing when +doing more complex macros. If you compare characters against numeric values, +be sure to take the translation into account. + + +<sect1>Deleting macros<p> + +Macros can be deleted. This will not work if the macro that should be deleted +is currently expanded as in the following non working example: + +<tscreen><verb> + .macro notworking + .delmacro notworking + .endmacro + + notworking ; Will not work +</verb></tscreen> + +The commands to delete classic and define style macros differ. Classic macros +can be deleted by use of <tt><ref id=".DELMACRO" name=".DELMACRO"></tt>, while +for <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros, <tt><ref +id=".UNDEFINE" name=".UNDEFINE"></tt> must be used. Example: + +<tscreen><verb> + .define value 1 + .macro mac + .byte 2 + .endmacro + + .byte value ; Emit one byte with value 1 + mac ; Emit another byte with value 2 + + .undefine value + .delmacro mac + + .byte value ; Error: Unknown identifier + mac ; Error: Missing ":" +</verb></tscreen> + +A separate command for <tt>.DEFINE</tt> style macros was necessary, because +the name of such a macro is replaced by its replacement list on a very low +level. To get the actual name, macro replacement has to be switched off when +reading the argument to <tt>.UNDEFINE</tt>. This does also mean that the +argument to <tt>.UNDEFINE</tt> is not allowed to come from another +<tt>.DEFINE</tt>. All this is not necessary for classic macros, so having two +different commands increases flexibility. + + +<sect>Macro packages<label id="macropackages"><p> + +Using the <tt><ref id=".MACPACK" name=".MACPACK"></tt> directive, predefined +macro packages may be included with just one command. Available macro packages +are: + + +<sect1><tt>.MACPACK generic</tt><p> + +This macro package defines macros that are useful in almost any program. +Currently defined macros are: + +<tscreen><verb> + .macro add Arg + clc + adc Arg + .endmacro + + .macro sub Arg + sec + sbc Arg + .endmacro + + .macro bge Arg + bcs Arg + .endmacro + + .macro blt Arg + bcc Arg + .endmacro + + .macro bgt Arg + .local L + beq L + bcs Arg + L: + .endmacro + + .macro ble Arg + beq Arg + bcc Arg + .endmacro + + .macro bnz Arg + bne Arg + .endmacro + + .macro bze Arg + beq Arg + .endmacro + +</verb></tscreen> + + +<sect1><tt>.MACPACK longbranch</tt><p> + +This macro package defines long conditional jumps. They are named like the +short counterpart but with the 'b' replaced by a 'j'. Here is a sample +definition for the "<tt/jeq/" macro, the other macros are built using the same +scheme: + +<tscreen><verb> + .macro jeq Target + .if .def(Target) .and ((*+2)-(Target) <= 127) + beq Target + .else + bne *+5 + jmp Target + .endif + .endmacro +</verb></tscreen> + +All macros expand to a short branch, if the label is already defined (back +jump) and is reachable with a short jump. Otherwise the macro expands to a +conditional branch with the branch condition inverted, followed by an absolute +jump to the actual branch target. + +The package defines the following macros: + +<tscreen><verb> + jeq, jne, jmi, jpl, jcs, jcc, jvs, jvc +</verb></tscreen> + + + +<sect1><tt>.MACPACK atari</tt><p> + +This macro package defines a macro named <tt/scrcode/. It takes a string +as argument and places this string into memory translated into screen codes. + + +<sect1><tt>.MACPACK cbm</tt><p> + +This macro package defines a macro named <tt/scrcode/. It takes a string +as argument and places this string into memory translated into screen codes. + + +<sect1><tt>.MACPACK cpu</tt><p> + +This macro package does not define any macros but constants used to examine +the value read from the <tt/<ref id=".CPU" name=".CPU">/ pseudo variable. For +each supported CPU a constant similar to + +<tscreen><verb> + CPU_6502 + CPU_65SC02 + CPU_65C02 + CPU_65816 + CPU_SWEET16 + CPU_HUC6280 +</verb></tscreen> + +is defined. These constants may be used to determine the exact type of the +currently enabled CPU. In addition to that, for each CPU instruction set, +another constant is defined: + +<tscreen><verb> + CPU_ISET_6502 + CPU_ISET_65SC02 + CPU_ISET_65C02 + CPU_ISET_65816 + CPU_ISET_SWEET16 + CPU_ISET_HUC6280 +</verb></tscreen> + +The value read from the <tt/<ref id=".CPU" name=".CPU">/ pseudo variable may +be checked with <tt/<ref id="operators" name=".BITAND">/ to determine if the +currently enabled CPU supports a specific instruction set. For example the +65C02 supports all instructions of the 65SC02 CPU, so it has the +<tt/CPU_ISET_65SC02/ bit set in addition to its native <tt/CPU_ISET_65C02/ +bit. Using + +<tscreen><verb> + .if (.cpu .bitand CPU_ISET_65SC02) + lda (sp) + .else + ldy #$00 + lda (sp),y + .endif +</verb></tscreen> + +it is possible to determine if the + +<tscreen><verb> + lda (sp) +</verb></tscreen> + +instruction is supported, which is the case for the 65SC02, 65C02 and 65816 +CPUs (the latter two are upwards compatible to the 65SC02). + + +<sect1><tt>.MACPACK module</tt><p> + +This macro package defines a macro named <tt/module_header/. It takes an +identifier as argument and is used to define the header of a module both +in the dynamic and static variant. + + + +<sect>Predefined constants<label id="predefined-constants"><p> + +For better orthogonality, the assembler defines similar symbols as the +compiler, depending on the target system selected: + +<itemize> +<item><tt/__APPLE2__/ - Target system is <tt/apple2/ or <tt/apple2enh/ +<item><tt/__APPLE2ENH__/ - Target system is <tt/apple2enh/ +<item><tt/__ATARI5200__/ - Target system is <tt/atari5200/ +<item><tt/__ATARI__/ - Target system is <tt/atari/ or <tt/atarixl/ +<item><tt/__ATARIXL__/ - Target system is <tt/atarixl/ +<item><tt/__ATMOS__/ - Target system is <tt/atmos/ +<item><tt/__BBC__/ - Target system is <tt/bbc/ +<item><tt/__C128__/ - Target system is <tt/c128/ +<item><tt/__C16__/ - Target system is <tt/c16/ or <tt/plus4/ +<item><tt/__C64__/ - Target system is <tt/c64/ +<item><tt/__CBM__/ - Target is a Commodore system +<item><tt/__CBM510__/ - Target system is <tt/cbm510/ +<item><tt/__CBM610__/ - Target system is <tt/cbm610/ +<item><tt/__GEOS__/ - Target is a GEOS system +<item><tt/__GEOS_APPLE__/ - Target system is <tt/geos-apple/ +<item><tt/__GEOS_CBM__/ - Target system is <tt/geos-cbm/ +<item><tt/__LUNIX__/ - Target system is <tt/lunix/ +<item><tt/__LYNX__/ - Target system is <tt/lynx/ +<item><tt/__NES__/ - Target system is <tt/nes/ +<item><tt/__PET__/ - Target system is <tt/pet/ +<item><tt/__PLUS4__/ - Target system is <tt/plus4/ +<item><tt/__SIM6502__/ - Target system is <tt/sim6502/ +<item><tt/__SIM65C02__/ - Target system is <tt/sim65c02/ +<item><tt/__SUPERVISION__/ - Target system is <tt/supervision/ +<item><tt/__VIC20__/ - Target system is <tt/vic20/ +</itemize> + + +<sect>Structs and unions<label id="structs"><p> + +<sect1>Structs and unions Overview<p> + +Structs and unions are special forms of <ref id="scopes" name="scopes">. They +are to some degree comparable to their C counterparts. Both have a list of +members. Each member allocates storage and may optionally have a name, which, +in case of a struct, is the offset from the beginning and, in case of a union, +is always zero. + + +<sect1>Declaration<p> + +Here is an example for a very simple struct with two members and a total size +of 4 bytes: + +<tscreen><verb> + .struct Point + xcoord .word + ycoord .word + .endstruct +</verb></tscreen> + +A union shares the total space between all its members, its size is the same +as that of the largest member. The offset of all members relative to the union +is zero. + +<tscreen><verb> + .union Entry + index .word + ptr .addr + .endunion +</verb></tscreen> + +A struct or union must not necessarily have a name. If it is anonymous, no +local scope is opened, the identifiers used to name the members are placed +into the current scope instead. + +A struct may contain unnamed members and definitions of local structs. The +storage allocators may contain a multiplier, as in the example below: + +<tscreen><verb> + .struct Circle + .struct Point + .word 2 ; Allocate two words + .endstruct + Radius .word + .endstruct +</verb></tscreen> + + +<sect1>The <tt/.TAG/ keyword<p> + +Using the <ref id=".TAG" name=".TAG"> keyword, it is possible to reserve space +for an already defined struct or unions within another struct: + +<tscreen><verb> + .struct Point + xcoord .word + ycoord .word + .endstruct + + .struct Circle + Origin .tag Point + Radius .byte + .endstruct +</verb></tscreen> + +Space for a struct or union may be allocated using the <ref id=".TAG" +name=".TAG"> directive. + +<tscreen><verb> + C: .tag Circle +</verb></tscreen> + +Currently, members are just offsets from the start of the struct or union. To +access a field of a struct, the member offset has to be added to the address +of the struct itself: + +<tscreen><verb> + lda C+Circle::Radius ; Load circle radius into A +</verb></tscreen> + +This may change in a future version of the assembler. + + +<sect1>Limitations<p> + +Structs and unions are currently implemented as nested symbol tables (in fact, +they were a by-product of the improved scoping rules). Currently, the +assembler has no idea of types. This means that the <ref id=".TAG" +name=".TAG"> keyword will only allocate space. You won't be able to initialize +variables declared with <ref id=".TAG" name=".TAG">, and adding an embedded +structure to another structure with <ref id=".TAG" name=".TAG"> will not make +this structure accessible by using the '::' operator. + + + +<sect>Module constructors/destructors<label id="condes"><p> + +<em>Note:</em> This section applies mostly to C programs, so the explanation +below uses examples from the C libraries. However, the feature may also be +useful for assembler programs. + + +<sect1>Module constructors/destructors Overview<p> + +Using the <tt><ref id=".CONSTRUCTOR" name=".CONSTRUCTOR"></tt>, <tt><ref +id=".DESTRUCTOR" name=".DESTRUCTOR"></tt> and <tt><ref id=".INTERRUPTOR" +name=".INTERRUPTOR"></tt> keywords it is possible to export functions in a +special way. The linker is able to generate tables with all functions of a +specific type. Such a table will <em>only</em> include symbols from object +files that are linked into a specific executable. This may be used to add +initialization and cleanup code for library modules, or a table of interrupt +handler functions. + +The C heap functions are an example where module initialization code is used. +All heap functions (<tt>malloc</tt>, <tt>free</tt>, ...) work with a few +variables that contain the start and the end of the heap, pointers to the free +list and so on. Since the end of the heap depends on the size and start of the +stack, it must be initialized at runtime. However, initializing these +variables for programs that do not use the heap are a waste of time and +memory. + +So the central module defines a function that contains initialization code and +exports this function using the <tt/.CONSTRUCTOR/ statement. If (and only if) +this module is added to an executable by the linker, the initialization +function will be placed into the table of constructors by the linker. The C +startup code will call all constructors before <tt/main/ and all destructors +after <tt/main/, so without any further work, the heap initialization code is +called once the module is linked in. + +While it would be possible to add explicit calls to initialization functions +in the startup code, the new approach has several advantages: + +<enum> +<item> +If a module is not included, the initialization code is not linked in and not +called. So you don't pay for things you don't need. + +<item> +Adding another library that needs initialization does not mean that the +startup code has to be changed. Before we had module constructors and +destructors, the startup code for all systems had to be adjusted to call the +new initialization code. + +<item> +The feature saves memory: Each additional initialization function needs just +two bytes in the table (a pointer to the function). + +</enum> + + +<sect1>Calling order<p> + +The symbols are sorted in increasing priority order by the linker when using +one of the builtin linker configurations, so the functions with lower +priorities come first and are followed by those with higher priorities. The C +library runtime subroutine that walks over the function tables calls the +functions starting from the top of the table - which means that functions with +a high priority are called first. + +So when using the C runtime, functions are called with high priority functions +first, followed by low priority functions. + + +<sect1>Pitfalls<p> + +When using these special symbols, please take care of the following: + +<itemize> + +<item> +The linker will only generate function tables, it will not generate code to +call these functions. If you're using the feature in some other than the +existing C environments, you have to write code to call all functions in a +linker generated table yourself. See the <tt/condes/ and <tt/callirq/ modules +in the C runtime for an example on how to do this. + +<item> +The linker will only add addresses of functions that are in modules linked to +the executable. This means that you have to be careful where to place the +condes functions. If initialization or an irq handler is needed for a group of +functions, be sure to place the function into a module that is linked in +regardless of which function is called by the user. + +<item> +The linker will generate the tables only when requested to do so by the +<tt/FEATURE CONDES/ statement in the linker config file. Each table has to +be requested separately. + +<item> +Constructors and destructors may have priorities. These priorities determine +the order of the functions in the table. If your initialization or cleanup code +does depend on other initialization or cleanup code, you have to choose the +priority for the functions accordingly. + +<item> +Besides the <tt><ref id=".CONSTRUCTOR" name=".CONSTRUCTOR"></tt>, <tt><ref +id=".DESTRUCTOR" name=".DESTRUCTOR"></tt> and <tt><ref id=".INTERRUPTOR" +name=".INTERRUPTOR"></tt> statements, there is also a more generic command: +<tt><ref id=".CONDES" name=".CONDES"></tt>. This allows to specify an +additional type. Predefined types are 0 (constructor), 1 (destructor) and 2 +(interruptor). The linker generates a separate table for each type on request. + +</itemize> + + +<sect>Porting sources from other assemblers<p> + +Sometimes it is necessary to port code written for older assemblers to ca65. +In some cases, this can be done without any changes to the source code by +using the emulation features of ca65 (see <tt><ref id=".FEATURE" +name=".FEATURE"></tt>). In other cases, it is necessary to make changes to the +source code. + +Probably the biggest difference is the handling of the <tt><ref id=".ORG" +name=".ORG"></tt> directive. ca65 generates relocatable code, and placement is +done by the linker. Most other assemblers generate absolute code, placement is +done within the assembler and there is no external linker. + +In general it is not a good idea to write new code using the emulation +features of the assembler, but there may be situations where even this rule is +not valid. + +<sect1>TASS<p> + +You need to use some of the ca65 emulation features to simulate the behaviour +of such simple assemblers. + +<enum> +<item>Prepare your sourcecode like this: + +<tscreen><verb> + ; if you want TASS style labels without colons + .feature labels_without_colons + + ; if you want TASS style character constants + ; ("a" instead of the default 'a') + .feature loose_char_term + + .word *+2 ; the cbm load address + + [yourcode here] +</verb></tscreen> + +notice that the two emulation features are mostly useful for porting +sources originally written in/for TASS, they are not needed for the +actual "simple assembler operation" and are not recommended if you are +writing new code from scratch. + +<item>Replace all program counter assignments (which are not possible in ca65 +by default, and the respective emulation feature works different from what +you'd expect) by another way to skip to memory locations, for example the +<tt><ref id=".RES" name=".RES"></tt> directive. + +<tscreen><verb> + ; *=$2000 + .res $2000-* ; reserve memory up to $2000 +</verb></tscreen> + +Please note that other than the original TASS, ca65 can never move the program +counter backwards - think of it as if you are assembling to disk with TASS. + +<item>Conditional assembly (<tt/.ifeq//<tt/.endif//<tt/.goto/ etc.) must be +rewritten to match ca65 syntax. Most importantly notice that due to the lack +of <tt/.goto/, everything involving loops must be replaced by +<tt><ref id=".REPEAT" name=".REPEAT"></tt>. + +<item>To assemble code to a different address than it is executed at, use the +<tt><ref id=".ORG" name=".ORG"></tt> directive instead of +<tt/.offs/-constructs. + +<tscreen><verb> + .org $1800 + + [floppy code here] + + .reloc ; back to normal +</verb></tscreen> + +<item>Then assemble like this: + +<tscreen><verb> + cl65 --start-addr 0x0ffe -t none myprog.s -o myprog.prg +</verb></tscreen> + +Note that you need to use the actual start address minus two, since two bytes +are used for the cbm load address. + +</enum> + + +<sect>Copyright<p> + +ca65 (and all cc65 binutils) are (C) Copyright 1998-2003 Ullrich von +Bassewitz. For usage of the binaries and/or sources the following +conditions do apply: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + + + +</article> + + + diff --git a/doc/cbm510.sgml b/doc/cbm510.sgml new file mode 100644 index 000000000..c24eba142 --- /dev/null +++ b/doc/cbm510.sgml @@ -0,0 +1,328 @@ +<!doctype linuxdoc system> + +<article> + +<title>Commodore 510 (aka P500) specific information for cc65 +<author> +<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> +<url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal">,<newline> +<url url="mailto:greg.king5@verizon.net" name="Greg King"> +<date>2014-04-25 + +<abstract> +An overview over the Commodore 510 runtime system as it is implemented for the +cc65 C compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the CBM 510 runtime system as it comes with +the cc65 C compiler. It describes the memory layout, CBM 510-specific header +files, available drivers, and any pitfalls specific to that platform. + +Please note that CBM 510-specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + +In addition to the Commodore 510 (named P128 in the U.S.), no other +machines are supported by this cc65 target. + + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the Commodore +510 target is a machine language program with a one-line BASIC stub, which +transfers control to the machine language running in bank 0. That means that a +program can be loaded as a BASIC program, and started with RUN. It is, of course, +possible to change that behaviour by using a modified startup file and linker +config. + + + +<sect>Memory layout<p> + +cc65 generated programs for the Commodore 510 run in bank 0, the memory bank +reserved for BASIC programs. Since there are no ROMs in this memory bank, +kernal subroutines are either emulated or called by bank switching, which has +the disadvantage of being slow compared to a direct call. + +The default memory configuration for the CBM 510 allocates all memory between +$0002 and $FFF0 in bank 0 for the compiled program. Some space +in low memory is lost, because a separate hardware stack is set up in page 1, +and the kernal replacement functions need some more memory locations. A few +more pages are lost in high memory, because the runtime sets up a copy of the +character ROM, a text screen, and a CBM-compatible jump table at $FF81. +The main startup code is located at $0400, so about 54K of the complete +bank are actually usable for applications. + +Special locations: + +<descrip> + <tag/Stack/ + The C runtime stack is located at $FF81, and grows downwards. + + <tag/Heap/ + The C heap is located at the end of the program, and grows towards the C + runtime stack. +</descrip><p> + + + +<sect>Platform-specific header files<p> + +Programs containing CBM 510-specific code may use the <tt/cbm510.h/ or +<tt/cbm.h/ header files. Using the later may be an option when writing code +for more than one CBM platform, since it includes <tt/cbm510.h/, and declares +several functions common to all CBM platforms. + +<sect1>CBM 510-specific functions<p> + +The functions listed below are special for the CBM 510. See the <url +url="funcref.html" name="function reference"> for declaration and usage. + +<itemize> +<item>peekbsys +<item>peekwsys +<item>pokebsys +<item>pokewsys +</itemize> + + +<sect1>CBM-specific functions<p> + +Some functions are available for all (or at least most) of the Commodore +machines. See the <url url="funcref.html" name="function reference"> for +declaration and usage. + + +<itemize> +<item>cbm_close +<item>cbm_closedir +<item>cbm_k_setlfs +<item>cbm_k_setnam +<item>cbm_k_load +<item>cbm_k_save +<item>cbm_k_open +<item>cbm_k_close +<item>cbm_k_readst +<item>cbm_k_chkin +<item>cbm_k_ckout +<item>cbm_k_basin +<item>cbm_k_bsout +<item>cbm_k_clrch +<item>cbm_load +<item>cbm_open +<item>cbm_opendir +<item>cbm_read +<item>cbm_readdir +<item>cbm_save +<item>cbm_write +<item>get_tv +</itemize> + + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/cbm510.h/ header file do +allow access to hardware located in the address space. Some variables are +structures; accessing the struct fields will access the chip registers. + +<em/Note:/ All I/O chips are located in the system bank (bank 15); and can +therefore not be accessed like on other platforms. Please use one of the +<tt/peekbsys/, <tt/peekwsys/, <tt/pokebsys/, and <tt/pokewsys/ functions to +access the I/O chips. Direct reads and writes to the structures named below +will <em>not</em> work! + +<descrip> + + <tag><tt/VIC/</tag> + The <tt/VIC/ structure allows access to the VIC II (the graphics + controller). See the <tt/_vic2.h/ header file located in the include + directory for the declaration of the structure. + + <tag><tt/SID/</tag> + The <tt/SID/ structure allows access to the SID (the sound interface + device). See the <tt/_sid.h/ header file located in the include directory + for the declaration of the structure. + + <tag><tt/ACIA/</tag> + Access to the ACIA (the RS232 chip) is available via the <tt/ACIA/ variable. + See the <tt/_6551.h/ header file located in the include directory for the + declaration of the structure. + + <tag><tt/CIA/</tag> + Access to the CIA chip is available via the <tt/CIA/ variable. See the + <tt/_6526.h/ header file located in the include directory for the + declaration of the structure. + + <tag><tt/TPI1, TPI2/</tag> + The two 6525 triport chips may be accessed by using these variables. See the + <tt/_6525.h/ header file located in the include directory for the + declaration of the structure. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +No graphics drivers are currently available for the Commodore 510. + + +<sect1>Extended memory drivers<p> + +<descrip> + <tag><tt/cbm510-ram.emd (cbm510_ram_emd)/</tag> + A driver for the RAM in bank 1. Supports up to 255 pages with 256 bytes + each. +</descrip><p> + + +<sect1>Joystick drivers<p> + +<descrip> + + <tag><tt/cbm510-std.joy (cbm510_std_joy)/</tag> + Supports up to two standard joysticks connected to the joysticks ports of + the Commodore 510. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +The default drivers, <tt/mouse_stddrv (mouse_static_stddrv)/, point to <tt/cbm510-joy.mou (cbm510_joy_mou)/. + +<descrip> + + <tag><tt/cbm510-joy.mou (cbm510_joy_mou)/</tag> + Supports a mouse that is emulated by a standard joystick, e.g. 1350 + mouse, in joystick port #2 of the CBM510. That stick's fire button acts as + the left mouse button. The fire button of a stick in joystick port #1 can + act as the right mouse button. + + <tag><tt/cbm510-inkwl.mou (cbm510_inkwl_mou)/</tag> + Supports the Inkwell Systems lightpens, connected to port #1 of the CBM510. + It can read both the 170-C and one button of the 184-C pens. (It can + read other lightpens and light-guns that send their button signal to the + joystick left-button pin.) + +</descrip><p> + + +<sect1>RS232 device drivers<p> + +<descrip> + + <tag><tt/cbm510-std.ser (cbm510_std_ser)/</tag> + Driver for the 6551 ACIA chip built into the Commodore 510. Supports up to + 19200 BPS, hardware flow control (RTS/CTS), and interrupt-driven receives. + Note that, because of the peculiarities of the 6551 chip, transmits are not + interrupt driven; and, the transceiver blocks if the receiver asserts flow + control because of a full buffer. + +</descrip><p> + + + +<sect>Limitations<label id="limitations"><p> + + +<sect1>Kernal and hardware access<p> + +Since the program runs in bank 0, and the kernal and all I/O chips are located +in bank 15, calling ROM routines or accessing hardware needs special code. The +cc65 runtime implements wrappers for all functions in the kernal jump table. +While this simplifies things, it should be noted that the wrappers do have +quite an impact on performance: A cross-bank call has an extra 300µs +penalty added by the wrapper. + + +<sect1>Interrupts<p> + +Compiled programs contain an interrupt handler that runs in the program bank. +This has several advantages, one of them being performance (see cross-bank +call overhead mentioned above). However, this introduces one problem: +Interrupts are lost while the CPU executes code in the kernal bank. As a +result, the clock may go wrong; and (worse), serial interrupts may get lost. + +Since the cc65 runtime does only call the kernal for disk I/O, this means that +a program should not do file I/O while it depends on interrupts. + + + +<sect>Other hints<p> + + +<sect1>Passing arguments to the program<p> + +Command-line arguments can be passed to <tt/main()/. Since that is not +supported directly by BASIC, the following syntax was chosen: + +<tscreen><verb> + RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 +</verb></tscreen> + +<enum> +<item>Arguments are separated by spaces. +<item>Arguments may be quoted. +<item>Leading and trailing spaces around an argument are ignored. Spaces within + a quoted argument are allowed. +<item>The first argument passed to <tt/main()/ is the program name. +<item>A maximum number of 10 arguments (including the program name) are + supported. +</enum> + + +<sect1>Program return code<p> + +The program return code (signed char) is passed back to BASIC by use of the +<tt/ST/ variable. + + +<sect1>Interrupt handlers<p> + +The runtime for the Commodore 510 uses routines marked as <tt/.INTERRUPTOR/ +for interrupt handlers. Such routines must be written as simple machine +language subroutines and will be called automatically by the interrupt handler +code when they are linked into a program. See the discussion of the +<tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/cbm610.sgml b/doc/cbm610.sgml new file mode 100644 index 000000000..790983b3d --- /dev/null +++ b/doc/cbm610.sgml @@ -0,0 +1,310 @@ +<!doctype linuxdoc system> + +<article> + +<title>Commodore 610-specific information for cc65 +<author> +<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> +<url url="mailto:greg.king5@verizon.net" name="Greg King"> +<date>2014-04-25 + +<abstract> +An overview over the Commodore 610 runtime system as it is implemented for the +cc65 C compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the CBM 610 runtime system as it comes with +the cc65 C compiler. It describes the memory layout, CBM 610-specific header +files, available drivers, and any pitfalls specific to that platform. + +Please note that CBM 610-specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + +In addition to the Commodore 610 (named B40 in the U.S.), several other +machines are supported by this cc65 target, since they have identical +hardware: The Commodore 620 and 630 (more memory, additional coprocessor +card), and the Commodore 710, 720, and 730 (same hardware in another case with +a built-in monitor). + + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the Commodore +610 target is a machine language program with a one-line BASIC stub, which +transfers control to the machine language running in bank 1. That means that a +program can be loaded as a BASIC program, and started with RUN. It is, of course, +possible to change that behaviour by using a modified startup file and linker +config. + + + +<sect>Memory layout<p> + +cc65 generated programs for the Commodore 610 run in bank 1, the memory bank +reserved for BASIC programs. Since there are no ROMs in this memory bank, +kernal subroutines are either emulated or called by bank switching, which has +the disadvantage of being slow compared to a direct call. + +The default memory configuration for the CBM 610 allocates all memory between +$0002 and $FFF0 in bank 1 for the compiled program. Some space +in low memory is lost, because a separate hardware stack is set up in page 1, +and the kernal replacement functions need some more memory locations. A few +more bytes are lost in high memory, because the runtime sets up a CBM-compatible +jump table at $FF81. The main startup code is located at +$0400, so about 63K of the complete bank are actually usable for +applications. + +Special locations: + +<descrip> + <tag/Stack/ + The C runtime stack is located at $FF81, and grows downwards. + + <tag/Heap/ + The C heap is located at the end of the program, and grows towards the C + runtime stack. +</descrip><p> + + + +<sect>Platform-specific header files<p> + +Programs containing CBM 610-specific code may use the <tt/cbm610.h/ or +<tt/cbm.h/ header files. Using the later may be an option when writing code +for more than one CBM platform, since it includes <tt/cbm610.h/, and declares +several functions common to all CBM platforms. + + +<sect1>CBM 610-specific functions<p> + +The functions listed below are special for the CBM 610. See the <url +url="funcref.html" name="function reference"> for declaration and usage. + +<itemize> +<item>peekbsys +<item>peekwsys +<item>pokebsys +<item>pokewsys +</itemize> + + +<sect1>CBM-specific functions<p> + +Some functions are available for all (or at least most) of the Commodore +machines. See the <url url="funcref.html" name="function reference"> for +declaration and usage. + + +<itemize> +<item>cbm_close +<item>cbm_closedir +<item>cbm_k_setlfs +<item>cbm_k_setnam +<item>cbm_k_load +<item>cbm_k_save +<item>cbm_k_open +<item>cbm_k_close +<item>cbm_k_readst +<item>cbm_k_chkin +<item>cbm_k_ckout +<item>cbm_k_basin +<item>cbm_k_bsout +<item>cbm_k_clrch +<item>cbm_load +<item>cbm_open +<item>cbm_opendir +<item>cbm_read +<item>cbm_readdir +<item>cbm_save +<item>cbm_write +<item>get_tv +</itemize> + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/cbm610.h/ header file do +allow access to hardware located in the address space. Some variables are +structures; accessing the struct fields will access the chip registers. + +<em/Note:/ All I/O chips are located in the system bank (bank 15); and can +therefore not be accessed like on other platforms. Please use one of the +<tt/peekbsys/, <tt/peekwsys/, <tt/pokebsys/, and <tt/pokewsys/ functions to +access the I/O chips. Direct reads and writes to the structures named below +will <em>not</em> work! + +<descrip> + + <tag><tt/CRTC/</tag> + The <tt/CRTC/ structure allows access to the CRTC (the video controller). + See the <tt/_6545.h/ header file located in the include directory for the + declaration of the structure. + + <tag><tt/SID/</tag> The <tt/SID/ structure allows access to the SID (the + sound interface device). See the <tt/_sid.h/ header file located in the + include directory for the declaration of the structure. + + <tag><tt/ACIA/</tag> + Access to the ACIA (the RS232 chip) is available via the <tt/ACIA/ variable. + See the <tt/_6551.h/ header file located in the include directory for the + declaration of the structure. + + <tag><tt/CIA/</tag> + Access to the CIA chip is available via the <tt/CIA/ variable. See the + <tt/_6526.h/ header file located in the include directory for the + declaration of the structure. + + <tag><tt/TPI1, TPI2/</tag> + The two 6525 triport chips may be accessed by using these variables. See the + <tt/_6525.h/ header file located in the include directory for the + declaration of the structure. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +No graphics drivers are currently available for the Commodore 610 (and since +the machine has no graphics capabilities, chances for a graphics driver aren't +really good :-). + + +<sect1>Extended memory drivers<p> + +<descrip> + <tag><tt/cbm610-ram.emd (cbm610_ram_emd)/</tag> + A driver for the RAM in bank 2. Supports up to 255 pages with 256 bytes + each. +</descrip><p> + + +<sect1>Joystick drivers<p> + +The Commodore 610 is a business machine, and doesn't have joystick ports. There +are no drivers for the non-existing ports available. + + +<sect1>Mouse drivers<p> + +No mouse drivers are currently available for the Commodore 610. + + +<sect1>RS232 device drivers<p> + +<descrip> + + <tag><tt/cbm610-std.ser (cbm610_std_ser)/</tag> + Driver for the 6551 ACIA chip built into the Commodore 610. Supports up to + 19200 BPS, hardware flow control (RTS/CTS), and interrupt-driven receives. + Note that, because of the peculiarities of the 6551 chip, transmits are not + interrupt driven; and, the transceiver blocks if the receiver asserts flow + control because of a full buffer. + +</descrip><p> + + + +<sect>Limitations<label id="limitations"><p> + + +<sect1>Kernal and hardware access<p> + +Since the program runs in bank 1, and the kernal and all I/O chips are located +in bank 15, calling ROM routines or accessing hardware needs special code. The +cc65 runtime implements wrappers for all functions in the kernal jump table. +While this simplifies things, it should be noted that the wrappers do have +quite an impact on performance: A cross-bank call has an extra 300µs +penalty added by the wrapper. + + +<sect1>Interrupts<p> + +Compiled programs contain an interrupt handler that runs in the program bank. +This has several advantages, one of them being performance (see cross-bank +call overhead mentioned above). However, this introduces one problem: +Interrupts are lost while the CPU executes code in the kernal bank. As a +result, the clock may go wrong; and (worse), serial interrupts may get lost. + +Since the cc65 runtime does only call the kernal for disk I/O, this means that +a program should not do file I/O while it depends on interrupts. + + + +<sect>Other hints<p> + + +<sect1>Passing arguments to the program<p> + +Command-line arguments can be passed to <tt/main()/. Since that is not +supported directly by BASIC, the following syntax was chosen: + +<tscreen><verb> + RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 +</verb></tscreen> + +<enum> +<item>Arguments are separated by spaces. +<item>Arguments may be quoted. +<item>Leading and trailing spaces around an argument are ignored. Spaces within + a quoted argument are allowed. +<item>The first argument passed to <tt/main()/ is the program name. +<item>A maximum number of 10 arguments (including the program name) are + supported. +</enum> + + +<sect1>Program return code<p> + +The program return code (low byte) is passed back to BASIC by use of the +<tt/ST/ variable. + + +<sect1>Interrupt handlers<p> + +The runtime for the Commodore 610 uses routines marked as <tt/.INTERRUPTOR/ +for interrupt handlers. Such routines must be written as simple machine +language subroutines and will be called automatically by the interrupt handler +code when they are linked into a program. See the discussion of the +<tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/cc65.sgml b/doc/cc65.sgml new file mode 100644 index 000000000..a6b4a07ee --- /dev/null +++ b/doc/cc65.sgml @@ -0,0 +1,1393 @@ +<!doctype linuxdoc system> + +<article> +<title>cc65 Users Guide +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2000-09-03, 2001-10-02, 2005-08-01 + +<abstract> +cc65 is a C compiler for 6502 targets. It supports several 6502 based home +computers like the Commodore and Atari machines, but it is easily retargetable. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + + +<sect>Overview<p> + +cc65 was originally a C compiler for the Atari 8-bit machines written by +John R. Dunning. In prior releases I've described the compiler by listing +up the changes made by me. I have made many more changes in the meantime +(and rewritten major parts of the compiler), so I will no longer do that, +since the list would be too large and of no use to anyone. Instead I will +describe the compiler in respect to the ANSI/ISO C standard. + +There are separate documents named <url url="library.html"> and <url +url="funcref.html"> that cover the library that is available for the compiler. +If you know C, and are interested in doing actual programming, the library +documentation is probably of much more use than this document. + +If you need some hints for getting the best code out of the compiler, you +may have a look at <url url="coding.html"> which covers some code generation +issues. + + + +<sect>Usage<p> + +The compiler translates C files into files containing assembly code that +may be translated by the ca65 macroassembler (for more information about +the assembler, have a look at <url url="ca65.html">). + + +<sect1>Command line option overview<p> + +The compiler may be called as follows: + +<tscreen><verb> +--------------------------------------------------------------------------- +Usage: cc65 [options] file +Short options: + -Cl Make local variables static + -Dsym[=defn] Define a symbol + -E Stop after the preprocessing stage + -I dir Set an include directory search path + -O Optimize code + -Oi Optimize code, inline more code + -Or Enable register variables + -Os Inline some known functions + -T Include source as comment + -V Print the compiler version number + -W warning[,...] Suppress warnings + -d Debug mode + -g Add debug info to object file + -h Help (this text) + -j Default characters are signed + -mm model Set the memory model + -o name Name the output file + -r Enable register variables + -t sys Set the target system + -v Increase verbosity + +Long options: + --add-source Include source as comment + --bss-name seg Set the name of the BSS segment + --check-stack Generate stack overflow checks + --code-name seg Set the name of the CODE segment + --codesize x Accept larger code by factor x + --cpu type Set cpu type (6502, 65c02) + --create-dep name Create a make dependency file + --create-full-dep name Create a full make dependency file + --data-name seg Set the name of the DATA segment + --debug Debug mode + --debug-info Add debug info to object file + --debug-opt name Debug optimization steps + --dep-target target Use this dependency target + --disable-opt name Disable an optimization step + --enable-opt name Enable an optimization step + --help Help (this text) + --include-dir dir Set an include directory search path + --list-opt-steps List all optimizer steps and exit + --list-warnings List available warning types for -W + --local-strings Emit string literals immediately + --memory-model model Set the memory model + --register-space b Set space available for register variables + --register-vars Enable register variables + --rodata-name seg Set the name of the RODATA segment + --signed-chars Default characters are signed + --standard std Language standard (c89, c99, cc65) + --static-locals Make local variables static + --target sys Set the target system + --verbose Increase verbosity + --version Print the compiler version number + --writable-strings Make string literals writable +--------------------------------------------------------------------------- +</verb></tscreen> + + +<sect1>Command line options in detail<p> + +Here is a description of all the command line options: + +<descrip> + + <label id="option-bss-name"> + <tag><tt>--bss-name seg</tt></tag> + + Set the name of the bss segment. See also <tt/<ref id="pragma-bss-name" + name="#pragma bss-name">/. + + + <label id="option-check-stack"> + <tag><tt>--check-stack</tt></tag> + + Tells the compiler to generate code that checks for stack overflows. See + <tt/<ref id="pragma-check-stack" name="#pragma check-stack">/ for an + explanation of this feature. + + + <label id="option-code-name"> + <tag><tt>--code-name seg</tt></tag> + + Set the name of the code segment. See also <tt/<ref id="pragma-code-name" + name="#pragma code-name">/ + + + <label id="option-codesize"> + <tag><tt>--codesize x</tt></tag> + + This options allows finer control about speed vs. size decisions in the code + generation and optimization phases. It gives the allowed size increase + factor (in percent). The default is 100 when not using <tt/-Oi/ and 200 when + using <tt/-Oi/ (<tt/-Oi/ is the same as <tt/-O --codesize 200/). + + + <label id="option--cpu"> + <tag><tt>--cpu CPU</tt></tag> + + Set the CPU, the compiler generates code for. You may specify "6502" or + "65C02" as the CPU. The default depends on the selected target (see option + <tt/<ref id="option-t" name="-t">/). It is the 6502 CPU for most targets or + if no target has been set. Specifying 65C02 will use a few 65C02 + instructions when generating code. Don't expect too much from this option: + In most cases the difference in size and speed is just 1-2%. + + + <label id="option-create-dep"> + <tag><tt>--create-dep name</tt></tag> + + Tells the compiler to generate a file containing the dependency list for the + compiled module in makefile syntax. The output is written to a file with the + given name. The output does not include system include files (in angle + brackets). + + + <label id="option-create-full-dep"> + <tag><tt>--create-full-dep name</tt></tag> + + Tells the compiler to generate a file containing the dependency list for the + compiled module in makefile syntax. The output is written to a file with the + given name. The output does include system include files (in angle + brackets). + + + <label id="option-data-name"> + <tag><tt>--data-name seg</tt></tag> + + Set the name of the data segment. See also <tt/<ref id="pragma-data-name" + name="#pragma data-name">/ + + + <tag><tt>-d, --debug</tt></tag> + + Enables debug mode, something that should not be needed for mere + mortals:-) + + + <label id="option-dep-target"> + <tag><tt>--dep-target target</tt></tag> + + When generating a dependency file, don't use the actual output file as the + target of the dependency, but the file specified with this option. The + option has no effect if neither <tt/<ref id="option-create-dep" + name="--create-dep">/ nor <tt/<ref id="option-create-full-dep" + name="--create-full-dep">/ is specified. + + + <tag><tt>-D sym[=definition]</tt></tag> + + Define a macro on the command line. If no definition is given, the macro + is defined to the value "1". + + + <tag><tt>-g, --debug-info</tt></tag> + + This will cause the compiler to insert a <tt/.DEBUGINFO/ command into the + generated assembler code. This will cause the assembler to include all + symbols in a special section in the object file. + + + <tag><tt>-h, --help</tt></tag> + + Print the short option summary shown above. + + + <label id="option-list-warnings"> + <tag><tt>--list-warnings</tt></tag> + + List the names of warning types available for use with <tt><ref + id="option-W" name="-W"></tt>. + + + <label id="option-local-strings"> + <tag><tt>--local-strings</tt></tag> + + Emit string literals into the rodata segment as soon as they're encountered + in the source (even if you do nothing but get the sizeof those strings). The + default is to keep string literals until end of assembly, merge read only + literals if possible, and then output the literals into the data or rodata + segment that is active at that point. Use of this option prevents merging of + duplicate strings, but the options that change the name of one of the data + segments will work. + + You can also use <tt><ref id="pragma-local-strings" + name="#pragma local-strings"></tt> for fine grained control. + + + <tag><tt>-o name</tt></tag> + + Specify the name of the output file. If you don't specify a name, the + name of the C input file is used, with the extension replaced by ".s". + + + <label id="option-register-vars"> + <tag><tt>-r, --register-vars</tt></tag> + + <tt/-r/ will make the compiler honor the <tt/register/ keyword. Local + variables may be placed in registers (which are actually zero page + locations). There is some overhead involved with register variables, since + the old contents of the registers must be saved and restored. Since register + variables are of limited use without the optimizer, there is also a combined + switch: <tt/-Or/ will enable both, the optimizer and register variables. + + For more information about register variables see <ref id="register-vars" + name="register variables">. + + The compiler setting can also be changed within the source file by using + <tt/<ref id="pragma-register-vars" name="#pragma register-vars">/. + + + <label id="option-register-space"> + <tag><tt>--register-space</tt></tag> + + This option takes a numeric parameter and is used to specify, how much + zero page register space is available. Please note that just giving this + option will not increase or decrease by itself, it will just tell the + compiler about the available space. You will have to allocate that space + yourself using an assembler module with the necessary allocations, and a + linker configuration that matches the assembler module. The default value + for this option is 6 (bytes). + + If you don't know what all this means, please don't use this option. + + + <label id="option-rodata-name"> + <tag><tt>--rodata-name seg</tt></tag> + + Set the name of the rodata segment (the segment used for readonly data). + See also <tt/<ref id="pragma-rodata-name" name="#pragma rodata-name">/ + + <label id="option-signed-chars"> + <tag><tt>-j, --signed-chars</tt></tag> + + Using this option, you can make the default characters signed. Since the + 6502 has no provisions for sign extending characters (which is needed on + almost any load operation), this will make the code larger and slower. A + better way is to declare characters explicitly as "signed" if needed. You + can also use <tt><ref id="pragma-signed-chars" + name="#pragma signed-chars"></tt> for better control of this option. + + + <label id="option--standard"> + <tag><tt>--standard std</tt></tag> + + This option allows to set the language standard supported. The argument is + one of + <descrip> + <tag/c89/ + This disables anything that is illegal in C89/C90. Among those things + are <tt>//</tt> comments and the non-standard keywords without + underscores. Please note that cc65 is not a fully C89 compliant compiler + despite this option. A few more things (like floats) are missing. + + <tag/c99/ + This enables a few features from the C99 standard. With this option, + <tt>//</tt> comments are allowed. It will also cause warnings and even + errors in a few situations that are allowed with <tt/--standard c89/. + For example, a call to a function without a prototype is an error in + this mode. + + <tag/cc65/ + This is the default mode. It is like c99 mode, but additional features + are enabled. Among these are "void data", non-standard keywords without + the underlines, unnamed function parameters and the requirement for + main() to return an int. + </descrip> + + Please note that the compiler does not support the C99 standard and never + will. c99 mode is actually c89 mode with a few selected C99 extensions. + + + <label id="option-t"> + <tag><tt>-t target, --target target</tt></tag> + + This option is used to set the target system. The target system determines + the character set that is used for strings and character constants and the + default CPU. The CPU setting can be overriden by use of the <tt/<ref + id="option--cpu" name="--cpu">/ option. + + The following target systems are supported: + + <itemize> + <item>none + <item>apple2 + <item>apple2enh + <item>atari + <item>atarixl + <item>atmos + <item>c16 (works also for the c116 with memory up to 32K) + <item>c64 + <item>c128 + <item>cbm510 (CBM-II series with 40 column video) + <item>cbm610 (all CBM-II II computers with 80 column video) + <item>geos-apple + <item>geos-cbm + <item>lunix + <item>lynx + <item>nes + <item>pet (all CBM PET systems except the 2001) + <item>plus4 + <item>sim6502 + <item>sim65c02 + <item>supervision + <item>vic20 + </itemize> + + <tag><tt>-v, --verbose</tt></tag> + + Using this option, the compiler will be somewhat more verbose if errors + or warnings are encountered. + + + <label id="option-writable-strings"> + <tag><tt>--writable-strings</tt></tag> + + Make string literals writable by placing them into the data segment instead + of the rodata segment. You can also use <tt><ref id="pragma-writable-strings" + name="#pragma writable-strings"></tt> to control this option from within + the source file. + + + <label id="option-static-locals"> + <tag><tt>-Cl, --static-locals</tt></tag> + + Use static storage for local variables instead of storage on the stack. + Since the stack is emulated in software, this gives shorter and usually + faster code, but the code is no longer reentrant. The difference between + <tt/-Cl/ and declaring local variables as static yourself is, that + initializer code is executed each time, the function is entered. So when + using + + <tscreen><verb> + void f (void) + { + unsigned a = 1; + ... + } + </verb></tscreen> + + the variable <tt/a/ will always have the value <tt/1/ when entering the + function and using <tt/-Cl/, while in + + <tscreen><verb> + void f (void) + { + static unsigned a = 1; + .... + } + </verb></tscreen> + + the variable <tt/a/ will have the value <tt/1/ only the first time that the + function is entered, and will keep the old value from one call of the + function to the next. + + You may also use <tt><ref id="pragma-static-locals" + name="#pragma static-locals"></tt> to change this setting in your + sources. + + + <label id="option-include-dir"> + <tag><tt>-I dir, --include-dir dir</tt></tag> + + Set a directory where the compiler searches for include files. You may + use this option multiple times to add more than one directory to the + search list. + + + <label id="option-O"> + <tag><tt>-O, -Oi, -Or, -Os</tt></tag> + + Enable an optimizer run over the produced code. + + Using <tt/-Oi/, the code generator will inline some code where otherwise a + runtime functions would have been called, even if the generated code is + larger. This will not only remove the overhead for a function call, but will + make the code visible for the optimizer. <tt/-Oi/ is an alias for + <tt/-O --codesize 200/. + + <tt/-Or/ will make the compiler honor the <tt/register/ keyword. Local + variables may be placed in registers (which are actually zero page + locations). See also the <tt/<ref id="option-register-vars" + name="--register-vars">/ command line option, and the <ref + id="register-vars" name="discussion of register variables"> below. + + Using <tt/-Os/ will force the compiler to inline some known functions from + the C library like strlen. Note: This has two consequences: + <p> + <itemize> + <item>You may not use names of standard C functions in your own code. If you + do that, your program is not standard compliant anyway, but using + <tt/-Os/ will actually break things. + <p> + <item>The inlined string and memory functions will not handle strings or + memory areas larger than 255 bytes. Similarly, the inlined <tt/is..()/ + functions will not work with values outside the char. range (such as + <tt/EOF/). + <p> + </itemize> + <p> + It is possible to concatenate the modifiers for <tt/-O/. For example, to + enable register variables and inlining of known functions, you may use + <tt/-Ors/. + + + <tag><tt>-T, --add-source</tt></tag> + + This include the source code as comments in the generated code. This is + normally not needed. + + + <tag><tt>-V, --version</tt></tag> + + Print the version number of the compiler. When submitting a bug report, + please include the operating system you're using, and the compiler + version. + + + <label id="option-W"> + <tag><tt>-W name[,name]</tt></tag> + + This option allows to control warnings generated by the compiler. It is + followed by a comma separated list of warnings that should be enabled or + disabled. To disable a warning, its name is prefixed by a minus sign. If + no such prefix exists, or the name is prefixed by a plus sign, the warning + is enabled. + + The following warning names are currently recognized: + <descrip> + <tag><tt/const-comparison/</tag> + Warn if the result of a comparison is constant. + <tag><tt/error/</tag> + Treat all warnings as errors. + <tag><tt/no-effect/</tag> + Warn about statements that don't have an effect. + <tag><tt/struct-param/</tag> + Warn when passing structs by value. + <tag><tt/unknown-pragma/</tag> + Warn about known #pragmas. + <tag><tt/unused-label/</tag> + Warn about unused labels. + <tag><tt/unused-param/</tag> + Warn about unused function parameters. + <tag><tt/unused-var/</tag> + Warn about unused variables. + </descrip> + + The full list of available warning names may be retrieved by using the + option <tt><ref id="option-list-warnings" name="--list-warnings"></tt>. + + You may also use <tt><ref id="pragma-warn" name="#pragma warn"></tt> to + control this setting for smaller pieces of code from within your code. + +</descrip><p> + + +<sect>Input and output<p> + +The compiler will accept one C file per invocation and create a file with +the same base name, but with the extension replaced by ".s". The output +file contains assembler code suitable for use with the ca65 macro +assembler. + +Include files in quotes are searched in the following places: +<enum> +<item>The current file's directory. +<item>Any directory added with the <tt/-I/ option on the command line. +<item>The value of the environment variable <tt/CC65_INC/ if it is defined. +</enum> + +Include files in angle brackets are searched in the following places: +<enum> +<item>Any directory added with the <tt/-I/ option on the command line. +<item>The value of the environment variable <tt/CC65_INC/ if it is defined. +<item>A subdirectory named <tt/include/ of the directory defined in the + environment variable <tt/CC65_HOME/, if it is defined. +<item>An optionally compiled-in directory. +</enum> + + + +<sect>Differences to the ISO standard<p> + +Apart from the things listed below, the compiler does support additional +keywords, has several functions in the standard headers with names outside the +reserved namespace and a few syntax extensions. All these can be disabled with +the <tt><ref id="option--standard" name="--standard"></tt> command line +option. Its use for maximum standards compatibility is advised. + +Here is a list of differences between the language, the compiler accepts, +and the one defined by the ISO standard: + +<itemize> + +<item> The datatypes "float" and "double" are not available. + <p> +<item> C Functions may not return structs (or unions), and structs may not + be passed as parameters by value. However, struct assignment *is* + possible. + <p> +<item> Part of the C library is available only with fastcall calling + conventions (see below). It means that you must not mix pointers to + those functions with pointers to user-written, not-fastcall functions. + <p> +<item> The <tt/volatile/ keyword doesn't have an effect. This is not as bad + as it sounds, since the 6502 has so few registers that it isn't + possible to keep values in registers anyway. + <p> +</itemize> + +There may be some more minor differences I'm currently not aware of. The +biggest problem is the missing float data type. With this limitation in +mind, you should be able to write fairly portable code. + + + +<sect>Extensions<p> + +This cc65 version has some extensions to the ISO C standard. + +<itemize> + +<item> The compiler allows to insert assembler statements into the output + file. The syntax is + + <tscreen><verb> + asm (<string literal>[, optional parameters]) ; + </verb></tscreen> + or + <tscreen><verb> + __asm__ (<string literal>[, optional parameters]) ; + </verb></tscreen> + + The first form is in the user namespace and is disabled if the <tt/-A/ + switch is given. + + There is a whole section covering inline assembler statements, + <ref id="inline-asm" name="see there">. + <p> + +<item> There is a special calling convention named "fastcall". + The syntax for a function declaration using fastcall is + + <tscreen><verb> + <return type> fastcall <function name> (<parameter list>) + </verb></tscreen> + or + <tscreen><verb> + <return type> __fastcall__ <function name> (<parameter list>) + </verb></tscreen> + An example would be + <tscreen><verb> + void __fastcall__ f (unsigned char c) + </verb></tscreen> + The first form of the fastcall keyword is in the user namespace and can + therefore be disabled with the <tt><ref id="option--standard" + name="--standard"></tt> command line option. + + For functions declared as <tt/fastcall/, the rightmost parameter is not + pushed on the stack but left in the primary register when the function + is called. This will reduce the cost when calling assembler functions + significantly, especially when the function itself is rather small. + <p> + +<item> There are two pseudo variables named <tt/__AX__/ and <tt/__EAX__/. + Both refer to the primary register that is used by the compiler to + evaluate expressions or return function results. <tt/__AX__/ is of + type <tt/unsigned int/ and <tt/__EAX__/ of type <tt/long unsigned int/ + respectively. The pseudo variables may be used as lvalue and rvalue as + every other variable. They are most useful together with short + sequences of assembler code. For example, the macro + + <tscreen><verb> + #define hi(x) \ + (__AX__ = (x), \ + asm ("txa"), \ + asm ("ldx #$00"), \ + __AX__) + </verb></tscreen> + + will give the high byte of any unsigned value. + <p> + +<item> Inside a function, the identifier <tt/__func__/ gives the name of the + current function as a string. Outside of functions, <tt/__func__/ is + undefined. + Example: + + <tscreen><verb> + #define PRINT_DEBUG(s) printf ("%s: %s\n", __func__, s); + </verb></tscreen> + + The macro will print the name of the current function plus a given + string. + <p> + +<item> cc65 allows the initialization of <tt/void/ variables. This may be + used to create variable structures that are more compatible with + interfaces written for assembler languages. Here is an example: + + <tscreen><verb> + void GCmd = { (char)3, (unsigned)0x2000, (unsigned)0x3000 }; + </verb></tscreen> + + This will be translated as follows: + + <tscreen><verb> + _GCmd: + .byte 3 + .word $2000 + .word $3000 + </verb></tscreen> + + Since the variable is of type <tt/void/ you may not use it as is. + However, taking the address of the variable results in a <tt/void*/ + which may be passed to any function expecting a pointer. + + See the <url url="geos.html" name="GEOS library document"> for examples + on how to use this feature. + <p> + +<item> cc65 implements flexible array struct members as defined in the C99 ISO + standard. As an extension, these fields may be initialized. There are + several exceptions, however (which is probably the reason why the + standard does not define this feature, because it is highly + unorthogonal). Flexible array members cannot be initialized ... + + <itemize> + <item>... when defining an array of structs with flexible + members. + <item>... if such a struct is a member field of another struct + which is not the last field. + <item>... if the struct which contains a flexible array member is + declared as <tt/register/, and the size and compiler settings + do allow the compiler actually to place the struct into the + register bank in the zero page. + </itemize> + + Please note that -- as defined in the ISO C standard -- the <tt/sizeof/ + operator returns the struct size with the flexible array member having + size zero, even if it is initialized. + <p> + +</itemize> +<p> + + +<sect>Predefined macros<p> + +The compiler defines several macros at startup: + +<descrip> + <tag><tt>__APPLE2__</tt></tag> + + This macro is defined if the target is the Apple ][ (-t apple2) or the enhanced Apple //e (-t apple2enh). + + <tag><tt>__APPLE2ENH__</tt></tag> + + This macro is defined if the target is the enhanced Apple //e (-t apple2enh). + + <tag><tt>__ATARI5200__</tt></tag> + + This macro is defined if the target is the Atari 5200 game console. + + <tag><tt>__ATARI__</tt></tag> + + This macro is defined if the target is the Atari 400/800 (-t atari) or the Atari 800XL/130XE (-t atarixl). + + <tag><tt>__ATARIXL__</tt></tag> + + This macro is defined if the target is the Atari 800XL/130XE (-t atarixl). + + <tag><tt>__ATMOS__</tt></tag> + + This macro is defined if the target is the Oric Atmos (-t atmos). + + <tag><tt>__C128__</tt></tag> + + This macro is defined if the target is the Commodore 128 (-t c128). + + <tag><tt>__C16__</tt></tag> + + This macro is defined if the target is the Commodore 16/116 (-t c16) or the Commodore Plus/4 (-t plus4). + + <tag><tt>__C64__</tt></tag> + + This macro is defined if the target is the Commodore 64 (-t c64). + + <tag><tt>__CBM__</tt></tag> + + This macro is defined if the target system is one of the CBM targets. + + <tag><tt>__CBM510__</tt></tag> + + This macro is defined if the target is the CBM 500 series of computers. + + <tag><tt>__CBM610__</tt></tag> + + This macro is defined if the target is one of the CBM 600/700 family of + computers (called B series in the US). + + <tag><tt>__CC65__</tt></tag> + + This macro is always defined. Its value is the version number of the + compiler in hex. For example, version 2.14 of the compiler has this macro + defined as <tt/0x02E0/. + + <tag><tt>__CC65_STD__</tt></tag> + + This macro is defined to one of the following depending on the <tt><ref + id="option--standard" name="--standard"></tt> command line option: + <itemize> + <item><tt/__CC65_STD_C89__/ + <item><tt/__CC65_STD_C99__/ + <item><tt/__CC65_STD_CC65__/ + </itemize> + + <tag><tt>__DATE__</tt></tag> + + This macro expands to the date of translation of the preprocessing + translation unit in the form "Mmm dd yyyy". + + <tag><tt>__FILE__</tt></tag> + + This macro expands to a string containing the name of the C source file. + + <tag><tt>__GEOS__</tt></tag> + + This macro is defined if you are compiling for one of the GEOS systems. + + <tag><tt>__GEOS_APPLE__</tt></tag> + + This macro is defined if you are compiling for the Apple GEOS system (-t geos-apple). + + <tag><tt>__GEOS_CBM__</tt></tag> + + This macro is defined if you are compiling for the GEOS 64/128 system (-t geos-cbm). + + <tag><tt>__LINE__</tt></tag> + + This macro expands to the current line number. + + <tag><tt>__LUNIX__</tt></tag> + + This macro is defined if you are compiling for the LUnix system (-t lunix). + + <tag><tt>__LYNX__</tt></tag> + + This macro is defined if the target is the Atari Lynx (-t lynx). + + <tag><tt>__NES__</tt></tag> + + This macro is defined if the target is the Nintendo Entertainment System (-t nes). + + <tag><tt>__OPT__</tt></tag> + + Is defined if the compiler was called with the <tt/-O/ command line option. + + <tag><tt>__OPT_i__</tt></tag> + + Is defined if the compiler was called with the <tt/-Oi/ command line option. + + <tag><tt>__OPT_r__</tt></tag> + + Is defined if the compiler was called with the <tt/-Or/ command line option. + + <tag><tt>__OPT_s__</tt></tag> + + Is defined if the compiler was called with the <tt/-Os/ command line option. + + <tag><tt>__PET__</tt></tag> + + This macro is defined if the target is the PET family of computers (-t pet). + + <tag><tt>__PLUS4__</tt></tag> + + This macro is defined if the target is the Commodore Plus/4 (-t plus4). + + <tag><tt>__STDC_HOSTED__</tt></tag> + + This macro is expands to the integer constant 1. + + <tag><tt>__SIM6502__</tt></tag> + + This macro is defined if the target is sim65 in 6502 mode (-t sim6502). + + <tag><tt>__SIM65C02__</tt></tag> + This macro is defined if the target is sim65 in 65C02 mode (-t sim65c02). + + <tag><tt>__SUPERVISION__</tt></tag> + + This macro is defined if the target is the Supervision (-t supervision). + + <tag><tt>__TIME__</tt></tag> + + This macro expands to the time of translation of the preprocessing + translation unit in the form "hh:mm:ss". + + <tag><tt>__VIC20__</tt></tag> + + This macro is defined if the target is the Commodore VIC20 (-t vic20). +</descrip> + + +<sect>#pragmas<label id="pragmas"><p> + +The compiler understands some pragmas that may be used to change code +generation and other stuff. Some of these pragmas understand a special form: +If the first parameter is <tt/push/, the old value is saved onto a stack +before changing it. The value may later be restored by using the <tt/pop/ +parameter with the <tt/#pragma/. + +<sect1><tt>#pragma bss-name ([push,] <name>)</tt><label id="pragma-bss-name"><p> + + This pragma changes the name used for the BSS segment (the BSS segment + is used to store uninitialized data). The argument is a string enclosed + in double quotes. + + Note: The default linker configuration file does only map the standard + segments. If you use other segments, you have to create a new linker + configuration file. + + Beware: The startup code will zero only the default BSS segment. If you + use another BSS segment, you have to do that yourself, otherwise + uninitialized variables do not have the value zero. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + + Example: + <tscreen><verb> + #pragma bss-name ("MyBSS") + </verb></tscreen> + + +<sect1><tt>#pragma charmap (<index>, <code>)</tt><label id="pragma-charmap"><p> + + Each literal string and each literal character in the source is translated + by use of a translation table. This translation table is preset when the + compiler is started depending on the target system, for example to map + ISO-8859-1 characters into PETSCII if the target is a commodore machine. + + This pragma allows to change entries in the translation table, so the + translation for individual characters, or even the complete table may be + adjusted. + + Both arguments are assumed to be unsigned characters with a valid range of + 1-255. + + Beware of two pitfalls: + + <itemize> + <item>The character index is actually the code of the character in the + C source, so character mappings do always depend on the source + character set. This means that <tt/#pragma charmap/ is not + portable -- it depends on the build environment. + <item>While it is possible to use character literals as indices, the + result may be somewhat unexpected, since character literals are + itself translated. For this reason I would suggest to avoid + character literals and use numeric character codes instead. + </itemize> + + Example: + <tscreen><verb> + /* Use a space wherever an 'a' occurs in ISO-8859-1 source */ + #pragma charmap (0x61, 0x20); + </verb></tscreen> + + +<sect1><tt>#pragma check-stack ([push,] on|off)</tt><label id="pragma-check-stack"><p> + + Tells the compiler to insert calls to a stack checking subroutine to detect + stack overflows. The stack checking code will lead to somewhat larger and + slower programs, so you may want to use this pragma when debugging your + program and switch it off for the release version. If a stack overflow is + detected, the program is aborted. + + If the argument is "off", stack checks are disabled (the default), otherwise + they're enabled. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + +<sect1><tt>#pragma code-name ([push,] <name>)</tt><label id="pragma-code-name"><p> + + This pragma changes the name used for the CODE segment (the CODE segment + is used to store executable code). The argument is a string enclosed in + double quotes. + + Note: The default linker configuration file does only map the standard + segments. If you use other segments, you have to create a new linker + configuration file. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + + Example: + <tscreen><verb> + #pragma code-name ("MyCODE") + </verb></tscreen> + + +<sect1><tt>#pragma codesize ([push,] <int>)</tt><label id="pragma-codesize"><p> + + This pragma allows finer control about speed vs. size decisions in the code + generation and optimization phase. It gives the allowed size increase factor + (in percent). The default is can be changed by use of the <tt/<ref + id="option-codesize" name="--codesize">/ compiler option. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + + +<sect1><tt>#pragma data-name ([push,] <name>)</tt><label id="pragma-data-name"><p> + + This pragma changes the name used for the DATA segment (the DATA segment + is used to store initialized data). The argument is a string enclosed in + double quotes. + + Note: The default linker configuration file does only map the standard + segments. If you use other segments, you have to create a new linker + configuration file. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + + Example: + <tscreen><verb> + #pragma data-name ("MyDATA") + </verb></tscreen> + + +<sect1><tt>#pragma local-strings ([push,] on|off)</tt><label id="pragma-local-strings"><p> + + When "on", emit string literals to the data segment when they're encountered + in the source. The default ("off") is to keep string literals until end of + assembly, merge read only literals if possible, and then output the literals + into the data or rodata segment that is active at that point. + + Using this <tt/#pragma/ it is possible to control the behaviour from within + the source. When <tt/#pragma local-strings/ is active, string literals are + output immediately, which means that they go into the currently active data + or rodata segment, but cannot be merged. When inactive, string literals are + remembered and output as a whole when translation is finished. + + +<sect1><tt>#pragma optimize ([push,] on|off)</tt><label id="pragma-optimize"><p> + + Switch optimization on or off. If the argument is "off", optimization is + disabled, otherwise it is enabled. Please note that this pragma only effects + whole functions. The setting in effect when the function is encountered will + determine if the generated code is optimized or not. + + Optimization and code generation is also controlled by the <ref + id="pragma-codesize" name="codesize pragma">. + + The default is "off", but may be changed with the <tt/<ref name="-O" + id="option-O">/ compiler option. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + + +<sect1><tt>#pragma rodata-name ([push,] <name>)</tt><label id="pragma-rodata-name"><p> + + This pragma changes the name used for the RODATA segment (the RODATA + segment is used to store readonly data). The argument is a string + enclosed in double quotes. + + Note: The default linker configuration file does only map the standard + segments. If you use other segments, you have to create a new linker + configuration file. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + + Example: + <tscreen><verb> + #pragma rodata-name ("MyRODATA") + </verb></tscreen> + + +<sect1><tt>#pragma regvaraddr ([push,] on|off)</tt><label id="pragma-regvaraddr"><p> + + The compiler does not allow to take the address of register variables. + The regvaraddr pragma changes this. Taking the address of a register + variable is allowed after using this pragma with "on" as argument. + Using "off" as an argument switches back to the default behaviour. + + Beware: The C standard does not allow taking the address of a variable + declared as register. So your programs become non-portable if you use + this pragma. In addition, your program may not work. This is usually the + case if a subroutine is called with the address of a register variable, + and this subroutine (or a subroutine called from there) uses + register variables. So be careful with this #pragma. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + + Example: + <tscreen><verb> + #pragma regvaraddr(on) /* Allow taking the address + * of register variables + */ + </verb></tscreen> + + +<sect1><tt>#pragma register-vars ([push,] on|off)</tt><label id="pragma-register-vars"><p> + + Enables or disables use of register variables. If register variables are + disabled (the default), the <tt/register/ keyword is ignored. Register + variables are explained in more detail in <ref id="register-vars" name="a separate + chapter">. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + + +<sect1><tt>#pragma signed-chars ([push,] on|off)</tt><label id="pragma-signed-chars"><p> + + Changes the signedness of the default character type. If the argument is + "on", default characters are signed, otherwise characters are unsigned. The + compiler default is to make characters unsigned since this creates a lot + better code. This default may be overridden by the <tt/<ref + name="--signed-chars" id="option-signed-chars">/ command line option. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + + +<sect1><tt>#pragma static-locals ([push,] on|off)</tt><label id="pragma-static-locals"<p> + + Use variables in the bss segment instead of variables on the stack. This + pragma changes the default set by the compiler option <tt/<ref + name="--static-locals" id="option-static-locals">/. If the argument is "on", + local variables are allocated in the BSS segment, leading to shorter and in + most cases faster, but non-reentrant code. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + + +<sect1><tt>#pragma warn (name, [push,] on|off)</tt><label id="pragma-warn"><p> + + Switch compiler warnings on or off. "name" is the name of a warning (see the + <tt/<ref name="-W" id="option-W">/ compiler option for a list). The name is + either followed by "pop", which restores the last pushed state, or by "on" or + "off", optionally preceeded by "push" to push the current state before + changing it. + + Example: + <tscreen><verb> + /* Don't warn about the unused parameter in function func */ + #pragma warn (unused-param, push, off) + static int func (int unused) + { + return 0; + } + #pragma warn (unused-param, pop) + </verb></tscreen> + +<sect1><tt>#pragma writable-strings ([push,] on|off)</tt><label id="pragma-writable-strings"><p> + + Changes the storage location of string literals. For historical reasons, + the C standard defines that string literals are of type "char[]", but + writing to such a literal causes undefined behaviour. Most compilers + (including cc65) place string literals in the read-only data segment, which + may cause problems with old C code that writes to string literals. + + Using this pragma (or the corresponding command line option <tt/<ref + name="--writable-strings" id="option-writable-strings">/) causes the + literals to be placed in the data segment so they can be written to without + worry. + + The <tt/#pragma/ understands the push and pop parameters as explained above. + + +<sect1><tt>#pragma zpsym (<name>)</tt><p> + + Tell the compiler that the -- previously as external declared -- symbol with + the given name is a zero page symbol (usually from an assembler file). + The compiler will create a matching import declaration for the assembler. + + Example: + <tscreen><verb> + extern int foo; + #pragma zpsym ("foo"); /* foo is in the zeropage */ + </verb></tscreen> + + + + +<sect>Register variables<label id="register-vars"><p> + +The runtime for all supported platforms has 6 bytes of zero page space +available for register variables (this could be increased, but I think it's a +good value). So you can declare register variables up to a total size of 6 per +function. The compiler will allocate register space on a "first come, first +served" base and convert any <tt/register/ declarations that exceed the +available register space silently to <tt/auto/. Parameters can also be +declared as <tt/register/, this will in fact give slightly shorter code than +using a register variable. + +Since a function must save the current values of the registers on entry and +restore them on exit, there is an overhead associated with register variables, +and this overhead is quite high (about 20 bytes per variable). This means that +just declaring anything as <tt/register/ is not a good idea. + +The best use for register variables are pointers, especially those that point +to structures. The magic number here is about 3 uses of a struct field: If the +function contains this number or even more, the generated code will be usually +shorter and faster when using a register variable for the struct pointer. The +reason for this is that the register variable can in many cases be used as a +pointer directly. Having a pointer in an auto variable means that this pointer +must first be copied into a zero page location, before it can be dereferenced. + +Second best use for register variables are counters. However, there is not +much difference in the code generated for counters, so you will need at least +100 operations on this variable (for example in a loop) to make it worth the +trouble. The only savings you get here are by the use of a zero page variable +instead of one on the stack or in the data segment. + +Register variables must be explicitly enabled, either by using <tt/<ref +name="-Or" id="option-O">/ or <tt/<ref name="--register-vars" +id="option-register-vars">/ on the command line or by use of <tt/<ref +name="#pragma register-vars" id="pragma-register-vars">/. Register variables +are only accepted on function top level, register variables declared in +interior blocks are silently converted to <tt/auto/. With register variables +disabled, all variables declared as <tt/register/ are actually auto variables. + +Please take care when using register variables: While they are helpful and can +lead to a tremendous speedup when used correctly, improper usage will cause +bloated code and a slowdown. + + + +<sect>Inline assembler<label id="inline-asm"><p> + +The compiler allows to insert assembler statements into the output file. The +syntax is + +<tscreen><verb> + asm (<string literal>[, optional parameters]) ; +</verb></tscreen> +or +<tscreen><verb> + __asm__ (<string literal>[, optional parameters]) ; +</verb></tscreen> +<p> + +The first form is in the user namespace and is disabled by <tt><ref +id="option--standard" name="--standard"></tt> if the argument is not <tt/cc65/. + +The asm statement may be used inside a function and on global file level. An +inline assembler statement is a primary expression, so it may also be used as +part of an expression. Please note however that the result of an expression +containing just an inline assembler statement is always of type <tt/void/. + +The contents of the string literal are preparsed by the compiler and inserted +into the generated assembly output, so that the can be further processed by +the backend and especially the optimizer. For this reason, the compiler does +only allow regular 6502 opcodes to be used with the inline assembler. Pseudo +instructions (like <tt/.import/, <tt/.byte/ and so on) are <em/not/ allowed, +even if the ca65 assembler (which is used to translate the generated assembler +code) would accept them. The builtin inline assembler is not a replacement for +the full blown macro assembler which comes with the compiler. + +Note: Inline assembler statements are subject to all optimizations done by the +compiler. There is currently no way to protect an inline assembler statement +from being moved or removed completely by the optimizer. If in doubt, check +the generated assembler output, or disable optimizations. + +The string literal may contain format specifiers from the following list. For +each format specifier, an argument is expected which is inserted instead of +the format specifier before passing the assembly code line to the backend. + +<itemize> + <item><tt/%b/ - Numerical 8-bit value + <item><tt/%w/ - Numerical 16-bit value + <item><tt/%l/ - Numerical 32-bit value + <item><tt/%v/ - Assembler name of a global variable or function + <item><tt/%o/ - Stack offset of a local variable + <item><tt/%g/ - Assembler name of a C label + <item><tt/%s/ - The argument is converted to a string + <item><tt/%%/ - The % sign itself +</itemize><p> + +Using these format specifiers, you can access C <tt/#defines/, variables or +similar stuff from the inline assembler. For example, to load the value of +a C <tt/#define/ into the Y register, one would use + +<tscreen><verb> + #define OFFS 23 + __asm__ ("ldy #%b", OFFS); +</verb></tscreen> + +Or, to access a struct member of a static variable: + +<tscreen><verb> + typedef struct { + unsigned char x; + unsigned char y; + unsigned char color; + } pixel_t; + static pixel_t pixel; + __asm__ ("ldy #%b", offsetof(pixel_t, color)); + __asm__ ("lda %v,y", pixel); +</verb></tscreen> +<p> +The next example shows how to use global variables to exchange data between C +an assembler and how to handle assembler jumps: + +<tscreen><verb> + unsigned char globalSubA, globalSubB, globalSubResult; + + /* return a-b, return 255 if b>a */ + unsigned char sub (unsigned char a, unsigned char b) + { + globalSubA = a; + globalSubB = b; + __asm__ ("sec"); + __asm__ ("lda %v", globalSubA); + __asm__ ("sbc %v", globalSubB); + __asm__ ("bcs %g", jumpSubNoError); + __asm__ ("lda #$FF"); + jumpSubNoError: + __asm__ ("sta %v", globalSubResult); + return globalSubResult; + } +</verb></tscreen> +<p> + +Arrays can also be accessed: + +<tscreen><verb> + unsigned char globalSquareTable[] = { + 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, + 100, 121, 144, 169, 196, 225 + }; + unsigned char globalSquareA, globalSquareResult; + + /* return a*a for a<16, else 255 */ + unsigned char square (unsigned char a) + { + if (a>15){ + return 255; + } + globalSquareA = a; + __asm__ ("ldx %v", globalSquareA); + __asm__ ("lda %v,x", globalSquareTable); + __asm__ ("sta %v", globalSquareResult); + return globalSquareResult; + } +</verb></tscreen> +<p> + +Note: Do not embed the assembler labels that are used as names of global +variables or functions into your asm statements. Code like this + +<tscreen><verb> + int foo; + int bar () { return 1; } + __asm__ ("lda _foo"); /* DON'T DO THAT! */ + ... + __asm__ ("jsr _bar"); /* DON'T DO THAT EITHER! */ +</verb></tscreen> +<p> + +may stop working if the way, the compiler generates these names is changed in +a future version. Instead use the format specifiers from the table above: + +<tscreen><verb> + __asm__ ("lda %v", foo); /* OK */ + ... + __asm__ ("jsr %v", bar); /* OK */ +</verb></tscreen> +<p> + + +<sect>Implementation-defined behavior<p> + +This section describes the behavior of cc65 when the standard describes the +behavior as implementation-defined. + +(to be done) + +<sect>Copyright<p> + +This is the original compiler copyright: + +<tscreen><verb> +-------------------------------------------------------------------------- + -*- Mode: Text -*- + + This is the copyright notice for RA65, LINK65, LIBR65, and other + Atari 8-bit programs. Said programs are Copyright 1989, by John R. + Dunning. All rights reserved, with the following exceptions: + + Anyone may copy or redistribute these programs, provided that: + + 1: You don't charge anything for the copy. It is permissable to + charge a nominal fee for media, etc. + + 2: All source code and documentation for the programs is made + available as part of the distribution. + + 3: This copyright notice is preserved verbatim, and included in + the distribution. + + You are allowed to modify these programs, and redistribute the + modified versions, provided that the modifications are clearly noted. + + There is NO WARRANTY with this software, it comes as is, and is + distributed in the hope that it may be useful. + + This copyright notice applies to any program which contains + this text, or the refers to this file. + + This copyright notice 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- + distribute this software. Nobody has the right to prevent anyone + else from copying, modifying or redistributing it. + +-------------------------------------------------------------------------- +</verb></tscreen> + +Small parts of the compiler (parts of the preprocessor and main parser) are +still covered by this copyright. The main portion is covered by the usual +cc65 license, which reads: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> + diff --git a/doc/cl65.sgml b/doc/cl65.sgml new file mode 100644 index 000000000..6e044b8d5 --- /dev/null +++ b/doc/cl65.sgml @@ -0,0 +1,307 @@ +<!doctype linuxdoc system> + +<article> +<title>cl65 Users Guide +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>01.08.2000, 27.11.2000, 02.10.2001 + +<abstract> +cl65 is the compile & link utility for cc65, the 6502 C compiler. It was +designed as a smart frontend for the C compiler (cc65), the assembler (ca65), +the object file converter (co65), and the linker (ld65). +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +cl65 is a frontend for cc65, ca65, co65 and ld65. While you may not use the +full power of the tools when calling them through cl65, most features are +available, and the use of cl65 is much simpler. + + +<sect>Basic Usage<p> + +The cl65 compile and link utility may be used to convert, compile, assemble +and link files. While the separate tools do just one step, cl65 knows how to +build object files from C files (by calling the compiler, then the assembler) +and other things. + +<tscreen><verb> +--------------------------------------------------------------------------- +Usage: cl65 [options] file [...] +Short options: + -c Compile and assemble but don't link + -d Debug mode + -g Add debug info + -h Help (this text) + -l name Create an assembler listing file + -m name Create a map file + -mm model Set the memory model + -o name Name the output file + -r Enable register variables + -t sys Set the target system + -u sym Force an import of symbol `sym' + -v Verbose mode + -vm Verbose map file + -C name Use linker config file + -Cl Make local variables static + -D sym[=defn] Define a preprocessor symbol + -I dir Set a compiler include directory path + -L path Specify a library search path + -Ln name Create a VICE label file + -O Optimize code + -Oi Optimize code, inline functions + -Or Optimize code, honour the register keyword + -Os Optimize code, inline known C funtions + -S Compile but don't assemble and link + -T Include source as comment + -V Print the version number + -W name[,...] Supress compiler warnings + -Wa options Pass options to the assembler + -Wl options Pass options to the linker + +Long options: + --add-source Include source as comment + --asm-args options Pass options to the assembler + --asm-define sym[=v] Define an assembler symbol + --asm-include-dir dir Set an assembler include directory + --bin-include-dir dir Set an assembler binary include directory + --bss-label name Define and export a BSS segment label + --bss-name seg Set the name of the BSS segment + --cc-args options Pass options to the compiler + --cfg-path path Specify a config file search path + --check-stack Generate stack overflow checks + --code-label name Define and export a CODE segment label + --code-name seg Set the name of the CODE segment + --codesize x Accept larger code by factor x + --config name Use linker config file + --cpu type Set cpu type + --create-dep name Create a make dependency file + --create-full-dep name Create a full make dependency file + --data-label name Define and export a DATA segment label + --data-name seg Set the name of the DATA segment + --debug Debug mode + --debug-info Add debug info + --feature name Set an emulation feature + --force-import sym Force an import of symbol `sym' + --help Help (this text) + --include-dir dir Set a compiler include directory path + --ld-args options Pass options to the linker + --lib file Link this library + --lib-path path Specify a library search path + --list-targets List all available targets + --listing name Create an assembler listing file + --list-bytes n Number of bytes per assembler listing line + --mapfile name Create a map file + --memory-model model Set the memory model + --module Link as a module + --module-id id Specify a module id for the linker + --o65-model model Override the o65 model + --obj file Link this object file + --obj-path path Specify an object file search path + --register-space b Set space available for register variables + --register-vars Enable register variables + --rodata-name seg Set the name of the RODATA segment + --signed-chars Default characters are signed + --standard std Language standard (c89, c99, cc65) + --start-addr addr Set the default start address + --static-locals Make local variables static + --target sys Set the target system + --version Print the version number + --verbose Verbose mode + --zeropage-label name Define and export a ZEROPAGE segment label + --zeropage-name seg Set the name of the ZEROPAGE segment +--------------------------------------------------------------------------- +</verb></tscreen> + +Most of the options have the same meaning than the corresponding compiler, +assembler or linker option. See the documentation for these tools for an +explanation. If an option is available for more than one of the tools, it +is set for all tools, where it is available. One example for this is <tt/-v/: +The compiler, the assembler and the linker are all called with the <tt/-v/ +switch. + +There are a few remaining options that control the behaviour of cl65: + +<descrip> + + <tag><tt>-S</tt></tag> + + This option forces cl65 to stop after the assembly step. This means that + C files are translated into assembler files, but nothing more is done. + Assembler files, object files and libraries given on the command line + are ignored. + + + <tag><tt>-c</tt></tag> + + This options forces cl65 to stop after the assembly step. This means + that C and assembler files given on the command line are translated into + object files, but there is no link step, and object files and libraries + given on the command line are ignored. + + + <tag><tt>-o name</tt></tag> + + The -o option is used for the target name in the final step. This causes + problems, if the linker will not be called, and there are several input + files on the command line. In this case, the name given with -o will be + used for all of them, which makes the option pretty useless. You + shouldn't use -o when more than one output file is created. + + + <tag><tt>-t sys, --target sys</tt></tag> + + The default for this option is different from the compiler and linker in the + case that the option is missing: While the other tools (compiler, assembler + and linker) will use the "none" system settings by default, cl65 will use + the C64 as a target system by default. This was chosen since most people + seem to use cc65 to develop for the C64. + + <tag><tt>-Wa options, --asm-args options</tt></tag> + + Pass options directly to the assembler. This may be used to pass options + that aren't directly supported by cl65. Several options may be separated by + commas, the commas are replaced by spaces when passing them to the + assembler. Beware: Passing arguments directly to the assembler may interfere + with some of the defaults, because cl65 doesn't parse the options passed. So + if cl65 supports an option by itself, do not pass this option to the + assembler by means of the <tt/-Wa/ switch. + + <tag><tt>-Wc options, --cc-args options</tt></tag> + + Pass options directly to the compiler. This may be used to pass options + that aren't directly supported by cl65. Several options may be separated by + commas, the commas are replaced by spaces when passing them to the + compiler. Beware: Passing arguments directly to the compiler may interfere + with some of the defaults, because cl65 doesn't parse the options passed. So + if cl65 supports an option by itself, do not pass this option to the + compiler by means of the <tt/-Wc/ switch. + + <tag><tt>-Wl options, --ld-args options</tt></tag> + + Pass options directly to the linker. This may be used to pass options that + aren't directly supported by cl65. Several options may be separated by + commas, the commas are replaced by spaces when passing them to the linker. + Beware: Passing arguments directly to the linker may interfere with some of + the defaults, because cl65 doesn't parse the options passed. So if cl65 + supports an option by itself, do not pass this option to the linker by means + of the <tt/-Wl/ switch. + +</descrip> + + + +<sect>More usage<p> + +Since cl65 was created to simplify the use of the cc65 development +package, it tries to be smart about several things. + +<itemize> + +<item> If you don't give a target system on the command line, cl65 + defaults to the C64. + +<item> When linking, cl65 will supply the names of the startup file and + library for the target system to the linker, so you don't have to do + that. + +<item> If the final step is the linker, and the name of the output file was + not explicitly given, cl65 will use the name of the first input file + without the extension, provided that the name of this file has an + extension. So you don't need to name the executable name in most + cases, just give the name of your "main" file as first input file. +</itemize> + +The command line is parsed from left to right, and the actual processing tool +(compiler, assembler, ...) is invoked whenever a file name is encountered. +This means that only the options to the left of a file name are in effect when +this file is processed. It does also mean that you're able to specify +different options for different files on the command line. As an example. + +<tscreen><verb> + cl65 -Oirs main.c -O -g module.c +</verb></tscreen> + +translates main.c with full optimization and module.c with less optimization +and debug info enabled. + +The type of an input file is derived from its extension: + +<itemize> +<item>C files: <tt/.c/ +<item>Assembler files: <tt/.s/, <tt/.asm/, <tt/.a65/ +<item>Object files: <tt/.o/ <tt/.obj/ +<item>Libraries: <tt/.a/, <tt/.lib/ +<item>GEOS resource files: <tt/.grc/ +<item>o65 files: <tt/.o65/, <tt/.emd/, <tt/.joy/, <tt/.tgi/ +</itemize> + +Please note that the program cannot handle input files with unknown file +extensions. + + +<sect>Examples<p> + +The morse trainer software, which consists of one C file (morse.c) and one +assembler file (irq.s) will need the following separate steps to compile +into an executable named morse: + +<tscreen><verb> + cc65 -g -Oi -t c64 morse.c + ca65 -g morse.s + ca65 -g irq.s + ld65 -o morse -t c64 c64.o morse.o irq.o c64.lib +</verb></tscreen> + +When using cl65, this is simplified to + +<tscreen><verb> + cl65 -g -Oi morse.c irq.s +</verb></tscreen> + +As a general rule, you may use cl65 instead of cc65 at most times, +especially in makefiles to build object files directly from C files. Use + +<tscreen><verb> + .c.o: + cl65 -g -Oi $< +</verb></tscreen> + +to do this. + + + +<sect>Copyright<p> + +cl65 (and all cc65 binutils) are (C) Copyright 1998-2004 Ullrich von +Bassewitz. For usage of the binaries and/or sources the following +conditions do apply: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + + + +</article> + diff --git a/doc/co65.sgml b/doc/co65.sgml new file mode 100644 index 000000000..9d70ffe6a --- /dev/null +++ b/doc/co65.sgml @@ -0,0 +1,344 @@ +<!doctype linuxdoc system> + +<article> +<title>co65 Users Guide +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>12.02.2003 + +<abstract> +co65 is an object file conversion utility. It converts o65 object files into +the native object file format used by the cc65 tool chain. Since o65 is the +file format used by cc65 for loadable drivers, the co65 utility allows (among +other things) to link drivers statically to the generated executables instead +of loading them from disk. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + + +<sect>Overview<p> + +co65 is an object file conversion utility. It converts o65 object files into +assembler files, which may be translated by ca65 to generate object files in +the native object file format used by the cc65 tool chain. + +Since loadable drivers used by the library that comes with cc65 use the o65 +relocatable object code format, using the co65 utility allows to link these +drivers statically. This enables the use of these drivers without loading +additional files from a disk or other secondary storage. + +Another use would be to link object files generated by other development tools +to projects using the cc65 tool chain, but this has not been tested until now, +since such tools are currently rare. + + + +<sect>Usage<p> + +The co65 utility converts one o65 file per run into one assembler files in +ca65 format. The utility tries to autodetect the type of the o65 input file +using the operating system identifier contained in the o65 option list. + + +<sect1>Command line option overview<p> + +The converter may be called as follows: + +<tscreen><verb> +--------------------------------------------------------------------------- +Usage: co65 [options] file +Short options: + -V Print the version number + -g Add debug info to object file + -h Help (this text) + -m model Override the o65 model + -n Don't generate an output file + -o name Name the output file + -v Increase verbosity + +Long options: + --bss-label name Define and export a BSS segment label + --bss-name seg Set the name of the BSS segment + --code-label name Define and export a CODE segment label + --code-name seg Set the name of the CODE segment + --data-label name Define and export a DATA segment label + --data-name seg Set the name of the DATA segment + --debug-info Add debug info to object file + --help Help (this text) + --no-output Don't generate an output file + --o65-model model Override the o65 model + --verbose Increase verbosity + --version Print the version number + --zeropage-label name Define and export a ZEROPAGE segment label + --zeropage-name seg Set the name of the ZEROPAGE segment +--------------------------------------------------------------------------- +</verb></tscreen> + + +<sect1>Command line options in detail<p> + +Here is a description of all the command line options: + +<descrip> + + <tag><tt>--bss-label name</tt></tag> + + Set the label used to mark the start of the bss segment. When this option is + given, the label is also exported and may be accessed from other code. When + accessing such a label from C code, be sure to include the leading + underscore. If you don't need to access the bss segment, there's no need to + use this option. + + + <tag><tt>--bss-name seg</tt></tag> + + Set the name of the bss segment. The default name is "BSS" which is + compatible with the standard ld65 linker configurations. + + + <tag><tt>--code-label name</tt></tag> + + Set the label used to mark the start of the code segment. When this option + is given, the label is also exported and may be accessed from other code. + When accessing such a label from C code, be sure to include the leading + underscore. If you don't need to access the code segment, there's no need to + use this option. + + + <tag><tt>--code-name seg</tt></tag> + + Set the name of the code segment. The default name is "CODE" which is + compatible with the standard ld65 linker configurations. + + + <tag><tt>--data-label name</tt></tag> + + Set the label used to mark the start of the data segment. When this option + is given, the label is also exported and may be accessed from other code. + When accessing such a label from C code, be sure to include the leading + underscore. If you don't need to access the data segment, there's no need to + use this option. + + + <tag><tt>--data-name seg</tt></tag> + + Set the name of the data segment. The default name is "DATA" which is + compatible with the standard ld65 linker configurations. + + + <tag><tt>-d, --debug</tt></tag> + + Enables debug mode, something that should not be needed for mere mortals. + Currently the converter does only accept cc65 loadable modules generated by + ld65 when not in debug mode. Please note that correct conversion has never + been tested for o65 files from other sources, so be careful when using + <tt/-d/. + + + <tag><tt>-g, --debug-info</tt></tag> + + This will cause the converter to insert a <tt/.DEBUGINFO/ command into the + generated assembler code. This will cause the assembler to include all + symbols in a special section in the object file. + + + <tag><tt>-h, --help</tt></tag> + + Print the short option summary shown above. + + + <tag><tt>-m model, --o65-model model</tt></tag> + + Set an o65 model. This option changes the way, output is generated for the + given o65 file. For example, cc65 loadable drivers have a zero page segment, + but this segment must not be defined in the file itself, because the + standard module loader will overlay it with the zeropage space used by the + application that loads this module. So instead of allocating space in the + zero page segment, the converter will reference the start of the zero page + area used by the application. + + Currently, the following models are defined: + + <itemize> + <item>lunix + <item>os/a65 + <item>cc65-module + </itemize> + + The default is to autodetect the model to use from the input file, so + there's rarely a need to use this option. + + + <tag><tt>-n, --no-output</tt></tag> + + Don't do the actual conversion, just read in the o65 file checking for + problems. This option may be used in conjunction with <tt/--verbose/ to + view some information about the input file. + + + <tag><tt>-o name</tt></tag> + + Specify the name of the output file. If you don't specify a name, the + name of the o65 input file is used, with the extension replaced by ".s". + + + <tag><tt>-v, --verbose</tt></tag> + + Using this option, the converter will be somewhat more verbose and print + some information about the o65 input file (among other things). You may use + this option together with <tt/--no-output/ to just get the o65 info. + + + <tag><tt>-V, --version</tt></tag> + + Print the version number of the compiler. When submitting a bug report, + please include the operating system you're using, and the compiler + version. + + + <tag><tt>--zeropage-label name</tt></tag> + + Set the label used to mark the start of the zeropage segment. When this + option is given, the label is also exported and may be accessed from other + code. When accessing such a label from C code, be sure to include the + leading underscore. If you don't need to access the zeropage segment, + there's no need to use this option. + + + <tag><tt>--zeropage-name seg</tt></tag> + + Set the name of the zeropage segment. The default name is "ZEROPAGE" which is + compatible with the standard ld65 linker configurations. + +</descrip> + + +<sect>Input and output<p> + +The converter will accept one o65 file per invocation and create a file with +the same base name, but with the extension replaced by ".s". The output +file contains assembler code suitable for the use with the ca65 macro +assembler. + + +<sect>Converting loadable drivers<p> + +<sect1>Differences between static linking and runtime loading<p> + +One main use of the utility is conversion of loadable drivers, so they may be +linked statically to an application. Statically linking will cause a few +things to be different from runtime loading: + +<itemize> + +<item> Without changing the segment names, all segments take the default + names used by the standard linker configurations. This means that the + driver code is no longer contingous in memory, instead the code + segment is placed somewhere in between all other code segments, the + data segment is placed with all other data segments and so on. If the + driver doesn't do strange things this shouldn't be a problem. + +<item> With statically linked code, data and bss segments will get intialized + once (when the application is loaded), while a loadable driver will + get its initialization each time the driver is loaded into memory + (which may be more than once in the lifetime of a program). It depends + on the driver if this is a problem. Currently, most drivers supplied + with cc65 behave correctly when linked statically. + +</itemize> + + +<sect1>Additional requirements<p> + +All loadable drivers used by cc65 have a header and a jump table at the start +of the code segment. The header is needed to detect the driver (it may also +contain some data that is necessary to access the driver). The jump table is +used to access the functions in the driver code. + +When loading a driver at runtime, the load address of the driver is also the +address of the code segment, so the locations of the header and jump table are +known. However, when linking the driver statically, it is up to the programmer +to provide this information to the driver API. + +For this purpose, it is necessary to define a code segment label that can be +accessed from the outside later. Please note that the converter does currently +<em/not/ create such a label without being ordered to do so, even if the input +file is a cc65 module. + +To create such a label, use the <tt/--code-label/ option when calling the +converter. Be sure to begin the label with a leading underscore when accessing +it from C code. In your code, define an arbitrary variable with this name. Use +the address of this variable as the address of the code segment of the driver. +Be sure to never modify the variable which is in reality the start of your +driver! + + +<sect1>Example - Convert and link a graphics driver<p> + +As an example, here are some instructions to convert and use the c64-hi.tgi +graphics driver: + +First, convert the driver, generating a label named "_c64_hi" for the code +segment. Use the assembler to generate an object file from the assembler +output. + + <tscreen><verb> + co65 --code-label _c64_hi c64-hi.tgi + ca65 c64-hi.s + </verb></tscreen> + +Next, change your C code to declare a variable that is actually the address +of the driver: + + <tscreen><verb> + extern void c64_hi[]; + </verb></tscreen> + +Instead of loading and unloading the driver, change the code to install and +uninstall the driver, which will be already in memory after linking: + + <tscreen><verb> + /* Install the driver */ + tgi_install (c64_hi); + + ... + + /* Uninstall the driver */ + tgi_uninstall (); + </verb></tscreen> + +Don't forget to link the driver object file to your application, otherwise you +will get an "undefined external" error for the _c64_hi symbol. + + + + +<sect>Copyright<p> + +co65 is (C) Copyright 2003 Ullrich von Bassewitz. For usage of the binaries +and/or sources the following conditions apply: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> + diff --git a/doc/coding.sgml b/doc/coding.sgml new file mode 100644 index 000000000..f6dfc3a35 --- /dev/null +++ b/doc/coding.sgml @@ -0,0 +1,308 @@ +<!doctype linuxdoc system> + +<article> +<title>cc65 coding hints +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2000-12-03, 2009-09-01 + +<abstract> +How to generate the most effective code with cc65. +</abstract> + + + +<sect>Use prototypes<p> + +This will not only help to find errors between separate modules, it will also +generate better code, since the compiler must not assume that a variable sized +parameter list is in place and must not pass the argument count to the called +function. This will lead to shorter and faster code. + + + +<sect>Don't declare auto variables in nested function blocks<p> + +Variable declarations in nested blocks are usually a good thing. But with +cc65, there is a drawback: Since the compiler generates code in one pass, it +must create the variables on the stack each time the block is entered and +destroy them when the block is left. This causes a speed penalty and larger +code. + + + +<sect>Remember that the compiler does no high level optimizations<p> + +The compiler needs hints from you about the code to generate. It will try to +optimize the generated code, but follow the outline you gave in your C +program. So for example, when accessing indexed data structures, get a pointer +to the element and use this pointer instead of calculating the index again and +again. If you want to have your loops unrolled, or loop invariant code moved +outside the loop, you have to do that yourself. + + + +<sect>Longs are slow!<p> + +While long support is necessary for some things, it's really, really slow on +the 6502. Remember that any long variable will use 4 bytes of memory, and any +operation works on double the data compared to an int. + + + +<sect>Use unsigned types wherever possible<p> + +The 6502 CPU has no opcodes to handle signed values greater than 8 bit. So +sign extension, test of signedness etc. has to be done with extra code. As a +consequence, the code to handle signed operations is usually a bit larger and +slower than the same code for unsigned types. + + + +<sect>Use chars instead of ints if possible<p> + +While in arithmetic operations, chars are immidiately promoted to ints, they +are passed as chars in parameter lists and are accessed as chars in variables. +The code generated is usually not much smaller, but it is faster, since +accessing chars is faster. For several operations, the generated code may be +better if intermediate results that are known not to be larger than 8 bit are +casted to chars. + +You should especially use unsigned chars for loop control variables if the +loop is known not to execute more than 255 times. + + + +<sect>Make the size of your array elements one of 1, 2, 4, 8<p> + +When indexing into an array, the compiler has to calculate the byte offset +into the array, which is the index multiplied by the size of one element. When +doing the multiplication, the compiler will do a strength reduction, that is, +replace the multiplication by a shift if possible. For the values 2, 4 and 8, +there are even more specialized subroutines available. So, array access is +fastest when using one of these sizes. + + + +<sect>Expressions are evaluated from left to right<p> + +Since cc65 is not building an explicit expression tree when parsing an +expression, constant subexpressions may not be detected and optimized properly +if you don't help. Look at this example: + +<tscreen><verb> + #define OFFS 4 + int i; + i = i + OFFS + 3; +</verb></tscreen> + +The expression is parsed from left to right, that means, the compiler sees 'i', +and puts it contents into the secondary register. Next is OFFS, which is +constant. The compiler emits code to add a constant to the secondary register. +Same thing again for the constant 3. So the code produced contains a fetch +of 'i', two additions of constants, and a store (into 'i'). Unfortunately, the +compiler does not see, that "OFFS + 3" is a constant for itself, since it does +its evaluation from left to right. There are some ways to help the compiler +to recognize expression like this: + +<enum> + +<item>Write "i = OFFS + 3 + i;". Since the first and second operand are +constant, the compiler will evaluate them at compile time reducing the code to +a fetch, one addition (secondary + constant) and one store. + +<item>Write "i = i + (OFFS + 3)". When seeing the opening parenthesis, the +compiler will start a new expression evaluation for the stuff in the braces, +and since all operands in the subexpression are constant, it will detect this +and reduce the code to one fetch, one addition and one store. + +</enum> + + +<sect>Use the preincrement and predecrement operators<p> + +The compiler is not always smart enough to figure out, if the rvalue of an +increment is used or not. So it has to save and restore that value when +producing code for the postincrement and postdecrement operators, even if this +value is never used. To avoid the additional overhead, use the preincrement +and predecrement operators if you don't need the resulting value. That means, +use + +<tscreen><verb> + ... + ++i; + ... +</verb></tscreen> + + instead of + +<tscreen><verb> + ... + i++; + ... +</verb></tscreen> + + + +<sect>Use constants to access absolute memory locations<p> + +The compiler produces optimized code, if the value of a pointer is a constant. +So, to access direct memory locations, use + +<tscreen><verb> + #define VDC_STATUS 0xD601 + *(char*)VDC_STATUS = 0x01; +</verb></tscreen> + +That will be translated to + +<tscreen><verb> + lda #$01 + sta $D601 +</verb></tscreen> + +The constant value detection works also for struct pointers and arrays, if the +subscript is a constant. So + +<tscreen><verb> + #define VDC ((unsigned char*)0xD600) + #define STATUS 0x01 + VDC[STATUS] = 0x01; +</verb></tscreen> + +will also work. + +If you first load the constant into a variable and use that variable to access +an absolute memory location, the generated code will be much slower, since the +compiler does not know anything about the contents of the variable. + + + +<sect>Use initialized local variables<p> + +Initialization of local variables when declaring them gives shorter and faster +code. So, use + +<tscreen><verb> + int i = 1; +</verb></tscreen> + +instead of + +<tscreen><verb> + int i; + i = 1; +</verb></tscreen> + +But beware: To maximize your savings, don't mix uninitialized and initialized +variables. Create one block of initialized variables and one of uniniitalized +ones. The reason for this is, that the compiler will sum up the space needed +for uninitialized variables as long as possible, and then allocate the space +once for all these variables. If you mix uninitialized and initialized +variables, you force the compiler to allocate space for the uninitialized +variables each time, it parses an initialized one. So do this: + +<tscreen><verb> + int i, j; + int a = 3; + int b = 0; +</verb></tscreen> + +instead of + +<tscreen><verb> + int i; + int a = 3; + int j; + int b = 0; +</verb></tscreen> + +The latter will work, but will create larger and slower code. + + + +<sect>Use the array operator [] even for pointers<p> + +When addressing an array via a pointer, don't use the plus and dereference +operators, but the array operator. This will generate better code in some +common cases. + +Don't use + +<tscreen><verb> + char* a; + char b, c; + char b = *(a + c); +</verb></tscreen> + +Use + +<tscreen><verb> + char* a; + char b, c; + char b = a[c]; +</verb></tscreen> + +instead. + + + +<sect>Use register variables with care<p> + +Register variables may give faster and shorter code, but they do also have an +overhead. Register variables are actually zero page locations, so using them +saves roughly one cycle per access. The calling routine may also use register +variables, so the old values have to be saved on function entry and restored +on exit. Saving an d restoring has an overhead of about 70 cycles per 2 byte +variable. It is easy to see, that - apart from the additional code that is +needed to save and restore the values - you need to make heavy use of a +variable to justify the overhead. + +As a general rule: Use register variables only for pointers that are +dereferenced several times in your function, or for heavily used induction +variables in a loop (with several 100 accesses). + +When declaring register variables, try to keep them together, because this +will allow the compiler to save and restore the old values in one chunk, and +not in several. + +And remember: Register variables must be enabled with <tt/-r/ or <tt/-Or/. + + + +<sect>Decimal constants greater than 0x7FFF are actually long ints<p> + +The language rules for constant numeric values specify that decimal constants +without a type suffix that are not in integer range must be of type long int +or unsigned long int. So a simple constant like 40000 is of type long int! +This is often unexpected and may cause an expression to be evaluated with 32 +bits. While in many cases the compiler takes care about it, in some places it +can't. So be careful when you get a warning like + +<tscreen><verb> + test.c(7): Warning: Constant is long +</verb></tscreen> + +Use the <tt/U/, <tt/L/ or <tt/UL/ suffixes to tell the compiler the desired +type of a numeric constant. + + + +<sect>Access to parameters in variadic functions is expensive<p> + +Since cc65 has the "wrong" calling order, the location of the fixed parameters +in a variadic function (a function with a variable parameter list) depends on +the number and size of variable arguments passed. Since this number and size +is unknown at compile time, the compiler will generate code to calculate the +location on the stack when needed. + +Because of this additional code, accessing the fixed parameters in a variadic +function is much more expensive than access to parameters in a "normal" +function. Unfortunately, this additional code is also invisible to the +programmer, so it is easy to forget. + +As a rule of thumb, if you access such a parameter more than once, you should +think about copying it into a normal variable and using this variable instead. + + +</article> + diff --git a/doc/customizing.sgml b/doc/customizing.sgml new file mode 100644 index 000000000..23cf8c5e8 --- /dev/null +++ b/doc/customizing.sgml @@ -0,0 +1,730 @@ +<!doctype linuxdoc system> + +<article> +<title>Defining a Custom cc65 Target +<author>Bruce Reidenbach +<date>2010-02-22 + +<abstract> +This section provides step-by-step instructions on how to use the cc65 +toolset for a custom hardware platform (a target system not currently +supported by the cc65 library set). +</abstract> + +<!-- Table of contents --> + +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +The cc65 toolset provides a set of pre-defined libraries that allow the +user to target the executable image to a variety of hardware platforms. +In addition, the user can create a customized environment so that the +executable can be targeted to a custom platform. The following +instructions provide step-by-step instructions on how to customize the +toolset for a target that is not supported by the standard cc65 +installation. + +The platform used in this example is a Xilinx Field Programmable Gate +Array (FPGA) with an embedded 65C02 core. The processor core supports +the additional opcodes/addressing modes of the 65SC02, along with the +STP and WAI instructions. These instructions will create a set of files +to create a custom target, named SBC, for <bf>S</bf>ingle <bf>B</bf>oard +<bf>C</bf>omputer. + +<sect>System Memory Map Definition<p> + +The targeted system uses block RAM contained on the XILINX FPGA for the +system memory (both RAM and ROM). The block RAMs are available in +various aspect ratios, and they will be used in this system as 2K*8 +devices. There will be two RAMs used for data storage, starting at +location $0000 and growing upwards. There will be one ROM (realized as +initialized RAM) used code storage, starting at location $FFFF and +growing downwards. + +The cc65 toolset requires a memory configuration file to define the +memory that is available to the cc65 run-time environment, which is +defined as follows: + +<tscreen><code> +MEMORY { + ZP: start = $0, size = $100, type = rw, define = yes; + RAM: start = $200, size = $0E00, define = yes; + ROM: start = $F800, size = $0800, file = %O; +} +</code></tscreen> + +ZP defines the available zero page locations, which in this case starts +at $0 and has a length of $100. Keep in mind that certain systems may +require access to some zero page locations, so the starting address may +need to be adjusted accordingly to prevent cc65 from attempting to reuse +those locations. Also, at a minimum, the cc65 run-time environment uses +26 zero page locations, so the smallest zero page size that can be +specified is $1A. The usable RAM memory area begins after the 6502 +stack storage in page 1, so it is defined as starting at location $200 +and filling the remaining 4K of space (4096 - 2 * +256 = 3584 = $0E00). The 2K of ROM space begins at +address $F800 and goes to $FFFF (size = $0800). + +Next, the memory segments within the memory devices need to be defined. +A standard segment definition is used, with one notable exception. The +interrupt and reset vector locations need to be defined at locations +$FFFA through $FFFF. A special segment named VECTORS is defined that +resides at these locations. Later, the interrupt vector map will be +created and placed in the VECTORS segment, and the linker will put these +vectors at the proper memory locations. The segment definition is: + +<tscreen><code> +SEGMENTS { + ZEROPAGE: load = ZP, type = zp, define = yes; + DATA: load = ROM, type = rw, define = yes, run = RAM; + BSS: load = RAM, type = bss, define = yes; + HEAP: load = RAM, type = bss, optional = yes; + STARTUP: load = ROM, type = ro; + INIT: load = ROM, type = ro, optional = yes; + CODE: load = ROM, type = ro; + RODATA: load = ROM, type = ro; + VECTORS: load = ROM, type = ro, start = $FFFA; +} +</code></tscreen> + +The meaning of each of these segments is as follows. + +<p><tt> ZEROPAGE: </tt>Data in page 0, defined by ZP as starting at $0 with length $100 +<p><tt> DATA: </tt>Initialized data that can be modified by the program, stored in RAM +<p><tt> BSS: </tt>Uninitialized data stored in RAM (used for variable storage) +<p><tt> HEAP: </tt>Uninitialized C-level heap storage in RAM, optional +<p><tt> STARTUP: </tt>The program initialization code, stored in ROM +<p><tt> INIT: </tt>The code needed to initialize the system, stored in ROM +<p><tt> CODE: </tt>The program code, stored in ROM +<p><tt> RODATA: </tt>Initialized data that cannot be modified by the program, stored in ROM +<p><tt> VECTORS: </tt>The interrupt vector table, stored in ROM at location $FFFA + +A note about initialized data: any variables that require an initial +value, such as external (global) variables, require that the initial +values be stored in the ROM code image. However, variables stored in +ROM cannot change; therefore the data must be moved into variables that +are located in RAM. Specifying <tt>run = RAM</tt> as part of +the DATA segment definition will indicate that those variables will +require their initialization value to be copied via a call to the +<tt>copydata</tt> routine in the startup assembly code. In addition, +there are system level variables that will need to be initialized as +well, especially if the heap segment is used via a C-level call to +<tt>malloc ()</tt>. + +The final section of the definition file contains the data constructors +and destructors used for system startup. In addition, if the heap is +used, the maximum C-level stack size needs to be defined in order for +the system to be able to reliably allocate blocks of memory. The stack +size selection must be greater than the maximum amount of storage +required to run the program, keeping in mind that the C-level subroutine +call stack and all local variables are stored in this stack. The +<tt>FEATURES</tt> section defines the required constructor/destructor +attributes and the <tt>SYMBOLS</tt> section defines the stack size. The +constructors will be run via a call to <tt>initlib</tt> in the startup +assembly code and the destructors will be run via an assembly language +call to <tt>donelib</tt> during program termination. + +<tscreen><code> +FEATURES { + CONDES: segment = STARTUP, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = STARTUP, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} + +SYMBOLS { + # Define the stack size for the application + __STACKSIZE__: value = $0200, weak = yes; +} +</code></tscreen> + +These definitions are placed in a file named "sbc.cfg" +and are referred to during the ld65 linker stage. + +<sect>Startup Code Definition<p> + +In the cc65 toolset, a startup routine must be defined that is executed +when the CPU is reset. This startup code is marked with the STARTUP +segment name, which was defined in the system configuration file as +being in read only memory. The standard convention used in the +predefined libraries is that this code is resident in the crt0 module. +For this custom system, all that needs to be done is to perform a little +bit of 6502 housekeeping, set up the C-level stack pointer, initialize +the memory storage, and call the C-level routine <tt>main ()</tt>. +The following code was used for the crt0 module, defined in the file +"crt0.s": + +<tscreen><code> +; --------------------------------------------------------------------------- +; crt0.s +; --------------------------------------------------------------------------- +; +; Startup code for cc65 (Single Board Computer version) + +.export _init, _exit +.import _main + +.export __STARTUP__ : absolute = 1 ; Mark as startup +.import __RAM_START__, __RAM_SIZE__ ; Linker generated + +.import copydata, zerobss, initlib, donelib + +.include "zeropage.inc" + +; --------------------------------------------------------------------------- +; Place the startup code in a special segment + +.segment "STARTUP" + +; --------------------------------------------------------------------------- +; A little light 6502 housekeeping + +_init: LDX #$FF ; Initialize stack pointer to $01FF + TXS + CLD ; Clear decimal mode + +; --------------------------------------------------------------------------- +; Set cc65 argument stack pointer + + LDA #<(__RAM_START__ + __RAM_SIZE__) + STA sp + LDA #>(__RAM_START__ + __RAM_SIZE__) + STA sp+1 + +; --------------------------------------------------------------------------- +; Initialize memory storage + + JSR zerobss ; Clear BSS segment + JSR copydata ; Initialize DATA segment + JSR initlib ; Run constructors + +; --------------------------------------------------------------------------- +; Call main() + + JSR _main + +; --------------------------------------------------------------------------- +; Back from main (this is also the _exit entry): force a software break + +_exit: JSR donelib ; Run destructors + BRK +</code></tscreen> + +The following discussion explains the purpose of several important +assembler level directives in this file. + +<tscreen><verb> +.export _init, _exit +</verb></tscreen> + +This line instructs the assembler that the symbols <tt>_init</tt> and +<tt>_exit</tt> are to be accessible from other modules. In this +example, <tt>_init</tt> is the location that the CPU should jump to when +reset, and <tt>_exit</tt> is the location that will be called when the +program is finished. + +<tscreen><verb> +.import _main +</verb></tscreen> + +This line instructs the assembler to import the symbol <tt>_main</tt> +from another module. cc65 names all C-level routines as +{underscore}{name} in assembler, thus the <tt>main ()</tt> routine +in C is named <tt>_main</tt> in the assembler. This is how the startup +code will link to the C-level code. + +<tscreen><verb> +.export __STARTUP__ : absolute = 1 ; Mark as startup +</verb></tscreen> + +This line marks this code as startup code (code that is executed when +the processor is reset), which will then be automatically linked into +the executable code. + +<tscreen><verb> +.import __RAM_START__, __RAM_SIZE__ ; Linker generated +</verb></tscreen> + +This line imports the RAM starting address and RAM size constants, which +are used to initialize the cc65 C-level argument stack pointer. + +<tscreen><verb> +.segment "STARTUP" +</verb></tscreen> + +This line instructs the assembler that the code is to be placed in the +STARTUP segment of memory. + +<tscreen><verb> + JSR zerobss ; Clear BSS segment + JSR copydata ; Initialize DATA segment + JSR initlib ; Run constructors +</verb></tscreen> + +These three lines initialize the external (global) and system +variables. The first line sets the BSS segment -- the memory locations +used for external variables -- to 0. The second line copies the +initialization value stored in ROM to the RAM locations used for +initialized external variables. The last line runs the constructors +that are used to initialize the system run-time variables. + +<tscreen><verb> + JSR _main +</verb></tscreen> + +This is the actual call to the C-level <tt>main ()</tt> routine, +which is called after the startup code completes. + +<tscreen><verb> +_exit: JSR donelib ; Run destructors + BRK +</verb></tscreen> + +This is the code that will be executed when <tt>main ()</tt> +terminates. The first thing that must be done is run the destructors +via a call to <tt>donelib</tt>. Then the program can terminate. In +this example, the program is expected to run forever. Therefore, there +needs to be a way of indicating when something has gone wrong and the +system needs to be shut down, requiring a restart only by a hard reset. +The BRK instruction will be used to indicate a software fault. This is +advantageous because cc65 uses the BRK instruction as the fill byte in +the final binary code. In addition, the hardware has been designed to +force the data lines to $00 for all illegal memory accesses, thereby +also forcing a BRK instruction into the CPU. + +<sect>Custom Run-Time Library Creation<p> + +The next step in customizing the cc65 toolset is creating a run-time +library for the targeted hardware. The easiest way to do this is to +modify a standard library from the cc65 distribution. In this example, +there is no console I/O, mouse, joystick, etc. in the system, so it is +most appropriate to use the simplest library as the base, which is for +the Watara Supervision and is named "supervision.lib" in the +lib directory of the distribution. + +The only modification required is to replace the <tt>crt0</tt> module in +the supervision.lib library with custom startup code. This is simply +done by first copying the library and giving it a new name, compiling +the startup code with ca65, and finally using the ar65 archiver to +replace the module in the new library. The steps are shown below: + +<tscreen><verb> +$ copy "C:\Program Files\cc65\lib\supervision.lib" sbc.lib +$ ca65 crt0.s +$ ar65 a sbc.lib crt0.o +</verb></tscreen> + +<sect>Interrupt Service Routine Definition<p> + +For this system, the CPU is put into a wait condition prior to allowing +interrupt processing. Therefore, the interrupt service routine is very +simple: return from all valid interrupts. However, as mentioned +before, the BRK instruction is used to indicate a software fault, which +will call the same interrupt service routine as the maskable interrupt +signal IRQ. The interrupt service routine must be able to tell the +difference between the two, and act appropriately. + +The interrupt service routine shown below includes code to detect when a +BRK instruction has occurred and stops the CPU from further processing. +The interrupt service routine is in a file named +"interrupt.s". + +<tscreen><code> +; --------------------------------------------------------------------------- +; interrupt.s +; --------------------------------------------------------------------------- +; +; Interrupt handler. +; +; Checks for a BRK instruction and returns from all valid interrupts. + +.import _stop +.export _irq_int, _nmi_int + +.segment "CODE" + +.PC02 ; Force 65C02 assembly mode + +; --------------------------------------------------------------------------- +; Non-maskable interrupt (NMI) service routine + +_nmi_int: RTI ; Return from all NMI interrupts + +; --------------------------------------------------------------------------- +; Maskable interrupt (IRQ) service routine + +_irq_int: PHX ; Save X register contents to stack + TSX ; Transfer stack pointer to X + PHA ; Save accumulator contents to stack + INX ; Increment X so it points to the status + INX ; register value saved on the stack + LDA $100,X ; Load status register contents + AND #$10 ; Isolate B status bit + BNE break ; If B = 1, BRK detected + +; --------------------------------------------------------------------------- +; IRQ detected, return + +irq: PLA ; Restore accumulator contents + PLX ; Restore X register contents + RTI ; Return from all IRQ interrupts + +; --------------------------------------------------------------------------- +; BRK detected, stop + +break: JMP _stop ; If BRK is detected, something very bad + ; has happened, so stop running +</code></tscreen> + +The following discussion explains the purpose of several important +assembler level directives in this file. + +<tscreen><verb> +.import _stop +</verb></tscreen> + +This line instructs the assembler to import the symbol <tt>_stop</tt> +from another module. This routine will be called if a BRK instruction +is encountered, signaling a software fault. + +<tscreen><verb> +.export _irq_int, _nmi_int +</verb></tscreen> + +This line instructs the assembler that the symbols <tt>_irq_int</tt> and +<tt>_nmi_int</tt> are to be accessible from other modules. In this +example, the address of these symbols will be placed in the interrupt +vector table. + +<tscreen><verb> +.segment "CODE" +</verb></tscreen> + +This line instructs the assembler that the code is to be placed in the +CODE segment of memory. Note that because there are 65C02 mnemonics in +the assembly code, the assembler is forced to use the 65C02 instruction +set with the <tt>.PC02</tt> directive. + +The final step is to define the interrupt vector memory locations. +Recall that a segment named VECTORS was defined in the memory +configuration file, which started at location $FFFA. The addresses of +the interrupt service routines from "interrupt.s" along with +the address for the initialization code in crt0 are defined in a file +named "vectors.s". Note that these vectors will be placed in +memory in their proper little-endian format as: + +<p><tt> $FFFA - $FFFB:</tt> NMI interrupt vector (low byte, high byte) +<p><tt> $FFFC - $FFFD:</tt> Reset vector (low byte, high byte) +<p><tt> $FFFE - $FFFF:</tt> IRQ/BRK interrupt vector (low byte, high byte) + +using the <tt>.addr</tt> assembler directive. The contents of the file are: + +<tscreen><code> +; --------------------------------------------------------------------------- +; vectors.s +; --------------------------------------------------------------------------- +; +; Defines the interrupt vector table. + +.import _init +.import _nmi_int, _irq_int + +.segment "VECTORS" + +.addr _nmi_int ; NMI vector +.addr _init ; Reset vector +.addr _irq_int ; IRQ/BRK vector +</code></tscreen> + +The cc65 toolset will replace the address symbols defined here with the +actual addresses of the routines during the link process. + +<sect>Adding Custom Instructions<p> + +The cc65 instruction set only supports the WAI (Wait for Interrupt) and +STP (Stop) instructions when used with the 65816 CPU (accessed via the +--cpu command line option of the ca65 macro assembler). The 65C02 core +used in this example supports these two instructions, and in fact the +system benefits from the use of both the WAI and STP instructions. + +In order to use the WAI instruction in this case, a C routine named +"wait" was created that consists of the WAI opcode followed by +a subroutine return. It was convenient in this example to put the IRQ +interrupt enable in this subroutine as well, since interrupts should +only be enabled when the code is in this wait condition. + +For both the WAI and STP instructions, the assembler is +"fooled" into placing those opcodes into memory by inserting a +single byte of data that just happens to be the opcode for those +instructions. The assembly code routines are placed in a file, named +"wait.s", which is shown below: + +<tscreen><code> +; --------------------------------------------------------------------------- +; wait.s +; --------------------------------------------------------------------------- +; +; Wait for interrupt and return + +.export _wait, _stop + +; --------------------------------------------------------------------------- +; Wait for interrupt: Forces the assembler to emit a WAI opcode ($CB) +; --------------------------------------------------------------------------- + +.segment "CODE" + +.proc _wait: near + + CLI ; Enable interrupts +.byte $CB ; Inserts a WAI opcode + RTS ; Return to caller + +.endproc + +; --------------------------------------------------------------------------- +; Stop: Forces the assembler to emit a STP opcode ($DB) +; --------------------------------------------------------------------------- + +.proc _stop: near + +.byte $DB ; Inserts a STP opcode + +.endproc +</code></tscreen> + +The label <tt>_wait</tt>, when exported, can be called by using the +<tt>wait ()</tt> subroutine call in C. The section is marked as +code so that it will be stored in read-only memory, and the procedure is +tagged for 16-bit absolute addressing via the "near" +modifier. Similarly, the <tt>_stop</tt> routine can be called from +within the C-level code via a call to <tt>stop ()</tt>. In +addition, the routine can be called from assembly code by calling +<tt>_stop</tt> (as was done in the interrupt service routine). + +<sect>Hardware Drivers<p> + +Oftentimes, it can be advantageous to create small application helpers +in assembly language to decrease codespace and increase execution speed +of the overall program. An example of this would be the transfer of +characters to a FIFO (<bf>F</bf>irst-<bf>I</bf>n, +<bf>F</bf>irst-<bf>O</bf>ut) storage buffer for transmission over a +serial port. This simple action could be performed by an assembly +language driver which would execute much quicker than coding it in C. +The following discussion outlines a method of interfacing a C program +with an assembly language subroutine. + +The first step in creating the assembly language code for the driver is +to determine how to pass the C arguments to the assembly language +routine. The cc65 toolset allows the user to specify whether the data +is passed to a subroutine via the stack or by the processor registers by +using the <tt>__fastcall__</tt> function declaration (note that there +are two underscore characters in front of and two behind the +<tt>fastcall</tt> declaration). When <tt>__fastcall__</tt> is +specified, the rightmost argument in the function call is passed to the +subroutine using the 6502 registers instead of the stack. Note that if +there is only one argument in the function call, the execution overhead +required by the stack interface routines is completely avoided. + +Without <tt>__fastcall__</tt>, the argument is loaded in the A and X +registers and then pushed onto the stack via a call to <tt>pushax</tt>. +The first thing the subroutine does is retrieve the argument from the +stack via a call to <tt>ldax0sp</tt>, which copies the values into the A +and X. When the subroutine is finished, the values on the stack must be +popped off and discarded via a jump to <tt>incsp2</tt>, which includes +the RTS subroutine return command. This is shown in the following code +sample. + +Calling sequence: + +<tscreen><verb> + lda #<(L0001) ; Load A with the high order byte + ldx #>(L0001) ; Load X with the low order byte + jsr pushax ; Push A and X onto the stack + jsr _foo ; Call foo, i.e., foo (arg) +</verb></tscreen> + +Subroutine code: + +<tscreen><verb> +_foo: jsr ldax0sp ; Retrieve A and X from the stack + sta ptr ; Store A in ptr + stx ptr+1 ; Store X in ptr+1 + ... ; (more subroutine code goes here) + jmp incsp2 ; Pop A and X from the stack (includes return) +</verb></tscreen> + +If <tt>__fastcall__</tt> is specified, the argument is loaded into the A +and X registers as before, but the subroutine is then called +immediately. The subroutine does not need to retrieve the argument +since the value is already available in the A and X registers. +Furthermore, the subroutine can be terminated with an RTS statement +since there is no stack cleanup which needs to be performed. This is +shown in the following code sample. + +Calling sequence: + +<tscreen><verb> + lda #<(L0001) ; Load A with the high order byte + ldx #>(L0001) ; Load X with the low order byte + jsr _foo ; Call foo, i.e., foo (arg) +</verb></tscreen> + +Subroutine code: + +<tscreen><verb> +_foo: sta ptr ; Store A in ptr + stx ptr+1 ; Store X in ptr+1 + ... ; (more subroutine code goes here) + rts ; Return from subroutine +</verb></tscreen> + +The hardware driver in this example writes a string of character data to +a hardware FIFO located at memory location $1000. Each character is +read and is compared to the C string termination value ($00), which will +terminate the loop. All other character data is written to the FIFO. +For convenience, a carriage return/line feed sequence is automatically +appended to the serial stream. The driver defines a local pointer +variable which is stored in the zero page memory space in order to allow +for retrieval of each character in the string via the indirect indexed +addressing mode. + +The assembly language routine is stored in a file names +"rs232_tx.s" and is shown below: + +<tscreen><code> +; --------------------------------------------------------------------------- +; rs232_tx.s +; --------------------------------------------------------------------------- +; +; Write a string to the transmit UART FIFO + +.export _rs232_tx +.exportzp _rs232_data: near + +.define TX_FIFO $1000 ; Transmit FIFO memory location + +.zeropage + +_rs232_data: .res 2, $00 ; Reserve a local zero page pointer + +.segment "CODE" + +.proc _rs232_tx: near + +; --------------------------------------------------------------------------- +; Store pointer to zero page memory and load first character + + sta _rs232_data ; Set zero page pointer to string address + stx _rs232_data+1 ; (pointer passed in via the A/X registers) + ldy #00 ; Initialize Y to 0 + lda (_rs232_data) ; Load first character + +; --------------------------------------------------------------------------- +; Main loop: read data and store to FIFO until \0 is encountered + +loop: sta TX_FIFO ; Loop: Store character in FIFO + iny ; Increment Y index + lda (_rs232_data),y ; Get next character + bne loop ; If character == 0, exit loop + +; --------------------------------------------------------------------------- +; Append CR/LF to output stream and return + + lda #$0D ; Store CR + sta TX_FIFO + lda #$0A ; Store LF + sta TX_FIFO + rts ; Return + +.endproc +</code></tscreen> + +<sect>Hello World! Example<p> + +The following short example demonstrates programming in C using the cc65 +toolset with a custom run-time environment. In this example, a Xilinx +FPGA contains a UART which is connected to a 65c02 processor with FIFO +(<bf>F</bf>irst-<bf>I</bf>n, <bf>F</bf>irst-<bf>O</bf>ut) storage to +buffer the data. The C program will wait for an interrupt generated by +the receive UART and then respond by transmitting the string "Hello +World! " every time a question mark character is received via a +call to the hardware driver <tt>rs232_tx ()</tt>. The driver +prototype uses the <tt>__fastcall__</tt> extension to indicate that the +driver does not use the stack. The FIFO data interface is at address +$1000 and is defined as the symbolic constant <tt>FIFO_DATA</tt>. +Writing to <tt>FIFO_DATA</tt> transfers a byte of data into the transmit +FIFO for subsequent transmission over the serial interface. Reading +from <tt>FIFO_DATA</tt> transfers a byte of previously received data out +of the receive FIFO. The FIFO status data is at address $1001 and is +defined as the symbolic constant <tt>FIFO_STATUS</tt>. For convenience, +the symbolic constants <tt>TX_FIFO_FULL</tt> (which isolates bit 0 of +the register) and <tt>RX_FIFO_EMPTY</tt> (which isolates bit 1 of the +register) have been defined to read the FIFO status. + +The following C code is saved in the file "main.c". As this +example demonstrates, the run-time environment has been set up such that +all of the behind-the-scene work is transparent to the user. + +<tscreen><code> +#define FIFO_DATA (*(unsigned char *) 0x1000) +#define FIFO_STATUS (*(unsigned char *) 0x1001) + +#define TX_FIFO_FULL (FIFO_STATUS & 0x01) +#define RX_FIFO_EMPTY (FIFO_STATUS & 0x02) + +extern void wait (); +extern void __fastcall__ rs232_tx (char *str); + +int main () { + while (1) { // Run forever + wait (); // Wait for an RX FIFO interrupt + + while (RX_FIFO_EMPTY == 0) { // While the RX FIFO is not empty + if (FIFO_DATA == '?') { // Does the RX character = '?' + rs232_tx ("Hello World!"); // Transmit "Hello World!" + } // Discard any other RX characters + } + } + + return (0); // We should never get here! +} +</code></tscreen> + +<sect>Putting It All Together<p> + +The following commands will create a ROM image named "a.out" +that can be used as the initialization data for the Xilinx Block RAM +used for code storage: + +<tscreen><verb> +$ cc65 -t none -O --cpu 65sc02 main.c +$ ca65 --cpu 65sc02 main.s +$ ca65 --cpu 65sc02 rs232_tx.s +$ ca65 --cpu 65sc02 interrupt.s +$ ca65 --cpu 65sc02 vectors.s +$ ca65 --cpu 65sc02 wait.s +$ ld65 -C sbc.cfg -m main.map interrupt.o vectors.o wait.o rs232_tx.o + main.o sbc.lib +</verb></tscreen> + +During the C-level code compilation phase (<tt>cc65</tt>), assumptions +about the target system are disabled via the <tt>-t none</tt> command +line option. During the object module linker phase (<tt>ld65</tt>), the +target customization is enabled via inclusion of the <tt>sbc.lib</tt> +file and the selection of the configuration file via the <tt>-C +sbc.cfg</tt> command line option. + +The 65C02 core used most closely matches the cc65 toolset processor +named 65SC02 (the 65C02 extensions without the bit manipulation +instructions), so all the commands specify the use of that processor via +the <tt>--cpu 65sc02</tt> option. + +</article> diff --git a/doc/da65.sgml b/doc/da65.sgml new file mode 100644 index 000000000..2b8cdb2a3 --- /dev/null +++ b/doc/da65.sgml @@ -0,0 +1,685 @@ +<!doctype linuxdoc system> + +<article> +<title>da65 Users Guide +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2003-08-08 + +<abstract> +da65 is a 6502/65C02 disassembler that is able to read user supplied +information about its input data for better results. The output is ready for +feeding into ca65, the macro assembler supplied with the cc65 C compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +da65 is a disassembler for 6502/65C02 code. It is supplied as a utility with +the cc65 C compiler and generates output that is suitable for the ca65 +macro assembler. + +Besides generating output for ca65, one of the design goals was that the user +is able to feed additional information about the code into the disassembler +for improved results. This information may include the location and size of +tables, and their format. + +One nice advantage of this concept is that disassembly of copyrighted binaries +may be handled without problems: One can just pass the information file for +disassembling the binary, so everyone with a legal copy of the binary can +generate a nicely formatted disassembly with readable labels and other +information. + + +<sect>Usage<p> + + +<sect1>Command line option overview<p> + +The assembler accepts the following options: + +<tscreen><verb> +--------------------------------------------------------------------------- +Usage: da65 [options] [inputfile] +Short options: + -g Add debug info to object file + -h Help (this text) + -i name Specify an info file + -o name Name the output file + -v Increase verbosity + -F Add formfeeds to the output + -S addr Set the start/load address + -V Print the disassembler version + +Long options: + --argument-column n Specify argument start column + --comment-column n Specify comment start column + --comments n Set the comment level for the output + --cpu type Set cpu type + --debug-info Add debug info to object file + --formfeeds Add formfeeds to the output + --help Help (this text) + --hexoffs Use hexadecimal label offsets + --info name Specify an info file + --label-break n Add newline if label exceeds length n + --mnemonic-column n Specify mnemonic start column + --pagelength n Set the page length for the listing + --start-addr addr Set the start/load address + --text-column n Specify text start column + --verbose Increase verbosity + --version Print the disassembler version +--------------------------------------------------------------------------- +</verb></tscreen> + + +<sect1>Command line options in detail<p> + +Here is a description of all the command line options: + +<descrip> + + <label id="option--argument-column"> + <tag><tt>--argument-column n</tt></tag> + + Specifies the column where the argument for a mnemonic or pseudo instruction + starts. + + + <label id="option--comment-column"> + <tag><tt>--comment-column n</tt></tag> + + Specifies the column where the comment for an instruction starts. + + + <label id="option--comments"> + <tag><tt>--comments n</tt></tag> + + Set the comment level for the output. Valid arguments are 0..4. Greater + values will increase the level of additional information written to the + output file in form of comments. + + + <label id="option--cpu"> + <tag><tt>--cpu type</tt></tag> + + Set the CPU type. The option takes a parameter, which may be one of + + 6502, 6502x, 65sc02, 65c02, huc6280 + + 6502x is the NMOS 6502 with illegal opcodes. huc6280 is the CPU of the PC + engine. Support for the 65816 is currently not available. + + + <label id="option--formfeeds"> + <tag><tt>-F, --formfeeds</tt></tag> + + Add formfeeds to the generated output. This feature is useful together + with the <tt><ref id="option--pagelength" name="--pagelength"></tt> option. + If <tt/--formfeeds/ is given, a formfeed is added to the output after each + page. + + + <tag><tt>-g, --debug-info</tt></tag> + + This option adds the <tt/.DEBUGINFO/ command to the output file, so the + assembler will generate debug information when reassembling the generated + output. + + + <tag><tt>-h, --help</tt></tag> + + Print the short option summary shown above. + + + <label id="option--hexoffs"> + <tag><tt>--hexoffs</tt></tag> + + Output label offsets in hexadecimal instead of decimal notation. + + + <label id="option--info"> + <tag><tt>-i name, --info name</tt></tag> + + Specify an info file. The info file contains global options that may + override or replace command line options plus informations about the code + that has to be disassembled. See the separate section <ref id="infofile" + name="Info File Format">. + + + <label id="option-o"> + <tag><tt>-o name</tt></tag> + + Specify a name for an output file. The default is to use <tt/stdout/, so + without this switch or the corresponding <ref id="global-options" + name="global option"> <tt><ref id="OUTPUTNAME" name="OUTPUTNAME"></tt>, + the output will go to the terminal. + + + <label id="option--label-break"> + <tag><tt>--label-break n</tt></tag> + + Adds a newline if the length of a label exceeds the given length. + Note: If the label would run into the code in the mid column, a + linefeed is always inserted regardless of this setting. + + This option overrides the <ref id="global-options" name="global option"> + <tt><ref id="LABELBREAK" name="LABELBREAK"></tt>. + + + <label id="option--mnemonic-column"> + <tag><tt>--mnemonic-column n</tt></tag> + + Specifies the column where a mnemonic or pseudo instrcuction is output. + + + <label id="option--pagelength"> + <tag><tt>--pagelength n</tt></tag> + + Sets the length of a listing page in lines. After this number of lines, a + new page header is generated. If the <tt><ref id="option--formfeeds" + name="--formfeeds"></tt> is also given, a formfeed is inserted before + generating the page header. + + A value of zero for the page length will disable paging of the output. + + + <label id="option--start-addr"> + <tag><tt>-S addr, --start-addr addr</tt></tag> + + Specify the start/load address of the binary code that is going to be + disassembled. The given address is interpreted as an octal value if + preceded with a '0' digit, as a hexadecimal value if preceded + with '0x', '0X', or '$', and as a decimal value in all other cases. If no + start address is specified, $10000 minus the size of the input file is used. + + + <label id="option--text-column"> + <tag><tt>--text-column n</tt></tag> + + Specifies the column where additional text is output. This additional text + consists of the bytes encoded in this line in text representation. + + + <tag><tt>-v, --verbose</tt></tag> + + Increase the disassembler verbosity. Usually only needed for debugging + purposes. You may use this option more than one time for even more + verbose output. + + + <tag><tt>-V, --version</tt></tag> + + Print the version number of the assembler. If you send any suggestions + or bugfixes, please include the version number. + +</descrip> +<p> + + +<sect>Detailed workings<p> + +<sect1>Supported CPUs<p> + +The default (no CPU given on the command line or in the <tt/GLOBAL/ section of +the info file) is the 6502 CPU. The disassembler knows all "official" opcodes +for this CPU. Invalid opcodes are translated into <tt/.byte/ commands. + +With the command line option <tt><ref id="option--cpu" name="--cpu"></tt>, the +disassembler may be told to recognize either the 65SC02 or 65C02 CPUs. The +latter understands the same opcodes as the former, plus 16 additional bit +manipulation and bit test-and-branch commands. + +While there is some code for the 65816 in the sources, it is currently +unsupported. + + +<sect1>Attribute map<p> + +The disassembler works by creating an attribute map for the whole address +space ($0000 - $FFFF). Initially, all attributes are cleared. Then, an +external info file (if given) is read. Disassembly is done in several passes. +In all passes with the exception of the last one, information about the +disassembled code is gathered and added to the symbol and attribute maps. The +last pass generates output using the information from the maps. + +<sect1>Labels<p> + +Some instructions may generate labels in the first pass, while most other +instructions do not generate labels, but use them if they are available. Among +others, the branch and jump instructions will generate labels for the target +of the branch in the first pass. External labels (taken from the info file) +have precedence over internally generated ones, They must be valid identifiers +as specified for the ca65 assembler. Internal labels (generated by the +disassembler) have the form <tt/Labcd/, where <tt/abcd/ is the hexadecimal +address of the label in upper case letters. You should probably avoid using +such label names for external labels. + + +<sect1>Info File<p> + +The info file is used to pass additional information about the input code to +the disassembler. This includes label names, data areas or tables, and global +options like input and output file names. See the <ref id="infofile" +name="next section"> for more information. + + + +<sect>Info File Format<label id="infofile"><p> + +The info file contains lists of specifications grouped together. Each group +directive has an identifying token and an attribute list enclosed in curly +braces. Attributes have a name followed by a value. The syntax of the value +depends on the type of the attribute. String attributes are places in double +quotes, numeric attributes may be specified as decimal numbers or hexadecimal +with a leading dollar sign. There are also attributes where the attribute +value is a keyword, in this case the keyword is given as is (without quotes or +anything). Each attribute is terminated by a semicolon. + +<tscreen><verb> + group-name { attribute1 attribute-value; attribute2 attribute-value; } +</verb></tscreen> + + +<sect1>Comments<p> + +Comments start with a hash mark (<tt/#/) and extend from the position of +the mark to the end of the current line. Hash marks inside of strings will +of course <em/not/ start a comment. + + +<sect1>Specifying global options<label id="global-options"><p> + +Global options may be specified in a group with the name <tt/GLOBAL/. The +following attributes are recognized: + +<descrip> + + <tag><tt/ARGUMENTCOLUMN/</tag> + This attribute specifies the column in the output, where the argument for + an opcode or pseudo instruction starts. The corresponding command line + option is + <tt><ref id="option--argument-column" name="--argument-column"></tt>. + + + <tag><tt/COMMENTCOLUMN/</tag> + This attribute specifies the column in the output, where the comment starts + in a line. It is only used for in-line comments. The corresponding command + line option is + <tt><ref id="option--comment-column" name="--comment-column"></tt>. + + + <label id="COMMENTS"> + <tag><tt/COMMENTS/</tag> + This attribute may be used instead of the <tt><ref id="option--comments" + name="--comments"></tt> option on the command line. It takes a numerical + parameter between 0 and 4. Higher values increase the amount of information + written to the output file in form of comments. + + + <tag><tt/CPU/</tag> + This attribute may be used instead of the <tt><ref id="option--cpu" + name="--cpu"></tt> option on the command line. For possible values see + there. The value is a string and must be enclosed in quotes. + + + <tag><tt/HEXOFFS/</tag> + The attribute is followed by a boolean value. If true, offsets to labels are + output in hex, otherwise they're output in decimal notation. The default is + false. The attribute may be changed on the command line using the <tt><ref + id="option--hexoffs" name="--hexoffs"></tt> option. + + + <tag><tt/INPUTNAME/</tag> + The attribute is followed by a string value, which gives the name of the + input file to read. If it is present, the disassembler does not accept an + input file name on the command line. + + + <tag><tt/INPUTOFFS/</tag> + The attribute is followed by a numerical value that gives an offset into + the input file which is skipped before reading data. The attribute may be + used to skip headers or unwanted code sections in the input file. + + + <tag><tt/INPUTSIZE/</tag> + <tt/INPUTSIZE/ is followed by a numerical value that gives the amount of + data to read from the input file. Data beyond <tt/INPUTOFFS + INPUTSIZE/ + is ignored. + + + <label id="LABELBREAK"> + <tag><tt/LABELBREAK/</tag> + <tt/LABELBREAK/ is followed by a numerical value that specifies the label + length that will force a newline. To have all labels on their own lines, + you may set this value to zero. + + See also the <tt><ref id="option--label-break" name="--label-break"></tt> + command line option. A <tt/LABELBREAK/ statement in the info file will + override any value given on the command line. + + + <tag><tt/MNEMONICCOLUMN/</tag> + This attribute specifies the column in the output, where the mnemonic or + pseudo instruction is placed. The corresponding command line option is + <tt><ref id="option--mnemonic-column" name="--mnemonic-column"></tt>. + + + <tag><tt/NEWLINEAFTERJMP/</tag> + This attribute is followed by a boolean value. When true, a newline is + inserted after each <tt/JMP/ instruction. The default is false. + + + <tag><tt/NEWLINEAFTERRTS/</tag> + This attribute is followed by a boolean value. When true, a newline is + inserted after each <tt/RTS/ instruction. The default is false. + + + <label id="OUTPUTNAME"> + <tag><tt/OUTPUTNAME/</tag> + The attribute is followed by string value, which gives the name of the + output file to write. If it is present, specification of an output file on + the command line using the <tt><ref id="option-o" name="-o"></tt> option is + not allowed. + + The default is to use <tt/stdout/ for output, so without this attribute or + the corresponding command line option <tt/<ref id="option-o" name="-o">/ + the output will go to the terminal. + + + <tag><tt/PAGELENGTH/</tag> + This attribute may be used instead of the <tt><ref id="option--pagelength" + name="--pagelength"></tt> option on the command line. It takes a numerical + parameter. Using zero as page length (which is the default) means that no + pages are generated. + + + <tag><tt/STARTADDR/</tag> + This attribute may be used instead of the <tt><ref id="option--start-addr" + name="--start-addr"></tt> option on the command line. It takes a numerical + parameter. The default for the start address is $10000 minus the size of + the input file (this assumes that the input file is a ROM that contains the + reset and irq vectors). + + + <tag><tt/TEXTCOLUMN/</tag> + This attribute specifies the column, where the data bytes are output + translated into ASCII text. It is only used if + <tt><ref id="COMMENTS" name="COMMENTS"></tt> is set to at least 4. The + corresponding command line option is + <tt><ref id="option--text-column" name="--text-column"></tt>. + +</descrip> + + +<sect1>Specifying Ranges<p> + +The <tt/RANGE/ directive is used to give information about address ranges. The +following attributes are recognized: + +<descrip> + + <tag><tt>COMMENT</tt></tag> + This attribute is only allowed if a label is also given. It takes a string + as argument. See the description of the <tt><ref id="infofile-label" + name="LABEL"></tt> directive for an explanation. + + <tag><tt>END</tt></tag> + This gives the end address of the range. The end address is inclusive, that + means, it is part of the range. Of course, it may not be smaller than the + start address. + + <tag><tt>NAME</tt></tag> + This is a convenience attribute. It takes a string argument and will cause + the disassembler to define a label for the start of the range with the + given name. So a separate <tt><ref id="infofile-label" name="LABEL"></tt> + directive is not needed. + + <tag><tt>START</tt></tag> + This gives the start address of the range. + + <tag><tt>TYPE</tt></tag> + This attribute specifies the type of data within the range. The attribute + value is one of the following keywords: + + <descrip> + <tag><tt>ADDRTABLE</tt></tag> + The range consists of data and is disassembled as a table of words + (16 bit values). The difference to the <tt/WORDTABLE/ type is that + a label is defined for each entry in the table. + + <tag><tt>BYTETABLE</tt></tag> + The range consists of data and is disassembled as a byte table. + + <tag><tt>CODE</tt></tag> + The range consists of code. + + <tag><tt>DBYTETABLE</tt></tag> + The range consists of data and is disassembled as a table of dbytes + (double byte values, 16 bit values with the low byte containing the + most significant byte of the 16 bit value). + + <tag><tt>DWORDTABLE</tt></tag> + The range consists of data and is disassembled as a table of double + words (32 bit values). + + <tag><tt>RTSTABLE</tt></tag> + The range consists of data and is disassembled as a table of words (16 bit + values). The values are interpreted as words that are pushed onto the + stack and jump to it via <tt/RTS/. This means that they contain + <tt/address-1/ of a function, for which a label will get defined by the + disassembler. + + <tag><tt>SKIP</tt></tag> + The range is simply ignored when generating the output file. Please note + that this means that reassembling the output file will <em/not/ generate + the original file, not only because the missing piece in between, but also + because the following code will be located on wrong addresses. Output + generated with <tt/SKIP/ ranges will need manual rework. + + <tag><tt>TEXTTABLE</tt></tag> + The range consists of readable text. + + <tag><tt>WORDTABLE</tt></tag> + The range consists of data and is disassembled as a table of words + (16 bit values). + + </descrip> + +</descrip> + + +<sect1>Specifying Labels<label id="infofile-label"><p> + +The <tt/LABEL/ directive is used to give names for labels in the disassembled +code. The following attributes are recognized: + +<descrip> + + <tag><tt>ADDR</tt></tag> + Followed by a numerical value. Specifies the value of the label. + + <tag><tt>COMMENT</tt></tag> + Attribute argument is a string. The comment will show up in a separate line + before the label, if the label is within code or data range, or after the + label if it is outside. + + Example output: + +<tscreen><verb> + foo := $0001 ; Comment for label named "foo" + + ; Comment for label named "bar" + bar: +</verb></tscreen> + + <tag><tt>NAME</tt></tag> + The attribute is followed by a string value which gives the name of the + label. Empty names are allowed, in this case the disassembler will create + an unnamed label (see the assembler docs for more information about unnamed + labels). + + <tag><tt>SIZE</tt></tag> + This attribute is optional and may be used to specify the size of the data + that follows. If a size greater than 1 is specified, the disassembler will + create labels in the form <tt/label+offs/ for all bytes within the given + range, where <tt/label/ is the label name given with the <tt/NAME/ + attribute, and <tt/offs/ is the offset within the data. + +</descrip> + + +<sect1>Specifying Segments<label id="infofile-segment"><p> + +The <tt/SEGMENT/ directive is used to specify a segment within the +disassembled code. The following attributes are recognized: + +<descrip> + + <tag><tt>START</tt></tag> + Followed by a numerical value. Specifies the start address of the segment. + + <tag><tt>END</tt></tag> + Followed by a numerical value. Specifies the end address of the segment. The + end address is last the address that is part of the segment. + + <tag><tt>NAME</tt></tag> + The attribute is followed by a string value which gives the name of the + segment. +</descrip> + +All attributes are mandatory. Segments may not overlap. Since there is no +explicit "end this segment" pseudo op, the disassembler cannot notify the +assembler that one segment has ended. This may lead to errors if you don't +define your segments carefully. As a rule of thumb, if you're using segments, +your should define segments for all disassembled code. + + +<sect1>Specifying Assembler Includes<label id="infofile-asminc"><p> + +The <tt/ASMINC/ directive is used to give the names of input files containing +symbol assignments in assembler syntax: + +<tscreen><verb> + Name = value + Name := value +</verb></tscreen> + +The usual conventions apply for symbol names. Values may be specified as hex +(leading $), binary (leading %) or decimal. The values may optionally +be signed. + +NOTE: The include file parser is very simple. Expressions are not allowed, and +anything but symbol assignments is flagged as an error (but see the +<tt/IGNOREUNKNOWN/ directive below). + +The following attributes are recognized: + +<descrip> + + <tag><tt>FILE</tt></tag> + Followed by a string value. Specifies the name of the file to read. + + <tag><tt>COMMENTSTART</tt></tag> + The optional attribute is followed by a character constant. It specifies the + character that starts a comment. The default value is a semicolon. This + value is ignored if <tt/IGNOREUNKNOWN/ is true. + + <tag><tt>IGNOREUNKNOWN</tt></tag> + This attribute is optional and is followed by a boolean value. It allows to + ignore input lines that don't have a valid syntax. This allows to read in + assembler include files that contain more than just symbol assignments. + Note: When this attribute is used, the disassembler will ignore any errors + in the given include file. This may have undesired side effects. + +</descrip> + + +<sect1>An Info File Example<p> + +The following is a short example for an info file that contains most of the +directives explained above: + +<tscreen><verb> + # This is a comment. It extends to the end of the line + GLOBAL { + OUTPUTNAME "kernal.s"; + INPUTNAME "kernal.bin"; + STARTADDR $E000; + PAGELENGTH 0; # No paging + CPU "6502"; + }; + + # One segment for the whole stuff + SEGMENT { START $E000; END $FFFF; NAME kernal; }; + + RANGE { START $E612; END $E631; TYPE Code; }; + RANGE { START $E632; END $E640; TYPE ByteTable; }; + RANGE { START $EA51; END $EA84; TYPE RtsTable; }; + RANGE { START $EC6C; END $ECAB; TYPE RtsTable; }; + RANGE { START $ED08; END $ED11; TYPE AddrTable; }; + + # Zero page variables + LABEL { NAME "fnadr"; ADDR $90; SIZE 3; }; + LABEL { NAME "sal"; ADDR $93; }; + LABEL { NAME "sah"; ADDR $94; }; + LABEL { NAME "sas"; ADDR $95; }; + + # Stack + LABEL { NAME "stack"; ADDR $100; SIZE 255; }; + + # Indirect vectors + LABEL { NAME "cinv"; ADDR $300; SIZE 2; }; # IRQ + LABEL { NAME "cbinv"; ADDR $302; SIZE 2; }; # BRK + LABEL { NAME "nminv"; ADDR $304; SIZE 2; }; # NMI + + # Jump table at end of kernal ROM + LABEL { NAME "kscrorg"; ADDR $FFED; }; + LABEL { NAME "kplot"; ADDR $FFF0; }; + LABEL { NAME "kiobase"; ADDR $FFF3; }; + LABEL { NAME "kgbye"; ADDR $FFF6; }; + + # Hardware vectors + LABEL { NAME "hanmi"; ADDR $FFFA; }; + LABEL { NAME "hares"; ADDR $FFFC; }; + LABEL { NAME "hairq"; ADDR $FFFE; }; +</verb></tscreen> + + + + + +<sect>Copyright<p> + +da65 (and all cc65 binutils) are (C) Copyright 1998-2007 Ullrich von +Bassewitz. For usage of the binaries and/or sources the following +conditions do apply: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + + + +</article> + + + + diff --git a/doc/debugging.sgml b/doc/debugging.sgml new file mode 100644 index 000000000..c7c7792db --- /dev/null +++ b/doc/debugging.sgml @@ -0,0 +1,154 @@ +<!doctype linuxdoc system> + +<article> + +<title>Using emulators with cc65 +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2014-04-11 + +<abstract> +How to debug your code using the VICE and Oricutron emulators. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This document describes how to debug your programs using the cc65 development +tools and the VICE CBM emulator. + + + +<sect>What is VICE?<p> + +VICE is an emulator for many of the CBM machines. It runs on Unix, MS-DOS, +Win32, OS/2, Acorn RISC OS, BeOS, QNX 6.x, Amiga, GP2X and Mac OS X. It emulates +the Commodore 64, 128, VIC20, PET and the 600/700 machines. For more information +see the VICE home page: + +<url url="http://vice-emu.sourceforge.net/">. + +VICE has a builtin machine language monitor that may be used for debugging +your programs. Using an emulator for debugging has some advantages: + +<itemize> + +<item>Since you're using a crossassembler/-compiler anyway, you don't need to +transfer the program to the real machine until it is done. + +<item>An emulator allows many things that are almost impossible one of the +original machines. You may set watchpoints (detect read or write access to +arbitary addresses), debug interrupt handlers and even debug routines that run +inside the 1541 floppy. + +<item>You may use the label file generated by the linker to make much more use +from the monitor. + +</itemize> + + + +<sect>How to prepare your programs<p> + +VICE support is mostly done via a label file that is generated by the linker +and that may be read by the VICE monitor, so it knows about your program. +Source level debugging is <tt/not/ available, you have to debug your programs +in the assembler view. + +The first step is to generate object files that contain information about +<em/all/ labels in your sources, not just the exported ones. This can be done +by several means: + +<itemize> + +<item>Use the -g switch on the assembler command line. + +<item>Use the +<tscreen><verb> + .debuginfo + +</verb></tscreen> + command in your source. + +<item>Use the <tt/-g/ switch when invoking the compiler. The compiler will +then place a <tt/.debuginfo/ command into the generated assembler source. + +</itemize> + +So, if you have just C code, all you need is to invoke the compiler with +<tt/-g/. If you're using assembler code, you have to use <tt/-g/ for the +assembler, or add "<tt/.debuginfo on/" to your source files. Since the +generated debug info is not appended to the generated executables, it is a +good idea to always use <tt/-g/. It makes the object files and libraries +slightly larger (˜30%), but this is usually not a problem. + +The second step is to tell the linker that it should generate a VICE label +file. This is done by the <tt/-Ln/ switch followed by the name of the label +file (I'm usually using a <tt/.lbl/ extension for these files). An example for +a linker command line would be: + +<tscreen><verb> + ld65 -o hello -t c64 -Ln hello.lbl -m hello.map hello.o c64.lib +</verb></tscreen> +or +<tscreen><verb> + ld65 -o hello.tap -t atmos -Ln hello.sym -m hello.map hello.o atmos.lib +</verb></tscreen> + +This will generate a file named hello.lbl that contains all symbols used in +your program. + +<bf>Note</bf>: The runtime libraries and startup files were generated with +debug info, so you don't have to care about this. + + + +<sect>How to use the label file with VICE<p> + +Load your program, then enter the monitor and use the "<tt/ll/" command to +load your label file like this: + +<tscreen><verb> + ll "hello.lbl" +</verb></tscreen> + +You will get lots of warnings and even a few errors. You may ignore safely all +these warnings and errors as long as they reference any problems VICE thinks +it has with the labels. + +After loading the labels, they are used by VICE in the disassembler listing, +and you may use them whereever you need to specify an address. Try + +<tscreen><verb> + d ._main +</verb></tscreen> + +as an example (note that VICE needs a leading dot before all labels, and that +the compiler prepends an underline under most named labels). + + + +<sect>How to use the label file with Oricutron<p> + +Load your program, then enter the monitor and use the "<tt/sl/" command to +load your label file like this: + +<tscreen><verb> + sl hello.sym +</verb></tscreen> + +After loading the labels, they are used by Oricutron in the disassembler listing, +and you may use them whereever you need to specify an address. Try + +<tscreen><verb> + d ._main +</verb></tscreen> + +as an example (note that VICE needs a leading dot before all labels, and that +the compiler prepends an underline under most named labels). + + + +</article> diff --git a/doc/dio.sgml b/doc/dio.sgml new file mode 100644 index 000000000..c85992a4a --- /dev/null +++ b/doc/dio.sgml @@ -0,0 +1,134 @@ +<!doctype linuxdoc system> + +<article> +<title>Diskette Sector I/O Routines +<author><url url="mailto:chris@groessler.org" name="Christian Groessler"> +<date>2014-04-10 + +<abstract> +The cc65 library provides functions to read and write raw disk sectors. +Include the dio.h header file to get the necessary definitions. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Opening the disk for low level I/O<p> + +Prior to using these functions a handle to the device has to be obtained. This +is done with the <tt>dio_open</tt> function. After use, the handle should be +released with the <tt>dio_close</tt> function. + +<tscreen><verb> + dhandle_t __fastcall__ dio_open (unsigned char device); +</verb></tscreen> + +The <tt>device</tt> specifies the device to access, with 0 being the first +device, 1 the second, and so on. + +<tscreen><verb> + unsigned char __fastcall__ dio_close (dhandle_t handle); +</verb></tscreen> + +Closes a handle obtained by <tt>dio_open</tt>. Returns status code. +<p> + +<sect>Reading and writing sectors<p> + +The read and write functions are: + +<tscreen><verb> + unsigned char __fastcall__ dio_read (dhandle_t handle, + unsigned sect_num, + void *buffer); +</verb></tscreen> + +This function will read the sector specified by <tt>sect_num</tt> into the memory +location at buffer. + +<tscreen><verb> + unsigned char __fastcall__ dio_write (dhandle_t handle, + unsigned sect_num, + const void *buffer); +</verb></tscreen> + +This function will write the memory contents at buffer to the sector specified +by <tt>sect_num</tt>. No verify is performed. + +<tscreen><verb> + unsigned char __fastcall__ dio_write_verify (dhandle_t handle, + unsigned sect_num, + const void *buffer); +</verb></tscreen> + +This function will write the memory contents at buffer to the sector specified +by <tt>sect_num</tt>. A verification is performed. +<p> + +Use the <tt><ref name="dio_query_sectsize" id="sectsizecount"></tt> function to query +the size of a sector and the <tt><ref name="dio_query_sectcount" id="sectsizecount"></tt> +function to query the number of available sectors. +<p> + +All these functions will return 0 for success and an OS specific error code in +case of failure. +<p> + +<sect>Querying sector size and count<label id="sectsizecount"><p> + +Some systems support multiple diskette formats which have different sector sizes +and/or different sector counts. +<p> + +The following function returns the sector size of the currently inserted disk: + +<tscreen><verb> + unsigned __fastcall__ dio_query_sectsize (dhandle_t handle); +</verb></tscreen> + +On the Atari platform, the sector size is handled specially. Please refer +to the DIO section in the <url url="atari.html" name="Atari-specific +platform documentation">. +<p> + +The following function returns the sector count of the currently inserted disk: + +<tscreen><verb> + unsigned __fastcall__ dio_query_sectcount (dhandle_t handle); +</verb></tscreen> + +<sect>Converting sector numbers<p> + +Since the read and write functions expect a sector number, for systems where +the sectors aren't addressed by a logical sector number (e.g. CBM devices), +there are 2 conversion functions. One of them converts a logical sector number +to a head/track/sector triple. The other conversion function works the other +way round. + +<tscreen><verb> + unsigned char __fastcall__ dio_phys_to_log (dhandle_t handle, + const dio_phys_pos *physpos, + unsigned *sectnum); +</verb></tscreen> + +This function converts track/head/sector to logical sector number. + +<tscreen><verb> + unsigned char __fastcall__ dio_log_to_phys (dhandle_t handle, + const unsigned *sectnum, + dio_phys_pos *physpos); +</verb></tscreen> + +This function converts a logical sector number to track/head/sector notation. +<p> + +Note, that on systems which natively use logical sector numbers (e.g. Atari), +the conversion functions are dummies. They ignore head/track +(<tt>dio_phys_to_log</tt>) or return them as zero (<tt>dio_log_to_phys</tt>). +The logical sector number is returned as physical sector and vice versa. +<p> + + +</article> diff --git a/doc/doc.css b/doc/doc.css new file mode 100644 index 000000000..232599a75 --- /dev/null +++ b/doc/doc.css @@ -0,0 +1,33 @@ +body { + font-family: arial, helvetica, sans-serif; + font-size: 100%; + text-align: justify; + margin-left: 110px; + margin-top: 10px; + margin-right: 30px; + margin-bottom: 10px; + background-image: url(doc.png); + background-repeat: repeat-y; +} + +h1, h2, h2 a:link, h2 a:active, h2 a:visited { + font-weight: bold; + font-style: italic; + text-align: left; + color: #DB3232; +} + +h1 { + font-size: 250%; + text-shadow: 2px 2px 6px #505050; + letter-spacing: 2px; + padding-top: 40px; +} + +h2 { + font-size: 160%; + text-shadow: 2px 2px 6px #303030; + letter-spacing: 1px; + margin-top: 2em; + margin-bottom: 1em; +} diff --git a/doc/doc.png b/doc/doc.png new file mode 100644 index 000000000..91af80d31 Binary files /dev/null and b/doc/doc.png differ diff --git a/doc/funcref.sgml b/doc/funcref.sgml new file mode 100644 index 000000000..60b8360ed --- /dev/null +++ b/doc/funcref.sgml @@ -0,0 +1,7486 @@ +<!doctype linuxdoc system> <!-- -*- text-mode -*- --> + +<article> +<title>cc65 function reference +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2014-05-26 + +<abstract> +cc65 is a C compiler for 6502 based systems. This function reference describes +the C functions available in the standard library. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Introduction<p> + +cc65 is a C compiler for 6502 based systems. It implements a subset of the ISO +C standard plus additional functions specially crafted for 6502 systems or +just some of the supported machines. This function refrence describes the +available functions together with any limitations. + +For an overview about the available libraries, their purpose, and any +differences to the ISO standard, please have a look at the <url +url="library.html" name="cc65 Library Overview">. + +<em/Note:/ Standard C functions are listed here, but not described in detail. +Since these functions behave identical on all standard compliant systems, they +are described in any book covering standard C. + +Each entry for a function contains a detailed description + +<quote> +<descrip> +<tag/Function/Summary of what <bf/function/ does. +<tag/Header/The header file that contains the declaration. +<tag/Declaration/Describes the needed header files and declaration of the +function. +<tag/Description/Description of the function. +<tag/Limits/Limits. +<tag/Availability/The availability of the function. +<tag/See also/Other related functions. +<tag/Example/A piece of actual code using the function. +</descrip> +</quote> + + +<sect>Functions by header file<p> + +<sect1><tt/6502.h/<label id="6502.h"><p> + +<itemize> +<item><ref id="BRK" name="BRK"> +<item><ref id="CLI" name="CLI"> +<item><ref id="SEI" name="SEI"> +<item><ref id="_sys" name="_sys"> +<item><ref id="getcpu" name="getcpu"> +<item><ref id="reset_brk" name="reset_brk"> +<item><ref id="reset_irq" name="reset_irq"> +<item><ref id="set_brk" name="set_brk"> +<item><ref id="set_irq" name="set_irq"> +</itemize> + + +<sect1><tt/apple2.h/<label id="apple2.h"><p> + +<itemize> +<item>_dos_type +<item><ref id="get_ostype" name="get_ostype"> +<item>rebootafterexit +</itemize> + + +<sect1><tt/apple2enh.h/<label id="apple2enh.h"><p> + +<itemize> +<item>_dos_type +<item><ref id="get_ostype" name="get_ostype"> +<item>rebootafterexit +<item>textframe +<item>textframexy +<item><ref id="videomode" name="videomode"> +</itemize> + + +<sect1><tt/assert.h/<label id="assert.h"><p> + +<itemize> +<item><ref id="assert" name="assert"> +</itemize> + + +<sect1><tt/atari.h/<label id="atari.h"><p> + +<itemize> +<!-- <item><ref id="_getcolor" name="_getcolor"> --> +<!-- <item><ref id="_getdefdev" name="_getdefdev"> --> +<!-- <item><ref id="_graphics" name="_graphics"> --> +<!-- <item><ref id="_rest_vecs" name="_rest_vecs"> --> +<!-- <item><ref id="_save_vecs" name="_save_vecs"> --> +<!-- <item><ref id="_scroll" name="_scroll"> --> +<!-- <item><ref id="_setcolor" name="_setcolor"> --> +<!-- <item><ref id="_setcolor_low" name="_setcolor_low"> --> +<item><ref id="get_ostype" name="get_ostype"> +<!-- <item><ref id="get_tv" name="get_tv"> --> +</itemize> + +(incomplete) + + +<sect1><tt/atmos.h/<label id="atmos.h"><p> + +<itemize> +<item><ref id="atmos_load" name="atmos_load"> +<item><ref id="atmos_save" name="atmos_save"> +<!-- <item><ref id="atmos_explode" name="atmos_explode"> --> +<!-- <item><ref id="atmos_ping" name="atmos_ping"> --> +<!-- <item><ref id="atmos_shoot" name="atmos_shoot"> --> +<!-- <item><ref id="atmos_tick" name="atmos_tick"> --> +<!-- <item><ref id="atmos_tock" name="atmos_tock"> --> +<!-- <item><ref id="atmos_zap" name="atmos_zap"> --> +</itemize> + +(incomplete) + + +<sect1><tt/c128.h/<label id="c128.h"><p> + +<itemize> +<item><ref id="c64mode" name="c64mode"> +<item><ref id="fast" name="fast"> +<item><ref id="slow" name="slow"> +<item><ref id="toggle_videomode" name="toggle_videomode"> +<item><ref id="videomode" name="videomode"> +</itemize> + + +<sect1><tt/c16.h/<label id="c16.h"><p> + +(incomplete) + + +<sect1><tt/c64.h/<label id="c64.h"><p> + +<itemize> +<item><ref id="get_ostype" name="get_ostype"> +</itemize> + + +<sect1><tt/cbm.h/<label id="cbm.h"><p> + +<itemize> +<item><ref id="cbm_k_acptr" name="cbm_k_acptr"> +<item><ref id="cbm_k_basin" name="cbm_k_basin"> +<item><ref id="cbm_k_bsout" name="cbm_k_bsout"> +<item><ref id="cbm_k_chkin" name="cbm_k_chkin"> +<item><ref id="cbm_k_ciout" name="cbm_k_ciout"> +<item><ref id="cbm_k_ckout" name="cbm_k_ckout"> +<item><ref id="cbm_k_clall" name="cbm_k_clall"> +<item><ref id="cbm_k_close" name="cbm_k_close"> +<item><ref id="cbm_k_clrch" name="cbm_k_clrch"> +<item><ref id="cbm_k_getin" name="cbm_k_getin"> +<item><ref id="cbm_k_iobase" name="cbm_k_iobase"> +<item><ref id="cbm_k_listen" name="cbm_k_listen"> +<item><ref id="cbm_k_load" name="cbm_k_load"> +<item><ref id="cbm_k_open" name="cbm_k_open"> +<item><ref id="cbm_k_readst" name="cbm_k_readst"> +<item><ref id="cbm_k_save" name="cbm_k_save"> +<item><ref id="cbm_k_setlfs" name="cbm_k_setlfs"> +<item><ref id="cbm_k_setnam" name="cbm_k_setnam"> +<item><ref id="cbm_k_unlsn" name="cbm_k_unlsn"> +<!-- <item><ref id="cbm_load" name="cbm_load"> --> +<!-- <item><ref id="cbm_open" name="cbm_open"> --> +<!-- <item><ref id="cbm_opendir" name="cbm_opendir"> --> +<!-- <item><ref id="cbm_read" name="cbm_read"> --> +<!-- <item><ref id="cbm_readdir" name="cbm_readdir"> --> +<!-- <item><ref id="cbm_save" name="cbm_save"> --> +<!-- <item><ref id="cbm_write" name="cbm_write"> --> +<!-- <item><ref id="get_tv" name="get_tv"> --> +</itemize> + +(incomplete) + + +<sect1><tt/cbm510.h/<label id="cbm510.h"><p> + +<itemize> +<item><ref id="peekbsys" name="peekbsys"> +<item><ref id="peekwsys" name="peekwsys"> +<item><ref id="pokebsys" name="pokebsys"> +<item><ref id="pokewsys" name="pokewsys"> +</itemize> + + +<sect1><tt/cbm610.h/<label id="cbm610.h"><p> + +<itemize> +<item><ref id="peekbsys" name="peekbsys"> +<item><ref id="peekwsys" name="peekwsys"> +<item><ref id="pokebsys" name="pokebsys"> +<item><ref id="pokewsys" name="pokewsys"> +</itemize> + + +<sect1><tt/cc65.h/<label id="cc65.h"><p> + +<!-- <itemize> --> +<!-- <item><ref id="cc65_cos" name="cc65_cos"> --> +<!-- <item><ref id="cc65_idiv32by16r16" name="cc65_idiv32by16r16"> --> +<!-- <item><ref id="cc65_imul16x16r32" name="cc65_imul16x16r32"> --> +<!-- <item><ref id="cc65_imul8x8r16" name="cc65_imul8x8r16"> --> +<!-- <item><ref id="cc65_sin" name="cc65_sin"> --> +<!-- <item><ref id="cc65_udiv32by16r16" name="cc65_udiv32by16r16"> --> +<!-- <item><ref id="cc65_umul16x16r32" name="cc65_umul16x16r32"> --> +<!-- <item><ref id="cc65_umul16x8r32" name="cc65_umul16x8r32"> --> +<!-- <item><ref id="cc65_umul8x8r16" name="cc65_umul8x8r16"> --> +<!-- </itemize> --> + +(incomplete) + + +<sect1><tt/conio.h/<label id="conio.h"><p> + +<itemize> +<item><ref id="bgcolor" name="bgcolor"> +<item><ref id="bordercolor" name="bordercolor"> +<item><ref id="cclear" name="cclear"> +<item><ref id="cclearxy" name="cclearxy"> +<item><ref id="cgetc" name="cgetc"> +<item><ref id="chline" name="chline"> +<item><ref id="chlinexy" name="chlinexy"> +<item><ref id="clrscr" name="clrscr"> +<item><ref id="cprintf" name="cprintf"> +<item><ref id="cputc" name="cputc"> +<item><ref id="cputcxy" name="cputcxy"> +<item><ref id="cputs" name="cputs"> +<item><ref id="cputsxy" name="cputsxy"> +<item><ref id="cursor" name="cursor"> +<item><ref id="cvline" name="cvline"> +<item><ref id="cvlinexy" name="cvlinexy"> +<item><ref id="gotox" name="gotox"> +<item><ref id="gotoxy" name="gotoxy"> +<item><ref id="gotoy" name="gotoy"> +<item><ref id="kbhit" name="kbhit"> +<item><ref id="revers" name="revers"> +<item><ref id="screensize" name="screensize"> +<item><ref id="textcolor" name="textcolor"> +<item><ref id="vcprintf" name="vcprintf"> +<item><ref id="wherex" name="wherex"> +<item><ref id="wherey" name="wherey"> +</itemize> + + +<sect1><tt/ctype.h/<label id="ctype.h"><p> + +<itemize> +<item><ref id="isalnum" name="isalnum"> +<item><ref id="isalpha" name="isalpha"> +<item><ref id="isascii" name="isascii"> +<item><ref id="isblank" name="isblank"> +<item><ref id="iscntrl" name="iscntrl"> +<item><ref id="isdigit" name="isdigit"> +<item><ref id="isgraph" name="isgraph"> +<item><ref id="islower" name="islower"> +<item><ref id="isprint" name="isprint"> +<item><ref id="ispunct" name="ispunct"> +<item><ref id="isspace" name="isspace"> +<item><ref id="isupper" name="isupper"> +<item><ref id="isxdigit" name="isxdigit"> +<item><ref id="tolower" name="tolower"> +<item><ref id="toupper" name="toupper"> +</itemize> + + +<sect1><tt/dbg.h/<label id="dbg.h"><p> + +<!-- <itemize> --> +<!-- <item><ref id="DbgInit" name="DbgInit"> --> +<!-- </itemize> --> + +(incomplete) + + +<sect1><tt/dio.h/<label id="dio.h"><p> + +<url url="dio.html" name="Low-level disk I/O API">. + + +<sect1><tt/dirent.h/<label id="dirent.h"><p> + +<itemize> +<item><ref id="_DE_ISDIR" name="_DE_ISDIR"> +<item><ref id="_DE_ISLBL" name="_DE_ISLBL"> +<item><ref id="_DE_ISLNK" name="_DE_ISLNK"> +<item><ref id="_DE_ISREG" name="_DE_ISREG"> +<item><ref id="closedir" name="closedir"> +<item><ref id="opendir" name="opendir"> +<item><ref id="readdir" name="readdir"> +<item><ref id="rewinddir" name="rewinddir"> +<item><ref id="seekdir" name="seekdir"> +<item><ref id="telldir" name="telldir"> +</itemize> + +(incomplete) + + +<sect1><tt/em.h/<label id="em.h"><p> + +<itemize> +<item><ref id="em_commit" name="em_commit"> +<item><ref id="em_copyfrom" name="em_copyfrom"> +<item><ref id="em_copyto" name="em_copyto"> +<item><ref id="em_install" name="em_install"> +<item><ref id="em_load_driver" name="em_load_driver"> +<item><ref id="em_map" name="em_map"> +<item><ref id="em_pagecount" name="em_pagecount"> +<item><ref id="em_uninstall" name="em_uninstall"> +<item><ref id="em_unload" name="em_unload"> +<item><ref id="em_use" name="em_use"> +</itemize> + + +<sect1><tt/errno.h/<label id="errno.h"><p> + +<!-- <itemize> --> +<!-- <item><ref id="_directerrno" name="_directerrno"> --> +<!-- <item><ref id="_mappederrno" name="_mappederrno"> --> +<!-- <item><ref id="_osmaperrno" name="_osmaperrno"> --> +<!-- <item><ref id="_seterrno" name="_seterrno"> --> +<!-- </itemize> --> + +(incomplete) + + +<sect1><tt/fcntl.h/<label id="fcntl.h"><p> + +<itemize> +<item><ref id="close" name="close"> +<item><ref id="creat" name="creat"> +<item><ref id="open" name="open"> +</itemize> + + +<sect1><tt/geos.h/<label id="geos.h"><p> + +(incomplete) + + +<sect1><tt/joystick.h/<label id="joystick.h"><p> + +<itemize> +<item><ref id="joy_count" name="joy_count"> +<item><ref id="joy_install" name="joy_install"> +<item><ref id="joy_load_driver" name="joy_load_driver"> +<item><ref id="joy_read" name="joy_read"> +<item><ref id="joy_uninstall" name="joy_uninstall"> +<item><ref id="joy_unload" name="joy_unload"> +</itemize> + + +<sect1><tt/locale.h/<label id="locale.h"><p> + +<itemize> +<item><ref id="localeconv" name="localeconv"> +<item><ref id="setlocale" name="setlocale"> +</itemize> + + +<sect1><tt/lynx.h/<label id="lynx.h"><p> + +<!-- <itemize> --> +<!-- <item><ref id="lynx_eeprom_erase" name="lynx_eeprom_erase"> --> +<!-- <item><ref id="lynx_eeprom_read" name="lynx_eeprom_read"> --> +<!-- <item><ref id="lynx_eeprom_write" name="lynx_eeprom_write"> --> +<!-- <item><ref id="lynx_eeread" name="lynx_eeread"> --> +<!-- <item><ref id="lynx_eewrite" name="lynx_eewrite"> --> +<!-- <item><ref id="lynx_exec" name="lynx_exec"> --> +<!-- <item><ref id="lynx_load" name="lynx_load"> --> +<!-- </itemize> --> + +(incomplete) + + +<sect1><tt/modload.h/<label id="modload.h"><p> + +<itemize> +<item><ref id="mod_load" name="mod_load"> +<item><ref id="mod_free" name="mod_free"> +</itemize> + + +<sect1><tt/mouse.h/<label id="mouse.h"><p> + +<itemize> +<item><ref id="mouse_buttons" name="mouse_buttons"> +<item><ref id="mouse_getbox" name="mouse_getbox"> +<item><ref id="mouse_geterrormsg" name="mouse_geterrormsg"> +<item><ref id="mouse_hide" name="mouse_hide"> +<item><ref id="mouse_info" name="mouse_info"> +<item><ref id="mouse_install" name="mouse_install"> +<item><ref id="mouse_ioctl" name="mouse_ioctl"> +<item><ref id="mouse_load_driver" name="mouse_load_driver"> +<item><ref id="mouse_move" name="mouse_move"> +<item><ref id="mouse_pos" name="mouse_pos"> +<item><ref id="mouse_setbox" name="mouse_setbox"> +<item><ref id="mouse_show" name="mouse_show"> +<item><ref id="mouse_uninstall" name="mouse_uninstall"> +<item><ref id="mouse_unload" name="mouse_unload"> +</itemize> + + +<sect1><tt/nes.h/<label id="nes.h"><p> + +<!-- <itemize> --> +<!-- <item><ref id="get_tv" name="get_tv"> --> +<!-- <item><ref id="waitvblank" name="waitvblank"> --> +<!-- </itemize> --> + +(incomplete) + + +<sect1><tt/o65.h/<label id="o65.h"><p> + +The <tt/o65.h/ header file contains structure and constant definitions that +may be used when dealing with files in <url +url="http://www.6502.org/users/andre/o65/fileformat.html" name="the o65 format">. +It does not declare any functions. + + +<sect1><tt/peekpoke.h/<label id="peekpoke.h"><p> + +<itemize> +<item><ref id="PEEK" name="PEEK"> +<item><ref id="PEEKW" name="PEEKW"> +<item><ref id="POKE" name="POKE"> +<item><ref id="POKEW" name="POKEW"> +</itemize> + + +<sect1><tt/pet.h/<label id="pet.h"><p> + +(incomplete) + + +<sect1><tt/plus4.h/<label id="plus4.h"><p> + +(incomplete) + + +<sect1><tt/serial.h/<label id="serial.h"><p> + +The <tt/serial.h/ header file contains definitions for initializing serial +communication. + +<itemize> +<item><ref id="ser_close" name="ser_close"> +<item><ref id="ser_get" name="ser_get"> +<item><ref id="ser_install" name="ser_install"> +<item><ref id="ser_ioctl" name="ser_ioctl"> +<item><ref id="ser_load_driver" name="ser_load_driver"> +<item><ref id="ser_open" name="ser_open"> +<item><ref id="ser_put" name="ser_put"> +<item><ref id="ser_status" name="ser_status"> +<item><ref id="ser_uninstall" name="ser_uninstall"> +<item><ref id="ser_unload" name="ser_unload"> +</itemize> + + +<sect1><tt/setjmp.h/<label id="setjmp.h"><p> + +<itemize> +<item><ref id="setjmp" name="setjmp"> +<item><ref id="longjmp" name="longjmp"> +</itemize> + + +<sect1><tt/signal.h/<label id="signal.h"><p> + +<itemize> +<item><ref id="raise" name="raise"> +<item><ref id="signal" name="signal"> +</itemize> + + +<sect1><tt/stdarg.h/<label id="stdarg.h"><p> + +(incomplete) + + +<sect1><tt/stdbool.h/<label id="stdbool.h"><p> + +(incomplete) + + +<sect1><tt/stddef.h/<label id="stddef.h"><p> + +<itemize> +<item><ref id="offsetof" name="offsetof"> +</itemize> + + +<sect1><tt/stdio.h/<label id="stdio.h"><p> + +<itemize> +<item><ref id="_poserror" name="_poserror"> +<item><ref id="clearerr" name="clearerr"> +<!-- <item><ref id="fclose" name="fclose"> --> +<!-- <item><ref id="fdopen" name="fdopen"> --> +<item><ref id="feof" name="feof"> +<item><ref id="ferror" name="ferror"> +<!-- <item><ref id="fflush" name="fflush"> --> +<!-- <item><ref id="fgetc" name="fgetc"> --> +<!-- <item><ref id="fgetpos" name="fgetpos"> --> +<!-- <item><ref id="fgets" name="fgets"> --> +<item><ref id="fileno" name="fileno"> +<!-- <item><ref id="fopen" name="fopen"> --> +<!-- <item><ref id="fprintf" name="fprintf"> --> +<!-- <item><ref id="fputc" name="fputc"> --> +<!-- <item><ref id="fputs" name="fputs"> --> +<!-- <item><ref id="fread" name="fread"> --> +<!-- <item><ref id="freopen" name="freopen"> --> +<!-- <item><ref id="fscanf" name="fscanf"> --> +<!-- <item><ref id="fseek" name="fseek"> --> +<!-- <item><ref id="fsetpos" name="fsetpos"> --> +<!-- <item><ref id="ftell" name="ftell"> --> +<!-- <item><ref id="fwrite" name="fwrite"> --> +<!-- <item><ref id="getc" name="getc"> --> +<!-- <item><ref id="getchar" name="getchar"> --> +<!-- <item><ref id="gets" name="gets"> --> +<!-- <item><ref id="printf" name="printf"> --> +<!-- <item><ref id="putc" name="putc"> --> +<!-- <item><ref id="putchar" name="putchar"> --> +<!-- <item><ref id="puts" name="puts"> --> +<item><ref id="rename" name="rename"> +<item><ref id="remove" name="remove"> +<!-- <item><ref id="rewind" name="rewind"> --> +<!-- <item><ref id="scanf" name="scanf"> --> +<!-- <item><ref id="snprintf" name="snprintf"> --> +<!-- <item><ref id="sprintf" name="sprintf"> --> +<!-- <item><ref id="sscanf" name="sscanf"> --> +<!-- <item><ref id="vfprintf" name="vfprintf"> --> +<!-- <item><ref id="vfscanf" name="vfscanf"> --> +<!-- <item><ref id="vprintf" name="vprintf"> --> +<!-- <item><ref id="vscanf" name="vscanf"> --> +<!-- <item><ref id="vsnprintf" name="vsnprintf"> --> +<!-- <item><ref id="vsprintf" name="vsprintf"> --> +<!-- <item><ref id="vsscanf" name="vsscanf"> --> +</itemize> + +(incomplete) + + +<sect1><tt/stdlib.h/<label id="stdlib.h"><p> + +<itemize> +<item><ref id="_heapadd" name="_heapadd"> +<item><ref id="_heapblocksize" name="_heapblocksize"> +<item><ref id="_heapmaxavail" name="_heapmaxavail"> +<item><ref id="_heapmemavail" name="_heapmemavail"> +<item><ref id="_randomize" name="_randomize"> +<item><ref id="_swap" name="_swap"> +<item><ref id="abort" name="abort"> +<item><ref id="abs" name="abs"> +<item><ref id="atexit" name="atexit"> +<item><ref id="atoi" name="atoi"> +<item><ref id="atol" name="atol"> +<item><ref id="bsearch" name="bsearch"> +<item><ref id="calloc" name="calloc"> +<item><ref id="div" name="div"> +<item><ref id="exit" name="exit"> +<item><ref id="free" name="free"> +<item><ref id="getenv" name="getenv"> +<item><ref id="itoa" name="itoa"> +<item><ref id="labs" name="labs"> +<item><ref id="ltoa" name="ltoa"> +<item><ref id="malloc" name="malloc"> +<item><ref id="perror" name="perror"> +<!-- <item><ref id="posix_memalign" name="posix_memalign"> --> +<!-- <item><ref id="putenv" name="putenv"> --> +<item><ref id="qsort" name="qsort"> +<item><ref id="rand" name="rand"> +<item><ref id="realloc" name="realloc"> +<item><ref id="srand" name="srand"> +<!-- <item><ref id="system" name="system"> --> +<item><ref id="ultoa" name="ultoa"> +<item><ref id="utoa" name="utoa"> +</itemize> + +(incomplete) + + +<sect1><tt/string.h/<label id="string.h"><p> + +<itemize> +<item><ref id="_stroserror" name="_stroserror"> +<item><ref id="bzero" name="bzero"> +<item><ref id="memchr" name="memchr"> +<item><ref id="memcmp" name="memcmp"> +<item><ref id="memcpy" name="memcpy"> +<item><ref id="memmove" name="memmove"> +<item><ref id="memset" name="memset"> +<item><ref id="strcasecmp" name="strcasecmp"> +<item><ref id="strcat" name="strcat"> +<item><ref id="strchr" name="strchr"> +<item><ref id="strcmp" name="strcmp"> +<item><ref id="strcoll" name="strcoll"> +<item><ref id="strcpy" name="strcpy"> +<item><ref id="strcspn" name="strcspn"> +<item><ref id="strdup" name="strdup"> +<item><ref id="strerror" name="strerror"> +<item><ref id="stricmp" name="stricmp"> +<item><ref id="strlen" name="strlen"> +<item><ref id="strlower" name="strlower"> +<item><ref id="strlwr" name="strlwr"> +<item><ref id="strncat" name="strncat"> +<item><ref id="strncmp" name="strncmp"> +<item><ref id="strncpy" name="strncpy"> +<item><ref id="strqtok" name="strqtok"> +<item><ref id="strrchr" name="strrchr"> +<item><ref id="strspn" name="strspn"> +<item><ref id="strstr" name="strstr"> +<item><ref id="strtok" name="strtok"> +<item><ref id="strxfrm" name="strxfrm"> +<item><ref id="strupper" name="strupper"> +<item><ref id="strupr" name="strupr"> +</itemize> + +(incomplete) + + +<sect1><tt/tgi.h/<label id="tgi.h"><p> + +<itemize> +<item><ref id="tgi_arc" name="tgi_arc"> +<item><ref id="tgi_bar" name="tgi_bar"> +<item><ref id="tgi_circle" name="tgi_circle"> +<item><ref id="tgi_clear" name="tgi_clear"> +<item><ref id="tgi_done" name="tgi_done"> +<item><ref id="tgi_ellipse" name="tgi_ellipse"> +<item><ref id="tgi_free_vectorfont" name="tgi_free_vectorfont"> +<item><ref id="tgi_getaspectratio" name="tgi_getaspectratio"> +<item><ref id="tgi_getcolor" name="tgi_getcolor"> +<item><ref id="tgi_getcolorcount" name="tgi_getcolorcount"> +<item><ref id="tgi_getdefpalette" name="tgi_getdefpalette"> +<item><ref id="tgi_geterror" name="tgi_geterror"> +<item><ref id="tgi_geterrormsg" name="tgi_geterrormsg"> +<item><ref id="tgi_getmaxcolor" name="tgi_getmaxcolor"> +<item><ref id="tgi_getmaxx" name="tgi_getmaxx"> +<item><ref id="tgi_getmaxy" name="tgi_getmaxy"> +<item><ref id="tgi_getpagecount" name="tgi_getpagecount"> +<item><ref id="tgi_getpalette" name="tgi_getpalette"> +<item><ref id="tgi_getpixel" name="tgi_getpixel"> +<item><ref id="tgi_gettextheight" name="tgi_gettextheight"> +<item><ref id="tgi_gettextwidth" name="tgi_gettextwidth"> +<item><ref id="tgi_getxres" name="tgi_getxres"> +<item><ref id="tgi_getyres" name="tgi_getyres"> +<item><ref id="tgi_gotoxy" name="tgi_gotoxy"> +<item><ref id="tgi_init" name="tgi_init"> +<item><ref id="tgi_install" name="tgi_install"> +<item><ref id="tgi_install_vectorfont" name="tgi_install_vectorfont"> +<item><ref id="tgi_ioctl" name="tgi_ioctl"> +<item><ref id="tgi_line" name="tgi_line"> +<item><ref id="tgi_lineto" name="tgi_lineto"> +<item><ref id="tgi_load_driver" name="tgi_load_driver"> +<item><ref id="tgi_load_vectorfont" name="tgi_load_vectorfont"> +<item><ref id="tgi_outtext" name="tgi_outtext"> +<item><ref id="tgi_outtextxy" name="tgi_outtextxy"> +<item><ref id="tgi_setaspectratio" name="tgi_setaspectratio"> +<item><ref id="tgi_setcolor" name="tgi_setcolor"> +<item><ref id="tgi_setdrawpage" name="tgi_setdrawpage"> +<item><ref id="tgi_setpalette" name="tgi_setpalette"> +<item><ref id="tgi_setpixel" name="tgi_setpixel"> +<item><ref id="tgi_setviewpage" name="tgi_setviewpage"> +<item><ref id="tgi_settextscale" name="tgi_settextscale"> +<item><ref id="tgi_settextstyle" name="tgi_settextstyle"> +<item><ref id="tgi_uninstall" name="tgi_uninstall"> +<item><ref id="tgi_unload" name="tgi_unload"> +</itemize> + +<sect1><tt/time.h/<label id="time.h"><p> + +<itemize> +<!-- <item><ref id="_systime" name="_systime"> --> +<!-- <item><ref id="asctime" name="asctime"> --> +<item><ref id="clock" name="clock"> +<!-- <item><ref id="ctime" name="ctime"> --> +<!-- <item><ref id="gmtime" name="gmtime"> --> +<!-- <item><ref id="localtime" name="localtime"> --> +<!-- <item><ref id="mktime" name="mktime"> --> +<!-- <item><ref id="strftime" name="strftime"> --> +<item><ref id="time" name="time"> +</itemize> + +(incomplete) + + +<sect1><tt/unistd.h/<label id="unistd.h"><p> + +<itemize> +<!-- <item><ref id="chdir" name="chdir"> --> +<item><ref id="exec" name="exec"> +<!-- <item><ref id="getcwd" name="getcwd"> --> +<item><ref id="getopt" name="getopt"> +<!-- <item><ref id="lseek" name="lseek"> --> +<!-- <item><ref id="mkdir" name="mkdir"> --> +<!-- <item><ref id="read" name="read"> --> +<!-- <item><ref id="rmdir" name="rmdir"> --> +<item><ref id="sleep" name="sleep"> +<item><ref id="unlink" name="unlink"> +<!-- <item><ref id="write" name="write"> --> +</itemize> + +(incomplete) + + +<sect1><tt/vic20.h/<label id="vic20.h"><p> + +(incomplete) + + +<sect1><tt/zlib.h/<label id="zlib.h"><p> + +<!-- <itemize> --> +<!-- <item><ref id="adler32" name="adler32"> --> +<!-- <item><ref id="crc32" name="crc32"> --> +<!-- <item><ref id="inflatemem" name="inflatemem"> --> +<!-- <item><ref id="uncompress" name="uncompress"> --> +<!-- </itemize> --> + +(incomplete) + + +<sect>Alphabetical function reference<p> + +<sect1>_DE_ISDIR<label id="_DE_ISDIR"><p> + +<quote> +<descrip> +<tag/Function/Determine if a directory entry specifies a directory. +<tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ +<tag/Declaration/<tt/int _DE_ISDIR(unsigned char type);/ +<tag/Description/The function is called with the type of a directory entry +taken from a <tt/struct dirent/ and returns true if the entry designates +a directory. +<tag/Limits/ +<itemize> +<item>The function is actually a macro. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="_DE_ISLBL" name="_DE_ISLBL">, +<ref id="_DE_ISLNK" name="_DE_ISLNK">, +<ref id="_DE_ISREG" name="_DE_ISREG"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_DE_ISLBL<label id="_DE_ISLBL"><p> + +<quote> +<descrip> +<tag/Function/Determine if a directory entry specifies a disk label. +<tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ +<tag/Declaration/<tt/int _DE_ISLBL(unsigned char type);/ +<tag/Description/The function is called with the type of a directory entry +taken from a <tt/struct dirent/ and returns true if the entry designates +a disk label. +<tag/Limits/ +<itemize> +<item>The function is actually a macro. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="_DE_ISDIR" name="_DE_ISDIR">, +<ref id="_DE_ISLNK" name="_DE_ISLNK">, +<ref id="_DE_ISREG" name="_DE_ISREG"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_DE_ISLNK<label id="_DE_ISLNK"><p> + +<quote> +<descrip> +<tag/Function/Determine if a directory entry specifies a link. +<tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ +<tag/Declaration/<tt/int _DE_ISLNK(unsigned char type);/ +<tag/Description/The function is called with the type of a directory entry +taken from a <tt/struct dirent/ and returns true if the entry designates +a link. +<tag/Limits/ +<itemize> +<item>The function is actually a macro. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="_DE_ISDIR" name="_DE_ISDIR">, +<ref id="_DE_ISLBL" name="_DE_ISLBL">, +<ref id="_DE_ISREG" name="_DE_ISREG"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_DE_ISREG<label id="_DE_ISREG"><p> + +<quote> +<descrip> +<tag/Function/Determine if a directory entry specifies a regular file. +<tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ +<tag/Declaration/<tt/int _DE_ISREG(unsigned char type);/ +<tag/Description/The function is called with the type of a directory entry +taken from a <tt/struct dirent/ and returns true if the entry designates +a regular file. +<tag/Limits/ +<itemize> +<item>The function is actually a macro. +<item>A "regular file" means anything with data in it. This might still mean +that special processing is needed, when accessing the file. Relative files of +the CBM systems are classified as being "regular" files, for example. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="_DE_ISDIR" name="_DE_ISDIR">, +<ref id="_DE_ISLBL" name="_DE_ISLBL">, +<ref id="_DE_ISLNK" name="_DE_ISLNK"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_heapadd<label id="_heapadd"><p> + +<quote> +<descrip> +<tag/Function/Add a block to the heap. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void __fastcall__ _heapadd (void* mem, size_t size);/ +<tag/Description/The function adds a block of raw memory to the heap. +<tag/Limits/ +<itemize> +<item>The minimum blocksize that can be added is 6 bytes; the function will +ignore smaller blocks. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="_heapblocksize" name="_heapblocksize">, +<ref id="_heapmaxavail" name="_heapmaxavail">, +<ref id="_heapmemavail" name="_heapmemavail">, +<ref id="calloc" name="calloc">, +<ref id="free" name="free">, +<ref id="malloc" name="malloc">, +<ref id="realloc" name="realloc"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_heapblocksize<label id="_heapblocksize"><p> + +<quote> +<descrip> +<tag/Function/Return the size of an allocated block. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/size_t __fastcall__ _heapblocksize (const void* block);/ +<tag/Description/The function returns the size of a block that must have +previously been allocated by <tt/<ref id="malloc" name="malloc">/, <tt/<ref +id="calloc" name="calloc">/ or <tt/<ref id="realloc" name="realloc">/. +<tag/Limits/ +<itemize> +<item>Passing a pointer to a block that was is not the result of one of the +allocation functions, or that has been free'd will give unpredicable results. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="_heapadd" name="_heapadd">, +<ref id="_heapmaxavail" name="_heapmaxavail">, +<ref id="_heapmemavail" name="_heapmemavail">, +<ref id="calloc" name="calloc">, +<ref id="free" name="free">, +<ref id="malloc" name="malloc">, +<ref id="realloc" name="realloc"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_heapmaxavail<label id="_heapmaxavail"><p> + +<quote> +<descrip> +<tag/Function/Return the largest block that is available on the heap. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/size_t _heapmaxavail (void);/ +<tag/Description/The function returns the size of the largest block that may +be allocated from the heap using <tt/<ref id="malloc" name="malloc">/. +<tag/Availability/cc65 +<tag/See also/ +<ref id="_heapadd" name="_heapadd">, +<ref id="_heapblocksize" name="_heapblocksize">, +<ref id="_heapmemavail" name="_heapmemavail">, +<ref id="calloc" name="calloc">, +<ref id="free" name="free">, +<ref id="malloc" name="malloc">, +<ref id="realloc" name="realloc"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_heapmemavail<label id="_heapmemavail"><p> + +<quote> +<descrip> +<tag/Function/Return the total available space on the heap. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/size_t __fastcall__ _heapmemavail (void);/ +<tag/Description/The function returns the total number of bytes available on +the heap. +<tag/Limits/ +<itemize> +<item>This function is of less use than usually assumed, since the returned +heap space may be available but not in one block. So even if this function +says that several times more heap space is available than needed, <ref +id="malloc" name="malloc"> may still return <tt/NULL/. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="_heapadd" name="_heapadd">, +<ref id="_heapblocksize" name="_heapblocksize">, +<ref id="_heapmaxavail" name="_heapmaxavail">, +<ref id="calloc" name="calloc">, +<ref id="free" name="free">, +<ref id="malloc" name="malloc">, +<ref id="realloc" name="realloc"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_poserror<label id="_poserror"><p> + +<quote> +<descrip> +<tag/Function/Print an error message for the error in <tt/_oserror/. +<tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ +<tag/Declaration/<tt/void __fastcall__ _poserror (const char* msg);/ +<tag/Description/<tt/_poserror/ prints an error message to <tt/stderr/. If +<tt/msg/ is not <tt/NULL/ and not an empty string, it is printed followed by +a colon and a blank. Then the error message for the current contents of +<tt/_oserror/ are printed followed by a newline. The message output is the +same as returned by <tt/<ref id="_stroserror" name="_stroserror">/ with an +argument of <tt/_oserror/. +<tag/Limits/ +<itemize> +<item>Since operating system specific error code are - you guessed it - +operating system specific, the value in <tt/_oserror/ and the message that is +printed depends on the cc65 target. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="_stroserror" name="_stroserror">, +<ref id="perror" name="perror"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_randomize<label id="_randomize"><p> + +<quote> +<descrip> +<tag/Function/Initialize the pseudo random number generator. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void _randomize (void);/ +<tag/Description/The function initializes the random number generator with +a seed derived from fast changing hardware events, so the seed itself can be +considered random to a certain degree. +<tag/Limits/<itemize> +<item>The randomness of the seed depends on the machine hardware. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="rand" name="rand">, +<ref id="srand" name="srand"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_stroserror<label id="_stroserror"><p> + +<quote> +<descrip> +<tag/Function/Return a string describing an OS specific error code. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/const char* __fastcall__ _stroserror (unsigned char errcode);/ +<tag/Description/<tt/_stroserror/ will return a string describing the given +operating system specific error code. +<tag/Limits/<itemize> +<item>Since operating system specific error code are - you guessed it - +operating system specific, the parameter and the string returned depend on the +cc65 target. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="strerror" name="strerror"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_swap<label id="_swap"><p> + +<quote> +<descrip> +<tag/Function/Swap the contents of memory areas. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void __fastcall__ _swap (void* p, void* q, size_t size);/ +<tag/Description/<tt/_swap/ will swap (exchange) the contents of the two memory +areas pointed to by <tt/p/ and <tt/q/. Both memory areas are assumed to be +<tt/size/ bytes in size. +<tag/Limits/<itemize> +<item>The memory areas may not overlap, otherwise the results are undefined. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="memcpy" name="memcpy">, +<ref id="memmove" name="memmove"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>_sys<label id="_sys"><p> + +<quote> +<descrip> +<tag/Function/Call a subroutine passing register values. +<tag/Header/<tt/<ref id="6502.h" name="6502.h">/ +<tag/Declaration/<tt/void __fastcall__ _sys (struct regs* r);/ +<tag/Description/The function will call the subroutine at the address +specified in the <tt/pc/ member of the passed <tt/regs/ structure. All +registers and the CPU flags are set to the values given in the <tt/regs/ +structure. On return from the subroutine, the new values of the registers and +flags are stored back overwriting the old values. +<tag/Limits/<itemize> +<item>Bits 4 and 5 of the flags value in the <tt/regs/ structure are ignored +when calling the subroutine (they are unchanged from their current values). +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/Example/None. +</descrip> +</quote> + + +<sect1>BRK<label id="BRK"><p> + +<quote> +<descrip> +<tag/Function/Insert a 6502 BRK instrunction into the code. +<tag/Header/<tt/<ref id="6502.h" name="6502.h">/ +<tag/Declaration/<tt/void BRK (void);/ +<tag/Description/The function will insert a 6502 BRK instruction into the code +which may be used to trigger a debugger. +<tag/Limits/<itemize> +<item>The function is actually a macro. +<item>The inserted instruction may lead to unexpected results if no debugger +is present. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="CLI" name="CLI">, +<ref id="SEI" name="SEI"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>CLI<label id="CLI"><p> + +<quote> +<descrip> +<tag/Function/Insert a 6502 CLI instrunction into the code. +<tag/Header/<tt/<ref id="6502.h" name="6502.h">/ +<tag/Declaration/<tt/void CLI (void);/ +<tag/Description/The function will insert a 6502 CLI instruction into the code, +so interrupts are enabled. Enabling interrupts has no effects if they are +already enabled (the default). +<tag/Limits/<itemize> +<item>The function is actually a macro. +<item>Disabling interrupts may lead to unexpected results. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="BRK" name="BRK">, +<ref id="SEI" name="SEI"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>PEEK<label id="PEEK"><p> + +<quote> +<descrip> +<tag/Function/Read a byte from memory. +<tag/Header/<tt/<ref id="peekpoke.h" name="peekpoke.h">/ +<tag/Declaration/<tt/unsigned char PEEK (unsigned addr);/ +<tag/Description/The function will read the absolute memory given by <tt/addr/ +and return the value read. +<tag/Limits/<itemize> +<item>The function is actually a macro. +<item>This function depends highly on the platform and environment. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="PEEKW" name="PEEKW">, +<ref id="POKE" name="POKE"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>PEEKW<label id="PEEKW"><p> + +<quote> +<descrip> +<tag/Function/Read a word (two bytes) from memory. +<tag/Header/<tt/<ref id="peekpoke.h" name="peekpoke.h">/ +<tag/Declaration/<tt/unsigned PEEKW (unsigned addr);/ +<tag/Description/The function will read the absolute memory given by <tt/addr/ +and return the value read. The byte read from the higher address is the high +byte of the return value. +<tag/Limits/<itemize> +<item>The function is actually a macro. +<item>This function depends highly on the platform and environment. +<item>The order in which the two bytes are read is unspecified and may +depend of the address expression used. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="PEEK" name="PEEK">, +<ref id="POKE" name="POKE"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>POKE<label id="POKE"><p> + +<quote> +<descrip> +<tag/Function/Write a byte to memory. +<tag/Header/<tt/<ref id="peekpoke.h" name="peekpoke.h">/ +<tag/Declaration/<tt/void POKE (unsigned addr, unsigned char val);/ +<tag/Description/The function writes the value <tt/val/ to the absolute +memory address given by <tt/addr/. +<tag/Limits/<itemize> +<item>The function is actually a macro. +<item>This function depends highly on the platform and environment. +<item>Careless use will cause the program to act strange or may crash the +machine. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="PEEK" name="PEEK">, +<ref id="POKEW" name="POKEW"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>POKEW<label id="POKEW"><p> + +<quote> +<descrip> +<tag/Function/Write a word (two bytes) to memory. +<tag/Header/<tt/<ref id="peekpoke.h" name="peekpoke.h">/ +<tag/Declaration/<tt/void POKEW (unsigned addr, unsigned val);/ +<tag/Description/The function writes the value <tt/val/ to the absolute +memory address given by <tt/addr/. The low byte of <tt/val/ is written to +the <tt/addr/, the high byte is written to <tt/addr+1/. +<tag/Limits/<itemize> +<item>The function is actually a macro. +<item>This function depends highly on the platform and environment. +<item>Careless use will cause the program to act strange or may crash the +machine. +<item>The order in which the two bytes are written is unspecified and may +depend of the address expression used. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="PEEK" name="PEEK">, +<ref id="POKE" name="POKE"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>SEI<label id="SEI"><p> + +<quote> +<descrip> +<tag/Function/Insert a 6502 SEI instrunction into the code. +<tag/Header/<tt/<ref id="6502.h" name="6502.h">/ +<tag/Declaration/<tt/void SEI (void);/ +<tag/Description/The function will insert a 6502 SEI instruction into the code, +so interrupts are disabled. Note that non maskable interrupts cannot be +disabled. +<tag/Limits/<itemize> +<item>The function is actually a macro. +<item>Disabling interrupts may lead to unexpected results. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="BRK" name="BRK">, +<ref id="CLI" name="CLI"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>abort<label id="abort"><p> + +<quote> +<descrip> +<tag/Function/Terminates a program abnormally. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void abort (void);/ +<tag/Description/<tt/abort/ raises <tt/SIGABRT/, writes a termination message +on stderr, then terminates the program with an exit code of 3. +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="assert" name="assert">, +<ref id="exit" name="exit">, +<ref id="raise" name="raise"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>abs<label id="abs"><p> + +<quote> +<descrip> +<tag/Function/Returns the absolute value of an integer. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/int __fastcall__ abs (int v);/ +<tag/Description/<tt/abs/ returns the absolute value of the argument passed to +the function. +<tag/Limits/<itemize> +<item>The return value is undefined if <tt/INT_MIN/ is passed to the function. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="labs" name="labs"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>assert<label id="assert"><p> + +<quote> +<descrip> +<tag/Function/Test a condition and possibly abort. +<tag/Header/<tt/<ref id="assert.h" name="assert.h">/ +<tag/Declaration/<tt/void assert (int cond);/ +<tag/Description/<tt/assert/ is a macro that expands to a <tt/id/ +statement. If the condition evaluates t zero (false), assert prints a message +on stderr and aborts the program. +<tag/Limits/<itemize> +<item>The function is actually a macro. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="abort" name="abort">, +<ref id="exit" name="exit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>atexit<label id="atexit"><p> + +<quote> +<descrip> +<tag/Function/Register an exit function. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/int __fastcall__ atexit (void (*exitfunc) (void));/ +<tag/Description/<tt/atexit/ registers the function pointed to by +<tt/exitfunc/ as an exit function. Exit functions are called when the program +terminates, they are called in LIFO order (the last function registered is +called first). <tt/atexit/ returns zero on success and a nonzero value on +failure. +<tag/Limits/<itemize> +<item>A maximum of 5 exit functions can be registered. +<item>There is no way to unregister an exit function. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="abort" name="abort">, +<ref id="exit" name="exit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>atmos_load<label id="atmos_load"><p> + +<quote> +<descrip> +<tag/Function/Load Atmos tape. +<tag/Header/<tt/<ref id="atmos.h" name="atmos.h">/ +<tag/Declaration/<tt/void __fastcall__ atmos_load(const char* name);/ +<tag/Description/<tt/atmos_load/ reads a memory block from tape. +<tag/Availability/cc65 +<tag/See also/ +<ref id="atmos_save" name="atmos_save"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>atmos_save<label id="atmos_save"><p> + +<quote> +<descrip> +<tag/Function/Save Atmos tape. +<tag/Header/<tt/<ref id="atmos.h" name="atmos.h">/ +<tag/Declaration/<tt/void __fastcall__ atmos_save(const char* name, const void* start, const void* end);/ +<tag/Description/<tt/atmos_save/ writes a memory block to tape. +<tag/Availability/cc65 +<tag/See also/ +<ref id="atmos_load" name="atmos_load"> +<tag/Example/<verb> +atmos_save("hires", 0xa000, 0xc000); +</verb> +</descrip> +</quote> + + +<sect1>atoi<label id="atoi"><p> + +<quote> +<descrip> +<tag/Function/Convert a string to an integer. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/int __fastcall__ atoi (const char* s);/ +<tag/Description/<tt/atoi/ converts the given string into an integer. +Conversion stops as soon as any invalid character is encountered. +<tag/Limits/<itemize> +<item>There is no way to detect any conversion errors. +<item>The function does not check for an numerical overflow when converting. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="atol" name="atol">, +<ref id="itoa" name="itoa">, +<ref id="ltoa" name="ltoa">, +<ref id="ultoa" name="ultoa">, +<ref id="utoa" name="utoa"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>atol<label id="atol"><p> + +<quote> +<descrip> +<tag/Function/Convert a string to a long integer. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/long __fastcall__ atol (const char* s);/ +<tag/Description/<tt/atol/ converts the given string into a long integer. +Conversion stops as soon as any invalid character is encountered. +<tag/Limits/<itemize> +<item>There is no way to detect any conversion errors. +<item>The function does not check for an numerical overflow when converting. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="atoi" name="atoi">, +<ref id="itoa" name="itoa">, +<ref id="ltoa" name="ltoa">, +<ref id="ultoa" name="ultoa">, +<ref id="utoa" name="utoa"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>bgcolor<label id="bgcolor"><p> + +<quote> +<descrip> +<tag/Function/Set the background text color. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ bgcolor (unsigned char color);/ +<tag/Description/The function will set a new background color and return the +old (current) one. The background color is valid for the whole text output +area of the screen, not just for new text. +<tag/Limits/<itemize> +<item>Background colors are system dependent. The function may have no effect +on systems where the background color cannot be changed. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="bordercolor" name="bordercolor">, +<ref id="textcolor" name="textcolor"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>bordercolor<label id="bordercolor"><p> + +<quote> +<descrip> +<tag/Function/Set the border (frame) color. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ bordercolor (unsigned char color);/ +<tag/Description/The function will set a new border color. It returns the old +(current) border color. +<tag/Limits/<itemize> +<item>Border colors are system dependent. The function may have no effect +on systems where the border color cannot be changed. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="bgcolor" name="bgcolor">, +<ref id="textcolor" name="textcolor"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>bsearch<label id="bsearch"><p> + +<quote> +<descrip> +<tag/Function/Do a binary search in a sorted array. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void* __fastcall__ bsearch (const void* key, +const void* base, size_t n, size_t size, +int (*cmp) (const void*, const void*));/ +<tag/Description/<tt/bsearch/ searches a sorted array for a member that +matches the one pointed to by <tt/key/. <tt/base/ is the address of the array, +<tt/n/ is the number of elements, <tt/size/ the size of an element and <tt/cmp/ +the function used to compare the members against the key. The function returns +a pointer to the member found, or <tt/NULL/ if there was no match. +<tag/Limits/ +<itemize> +<item>The contents of the array must be sorted in ascending order according to +the compare function given. +<item>If there are multiple members that match the key, the function will +return one of the members. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="qsort" name="qsort"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>bzero<label id="bzero"><p> + +<quote> +<descrip> +<tag/Function/Fill a memory area with zeroes. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/void __fastcall__ bzero (void* p, size_t count);/ +<tag/Description/<tt/bzero/ fills the memory area pointed to by <tt/p/ with +zero. +<tag/Limits/ +<itemize> +<item>The function is non standard and therefore only available in non ANSI +mode. You should use <tt/<ref id="memset" name="memset">/ instead. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="_swap" name="_swap">, +<ref id="memcpy" name="memcpy">, +<ref id="memmove" name="memmove">, +<ref id="memset" name="memset">, +<tag/Example/None. +</descrip> +</quote> + + +<sect1>c64mode<label id="c64mode"><p> + +<quote> +<descrip> +<tag/Function/Switch the C128 into C64 compatible mode. +<tag/Header/<tt/<ref id="c128.h" name="c128.h">/ +<tag/Declaration/<tt/void c64mode (void);/ +<tag/Description/The function will cause the machine to reboot into C64 mode. +<tag/Limits/<itemize> +<item>The function is specific to the C128. +<item>The function will not return to the caller. +</itemize> +<tag/Availability/C128 +<tag/Example/None. +</descrip> +</quote> + + +<sect1>calloc<label id="calloc"><p> + +<quote> +<descrip> +<tag/Function/Allocate and clear memory. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void* __fastcall__ calloc (size_t n, size_t size);/ +<tag/Description/<tt/calloc/ allocates memory for an array of <tt/n/ elements +of size <tt/size/, clears the whole block with binary zeroes and returns a +pointer to it. On error (not enough memory available), <tt/calloc/ returns +<tt/NULL/. +<tag/Limits/ +<itemize> +<item>Clearing the memory may not have the expected effect on all platforms: +pointers in the block may not be <tt/NULL/ and floating point variables may +not be zero (0.0). In other words: The "clearing" effect of this function +should be used with care for portable programs. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="_heapadd" name="_heapadd">, +<ref id="_heapblocksize" name="_heapblocksize">, +<ref id="_heapmaxavail" name="_heapmaxavail">, +<ref id="_heapmemavail" name="_heapmemavail">, +<ref id="free" name="free">, +<ref id="malloc" name="malloc">, +<ref id="realloc" name="realloc"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_acptr<label id="cbm_k_acptr"><p> + +<quote> +<descrip> +<tag/Function/Input byte from serial bus +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/unsigned char cbm_k_acptr (void);/ +<tag/Description/The function returns a byte of data, which it +gets from the current TALKer on the serial bus. +In order to receive the data, the device must have previously been +sent a command to TALK and a secondary address if it needs one. +<tag/Limits/<itemize> +<item> +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_talk" name="cbm_k_talk">, +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_basin<label id="cbm_k_basin"><p> + +<quote> +<descrip> +<tag/Function/Input a Character from the Current Device +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/unsigned char cbm_k_basin (void);/ +<tag/Description/The function returns a character from the current input device. +Device must first have been OPENed and then designated as the input channel by the CHKIN routine. +When this function is called, the next byte of data available from the device is returned. +Exception is the routine for the keyboard device (which is the default input device). +<tag/Limits/<itemize> +<item> +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_open" name="cbm_k_open">, +<ref id="cbm_k_chkin" name="cbm_k_chkin"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_bsout<label id="cbm_k_bsout"><p> + +<quote> +<descrip> +<tag/Function/Output a byte +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/void __fastcall__ cbm_k_bsout (unsigned char C);/ +<tag/Description/Function sends the character to the current output device. +Unless a device has been OPENed and designated as the +current output channel using the CHKOUT routine, the character is +printed to the screen, which is the default output device. If the +cassette is the current device, outputting a byte will only add it to +the buffer. No actual transmission of data will occur until the +192-byte buffer is full. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_open" name="cbm_k_open">, +<ref id="cbm_k_chkin" name="cbm_k_chkout"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_chkin<label id="cbm_k_chkin"><p> + +<quote> +<descrip> +<tag/Function/Designate a Logical File As the Current Input Channel +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ cbm_k_chkin (unsigned char FN);/ +<tag/Description/If you wish to +get data from any device other than the keyboard, this function must be +called after OPENing the device, before you can get a data byte with +the cbm_k_basin or cbm_k_getin routine. When called, the routine will designate +the logical file whose file number was supplied as the +current file, its device as the current device, and its secondary +address as the current secondary address. If the device on the +channel is a serial device, which requires a TALK command and +sometimes a secondary address, function will send them over the +serial bus. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_open" name="cbm_k_open">, +<ref id="cbm_k_basin" name="cbm_k_basin">, +<ref id="cbm_k_getin" name="cbm_k_getin"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_ciout<label id="cbm_k_ciout"><p> + +<quote> +<descrip> +<tag/Function/Transmit a byte over the serial bus +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/void __fastcall__ cbm_k_ciout (unsigned char C);/ +<tag/Description/Purpose of this function is to send a byte of data over +the serial bus. In order for the data to be received, the serial +device must have first been commanded to LISTEN and been given a +secondary address if necessary. This routine always buffers the +current character, and defers sending it until the next byte is +buffered. When the UNLISTEN command is sent, the last byte will be +sent with an End or Identify (EOI). +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_listen" name="cbm_k_listen">, +<ref id="cbm_k_unlsn" name="cbm_k_unlsn"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_ckout<label id="cbm_k_ckout"><p> + +<quote> +<descrip> +<tag/Function/Designate a Logical File As the Current Output Channel +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ cbm_k_ckout (unsigned char FN);/ +<tag/Description/If you wish to +output data to any device other than the screen, this routine must be +called after OPENing the device, and before you output a data byte +with the cbm_k_bsout() function. When called, the function will designate the +logical file whose file number was supplied as the current +file, its device as the current device, and its secondary address as +the current secondary address. If the device on the channel uses the +serial bus, and therefore requires a LISTEN command and possibly a +secondary address, this information will be sent on the bus. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_bsout" name="cbm_k_bsout">, +<ref id="cbm_k_listen" name="cbm_k_listen"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_clall<label id="cbm_k_clall"><p> + +<quote> +<descrip> +<tag/Function/Close All Logical I/O Files +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/void cbm_k_clall (void);/ +<tag/Description/It closes all +open files, by resetting the index into open files to +zero and restores the default I/O devices. +<tag/Limits/<itemize> +<item> +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_open" name="cbm_k_open">, +<ref id="cbm_k_close" name="cbm_k_close"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_close<label id="cbm_k_close"><p> + +<quote> +<descrip> +<tag/Function/Close a Logical I/O File +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/void __fastcall__ cbm_k_close (unsigned char FN);/ +<tag/Description/It is used to +close a logical file after all I/O operations involving that file have +been completed. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_open" name="cbm_k_open">, +<ref id="cbm_k_clall" name="cbm_k_clall"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_clrch<label id="cbm_k_clrch"><p> + +<quote> +<descrip> +<tag/Function/Restore Current Input and Output Devices to the Default Devices +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/void cbm_k_clrch (void);/ +<tag/Description/It sets the +current input device to the keyboard, and the current output device to +the screen. Also, if the current input device was formerly a serial +device, the routine sends it an UNTALK command on the serial bus, and +if a serial device was formerly the current output device, the routine +sends it an UNLISTEN command. +<tag/Limits/<itemize> +<item> +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_chkin" name="cbm_k_chkin">, +<ref id="cbm_k_ckout" name="cbm_k_ckout"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_getin<label id="cbm_k_getin"><p> + +<quote> +<descrip> +<tag/Function/Get One Byte from the Input Device +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/unsigned char cbm_k_getin (void);/ +<tag/Description/Function gets a character from the current input device. +<tag/Limits/<itemize> +<item> +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_basin" name="cbm_k_basin"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_iobase<label id="cbm_k_iobase"><p> + +<quote> +<descrip> +<tag/Function/Return Base Address of Memory-Mapped I/O Devices +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/unsigned cbm_k_iobase (void);/ +<tag/Description/This function returns the address of +the memory section where the memory mapped I/O devices are located. This +address can then be used with an offset to access the memory mapped I/O +devices in the Commodore 64. The offset is the number of locations from +the beginning of the page on which the I/O register you want is located. +This function exists to provide compatibility between the Commodore 64, +VIC-20, and future models of the Commodore 64. If the I/O locations for +a program are set by a call to this function, they should +still remain compatible with future versions of the Commodore 64, the +KERNAL and BASIC. +<tag/Limits/<itemize> +<item> +</itemize> +<tag/Availability/cc65 +<tag/See also/ + +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_listen<label id="cbm_k_listen"><p> + +<quote> +<descrip> +<tag/Function/Command a device on the serial bus to LISTEN +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/void __fastcall__ cbm_k_listen (unsigned char dev);/ +<tag/Description/This function will command a device on the serial bus to +receive data. The KERNAL routine will OR the supplied device number bit by bit +to convert it to a listen address, then transmits this data as a command on +the serial bus. The specified device will then go into listen mode, and +be ready to accept information. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_unlsn" name="cbm_k_unlsn">, +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_load<label id="cbm_k_load"><p> + +<quote> +<descrip> +<tag/Function/Load RAM from a Device +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/unsigned int __fastcall__ cbm_k_load(unsigned char flag, unsigned addr);/ +<tag/Description/This function LOADs data bytes from any input device directly into the memory. +It can also be used for a verify operation, comparing data from a device with the data already in +memory, while leaving the data stored in RAM unchanged. +The flag must be set to 0 for a LOAD operation, or 1 for a +verify, If the input device is OPENed with a secondary address (SA) of 0 +the header information from the device is ignored. In this case, the starting address for the load must be supplied. +If the device is addressed with a secondary address of 1, then the data is +loaded into memory starting at the location specified by the header. +Function returns the address of the highest RAM location loaded. +Before this function can be called, the KERNAL SETLFS, and SETNAM +routines must be called. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_save" name="cbm_k_save">, +<ref id="cbm_k_setlfs" name="cbm_k_setlfs">, +<ref id="cbm_k_setnam" name="cbm_k_setnam"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_open<label id="cbm_k_open"><p> + +<quote> +<descrip> +<tag/Function/Open a Logical I/O File +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/unsigned char cbm_k_open (void);/ +<tag/Description/This function assigns a logical file to a device, so that it can be used for +Input/Output operations. In order to specify the logical file number, +the device number, and the secondary address if any, the cbm_k_setlfs() function must first be called. +Likewise, in order to designate the filename, the cbm_k_setnam() function must be used first. After these two +functions are called, cbm_k_open() is then called. +<tag/Limits/<itemize> +<item> +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_close" name="cbm_k_close">, +<ref id="cbm_k_setlfs" name="cbm_k_setlfs">, +<ref id="cbm_k_setnam" name="cbm_k_setnam"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_readst<label id="cbm_k_readst"><p> + +<quote> +<descrip> +<tag/Function/Read status word +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/unsigned char cbm_k_readst (void);/ +<tag/Description/This function returns the current status of the I/O devices. It is usually called after new communication to an I/O device and gives information about device status, or errors that have occurred during the I/O operation. +<tag/Limits/<itemize> +<item> +</itemize> +<tag/Availability/cc65 +<tag/See also/ + +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_save<label id="cbm_k_save"><p> + +<quote> +<descrip> +<tag/Function/Save RAM to a Device +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ cbm_k_save(unsigned int start, unsigned int end)/ +<tag/Description/This function saves a section of memory. The cbm_k_setlfs() and cbm_k_setnam() functions must be +used before calling this function. However, a file name is not required to +SAVE to device 1 (the Datassette(TM) recorder). Any attempt to save to +other devices without using a file name results in an error. NOTE: Device 0 (the keyboard), device 2 (RS-232), and device 3 (the screen) cannot be SAVEd to. If the attempt is made, an error occurs, and the SAVE is stopped. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_load" name="cbm_k_load">, +<ref id="cbm_k_setlfs" name="cbm_k_setlfs">, +<ref id="cbm_k_setnam" name="cbm_k_setnam"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_setlfs<label id="cbm_k_setlfs"><p> + +<quote> +<descrip> +<tag/Function/Set up a logical file +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/void __fastcall__ cbm_k_setlfs (unsigned char LFN, unsigned char DEV, unsigned char SA);/ +<tag/Description/This functions sets up the logical file by setting its number, device address, +and secondary address. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_setnam" name="cbm_k_setnam"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_setnam<label id="cbm_k_setnam"><p> + +<quote> +<descrip> +<tag/Function/Set Filename Parameters +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/void __fastcall__ cbm_k_setnam (const char* Name);/ +<tag/Description/This function is used to set up the file name for the OPEN, +SAVE, or LOAD operations. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_open" name="cbm_k_open">, +<ref id="cbm_k_load" name="cbm_k_load">, +<ref id="cbm_k_save" name="cbm_k_save"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_talk<label id="cbm_k_talk"><p> + +<quote> +<descrip> +<tag/Function/Commands device to TALK +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/void __fastcall__ cbm_k_talk (unsigned char dev);/ +<tag/Description/When called, it ORs the device number with the TALK code (64, $40) and sends it on the serial +bus. This commands the device to TALK. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_acptr" name="cbm_k_acptr"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cbm_k_unlsn<label id="cbm_k_unlsn"><p> + +<quote> +<descrip> +<tag/Function/Send an UNLISTEN command +<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ +<tag/Declaration/<tt/void cbm_k_unlsn (void);/ +<tag/Description/This function commands all devices on the serial bus to +stop receiving data from the host computer (i.e., UNLISTEN). Calling this +function results in an UNLISTEN command being transmitted on the serial +bus. Only devices previously commanded to LISTEN are affected. This +function is normally used after the host computer is finished sending data +to external devices. Sending the UNLISTEN commands the listening devices +to get off the serial bus so it can be used for other purposes. +<tag/Limits/<itemize> +<item> +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cbm_k_listen" name="cbm_k_listen"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cclear<label id="cclear"><p> + +<quote> +<descrip> +<tag/Function/Clear part of a line (write a given number of spaces). +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ cclear (unsigned char length);/ +<tag/Description/The function clears part of a line by writing <tt/length/ +spaces in the current text color. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cclearxy" name="cclearxy">, +<ref id="clrscr" name="clrscr"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cclearxy<label id="cclearxy"><p> + +<quote> +<descrip> +<tag/Function/Clear part of a line (write a given number of spaces) starting +at a specific screen position. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ cclearxy (unsigned char x, unsigned char y, unsigned char length);/ +<tag/Description/The function moves the cursor to a specific position, and +will then clear part of the line by writing <tt/length/ spaces in the current +text color. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cclear" name="cclear">, +<ref id="clrscr" name="clrscr"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cgetc<label id="cgetc"><p> + +<quote> +<descrip> +<tag/Function/Read a character from the keyboard. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/char cgetc (void);/ +<tag/Description/The function reads a character from the keyboard. If there is +no character available, <tt/cgetc/ waits until the user presses a key. If the +cursor is enabled by use of the <tt/cursor/ function, a blinking cursor is +displayed while waiting. +<tag/Limits/<itemize> +<item>If the system supports a keyboard buffer, <tt/cgetc/ will fetch a key +from this buffer and wait only if the buffer is empty. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cursor" name="cursor">, +<ref id="kbhit" name="kbhit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>chline<label id="chline"><p> + +<quote> +<descrip> +<tag/Function/Output a horizontal line in text mode. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ chline (unsigned char length);/ +<tag/Description/The function outputs a horizontal line with the given length +starting at the current cursor position. +<tag/Limits/<itemize> +<item>The character used to draw the horizontal line is system dependent. +If available, a line drawing character is used. Drawing a line that is partially +off screen leads to undefined behaviour. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="chlinexy" name="chlinexy">, +<ref id="cvline" name="cvline">, +<ref id="cvlinexy" name="cvlinexy"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>chlinexy<label id="chlinexy"><p> + +<quote> +<descrip> +<tag/Function/Output a horizontal line at a given position in text mode. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ chlinexy (unsigned char x, unsigned char y, unsigned char length);/ +<tag/Description/The function outputs a horizontal line with the given length +starting at a given position. +<tag/Limits/<itemize> +<item>The character used to draw the horizontal line is system dependent. +If available, a line drawing character is used. Drawing a line that is partially +off screen leads to undefined behaviour. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="chline" name="chline">, +<ref id="cvline" name="cvline">, +<ref id="cvlinexy" name="cvlinexy"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>clearerr<label id="clearerr"><p> + +<quote> +<descrip> +<tag/Function/Clear error and end-of-file status of a stream. +<tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ +<tag/Declaration/<tt/void __fastcall__ clearerr (FILE* f);/ +<tag/Description/<tt/clearerr/ clears the error and end-of-file status +indicators for the stream <tt/f/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="feof" name="feof">, +<ref id="ferror" name="ferror"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>clock<label id="clock"><p> + +<quote> +<descrip> +<tag/Function/Determine the processor time used. +<tag/Header/<tt/<ref id="time.h" name="time.h">/ +<tag/Declaration/<tt/clock_t clock (void);/ +<tag/Description/The <tt/clock/ function returns an approximaton of processor +time used by the program. The time is returned in implementation defined +units. It can be converted to seconds by dividing by the value of the macro +<tt/CLOCKS_PER_SEC/. +<tag/Limits/<itemize> +<item>Since the machines, cc65 generated programs run on, cannot run multiple +processes, the function will actually return the time since some +implementation defined point in the past. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="time" name="time"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>clrscr<label id="clrscr"><p> + +<quote> +<descrip> +<tag/Function/Clear the text screen. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void clrscr (void);/ +<tag/Description/The function clears the text screen and moves the cursor to +the upper left corner. +<tag/Availability/cc65 +<tag/See also/ +<ref id="cclear" name="cclear">, +<ref id="cclearxy" name="cclearxy"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>close<label id="close"><p> + +<quote> +<descrip> +<tag/Function/Close a file descriptor. +<tag/Header/<tt/<ref id="fcntl.h" name="fcntl.h">/ +<tag/Declaration/<tt/int __fastcall__ close (int fd);/ +<tag/Description/The function closes the given file descriptor. It returns zero +on success and -1 on error. If an error occurs, the cause can be determined by +reading the <tt/errno/ variable. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/See also/ +<ref id="creat" name="creat">, +<ref id="open" name="open"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>closedir<label id="closedir"><p> + +<quote> +<descrip> +<tag/Function/Close a directory. +<tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ +<tag/Declaration/<tt/int __fastcall__ closedir (DIR* dir);/ +<tag/Description/The function closes the given directory descriptor. It returns +zero on success and -1 on error. If an error occurs, the cause can be determined +by reading the <tt/errno/ variable. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/See also/ +<ref id="opendir" name="opendir">, +<ref id="readdir" name="readdir"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>creat<label id="creat"><p> + +<quote> +<descrip> +<tag/Function/Create a file. +<tag/Header/<tt/<ref id="fcntl.h" name="fcntl.h">/ +<tag/Declaration/<tt/int __fastcall__ creat (const char* name, unsigned mode);/ +<tag/Description/<tt/creat/ creates a new file and returns the file descriptor +associated with it. On error, -1 is returned and an error code is stored in +<tt/errno/. +<tag/Limits/<itemize> +<item><tt/creat/ is identical to calling <tt/<ref id="open" name="open">/ with +<tt/flags/ equal to <tt/O_WRONLY | O_CREAT | O_TRUNC/. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/See also/ +<ref id="close" name="close">, +<ref id="open" name="open"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cprintf<label id="cprintf"><p> + +<quote> +<descrip> +<tag/Function/Formatted output to the console. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/int cprintf (const char* format, ...);/ +<tag/Description/The arguments are converted to text where necessary and +formatted according to the format string given. The resulting string is output +to the console. <tt/cprintf/ supports the same format specifiers as +<tt/printf/. <!-- <tt/<ref id="printf" name="printf">/. --> +<tag/Limits/<itemize> +<item>Like all other <tt/conio/ output functions, <tt/cprintf/ distinguishes +between <tt/\r/ and <tt/\n/. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cputc" name="cputc">, +<ref id="cputcxy" name="cputcxy">, +<ref id="cputs" name="cputs">, +<ref id="cputsxy" name="cputsxy">, +<ref id="vcprintf" name="vcprintf"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cputc<label id="cputc"><p> + +<quote> +<descrip> +<tag/Function/Output a character directly to the console. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ cputc (char c);/ +<tag/Description/Output one character to the console at the current cursor +position. +<tag/Limits/<itemize> +<item>Like all other <tt/conio/ output functions, <tt/cputc/ distinguishes +between <tt/\r/ and <tt/\n/. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cprintf" name="cprintf">, +<ref id="cputcxy" name="cputcxy">, +<ref id="cputs" name="cputs">, +<ref id="cputsxy" name="cputsxy">, +<ref id="vcprintf" name="vcprintf"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cputcxy<label id="cputcxy"><p> + +<quote> +<descrip> +<tag/Function/Output a character at a specific screen position. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);/ +<tag/Description/<tt/cputcxy/ moves the cursor to the given x/y position on +the screen and outputs one character. +<tag/Limits/<itemize> +<item>Like all other <tt/conio/ output functions, <tt/cputcxy/ distinguishes +between <tt/\r/ and <tt/\n/. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cprintf" name="cprintf">, +<ref id="cputc" name="cputc">, +<ref id="cputs" name="cputs">, +<ref id="cputsxy" name="cputsxy">, +<ref id="vcprintf" name="vcprintf"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cputs<label id="cputs"><p> + +<quote> +<descrip> +<tag/Function/Output a string directly to the console. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ cputs (const char* s);/ +<tag/Description/The function outputs the given string on the console at the +current cursor position. +<tag/Limits/<itemize> +<item>Like all other <tt/conio/ output functions, <tt/cputs/ distinguishes +between <tt/\r/ and <tt/\n/. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cprintf" name="cprintf">, +<ref id="cputc" name="cputc">, +<ref id="cputcxy" name="cputcxy">, +<ref id="cputsxy" name="cputsxy">, +<ref id="vcprintf" name="vcprintf"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cputsxy<label id="cputsxy"><p> + +<quote> +<descrip> +<tag/Function/Output a string to the console at a given position. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ cputsxy (unsigned char x, unsigned char y, const char* s);/ +<tag/Description/<tt/cputsxy/ moves the cursor to the given x/y position, +and outputs the string <tt/s/. +<tag/Limits/<itemize> +<item>Like all other <tt/conio/ output functions, <tt/cputsxy/ distinguishes +between <tt/\r/ and <tt/\n/. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cprintf" name="cprintf">, +<ref id="cputc" name="cputc">, +<ref id="cputcxy" name="cputcxy">, +<ref id="cputs" name="cputs">, +<ref id="vcprintf" name="vcprintf"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cursor<label id="cursor"><p> + +<quote> +<descrip> +<tag/Function/Enable/disable a blinking cursor when waiting for keyboard input. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ cursor (unsigned char onoff);/ +<tag/Description/If the argument to the function is non zero, a blinking cursor +will be enabled when the <tt/cgetc/ function waits for input from the keyboard. +If the argument is zero, <tt/cgetc/ will wait without a blinking cursor. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cgetc" name="cgetc">, +<ref id="kbhit" name="kbhit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cvline<label id="cvline"><p> + +<quote> +<descrip> +<tag/Function/Output a vertical line in text mode. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ cvline (unsigned char length);/ +<tag/Description/The function outputs a vertical line with the given length +starting at the current cursor position. +<tag/Limits/<itemize> +<item>The character used to draw the vertical line is system dependent. +If available, a line drawing character is used. Drawing a line that is partially +off screen leads to undefined behaviour. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="chline" name="chline">, +<ref id="chlinexy" name="chlinexy">, +<ref id="cvlinexy" name="cvlinexy"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cvlinexy<label id="cvlinexy"><p> + +<quote> +<descrip> +<tag/Function/Output a vertical line at a given position in text mode. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ cvlinexy (unsigned char x, unsigned char y, unsigned char length);/ +<tag/Description/The function outputs a vertical line with the given length +starting at a given position. +<tag/Limits/<itemize> +<item>The character used to draw the vertical line is system dependent. +If available, a line drawing character is used. Drawing a line that is partially +off screen leads to undefined behaviour. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="chline" name="chline">, +<ref id="chlinexy" name="chlinexy">, +<ref id="cvline" name="cvline"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>div<label id="div"><p> + +<quote> +<descrip> +<tag/Function/Divide two ints and return quotient and remainder. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/div_t __fastcall__ div (int numer, int denom);/ +<tag/Description/<tt/div/ divides <tt/numer/ by <tt/denom/ and returns the +quotient and remainder in a <tt/div_t/ structure. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +ldiv +<tag/Example/None. +</descrip> +</quote> + + +<sect1>em_commit<label id="em_commit"><p> + +<quote> +<descrip> +<tag/Function/Commit changes into extended memory. +<tag/Header/<tt/<ref id="em.h" name="em.h">/ +<tag/Declaration/<tt/void em_commit (void);/ +<tag/Description/Commit changes in the memory window to extended storage. If +the contents of the memory window have been changed, these changes may be lost +if <tt/<ref id="em_map" name="em_map">/, <tt/<ref id="em_use" name="em_use">/, +<tt/<ref id="em_copyfrom" name="em_copyfrom">/ or <tt/<ref id="em_copyto" +name="em_copyto">/ are called without calling <tt/em_commit/ first. +<tag/Limits/<itemize> +<item>Calling <tt/em_commit/ does not necessarily mean that changes to the +memory window are discarded, it does just mean that the drivers is allowed +to discard it. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +<item>The function produces undefined results if no extended memory driver is +loaded. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="em_load_driver" name="em_load_driver">, +<ref id="em_map" name="em_map">, +<ref id="em_use" name="em_use"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>em_copyfrom<label id="em_copyfrom"><p> + +<quote> +<descrip> +<tag/Function/Copy from extended into normal memory. +<tag/Header/<tt/<ref id="em.h" name="em.h">/ +<tag/Declaration/<tt/void __fastcall__ em_copyfrom (const struct em_copy* copy_data);/ +<tag/Description/Copy data from extended memory into linear memory. Source and +target addresses as well as the number of bytes to transfer are specified in +the <tt/em_copy/ structure that is passed as a parameter. +<tag/Limits/<itemize> +<item>Calling <tt/em_copyfrom/ will invalidate the memory window, so if you +made any changes to the data in the window, call <tt/<ref id="em_commit" +name="em_commit">/ first, or the changes are lost. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +<item>The function produces undefined results if no extended memory driver is +loaded. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="em_commit" name="em_commit">, +<ref id="em_copyto" name="em_copyto">, +<ref id="em_load_driver" name="em_load_driver"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>em_copyto<label id="em_copyto"><p> + +<quote> +<descrip> +<tag/Function/Copy from normal into extended memory. +<tag/Header/<tt/<ref id="em.h" name="em.h">/ +<tag/Declaration/<tt/void __fastcall__ em_copyto (const struct em_copy* copy_data);/ +<tag/Description/Copy data from linear into extended memory. Source and +target addresses as well as the number of bytes to transfer are specified in +the <tt/em_copy/ structure that is passed as a parameter. +<tag/Limits/<itemize> +<item>Calling <tt/em_copyto/ will invalidate the memory window, so if you +made any changes to the data in the window, call <tt/<ref id="em_commit" +name="em_commit">/ first, or the changes are lost. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +<item>The function produces undefined results if no extended memory driver is +loaded. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="em_commit" name="em_commit">, +<ref id="em_copyfrom" name="em_copyfrom">, +<ref id="em_load_driver" name="em_load_driver"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>em_install<label id="em_install"><p> + +<quote> +<descrip> +<tag/Function/Install an already loaded extended memory driver. +<tag/Header/<tt/<ref id="em.h" name="em.h">/ +<tag/Declaration/<tt/unsigned char _fastcall__ em_install (void* driver);/ +<tag/Description/The function installs an already loaded extended memory driver +and returns an error code. The function may be used to install a driver linked +statically to the program. +<tag/Limits/<itemize> +<item>Not all drivers are able to detect if the supported hardware is really +present. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="em_load_driver" name="em_load_driver">, +<ref id="em_uninstall" name="em_uninstall">, +<ref id="em_unload" name="em_unload"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>em_load_driver<label id="em_load_driver"><p> + +<quote> +<descrip> +<tag/Function/Load and initialize an extended memory driver. +<tag/Header/<tt/<ref id="em.h" name="em.h">/ +<tag/Declaration/<tt/void __fastcall__ em_load_driver (const char* name);/ +<tag/Description/Load an extended memory driver into memory and initialize +it. The function returns an error code that tells if all this has been +successful. +<tag/Limits/<itemize> +<item>Not all drivers are able to detect if the supported hardware is really +present. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +<item>The driver is loaded by name, so currently you must know the type of +extended memory that should be supported. There is no autodetect capability. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="em_unload" name="em_unload"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>em_map<label id="em_map"><p> + +<quote> +<descrip> +<tag/Function/Make a page of extended memory accessible. +<tag/Header/<tt/<ref id="em.h" name="em.h">/ +<tag/Declaration/<tt/void* __fastcall__ em_map (unsigned page);/ +<tag/Description/The function maps one page of extended memory into linear +memory and returns a pointer to the page frame. Depending on the hardware +and driver, the data is either mapped into the address space or transfered +into a buffer. If you don't need the actual contents of the page (for example +because you're going to overwrite it completely), it is better to call +<tt/<ref id="em_use" name="em_use">/ instead. <tt/em_use/ will not transfer the +data if it is possible to avoid that. +<tag/Limits/<itemize> +<item>Calling <tt/em_map/ will invalidate the memory window, so if you +made any changes to the data in the window, call <tt/<ref id="em_commit" +name="em_commit">/ first, or the changes are lost. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +<item>The function produces undefined results if no extended memory driver is +loaded. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="em_commit" name="em_commit">, +<ref id="em_load_driver" name="em_load_driver">, +<ref id="em_use" name="em_use"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>em_pagecount<label id="em_pagecount"><p> + +<quote> +<descrip> +<tag/Function/Return the number of available extended memory pages. +<tag/Header/<tt/<ref id="em.h" name="em.h">/ +<tag/Declaration/<tt/unsigned em_pagecount (void);/ +<tag/Description/The function returns the size of the extended memory supported +by the driver in 256 byte pages. +<tag/Limits/<itemize> +<item>The function returns zero if no extended memory driver is loaded. +<item>The function may return zero if the supported hardware was not detected. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="em_load_driver" name="em_load_driver"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>em_uninstall<label id="em_uninstall"><p> + +<quote> +<descrip> +<tag/Function/Uninstall an already loaded extended memory driver. +<tag/Header/<tt/<ref id="em.h" name="em.h">/ +<tag/Declaration/<tt/unsigned char em_uninstall (void);/ +<tag/Description/The function uninstalls an already loaded extended memory +driver but doesn't remove it from memory. +<tag/Limits/<itemize> +<item>If the driver has been loaded using <tt/<ref id="em_load_driver" +name="em_load_driver">/, <tt/<ref id="em_unload" name="em_unload">/ +should be used instead of <tt/em_uninstall/ so the driver is also removed +from memory. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="em_install" name="em_install">, +<ref id="em_load_driver" name="em_load_driver">, +<ref id="em_unload" name="em_unload"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>em_unload<label id="em_unload"><p> + +<quote> +<descrip> +<tag/Function/Unload an extended memory driver. +<tag/Header/<tt/<ref id="em.h" name="em.h">/ +<tag/Declaration/<tt/unsigned char em_unload (void);/ +<tag/Description/The function unloads a loaded extended memory driver and +frees all memory allocated for the driver. +<tag/Limits/<itemize> +<item>The function does nothing if no driver is loaded. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="em_load_driver" name="em_load_driver"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>em_use<label id="em_use"><p> + +<quote> +<descrip> +<tag/Function/Prepare an extended memory page for use. +<tag/Header/<tt/<ref id="em.h" name="em.h">/ +<tag/Declaration/<tt/void* __fastcall__ em_use (unsigned page);/ +<tag/Description/The function maps one page of extended memory into linear +memory and returns a pointer to the page frame. This function is similar to +<tt/<ref id="em_map" name="em_map">/, but will not transfer data into the +actual memory window in the assumption that the existing data is wrong or +will get overwritten. +<tag/Limits/<itemize> +<item>Calling <tt/em_use/ will invalidate the memory window, so if you +made any changes to the data in the window, call <tt/<ref id="em_commit" +name="em_commit">/ first, or the changes are lost. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +<item>The function produces undefined results if no extended memory driver is +loaded. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="em_commit" name="em_commit">, +<ref id="em_load_driver" name="em_load_driver">, +<ref id="em_map" name="em_map"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>exit<label id="exit"><p> + +<quote> +<descrip> +<tag/Function/Terminate the program. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void __fastcall__ exit (int status);/ +<tag/Description/<tt/exit/ terminates the program. The argument specifies the +return code of the program. Before termination, all files are closed, buffered +output is written and any functions registered with <tt/<ref id="atexit" +name="atexit">/ are called. Common values for status are <tt/EXIT_SUCCESS/ and +<tt/EXIT_FAILURE/ which are also defined in <tt/<ref id="stdlib.h" +name="stdlib.h">/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>It depends on the host machine if the program return code can be +evaluated or is ignored. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="abort" name="abort">, +<ref id="exit" name="exit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>exec<label id="exec"><p> + +<quote> +<descrip> +<tag/Function/Execute a program file. +<tag/Header/<tt/<ref id="unistd.h" name="unistd.h">/ +<tag/Declaration/<tt/int __fastcall__ exec (const char* progname, const char* cmdline);/ +<tag/Description/<tt/exec/ replaces the currently running program by a new one. +Calling <tt/exec()/ is identical to calling <tt/<ref id="exit" name="exit()">/, +then loading and starting the program named in the first argument, passing +the command line specified as second argument. Instead of an empty string, +a <tt/NULL/ pointer may be passed as second parameter. +On success, the function does not return. On failure, -1 is returned and +<tt/errno/ contains an error code. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>On most platforms, the function needs to copy a small stub loader to +some memory area outside the program space. This may collide with other +programs. See the platform specific docs on this. +<item>Because it is necessary to terminate the running program before the +memory can be reused to load the new one, there is a high chance that the +function may not be able to return on errors. +<item>The command line is passed to the new program in the same way as cc65 +programs expect the command line. If the new program is not a cc65 generated +program, it may not be able to read it. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="exit" name="exit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>fast<label id="fast"><p> + +<quote> +<descrip> +<tag/Function/Switch the C128 into 2MHz mode. +<tag/Header/<tt/<ref id="c128.h" name="c128.h">/ +<tag/Declaration/<tt/void fast (void);/ +<tag/Description/The function will switch the clock of the C128 to 2MHz. This +will nearly double the speed compared to slow mode. +<tag/Limits/<itemize> +<item>The function is specific to the C128. +<item>2MHz clock will not work in 40 column mode. +</itemize> +<tag/Availability/C128 +<tag/See also/ +<ref id="slow" name="slow">, +<ref id="toggle_videomode" name="toggle_videomode">, +<ref id="videomode" name="videomode"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>feof<label id="feof"><p> + +<quote> +<descrip> +<tag/Function/Return the end-of-file indicator of a stream. +<tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ +<tag/Declaration/<tt/int __fastcall__ feof (FILE* f);/ +<tag/Description/<tt/feof/ tests the end-of-file indicator ofthe stream +<tt/f/, and returns a non zero value if it is set. +<tag/Limits/<itemize> +<item>The indicator is set only after a read past the end of a file is +attempted. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="feof" name="clearerr">, +<ref id="ferror" name="ferror"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>ferror<label id="ferror"><p> + +<quote> +<descrip> +<tag/Function/Return the error indicator of a stream. +<tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ +<tag/Declaration/<tt/int __fastcall__ ferror (FILE* f);/ +<tag/Description/<tt/ferror/ tests the error indicator of the stream +<tt/f/, and returns a non zero value if it is set. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="feof" name="clearerr">, +<ref id="ferror" name="feof"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>fileno<label id="fileno"><p> + +<quote> +<descrip> +<tag/Function/Return the file handle used by a stream. +<tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ +<tag/Declaration/<tt/int __fastcall__ fileno (FILE* f);/ +<tag/Description/The <tt/fileno/ function returns the file handle used +internally by a C stream. This file handle (an integer) can be used as a +handle for the POSIX input/output functions. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +<item>Mixing C file I/O functions and POSIX file I/O functions for the same +file may have unpredictable results. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/See also/ +<ref id="creat" name="creat">, +<ref id="open" name="open"> <!-- , --> +<!-- <ref id="read" name="read">, --> +<!-- <ref id="write" name="write"> --> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>free<label id="free"><p> + +<quote> +<descrip> +<tag/Function/Free a block of dynamic memory. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void __fastcall__ free (void* block);/ +<tag/Description/Free a block of dynamic memory previously allocated with +<tt/<ref id="malloc" name="malloc">/, <tt/<ref id="calloc" name="calloc">/ +or <tt/<ref id="realloc" name="realloc">/. As an exception, if the passed +pointer is <tt/NULL/, no action is performed. +<tag/Limits/ +<itemize> +<item>Passing an already free'd block to <tt/free/ again will cause undefined +behaviour and may crash your program. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="_heapadd" name="_heapadd">, +<ref id="_heapblocksize" name="_heapblocksize">, +<ref id="_heapmaxavail" name="_heapmaxavail">, +<ref id="_heapmemavail" name="_heapmemavail">, +<ref id="calloc" name="calloc">, +<ref id="malloc" name="malloc">, +<ref id="realloc" name="realloc"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>get_ostype<label id="get_ostype"><p> + +<quote> +<descrip> +<tag/Function/The function returns the operating system, the program runs on. +<tag/Header/<tt/<ref id="apple2.h" name="apple2.h">, +<ref id="atari.h" name="atari.h">, <ref id="c64.h" name="c64.h">/ +<tag/Declaration/<tt/unsigned char get_ostype (void);/ +<tag/Description/<tt/get_ostype/ is machine dependent and does not exist for +all supported targets. If it exists, it returns a number that identifies the +operating system or machine type, the program runs on. The machine dependent +header files define constants that can be used to check the return code. +<tag/Limits/<itemize> +<item>The function does not exist on all platforms. +<item>The return codes are platform dependent. +</itemize> +<tag/Availability/cc65 (not all platforms) +<tag/Example/None. +</descrip> +</quote> + + +<sect1>getcpu<label id="getcpu"><p> + +<quote> +<descrip> +<tag/Function/Determine on which CPU the program is running. +<tag/Header/<tt/<ref id="6502.h" name="6502.h">/ +<tag/Declaration/<tt/unsigned char getcpu (void);/ +<tag/Description/The function checks on which CPU the code is running. It +returns one of the constants<itemize> +<item><tt/CPU_6502/ +<item><tt/CPU_65C02/ +<item><tt/CPU_65816/ +</itemize> +<tag/Limits/<itemize> +<item>Other, more exotic CPU types are not disinguished. +</itemize> +<tag/Availability/cc65 +<tag/Example/None. +</descrip> +</quote> + + +<sect1>getenv<label id="getenv"><p> + +<quote> +<descrip> +<tag/Function/Return a value from the environment. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/char* __fastcall__ getenv (const char* name);/ +<tag/Description/The function searches the environment for an entry that +matches <tt/name/ and returns its value. The environment consists of a list +of strings in the form <tt/name=value/. If there is no match, <tt/getenv/ +returns <tt/NULL/. +<tag/Limits/<itemize> +<item>What exactly is stored in the environment depends on the machine the +program is running on. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/Example/None. +</descrip> +</quote> + + +<sect1>getopt<label id="getopt"><p> + +<quote> +<descrip> +<tag/Function/Parse command line options. +<tag/Header/<tt/<ref id="unistd.h" name="unistd.h">/ +<tag/Declaration/<tt/int __fastcall__ getopt (int argc, char* const* argv, +const char* optstring);/ +<tag/Description/The function parses command line arguments, <tt/argc/ and +<tt/argv/ are the argument count and array passed to <tt/main/. <tt/optstring/ +is a string that contains command line option characters. If a character in +<tt/optstring/ is followed by a colon, the option requires an argument. An +option on the command line is recognized if it is one of the option characters +preceeded by a '-'. +<tt/getopt/ must be called repeatedly. It will return each option character +found on the command line and <tt/EOF/ (-1) if there is no other option. An +option argument is placed in <tt/optarg/, the index of the next element on the +command line to be processed is placed in <tt/optind/. +<tag/Limits/<itemize> +<item>The implementation will not reorder options. A non option on the command +line will terminate option processing. All remaining arguments are not +recognized as options, even if the start with a '-' character. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/POSIX.2 +<tag/Example/None. +</descrip> +</quote> + + +<sect1>gotox<label id="gotox"><p> + +<quote> +<descrip> +<tag/Function/Move the text mode cursor to a new X position. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ gotox (unsigned char x);/ +<tag/Description/The function moves the text mode cursor to the specified X +position while leaving the Y position untouched. The leftmost position on the +screen has the coordinate 0. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +<item>Invalid values for the X position (out of screen coordinates) may +lead to undefined behaviour. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="gotoy" name="gotoy">, +<ref id="gotoxy" name="gotoxy">, +<ref id="wherex" name="wherex">, +<ref id="wherey" name="wherey"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>gotoxy<label id="gotoxy"><p> + +<quote> +<descrip> +<tag/Function/Move the text mode cursor to a new position. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ gotoxy (unsigned char x, unsigned char y);/ +<tag/Description/The function moves the text mode cursor to the specified +position. The leftmost position on the screen has the X coordinate 0, the +topmost line has the Y coordinate 0. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +<item>Invalid values for any of both coordinates (out of screen positions) may +lead to undefined behaviour. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="gotox" name="gotox">, +<ref id="gotoy" name="gotoy">, +<ref id="wherex" name="wherex">, +<ref id="wherey" name="wherey"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>gotoy<label id="gotoy"><p> + +<quote> +<descrip> +<tag/Function/Move the text mode cursor to a new Y position. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ gotoy (unsigned char x);/ +<tag/Description/The function moves the text mode cursor to the specified Y +position while leaving the X position untouched. The uppermost position on the +screen has the coordinate 0. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +<item>Invalid values for the Y position (out of screen coordinates) may lead +to undefined behaviour. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="gotox" name="gotox">, +<ref id="gotoxy" name="gotoxy">, +<ref id="wherex" name="wherex">, +<ref id="wherey" name="wherey"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>isalnum<label id="isalnum"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is a letter or digit. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ isalnum (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is a letter or digit. The return value is zero if the character is anything +else. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing +the macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalpha" name="isalpha">, +<ref id="isascii" name="isascii">, +<ref id="isblank" name="isblank">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isdigit" name="isdigit">, +<ref id="isgraph" name="isgraph">, +<ref id="islower" name="islower">, +<ref id="isprint" name="isprint">, +<ref id="ispunct" name="ispunct">, +<ref id="isspace" name="isspace">, +<ref id="isupper" name="isupper">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>isalpha<label id="isalpha"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is a letter. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ isalpha (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is a letter. The return value is zero if the character is anything else. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isascii" name="isascii">, +<ref id="isblank" name="isblank">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isdigit" name="isdigit">, +<ref id="isgraph" name="isgraph">, +<ref id="islower" name="islower">, +<ref id="isprint" name="isprint">, +<ref id="ispunct" name="ispunct">, +<ref id="isspace" name="isspace">, +<ref id="isupper" name="isupper">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>isascii<label id="isascii"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is in the ASCII (0..127) range. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ isascii (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is in the range 0..127 (the range of valid ASCII characters) and zero if not. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isalpha" name="isalpha">, +<ref id="isblank" name="isblank">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isdigit" name="isdigit">, +<ref id="isgraph" name="isgraph">, +<ref id="islower" name="islower">, +<ref id="isprint" name="isprint">, +<ref id="ispunct" name="ispunct">, +<ref id="isspace" name="isspace">, +<ref id="isupper" name="isupper">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>isblank<label id="isblank"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is a space or tab. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ isblank (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is a space or tab character. The return value is zero if the character is +anything else. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isalpha" name="isalpha">, +<ref id="isascii" name="isascii">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isdigit" name="isdigit">, +<ref id="isgraph" name="isgraph">, +<ref id="islower" name="islower">, +<ref id="isprint" name="isprint">, +<ref id="ispunct" name="ispunct">, +<ref id="isspace" name="isspace">, +<ref id="isupper" name="isupper">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>iscntrl<label id="iscntrl"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is a control character. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ iscntrl (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is a control character. The return value is zero if the character is anything +else. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isalpha" name="isalpha">, +<ref id="isascii" name="isascii">, +<ref id="isblank" name="isblank">, +<ref id="isdigit" name="isdigit">, +<ref id="isgraph" name="isgraph">, +<ref id="islower" name="islower">, +<ref id="isprint" name="isprint">, +<ref id="ispunct" name="ispunct">, +<ref id="isspace" name="isspace">, +<ref id="isupper" name="isupper">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>isdigit<label id="isdigit"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is a digit. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ isdigit (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is a digit. The return value is zero if the character is anything else. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isalpha" name="isalpha">, +<ref id="isascii" name="isascii">, +<ref id="isblank" name="isblank">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isgraph" name="isgraph">, +<ref id="islower" name="islower">, +<ref id="isprint" name="isprint">, +<ref id="ispunct" name="ispunct">, +<ref id="isspace" name="isspace">, +<ref id="isupper" name="isupper">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>isgraph<label id="isgraph"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is a printable character (except +space). +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ isgraph (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is a printable character with the exception of space. The return value is zero +if the character is anything else. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isalpha" name="isalpha">, +<ref id="isascii" name="isascii">, +<ref id="isblank" name="isblank">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isdigit" name="isdigit">, +<ref id="islower" name="islower">, +<ref id="isprint" name="isprint">, +<ref id="ispunct" name="ispunct">, +<ref id="isspace" name="isspace">, +<ref id="isupper" name="isupper">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>islower<label id="islower"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is a lower case letter. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ islower (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is a lower case letter. The return value is zero if the character is anything +else. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isalpha" name="isalpha">, +<ref id="isascii" name="isascii">, +<ref id="isblank" name="isblank">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isdigit" name="isdigit">, +<ref id="isgraph" name="isgraph">, +<ref id="isprint" name="isprint">, +<ref id="ispunct" name="ispunct">, +<ref id="isspace" name="isspace">, +<ref id="isupper" name="isupper">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>isprint<label id="isprint"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is a printable character. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ isprint (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is a printable character (this includes the space character). The return value +is zero if the character is anything else. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isalpha" name="isalpha">, +<ref id="isascii" name="isascii">, +<ref id="isblank" name="isblank">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isdigit" name="isdigit">, +<ref id="isgraph" name="isgraph">, +<ref id="islower" name="islower">, +<ref id="ispunct" name="ispunct">, +<ref id="isspace" name="isspace">, +<ref id="isupper" name="isupper">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>ispunct<label id="ispunct"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is a printable character but not a +space or an alphanumeric character. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ ispunct (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is a printable character, but not a space or anything alphanumeric. The return +value is zero if the character is anything else. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isalpha" name="isalpha">, +<ref id="isascii" name="isascii">, +<ref id="isblank" name="isblank">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isdigit" name="isdigit">, +<ref id="isgraph" name="isgraph">, +<ref id="islower" name="islower">, +<ref id="isprint" name="isprint">, +<ref id="isspace" name="isspace">, +<ref id="isupper" name="isupper">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>isspace<label id="isspace"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is a a white-space character. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ isspace (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is a white space character. The return value is zero if the character is +anything else. The standard white space characters are: space, formfeed ('\f'), +newline ('\n'), carriage return ('\r'), horizontal tab ('\t'), and vertical tab +('\v'). +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isalpha" name="isalpha">, +<ref id="isascii" name="isascii">, +<ref id="isblank" name="isblank">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isdigit" name="isdigit">, +<ref id="isgraph" name="isgraph">, +<ref id="islower" name="islower">, +<ref id="isprint" name="isprint">, +<ref id="ispunct" name="ispunct">, +<ref id="isupper" name="isupper">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>isupper<label id="isupper"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is an upper case letter. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ isupper (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is an upper case letter. The return value is zero if the character is anything +else. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isalpha" name="isalpha">, +<ref id="isascii" name="isascii">, +<ref id="isblank" name="isblank">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isdigit" name="isdigit">, +<ref id="isgraph" name="isgraph">, +<ref id="islower" name="islower">, +<ref id="isprint" name="isprint">, +<ref id="ispunct" name="ispunct">, +<ref id="isspace" name="isspace">, +<ref id="isxdigit" name="isxdigit"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>isxdigit<label id="isxdigit"><p> + +<quote> +<descrip> +<tag/Function/Check if a given character is a hexadecimal digit. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ isxdigit (int c);/ +<tag/Description/The function returns a non zero value if the given argument +is a hexadecimal digit (0..9, a..f and A..F). The return value is zero if the +character is anything else. +<tag/Limits/<itemize> +<item>When compiling with <tt/-Os/ the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of +this range. The non inline function may be accessed by <tt/#undef/'ing the +macro. +<item>When compiling without <tt/-Os/, the function is only available as +fastcall function, so it may only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="isalnum" name="isalnum">, +<ref id="isalpha" name="isalpha">, +<ref id="isascii" name="isascii">, +<ref id="isblank" name="isblank">, +<ref id="iscntrl" name="iscntrl">, +<ref id="isdigit" name="isdigit">, +<ref id="isgraph" name="isgraph">, +<ref id="islower" name="islower">, +<ref id="isprint" name="isprint">, +<ref id="ispunct" name="ispunct">, +<ref id="isspace" name="isspace">, +<ref id="isupper" name="isupper"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>itoa<label id="itoa"><p> + +<quote> +<descrip> +<tag/Function/Convert an integer into a string. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/char* __fastcall__ itoa (int val, char* buf, int radix);/ +<tag/Description/<tt/itoa/ converts the integer <tt/val/ into a string using +<tt/radix/ as the base. +<tag/Limits/<itemize> +<item>There are no provisions to prevent a buffer overflow. +<item>If <tt/val/ contains <tt/INT_MIN/, the behaviour is undefined. +<item>The function is non standard, so it is not available in strict ANSI mode. +You should probably use <tt/sprintf/ instead. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="atoi" name="atoi">, +<ref id="atol" name="atol">, +<ref id="ltoa" name="ltoa">, +<ref id="ultoa" name="ultoa">, +<ref id="utoa" name="utoa"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>joy_count<label id="joy_count"><p> + +<quote> +<descrip> +<tag/Function/Return the number of joysticks supported by the current driver. +<tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ +<tag/Declaration/<tt/unsigned char joy_count (void);/ +<tag/Description/The function returns a the number of joysticks supported +by the current joystick driver. +<tag/Limits/<itemize> +<item>A joystick driver must be loaded using <ref id="joy_load_driver" +name="joy_load_driver"> before calling this function. +<item>The function returns the number of joysticks supported by the driver. +There's no way to check for the number of actually connected joysticks. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="joy_load_driver" name="joy_load_driver">, +<ref id="joy_read" name="joy_read"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>joy_install<label id="joy_install"><p> + +<quote> +<descrip> +<tag/Function/Install an already loaded driver and return an error code. +<tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ joy_install (void* driver);/ +<tag/Description/The function installs a driver that was already loaded into +memory (or linked statically to the program). It returns an error code +(<tt/JOY_ERR_OK/ in case of success). +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="joy_load_driver" name="joy_load_driver">, +<ref id="joy_uninstall" name="joy_uninstall">, +<ref id="joy_unload" name="joy_unload"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>joy_load_driver<label id="joy_load_driver"><p> + +<quote> +<descrip> +<tag/Function/Load a driver from disk and install it. +<tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ joy_load_driver (const char* driver);/ +<tag/Description/The function loads a driver with the given name from disk +and installs it. An error code is returned, which is <tt/JOY_ERR_OK/ if the +driver was successfully loaded and installed. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="joy_install" name="joy_install">, +<ref id="joy_uninstall" name="joy_uninstall">, +<ref id="joy_unload" name="joy_unload"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>joy_read<label id="joy_read"><p> + +<quote> +<descrip> +<tag/Function/Read the status of a joystick. +<tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ joy_read (unsigned char joystick);/ +<tag/Description/The function reads the status bits for a joystick. The number +of the joystick is passed as parameter. The result may be examined by using one +of the <tt/JOY_xxx/ macros from <ref id="joystick.h" name="joystick.h">. +<tag/Limits/<itemize> +<item>A joystick driver must be loaded using <ref id="joy_load_driver" +name="joy_load_driver"> before calling this function. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="joy_count" name="joy_count">, +<ref id="joy_load_driver" name="joy_load_driver">, +<ref id="joy_unload" name="joy_unload"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>joy_uninstall<label id="joy_uninstall"><p> + +<quote> +<descrip> +<tag/Function/Uninstall the current joystick driver. +<tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ +<tag/Declaration/<tt/unsigned char joy_uninstall (void);/ +<tag/Description/The function uninstalls the currently installed joystick +driver. It does not remove the driver from memory. The function returns an +error code, which is <tt/JOY_ERR_OK/ if the driver was successfully uninstalled. +<tag/Limits/<itemize> +<item>A joystick driver must be installed using <ref id="joy_install" +name="joy_install"> before calling this function. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="joy_install" name="joy_install">, +<ref id="joy_load_driver" name="joy_load_driver">, +<ref id="joy_unload" name="joy_unload"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>joy_unload<label id="joy_unload"><p> + +<quote> +<descrip> +<tag/Function/Uninstall, then unload the current joystick driver. +<tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ +<tag/Declaration/<tt/unsigned char joy_unload (void);/ +<tag/Description/The function uninstalls the currently installed joystick +driver and removes it from memory. An error code is returned, which is +<tt/JOY_ERR_OK/ if the driver was successfully uninstalled. +<tag/Limits/<itemize> +<item>A joystick driver must be loaded using <ref id="joy_load_driver" +name="joy_load_driver"> before calling this function. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="joy_load_driver" name="joy_load_driver"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>kbhit<label id="kbhit"><p> + +<quote> +<descrip> +<tag/Function/Check if there's a key waiting in the keyboard buffer. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/unsigned char kbhit (void);/ +<tag/Description/The function returns a value of zero if there is no character +waiting to be read from the keyboard. It returns non zero otherwise. +<tag/Limits/<itemize> +<item>If the system does not support a keyboard buffer (most systems +do), the function is rather useless. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cgetc" name="cgetc">, +<ref id="cursor" name="cursor"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>labs<label id="labs"><p> + +<quote> +<descrip> +<tag/Function/Returns the absolute value of a long integer. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/long __fastcall__ labs (long v);/ +<tag/Description/<tt/labs/ returns the absolute value of the argument passed to +the function. +<tag/Limits/<itemize> +<item>The return value is undefined if <tt/LONG_MIN/ is passed to the function. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="abs" name="abs"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>ltoa<label id="ltoa"><p> + +<quote> +<descrip> +<tag/Function/Convert a long integer into a string. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/char* __fastcall__ ltoa (long val, char* buf, int radix);/ +<tag/Description/<tt/itoa/ converts the long integer <tt/val/ into a string +using <tt/radix/ as the base. +<tag/Limits/<itemize> +<item>There are no provisions to prevent a buffer overflow. +<item>If <tt/val/ contains <tt/LONG_MIN/, the behaviour is undefined. +<item>The function is non standard, so it is not available in strict ANSI mode. +You should probably use <tt/sprintf/ instead. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="atoi" name="atoi">, +<ref id="atol" name="atol">, +<ref id="itoa" name="itoa">, +<ref id="ultoa" name="ultoa">, +<ref id="utoa" name="utoa"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>localeconv<label id="localeconv"><p> + +<quote> +<descrip> +<tag/Function/Returns a pointer to the current locale structure. +<tag/Header/<tt/<ref id="locale.h" name="locale.h">/ +<tag/Declaration/<tt/struct lconv* localeconv (void);/ +<tag/Description/<tt/localeconv/ returns a pointer to the current locale +structure. +<tag/Limits/<itemize> +<item>cc65 supports only the "C" locale, so even after setting a new locale +using <tt/<ref id="setlocale" name="setlocale">/, the structure returned will +always be the same. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="setlocale" name="setlocale"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>longjmp<label id="longjmp"><p> + +<quote> +<descrip> +<tag/Function/Non local goto. +<tag/Header/<tt/<ref id="setjmp.h" name="setjmp.h">/ +<tag/Declaration/<tt/void __fastcall__ longjmp (jmp_buf buf, int retval);/ +<tag/Description/The <tt/longjmp/ function restores a program context from the +data in <tt/buf/, which must have been set by a preceeding call to +<tt/<ref id="setjmp" name="setjmp">/. Program execution continues as if the +call to <tt/<ref id="setjmp" name="setjmp">/ has just returned the value +<tt/retval/. +<tag/Limits/ +<itemize> +<item>If the parameter <tt/retval/ is zero, the function will behave as if it +was called with a value of one. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="setjmp" name="setjmp"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>malloc<label id="malloc"><p> + +<quote> +<descrip> +<tag/Function/Allocate dynamic memory. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void* __fastcall__ malloc (size_t size);/ +<tag/Description/<tt/malloc/ allocates size bytes on the heap and returns a +pointer to the allocated memory block. On error (not enough memory available), +<tt/malloc/ returns <tt/NULL/. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="_heapadd" name="_heapadd">, +<ref id="_heapblocksize" name="_heapblocksize">, +<ref id="_heapmaxavail" name="_heapmaxavail">, +<ref id="_heapmemavail" name="_heapmemavail">, +<ref id="calloc" name="calloc">, +<ref id="free" name="free">, +<ref id="realloc" name="realloc">, +<ref id="strdup" name="strdup"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>memchr<label id="memchr"><p> + +<quote> +<descrip> +<tag/Function/Search for a character in a block of raw memory. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/void* __fastcall__ strchr (const void* mem, int c, size_t count);/ +<tag/Description/The <tt/memchr/ function locates the first occurrence of <tt/c/ +(converted to a char) in the block of raw memory string pointed to by <tt/mem/ +that is of size <tt/count/. Upon completion, the function returns a pointer to +the character found, or a null pointer if the character was not found. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strchr" name="strchr"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>memcmp<label id="memcmp"><p> + +<quote> +<descrip> +<tag/Function/Compare two memory areas. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/int __fastcall__ memcmp (const void* p1, const void* p2, size_t count);/ +<tag/Description/<tt/memcmp/ compares <tt/count/ bytes from the memory area +pointed to by <tt/p1/ into the memory area pointed to by <tt/p2/. It returns a value that is less than +zero if <tt/p1/ is less than <tt/p2/, zero if <tt/p1/ is the same as <tt/p2/, +and a value greater than zero if <tt/p1/ is greater than <tt/p2/. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strcmp" name="strcmp">, +<ref id="memmove" name="memmove">, +<ref id="memset" name="memset"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>memcpy<label id="memcpy"><p> + +<quote> +<descrip> +<tag/Function/Copy a memory area. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/void* __fastcall__ memcpy (void* dest, const void* src, size_t count);/ +<tag/Description/<tt/memcpy/ copies <tt/count/ bytes from the memory area +pointed to by <tt/src/ into the memory area pointed to by <tt/dest/. It returns +<tt/dest/. +<tag/Limits/ +<itemize> +<item>The result is undefined if the memory areas do overlap. Use +<tt/<ref id="memmove" name="memmove">/ to copy overlapping memory areas. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="_swap" name="_swap">, +<ref id="memmove" name="memmove">, +<ref id="memset" name="memset"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>memmove<label id="memmove"><p> + +<quote> +<descrip> +<tag/Function/Copy a memory area. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/void* __fastcall__ memmove (void* dest, const void* src, size_t count);/ +<tag/Description/<tt/memmove/ copies <tt/count/ bytes from the memory area +pointed to by <tt/src/ into the memory area pointed to by <tt/dest/. It returns +<tt/dest/. +<tag/Limits/ +<itemize> +<item>While <tt/memmove/ allows the memory areas to overlap, it has some +additional overhead compared to <tt/<ref id="memcpy" name="memcpy">/. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="_swap" name="_swap">, +<ref id="memcpy" name="memcpy">, +<ref id="memset" name="memset"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>memset<label id="memset"><p> + +<quote> +<descrip> +<tag/Function/Fill a memory area. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/void* __fastcall__ memset (void* p, int val, size_t count);/ +<tag/Description/<tt/memset/ fills the memory area pointed to by <tt/p/ with +the value <tt/val/. The function returns <tt/p/. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="_swap" name="_swap">, +<ref id="bzero" name="bzero">, +<ref id="memcpy" name="memcpy">, +<ref id="memmove" name="memmove"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mod_free<label id="mod_free"><p> + +<quote> +<descrip> +<tag/Function/Free a relocatable module. +<tag/Header/<tt/<ref id="modload.h" name="modload.h">/ +<tag/Declaration/<tt/void __fastcall__ mod_free (void* module);/ +<tag/Description/The function will free a module loaded into memory by use of +the <tt/<ref id="mod_load" name="mod_load">/ function. +<tag/Limits/<itemize> +<item>The pointer passed as parameter is the pointer to the module memory, +not the pointer to the control structure. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mod_load" name="mod_load"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mod_load<label id="mod_load"><p> + +<quote> +<descrip> +<tag/Function/Load a relocatable module. +<tag/Header/<tt/<ref id="modload.h" name="modload.h">/ +<tag/Declaration/<tt/unsigned char mod_load (struct mod_ctrl* ctrl);/ +<tag/Description/The function will load a code module into memory and relocate +it. The function will return an error code. If <tt/MLOAD_OK/ is returned, the +outgoing fields in the passed <tt/mod_ctrl/ struct contain information about +the module just loaded. Possible error codes are: +<itemize> +<item><tt/MLOAD_OK/ - Module load successful +<item><tt/MLOAD_ERR_READ/ - Read error +<item><tt/MLOAD_ERR_HDR/ - Header error +<item><tt/MLOAD_ERR_OS/ - Wrong operating system +<item><tt/MLOAD_ERR_FMT/ - Data format error +<item><tt/MLOAD_ERR_MEM/ - Not enough memory +</itemize> +<tag/Limits/<itemize> +<item>The <htmlurl url="ld65.html" name="ld65"> linker is needed to create +relocatable o65 modules for use with this function. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mod_free" name="mod_free"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_setbox<label id="mouse_setbox"><p> + +<quote> +<descrip> +<tag/Function/Specify a bounding box for the mouse cursor. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/void __fastcall__ mouse_setbox (const struct mouse_box* box);/ +<tag/Description/The function allows to set a bounding box for mouse movement. +<tag/Limits/<itemize> +<item>The function does not check if the mouse cursor is currently within the +given rectangle. Placing the mouse cursor within the bounding box is the +responsibility of the programmer. +<item>While the bounding box may be larger than the actual screen size, the +standard mouse cursor draw routines may fail to set the cursor to coordinates +outside of the screen area. Depending on the platform, you may have to supply +your own mouse cursor routines. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_getbox" name="mouse_getbox">, +<ref id="mouse_move" name="mouse_move"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_getbox<label id="mouse_getbox"><p> + +<quote> +<descrip> +<tag/Function/Return the current bounding box for the mouse cursor. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/void __fastcall__ mouse_getbox (struct mouse_box* box);/ +<tag/Description/The function queries the current bounding box for mouse +movement. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_move" name="mouse_move">, +<ref id="mouse_setbox" name="mouse_setbox"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_buttons<label id="mouse_buttons"><p> + +<quote> +<descrip> +<tag/Function/Return a bit mask encoding the state of the mouse buttons. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/unsigned char mouse_buttons (void);/ +<tag/Description/The function returns a bit mask that encodes the state of the +mouse buttons. You may use the <tt/MOUSE_BTN_XXX/ flags to decode the function +return value. +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_info" name="mouse_info">, +<ref id="mouse_pos" name="mouse_pos"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_geterrormsg<label id="mouse_geterrormsg"><p> + +<quote> +<descrip> +<tag/Function/Return a readable error message for an error code. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/const char* __fastcall__ mouse_geterrormsg (unsigned char +code);/ +<tag/Description/The function returns an error message (in english) for the +error code passed parameter. +<tag/Limits/<itemize> +<item>The function will return "Unknown error" for invalid error codes. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_load_driver" name="mouse_load_driver">, +<ref id="mouse_uninstall" name="mouse_uninstall">, +<ref id="mouse_unload" name="mouse_unload"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_hide<label id="mouse_hide"><p> + +<quote> +<descrip> +<tag/Function/Hide the mouse pointer. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/void mouse_hide (void);/ +<tag/Description/The function hides the mouse pointer. It manages a counter +that is shared between <tt/<ref id="mouse_show" name="mouse_show">/ and +<tt/mouse_hide/ so that every call call to <tt/mouse_hide/ must be followed by +a call to <tt/<ref id="mouse_show" name="mouse_show">/ to make the mouse cursor +visible. +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_show" name="mouse_show"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_info<label id="mouse_info"><p> + +<quote> +<descrip> +<tag/Function/Return the state of the mouse buttons and the position of the +mouse. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/void __fastcall__ mouse_info (struct mouse_info* info);/ +<tag/Description/The function returns the state of the mouse buttons and the +position of the mouse in the <tt/mouse_info/ structure passed as parameter. +<tag/Limits/<itemize> +<item>The <tt/mouse_info/ struct is a superset of the <tt/mouse_pos/ struct, +so if you just need the mouse position, call <tt/<ref id="mouse_pos" +name="mouse_pos">/ instead. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_buttons" name="mouse_buttons">, +<ref id="mouse_pos" name="mouse_pos"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_install<label id="mouse_install"><p> + +<quote> +<descrip> +<tag/Function/Install an already loaded mouse driver. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ mouse_install (const struct +mouse_callbacks* c, void* driver);/ +<tag/Description/The function installs an already loaded mouse driver and +returns an error code. The <tt/mouse_callbacks/ structure passed as first +parameter contains pointers to routines needed to move or hide/show the mouse +pointer. Defaults for these routines are supplied by the library, so if you +can live with these defaults (which are platform specific), just pass a +pointer to <tt/mouse_def_callbacks/. The function may be used to install a +driver linked statically to the program. +<tag/Limits/<itemize> +<item>Not all drivers are able to detect if the supported hardware is really +present. +<item>After installing a driver, the mouse cursor is hidden. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_load_driver" name="mouse_load_driver">, +<ref id="mouse_uninstall" name="mouse_uninstall">, +<ref id="mouse_unload" name="mouse_unload"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_ioctl<label id="mouse_ioctl"><p> + +<quote> +<descrip> +<tag/Function/Call the driver specific ioctl function. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data);/ +<tag/Description/The function calls the IOCTL entry in the mouse driver, +which is driver specific. The <tt/code/ parameter will choose between +different IOCTL functions, and the <tt/data/ depends on code. The +function returns an error code. The purpose of this function is to allow +for driver specific extensions. See the documentation for a specific mouse +driver for supported ioctl calls. +<tag/Limits/<itemize> +<item>Calling this function is non portable, because each driver may +implement different ioctl calls (or none at all). +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_load_driver<label id="mouse_load_driver"><p> + +<quote> +<descrip> +<tag/Function/Load and initialize a mouse driver. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ mouse_load_driver (const struct +mouse_callbacks* c, const char* driver);/ +<tag/Description/Load a mouse driver into memory and initialize it. The +function returns an error code that tells if the call has been successful. The +<tt/mouse_callbacks/ structure passed as first parameter contains pointers to +routines needed to move or hide/show the mouse pointer. Defaults for these +routines are supplied by the library, so if you can live with these defaults +(which are platform specific), just pass a pointer to <tt/mouse_def_callbacks/. +<tag/Limits/<itemize> +<item>The driver is loaded by name, so currently you must know the type of +mouse that should be supported. There is no autodetect capability. +<item>Not all drivers are able to detect if the supported hardware is really +present. +<item>After installing a driver, the mouse cursor is hidden. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_install" name="mouse_install">, +<ref id="mouse_uninstall" name="mouse_uninstall">, +<ref id="mouse_unload" name="mouse_unload"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_move<label id="mouse_move"><p> + +<quote> +<descrip> +<tag/Function/Move the mouse cursor to a specific position. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/void __fastcall__ mouse_move (int x, int y);/ +<tag/Description/The function updates the mouse position. If the mouse cursor +is visible, it is shown at the new position. +<tag/Limits/<itemize> +<item>The function does not check if the new position is within the bounding +box specified with <tt/<ref id="mouse_setbox" name="mouse_setbox">/. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_getbox" name="mouse_getbox">, +<ref id="mouse_setbox" name="mouse_setbox"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_pos<label id="mouse_pos"><p> + +<quote> +<descrip> +<tag/Function/Return the position of the mouse. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/void __fastcall__ mouse_pos (struct mouse_pos* pos);/ +<tag/Description/The function returns the position of the mouse in the +<tt/mouse_pos/ structure passed as parameter. +<tag/Limits/<itemize> +<item>The <tt/mouse_pos/ struct is a subset of the <tt/mouse_info/ struct, +so if you do also need the mouse buttons, call <tt/<ref id="mouse_info" +name="mouse_info">/ instead. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_buttons" name="mouse_buttons">, +<ref id="mouse_info" name="mouse_info"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_show<label id="mouse_show"><p> + +<quote> +<descrip> +<tag/Function/Show the mouse pointer. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/void mouse_show (void);/ +<tag/Description/The function shows the mouse pointer. It manages a counter +that is shared between <tt/<ref id="mouse_hide" name="mouse_hide">/ and +<tt/mouse_show/. The mouse cursor is visible if there was one more call to +<tt/mouse_show/ than to <tt/<ref id="mouse_hide" name="mouse_hide">/. +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_hide" name="mouse_hide"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_uninstall<label id="mouse_uninstall"><p> + +<quote> +<descrip> +<tag/Function/Uninstall an already loaded mouse driver. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/unsigned char mouse_uninstall (void);/ +<tag/Description/The function uninstalls an already loaded mouse driver but +don't removes it from memory. +<tag/Limits/<itemize> +<item>If the driver has been loaded using <tt/<ref id="mouse_load_driver" +name="mouse_load_driver">/, <tt/<ref id="mouse_unload" name="mouse_unload">/ +should be used instead of <tt/mouse_uninstall/ so the driver is also removed +from memory. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_install" name="mouse_install">, +<ref id="mouse_load_driver" name="mouse_load_driver">, +<ref id="mouse_unload" name="mouse_unload"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>mouse_unload<label id="mouse_unload"><p> + +<quote> +<descrip> +<tag/Function/Unload a mouse driver. +<tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ mouse_unload (void);/ +<tag/Description/The function unloads a loaded mouse driver and frees all +memory allocated for the driver. +<tag/Limits/<itemize> +<item>The function does nothing if no driver is loaded. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="mouse_install" name="mouse_install">, +<ref id="mouse_load_driver" name="mouse_load_driver">, +<ref id="mouse_uninstall" name="mouse_uninstall"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>offsetof<label id="offsetof"><p> + +<quote> +<descrip> +<tag/Function/Calculate the offset of a struct or union member. +<tag/Header/<tt/<ref id="stddef.h" name="stddef.h">/ +<tag/Declaration/<tt/size_t offsetof (type, member);/ +<tag/Description/<tt/offsetof/ calculates the address offset of a <tt/struct/ +or <tt/union/ member. +<tag/Limits/<itemize> +<item>The function is actually a macro. +</itemize> +<tag/Availability/ISO 9899 +<tag/Example/None. +</descrip> +</quote> + + +<sect1>open<label id="open"><p> + +<quote> +<descrip> +<tag/Function/Open and possibly create a file. +<tag/Header/<tt/<ref id="fcntl.h" name="fcntl.h">/ +<tag/Declaration/<tt/int open (const char* name, int flags, ...);/ +<tag/Description/<tt/open/ opens a file and returns the file descriptor +associated with it. On error, -1 is returned and an error code is stored in +<tt/errno/. Several flags may be passed to <tt/open/ that change the behaviour. +<tag/Limits/<itemize> +<item>POSIX specifies an additional <tt/mode/ argument that may be passed to +open, which is used as the permission mask when a new file is created. While +cc65 allows to pass this argument, it is ignored. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/See also/ +<ref id="close" name="close">, +<ref id="creat" name="creat"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>opendir<label id="opendir"><p> + +<quote> +<descrip> +<tag/Function/Open a directory. +<tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ +<tag/Declaration/<tt/DIR* __fastcall__ opendir (const char* name);/ +<tag/Description/<tt/opendir/ opens a directory and returns the direcory +descriptor associated with it. On error, NULL is returned and an error code is +stored in <tt/errno/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/See also/ +<ref id="closedir" name="closedir">, +<ref id="readdir" name="readdir"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>peekbsys<label id="peekbsys"><p> + +<quote> +<descrip> +<tag/Function/Read one byte from a location in the system bank. +<tag/Header/<tt/<ref id="cbm610.h" name="cbm610.h">/, +<tt/<ref id="cbm510.h" name="cbm510.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ peekbsys (unsigned addr);/ +<tag/Description/<tt/peekbsys/ reads one byte from the given address in the +system bank (bank 15) of the CBM PET-II machines and returns it. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>This function may be a macro depending on the compiler options. The +actual function is accessible by #undef'ing the macro. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="PEEK" name="PEEK">, +<ref id="PEEKW" name="PEEKW">, +<ref id="peekwsys" name="peekwsys">, +<ref id="pokebsys" name="pokebsys">, +<ref id="pokewsys" name="pokewsys"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>peekwsys<label id="peekwsys"><p> + +<quote> +<descrip> +<tag/Function/Read one word from a location in the system bank. +<tag/Header/<tt/<ref id="cbm610.h" name="cbm610.h">/, +<tt/<ref id="cbm510.h" name="cbm510.h">/ +<tag/Declaration/<tt/unsigned __fastcall__ peekwsys (unsigned addr);/ +<tag/Description/<tt/peekwsys/ reads one word from the given address in the +system bank (bank 15) of the CBM PET-II machines and returns it. Following +the usual 6502 conventions, the low byte is read from <tt/addr/, and the +high byte is read from <tt/addr+1/. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>The order in which the two bytes are read is undefined. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="PEEK" name="PEEK">, +<ref id="PEEKW" name="PEEKW">, +<ref id="peekbsys" name="peekbsys">, +<ref id="pokebsys" name="pokebsys">, +<ref id="pokewsys" name="pokewsys"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>perror<label id="perror"><p> + +<quote> +<descrip> +<tag/Function/Print an error message for the error in <tt/errno/. +<tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ +<tag/Declaration/<tt/void __fastcall__ perror (const char* s);/ +<tag/Description/<tt/perror/ prints an error message to <tt/stderr/. If <tt/s/ +is not <tt/NULL/ and not an empty string, it is printed followed by a colon and +a blank. Then the error message for the current contents of <tt/errno/ is +printed followed by a newline. The message output is the same as returned by +<tt/<ref id="strerror" name="strerror">/ with an argument of <tt/errno/. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="_poserror" name="_poserror">, +<ref id="strerror" name="strerror"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>pokebsys<label id="pokebsys"><p> + +<quote> +<descrip> +<tag/Function/Write one byte to a location in the system bank. +<tag/Header/<tt/<ref id="cbm610.h" name="cbm610.h">/, +<tt/<ref id="cbm510.h" name="cbm510.h">/ +<tag/Declaration/<tt/void __fastcall__ pokebsys (unsigned addr, unsigned char val);/ +<tag/Description/<tt/pokebsys/ writes one byte to the given address in the +system bank (bank 15) of the CBM PET-II machines. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="POKE" name="POKE">, +<ref id="POKEW" name="POKEW">, +<ref id="peekbsys" name="peekbsys">, +<ref id="peekwsys" name="peekwsys">, +<ref id="pokewsys" name="pokewsys"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>pokewsys<label id="pokewsys"><p> + +<quote> +<descrip> +<tag/Function/Write one word to a location in the system bank. +<tag/Header/<tt/<ref id="cbm610.h" name="cbm610.h">/, +<tt/<ref id="cbm510.h" name="cbm510.h">/ +<tag/Declaration/<tt/void __fastcall__ pokewsys (unsigned addr, unsigned val);/ +<tag/Description/<tt/pokewsys/ writes one word to the given address in the +system bank (bank 15) of the CBM PET-II machines. Following the usual 6502 +conventions, the low byte of <tt/val/ is written to <tt/addr/, and the +high byte is written to <tt/addr+1/. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>The order in which the two bytes are written is undefined. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="POKE" name="POKE">, +<ref id="POKEW" name="POKEW">, +<ref id="peekbsys" name="peekbsys">, +<ref id="peekwsys" name="peekwsys">, +<ref id="pokebsys" name="pokebsys"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>qsort<label id="qsort"><p> + +<quote> +<descrip> +<tag/Function/Sort an array. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void __fastcall__ qsort (void* base, size_t count, +size_t size, int (*compare) (const void*, const void*));/ +<tag/Description/<tt/qsort/ sorts an array according to a given compare +function <tt/compare/. <tt/base/ is the address of the array, <tt/count/ +is the number of elements, <tt/size/ the size of an element and <tt/compare/ +the function used to compare the members. +<tag/Limits/ +<itemize> +<item>If there are multiple members with the same key, the order after calling +the function is undefined. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="bsearch" name="bsearch"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>raise<label id="raise"><p> + +<quote> +<descrip> +<tag/Function/Send a signal to the executing program. +<tag/Header/<tt/<ref id="signal.h" name="signal.h">/ +<tag/Declaration/<tt/int __fastcall__ raise (int sig);/ +<tag/Description/<tt/raise/ sends the given signal to the program. If the +program has installed a signal handler for the signal, this signal handler +will be executed. If no handler has been installed, the default action for +the raised signal will be taken. The function returns zero on success, +nonzero otherwise. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="abort" name="abort">, +<ref id="signal" name="signal"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>rand<label id="rand"><p> + +<quote> +<descrip> +<tag/Function/Return a pseudo random number. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/int rand (void);/ +<tag/Description/The function returns a pseudo random number +between 0 and <tt/RAND_MAX/ (exclusive). +<tag/Limits/<itemize> +<item>Without using <tt><ref id="srand" name="srand"></tt>, always the same +flow of numbers is generated. +<item>On startup, the function behaves as if <ref id="srand" name="srand"> +had been used with an argument of 1. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="_randomize" name="_randomize">, +<ref id="srand" name="srand"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>readdir<label id="readdir"><p> + +<quote> +<descrip> +<tag/Function/Read a directory. +<tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ +<tag/Declaration/<tt/struct dirent* __fastcall__ readdir (DIR* dir);/ +<tag/Description/<tt/readdir/ reads the next directory entry from the directory +stream pointed to by <tt/dir/. It stores the data in a <tt/dirent/ structure +and returns a pointer to it. If the end of directory is reached, or an error +occurs, NULL is returned. In case of errors, an error code is stored into +<tt/errno/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>The returned pointer may point to a statically allocated instance of +<tt/struct dirent/, so it may get overwritten by subsequent calls to +<tt/readdir/. +<item>On several platforms, namely the CBMs and the Atari, the disk drives get +confused when opening/closing files between directory reads. So for example a +program that reads the list of files on a disk, and after each call to +<tt/readdir/, opens the file to process it, will fail.<newline> +Possible solutions are reading the directory into memory before processing the +file list, or to reset the directory by seeking to the correct position after +opening/closing a file: +<verb> + seekdir (DIR, telldir (DIR)); +</verb> +Platforms known to work without problems are: Apple. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/See also/ +<ref id="closedir" name="closedir">, +<ref id="opendir" name="opendir"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>realloc<label id="realloc"><p> + +<quote> +<descrip> +<tag/Function/Change the size of an allocated memory block. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void* __fastcall__ realloc (void* block, size_t size);/ +<tag/Description/<tt/realloc/ changes the size of the memory block pointed to +by <tt/block/ to <tt/size/ bytes. If <tt/block/ is <tt/NULL/, <tt/realloc/ +behaves as if <tt/malloc/ had been called. If <tt/size/ is zero, <tt/realloc/ +behaves as if <tt/free/ had been called. On error (not enough memory +available), <tt/realloc/ returns <tt/NULL/. +<tag/Limits/ +<itemize> +<item>The part of the memory block that is returned will have its contents +unchanged. +<item>This function is somewhat dangerous to use. Be careful to save the +pointer you're passing somewhere else, otherwise +<tscreen><verb> + ptr = realloc (ptr, size); +</verb></tscreen> +will loose your only copy of <tt/ptr/ if <tt/realloc/ returns <tt/NULL/. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="_heapadd" name="_heapadd">, +<ref id="_heapblocksize" name="_heapblocksize">, +<ref id="_heapmaxavail" name="_heapmaxavail">, +<ref id="_heapmemavail" name="_heapmemavail">, +<ref id="calloc" name="calloc">, +<ref id="free" name="free">, +<ref id="realloc" name="realloc"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>remove<label id="remove"><p> + +<quote> +<descrip> +<tag/Function/Delete a file. +<tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ +<tag/Declaration/<tt/int __fastcall__ remove (const char* name);/ +<tag/Description/<tt/remove/ deletes the file with the given name. On success, +zero is returned. On error, -1 is returned and <tt/errno/ is set to an error +code describing the reason for the failure. +<tag/Limits/ +<itemize> +<item>This function is not available on all cc65 targets (depends on the +availability of file I/O). +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="rename" name="rename">, +<ref id="unlink" name="unlink"> +<tag/Example/ +<verb> +#include <stdio.h> + +#define FILENAME "helloworld" + +if (remove (FILENAME) == 0) { + printf ("We deleted %s successfully\n", FILENAME); +} else { + printf ("There was a problem deleting %s\n", FILENAME); +} +</verb> +</descrip> +</quote> + + +<sect1>rename<label id="rename"><p> + +<quote> +<descrip> +<tag/Function/Rename a file. +<tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ +<tag/Declaration/<tt/int __fastcall__ rename (const char* oldname, const char* newname);/ +<tag/Description/<tt/rename/ renames a file (gives it a new name). On success, +zero is returned. On error, -1 is returned and <tt/errno/ is set to an error +code describing the reason for the failure. +<tag/Limits/ +<itemize> +<item>This function is not available on all cc65 targets (depends on the +capabilities of the storage devices). +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="remove" name="remove"> +<tag/Example/ +<verb> +#include <stdio.h> + +#define OLDNAME "textfile.txt" +#define NEWNAME "textfile.bak" + +if (rename (OLDNAME, NEWNAME) == 0) { + printf ("Renamed %s to %s\n", OLDNAME, NEWNAME); +} else { + printf ("Error renaming %s to %s\n", OLDNAME, NEWNAME); +} +</verb> +</descrip> +</quote> + + +<sect1>reset_brk<label id="reset_brk"><p> + +<quote> +<descrip> +<tag/Function/Resets the break vector to its original value. +<tag/Header/<tt/<ref id="6502.h" name="6502.h">/ +<tag/Declaration/<tt/void reset_brk (void);/ +<tag/Description/<tt/reset_brk/ resets the break vector to the value it had +before a call to <tt/set_brk/. +<tag/Limits/ +<itemize> +<item>Since <tt/<ref id="set_brk" name="set_brk">/ installs an exit handler, +it is not strictly necessary to call this function as part of the cleanup when +the program ends. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="reset_irq" name="reset_irq">, +<ref id="set_brk" name="set_brk">, +<ref id="set_irq" name="set_irq"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>reset_irq<label id="reset_irq"><p> + +<quote> +<descrip> +<tag/Function/Resets the C level interrupt request vector. +<tag/Header/<tt/<ref id="6502.h" name="6502.h">/ +<tag/Declaration/<tt/void reset_irq (void);/ +<tag/Description/<tt/reset_irq/ resets the C level interrupt request vector. +<tag/Limits/ +<itemize> +<item>The original IRQ vector is restored on program termination even without +calling this function. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="reset_brk" name="reset_brk">, +<ref id="set_brk" name="set_brk">, +<ref id="set_irq" name="set_irq"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>revers<label id="revers"><p> + +<quote> +<descrip> +<tag/Function/Control revers character display. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ revers (unsigned char onoff);/ +<tag/Description/If the argument is non zero, the function enables reverse +character display. If the argument is zero, reverse character display is +switched off. The old value of the setting is returned. +<tag/Limits/<itemize> +<item>The function may not be supported by the hardware, in which case +the call is ignored. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="textcolor" name="textcolor"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>rewinddir<label id="rewinddir"><p> + +<quote> +<descrip> +<tag/Function/Reset a directory stream. +<tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ +<tag/Declaration/<tt/void __fastcall__ rewinddir (DIR* dir);/ +<tag/Description/<tt/rewinddir/ sets the position of the directory stream +pointed to by <tt/dir/ to the start of the directory. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/See also/ +<ref id="seekdir" name="seekdir">, +<ref id="telldir" name="telldir"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>screensize<label id="screensize"><p> + +<quote> +<descrip> +<tag/Function/Return the dimensions of the text mode screen. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ screensize (unsigned char* x, unsigned char* y);/ +<tag/Description/The function returns the dimensions of the text mode screen. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="gotox" name="gotox">, +<ref id="gotoxy" name="gotoxy">, +<ref id="gotoy" name="gotoy">, +<ref id="wherex" name="wherex">, +<ref id="wherey" name="wherey"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>seekdir<label id="seekdir"><p> + +<quote> +<descrip> +<tag/Function/Set the position of a directory stream. +<tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ +<tag/Declaration/<tt/void __fastcall__ seekdir (DIR* dir, long offset);/ +<tag/Description/<tt/seekdir/ sets the position of the directory stream +pointed to by <tt/dir/ to the value given in <tt/offset/, which should be a +value returned by <tt/<ref id="telldir" name="telldir">/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/See also/ +<ref id="rewinddir" name="rewinddir">, +<ref id="telldir" name="telldir"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>ser_close<label id="ser_close"><p> + +<quote> +<descrip> +<tag/Function/Close the port and disable interrupts +<tag/Header/<tt/<ref id="serial.h" name="serial.h">/ +<tag/Declaration/<tt/unsigned char ser_close (void);/ +<tag/Description/Close the port by clearing buffers and disable interrupts. +<tag/Availability/cc65 +<tag/See also/Other serial functions. +<tag/Example/ +<verb> +#include <serial.h> + +static void initialize(){ + struct ser_params params = { + SER_BAUD_9600, + SER_BITS_8, + SER_STOP_1, + SER_PAR_MARK, + SER_HS_NONE + }; + ser_install(lynx_comlynx); // This will activate the ComLynx + CLI(); + ser_open(&params); +} +</verb> +</descrip> +</quote> + + +<sect1>ser_get<label id="ser_get"><p> + +<quote> +<descrip> +<tag/Function/Read a character from serial port. +<tag/Header/<tt/<ref id="serial.h" name="serial.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ ser_get (char* b);/ +<tag/Description/Get a character from the serial port. If no characters are +available, the function will return SER_ERR_NO_DATA, so this is not a fatal +error. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other serial functions. +<tag/Example/ +Wait for a character to be available from a serial port. +<verb> +char ch; +while (ser_get(&ch) == SER_ERR_NO_DATA) + ; +</verb> +</descrip> +</quote> + + +<sect1>ser_install<label id="ser_install"><p> + +<quote> +<descrip> +<tag/Function/Install an already loaded driver and return an error code. +<tag/Header/<tt/<ref id="serial.h" name="serial.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ ser_install (void* driver);/ +<tag/Description/The function installs a driver that was already loaded into +memory (or linked statically to the program). It returns an error code +(<tt/SER_ERR_OK/ in case of success). +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="ser_load_driver" name="ser_load_driver">, +<ref id="ser_uninstall" name="ser_uninstall">, +<ref id="ser_unload" name="ser_unload"> +<tag/Example/<verb> +ser_install(lynx_comlynx); //Include the driver statically instead of loading it. +</verb> +</descrip> +</quote> + + +<sect1>ser_ioctl<label id="ser_ioctl"><p> + +<quote> +<descrip> +<tag/Function/Platform dependent code extensions. +<tag/Header/<tt/<ref id="serial.h" name="serial.h">/ +<tag/Declaration/<tt/unsigned __fastcall__ ser_ioctl (unsigned char code, void* data);/ +<tag/Description/Some platforms have extra serial functions that are not +supported by standard serial driver functions. You can extend the driver to support +this extra functionality bt using ser_ioctl functions. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>These functions are not easily portable to other cc65 platforms. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other serial functions. +<tag/Example/None +</descrip> +</quote> + +<sect1>ser_load_driver<label id="ser_load_driver"><p> + +<quote> +<descrip> +<tag/Function/Load and install a serial driver. +<tag/Header/<tt/<ref id="serial.h" name="serial.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ ser_load_driver (const char *name);/ +<tag/Description/Load and install the driver by name. +Will just load the driver and check if loading was successful. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other serial functions. +<tag/Example/None. +</descrip> +</quote> + + +<sect1>ser_open<label id="ser_open"><p> + +<quote> +<descrip> +<tag/Function/Open the port by setting the port parameters and enable interrupts +<tag/Header/<tt/<ref id="serial.h" name="serial.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ ser_open (const struct ser_params* params);/ +<tag/Description/Open the port by setting the port parameters and enable interrupts. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other serial functions. +<tag/Example/ +<verb> +#include <serial.h> + +static void initialize(){ + struct ser_params params = { + SER_BAUD_9600, + SER_BITS_8, + SER_STOP_1, + SER_PAR_MARK, + SER_HS_NONE + }; + ser_install(lynx_comlynx); // This will activate the ComLynx + CLI(); + ser_open(&params); +} +</verb> +</descrip> +</quote> + + +<sect1>ser_put<label id="ser_put"><p> + +<quote> +<descrip> +<tag/Function/Write a character to a serial port. +<tag/Header/<tt/<ref id="serial.h" name="serial.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ ser_put (char b);/ +<tag/Description/Send a character via the serial port. There is a transmit +buffer, but transmitting is not done via interrupt. The function returns +SER_ERR_OVERFLOW if there is no space left in the transmit buffer. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other serial functions. +<tag/Example/ +<verb> +ser_put('A'); +</verb> +</descrip> +</quote> + + +<sect1>ser_status<label id="ser_status"><p> + +<quote> +<descrip> +<tag/Function/Return the serial port status. +<tag/Header/<tt/<ref id="serial.h" name="serial.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ ser_status (unsigned char* status);/ +<tag/Description/Return the serial port status. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other serial functions. +<tag/Example/None +</descrip> +</quote> + + +<sect1>ser_uninstall<label id="ser_uninstall"><p> + +<quote> +<descrip> +<tag/Function/Uninstall the currently loaded driver but do not unload it. +<tag/Header/<tt/<ref id="serial.h" name="serial.h">/ +<tag/Declaration/<tt/unsigned char ser_uninstall (void);/ +<tag/Description/Uninstall the currently loaded driver but do not unload it. +<tag/Availability/cc65 +<tag/See also/Other serial functions. +<tag/Example/None. +</descrip> +</quote> + +<sect1>ser_unload<label id="ser_unload"><p> + +<quote> +<descrip> +<tag/Function/Uninstall, then unload the currently loaded driver. +<tag/Header/<tt/<ref id="serial.h" name="serial.h">/ +<tag/Declaration/<tt/unsigned char ser_unload (void);/ +<tag/Description/Uninstall, then unload the currently loaded driver. +<tag/Availability/cc65 +<tag/See also/Other serial functions. +<tag/Example/None. +</descrip> +</quote> + + +<sect1>set_brk<label id="set_brk"><p> + +<quote> +<descrip> +<tag/Function/Set the break vector to a user function. +<tag/Header/<tt/<ref id="6502.h" name="6502.h">/ +<tag/Declaration/<tt/void __fastcall__ set_brk (brk_handler func);/ +<tag/Description/<tt/set_brk/ allows a user program to handle breaks within the +program code by letting the vector point to a user written C function. The +runtime library installs a small stub that saves the registers into global +variables that may be accessed (and changed) by the break handler. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>The stub saves the zero page registers used by the C runtime and switches +to a small break handler stack. This means that it is safe to execute C code, +even if C code was interrupted. Be careful however not to use too many local +variables, and do not enable stack checks for the handler function or any other +function called from it. +<item>The <tt/brk_pc/ variable points to the <tt/BRK/ instruction. If you want +the continue with the interrupted code, you have to adjust <tt/brk_pc/, +otherwise the <tt/BRK/ instruction will get executed over and over again. +<item>Since <tt/set_brk/ installs an exit handler, it is not strictly necessary +to call <tt/<ref id="reset_brk" name="reset_brk">/ as part of the cleanup when +the program terminates. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="reset_brk" name="reset_brk"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>set_irq<label id="set_irq"><p> + +<quote> +<descrip> +<tag/Function/Set the C level interrupt request vector to the given address. +<tag/Header/<tt/<ref id="6502.h" name="6502.h">/ +<tag/Declaration/<tt/void __fastcall__ set_irq (irq_handler f, void *stack_addr, size_t stack_size);/ +<tag/Description/<tt/set_irq/ allows a user program to handle interrupt requests +(IRQs) within the program code by letting the vector point to a user written C +function. The runtime library installs a small stub that saves the zero page +registers used by the C runtime before calling the handler function and restores +them after the handler function returns. Additionally the stub temporarily switches +the C runtime stack to the stack area provided as parameter. If the handler function +was set up to handle a "private", "exclusive" interrupt request source it must +return the value <tt/IRQ_HANDLED/ if and only if it has verified that the current +interrupt request actually stems from that source. In all other cases it must return +the value <tt/IRQ_NOT_HANDLED/. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>The stub saves the registers and zero page locations used by the C runtime +and switches to the provided stack area. As a consequence, there is some +runtime overhead, but it it is safe to execute C code, even if other C code +was interrupted. Be careful however not to call C library functions, and do not +enable stack checks for the handler function or any other function called from +it. +<item>The interrupt vector is reset on function termination, so it's not +strictly necessary to call <tt/<ref id="reset_irq" name="reset_irq">/ as part +of the cleanup when the program terminates. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="reset_brk" name="reset_brk">, +<ref id="reset_irq" name="reset_irq">, +<ref id="set_brk" name="set_brk"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>setjmp<label id="setjmp"><p> + +<quote> +<descrip> +<tag/Function/Save the context for use with <tt/longjmp/. +<tag/Header/<tt/<ref id="setjmp.h" name="setjmp.h">/ +<tag/Declaration/<tt/int __fastcall__ setjmp (jmp_buf buf);/ +<tag/Description/The <tt/setjmp/ function saves the current context in <tt/buf/ +for subsequent use by the <tt/<ref id="longjmp" name="longjmp">/ function and +returns zero. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item><tt/setjmp/ is actually a macro as required by the ISO standard. +<item><tt/setjmp/ will not save the signal context. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="longjmp" name="longjmp"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>setlocale<label id="setlocale"><p> + +<quote> +<descrip> +<tag/Function/Selects a locale. +<tag/Header/<tt/<ref id="locale.h" name="locale.h">/ +<tag/Declaration/<tt/char* __fastcall__ setlocale (int category, const char* locale);/ +<tag/Description/<tt/setlocale/ sets or queries the program's locale. +<tag/Limits/ +<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>cc65 supports only the "C" locale, so calling this function to set a +different locale has no effect. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="localeconv" name="localeconv">, +<ref id="strcoll" name="strcoll"> +<ref id="strxfrm" name="strxfrm"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>signal<label id="signal"><p> + +<quote> +<descrip> +<tag/Function/Install a signal handler. +<tag/Header/<tt/<ref id="signal.h" name="signal.h">/ +<tag/Declaration/<tt/__sigfunc __fastcall__ signal (int sig, __sigfunc func);/ +<tag/Description/<tt/signal/ installs a handler for the given signal. The +handler may either be a user supplied function, or one of the predefined +signal handlers <tt/SIG_IGN/ or <tt/SIG_DFL/. The function returns the +previous value if the signal , or the special function vector SIG_ERR in +case of an error. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="abort" name="abort">, +<ref id="raise" name="raise"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>sleep<label id="sleep"><p> + +<quote> +<descrip> +<tag/Function/Sleep for a specified amount of time. +<tag/Header/<tt/<ref id="unistd.h" name="unistd.h">/ +<tag/Declaration/<tt/void __fastcall__ sleep (unsigned seconds);/ +<tag/Description/The function will return after the specified number of +seconds have elapsed. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/Example/None. +</descrip> +</quote> + + +<sect1>slow<label id="slow"><p> + +<quote> +<descrip> +<tag/Function/Switch the C128 into 1MHz mode. +<tag/Header/<tt/<ref id="c128.h" name="c128.h">/ +<tag/Declaration/<tt/void slow (void);/ +<tag/Description/The function will switch the clock of the C128 to 1MHz. This +will halve the speed compared to fast mode. +<tag/Limits/<itemize> +<item>The function is specific to the C128. +</itemize> +<tag/Availability/C128 +<tag/See also/ +<ref id="fast" name="fast">, +<ref id="toggle_videomode" name="toggle_videomode">, +<ref id="videomode" name="videomode"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>srand<label id="srand"><p> + +<quote> +<descrip> +<tag/Function/Initialize the pseudo random number generator. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/void __fastcall__ srand (unsigned seed);/ +<tag/Description/The function initializes the random number generator using +the given seed. On program startup, the generator behaves as if <tt/srand/ has +been called with an argument of 1. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="_randomize" name="_randomize">, +<ref id="rand" name="rand"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strcasecmp<label id="strcasecmp"><p> + +<quote> +<descrip> +<tag/Function/Compare two strings case insensitive. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/int __fastcall__ strcasecmp (const char* s1, const char* s2);/ +<tag/Description/The <tt/strcasecmp/ function compares the two strings passed +as parameters without case sensitivity. It returns a value that is less than +zero if <tt/s1/ is less than <tt/s2/, zero if <tt/s1/ is the same as <tt/s2/, +and a value greater than zero if <tt/s1/ is greater than <tt/s2/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>The function is not available in strict ANSI mode. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="strcmp" name="strcmp">, +<ref id="strcoll" name="strcoll">, +<ref id="stricmp" name="stricmp">, +<ref id="strncmp" name="strncmp">, +<ref id="strxfrm" name="strxfrm"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strcat<label id="strcat"><p> + +<quote> +<descrip> +<tag/Function/Concatentate two strings. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strcat (char* s1, const char* s2);/ +<tag/Description/The <tt/strcat/ function appends a copy of the string +pointed to by s2 (including the terminating null byte) to the end of the +string pointed to by s1. The initial byte of s2 overwrites the null byte at +the end of s1. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>If copying takes place between objects that overlap, the behaviour +is undefined. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strcpy" name="strcpy">, +<ref id="strncat" name="strncat">, +<ref id="strncpy" name="strncpy"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strchr<label id="strchr"><p> + +<quote> +<descrip> +<tag/Function/Search for a character in a string. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strchr (const char* s, int c);/ +<tag/Description/The <tt/strchr/ function locates the first occurrence of <tt/c/ +(converted to a char) in the string pointed to by <tt/s/. The terminating null +byte is considered to be part of the string. Upon completion, the function +returns a pointer to the byte, or a null pointer if the byte was not found. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="memchr" name="memchr">, +<ref id="strrchr" name="strrchr"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strcmp<label id="strcmp"><p> + +<quote> +<descrip> +<tag/Function/Compare two strings. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/int __fastcall__ strcmp (const char* s1, const char* s2);/ +<tag/Description/The <tt/strcmp/ function compares the two strings passed as +parameters. It returns a value that is less than zero if <tt/s1/ is less than +<tt/s2/, zero if <tt/s1/ is the same as <tt/s2/, and a value greater than zero +if <tt/s1/ is greater than <tt/s2/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strcasecmp" name="strcasecmp">, +<ref id="strcoll" name="strcoll">, +<ref id="stricmp" name="stricmp">, +<ref id="strncmp" name="strncmp"> +<ref id="strxfrm" name="strxfrm"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strcoll<label id="strcoll"><p> + +<quote> +<descrip> +<tag/Function/Compare two strings. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/int __fastcall__ strcoll (const char* s1, const char* s2);/ +<tag/Description/The <tt/strcoll/ function compares the two strings passed as +parameters, according to the collating sequence set by <tt/<ref id="setlocale" +name="setlocale">/. It returns a value that is less than zero if <tt/s1/ is +less than <tt/s2/, zero if <tt/s1/ is the same as <tt/s2/, and a value greater +than zero if <tt/s1/ is greater than <tt/s2/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="setlocale" name="setlocale">, +<ref id="strcasecmp" name="strcasecmp">, +<ref id="strcmp" name="strcmp">, +<ref id="stricmp" name="stricmp">, +<ref id="strncmp" name="strncmp">, +<ref id="strxfrm" name="strxfrm"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strcpy<label id="strcpy"><p> + +<quote> +<descrip> +<tag/Function/Copy a string. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strcpy (char* s1, const char* s2);/ +<tag/Description/The <tt/strcpy/ function copies the string pointed to by +<tt/s2/ (including the terminating null byte) into the array pointed to by +<tt/s1/. The function will always return <tt/s1/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>If copying takes place between objects that overlap, the behaviour +is undefined. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strcat" name="strcat">, +<ref id="strncat" name="strncat">, +<ref id="strncpy" name="strncpy"> +<tag/Example/ +<verb> +#include <string.h> + +static char hello[14]; + +strcpy (hello, "Hello world!\n"); +</verb> +</descrip> +</quote> + + +<sect1>strcspn<label id="strcspn"><p> + +<quote> +<descrip> +<tag/Function/Compute the length of a substring. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/size_t __fastcall__ strcspn (const char* s, const char* set);/ +<tag/Description/The <tt/strcspn/ function computes and returns the length of +the substring pointed to by <tt/s/ which does <em>not</em> consist of +characters contained in the string <tt/set/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strqtok" name="strqtok">, +<ref id="strspn" name="strspn">, +<ref id="strstr" name="strstr">, +<ref id="strtok" name="strtok"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strdup<label id="strdup"><p> + +<quote> +<descrip> +<tag/Function/Allocate a copy of a string on the heap. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strdup (const char* s);/ +<tag/Description/<tt/strdup/ allocates a memory block on the heap, big enough +to hold a copy of <tt/s/ including the terminating zero. If the allocation +fails, <tt/NULL/ is returned, otherwise <tt/s/ is copied into the allocated +memory block, and a pointer to the block is returned. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>It is up to the caller to free the allocated memory block. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="free" name="free">, +<ref id="malloc" name="malloc"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strerror<label id="strerror"><p> + +<quote> +<descrip> +<tag/Function/Return a string describing an error code. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strerror (int errcode);/ +<tag/Description/The <tt/strerror/ function returns a string describing the +given error code. If an invalid error code is passed, the string "Unknown +error" is returned, and <tt/errno/ is set to <tt/EINVAL/. In all other cases, +<tt/errno/ is left untouched. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>While the return type of the function is a <tt/char*/, the returned +string must not be modified by the caller! +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="_stroserror" name="_stroserror"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>stricmp<label id="stricmp"><p> + +<quote> +<descrip> +<tag/Function/Compare two strings case insensitive. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/int __fastcall__ stricmp (const char* s1, const char* s2);/ +<tag/Description/The <tt/stricmp/ function compares the two strings passed as +parameters without case sensitivity. It returns a value that is less than zero +if <tt/s1/ is less than <tt/s2/, zero if <tt/s1/ is the same as <tt/s2/, and a +value greater than zero if <tt/s1/ is greater than <tt/s2/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>The function is not available in strict ANSI mode. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="strcasecmp" name="strcasecmp">, +<ref id="strcmp" name="strcmp">, +<ref id="strcoll" name="strcoll">, +<ref id="strncmp" name="strncmp">, +<ref id="strxfrm" name="strxfrm"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strlen<label id="strlen"><p> + +<quote> +<descrip> +<tag/Function/Return the length of a string. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/size_t __fastcall__ strlen (const char* s);/ +<tag/Description/The <tt/strlen/ function computes the number of bytes in the +string to which s points, not including the terminating null byte. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>When compiling with <tt/-Os/ (inline known standard functions), the +function does not work correctly for strings with more than 255 characters. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strcpy" name="strcpy"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strlower<label id="strlower"><p> + +<quote> +<descrip> +<tag/Function/Make a string lower case. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strlower (char* s);/ +<tag/Description/The <tt/strlower/ function will apply the <tt/tolower/ +function to each character of a string. The function will always return <tt/s/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>The function prototype is unavailable when compiling in strict ANSI mode. +<item>An alias name for this function is <tt/strlwr/. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="strupper" name="strupper">, +<ref id="tolower" name="tolower"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strlwr<label id="strlwr"><p> + +<quote> +See <tt/strlower/. +</quote> + + +<sect1>strncat<label id="strncat"><p> + +<quote> +<descrip> +<tag/Function/Concatentate two strings. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strncat (char* s1, const char* s2, size_t n);/ +<tag/Description/The <tt/strncat/ function appends not more than n characters +of the string pointed to by s2 to the end of the string pointed to by s1. The +terminating null character at the end of s1 is overwritten. A terminating null +character is appended to the result, even if not all of s2 is appended to s1. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>If copying takes place between objects that overlap, the behaviour +is undefined. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strcpy" name="strcpy">, +<ref id="strncat" name="strncat">, +<ref id="strncpy" name="strncpy"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strncmp<label id="strncmp"><p> + +<quote> +<descrip> +<tag/Function/Compare two strings. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/int __fastcall__ strncmp (const char* s1, const char* s2, size_t count);/ +<tag/Description/The <tt/strncmp/ function compares not more than <tt/count/ +characters of the two strings passed as parameters. It returns a value that is +less than zero if the first <tt/count/ characters of <tt/s1/ are less than +<tt/s2/, zero if they are identical, and a value greater than zero they are +greater. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strcasecmp" name="strcasecmp">, +<ref id="strcmp" name="strcmp">, +<ref id="strcoll" name="strcoll">, +<ref id="stricmp" name="stricmp">, +<ref id="strxfrm" name="strxfrm"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strncpy<label id="strncpy"><p> + +<quote> +<descrip> +<tag/Function/Copy part of a string. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strncpy (char* s1, const char* s2, size_t n);/ +<tag/Description/The <tt/strncpy/ function copies not more than <tt/n/ bytes from +the array pointed to by <tt/s2/ to the array pointed to by <tt/s1/. If the array +pointed to by <tt/s2/ is a string that is shorter than <tt/n/ bytes, null bytes are +appended to the copy in the array pointed to by <tt/s1/, until <tt/n/ bytes are +written. The function always will return <tt/s1/. +<tag/Limits/<itemize> +<item>The function is available only as a fastcall function; so, it may be used +only in the presence of a prototype. +<item>If there is no null byte in the first <tt/n/ bytes of the array pointed +to by <tt/s2/, the result is <em/not/ null-terminated! +<item>If copying takes place between objects that overlap, the behaviour is +undefined. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="memcpy" name="memcpy">, +<ref id="strcat" name="strcat">, +<ref id="strcpy" name="strcpy">, +<ref id="strncat" name="strncat"> +<tag/Example/ +<verb> +#include <string.h> + +static char hello[6]; + +strncpy (hello, "Hello world!\n", sizeof hello - 1)[5] = '\0'; +</verb> +</descrip> +</quote> + + +<sect1>strqtok<label id="strqtok"><p> + +<quote> +<descrip> +<tag/Function/Break a string into tokens. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strqtok (char* s1, const char* s2);/ +<tag/Description/<tt/strqtok()/ will break the string <tt/s1/ into a sequence of +tokens, which are delimited by either quotation marks or characters from the +string <tt/s2/. Tokens inside quotation marks may contain characters from <tt/s2/ +(they aren't delimiters there). The first call to <tt/strqtok()/ will return a +pointer to the first token in the string <tt/s1/. The following calls must pass +a <tt/NULL/ pointer as <tt/s1/, in order to get the next token in the string. +Different sets of delimiters may be used for the subsequent calls to <tt/strqtok()/. +<tag/Limits/<itemize> +<item>The function is available only as a fastcall function; so, it may be used +only in the presence of a prototype. +<item><tt/strqtok()/ will modify the string <tt/s1/. +<item>The function will forget where it is in the <tt/s1/ string if it is given +a second <tt/s1/ string before it finishes the first one. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="strcspn" name="strcspn">, +<!-- <ref id="strpbrk" name="strpbrk">, --> +<ref id="strspn" name="strspn">, +<ref id="strtok" name="strtok"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strrchr<label id="strrchr"><p> + +<quote> +<descrip> +<tag/Function/Search for a character in a string. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strrchr (const char* s, int c);/ +<tag/Description/The <tt/strrchr/ function locates the last occurrence of <tt/c/ +(converted to a char) in the string pointed to by <tt/s/. The terminating null +byte is considered to be part of the string. Upon completion, the function +returns a pointer to the byte, or a null pointer if the byte was not found. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strchr" name="strchr"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strspn<label id="strspn"><p> + +<quote> +<descrip> +<tag/Function/Compute the length of a substring. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/size_t __fastcall__ strspn (const char* s, const char* set);/ +<tag/Description/The <tt/strspn/ function computes and returns the length of +the substring pointed to by <tt/s/ which does consist only of characters +contained in the string <tt/set/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strcspn" name="strcspn">, +<ref id="strstr" name="strstr"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strstr<label id="strstr"><p> + +<quote> +<descrip> +<tag/Function/Find a substring. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strstr (const char* str, const char* substr);/ +<tag/Description/<tt/strstr/ searches for the first occurance of the string +<tt/substr/ within <tt/str/. If found, it returns a pointer to the copy, +otherwise it returns <tt/NULL/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strcspn" name="strcspn">, +<ref id="strspn" name="strspn"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strtok<label id="strtok"><p> + +<quote> +<descrip> +<tag/Function/Break a string into tokens. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strtok (char* s1, const char* s2);/ +<tag/Description/<tt/strtok()/ will break the string <tt/s1/ into a sequence of +tokens, which are delimited by characters from the string <tt/s2/. The first call +to <tt/strtok()/ will return a pointer to the first token in the string <tt/s1/. +The following calls must pass a <tt/NULL/ pointer as <tt/s1/, in order to get +the next token in the string. Different sets of delimiters may be used for the +subsequent calls to <tt/strtok()/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item><tt/strtok()/ will modify the string <tt/s1/. +<item>The function will forget where it is in the <tt/s1/ string if it is given +a second <tt/s1/ string before it finishes the first one. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strcspn" name="strcspn">, +<!-- <ref id="strpbrk" name="strpbrk">, --> +<ref id="strqtok" name="strqtok">, +<ref id="strspn" name="strspn"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strxfrm<label id="strxfrm"><p> + +<quote> +<descrip> +<tag/Function/Transform a string. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/size_t __fastcall__ strxfrm (char* s1, const char* s2, size_t n);/ +<tag/Description/The <tt/strxfrm/ function transforms the string pointed to by +s2 and places the resulting string into the string pointed to by s1. The +transformation is such that if the <tt/strcmp/ function is applied to two +transformed strings, it returns a value greater than, equal to, or less than +zero, corresponding to the result of the <tt/strcoll/ function applied to the +same two original strings. No more than n characters are placed into the +resulting array pointed to by s1, including the terminating null character. +<tag/Limits/<itemize> +<item><tt/s1/ and <tt/s2/ must not point to the same memory area, otherwise +the behaviour is undefined. +<item>If <tt/n/ is zero, <tt/s1/ may be a NULL pointer. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>Since cc65 doesn't support different charcter sets, <tt/strxfrm/ will +just copy s2 to s1 using <tt><ref id="strncpy" name="strncpy"></tt>. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="strcmp" name="strcmp">, +<ref id="strcoll" name="strcoll">, +<ref id="strncpy" name="strncpy"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strupper<label id="strupper"><p> + +<quote> +<descrip> +<tag/Function/Make a string upper case. +<tag/Header/<tt/<ref id="string.h" name="string.h">/ +<tag/Declaration/<tt/char* __fastcall__ strupper (char* s);/ +<tag/Description/The <tt/strupper/ function will apply the <tt/toupper/ +function to each character of a string. The function will always return <tt/s/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>The function prototype is unavailable when compiling in strict ANSI mode. +<item>An alias name for this function is <tt/strupr/. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="strlower" name="strlower"> +<ref id="toupper" name="toupper"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>strupr<label id="strupr"><p> + +<quote> +See <tt/strupper/. +</quote> + + +<sect1>telldir<label id="telldir"><p> + +<quote> +<descrip> +<tag/Function/Return the current position of a directory stream. +<tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ +<tag/Declaration/<tt/long __fastcall__ telldir (DIR* dir);/ +<tag/Description/<tt/telldir/ returns the current position of a directory +stream. The return value may be used in subsequent calls to +<tt/<ref id="seekdir" name="seekdir">/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/See also/ +<ref id="seekdir" name="seekdir">, +<ref id="telldir" name="telldir"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>textcolor<label id="textcolor"><p> + +<quote> +<descrip> +<tag/Function/Set the text color. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ textcolor (unsigned char color);/ +<tag/Description/The function will set a new text color. It returns the old +(current) text color. Text output using any <tt/conio.h/ function will use +the color set by this function. +<tag/Limits/<itemize> +<item>Text colors are system dependent. The function may have no effect +on systems where the text color cannot be changed. +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="bgcolor" name="bgcolor">, +<ref id="bordercolor" name="bordercolor"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_arc<label id="tgi_arc"><p> + +<quote> +<descrip> +<tag/Function/Draw an elliptic arc in the current color. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_arc (int x, int y, +unsigned char rx, unsigned char ry, unsigned sa, unsigned ea);/ +<tag/Description/The function draws an elliptic arc with center at x/y and +radii rx/ry using the current drawing color. The arc covers the angle +between sa and ea (startangle and endangle), which must be in the range +0..360. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>The function behaves unexpectedly or may crash if the angles are out +of range. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_bar" name="tgi_bar">, +<ref id="tgi_circle" name="tgi_circle">, +<ref id="tgi_ellipse" name="tgi_ellipse">, +<ref id="tgi_pieslice" name="tgi_pieslice">, +<ref id="tgi_setcolor" name="tgi_setcolor"> +<tag/Example/<verb> +/* Draw the upper half of an ellipse */ +tgi_setcolor(TGI_COLOR_BLUE); +tgi_arc (50, 50, 40, 20, 0, 180); +</verb> +</descrip> +</quote> + + +<sect1>tgi_bar<label id="tgi_bar"><p> + +<quote> +<descrip> +<tag/Function/The function fills a rectangle on the drawpage with the current +color. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_bar (int x1, int y1, int x2, int y2);/ +<tag/Description/The function fills a rectangle on the drawpage with the current +color. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi function +<tag/Example/<verb> +tgi_setcolor(TGI_COLOR_GREEN); +tgi_bar(10, 10, 100, 60); +</verb> +</descrip> +</quote> + + +<sect1>tgi_circle<label id="tgi_circle"><p> + +<quote> +<descrip> +<tag/Function/The function draws a circle in the current color. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_circle (int x, int y, unsigned char radius);/ +<tag/Description/The function draws a circle in the current color. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_arc" name="tgi_arc">, +<ref id="tgi_bar" name="tgi_bar">, +<ref id="tgi_ellipse" name="tgi_ellipse">, +<ref id="tgi_pieslice" name="tgi_pieslice">, +<ref id="tgi_setcolor" name="tgi_setcolor"> +<tag/Example/<verb> +tgi_setcolor(TGI_COLOR_BLACK); +tgi_circle(50, 40, 40); +</verb> +</descrip> +</quote> + + +<sect1>tgi_clear<label id="tgi_clear"><p> + +<quote> +<descrip> +<tag/Function/Clear the drawpage +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void tgi_clear (void);/ +<tag/Description/Clear the drawpage +<tag/Availability/cc65 +<tag/See also/Other tgi functions +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_done<label id="tgi_done"><p> + +<quote> +<descrip> +<tag/Function/End graphics mode, switch back to text mode. +Will NOT uninstall or unload the driver! +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void tgi_done (void);/ +<tag/Description/End graphics mode, switch back to text mode. +Will NOT uninstall or unload the driver! +<tag/Availability/cc65 +<tag/See also/Other tgi functions +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_ellipse<label id="tgi_ellipse"><p> + +<quote> +<descrip> +<tag/Function/The function draws an ellipse in the current color. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_ellipse (int x, int y, unsigned char rx, unsigned char ry);/ +<tag/Description/The function draws an ellipse at position x/y with radii +rx and ry, using the current drawing color. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_arc" name="tgi_arc">, +<ref id="tgi_bar" name="tgi_bar">, +<ref id="tgi_circle" name="tgi_circle">, +<ref id="tgi_pieslice" name="tgi_pieslice">, +<ref id="tgi_setcolor" name="tgi_setcolor"> +<tag/Example/<verb> +tgi_setcolor(TGI_COLOR_RED); +tgi_ellipse (50, 40, 40, 20); +</verb> +</descrip> +</quote> + + +<sect1>tgi_free_vectorfont<label id="tgi_free_vectorfont"><p> + +<quote> +<descrip> +<tag/Function/Free a vector font that was previously loaded into memory. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_free_vectorfont (const tgi_vectorfont* font);/ +<tag/Description/Free a vector font that was previously loaded into memory. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_load_vectorfont" name="tgi_load_vectorfont">, +<ref id="tgi_install_vectorfont" name="tgi_install_vectorfont"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_getaspectratio<label id="tgi_getaspectratio"><p> + +<quote> <descrip> <tag/Function/Return the pixel aspect ratio. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned tgi_getaspectratio (void);/ +<tag/Description/The function returns the pixel aspect ratio for the current +driver and display as an 8.8 fixed point value. It may be used to correct +geometric shapes so they look correct on the display. As an example, a circle +with a radius of 100 pixels may look elliptic on some driver/display +combinations if the aspect ratio is not 1.00. +<tag/Limits/<itemize> +<item>The aspect ratio is encoded in the TGI driver which assumes a "standard" +monitor for the given platform. The aspect ratio may be wrong if another +monitor is used. +<item>No TGI function will use the aspect ratio. It is up to the programmer to +make use of it. +<item>The <ref id="tgi_setaspectratio" name="tgi_setaspectratio"> function can +be used to change the aspect ratio for a loaded driver. The value is not reset +by <ref id="tgi_init" name="tgi_init">, so if a driver is linked statically to +an application, switching into and out of graphics mode will not restore the +original aspect ratio. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_setaspectratio" name="tgi_setaspectratio"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_getcolor<label id="tgi_getcolor"><p> + +<quote> +<descrip> +<tag/Function/Return the current drawing color. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned char tgi_getcolor (void);/ +<tag/Description/The actual color is an index to a palette. During tgi_init +you will get a default palette. The number of colors depend on the platform. +All platforms recognize at least TGI_COLOR_BLACK and TGI_COLOR_WHITE. But some +platforms have many more predefined colors. If you paint using TGI_COLOR_GREEN +and then you change the green of the palette to blue using tgi_setpalette then +after this painting in TGI_COLOR_GREEN will actually be blue. +<tag/Availability/cc65 +<tag/See also/Other tgi functions +<tag/Example/<verb> +color = tgi_getcolor(); +</verb> +</descrip> +</quote> + + +<sect1>tgi_getcolorcount<label id="tgi_getcolorcount"><p> + +<quote> +<descrip> +<tag/Function/Get the number of available colors. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned char tgi_getcolorcount (void);/ +<tag/Description/Tgi platforms use indexed color palettes. This function +returns the number of entries we can use in the palette. +<tag/Availability/cc65 +<tag/See also/Other tgi functions +<tag/Example/<verb> +if (tgi_getcolorcount() == 2) { + printf("Only monochrome graphics is supported\n"); +} +</verb> +</descrip> +</quote> + + +<sect1>tgi_getdefpalette<label id="tgi_getdefpalette"><p> + +<quote> +<descrip> +<tag/Function/Get the palette installed by default. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/const unsigned char* tgi_getdefpalette (void);/ +<tag/Description/The tgi driver has a default palette that is active at startup. +The named colors TGI_COLOR_BLACK, TGI_COLOR_WHITE, TGI_COLOR_RED... need this +palette to work correctly. +<tag/Availability/cc65 +<tag/See also/Other tgi functions +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_geterror<label id="tgi_geterror"><p> + +<quote> +<descrip> +<tag/Function/Return the error code for the last operation. +This will also clear the error. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned char tgi_geterror (void);/ +<tag/Description/Return the error code for the last operation. +This will also clear the error. +<tag/Availability/cc65 +<tag/See also/Other tgi functions +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_geterrormsg<label id="tgi_geterrormsg"><p> + +<quote> +<descrip> +<tag/Function/Get an error message describing the error. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/const char* __fastcall__ tgi_geterrormsg (unsigned char code);/ +<tag/Description/Get an error message describing the error. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_getmaxcolor<label id="tgi_getmaxcolor"><p> + +<quote> +<descrip> +<tag/Function/Get the highest index of the palette. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned char tgi_getmaxcolor (void);/ +<tag/Description/Get the highest index of the palette. +<tag/Availability/cc65 +<tag/See also/Other tgi functions +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_getmaxx<label id="tgi_getmaxx"><p> + +<quote> +<descrip> +<tag/Function/Get the maximum x coordinate that can be used on this screen. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned tgi_getmaxx (void);/ +<tag/Description/Get the maximum x coordinate that can be used on this screen. +<tag/Availability/cc65 +<tag/See also/Other tgi functions +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_getmaxy<label id="tgi_getmaxy"><p> + +<quote> +<descrip> +<tag/Function/Get the maximum y coordinate that can be used on this screen. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned tgi_getmaxy (void);/ +<tag/Description/Get the maximum y coordinate that can be used on this screen. +<tag/Availability/cc65 +<tag/See also/Other tgi functions +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_getpagecount<label id="tgi_getpagecount"><p> + +<quote> +<descrip> +<tag/Function/Return the number of screen pages available. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned tgi_getpagecount (void);/ +<tag/Description/Return the number of screen pages available. +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_setdrawpage" name="tgi_setdrawpage">, +<ref id="tgi_setviewpage" name="tgi_setviewpage"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_getpalette<label id="tgi_getpalette"><p> + +<quote> +<descrip> +<tag/Function/Get the palette installed. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/const unsigned char* tgi_getpalette (void);/ +<tag/Description/Get the palette installed. +<tag/Availability/cc65 +<tag/See also/Other tgi functions +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_getpixel<label id="tgi_getpixel"><p> + +<quote> +<descrip> +<tag/Function/Get the color of a pixel from the viewpage. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ tgi_getpixel (int x, int y);/ +<tag/Description/Get the color of a pixel from the viewpage. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_getxres<label id="tgi_getxres"><p> + +<quote> +<descrip> +<tag/Function/Get number of horisontal pixels on the screen. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned tgi_getxres (void);/ +<tag/Description/Get number of horisontal pixels on the screen. +This is same as tgi_maxx()+1. +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_getyres<label id="tgi_getyres"><p> + +<quote> +<descrip> +<tag/Function/Get number of vertical pixels on the screen. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned tgi_getyres (void);/ +<tag/Description/Get number of vertical pixels on the screen. +This is same as tgi_maxy()+1. +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_gotoxy<label id="tgi_gotoxy"><p> + +<quote> +<descrip> +<tag/Function/Set graphics cursor at x, y. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_gotoxy (int x, int y);/ +<tag/Description/Set graphics cursor at x, y. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_init<label id="tgi_init"><p> + +<quote> +<descrip> +<tag/Function/Initialize the already loaded graphics driver. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void tgi_init (void);/ +<tag/Description/The tgi_init function will set the default palette to the +hardware. +<tag/Limits/<itemize> +<item><tt/tgi_init/ will not clear the screen. This allows switching between +text and graphics mode on platforms that have separate memory areas for the +screens. If you want the screen cleared, call <tt/<ref id="tgi_clear" +name="tgi_clear">/ after <tt/tgi_init/. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/<verb> +tgi_install(tgi_static_stddrv); //Include the driver statically instead of loading it. +tgi_init(); //Set up the default palette and clear the screen. +</verb> +</descrip> +</quote> + + +<sect1>tgi_install<label id="tgi_install"><p> + +<quote> +<descrip> +<tag/Function/Install an already loaded driver and return an error code. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned char __fastcall__ tgi_install (void* driver);/ +<tag/Description/The function installs a driver that was already loaded into +memory (or linked statically to the program). It returns an error code +(<tt/TGI_ERR_OK/ in case of success). +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_load_driver" name="tgi_load_driver">, +<ref id="tgi_uninstall" name="tgi_uninstall">, +<ref id="tgi_unload" name="tgi_unload"> +<tag/Example/<verb> +tgi_install(tgi_static_stddrv); //Include the driver statically instead of loading it. +tgi_init(); //Set up the default palette and clear the screen. +</verb> +</descrip> +</quote> + + +<sect1>tgi_install_vectorfont<label id="tgi_install_vectorfont"><p> + +<quote> +<descrip> +<tag/Function/Install an already loaded driver and return an error code. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_install_vectorfont (const tgi_vectorfont* font);/ +<tag/Description/ +Install a vector font for use. More than one vector font can be loaded, +but only one can be active. This function is used to tell which one. Call +with a NULL pointer to uninstall the currently installed font. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_load_vectorfont" name="tgi_load_vectorfont">, +<ref id="tgi_free_vectorfont" name="tgi_free_vectorfont"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_ioctl<label id="tgi_ioctl"><p> + +<quote> +<descrip> +<tag/Function/Platform dependent code extensions. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned __fastcall__ tgi_ioctl (unsigned char code, void* data);/ +<tag/Description/Some platforms have extra display hardware that is not +supported by standard tgi functions. You can extend the driver to support +this extra hardware using tgi_ioctl functions. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>These functions are not easily portable to other cc65 platforms. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/<verb> +#define tgi_sprite(spr) tgi_ioctl(0, (void*)(spr)) +#define tgi_flip() tgi_ioctl(1, (void*)0) +#define tgi_setbgcolor(bgcol) tgi_ioctl(2, (void*)(bgcol)) +#define tgi_setframerate(rate) tgi_ioctl(3, (void*)(rate)) +#define tgi_busy() tgi_ioctl(4, (void*)0) +#define tgi_updatedisplay() tgi_ioctl(4, (void*)1) +if (!tgi_busy()) { + tgi_sprite(&background); + tgi_setcolor(TGI_COLOR_BLUE); + tgi_outttextxy(20,40,"Hello World"); + tgi_updatedisplay(); +} +</verb> +</descrip> +</quote> + + +<sect1>tgi_line<label id="tgi_line"><p> + +<quote> +<descrip> +<tag/Function/Draw a line in the current drawing color. +The graphics cursor will be set to x2/y2 by this call. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_line (int x1, int y1, int x2, int y2);/ +<tag/Description/Draw a line in the current drawing color. +The graphics cursor will be set to x2/y2 by this call. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_lineto<label id="tgi_lineto"><p> + +<quote> +<descrip> +<tag/Function/Draw a line in the current drawing color from the graphics +cursor to the new end point. The graphics cursor will be updated to x2/y2. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_lineto (int x2, int y2);/ +<tag/Description/Draw a line in the current drawing color from the graphics +cursor to the new end point. The graphics cursor will be updated to x2/y2. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_load_driver<label id="tgi_load_driver"><p> + +<quote> +<descrip> +<tag/Function/Load and install the given driver. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_load_driver (const char *name);/ +<tag/Description/Load and install the driver by name. +Will just load the driver and check if loading was successful. +Will not switch to graphics mode. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_load_vectorfont<label id="tgi_load_vectorfont"><p> + +<quote> +<descrip> +<tag/Function/Load the given vector font. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/const tgi_vectorfont* __fastcall__ tgi_load_vectorfont (const char* name);/ +<tag/Description/ +Load a vector font into memory and return it. In case of errors, NULL is +returned and an error is set, which can be retrieved using tgi_geterror. +To use the font, it has to be installed using tgi_install_vectorfont. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_install_vectorfont" name="tgi_install_vectorfont">, +<ref id="tgi_free_vectorfont" name="tgi_free_vectorfont"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_outtext<label id="tgi_outtext"><p> + +<quote> +<descrip> +<tag/Function/Output text at the current graphics cursor position. +The graphics cursor is moved to the end of the text. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_outtext (const char* s);/ +<tag/Description/Output text at the current graphics cursor position. +The graphics cursor is moved to the end of the text. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_outtextxy<label id="tgi_outtextxy"><p> + +<quote> +<descrip> +<tag/Function/Output text at the given cursor position. +The graphics cursor is moved to the end of the text. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_outtextxy (int x, int y, const char* s);/ +<tag/Description/Output text at the given cursor position. +The graphics cursor is moved to the end of the text. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_pieslice<label id="tgi_pieslice"><p> + +<quote> +<descrip> +<tag/Function/Draw an elliptic pie slice in the current color. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_pie slice (int x, int y, +unsigned char rx, unsigned char ry, unsigned sa, unsigned ea);/ +<tag/Description/The function draws an elliptic pie slice with center at x/y +and radii rx/ry using the current drawing color. The pie slice covers the angle +between sa and ea (startangle and endangle), which must be in the range +0..360. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>The function behaves unexpectedly or may crash if the angles are out +of range. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_bar" name="tgi_arc">, +<ref id="tgi_bar" name="tgi_bar">, +<ref id="tgi_circle" name="tgi_circle">, +<ref id="tgi_ellipse" name="tgi_ellipse">, +<ref id="tgi_setcolor" name="tgi_setcolor"> +<tag/Example/<verb> +/* Draw the closed upper half of an ellipse */ +tgi_setcolor(TGI_COLOR_BLUE); +tgi_pieslice (50, 50, 40, 20, 0, 180); +</verb> +</descrip> +</quote> + + +<sect1>tgi_setaspectratio<label id="tgi_setaspectratio"><p> + +<quote> <descrip> <tag/Function/Set the pixel aspect ratio. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_setaspectratio (unsigned ratio);/ +<tag/Description/The function sets the pixel aspect ratio for the current +driver and display. The argument is an 8.8 fixed point value. The aspect ratio +may be used to correct geometric shapes so they look correct on a given +display. As an example, a circle with a radius of 100 pixels may look elliptic +on some driver/display combinations if the aspect ratio is not 1.00. +<tag/Limits/<itemize> +<item>The aspect ratio is encoded in the TGI driver which assumes a "standard" +monitor for the given platform. The aspect ratio may be wrong if another +monitor is used. +<item>No TGI function will use the aspect ratio. It is up to the programmer to +make use of it. +<item>The <tt/tgi_setaspectratio/ function can be used to change the aspect +ratio for a loaded driver. The value is not reset by <ref id="tgi_init" +name="tgi_init">, so if a driver is linked statically to an application, +switching into and out of graphics mode will not restore the original aspect +ratio. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_getaspectratio" name="tgi_getaspectratio"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tgi_setcolor<label id="tgi_setcolor"><p> + +<quote> +<descrip> +<tag/Function/Set color to be used in future draw operations. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_setcolor (unsigned char color);/ +<tag/Description/Set color to be used in future draw operations. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/<verb> +tgi_setcolor(TGI_COLOR_BLACK); +tgi_bar(0,0,30,30); +tgi_setcolor(TGI_COLOR_WHITE); +tgi_bar(10,10,20,20); +</verb> +</descrip> +</quote> + +<sect1>tgi_setdrawpage<label id="tgi_setdrawpage"><p> + +<quote> +<descrip> +<tag/Function/Set the page for drawing. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_setdrawpage (unsigned char page);/ +<tag/Description/If the drawpage and the viewpage are the same then all drawing +is seen immediately as it is drawn. For double buffered games you can set the +drawpage to a different page than the viewpage. This lets you draw the next +screen in the background and when the screen is ready you display it. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/<verb> +tgi_setdrawpage(1); +tgi_outtextxy(10, 10, "Hello World"); +tgi_setviewpage(1); // Show page 1 +tgi_setdrawpage(0); +tgi_outtextxy(10, 10, "Creating next frame"); +... +tgi_setviewpage(0); // Show page 0 +</verb> +</descrip> +</quote> + +<sect1>tgi_setpalette<label id="tgi_setpalette"><p> + +<quote> +<descrip> +<tag/Function/Set the palette (not available with all drivers/hardware). +Palette is a pointer to as many entries as there are colors. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_setpalette (const unsigned char* palette);/ +<tag/Description/Set the palette (not available with all drivers/hardware). +Palette is a pointer to as many entries as there are colors. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + +<sect1>tgi_setpixel<label id="tgi_setpixel"><p> + +<quote> +<descrip> +<tag/Function/Plot a pixel on the drawpage with the current color. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_setpixel (int x, int y);/ +<tag/Description/Plot a pixel on the drawpage with the current color. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + +<sect1>tgi_setviewpage<label id="tgi_setviewpage"><p> + +<quote> +<descrip> +<tag/Function/Set page to be visible on screen. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_setviewpage (unsigned char page);/ +<tag/Description/If the drawpage and the viewpage are the same then all drawing +is seen immediately as it is drawn. For double buffered games you can set the +drawpage to a different page than the viewpage. This lets you draw the next +screen in the background and when the screen is ready you display it. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/<verb> +tgi_setdrawpage(1); +tgi_outtextxy(10, 10, "Hello World"); +tgi_setviewpage(1); // Show page 1 +tgi_setdrawpage(0); +tgi_outtextxy(10, 10, "Creating next frame"); +... +tgi_setviewpage(0); // Show page 0 +</verb> +</descrip> +</quote> + +<sect1>tgi_gettextheight<label id="tgi_gettextheight"><p> + +<quote> +<descrip> +<tag/Function/Calculate the height of the text in pixels according to +the current text style. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned __fastcall__ tgi_gettextheight (const char* s);/ +<tag/Description/Calculate the height of the text in pixels according to +the current text style. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + +<sect1>tgi_settextscale<label id="tgi_settextscale"><p> + +<quote> +<descrip> +<tag/Function/Set the scaling for text output. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_settextscale (unsigned width, unsigned height);/ +<tag/Description/ +Set the scaling for text output. The scaling factors for width and height +are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_settextstyle" name="tgi_settextstyle"> +<tag/Example/None. +</descrip> +</quote> + +<sect1>tgi_settextstyle<label id="tgi_settextstyle"><p> + +<quote> +<descrip> +<tag/Function/Set the style for text output. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void __fastcall__ tgi_settextstyle (unsigned char magx, unsigned char magy, unsigned char dir, unsigned char font);/ +<tag/Description/Set the style for text output. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="tgi_settextscale" name="tgi_settextscale"> +<tag/Example/None. +</descrip> +</quote> + +<sect1>tgi_gettextwidth<label id="tgi_gettextwidth"><p> + +<quote> +<descrip> +<tag/Function/Calculate the width of the text in pixels according to the current text style. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/unsigned __fastcall__ tgi_gettextwidth (const char* s);/ +<tag/Description/Calculate the width of the text in pixels according to the current text style. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + +<sect1>tgi_uninstall<label id="tgi_uninstall"><p> + +<quote> +<descrip> +<tag/Function/Uninstall the currently loaded driver but do not unload it. +Will call tgi_done if necessary. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void tgi_uninstall (void);/ +<tag/Description/Uninstall the currently loaded driver but do not unload it. +Will call tgi_done if necessary. +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + +<sect1>tgi_unload<label id="tgi_unload"><p> + +<quote> +<descrip> +<tag/Function/Uninstall, then unload the currently loaded driver. +Will call tgi_done if necessary. +<tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ +<tag/Declaration/<tt/void tgi_unload (void);/ +<tag/Description/Uninstall, then unload the currently loaded driver. +Will call tgi_done if necessary. +<tag/Availability/cc65 +<tag/See also/Other tgi functions. +<tag/Example/None. +</descrip> +</quote> + +<sect1>time<label id="time"><p> + +<quote> +<descrip> +<tag/Function/Get the time. +<tag/Header/<tt/<ref id="time.h" name="time.h">/ +<tag/Declaration/<tt/time_t __fastcall__ time (time_t* t);/ +<tag/Description/The function returns the time since the 1970-01-01 00:00:00 +measured in seconds. If the pointer <tt/t/ is not <tt/NULL/, the function +result will also be stored there. If no time is available, <tt/(time_t)-1/ is +returned and <tt/errno/ is set to <tt/ENOSYS/. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +<item>Many platforms supported by cc65 do not have a realtime clock, so the +returned value may not be valid. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="clock" name="clock"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>toggle_videomode<label id="toggle_videomode"><p> + +<quote> +<descrip> +<tag/Function/Toggle between 40 and 80 column mode. +<tag/Header/<tt/<ref id="c128.h" name="c128.h">/ +<tag/Declaration/<tt/void toggle_videomode (void);/ +<tag/Description/Toggle between 40 and 80 column mode. The settings for the +old mode (cursor position, color and so on) are saved and restored together +with the mode. +<tag/Limits/<itemize> +<item>The function is specific to the C128. +<item>This function is deprecated. Please use <ref id="videomode" +name="videomode"> instead! +</itemize> +<tag/Availability/C128 +<tag/See also/ +<ref id="fast" name="fast">, +<ref id="slow" name="slow">, +<ref id="videomode" name="videomode"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>tolower<label id="tolower"><p> + +<quote> +<descrip> +<tag/Function/Convert a character into its lower case representation. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ tolower (int c);/ +<tag/Description/The function returns the given character converted to lower +case. If the given character is not a letter, it is returned unchanged. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="islower" name="islower">, +<ref id="isupper" name="isupper">, +<ref id="toupper" name="toupper"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>toupper<label id="toupper"><p> + +<quote> +<descrip> +<tag/Function/Convert a character into its upper case representation. +<tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ +<tag/Declaration/<tt/int __fastcall__ toupper (int c);/ +<tag/Description/The function returns the given character converted to upper +case. If the given character is not a letter, it is returned unchanged. +<tag/Limits/<itemize> +<item>The function is only available as fastcall function, so it may +only be used in presence of a prototype. +</itemize> +<tag/Availability/ISO 9899 +<tag/See also/ +<ref id="islower" name="islower">, +<ref id="isupper" name="isupper">, +<ref id="tolower" name="tolower"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>ultoa<label id="ultoa"><p> + +<quote> +<descrip> +<tag/Function/Convert an unsigned long integer into a string. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/char* __fastcall__ ultoa (unsigned long val, char* buf, int radix);/ +<tag/Description/<tt/itoa/ converts the unsigned long integer <tt/val/ into a +string using <tt/radix/ as the base. +<tag/Limits/<itemize> +<item>There are no provisions to prevent a buffer overflow. +<item>The function is non standard, so it is not available in strict ANSI mode. +You should probably use <tt/sprintf/ instead. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="atoi" name="atoi">, +<ref id="atol" name="atol">, +<ref id="itoa" name="itoa">, +<ref id="ltoa" name="ltoa">, +<ref id="utoa" name="utoa"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>unlink<label id="unlink"><p> + +<quote> +<descrip> +<tag/Function/Delete a file. +<tag/Header/<tt/<ref id="unistd.h" name="unistd.h">/ +<tag/Declaration/<tt/int __fastcall__ unlink (const char* name);/ +<tag/Description/<tt/unlink/ deletes the file with the given name. On success, +zero is returned. On error, -1 is returned and <tt/errno/ is set to an error +code describing the reason for the failure. +<tag/Limits/ +<itemize> +<item>The use of this function is discouraged. Please use <tt/<ref id="remove" +name="remove">/ instead, which is a native ANSI C function and does the same. +<item>This function is not available on all cc65 targets (depends on the +availability of file I/O). +<item>The function is only available as fastcall function, so it may only +be used in presence of a prototype. +<item>Instead of <tt/unlink/, <tt/<ref id="remove" name="remove">/ should be +used, which has the same semantics, but is more portable, because it conforms +to the ISO C standard. +</itemize> +<tag/Availability/POSIX 1003.1 +<tag/See also/ +<ref id="remove" name="remove"> +<tag/Example/ +<verb> +#include <stdio.h> +#include <unistd.h> + +#define FILENAME "helloworld" + +if (unlink (FILENAME) == 0) { + printf ("We deleted %s successfully\n", FILENAME); +} else { + printf ("There was a problem deleting %s\n", FILENAME); +} +</verb> +</descrip> +</quote> + + +<sect1>utoa<label id="utoa"><p> + +<quote> +<descrip> +<tag/Function/Convert an unsigned integer into a string. +<tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ +<tag/Declaration/<tt/char* __fastcall__ utoa (unsigned val, char* buf, int radix);/ +<tag/Description/<tt/itoa/ converts the unsigned integer <tt/val/ into a string +using <tt/radix/ as the base. +<tag/Limits/<itemize> +<item>There are no provisions to prevent a buffer overflow. +<item>The function is non standard, so it is not available in strict ANSI mode. +You should probably use <tt/sprintf/ instead. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="atoi" name="atoi">, +<ref id="atol" name="atol">, +<ref id="itoa" name="itoa">, +<ref id="ltoa" name="ltoa">, +<ref id="ultoa" name="ultoa"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>vcprintf<label id="vcprintf"><p> + +<quote> +<descrip> +<tag/Function/Formatted output to the console. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/int __fastcall__ vcprintf (const char* format, va_list ap);/ +<tag/Description/The arguments specified as a <tt/va_list/ are converted to +text where necessary and formatted according to the format string given. The +resulting string is output to the console. <tt/vcprintf/ supports the same +format specifiers as <tt/vprintf/. <!-- <tt/<ref id="vprintf" name="vprintf">/. --> +<tag/Limits/<itemize> +<item>Like all other <tt/conio/ output functions, <tt/vcprintf/ distinguishes +between <tt/\r/ and <tt/\n/. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cprintf" name="cprintf">, +<ref id="cputc" name="cputc">, +<ref id="cputcxy" name="cputcxy">, +<ref id="cputs" name="cputs">, +<ref id="cputsxy" name="cputsxy"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>videomode<label id="videomode"><p> + +<quote> +<descrip> +<tag/Function/Switch to either 40 or 80 column mode. +<tag/Header/<tt/<ref id="apple2enh.h" name="apple2enh.h">, +<ref id="c128.h" name="c128.h">/ +<tag/Declaration/<tt/unsigned __fastcall__ videomode (unsigned Mode);/ +<tag/Description/Switch to 40 or 80 column mode depending on the argument. If +the requested mode is already active, nothing happens. The old mode is returned +from the call. +<tag/Limits/<itemize> +<item>The function is specific to the C128 and enhanced Apple //e. +<item>This function replaces <ref id="toggle_videomode" +name="toggle_videomode">. +<item>The function is only available as fastcall function, so it may only be +used in presence of a prototype. +</itemize> +<tag/Availability/C128 and enhanced Apple //e +<tag/See also/ +<ref id="fast" name="fast">, +<ref id="slow" name="slow">, +<ref id="toggle_videomode" name="toggle_videomode"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>wherex<label id="wherex"><p> + +<quote> +<descrip> +<tag/Function/Return the current X position of the text mode cursor. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/unsigned char wherex (void);/ +<tag/Description/The function returns the current X position of the text mode +cursor. Zero is returned for the leftmost screen position. +<tag/Availability/cc65 +<tag/See also/ +<ref id="gotox" name="gotox">, +<ref id="gotoy" name="gotoy">, +<ref id="gotoxy" name="gotoxy">, +<ref id="wherey" name="wherey"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>wherey<label id="wherey"><p> + +<quote> +<descrip> +<tag/Function/Return the current Y position of the text mode cursor. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/unsigned char wherey (void);/ +<tag/Description/The function returns the current Y position of the text mode +cursor. Zero is returned for the uppermost screen position. +<tag/Availability/cc65 +<tag/See also/ +<ref id="gotox" name="gotox">, +<ref id="gotoy" name="gotoy">, +<ref id="gotoxy" name="gotoxy">, +<ref id="wherex" name="wherex"> +<tag/Example/None. +</descrip> +</quote> + + +</article> diff --git a/doc/geos.sgml b/doc/geos.sgml new file mode 100644 index 000000000..aa3725bdf --- /dev/null +++ b/doc/geos.sgml @@ -0,0 +1,1659 @@ +<!doctype linuxdoc system> + +<article> + +<!-- Title information --> + +<title>GEOSLib docs +<author><url url="mailto:ytm@elysium.pl" name="Maciej Witkowiak"> +<date>2014-04-11 +<abstract> +This is the documentation of cc65's GEOSLib, but information contained here may be also +useful for writing GEOS applications in general. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Introduction +<p> +As we all know that the best computers in the world are the C64 and C128. They have their GUI too - +the excellent GEOS. GEOS seems very difficult and cryptic for many people, from programmer's point +of view. That's not true. The designers of GEOS created a flexible and powerful system, which +is easy to use and program. +<p> +Coding GEOS in C? That's something new. It is possible now - with Ulrich von Bassewitz's cc65 +package and my GEOSLib you are able to create GEOS applications in no time. +<p> +GEOSLib supports a subset of the standard cc65 libraries. Whenever possible native Kernal functions +are used (e.g. <tt/memset/ is an alias for <tt/FillRam/), however not all are supported. E.g. +string functions like <tt/strcmp/, <tt/strcpy/ are doubled with native <tt/CmpString/, +<tt/CopyString/ because the latter can handle only 256 byte strings. Keep this in mind when +you write your program. If you don't need long strings simply use functions from the Kernal, +the resulting code will be smaller. +<p> +<tt/dio/ - direct disk access is available, but you might have problems with devices other +than 1541, 1571 or 1581. RAM drives emulating these should work. +<p> +<tt/conio/ - simple console input-output is available for command line applications. +This implementation assumes that one character does fit in 8x8 cell, so output with +default BSW font, which is has 9 points, might be a bit messy. There is no color support in +GEOS 2.0 so color functions are disabled. Both 40 and 80 column modes are supported +and automatically detected. +<p> +<tt/tgi/ - TGI driver for GEOS that supports both 40 and 80 column modes but mode can not be +changed between <tt/tgi_init/ and <tt/tgi_done/. +<p> +<tt/joy/ - JOY driver for GEOS that supports only joystick, not current pointing device. +<p> +It is safe to use these standard includes and their contents: +<tt/assert.h, conio.h, dio.h, errno.h, em.h, geos.h, joystick.h, modload.h, mouse.h, stdlib.h, string.h, tgi.h, time.h/ +<p> +For <tt/time.h/ functions <tt/systime()/ and <tt/clock()/ note that the resolution is one second. +<p> +Functions from the headers above are either standard C library functions or cc65-specific, in +either case they are not GEOS specific and so they are not described here. +<p> +I am an assembler programmer and GEOSLib was designed in such way that cc65 could emit the best +available code (well, the best as for machine :-). Many of the <tt/void foo (void)/ functions are +just raw calls to the Kernal (assembled just as <tt/jsr _foo/), look in <tt/gsym.h/, where you +can find many definitions of standard GEOS locations. Access to these addresses is optimized by +cc65 to simple <tt/lda/ and <tt/sta/. Don't be afraid to use C syntax. + +<sect1>Requirements +<p> +You don't need a C64 or C128 for development. The only hardware requirement is a PC capable of +running cc65. You do however need C64 or C128 emulator and GEOS disk images (.d64) to test your +programs. + +The software needed: +<itemize> + <item><em/cc65/ Excellent package containing a C crosscompiler, a crossassembler and a linker, you + can get it from: <url url="http://cc65.github.io/cc65/">. + <item><em/VICE/ This is a portable C64, C128 and few other Commodore computers emulator, you + can obtain it from: <url url="http://vice-emu.sourceforge.net/">. + The VICE package contains the <em/c1541/ program that is able + to convert/unconvert GEOS files to disk images. + <item><em/The Star Commander/ This tool is only for DOS. You will need it for transferring + object files from a PC to a 1541. There's also one important ability of this + tool - it automatically un-converts .cvt files into GEOS native format on + disk image files. Check out: <url url="http://sta.c64.org/sc.html">. + <item><em/opencbm/ A package that allows for communication directly with a 1541 and + other Commodore IEC bus drives. It can be a replacement for Star Commander if + you only want to transfer files to a disk and unconvert using GEOS program for + this purpose. Check out: <url url="http://opencbm.sourceforge.net/">. +</itemize> +<p> +VICE and cc65 are portable - they run on variety of platforms - DOS, Win32 and UNIX. GEOSLib only +needs cc65. +<p> +<em/Update:/ starting from v2.5.0 GEOSLib is a part of the cc65 package as its GEOS support library. + +<sect1>Legal +<p> +I want to thank Uz for his cc65 package, Alexander Boyce for his excellent GEOS Programmer's +Reference Guide and BSW for GEOS. +<p> +GEOSLib is covered by the same license as cc65. You can find the whole text +among documentation. I would really appreciate if you would like to send me +your comments, suggestions, questions, changes, bug reports etc. I will also +appreciate if you will just give me a sign that you are using GEOSLib - not +especially something big and important, mail me even if you are just playing +with it. +<p> +You can send postcards with hellos to: +<p> +Maciej Witkowiak, ul. Slowackiego 6/57, 77-400 ZLOTOW +<p> +POLAND +<p> +e-mail: <tt/ytm@elysium.pl/ + +<sect>What do you have and what to do with it? +<p> +This chapter describes some rules you ought to obey, and how to use GEOSLib. + +<sect1>Usage +<p> +Apart from this file, which merely describes only standard GEOS library +functions, you should read the <tt/grc65/ (GEOS resource compiler) documentation. +There is information about necessary resource files (each GEOS application +needs at least one) and the build process - what should be done and in what +order. Please also read the cc65 documentation on how to compile C, assembler +and link everything together. +<p> +All in all, you just need to place +<tscreen><verb> +#include <geos.h> +</verb></tscreen> +at the top of your source. +<p> +As a general rule read the sources of the example programs and read the headers. +These are the most reliable sources of knowledge ;-). You will also find there +many C macros representing various arguments passed to the functions. Please use +them. You will find your sources easier to understand, and it will be easier +to find bugs. +<p> +All types used in GEOSLib are <tt/unsigned/. +<p> +Screen coordinates are given in pixels unless stated differently. + +<sect1>Notes on style +<p> +Contrary to a typical GEOS assembly program which has a main function called after loading that +setups the screen, menus, icons etc. exiting from the <tt/main/ function in C is equivalent to +calling <tt/exit()/. These two are the only safe methods of terminating applications. DO NOT +USE <tt/EnterDeskTop/! Your data may be lost as library destructors and functions registered +with <tt/atexit/ are not called. +<p> +For GEOS GUI applications the recommended program structure is to have everything initialized +in the <tt/main/ function and at the end of it a call to the <tt/MainLoop()/ function. WARNING! This +function never returns, any code between <tt/MainLoop();/ and the end of <tt/main/ will not +be executed. You have to call <tt/exit()/ explicitly somewhere in your code (e.g. in a menu +handler or via DialogBox action). +<p> +Whenever possible use definitions from <tt/gsym.h/. The resulting code is translated by cc65 into +series of <tt/lda/ and <tt/sta/, so you can't do it better :-). +<p> +Don't hesitate to use library functions. Everything was written with size and speed in mind. In +fact many calls are just redirections to the GEOS Kernal which results in a simple <tt/jsr/. +<p> +The <tt/main/ function receives the standard <tt/argc/ and <tt/argv/ parameters. There are +always either 1 or 3 parameters. The DOS application name is always set as <tt/argv[0]/. +If present, <tt/argv[1]/ and <tt/argv[2]/ will be set to the data filename and data diskname (it only +works if the user double-clicks on a data file associated with your application). Note that it is up +to your application to determine which of the available (up to four) disk drives has the disk +with given diskname inside. If this fails your program should ask to insert the proper disk into +one of available drives. +<p> +You might wonder why I have chosen a sometimes weird order of arguments in functions. I just +wanted to avoid unnecessary pushing and popping of arguments from the stack because cc65 can pass a single +<tt/unsigned int/ through CPU registers. +<p> +Do not try to compile in strict ANSI mode. The library uses cc65 extensions which are not available in +ANSI. +<p> +It is possible to use dynamically loaded modules, three such modules are provided: +A GEOS TGI driver, a GEOS EMD driver (for VDC extended memory) and a GEOS JOY driver. +Just make sure that their filenames appear UPPERCASE in DeskTop. There are no more special +recommendations, read the cc65 documentation about modules and the demo programs source code. + +<sect>Library Functions +<p> +Functions here are sorted more or less in the way they appear in the header files. This way I am able +to keep functions covering similar tasks near each other. All function names are identical to those +from the <tt/geosSym/ file provided with the GeoProgrammer package. Only my extensions to <tt/geosSym/ +are covered by new names, but I tried to keep them in the naming convention. + +<sect1>Graphics +<p> +This section covers the drawing package of GEOS along with text output routines. + +<sect2>SetPattern +<p> +<tt/void SetPattern (char pattern)/ +<p> +This function sets the current pattern to the given. There are 32 different patterns in GEOS. You can +see them together in the filling box in GeoPaint. + +<sect2>GraphicsString +<p> +<tt/void GraphicsString (char *myGString)/ +<p> +One of the more powerfull routines of GEOS. This function calls other graphic functions depending +on the given command string. See the structures chapter for a more detailed description. + +<sect2>Rectangle functions +<p> +Parameters to those functions are grouped in the <tt/struct window drawWindow/. To speed up things and +reduce overhead this structure is bound to zero page locations, where all rectangle functions +expect their parameters. You can modify the data directly (e.g. <tt/drawWindow.top=10/) or via the +<tt/InitDrawWindow/ function. Contents of <tt/drawWindow/ are guaranteed not to change when only +using graphics functions. In other cases you should keep your data in separate <tt/struct window/ +and use <tt/InitDrawWindow/ before the first call to one of the rectangle functions. + +<sect3>InitDrawWindow +<p> +<tt/void InitDrawWindow (struct window *myWindow)/ +<p> +This function only copies the contents of <tt/myWindow/ into the system area of <tt/drawWindow/. Use it +if for some reason you have to keep your window data out of the zero page space. + +<sect3>Rectangle +<p> +<tt/void Rectangle (void)/ +<p> +This draws on screen a rectangle filled with the current pattern. + +<sect3>FrameRectangle +<p> +<tt/void FrameRectangle (char pattern)/ +<p> +This one draws a frame with the given bit pattern (not a pattern from the GEOS palette). + +<sect3>InvertRectangle +<p> +<tt/void InvertRectangle (void)/ +<p> +Just as the name says... + +<sect3>ImprintRectangle and RecoverRectangle +<p> +<tt/void ImprintRectangle (void)/ +<p> +<tt/void RecoverRectangle (void)/ +<p> +These two functions are for copying parts of the screen to (<tt/Imprint/) and from (<tt/Recover/) the +backbuffer of the screen. For example when drawing a new menu box GEOS first uses +<tt/ImprintRectangle/ to save the area under the box, and restores it by <tt/RecoverRectangle/ upon +destroying the menu. + +<sect2>Line Functions +<p> +The GEOS drawing package is optimized so there are different functions for drawing vertical and +horizontal lines. + +<sect3>HorizontalLine +<p> +<tt/void HorizontalLine (char pattern, char y, unsigned xStart, unsigned xEnd)/ +<p> +This function draws a horizontal line using the given pattern. Note that <tt/pattern/ is not a pattern +number as set in <tt/SetPattern/ but a true bit pattern. + +<sect3>InvertLine +<p> +<tt/void InvertLine (char y, unsigned xStart, unsigned xEnd)/ +<p> +There is only a horizontal version. + +<sect3>RecoverLine +<p> +<tt/void RecoverLine (char y, unsigned xStart, unsigned xEnd)/ +<p> +This function recovers a single line. It is utilized by <tt/RecoverRectangle/. See its description +for more details. + +<sect3>VerticalLine +<p> +<tt/void VerticalLine (char pattern, char yStart, char yEnd, unsigned x)/ +<p> +This function draws a vertical line using the given pattern. Note that <tt/pattern/ is not a pattern +number as set in <tt/SetPattern/ but a true bit pattern. + +<sect3>DrawLine +<p> +<tt/void DrawLine (char mode, struct window *myWindow)/ +<p> +The <tt/top/ parameters of <tt/struct window/ describe the starting point of the line, while +<tt/bottom/ ones are for the ending point. If <tt/mode/ is <tt/DRAW_DRAW/ then the current pattern from +<tt/SetPattern/ is used for drawing. If <tt/mode/ is <tt/DRAW_ERASE/ then the line is erased from the +screen. If <tt/mode/ is <tt/DRAW_COPY/ then the line is copied from/to back/frontbuffer, according to +the <tt/dispBufferOn/ setting. + +<sect2>Point Functions +<p> +The parameters to these two functions are passed by a pointer to an own <tt/struct pixel/ filled with +proper values. + +<sect3>DrawPoint +<p> +<tt/void DrawPoint (char mode, struct pixel *myPixel)/ +<p> +Depending on <tt/mode/ (see <tt/DrawLine/) draws/erases/copies a single point +on the screen. + +<sect3>TestPoint +<p> +<tt/char TestPoint (struct pixel *myPixel)/ +<p> +This function tests if the given pixel is set and returns <tt/true/ (non-zero) or <tt/false/ (zero). + +<sect2>Character and string output + +<sect3>PutChar +<p> +<tt/void PutChar (char character, char y, unsigned x)/ +<p> +This function outputs a single character using the current style and font to the screen. + +<sect3>PutString +<p> +<tt/void PutString (char *myString, char y, unsigned x)/ +<p> +Same as <tt/PutChar/ except the fact that you can output a whole <tt/NULL/-terminated string. +See <tt/ggraph.h/ for the list of tokens that you can also place in the string - like <tt/CBOLDON/ or +<tt/COUTLINEON/. + +<sect3>PutDecimal +<p> +<tt/void PutDecimal (char parameter, unsigned value, char y, unsigned x)/ +<p> +This function converts <tt/value/ to its decimal representation and outputs it to the screen. +The <tt/parameter/ is the field width in pixels (range 1-31) and the mode bits. Depending on them +the string can be filled with zeroes (the string is always 5 characters long) or not and left or right +justified to the given pixel. See <tt/ggraph.h/ for predefined values for <tt/parameter/. + +<sect2>Font Handling + +<sect3>GetCharWidth +<p> +<tt/char GetCharWidth (char character)/ +<p> +This function returns the real width (in pixels) of the given character with the current font. It can be used +for counting the length of a string on the screen, allowing for indentation or justification. + +<sect3>LoadCharSet +<p> +<tt/void LoadCharSet (struct fontdesc *myFont)/ +<p> +This function forces GEOS to use the given font. <tt/myFont/ should be casted from a +pointer to the start of the area where a record from a font file (VLIR structure) was loaded. + +<sect3>UseSystemFont +<p> +<tt/void UseSystemFont (void)/ +<p> +This function forces GEOS to use the built-in BSW font. + +<sect2>Bitmap handling +<p> +I'm not quite sure how these functions are working (except <tt/BitmapUp/) so you should +probably look into the library sources and compare it with your knowledge. Please let me know +if something is wrong or broken. + +<sect3>BitmapUp +<p> +<tt/void BitmapUp (struct iconpic *myPic)/ +<p> +This function unpacks the bitmap and places it on the screen - just as you set it in the +<tt/struct iconpic/ pointer which you pass. See <tt/gstruct.h/ for a description of this +structure. Note that you can only use packed GEOS bitmaps - a simple Photo Scrap is in this format. + +<sect3>BitmapClip +<p> +<tt/void BitmapClip (char skipLeft, char skipRight, unsigned skipTop, struct iconpic *myPic)/ +<p> +This function acts similar to <tt/BitmapUp/ but you can also define which parts of the bitmap are +to be drawn - you give the number of columns (8-pixel) to skip on the right and left of the bitmap, +and the number of rows to skip from the top if it. + +<sect3>BitOtherClip +<p> +<tt/void BitOtherClip (void *proc1, void *proc2, char skipLeft, char skip Right, unsigned skipTop, + struct iconpic *myPic)/ +<p> +Similar to the previous one with some extension. <tt/proc1/ is called before reading a byte (it +returns in .A the next value), and <tt/proc2/ is called every time the parser reads a byte which is +not a piece of a pattern (byte of code greater than 219). Both procedures should be written +separately in assembler and declared as <tt/__fastcall__/ returning char. + +<sect1>Menus and Icons +<p> +Here you will find information about functions related with menus and icons. + +<sect2>Menus +<p> +Menus are essential for a GUI. GEOS can handle only one menu at a time, but each menu can call +another one, which results in a submenu tree. There can be up to 8 menu levels, each one with up +to 32 items. +<p> +Menus are initialized with <tt/DoMenu/ and then the Kernal takes care of everything. Your code +(called from an event handler) should be a function without parameters, returning void. You should +use <tt/DoPreviousMenu/ or <tt/GotoFirstMenu/ at least once in its code to have the screen clean. + +<sect3>DoMenu +<p> +<tt/void DoMenu (struct menu *myMenu)/ +<p> +This function initializes the GEOS menu processor and exits. See <tt/DoMenu structure/ for more +information about it. Know that many GEOS applications just initialize the screen, menu and +exit to the main Kernal loop, this proves the power of <tt/DoMenu/. + +<sect3>ReDoMenu +<p> +<tt/void ReDoMenu (void)/ +<p> +This simply redraws the menu at the lowest level. It works like calling <tt/DoMenu/ again with +the same parameters. + +<sect3>RecoverMenu +<p> +<tt/void RecoverMenu (void)/ +<p> +This function erases the current menu from the screen. It doesn't change the menu level. + +<sect3>RecoverAllMenus +<p> +<tt/void RecoverAllMenus (void)/ +<p> +This calls <tt/RecoverMenu/ and erases all menus from the screen. Then the menu level is +set to 0 (topmost). + +<sect3>DoPreviousMenu +<p> +<tt/void DoPreviousMenu (void)/ +<p> +This functions causes the menu processor to go back one menu level. You should use it in menu +handler code to have the screen clean. + +<sect3>GotoFirstMenu +<p> +<tt/void GotoFirstMenu (void)/ +<p> +This one jumps back to the topmost menu. If there is only a menu and one submenu it works the +same as <tt/DoPreviousMenu/. + +<sect2>Icon Functions +<p> +Icons are working similar to menus except the fact that there is only one level. Icons are +defined as a screen area filled with a bitmap, but if you would setup icons and erase the +screen they would still be active and clicking in the place where formerly an icon was would cause +an effect. Similarly if you would setup icons and then turn them off with <tt/ClearMouseMode/ +the bitmap would still be on the screen but clicking on it would not cause any action. +There is only one, but powerful icon function. + +<sect3>DoIcons +<p> +<tt/void DoIcons (struct icontab *myIconTab)/ +<p> +This function initializes all icons that are present on the screen at once. For more information +look at the <tt/Icons/ chapter in this manual. + +<sect1>DialogBoxes +<p> +This chapter covers the most powerful GEOS user interface function - <tt/DoDlgBox/. + +<sect2>GEOS standard + +<sect3>DoDlgBox +<p> +<tt/char DoDlgBox (char *dialogString)/ +<p> +This function returns one byte. It can be the value of one of six standard icons (see <tt/gdlgbox.h/) +or whatever the closing routine passes. Register <tt/r0L/ also contains this value. +<p> +Read the structures chapter for the specs of the <tt/dialogString/. + +<sect3>RstrFrmDialogue +<p> +<tt/char RstrFrmDialogue/ +<p> +This function is called from within DoDlgBox event. It immediately closes the DialogBox and returns +the owner ID (or whatever caller has in the .A register). + +<sect2>GEOSLib extensions +<p> +To simplify the usage of DoDlgBox from C I wrote some helper functions - wrappers for DoDlgBox, +with predefined data. In one word - these are standard DialogBoxes you can see in almost every +GEOS application. + +<sect3>DlgBoxYesNo, DlgBoxOkCancel, DlgBoxOk +<p> +<tt/char DlgBoxYesNo (char *line1, char *line2)/ +<p> +<tt/char DlgBoxOkCancel (char *line1, char *line2)/ +<p> +<tt/void DlgBoxOk (char *line1, char *line2)/ +<p> +These function show two lines of text in a standard-sized DialogBox. You can read the code of the +pressed icon from the return value. E.g. for <tt/DlgBoxYesNo/ it can only be <tt/YES/ or <tt/NO/. +You can pass an empty string or NULL to get a blank line. + +<sect3>DlgBoxGetString +<p> +<tt/char DlgBoxGetString (char *string, char strlen, char *line1, char *line2)/ +<p> +This function prompts the user to enter a string of at most <tt/strlen/ characters. It is returned +in <tt/string/. The two given lines of text are shown above the input line. Please remember +that there is also a <tt/CANCEL/ icon in the DialogBox and you should test if user confirmed his +input or gave up. The <tt/string/ is also shown so you can place a default input there or remember +to place <tt/NULL/ at start. + +<sect3>DlgBoxFileSelect +<p> +<tt/char DlgBoxFileSelect (char *class, char filetype, char *filename)/ +<p> +This routine is the standard file selector. It can return <tt/OPEN/, <tt/CANCEL/ or disk error +on reading the directory or opening the disk. +There is also a <tt/DISK/ icon shown, but it is handled internally. You pass as input parameters +<tt/filetype/ and a pointer to a string containing the first part of a file's class. If this string is +empty (<tt/NULL/ at the start), then all files with given filetype will be shown. +<p> +At present this file selector handles only first 16 files of given type and supports only one +(current) drive. + +<sect3>MessageBox +<p> +<tt/char MessageBox (char mode, const char *format, ...)/ +<p> +This function is a more general one. It works very much like <tt/printf/ in a +box. The only difference is the <tt/mode/ parameter which allows for placing +default icons (see <tt/gdlgbox.h/ for list of possible <tt/MB_/ values). +Any too wide text will be clipped to the size of the default window. If <tt/mode/ +is invalid or equal to <tt/MB_EMPTY/ then the window will be closed +after a click. Otherwise the user must choose an icon. +<p> +Note: Use it if you really need (or if you use it in many places) as +it adds quite amount of code to your program. +<p> +Note: the formatted text <em/cannot exceed/ 255 bytes in length, there is no check +for that. + +<sect1>Mouse, Sprites and Cursors +<p> +You will find here functions related to sprite and mouse drawing and handling. + +<sect2>Mouse related functions +<p> +These cover the mouse - as a general pointing device, but expect users to utilize as different devices +as a digital or analog joystick, a mouse, a lightpen or a koalapad (whatever it is). + +<sect3>StartMouseMode +<p> +<tt/void StartMouseMode (void)/ +<p> +This function initializes the mouse vectors - <tt/mouseVector/ and <tt/mouseFaultVec/, and then +calls <tt/MouseUp/. + +<sect3>ClearMouseMode +<p> +<tt/void ClearMouseMode (void)/ +<p> +This function disables all mouse activities - icons and menus stop to respond to mouse events, +but they are not cleared from the screen. + +<sect3>MouseUp and MouseOff +<p> +<tt/void MouseUp (void)/ +<p> +<tt/void MouseOff (void)/ +<p> +The first function turns the mouse pointer on. It appears on the next IRQ. The second one does +the opposite - it turns off the pointer, but its position is still updated by the input driver. + +<sect3>IsMseInRegion +<p> +<tt/char IsMseInRegion (struct window *myWindow)/ +<p> +This function tests if the mouse pointer is actually in the given range of the screen. See <tt/gsprite.h/ for +a description of the bits in the return values - they describe the position in detail. + +<sect2>Sprites +<p> +You are free to use any of the eight sprites, but keep in mind that sprite 0 is actually the mouse +pointer and sprite 1 can be overwritten when using a text prompt. You don't have to worry about +40/80 column issues because GEOS128 has a pretty good sprite emulator for the VDC. + +<sect3>DrawSprite +<p> +<tt/void DrawSprite (char sprite, char *mySprite)/ +<p> +This function initializes the sprite data. <tt/mySprite/ is a 63-byte table with bitmap data, which +is copied to the system sprite area (at <tt/sprpic/ - see <tt/gsym.h/). Hardware sprite registers are +not initialized and the sprite is not yet visible. + +<sect3>PosSprite +<p> +<tt/void PosSprite (char sprite, struct pixel *myPixel)/ +<p> +This function positions the sprite on the screen. The given coordinates are screen ones - they are +converted to sprite coordinates by GEOS. Due to this you cannot use this function to position your +sprite off the left or top to the screen. + +<sect3>EnablSprite and DisablSprite +<p> +<tt/void EnablSprite (char sprite)/ +<p> +<tt/void DisablSprite (char sprite)/ +<p> +These two functions are responsible for making the sprite visible or not. + +<sect2>Cursors and Console + +<sect3>InitTextPrompt +<p> +<tt/void InitTextPrompt (char height)/ +<p> +This function initializes sprite 1 for a text prompt with given <tt/height/. This parameter can be in +range 1-48. + +<sect3>PromptOn and PromptOff +<p> +<tt/void PromptOn (struct pixel *myPixel)/ +<p> +<tt/void PromptOff (void)/ +<p> +The first function places a text prompt in given place and enables blinking. +The second one is pretty self-explanatory. + +<sect3>GetNextChar +<p> +<tt/char GetNextChar (void)/ +<p> +This function gets the next character from the keyboard queue. If the queue is empty it returns +<tt/NULL/, otherwise you receive the true ASCII code of a character or the value of a special (function) +key. See <tt/gsprite.h/ for the list of them. + +<sect1>Disk +<p> +This chapter covers rather low-level disk routines. You should use them with care, because +you may easily corrupt data on disks. Also remember that contemporary GEOS supports many various +devices and sticking to 1541 track layout (e.g. expecting the directory on track 18) might be +dangerous. +<p> +For some purposes you might consider using the <tt/dio.h/ interface to disk access. It is native. +<p> +All GEOS disk functions return an error code in the X register. In some cases this is returned by the +GEOSLib function (if its type is <tt/char/), but in all cases the last error is saved in the <tt/__oserror/ +location. If it is nonzero - an error occured. See <tt/gdisk.h/ for the list of possible errorcodes. +You need to include <tt/errno.h/ to get <tt/__oserror/, together with the standard <tt/errno/. The +latter gives less verbose, but still usable information and can be used with <tt/strerror/. +Probably you will get more information using <tt/_stroserror/ in a similar way. +<p> +For passing parameters use almost always a pointer to your data e.g. <tt/ReadBuff (&myTrSe)/. + +<sect2>Buffer functions +<p> +These functions take a single data sector (256 bytes) to read or write on the disk. + +<sect3>ReadBuff and Writebuff +<p> +<tt/char ReadBuff (struct tr_se *myTrSe)/ +<p> +<tt/char WriteBuff (struct tr_se *myTrSe)/ +<p> +These functions read and write a sector placed at <tt/diskBlkBuf/. + +<sect3>GetBlock and ReadBlock +<p> +<tt/char GetBlock (struct tr_se *myTrSe, char *buffer)/ +<p> +<tt/char ReadBlock (struct tr_se *myTrSe, char *buffer)/ +<p> +These two functions read a single block directly to the 256 byte array placed at <tt/buffer/. +The difference between them is that <tt/GetBlock/ initializes TurboDos in the drive if it was not +enabled. <tt/ReadBlock/ assumes that it is already enabled thus being slightly faster. + +<sect3>PutBlock, WriteBlock, VerWriteBlock +<p> +<tt/char PutBlock (struct tr_se *myTrSe, char *buffer)/ +<p> +<tt/char WriteBlock (struct tr_se *myTrSe, char *buffer)/ +<p> +<tt/char VerWriteBlock (struct tr_se *myTrSe, char *buffer)/ +<p> +Similar to previous but needed for writing the disk. <tt/VerWriteBlock/ verifies the data after +writing. In case of an error five tries are attempted before an error code is returned. + +<sect2>Directory header +<p> +The functions described here operate on <tt/curDirHeader/ where the current disk header is stored. +On larger (than 1541) capacity drives the second part of the directory header is in <tt/dir2Head/. + +<sect3>GetPtrCurDkNm +<p> +<tt/void GetPtrCurDkNm (char *diskName)/ +<p> +This function fills the given character string with the name of current disk. It is converted to C +standard - the string is terminated with <tt/NULL/ character instead of code 160 as in Commodore DOS. +Note that the passed pointer must point to an array of at least 17 bytes. + +<sect3>GetDirHead and PutDirHead +<p> +<tt/char GetDirHead (void)/ +<p> +<tt/char PutDirHead (void)/ +<p> +These functions read and write the directory header. You should use <tt/GetDirHead/ before +using any functions described below, and you should use <tt/PutDirHead/ to save the changes on the +disk. Otherwise they will be lost. Operating area is the <tt/curDirHead/. + +<sect3>CalcBlksFree +<p> +<tt/unsigned CalcBlksFree (void)/ +<p> +This function returns the number of free blocks on the current disk. It is counted using data in +<tt/curDirHead/ so you must initialize the disk before calling it. + +<sect3>ChkDskGEOS +<p> +<tt/char ChkDskGEOS (void)/ +<p> +This functions checks <tt/curDirHead/ for the GEOS Format identifier. It returns either true or false, +and also sets <tt/isGEOS/ properly. You must initialize the disk before using this. + +<sect3>SetGEOSDisk +<p> +<tt/char SetGEOSDisk (void)/ +<p> +This function initializes disk for use with GEOS. It sets the indicator in directory header and +allocates a sector for the directory of border files. You don't need to initialize the disk before +using. + +<sect3>FindBAMBit +<p> +<tt/char FindBAMBit (struct tr_se *myTrSe)/ +<p> +This function returns the bit value from the BAM (Block Allocation Map) for the given sector. The bit is +set if the sector is free to use. The returned value is always zero if the sector is already allocated. +In fact, this function could be used in a following way: +<tscreen><verb> +#define BlockInUse FindBAMBit +... +if (!BlockInUse(&myTrSe)) { +... block not allocated ... +} +</verb></tscreen> +<p> +Anyway, I feel that this function is too low-level. + +<sect3>BlkAlloc and NxtBlkAlloc +<p> +<tt/char BlkAlloc (struct tr_se output[&rsqb, unsigned length)/ +<p> +<tt/char NxtBlkAlloc (struct tr_se *myTrSe, struct tr_se output[&rsqb, unsigned length)/ +<p> +Both functions allocate enough disk sectors to fit <tt/length/ bytes in them. You +find the output in <tt/output/ which is a table of <tt/struct tr_se/. The last entry will have the +track equal to 0 and sector equal to 255. The simplest way of using them is to use +predefined space in the GEOS data space and pass <tt/fileTrScTab/, which is a predefined table. +<p> +The difference between those two is that <tt/NextBlkAlloc/ starts allocating from the given sector, +and <tt/BlkAlloc/ starts from the first nonused sector. +<p> +You need to use <tt/PutDirHead/ later to save any changes in BAM. + +<sect3>FreeBlock +<p> +<tt/char FreeBlock (struct tr_se *myTrSe)/ +<p> +Simply deallocates a block in the BAM. You need to update the BAM with <tt/PutDirHead/. + +<sect3>SetNextFree +<p> +<tt/struct tr_se SetNextFree (struct tr_se *myTrSe)/ +<p> +This function finds the first free sector starting from given track and sector and allocates it. +It might return the same argument if the given block is not allocated. I wanted it to be type +clean, but this made the usage a bit tricky. To assign a value to your own <tt/struct tr_se/ you have to +cast both variables to <tt/unsigned/. E.g. +<tscreen><verb> +struct tr_se myTrSe; +... +(unsigned)myTrSe=(unsigned)SetNextFree(&otherTrSe); +</verb></tscreen> +<p> +In this example <tt/otherTrSe/ can be replaced by <tt/myTrSe/. +<p> +Note: you <em/must/ use casting to have the correct values. + +<sect2>Low-level disk IO +<p> +Functions described here are more usable in Kernal or drivers code, less common in applications, +but who knows, maybe someone will need them. + +<sect3>EnterTurbo, ExitTurbo, PurgeTurbo +<p> +<tt/void EnterTurbo (void)/ +<p> +<tt/void ExitTurbo (void)/ +<p> +<tt/void PurgeTurbo (void)/ +<p> +These functions are the interface to the GEOS TurboDos feature which makes slow Commodore drives a bit +more usable. <tt/EnterTurbo/ enables TurboDos unless it is already enabled. If not, then you will +have to wait a bit to transfer the TurboDos code into disk drive RAM. <tt/ExitTurbo/ disables TurboDos. +This is useful for sending some DOS commands to a drive e.g. for formatting. Note that before any +interaction with the Kernal in ROM you have to call <tt/InitForIO/. You don't have to worry about speed. +<tt/EnterTurbo/ will only enable TurboDos (no code transfer) if TurboDos was disabled with +<tt/ExitTurbo/. <tt/PurgeTurbo/ acts differently from <tt/ExitTurbo/ - it not only disables TurboDos, +but also removes it from drive RAM (not quite true, but it works like that). After using +<tt/PurgeTurbo/ the next call to <tt/EnterTurbo/ will reload drive RAM. + +<sect3>ChangeDiskDevice +<p> +<tt/char ChangeDiskDevice (char newDevice)/ +<p> +This function changes the device number of the current device (in fact drives only) to the given one. It is +usable for swapping drives. There's no check if the given <tt/newDevice/ already exist, so if you want +to change the logical number of drive 8 to 9 and you already have a drive number 9 then GEOS will probably +hang on disk access. Use safe, large numbers. Note that the safe IEC range is 8-30. + +<sect2>Disk Initialization +<p> +GEOS has two functions for initialization ('logging in' as they say on CP/M) of a disk. +<sect3>OpenDisk +<p> +<tt/char OpenDisk (void)/ +<p> +This function initializes everything for a new disk. It loads and enables TurboDos if needed. +Then the disk is initialized with <tt/NewDisk/. Next, <tt/GetDirHead/ initializes <tt/curDirHead/. +Disk names are compared and if they differ then the disk cache on REU is cleared. Finally the format is +checked with <tt/ChkDkGEOS/ and the disk name is updated in the internal tables. + +<sect3>NewDisk +<p> +<tt/char NewDisk (void)/ +<p> +This function is similar to the DOS command I. It clears the REU cache and enables TurboDos if needed. + +<sect1>Files +<p> +This section covers the GEOS file interface. + +<sect2>Directory handling +<p> +The functions described here are common for SEQ and VLIR structures. + +<sect3>Get1stDirEntry and GetNxtDirEntry +<p> +<tt/struct filehandle *Get1stDirEntry (void)/ +<p> +<tt/struct filehandle *GetNxtDirEntry (void)/ +<p> +These two functions are best suited for scanning the whole directory for particular files. Note that +the returned filehandles describe all file slots in the directory - even those with deleted files. +The return value can be obtained by casting both sides to <tt/unsigned/ - as in the <tt/SetNextFree/ +function or read directly after a call to those two functions from <tt/r5/. The current sector number +is in <tt/r1/ and the sector data itself is in <tt/diskBlkBuf/. + +<sect3>FindFile +<p> +<tt/char FindFile (char *fName)/ +<p> +This function scans the whole directory for the given filename. It returns either 0 (success) or 5 +(FILE_NOT_FOUND, defined in <tt/gdisk.h/) or any other fatal disk read error. After a successful +<tt/FindFile/ you will have <tt/struct filehandle/ at <tt/dirEntryBuf/ filled with the file's data and +other registers set as described in <tt/GetNxtDirEntry/. + +<sect3>FindFTypes +<p> +<tt/char FindFTypes (char *buffer, char fType, char fMaxNum, char *classTxt)/ +<p> +This function scans the directory and fills a table at <tt/buffer/ with <tt/char [17]/ entries. +<tt/fType/ is the GEOS type of the searched files and <tt/classTxt/ is a string for the Class field in the file +header. Class matches if the given string is equal or shorter than that found in the file's header block. +If you want just to find all files with the given GEOS type you should pass an empty string or <tt/NULL/ as +<tt/classTxt/. Be warned that for searching <tt/NON_GEOS/ files you must pass <tt/NULL/ as <tt/classTxt/. +<tt/fMaxNum/ is the maximal number of files to find, thus the <tt/buffer/ must provide an area of size +equal to <tt/17 * fMaxNum/. This function returns the number of found files, ranging from 0 to number +passed as <tt/fMaxNum/. The return value can be also restored from <tt/r7H/. + +<sect3>DeleteFile +<p> +<tt/char DeleteFile (char *fName)/ +<p> +This function deletes a file by its name. It works for SEQ and VLIR files. + +<sect3>RenameFile +<p> +<tt/char RenameFile (char *oldName, char *newName)/ +<p> +I think it is obvious... + +<sect3>GetFHdrInfo +<p> +<tt/char GetFHdrInfo (struct filehandle *myFile)/ +<p> +This function loads the file header into the <tt/fileHeader/ buffer. Using after e.g. <tt/FindFile/ +you can pass the address of <tt/dirEntryBuf/. + +<sect2>Common and SEQ structure +<p> +Functions described here are common for SEQ and VLIR structures because the arguments passed are the +starting track and sector which may point either to the start of a chain for VLIR or the data for SEQ. + +<sect3>GetFile +<p> +<tt/char __fastcall__ GetFile(char flag, const char *fname, const char *loadaddr, const char *datadname, const char *datafname)/ +<p> +This routine loads and runs a given file <tt/fname/. The file must be one of following types: +<tt/SYSTEM, DESK_ACC, APPLICATION, APPL_DATA, PRINTER,/ or <tt/INPUT_DEVICE/. The execution +address is taken from the file header. If it is zero, then the file is only loaded. Only the first chain +from VLIR files is loaded. If <tt/flag/ has bit 0 set then the load address is taken from <tt/loadaddr/ +and not from the file header. In this case <tt/APPLICATION/ files will be only loaded, not executed. +This does not apply to <tt/DESK_ACC/. If either bit 6 or 7 of <tt/flag/ are set, then 16 bytes from +<tt/datadname/ are copied to <tt/dataDiskName/ and 16 bytes from <tt/datafname/ go to <tt/dataFileName/ +thus becoming parameters for the new application. Pass <tt/NULL/ for any unused parameter. + +<sect3>ReadFile +<p> +<tt/char ReadFile (struct tr_se *myTrSe, char *buffer, unsigned fLength)/ +<p> +This function reads at most <tt/fLength/ bytes into <tt/buffer/ from chained sectors starting at +<tt/myTrSe/. + +<sect3>ReadByte +<p> +<tt/char ReadByte (void)/ +<p> +This function returns the next byte from a file. Before the first call to it you must load <tt/r5/ +with <tt/NULL/, <tt/r4/ with the sector buffer address and <tt/r1/ with the track and sector of the +first block of a file. +Remember to not modify <tt/r1/, <tt/r4/ and <tt/r5/. These registers must be preserved between +calls to <tt/ReadByte/. +<p> +The returned value is valid only if there was no error. The end of file is marked as <tt/BFR_OVERFLOW/ +in <tt/__oserror/, this is set when trying to read one byte after the end of file, in this case the +returned value is invalid. + +<sect3>SaveFile +<p> +<tt/char SaveFile (char skip, struct fileheader *myHeader)/ +<p> +<tt/SaveFile/ will take care of everything needed to create a GEOS file, no matter if VLIR of SEQ +structure. All you need to do is to place the data in the proper place and prepare a header which will +contain all information about a file. The <tt/skip/ parameter says how many directory pages you +want to skip before searching for a free slot for the directory entry. In most cases you will put +<tt/0/ there. +<p> +You have to declare a <tt/struct fileheader/ and fill it with proper values. There is only one +difference - the first two bytes which are a link to a nonexistent next sector are replaced by a +pointer to the DOS filename of the file. +<p> +When saving sequential files the two most important fields in <tt/struct fileheader/ are <tt/fileheader.load_address/ +and <tt/fileheader.end_address/. + +<sect3>FreeFile +<p> +<tt/char FreeFile (struct tr_se myTable[])/ +<p> +This function deallocates all sectors contained in the passed table. + +<sect3>FollowChain +<p> +<tt/char FollowChain(struct tr_se *myTrSe, char *buffer)/ +<p> +This function fills a <tt/struct tr_se/ table at <tt/buffer/ with the sector numbers for a chain of +sectors starting with <tt/myTrSe/. You can pass such data (<tt/buffer/) to e.g. <tt/FreeFile/. + +<sect2>VLIR structure +<p> +Here is information about VLIR files (later called RecordFiles) and functions. +<p> +A VLIR structure file consists of up to 127 SEQ-like files called records. Each record is like one +SEQ structure file. Records are grouped together, described by a common name - the VLIR file name and +an own number. Each record pointed to by its number is described by the starting track and sector numbers. +VLIR structures allow records to be empty (<tt/tr_se/ of such record is equal to <tt/{NULL,$ff}/), +or even non-exist (<tt/{NULL,NULL}/). Any other numbers represent the starting track and sector of +a particular file. +<p> +In GEOS there can be only one file opened at a time. Upon opening a VLIR file some information +about it is copied into memory. You can retrieve the records table at <tt/fileTrScTab/ (table of +128 <tt/struct tr_se/) and from <tt/VLIRInfo/ (<tt/struct VLIR_info/. +E.g. the size of whole VLIR file can be retrieved by reading <tt/VLIRInfo.fileSize/. + +<sect3>OpenRecordFile +<p> +<tt/char OpenRecordFile (char *fName)/ +<p> +This function finds and opens a given file. An error is returned if the file is not found or if it is not +in VLIR format. Information in <tt/VLIRInfo/ is initialized. VLIR track and sector table is +loaded at <tt/fileTrScTab/ and will be valid until a call to <tt/CloseRecordFile/ so don't modify it. +You should call <tt/PointRecord/ before trying to do something with the file. + +<sect3>CloseRecordFile +<p> +<tt/char CloseRecordFile (void)/ +<p> +This function calls <tt/UpdateRecordFile/ and clears internal GEOS variables. + +<sect3>UpdateRecordFile +<p> +<tt/char UpdateRecordFile (void)/ +<p> +This function will check the <tt/VLIRInfo.fileWritten/ flag and if it is set, then <tt/curDirHead/ is +updated along with size and date stamps in the directory entry. + +<sect3>PointRecord +<p> +<tt/char PointRecord (char recordNumber)/ +<p> +This function will setup internal variables (and <tt/VLIRInfo.curRecord/) and return the track and +sector of the given record in <tt/r1/. Note that the data may not be valid (if the record is non-existing +you will get 0,0 and if it is empty - 255,0). + +<sect3>NextRecord and PreviousRecord +<p> +<tt/char NextRecord (void)/ +<p> +<tt/char PreviousRecord (void)/ +<p> +These two work like <tt/PointRecord/. Names are self-explanatory. + +<sect3>AppendRecord +<p> +<tt/char AppendRecord (void)/ +<p> +This function will append an empty record (pair of 255,0) to the current VLIR track and sector +table. It will also set <tt/VLIRInfo.curRecord/ to its number. + +<sect3>DeleteRecord +<p> +<tt/char DeleteRecord (void)/ +<p> +This function will remove the current record from the table, and move all current+1 records one place +back (in the table). Note that there's no BAM update and you must call <tt/UpdateRecordFile/ to +commit changes. + +<sect3>InsertRecord +<p> +<tt/char InsertRecord (void)/ +<p> +This function will insert an empty record in place of <tt/VLIRInfo.curRecord/ and move all following +records in the table one place forward (contents of <tt/VLIRInfo.curRecord/ after a call to <tt/InsertRecord/ +can be found in <tt/VLIRInfo.curRecord + 1/). + +<sect3>ReadRecord and WriteRecord +<p> +<tt/char ReadRecord (char *buffer, unsigned fLength)/ +<p> +<tt/char WriteRecord (char *buffer, unsigned fLength)/ +<p> +This function will load or save at most <tt/fLength/ bytes from the currently pointed record into or from +<tt/buffer/. + +<sect1>Memory and Strings +<p> +The functions covered in this section are common for the whole C world - copying memory parts and +strings is one of the main computer tasks. GEOS also has an interface to do this. These functions +are replacements for those like <tt/memset, memcpy, strcpy/ etc. from standard libraries. +If you are dealing with short strings (up to 255 characters) you should use these functions +instead of standard ones, e.g. <tt/CopyString/ instead of <tt/strcpy/. It will work faster. +<p> +However some of them have slightly different calling conventions (order of arguments to be specific), +so please check their syntax here before a direct replacement. +<p> +Please note that the memory areas described here as <em/strings/ are up to 255 characters (without +counting the terminating <tt/NULL/), and <em/regions/ can cover the whole 64K of memory. + +<sect2>CopyString +<p> +<tt/void CopyString (char *dest, char *src)/ +<p> +This function copies the string from <tt/src/ to <tt/dest/, until it reaches <tt/NULL/. The <tt/NULL/ +is also copied. + +<sect2>CmpString +<p> +<tt/char CmpString (char *s1, char *s2)/ +<p> +This function compares the strings <tt/s1/ to <tt/s2/ for equality - this is case sensitive, and both +strings have to have the same length. It returns either <tt/true/ (non-zero) or <tt/false/ (zero). + +<sect2>CopyFString and CmpFString +<p> +<tt/void CopyFString (char length, char *dest, char *src)/ +<p> +<tt/char CmpFString (char length, char *s1, char *s2)/ +<p> +These two are similar to <tt/CopyString/ and <tt/CmpString/ except the fact, that you provide +the length of the copied or compared strings. The strings can also contain several <tt/NULL/ +characters - they are not treated as delimiters. + +<sect2>CRC +<p> +<tt/unsigned CRC (char *src, unsigned length)/ +<p> +This function calculates the CRC checksum for the given memory range. I don't know if it is +compatible with standard CRC routines. + +<sect2>FillRam and ClearRam +<p> +<tt/void *FillRam (char *dest, char value, unsigned length)/ +<p> +<tt/void *ClearRam (char *dest, unsigned length)/ +<p> +Both functions are filling the given memory range. <tt/ClearRam/ fills with <tt/0s/, while +<tt/FillRam/ uses the given <tt/value/. Be warned that these functions destroy <tt/r0, r1 and +r2L/ registers. The functions are aliases for <tt/memset/ and <tt/bzero/, respectively. + +<sect2>MoveData +<p> +<tt/void *MoveData (char *dest, char *src, unsigned length)/ +<p> +This functions copies one memory region to another. There are checks for an overlap and the +non-destructive method is chosen. Be warned that this function destroys contents of the +<tt/r0, r1 and r2/ registers. This function is an alias for <tt/memcpy/. + +<sect2>InitRam +<p> +<tt/void InitRam (char *table)/ +<p> +This function allows to initialize multiple memory locations with single bytes or strings. +This is done with a <tt/table/ where everything is defined. See the structures chapter for a description of +<tt/InitRam's/ command string. + +<sect2>StashRAM, FetchRAM, SwapRAM, and VerifyRAM +<p> +<tt/void StashRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/ +<p> +<tt/void FetchRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/ +<p> +<tt/void SwapRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/ +<p> +<tt/ char VerifyRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/ +<p> +These functions are the interface to a REU - Ram Expansion Unit. I think that they are self-explanatory. +You can check for REU presence by taking the value of <tt/ramExpSize/. You have to do it before +using any of these functions. + +<sect1>Processes and Multitasking +<p> +Weird? Not at all. GEOS has some limited multitasking ability. You can set up a chain of functions +called in specified intervals and you can put the main program to sleep without disturbing other +tasks and making the user interface unresponsive. + +<sect2>InitProcesses +<p> +<tt/void InitProcesses (char number, struct process *processTab)/ +<p> +This is the main initialization routine. After calling it processes are set up, but not +enabled. The parameters for <tt/InitProcesses/ are: +<itemize> + <item><tt/number/ - number of processes + <item><tt/processTab/ - a table of <tt/struct process/, with size equal to <tt/number/ +</itemize> +<p> +A single task is described by an entry in <tt/processTab/, it contains two values - a <tt/pointer/ to +the task function and a number of <tt/jiffies/ which describe the delay between calls to task. On PAL +systems there are 50 jiffies per second, while on NTSC there are 60. +<p> +The maximum number of tasks is 20. Be warned that GEOS doesn't check if parameters are valid and +if <tt/processTab/ would be too large it would overwrite existing data in GEOS space. +<p> +There's one important thing - the last entry in <tt/processTab/ has to be <tt/NULL,NULL/, so the +maximum size of <tt/processTab/ is equal to 21. +<p> +See the description of <tt/process/ structure for a more detailed discussion on this. + +<sect2>RestartProcess and EnableProcess +<p> +<tt/void RestartProcess (char processNumber)/ +<p> +<tt/void EnableProcess (char processNumber)/ +<p> +These two functions start the task counter. <tt/RestartProcess/ should be called for each process +after <tt/InitProcesses/, because it resets all flags and counters and it starts the counters. +<p> +<tt/RestartProcess/ enables the counters and sets their initial value to that given in <tt/processTab/. +<p> +<tt/EnableProcess/ forces the given process to execute by simulating the timer expiring. + +<sect2>BlockProcess and UnblockProcess +<p> +<tt/void BlockProcess (char processNumber)/ +<p> +<tt/void UnblockProcess (char processNumber)/ +<p> +<tt/BlockProcess/ disables the execution of the given process, but this does not disable the timers. +It means that if you call <tt/UnblockProcess/ before the timer runs out, the process will be executed. +<p> +<tt/UnblockProcess/ does the opposite. + +<sect2>FreezeProcess and UnfreezeProcess +<p> +<tt/void FreezeProcess (char processNumber)/ +<p> +<tt/void UnfreezeProcess (char processNumber)/ +<p> +<tt/FreezeProcess/ disables timer for given process. <tt/UnfreezeProcess/ does the opposite. +This is not equal to <tt/RestartProcess/ as timers are not reloaded with initial value. + +<sect2>Sleep +<p> +<tt/void Sleep (unsigned jiffies)/ +<p> +This function is a multitasking sleep - the program is halted, but it doesn't block other functions +e.g. callbacks from menus and icons. +The only argument here is the number of jiffies to wait until the app will wake up. It depends on the +video mode (PAL or NTSC) how many jiffies there are per second (50 or 60, respectively). +If you don't want to worry about it and need only full second resolution, call the standard +<tt/sleep/ function from <tt/unistd.h/. + +<sect1>System Functions + +<sect2>FirstInit +<p> +<tt/void FirstInit (void)/ +<p> +This function initializes some GEOS variables and mouse parameters. This is called on GEOS boot +up. You shouldn't use this unless you know what you are doing. + +<sect2>InitForIO and DoneWithIO +<p> +<tt/void InitForIO (void)/ +<p> +<tt/void DoneWithIO (void)/ +<p> +These functions are called by some disk routines. You should call them only if you want to +do something with IO registers or call one of the Kernal ROM routines. Note that this is rather an +expensive way of turning off IRQs and enabling IO. + +<sect2>MainLoop +<p> +<tt/void MainLoop (void)/ +<p> +Returns control to the system. Any code between call to <tt/MainLoop/ and the end of current +function will never be executed. When in <tt/MainLoop/ the system waits for your action - using +icons, keyboard or menus to force some specific action from the program. You have to define +proper handlers before that. + +<sect2>EnterDeskTop +<p> +<tt/void EnterDeskTop (void)/ +<p> +This is an alias for <tt/exit(0)/ so you will never burn yourself. Anyway, you should not +use it. Always use <tt/exit()/ instead. Library destructors and functions registered with +<tt/atexit()/ are called. + +<sect2>ToBASIC +<p> +<tt/void ToBASIC (void)/ +<p> +This one is another way of terminating an application - forcing GEOS to shutdown and exit to BASIC. +I was considering whether to include it or not, but maybe someone will need it - which I doubt. +<p> +<em/WARNING:/ library destructors and functions registered with <tt/atexit()/ will not be called +so it is quite unsafe way to terminate your program. + +<sect2>Panic +<p> +<tt/void Panic (void)/ +<p> +This calls system's <tt/Panic/ handler - it shows a dialog box with the message +<tscreen><verb> +System error at:xxxx +</verb></tscreen> +where <tt/xxxx/ is last known execution address (caller). By default this is bound to the <tt/BRK/ +instruction, but it might be usable in debugging as kind of <tt/assert/. (Note that <tt/assert/ +is available as a separate function and will give you more information than that). +<p> +The system is halted after a call to <tt/Panic/ which means that library destructors will not be +called and some data may be lost (no wonder you're panicking). + +<sect2>CallRoutine +<p> +<tt/void CallRoutine (void *myFunct)/ +<p> +This is a system caller routine. You need to provide a pointer to a function and it will be immediately +called, unless the pointer is equal to <tt/NULL/. This is the main functionality of this function - +you don't need to check if the pointer is valid. + +<sect2>GetSerialNumber +<p> +<tt/unsigned GetSerialNumber (void)/ +<p> +This function returns the serial number of the system. It might be used for copy-protection. +However, please remember that Free Software is a true power and you are using it right now. + +<sect2>GetRandom +<p> +<tt/char GetRandom (void)/ +<p> +This function returns a random number. It can be also read from <tt/random/ e.g. +<tscreen><verb> +a=random; +</verb></tscreen> +but by calling this function you are sure that the results will be always different. +<tt/random/ is updated once a frame (50Hz PAL) and on every call to <tt/GetRandom/. +<p> +Note that this is not the same as the <tt/rand/ function from the standard library. <tt/GetRandom/ +will give you unpredictable results (if IRQs occur between calls to it) while +<tt/rand/ conforms to the standard and for a given seed (<tt/srand/) always returns with the +same sequence of values. + +<sect2>SetDevice +<p> +<tt/void SetDevice (char device)/ +<p> +This function sets the current device to the given. It might be used together with <tt/InitForIO/, +<tt/DoneWithIO/ and some Kernal routines. Unless the new device is a disk drive this only sets +new value in <tt/curDevice/, in the other case new disk driver is loaded from REU or internal RAM. + +<sect2>get_ostype +<p> +<tt/char get_ostype (void)/ +<p> +This function returns the GEOS Kernal version combined (by logical OR) with the machine type. Read +<tt/gsys.h/ for definitions of the returned values. + +<sect2>get_tv +<p> +<tt/char get_tv (void)/ +<p> +This function returns the PAL/NTSC flag combined (by logical OR) with the 40/80 columns flag. This is +not the best way to check if the screen has 40 or 80 columns since a PAL/NTSC check is always +performed and it can take as long as a full raster frame. If you just want to know if the +screen has 40 or 80 columns use the expression <tt/graphMode & 0x80/ which returns <tt/0/ for +40 columns and <tt/0x80/ for 80 columns. Remember that this value can be changed during +runtime. It is unclear if this will work for GEOS 64 so you probably do not want to test +anything if not running under GEOS128. Use <tt/get_ostype/ to check it. Read <tt/gsys.h/ for +definitions of the returned values. + +<sect>Library Structures +<p> +To simplify usage and optimize passing parameters to functions I have declared several structures +which describe the most common objects. Some of these structures are bound to static addresses in +the GEOS data space (<tt/$8000-$8fff/), so you can use their fields directly in an optimized way. +Please see <tt/gsym.h/ to find them. All structures are defined in <tt/gstruct.h/ and you may +find also some comments there. + +<sect1>Graphics Structures + +<sect2>pixel +<p> +A simple structure describing a point on the screen. + +<sect2>fontdesc +<p> +This structure describes a font in one pointsize. There is the current font - <tt/struct fontdesc/ +bound to <tt/curFontDesc/. You can also force GEOS to use your own fonts by calling +<tt/LoadCharSet/. You just need to open a VLIR font file and load one record - one pointsize - +somewhere. At the start of this area you already have all data for <tt/fontdesc/ so you can +pass a pointer to the load address of that pointsize to <tt/LoadCharSet/. (Note that although +it has 'Load' in the name, that function loads only GEOS internal data structures, not data +from disk). + +<sect2>window +<p> +This widely used structure holds the description of a region of the screen. It describes the top-left and +bottom-right corners of a window. + +<sect2>iconpic +<p> +Maybe the name isn't the best - it has nothing with <tt/DoIcons/ but with bitmap functions - +<tt/BitmapUp/ for example. This structure holds the parameters needed to properly decode and show +a bitmap on the screen. The bitmap has to be encoded - if you have some non-GEOS bitmaps simply +convert them to Photo Scraps - this is the format used by all GEOS bitmap functions - <tt/DoIcons/ +too. + +<sect1>Icons +<p> +These structures describe click boxes (icons) that can be placed on screen or in a dialog box. + +<sect2>icondef +<p> +This is the definition of a single click box. Please see <tt/gstruct.h/ for a description of its fields. + +<sect2>icontab +<p> +This is the toplevel description of icons to be placed and enabled on the screen. This structure +has the following fields: +<itemize> + <item><tt/char number/ - total number of icons declared here + <item><tt/struct pixel mousepos/ - after finishing <tt/DoIcons/ the mouse pointer will be placed in + this point allowing you to have a hint for the user what the default action is + <item><tt/struct icondef tab[&rsqb/ - this table of size equal to <tt/icontab.number/ contains + descriptions for all icons +</itemize> + +<sect1>File and Disk + +<sect2>tr_se +<p> +This simple structure holds the track and sector number of something. Do not expect the track to be +in range 1-35, as GEOS can support many various and weird devices. For example my C128 256K +expansion is utilized as RAMDisk with a layout of 4 tracks of 128 sectors each. However assuming that +a track number equal to 0 is illegal might be wise. + +<sect2>f_date +<p> +This is a placeholder for a file datestamp. This structure is also present in <tt/struct filehandle/. +GEOS is not Y2K compliant, so if the current file has in <tt/filehandle.date.year/ a value less than 86 +you can safely assume that it is e.g. 2004 and not 1904. + +<sect2>filehandle +<p> +This is the main file descriptor. It is either an entry in the directory (returned from file functions) +or its copy in <tt/dirEntryBuf/. This is optimized so you can safely get to the file's year e.g. +by testing <tt/dirEntryBuf.date.year/ - it will be compiled to simple <tt/LDA, STA/. + +<sect2>fileheader +<p> +This structure holds the fileheader description. You can load a file's header into the <tt/fileHeader/ +fixed area using <tt/GetFHdrInfo/. (note that <tt/fileHeader/ is a place in memory while +<tt/fileheader/ is a structure). +You will also need your own fileheader for <tt/SaveFile/. + +<sect1>System Structures + +<sect2>s_date +<p> +This structure is defined only for <tt/system_date/. It is slightly different from <tt/f_date/ +so I prepared this one. You can e.g. get or set the current time using <tt/system_date.s_hour/ and +<tt/system_date.s_minute/. Accesses to these will be optimized to simple <tt/LDA/ and <tt/STA/ +pair. + +<sect2>process +<p> +You should declare a table of that type to prepare data for <tt/InitProcesses/. The maximum number +of processes is 20, and the last entry has to be equal to <tt/{NULL,NULL}/, so this table may hold +only 21 entries. The first member of this structure (<tt/pointer/) holds the pointer to the called +function (void returning void), you will probably have to cast that pointer into <tt/unsigned int/. +The second field <tt/jiffies/ holds the amount of time between calls to that function. +On PAL systems there are 50 jiffies per second, while NTSC have 60 of them. + +<sect1>A few things in detail... +<p> +GEOSLib uses cc65 non-ANSI extensions to easily initialize data in memory. This is done with a +kind of array of unspecified length and unspecified type. Here is how it works: +<tscreen><verb> +void example = { + (char)3, (unsigned)3, (char)0 }; +</verb></tscreen> +Which will be compiled to following string of bytes: +<tscreen><verb> +_example: + .byte 3 + .word 3 + .byte 0 +</verb></tscreen> +As you see this way it is possible to define data of any type in any order. You must remember to +cast each member to proper type. + +<sect2>DoMenu structure +<p> +<tt/DoMenu/ is responsible for everything concerned with menu processing. Many, many GEOS programs +are just initializing the screen and menu and returning to <tt/MainLoop/. In GEOSLib it is the same as +returning from <tt/main/ function without using <tt/exit(0)/. +<p> +A menu is described by two types of data - menu descriptors and menu items. A descriptor contains +information about the following menu items, and items contain names of entries and either +pointers to functions to execute or, in case of nested menus, pointers to submenu descriptors. +Note that submenu descriptor can be top-level descriptor, there's no difference in structure, +just in the content. +<p> +Here is how a single descriptor looks like: +<tscreen><verb> +void myMenu = { + (char)top, (char)bottom, // this is the size of the menubox + (unsigned)left, (unsigned)right, // counting all items in the current descriptor + (char)number_of_items | type_of_menu, // number of following items ORed with + // type of this menu, it can be either + // HORIZONTAL or VERTICAL if you will have also bit 6 set then menu won't be closed + // after moving mouse pointer outside the menubox. You can have at most 31 items. +</verb></tscreen> +This is followed by <tt/number_of_items/ of following item description. +<tscreen><verb> + ... + "menuitemname", (char)item_type, (unsigned)pointer, + "nextitemname", (char)item_type, (unsigned)pointer, + ... + "lastitemname", (char)item_type, (unsigned)pointer }; + // Note that there isn't ending <tt/NULL/ or something like that. +</verb></tscreen> +<tt/pointer/ is a pointer to something, what it points for depends from <tt/item_type/. This one +can have following values: +<p> +<tt/MENU_ACTION/ - a function pointed by <tt/pointer/ will be called after clicking on the menu item +<p> +<tt/SUB_MENU/ - <tt/pointer/ points to next menu descriptor - a submenu +<p> +Both of them can be ORed with <tt/DYN_SUB_MENU/ and then the <tt/pointer/ points to a function +which will return in <tt/r0/ the needed pointer (to function to execute or a submenu). +<p> +For creating nested menus (you can have at most 8 levels of submenus) you need to declare such +a structure for each submenu and top level menu. + +<sect2>DoDlgBox command string +<p> +<tt/DoDlgBox/ is together with <tt/DoMenu/ one of the most powerful routines in GEOS. It is +responsible for creating dialog boxes, that is windows which task is to interact with the user. +The format of the command string is following: +<tscreen><verb> + (window size and position) + (commands and parameters) + NULL +</verb></tscreen> +There is a custom type defined for the command string: <tt/dlgBoxStr/. + +<sect3>Size and position +<p> +The first element can be specified in two ways - by using the default size and position or specifying +your own. The first case results in +<tscreen><verb> +const dlgBoxStr example = { + DB_DEFPOS (pattern_of_shadow), + ... // commands + DB_END }; +</verb></tscreen> +And the own size and position would be: +<tscreen><verb> +const dlgBoxStr example = { + DB_SETPOS (pattern, top, bottom, left, right) + ... // commands + DB_END }; +</verb></tscreen> + +<sect3>Commands +<p> +The next element of the <tt/DoDlgBox/ command string are the commands themselves. The first six commands are +default icons and the number of the selected icon will be returned from window processor. The icons are +<tt/OK, CANCEL, YES, NO, OPEN/, and <tt/DISK/. You can use predefined macros for using them, e.g.: +<tscreen><verb> + ... + DB_ICON(OK, DBI_X_0, DBI_Y_0), + ... +</verb></tscreen> +Note that the position is counted from top left corner of window, not entire screen and that the 'x' +position is counted in cards (8-pixel) and not in pixels. This is also true for all following commands. +<tt/DBI_X_0/ and <tt/DBI_Y_0/ are predefined (see <tt/gdlgbox.h/ for more), the default positions +which will cause icons to appear on a default window exactly where you would expect them. +<p> +<tt/DB_TXTSTR (x, y, text)/ will cause to show the given text in the window. +<p> +<tt/DB_VARSTR (x, y, ptr)/ works as above, but here you are passing a pointer to a zero page location +where the address of the text is stored. This is useful for information windows where only the text content +is variable. Consider following: +<tscreen><verb> +char text = "foo"; + ... + r15=(unsigned)text; // in code just before call to DoDlgBox + ... + DB_VARSTR (TXT_LN_X, TXT_LN_1_Y, &r15), + ... +</verb></tscreen> +will cause the word ``foo'' to appear in the window, but you may store the pointer to any text in +<tt/r15/ (in this case) before the call to DoDlgBox. +<p> +<tt/DB_GETSTR(x, y, ptr, length)/ - will add a input-from-keyboard feature. <tt/ptr/ works as in the +previous example and points to the location where the text is to be stored. Note that the contents of this +location will be shown upon creating the window. <tt/length/ is the maximum number of characters to input. +<p> +<tt/DB_SYSOPV(ptr)/ - this sets <tt/otherPressVec/ to the given pointer. It is called on every keypress. +<p> +<tt/DB_GRPHSTR(ptr)/ - the data for this command is a pointer for <tt/GraphicsString/ commands. +<p> +<tt/DB_GETFILES(x, y)/ - for a standard window you should pass 4 for both x and y. This function +draws a file selection box and searches the current drive for files. Before the call to <tt/DoDlgBox/ you +must load <tt/r7L/ with the GEOS filetype of searched files and <tt/r10/ with the class text. In <tt/r5/ +you have to load a pointer to a <tt/char[17]/ where the selected filename will be copied. It works +like <tt/FindFTypes/ but is limited to first 16 files. +<p> +<tt/DB_OPVEC(ptr)/ - this sets a new pointer for the button press function, if you pass +<tt/RstrFrmDialogue/ here you will cause the window to close after pressing mouse button. +<p> +<tt/DB_USRICON(x, y, ptr)/ - places a single user icon (click box) on the window, <tt/ptr/ points at a +<tt/struct icondef/ but fields <tt/x/ and <tt/y/ are not used here. You can have at most 8 click +boxes in a window, this is an internal limit of the GEOS Kernal. +<p> +<tt/DB_USRROUT(ptr)/ - this command causes to immediately call the user routine pointed by <tt/ptr/. + +<sect2>GraphicsString command string +<p> +<tt/GraphicsString/ is a very powerful routine to initialize the whole screen at once. There are +predefined macros for all commands, names are self-explanatory, see them in <tt/ggraph.h/. The last +command has to be <tt/GSTR_END/. There is a custom type defined for the command string: <tt/graphicStr/. +<p> +Here is an example for clearing the screen: +<tscreen><verb> +const graphicStr example = { + MOVEPENTO(0,0), + NEWPATTERN(0), + RECTANGLETO(319,199) + GSTR_END }; +</verb></tscreen> + +<sect2>InitRam table +<p> +This type of data is used to initialize one or more bytes in different locations at once. The format is +the following: +<tscreen><verb> +void example = { + (unsigned)address_to_store_values_at, + (char)number_of_bytes_that_follow, + (char)data,(char)data (...) + // more such definitions + (unsigned)NULL // address of 0 ends the table + }; +</verb></tscreen> + +<sect2>Intercepting system vectors +<p> +It is possible to intercept events and hook into the GEOS Kernal using vectors. Here is a little example: +<tscreen><verb> +void_func oldVector; + +void NewVectorHandler(void) { + // do something and at the end call the old vector routine + oldVector(); +} + +void hook_into_system(void) { + oldVector = mouseVector; + mouseVector = NewVectorHandler; +} + +void remove_hook(void) { + mouseVector = oldVector; +} +</verb></tscreen> +<p> +In your <tt/main/ function you should call <tt/hook_into_system()/ but <em/after/ all calls to the GEOS +Kernal (like <tt/DoMenu/, <tt/DoIcons/, etc.) - right before passing control to the <tt/MainLoop()/. +Be warned that vectors are most likely to be changed by the GEOS Kernal also via other functions (like +<tt/GotoFirstMenu/, <tt/DoDlgBox/ and its derivatives etc.). It depends on what Kernal functions +you use and which vectors you altered. Unfortunately there is no exact list for GEOS 2.0, a complete +list for GEOS 1.x can be found in A. Boyce's Programmers' Reference Guide mentioned before. Most of the +information contained there should be still valid for GEOS 2.0. When calling a function that restores +the vector you should add a <tt/hook_into_system()/ call right after it. +<p> +It is critical to restore old vector values before exiting the program. If you have more than one +place where you call <tt/exit()/ then it might be worth to register <tt/remove_hook/ function to +be called upon exiting with <tt/atexit(&remove_hook);/ call. This way you will ensure that +such destructor will be always called. +<p> +That little example above intercepts <tt/mouseVector/. The <tt/NewVectorHandler/ function will be +called every time the mouse button changes status. Other important vectors you should know about +are: +<itemize> + <item><tt/appMain/ - this is called from within the <tt/MainLoop/ system loop + <item><tt/keyVector/ - called whenever a keypress occurs + <item><tt/intTopVector/ - called at the start of the IRQ routine + <item><tt/intBotVector/ - called at the end of the IRQ routine +</itemize> + +</article> diff --git a/doc/grc65.sgml b/doc/grc65.sgml new file mode 100644 index 000000000..1acc6b1f2 --- /dev/null +++ b/doc/grc65.sgml @@ -0,0 +1,393 @@ +<!doctype linuxdoc system> +<article> + +<!-- Title information --> + +<title>grc65 -- GEOS Resource Compiler +<author> +<url url="mailto:ytm@elysium.pl" name="Maciej 'YTM/Elysium' Witkowiak">,<newline> +<url url="mailto:greg.king5@verizon.net" name="Greg King"> +<date>2014-04-24 +<abstract> +This document describes a compiler that can create GEOS headers and menues for +cc65-compiled programs. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview +<p><bf/grc65/ is a part of cc65's GEOS support. The tool is necessary to +generate required and optional resources. A required resource for every GEOS +application is the header, that is: an icon, some strings, and some addresses. +Optional resources might be menu definitions, other headers (e.g., for data +files of an app.), dialog definitions, etc. Without an application's header, +GEOS is unable to load and start it. + +Currently, <bf/grc65/ supports only menues and the required header definition, +along with support for building applications with VLIR-structured overlays. + +<bf/grc65/ generates output in two formats: C header and <bf/ca65/ source (.s). +That is because the application header data must be in assembly format, while +the menu definitions can be translated easily into C. The purpose of the C +file is to include it as a header in only one project file. The assembly source +should be processed by <bf/ca65/ and linked to the application (read about +<ref name="the building process" id="building-seq">). + + + +<sect>Usage +<p>grc65 accepts the following options: + +<tscreen><verb> +--------------------------------------------------------------------------- +Usage: grc65 [options] file +Short options: + -V Print the version number + -h Help (this text) + -o name Name the C output file + -s name Name the asm output file + -t sys Set the target system + +Long options: + --help Help (this text) + --target sys Set the target system + --version Print the version number +--------------------------------------------------------------------------- +</verb></tscreen> +Default output names are made from input names with extensions replaced by +<tt/.h/ and <tt/.s/. + + + +<sect>Resource file format +<p>A resource file has the name extension <tt/.grc/. That is not required, but +it will make for an easier recognition of the file's purpose. Also, <bf/cl65/ +recognizes those files. <bf/grc65/'s parser is very weak at the moment; so, +read the comments carefully, and write resources exactly as they are written +here. Look out for CAPS and small letters. Everything after a '<tt/;/' +until the end of the line is considered as a comment and ignored. See the +included <ref name="commented example .grc file" id="example-grc"> for a +better view of the situation. + + +<sect1>Menu definition +<p><tscreen><verb> +MENU menuName leftx,topy <ORIENTATION> { + "item name 1" <MENU_TYPE> pointer + ... + "item name x" <MENU_TYPE> pointer +}</verb></tscreen> +The definition starts with the keyword <tt/MENU/, then comes the menu's name, +which will be represented in C as <tt/const void/. Then are the co-ordinates +of the top left corner of the menu box. The position of the bottom right +corner is estimated, based on the length of item names and the menu's +orientation. It means that the menu box always will be as large as it should +be. Then, there's the orientation keyword; it can be either <tt/HORIZONTAL/ or +<tt/VERTICAL/. Between <tt/{/ and <tt/}/, there's the menu's +content. It consists of item definitions. First is an item name -- it has to +be in quotes. Next is a menu-type bit. It can be <tt/MENU_ACTION/ or +<tt/SUB_MENU/; either of them can be combined with the <tt/DYN_SUB_MENU/ bit +(see <url name="the GEOSLib documentation" url="geos.html"> for descriptions of +them). You can use C logical operators in expressions, but you have to do it +without spaces. So a dynamically created submenu will be something like: +<tscreen><verb> +"dynamic" SUB_MENU|DYN_SUB_MENU create_dynamic</verb></tscreen> +The last part of the item definition is a pointer which can be any name that is +present in the C source code that includes the generated header. It can point +to a function or to another menu definition. + +If you are doing sub(sub)menu definitions, remember to place the lowest level +definition first, and the top-level menu as the last one. That way the C +compiler won't complain about unknown names. + + +<sect1>Header definition +<p><tscreen><verb> +HEADER <GEOS_TYPE> "dosname" "classname" "version" { + author "Joe Schmoe" + info "This is my killer-app!" + date yy mm dd hh ss + dostype SEQ + mode any + structure SEQ + icon "sprite.raw" +}</verb></tscreen> +The header definition describes the GEOS header sector which is unique to +each file. The definition starts with the keyword <tt/HEADER/, then goes the +GEOS file-type. You can use only <tt/APPLICATION/ here at the moment. Then, +there are (each one in quotes) the DOS file-name (up to 16 characters), the GEOS +Class name (up to 12 characters), and the version info (up to 4 characters). +The version should be written as &dquot;<tt/V/x.y&dquot;, where <em/x/ is the +major, and <em/y/ is the minor, version number. Those fields, along with both +braces, are required. The lines between braces are optional, and will be replaced +by default and current values. The keyword <tt/author/ and its value in quotes name +the programmer, and can be up to 63 bytes long. <tt/info/ (in the same format) can +have up to 95 characters. If the <tt/date/ field is omitted, then the time of +that compilation will be placed into the header. Note that, if you do specify +the date, you have to write all 5 numbers. The <tt/dostype/ can be <tt/SEQ/, +<tt/PRG/, or <tt/USR/. <tt/USR/ is used by default; GEOS usually doesn't care. +The <tt/mode/ can be <tt/any/, <tt/40only/, <tt/80only/, or <tt/c64only/; and, +it describes system requirements. <tt/any/ will work on both 64-GEOS and +128-GEOS, in 40- and 80-column modes. <tt/40only/ will work on 128-GEOS in +40-column mode only. <tt/80only/ will work on only 128-GEOS in 80-column mode, +and <tt/c64only/ will work on only 64-GEOS. The default value for +<tt/structure/ is <tt/SEQ/ (sequential). You can put <tt/VLIR/ there, too; but +then, you also have to put in a third type of resource -- a memory definition. +The value of <tt/icon/ is a quoted file-name. The first 63 bytes of this file +are expected to represent a standard monochrome VIC sprite. The file gets accessed +when the generated assembly source is being processed by <bf/ca65/. Examples for +programs generating such files are <em/Sprite Painter/, <em/SpritePad/ and the +<url name="sp65 sprite and bitmap utility" url="sp65.html">. The default <tt/icon/ +is an empty frame internally represented in the generated assembly file. + + +<sect1>Memory definition +<p><tscreen><verb> +MEMORY { + stacksize 0x0800 + overlaysize 0x2000 + overlaynums 0 1 2 4 5 +}</verb></tscreen> +The memory definition is unique to each file and describes several attributes related +to the memory layout. It consists of the keyword <tt/MEMORY/ followed by braces which +contain optional lines. The value of <tt/stacksize/ can be either decimal (e.g. +<tt/4096/) or hexadecimal with a <tt/0x/ prefix (e.g. <tt/0x1000/). The default value +of 0x400 comes from the linker configuration file. The value of <tt/backbuffer/ can be +either <tt/yes/ or <tt/no/. The further means that the application uses the system-supplied +background screen buffer while the latter means that the program uses the memory of the +background screen buffer for own purposes. The default value of <tt/yes/ comes from the +linker configuration file. If the <tt/structure/ in the header definition is set to the +value <tt/VLIR/ then it is possible and necessary to provide here the attributes of the +VLIR overlays. <tt/overlaysize/ defines the maximal size for all VLIR records but number +0. It can be either decimal (e.g. <tt/4096/) or hexadecimal with a <tt/0x/ prefix (e.g. +<tt/0x1000/). <tt/overlaynums/ defines the VLIR record numbers used by the application. +Skipped numbers denote empty records. In the example, record number 3 is missing. Read +<ref name="this description" id="building-vlir"> for details. + + + +<sect>Building a GEOS sequential application<label id="building-seq"> +<p>Before proceeding, please read the <url name="compiler" url="cc65.html">, +<url name="assembler" url="ca65.html">, and <url name="linker" url="ld65.html"> +documentation, and find the appropriate sections about building programs, in +general. + +GEOS support in cc65 is based on the <em/Convert v2.5/ format, well-known in +the GEOS world. It means that each file built with the cc65 package has to be +deconverted in GEOS, before it can be run. You can read a step-by-step +description of that in the <url name="GEOS section of the cc65 Compiler Intro" +url="intro.html#ss6.5">. + +Each project consists of four parts, two are provided by cc65. Those parts +are:<enum> +<item>application header +<item>start-up object +<item>application objects +<item>system library +</enum> +<bf/2./ and <bf/4./ come with cc65; however you have to write the application +yourself ;-) + +The application header is defined in the <tt/HEADER/ section of the <tt/.grc/ +file and is processed into an assembly <tt/.s/ file. You must assemble it, with +<bf/ca65/, into the object <tt/.o/ format. + +Assume that there are three input files: &dquot;<tt/test.c/&dquot; (a C +source), &dquot;<tt/test.h/&dquot; (a header file), and +&dquot;<tt/testres.grc/&dquot; (with menu and header definitions). Note the +fact that I <em/don't recommend/ naming that file &dquot;<tt/test.grc/&dquot; +because you will have to be very careful with names (<bf/grc65/ will make +&dquot;<tt/test.s/&dquot; and &dquot;<tt/test.h/&dquot; out of +&dquot;<tt/test.grc/&dquot; by default; and you don't want that because +&dquot;<tt/test.s/&dquot; is compiled from &dquot;<tt/test.c/&dquot;, and +&dquot;<tt/test.h/&dquot; is something completely different)! + +<bf/One important thing/ -- the top of &dquot;<tt/test.c/&dquot; looks like: +<tscreen><verb> +#include <geos.h> +#include "testres.h" +</verb></tscreen> +There are no other includes. + + +<sect1>Building the GEOS application using cl65 +<p>This is a simple one step process: +<tscreen><verb> +cl65 -t geos-cbm -O -o test.cvt testres.grc test.c +</verb></tscreen> +Always place the <tt/.grc/ file as first input file on the command-line in order +to make sure that the generated <tt/.h/ file is available when it is needed for +inclusion by a <tt/.c/ file. + + +<sect1>Building the GEOS application without cl65 +<sect2>First step -- compiling the resources +<p> +<tscreen><verb> +grc65 -t geos-cbm testres.grc +</verb></tscreen> +will produce two output files: &dquot;<tt/testres.h/&dquot; and +&dquot;<tt/testres.s/&dquot;. + +Note that &dquot;<tt/testres.h/&dquot; is included at the top of +&dquot;<tt/test.c/&dquot;. So, resource compiling <em/must be/ the first step. + +<sect2>Second step -- assembling the application header +<p> +<tscreen><verb> +ca65 -t geos-cbm testres.s +</verb></tscreen> +And, voilá -- &dquot;<tt/testres.o/&dquot; is ready. + +<sect2>Third step -- compiling the code +<p> +<tscreen><verb> +cc65 -t geos-cbm -O test.c +ca65 -t geos-cbm test.s +</verb></tscreen> +That way, you have a &dquot;<tt/test.o/&dquot; object file which +contains all of the executable code. + +<sect2>Fourth and last step -- linking the application +<p> +<tscreen><verb> +ld65 -t geos-cbm -o test.cvt testres.o test.o geos-cbm.lib +</verb></tscreen> +The last file is the GEOS system library. + +The resulting file &dquot;<tt/test.cvt/&dquot; is an executable that's +contained in the well-known GEOS <em/Convert/ format. Note that its name +(<tt/test.cvt/) isn't important; the real name, after deconverting, is the DOS name +that was given in the header definition. + +At each step, a <tt/-t geos-cbm/ was present on the command-line. That switch is +required for the correct process of GEOS sequential application building. + + + +<sect>Building a GEOS VLIR overlay application<label id="building-vlir"> +<p>Large GEOS applications typically don't fit in one piece in their designated +memory area. They are therefore split into overlays which are loaded into memory +on demand. The individual overlays are stored as records of a VLIR (Variable +Length Index Record) file. When GEOS starts a VLIR overlay appliation it loads +record number 0 which is supposed to contain the main program. The record numbers +starting with 1 are to be used for the actual overlays. + +In "<tt>cc65/samples/geos</tt>" there's a VLIR overlay demo application consisting +of the files "<tt/overlay-demo.c/" and "<tt/overlay-demores.grc/". + + +<sect1>Building the GEOS overlay application using cl65 +<p>This is a simple one step process: +<tscreen><verb> +cl65 -t geos-cbm -O -o overlay-demo.cvt -m overlay-demo.map overlay-demores.grc overlay-demo.c +</verb></tscreen> +Always place the <tt/.grc/ file as first input file on the command-line in order +to make sure that the generated <tt/.h/ file is available when it is needed for +inclusion by a <tt/.c/ file. + +You will almost certainly want to generate a map file that shows (beside a lot of +other infos) how large your individual overlays are. This info is necessary to tune +the distribution of code into the overlays and to optimize the memory area reserved +for the overlays. + + +<sect1>Building the GEOS overlay application without cl65 +<sect2>First step -- compiling the overlay resources +<p> +<tscreen><verb> +grc65 -t geos-cbm overlay-demores.grc +</verb></tscreen> + +<sect2>Second step -- assembling the overlay application header +<p> +<tscreen><verb> +ca65 -t geos-cbm overlay-demores.s +</verb></tscreen> + +<sect2>Third step -- compiling the overlay code +<p> +<tscreen><verb> +cc65 -t geos-cbm -O overlay-demo.c +ca65 -t geos-cbm overlay-demo.s +</verb></tscreen> + +<sect2>Fourth and last step -- linking the overlay application +<p> +<tscreen><verb> +ld65 -t geos-cbm -o overlay-demo.cvt -m overlay-demo.map overlay-demores.o overlay-demo.o geos-cbm.lib +</verb></tscreen> + + + +<sect>Bugs and feedback +<p>This is the first release of <bf/grc65/, and it contains bugs, for sure! I +am aware of them; I know that the parser is weak, and if you don't follow the +grammar rules strictly, then everything will crash. However, if you find an +interesting bug, mail me. :-) Mail me also for help with writing your +<tt/.grc/ file correctly if you have problems with it. I would appreciate +comments also, and help on this file because I am sure that it can be written +better. + + + +<sect>Legal stuff +<p><bf/grc65/ is covered by the same license as the whole cc65 package, so you +should see its documentation for more info. Anyway, if you like it, and want +to encourage me to work more on it, send me a postcard with a sight of your +neighbourhood, city, region, etc. Or, just e-mail me with info that you +actually used it. See <url name="the GEOSLib documentation" url="geos.html"> +for addresses. + + + +<!-- <appendix> --> +<sect>Appendix A -- example.grc<label id="example-grc"> +<p><tscreen><verb> +; Note that MENU can define both menues and submenues. +; If you want to use any C operators (such as "|", "&", etc.), do it WITHOUT +; any spaces between the arguments (the parser is simple and weak). + +MENU subMenu1 15,0 VERTICAL +; This is a vertical menu, placed at (15,0). +{ +; There are three items, all of them will call functions. +; The first and third ones are normal functions, see GEOSLib documentation for +; information about what the second function should return (it's a dynamic one). + "subitem1" MENU_ACTION smenu1 + "subitem2" MENU_ACTION|DYN_SUB_MENU smenu2 + "subitem3" MENU_ACTION smenu3 +} + +;; Format: MENU "name" left,top ALIGN { "itemname" TYPE pointer ... } + +MENU mainMenu 0,0 HORIZONTAL +; Here, we have our main menu, placed at (0,0), and it is a horizontal menu. +; Because it is a top-level menu, you would register it in your C source by +; using: DoMenu(&ero;mainMenu); +{ +; There are two items -- a submenu and an action. +; This calls a submenu named subMenu1 (see previous definition). + "first sub-menu" SUB_MENU subMenu1 +; This will work the same as an EnterDeskTop() call in C source code. + "quit" MENU_ACTION EnterDeskTop +} + +;; Format: HEADER <GEOS_TYPE> "dosname" "classname" "version" + +HEADER APPLICATION "MyFirstApp" "Class Name" "V1.0" +; This is a header for an APPLICATION which will be seen in the directory as a +; file named MyFirstApp with the Class-string "Class Name V1.0" +{ +; Not all fields are required, default and current values will be used. + author "Maciej Witkowiak" ; always in quotes! + info "Information text" ; always in quotes! +; date yy mm dd hh ss ; always 5 fields! +; dostype seq ; can be: PRG, SEQ, USR (only all UPPER- or lower-case) +; structure seq ; can be: SEQ, VLIR (only UPPER- or lower-case) + mode c64only ; can be: any, 40only, 80only, c64only +}</verb></tscreen> +</article> diff --git a/doc/header.html b/doc/header.html new file mode 100644 index 000000000..38a943e5b --- /dev/null +++ b/doc/header.html @@ -0,0 +1,4 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<HTML> +<HEAD> + <LINK REL="stylesheet" TYPE="text/css" HREF="doc.css"> diff --git a/doc/index.sgml b/doc/index.sgml new file mode 100644 index 000000000..c77344865 --- /dev/null +++ b/doc/index.sgml @@ -0,0 +1,153 @@ +<!doctype linuxdoc system> + +<article> +<title>cc65 Documentation Overview +<author><url url="https://github.com/cc65/cc65/"> +<date> + +<sect>Program documentation<p> + +<descrip> + + <tag><htmlurl url="ar65.html" name="ar65.html"></tag> + Describes the ar65 archiver. + + <tag><htmlurl url="ca65.html" name="ca65.html"></tag> + Describes the ca65 macro assembler. + + <tag><htmlurl url="cc65.html" name="cc65.html"></tag> + Describes the cc65 C compiler. + + <tag><htmlurl url="cl65.html" name="cl65.html"></tag> + Describes the cl65 compile & link utility. + + <tag><htmlurl url="co65.html" name="co65.html"></tag> + Describes the co65 object-file converter. + + <tag><htmlurl url="da65.html" name="da65.html"></tag> + Describes the da65 6502/65C02 disassembler. + + <tag><htmlurl url="grc65.html" name="grc65.html"></tag> + Describes the GEOS resource compiler (grc65). + + <tag><htmlurl url="ld65.html" name="ld65.html"></tag> + Describes the ld65 linker. + + <tag><htmlurl url="od65.html" name="od65.html"></tag> + Describes the od65 object-file analyzer. + + <tag><htmlurl url="sp65.html" name="sp65.html"></tag> + Describes the sprite and bitmap utility. + +</descrip> + + +<sect>Usage<p> + +<descrip> + + <tag><htmlurl url="intro.html" name="intro.html"></tag> + Describes the use of the tools, by building a short &dquot;hello world&dquot; + example. + + <tag><htmlurl url="coding.html" name="coding.html"></tag> + Contains hints on creating the most effective code with cc65. + + <tag><htmlurl url="using-make.html" name="using-make.html"></tag> + Build programs, using the GNU Make utility. + + <tag><htmlurl url="customizing.html" name="customizing.html"></tag> + How to use the cc65 toolset for a custom hardware platform (a target system + not currently supported by the cc65 library set). + + <tag><htmlurl url="debugging.html" name="debugging.html"></tag> + Debug programs, using the VICE emulator. + +</descrip> + + +<sect>Library information and other references<p> + +<descrip> + + <tag><htmlurl url="funcref.html" name="funcref.html"></tag> + A (currently incomplete) function reference. + + <tag><htmlurl url="dio.html" name="dio.html"></tag> + Low-level disk I/O API. + + <tag><htmlurl url="geos.html" name="geos.html"></tag> + The GEOSLib manual. + + <tag><htmlurl url="library.html" name="library.html"></tag> + An overview over the cc65 runtime and C libraries. + + <tag><htmlurl url="smc.html" name="smc.html"></tag> + Describes Christian Krügers macro package for writing self modifying + assembler code. + + <tag><url name="6502 Binary Relocation Format document" + url="http://www.6502.org/users/andre/o65/fileformat.html"></tag> + Describes the o65 file format that is used for dynamically loadable modules + and LUnix programs. + +</descrip> + + +<sect>Platform-specific information<p> + +<descrip> + + <tag><htmlurl url="apple2.html" name="apple2.html"></tag> + Topics specific to the Apple ][. + + <tag><htmlurl url="apple2enh.html" name="apple2enh.html"></tag> + Topics specific to the enhanced Apple //e. + + <tag><htmlurl url="atari.html" name="atari.html"></tag> + Topics specific to the Atari 8-bit machines. + + <tag><htmlurl url="atari5200.html" name="atari5200.html"></tag> + Topics specific to the Atari 5200 Game Console. + + <tag><htmlurl url="atmos.html" name="atmos.html"></tag> + Topics specific to the Oric Atmos. + + <tag><htmlurl url="c128.html" name="c128.html"></tag> + Topics specific to the Commodore 128. + + <tag><htmlurl url="c16.html" name="c16.html"></tag> + Topics specific to the Commodore 16/116. + + <tag><htmlurl url="c64.html" name="c64.html"></tag> + Topics specific to the Commodore 64. + + <tag><htmlurl url="cbm510.html" name="cbm510.html"></tag> + Topics specific to the Commodore 510. + + <tag><htmlurl url="cbm610.html" name="cbm610.html"></tag> + Topics specific to the Commodore 610. + + <tag><htmlurl url="lynx.html" name="lynx.html"></tag> + Topics specific to the Atari Lynx Game Console. + + <tag><htmlurl url="nes.html" name="nes.html"></tag> + Topics specific to the Nintendo Entertainment System. + + <tag><htmlurl url="pet.html" name="pet.html"></tag> + Topics specific to the Commodore PET machines. + + <tag><htmlurl url="plus4.html" name="plus4.html"></tag> + Topics specific to the Commodore Plus/4. + + <tag><htmlurl url="supervision.html" name="supervision.html"></tag> + Topics specific to the Supervision Console. + + <tag><htmlurl url="vic20.html" name="vic20.html"></tag> + Topics specific to the Commodore VIC20. + +</descrip> + + +</article> + diff --git a/doc/intro.sgml b/doc/intro.sgml new file mode 100644 index 000000000..02c5c83d5 --- /dev/null +++ b/doc/intro.sgml @@ -0,0 +1,528 @@ +<!doctype linuxdoc system> + +<article> + +<title>cc65 Compiler Intro +<author> +<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> +<url url="mailto:cbmnut@hushmail.com" name="CbmNut">,<newline> +<url url="mailto:greg.king5@verizon.net" name="Greg King"> +<date>2014-4-24 + +<abstract> +How to use the cc65 C language system -- an introduction. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This is a short intro of how to use the compiler and the bin-utils. It contains +a step-by-step example of how to build a complete application from one C and +one assembly modules. This file does <em/not/ contain a complete reference for +the tools used in the process. There are separate files describing those tools, +in detail (see <url url="index.html">). + +I do assume that you have downloaded and installed the compiler and +target-specific files. Windows users should use the friendly .exe installer +(named cc65-2.13.0-1.exe for version 2.13.0 of the package - adjust the +version number if necessary). It does not only install the target files, but +will also set up necessary environment variables for you. + +If you're going for the .ZIP archives, please note that there is one file for +the host platform (Windows, DOS or OS/2), one file for each target platform +(C64 or whatever) and a separate file containing the docs (which include the +file you're currently reading). So for most uses, you will need at least 3 +files and unpack all three into one directory. In case of the .ZIP archives, +you will also need to set the environment variables <tt/CC65_INC/, +<tt/LD65_LIB/ and <tt/LD65_CFG/ as described below. + +<em/Note:/ There is a much simpler way to compile this example, by using the +<bf/cl65/ compile-and-link utility. However, it makes sense to understand how +the separate steps work. How to do the example with the <bf/cl65/ utility is +described <ref id="using-cl65" name="later">. + + +<sect1>Before we start<p> + +You will find a copy of the sample modules, used in the next section, in the +"<tt>cc65/samples/tutorial</tt>" directory. If you encounter problems with +missing include files and/or libraries, please check the environment variables +<tt/CC65_INC/, <tt/LD65_LIB/ and <tt/LD65_CFG/. They should point to the +<tt/include/, <tt/lib/ and <tt/cfg/ subdirectories of the directory, where you +installed cc65. + + +<sect1>The sample modules<p> + +To explain the development flow, I will use the following example modules: + +hello.c: +<tscreen><code> + #include <stdio.h> + #include <stdlib.h> + + extern const char text[]; /* In text.s */ + + int main (void) + { + printf ("%s\n", text); + return EXIT_SUCCESS; + } +</code></tscreen> + +text.s: +<tscreen><code> + .export _text + _text: .asciiz "Hello world!" +</code></tscreen> + + +<sect1>Translation phases<p> + +We assume that the target file should be named "hello", and the target system +is the C64. + +<tscreen><verb> + +---------+ + | hello.c | + +---------+ + | + cc65 + \/ + +---------+ +---------+ +---------+ + | hello.s | | text.s | | crt0.o | + +---------+ +---------+ +---------+ + | | | + ca65 ca65 ar65 + \/ \/ \/ + +---------+ +---------+ +---------+ + | hello.o | | text.o | | c64.lib | + +---------+ +---------+ +---------+ + | \ / + | \ / + | \ / + +----------------------->ld65< + \/ + hello +</verb></tscreen> + +<tt/crt0.o/ (the startup code) and <tt/c64.lib/ (the C64 version of the runtime +and C library) are provided in binary form in the cc65 package. Actually, the +startup code is contained in the library, so you won't need to care about it. + + + +<sect>The compiler<p> + +The compiler translates one C source into one assembly source, for each +invocation. It does <em/not/ create object files directly, and it is <em/not/ +able to translate more than one file per run. + +In the example above, we would use the following command line, to translate +<tt/hello.c/ into <tt/hello.s/: + +<tscreen><verb> + cc65 -O -t c64 hello.c +</verb></tscreen> + +The <tt/-O/ switch tells the compiler to do an additional optimizer run, which +is usually a good idea, since it makes the code smaller. If you don't care +about the size, but want to have slightly faster code, use <tt/-Oi/ to inline +some runtime functions. + +The <tt/-t/ switch is followed by the target system name. + +If the compiler does not complain about errors in our "hello world" program, we +will have a file named "<tt/hello.s/", in our directory, that contains the +assembly source for the <bf/hello/ module. + +For more information about the compiler, see <url url="cc65.html">. + + + +<sect>The assembler<p> + +The assembler translates one assembly source into an object file, for each +invocation. The assembler is <em/not/ able to translate more than one source +file per run. + +Let's translate the "hello.s" and "text.s" files from our example: + +<tscreen><verb> + ca65 hello.s + ca65 -t c64 text.s +</verb></tscreen> + +The <tt/-t/ switch is needed when translating the <tt/text.s/ file, so the +text is converted from the input character-set (usually ISO-8859-1) into the +target character-set (PETSCII, in this example) by the assembler. The +compiler-generated file <tt/hello.s/ does not contain any character constants, +so specification of a target is not necessary (it wouldn't do any harm, +however). + +If the assembler does not complain, we should now have two object files (named +<tt/hello.o/ and <tt/text.o/) in the current directory. + +For more information about the assembler, see <url url="ca65.html">. + + + +<sect>The linker<p> + +The linker combines several object and library files into one output file. +<bf/ld65/ is very configurable, but fortunately has built-in configurations, +so we don't need to mess with configuration files, here. + +The compiler uses small functions to do things that cannot be done inline +without a big impact on code size. Those runtime functions, together with the +C library, are in an object-file archive named after the system, in this case, +"<tt/c64.lib/". We have to specify that file on the command line, so that the +linker can resolve those functions. + +Let's link our files to get the final executable: + +<tscreen><verb> + ld65 -o hello -t c64 hello.o text.o c64.lib +</verb></tscreen> + +The argument after <tt/-o/ specifies the name of the output file, the argument +after <tt/-t/ gives the target system. The following arguments are object +files or libraries. Since the target library resolves imports in <tt/hello.o/ +and <tt/text.o/, it must be specified <em/after/ those files. + +After a successful linker run, we have a file named "<tt/hello/", ready for +our C64! + +For more information about the linker, see <url url="ld65.html">. + + + +<sect>The easy way (using the cl65 utility)<label id="using-cl65"><p> + +The <bf/cl65/ utility is able to do all of the steps described above, in just +one command line, and it has defaults for some options that are very +well-suited for our example. + +To compile both files into one executable, enter: + +<tscreen><verb> + cl65 -O hello.c text.s +</verb></tscreen> + +The <bf/cl65/ utility knows how to translate C files into object files (it will +call the compiler, and then the assembler). It does know also how to create +object files from assembly files (it will call only the assembler, for that). +It knows how to build an executable (it will pass all object files to the +linker). And finally, it has the C64 as a default target, and will supply the +correct startup file and runtime library names to the linker, so you don't +have to care about that. + +The one-liner above should give you a C64 executable named "<tt/hello/" in the +current directory. + +For more information about the compile & link utility, see <url +url="cl65.html">. + + + +<sect>Running The Executable<p> + +<em/Note: this section is incomplete!/ + +Depending on the target, cc65 chooses several methods of making a program +available for execution. Here, we list sample emulators and instructions for +running the program. Unless noted, similar instructions would also apply to a +real machine. One word of advice: we suggest you clear the screen at the +start, and wait for a keypress at the end of your program, as each target +varies in its start and exit conditions. + + +<sect1>Apple + +<sect2>AppleWin<p> +Available at <url +url="http://applewin.berlios.de/">: + +Emulates Apple ][/enhanced Apple //e computers, with +sound, video, joysticks, serial port, and disk images. Includes monitor. Only +for Windows. The package comes with a DOS 3.3 disk (called "master.dsk") image; +however, you will need <bf/AppleCommander 1.3.5/ or later (available at <url +url="http://applecommander.sourceforge.net/">). + +Compile the tutorial with + +<tscreen><verb> +cl65 -O -t apple2 hello.c text.s +</verb></tscreen> +for the Apple ][, or: +<tscreen><verb> +cl65 -O -t apple2enh hello.c text.s +</verb></tscreen> +for the enhanced Apple //e. + +Then, put the file onto an Apple disk image, for use with an emulator. Copy +the <tt/master.dsk/ which comes with <bf/AppleWin/, and rename it to +<tt/cc65.dsk/, then use <bf/AppleCommander/: + +<tscreen><verb> +java -jar ac.jar -cc65 cc65.dsk test B < hello +</verb></tscreen> + +Note that a convention in the Apple world is that "hello" is the file which is +run automatically upon booting a DOS disk, sort of like the "autoexec.bat" of +the MSDOS/Windows world. We've avoided that in the example, however. Also, +the <tt/B/ parameter must be in caps., and "test" is the name of the program as +it will appear on the Apple disk. + +Start the emulator, click on the <bf/Disk 1/ icon, and point to <bf/cc65.dsk/; +then, click the big Apple logo, to boot the system. Then, type this on the +Apple: + +<tscreen><verb> +BRUN TEST +</verb></tscreen> + +You will see "Hello, World!" appear on the same line. Thanks to +<url url="mailto:ol.sc@web.de" name="Oliver Schmidt"> for his help +in completing this section. + + +<sect1>Atari + +<sect2>Atari800Win PLus<p> +Available at <url +url="http://www.atari.org.pl/PLus/index_us.htm">: + +Emulates Atari 400/800/65XE/130XE/800XL/1200XL/5200, with stereo sound, disk +images, scanline-exact NTSC/PAL video, joysticks, mouse, cartridges, and RAM +expansions. Includes monitor. Unfortunately, only for Windows. You will need +the emulator, "atarixl.rom" or "atariosb.rom"/"ataribas.rom", and "dos25.xfd" +files (not supplied). + +Compile the tutorial with + +<tscreen><verb> +cl65 -O -t atari hello.c text.s +</verb></tscreen> + +Start the emulator, choose <bf/File>Autoboot image/ or <bf/File>Load +executable/, and point to the "<bf/hello/" executable. It is customary to +rename executables of that type to "<bf/hello.xex/". The file has a 7-byte +header meant to be loaded directly from Atari DOS 2/2.5 or compatibles. + +On a real Atari, you would need a disk drive, and Atari DOS 2.5 or compatible. +Turn on the computer, type + +<tscreen><verb> +DOS +</verb></tscreen> + +at the BASIC prompt, then choose <bf/N. CREATE MEM.SAV/, +then choose <bf/L. BINARY LOAD/, and enter <tt/HELLO/. + +The emulation, also, supports that method. Look at <bf/Atari>Settings/, and +check <bf/Enable H: Patch for Hard Disk Devices/, then <bf/Atari>Hard +disks/, and set the path of <bf/H1:/ to your executables directory, then use +"<bf/H0:HELLO.XEX/" in the above procedure (after pressing <tt/L/), to access +your harddrive directly. + +<em/Note:/ There is no delay after the program exits, as you are returned +to the DOS menu. Your C program should wait for a keypress if you want to see +any output. + + +<sect1>Atmos + +<sect2>Oricutron<p> +Available at <url +url="http://code.google.com/p/oriculator/">: + +Emulates Oric-1 and Atmos computers, with sound, disk images, +scanline-exact NTSC/PAL video, and movie export. Includes monitor. +Fortunately for all SDL platforms. You will just need the emulator, all +ROMs are supplied. + +Compile the tutorial with + +<tscreen><verb> +cl65 -O -t atmos hello.c text.s -o hello.tap +</verb></tscreen> + +Start the emulator, choose <bf/F1/ and <bf/Insert tape.../, and point to +the "<bf/hello.tap/" executable. The file has an auto start header meant to +be loaded directly from tape. + +On a real Atmos, you would need a tape drive. +Turn on the computer, type + +<tscreen><verb> +CLOAD"" +</verb></tscreen> + +at the BASIC prompt. + +The emulation, also, supports that method. + + +<sect1>Commodore + +<sect2>VICE<p> +Available at <url +url="http://vice-emu.sourceforge.net/">: + +Emulates Commodore 64/128/VIC-20/PET/CBM II/Plus 4 computers. Supports +printers, serial port and adapters, stereo sound, disk drives and images, RAM expansions, +cartridges, ethernet connection, cycle-exact NTSC/PAL video, mice, graphics tablet, +lightpens, and joysticks. Includes monitor. Runs on MSDOS/PCDOS, Win9x/ME/NT/2000/XP, OS2, +BeOS x86, Acorn RISC OS, and most Unixes. + +Compile the tutorial with +<tscreen><verb> +cl65 -O -t <sys> hello.c text.s +</verb></tscreen> +Substitute the name of a Commodore computer for that <tt/<sys>/: +<itemize> +<item><tt/c128/ +<item><tt/c16/ +<item><tt/c64/ +<item><tt/cbm510/ +<item><tt/cbm610/ +<item><tt/pet/ +<item><tt/plus4/ +<item><tt/vic20/ +</itemize> + +Start the desired version of the emulator (CBM610 programs run on +the CBM II [<tt/xcbm2/] emulator). + +In the Windows versions of VICE, choose <bf>File>Autoboot disk/tape +image...</bf>, choose your executable, and click <bf/OK/. + +In the Unix versions, hold down the mouse's first button. Move the pointer to +<bf>Smart-attach disk/tape...</bf>, and release the button. Choose your +executable, and click <bf/Autostart/. + +The file has a 14-byte header which corresponds to a PRG-format BASIC program, +consisting of a single line, similar to this: + +<tscreen><code> +1000 sys2061 +</code></tscreen> + +On a real Commodore with attached disk drive, you would type: + +<tscreen><verb> +LOAD "0:HELLO",8 +</verb></tscreen> + +for VIC-20/C64, or: + +<tscreen><verb> +DLOAD "HELLO" +</verb></tscreen> + +on PET/CBM II/C128/C16/Plus 4; then, type + +<tscreen><verb> +RUN +</verb></tscreen> + +On a Commodore 128, you can combine those two commands: +<tscreen><verb> +RUN "HELLO" +</verb></tscreen> + +The output will appear on a separate line, and you will be returned to a BASIC +prompt. + + +<sect1>GEOS<p> +Available at <it/Click Here Software's/ <url +url="http://cbmfiles.com/geos/index.html" name="GEOS download section">: + +<it><bf/G/raphics <bf/E/nvironment <bf/O/perating <bf/S/ystem.</it> +It provides a WIMP GUI (Windows, Icons, and Mouse-Pointer Graphical User +Interface) for Commodore's computer models <bf/64/ and <bf/128/. It can be +controlled by many different types of input devices: +<itemize> +<item>keyboard +<item>joysticks +<item>mice +<item>trackballs +<item>graphics drawing tablets +<item>light-pens +</itemize> + +The tutorial files are different for GEOS. You will find them "next door," in +"<tt>cc65/samples/geos</tt>"; they are called "<tt/hello1.c/" and +"<tt/hello1res.grc/". + +Compile the tutorial with +<tscreen><verb> +cl65 -t geos-cbm -O -o hello1 hello1res.grc hello1.c +</verb></tscreen> +Copy the resulting file "<tt/hello1/" onto a (GEOS-format) disk. + +Boot the GEOS master disk/image. + +<quote> +When you want to run GEOS in an emulator, you must adjust that emulator so that +it does a "true drive" emulation. Each emulator has its own way of turning that +feature on. +</quote> + +<quote> +VICE even has different ways that depend on which operating system is running +the emulator. +<itemize> +<item>In Windows, you must click on <bf/Options/ (in an always visible menu). + Then, you must click on <bf/True drive emulation/. +<item>In Unix, you must <em/hold down/ the second button on your mouse. Move + the pointer down to <bf/Drive settings/. Then, move the pointer over to + <bf/Enable true drive emulation/. (If there is a check-mark in front of + those words, that feature already is turned on -- then, move the pointer + off of that menu.) Release the mouse button. +</itemize> +</quote> + +Find the <bf/CONVERT/ program on the boot disk [tap the 6-key; then, you +should see its icon in the fourth position on the <bf/deskTop/'s directory +notePad]. Move GEOS's pointer over to <bf/CONVERT/'s icon; double-click +it to run that program. Click on the <bf/Disk/ icon; put the disk with +"<tt/hello1/" into the drive; and, click the <bf/OK/ icon. Use the little +icons under the list of file-names to move through that list until you find +"<tt/hello1/". Click on it; and then, click on the <bf/Convrt/ icon. +<bf/CONVERT/ will ask you to confirm that you choose the correct file; click +<bf/YES/ if you did (or, click <bf/NO/ if you made a mistake). After the +program has converted "<tt/hello1/" from a CBM file into a GEOS file, it will +announce what it did -- click on <bf/OK/. <bf/CONVERT/ will show the file list +again. This time, click on <bf/Quit/. + +(You might need to put the boot disk back into the drive, in order to reload +<bf/deskTop/. Then, you must swap back to the disk with the tutorial program +on it, and click on its disk icon [on the right side of the screen].) + +Now, you must find <bf/hello1/. Click on the lower left-hand corner of the +directory notePad. Look at the eight file-positions on each page until you see +<bf/hello1/. Double-click on its icon. + +The output is shown in a GEOS dialog box; click <bf/OK/ when you have finished +reading it. + + +<sect1>Contributions wanted<p> + +We need your help! Recommended emulators and instructions for other targets +are missing. We suggest that you choose emulators with good compatibility. +Also, being able to run all computers in the target series is good for +target compatibility testing. A machine-language monitor is almost essential +for debugging, but a native debugger could be used, as well. + +Finally, emulators which run on Unix or Windows would help to reach a wider +audience. + +</article> diff --git a/doc/ld65.sgml b/doc/ld65.sgml new file mode 100644 index 000000000..329f975e1 --- /dev/null +++ b/doc/ld65.sgml @@ -0,0 +1,1088 @@ +<!doctype linuxdoc system> <!-- -*- text-mode -*- --> + +<article> +<title>ld65 Users Guide +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2014-04-20 + +<abstract> +The ld65 linker combines object files into an executable file. ld65 is highly +configurable and uses configuration files for high flexibility. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +The ld65 linker combines several object modules created by the ca65 +assembler, producing an executable file. The object modules may be read +from a library created by the ar65 archiver (this is somewhat faster and +more convenient). The linker was designed to be as flexible as possible. +It complements the features that are built into the ca65 macroassembler: + +<itemize> + +<item> Accept any number of segments to form an executable module. + +<item> Resolve arbitrary expressions stored in the object files. + +<item> In case of errors, use the meta information stored in the object files + to produce helpful error messages. In case of undefined symbols, + expression range errors, or symbol type mismatches, ld65 is able to + tell you the exact location in the original assembler source, where + the symbol was referenced. + +<item> Flexible output. The output of ld65 is highly configurable by a config + file. Some more-common platforms are supported by default configurations + that may be activated by naming the target system. The output + generation was designed with different output formats in mind, so + adding other formats shouldn't be a great problem. + +</itemize> + + +<sect>Usage<p> + + +<sect1>Command-line option overview<p> + +The linker is called as follows: + +<tscreen><verb> +--------------------------------------------------------------------------- +Usage: ld65 [options] module ... +Short options: + -( Start a library group + -) End a library group + -C name Use linker config file + -D sym=val Define a symbol + -L path Specify a library search path + -Ln name Create a VICE label file + -S addr Set the default start address + -V Print the linker version + -h Help (this text) + -m name Create a map file + -o name Name the default output file + -t sys Set the target system + -u sym Force an import of symbol `sym' + -v Verbose mode + -vm Verbose map file + +Long options: + --cfg-path path Specify a config file search path + --config name Use linker config file + --dbgfile name Generate debug information + --define sym=val Define a symbol + --end-group End a library group + --force-import sym Force an import of symbol `sym' + --help Help (this text) + --lib file Link this library + --lib-path path Specify a library search path + --mapfile name Create a map file + --module-id id Specify a module id + --obj file Link this object file + --obj-path path Specify an object file search path + --start-addr addr Set the default start address + --start-group Start a library group + --target sys Set the target system + --version Print the linker version +--------------------------------------------------------------------------- +</verb></tscreen> + + +<sect1>Command-line options in detail<p> + +Here is a description of all of the command-line options: + +<descrip> + + <label id="option--start-group"> + <tag><tt>-(, --start-group</tt></tag> + + Start a library group. The libraries specified within a group are searched + multiple times to resolve crossreferences within the libraries. Normally, + crossreferences are resolved only within a library, that is the library is + searched multiple times. Libraries specified later on the command line + cannot reference otherwise unreferenced symbols in libraries specified + earlier, because the linker has already handled them. Library groups are + a solution for this problem, because the linker will search repeatedly + through all libraries specified in the group, until all possible open + symbol references have been satisfied. + + + <tag><tt>-), --end-group</tt></tag> + + End a library group. See the explanation of the <tt><ref + id="option--start-group" name="--start-group"></tt> option. + + + <tag><tt>-h, --help</tt></tag> + + Print the short option summary shown above. + + + <label id="option-m"> + <tag><tt>-m name, --mapfile name</tt></tag> + + This option (which needs an argument that will used as a filename for + the generated map file) will cause the linker to generate a map file. + The map file does contain a detailed overview over the modules used, the + sizes for the different segments, and a table containing exported + symbols. + + + <label id="option-o"> + <tag><tt>-o name</tt></tag> + + The -o switch is used to give the name of the default output file. + Depending on your output configuration, this name <em/might not/ be used as the + name for the output file. However, for the default configurations, this + name is used for the output file name. + + + <label id="option-t"> + <tag><tt>-t sys, --target sys</tt></tag> + + The argument for the -t switch is the name of the target system. Since this + switch will activate a default configuration, it may not be used together + with the <tt><ref id="option-C" name="-C"></tt> option. The following target + systems are currently supported: + + <itemize> + <item>none + <item>module + <item>apple2 + <item>apple2enh + <item>atari + <item>atarixl + <item>atmos + <item>c16 (works also for the c116 with memory up to 32K) + <item>c64 + <item>c128 + <item>cbm510 (CBM-II series with 40-column video) + <item>cbm610 (all CBM series-II computers with 80-column video) + <item>geos-apple + <item>geos-cbm + <item>lunix + <item>lynx + <item>nes + <item>pet (all CBM PET systems except the 2001) + <item>plus4 + <item>sim6502 + <item>sim65c02 + <item>supervision + <item>vic20 + </itemize> + + There are a few more targets defined but neither of them is actually + supported. + + + <tag><tt>-u sym[:addrsize], --force-import sym[:addrsize]</tt></tag> + + Force an import of a symbol. While object files are always linked to the + output file, regardless if there are any references, object modules from + libraries get only linked in if an import can be satisfied by this module. + The <tt/--force-import/ option may be used to add a reference to a symbol and + as a result force linkage of the module that exports the identifier. + + The name of the symbol may optionally be followed by a colon and an address-size + specifier. If no address size is specified, the default address size + for the target machine is used. + + Please note that the symbol name needs to have the internal representation, + meaning you have to prepend an underscore for C identifiers. + + + <label id="option-v"> + <tag><tt>-v, --verbose</tt></tag> + + Using the -v option, you may enable more output that may help you to + locate problems. If an undefined symbol is encountered, -v causes the + linker to print a detailed list of the references (that is, source file + and line) for this symbol. + + + <tag><tt>-vm</tt></tag> + + Must be used in conjunction with <tt><ref id="option-m" name="-m"></tt> + (generate map file). Normally the map file will not include empty segments + and sections, or unreferenced symbols. Using this option, you can force the + linker to include all that information into the map file. Also, it will + include a second <tt/Exports/ list. The first list is sorted by name; + the second one is sorted by value. + + + <label id="option-C"> + <tag><tt>-C</tt></tag> + + This gives the name of an output config file to use. See section 4 for more + information about config files. -C may not be used together with <tt><ref + id="option-t" name="-t"></tt>. + + + <label id="option-D"> + <tag><tt>-D sym=value, --define sym=value</tt></tag> + + This option allows to define an external symbol on the command line. Value + may start with a '$' sign or with <tt/0x/ for hexadecimal values, + otherwise a leading zero denotes octal values. See also <ref + id="SYMBOLS" name="the SYMBOLS section"> in the configuration file. + + + <label id="option--lib-path"> + <tag><tt>-L path, --lib-path path</tt></tag> + + Specify a library search path. This option may be used more than once. It + adds a directory to the search path for library files. Libraries specified + without a path are searched in the current directory, in the list of + directories specified using <tt/--lib-path/, in directories given by + environment variables, and in a built-in default directory. + + + <tag><tt>-Ln</tt></tag> + + This option allows you to create a file that contains all global labels and + may be loaded into the VICE emulator using the <tt/ll/ (load label) command. You + may use this to debug your code with VICE. Note: Older versions had some + bugs in the label code. If you have problems, please get the latest <url + url="http://vice-emu.sourceforge.net/" name="VICE"> version. + + + <label id="option-S"> + <tag><tt>-S addr, --start-addr addr</tt></tag> + + Using -S you may define the default starting address. If and how this + address is used depends on the config file in use. For the default + configurations, only the "none", "apple2" and "apple2enh" systems honor an + explicit start address, all other default configs provide their own. + + + <tag><tt>-V, --version</tt></tag> + + This option prints the version number of the linker. If you send any + suggestions or bugfixes, please include this number. + + + <label id="option--cfg-path"> + <tag><tt>--cfg-path path</tt></tag> + + Specify a config file search path. This option may be used more than once. + It adds a directory to the search path for config files. A config file given + with the <tt><ref id="option-C" name="-C"></tt> option that has no path in + its name is searched in the current directory, in the list of directories + specified using <tt/--cfg-path/, in directories given by environment variables, + and in a built-in default directory. + + + <label id="option--dbgfile"> + <tag><tt>--dbgfile name</tt></tag> + + Specify an output file for debug information. Available information will be + written to this file. Using the <tt/-g/ option for the compiler and assembler + will increase the amount of information available. Please note that debug + information generation is currently being developed, so the format of the + file and its contents are subject to change without further notice. + + + <tag><tt>--lib file</tt></tag> + + Links a library to the output. Use this command-line option instead of just + naming the library file, if the linker is not able to determine the file + type because of an unusual extension. + + + <tag><tt>--obj file</tt></tag> + + Links an object file to the output. Use this command-line option instead + of just naming the object file, if the linker is not able to determine the + file type because of an unusual extension. + + + <label id="option--obj-path"> + <tag><tt>--obj-path path</tt></tag> + + Specify an object file search path. This option may be used more than once. + It adds a directory to the search path for object files. An object file + passed to the linker that has no path in its name is searched in the current + directory, in the list of directories specified using <tt/--obj-path/, in + directories given by environment variables, and in a built-in default directory. + +</descrip> + + + +<sect>Search paths<p> + +Starting with version 2.10, there are now several search-path lists for files needed +by the linker: one for libraries, one for object files, and one for config +files. + + +<sect1>Library search path<p> + +The library search-path list contains in this order: + +<enum> +<item>The current directory. +<item>Any directory added with the <tt><ref id="option--lib-path" + name="--lib-path"></tt> option on the command line. +<item>The value of the environment variable <tt/LD65_LIB/ if it is defined. +<item>A subdirectory named <tt/lib/ of the directory defined in the environment + variable <tt/CC65_HOME/, if it is defined. +<item>An optionally compiled-in library path. +</enum> + + +<sect1>Object file search path<p> + +The object file search-path list contains in this order: + +<enum> +<item>The current directory. +<item>Any directory added with the <tt><ref id="option--obj-path" + name="--obj-path"></tt> option on the command line. +<item>The value of the environment variable <tt/LD65_OBJ/ if it is defined. +<item>A subdirectory named <tt/obj/ of the directory defined in the environment + variable <tt/CC65_HOME/, if it is defined. +<item>An optionally compiled-in directory. +</enum> + + +<sect1>Config file search path<p> + +The config file search-path list contains in this order: + +<enum> +<item>The current directory. +<item>Any directory added with the <tt><ref id="option--cfg-path" + name="--cfg-path"></tt> option on the command line. +<item>The value of the environment variable <tt/LD65_CFG/ if it is defined. +<item>A subdirectory named <tt/cfg/ of the directory defined in the environment + variable <tt/CC65_HOME/, if it is defined. +<item>An optionally compiled-in directory. +</enum> + + + +<sect>Detailed workings<p> + +The linker does several things when combining object modules: + +First, the command line is parsed from left to right. For each object file +encountered (object files are recognized by a magic word in the header, so +the linker does not care about the name), imported and exported +identifiers are read from the file and inserted in a table. If a library +name is given (libraries are also recognized by a magic word, there are no +special naming conventions), all modules in the library are checked if an +export from this module would satisfy an import from other modules. All +modules where this is the case are marked. If duplicate identifiers are +found, the linker issues warnings. + +That procedure (parsing and reading from left to right) does mean that a +library may only satisfy references for object modules (given directly or from +a library) named <em/before/ that library. With the command line + +<tscreen><verb> + ld65 crt0.o clib.lib test.o +</verb></tscreen> + +the module <tt/test.o/ must not contain references to modules in the library +<tt/clib.lib/. But, if it does, you have to change the order of the modules +on the command line: + +<tscreen><verb> + ld65 crt0.o test.o clib.lib +</verb></tscreen> + +Step two is, to read the configuration file, and assign start addresses +for the segments and define any linker symbols (see <ref id="config-files" +name="Configuration files">). + +After that, the linker is ready to produce an output file. Before doing that, +it checks its data for consistency. That is, it checks for unresolved +externals (if the output format is not relocatable) and for symbol type +mismatches (for example a zero-page symbol is imported by a module as an absolute +symbol). + +Step four is, to write the actual target files. In this step, the linker will +resolve any expressions contained in the segment data. Circular references are +also detected in this step (a symbol may have a circular reference that goes +unnoticed if the symbol is not used). + +Step five is to output a map file with a detailed list of all modules, +segments and symbols encountered. + +And, last step, if you give the <tt><ref id="option-v" name="-v"></tt> switch +twice, you get a dump of the segment data. However, this may be quite +unreadable if you're not a developer. :-) + + + +<sect>Configuration files<label id="config-files"><p> + +Configuration files are used to describe the layout of the output file(s). Two +major topics are covered in a config file: The memory layout of the target +architecture, and the assignment of segments to memory areas. In addition, +several other attributes may be specified. + +Case is ignored for keywords, that is, section or attribute names, but it is +<em/not/ ignored for names and strings. + + + +<sect1>Memory areas<p> + +Memory areas are specified in a <tt/MEMORY/ section. Let's have a look at an +example (this one describes the usable memory layout of the C64): + +<tscreen><verb> + MEMORY { + RAM1: start = $0800, size = $9800; + ROM1: start = $A000, size = $2000; + RAM2: start = $C000, size = $1000; + ROM2: start = $E000, size = $2000; + } +</verb></tscreen> + +As you can see, there are two RAM areas and two ROM areas. The names +(before the colon) are arbitrary names that must start with a letter, with +the remaining characters being letters or digits. The names of the memory +areas are used when assigning segments. As mentioned above, case is +significant for those names. + +The syntax above is used in all sections of the config file. The name +(<tt/ROM1/ etc.) is said to be an identifier, the remaining tokens up to the +semicolon specify attributes for this identifier. You may use the equal sign +to assign values to attributes, and you may use a comma to separate +attributes, you may also leave both out. But you <em/must/ use a semicolon to +mark the end of the attributes for one identifier. The section above may also +have looked like this: + +<tscreen><verb> + # Start of memory section + MEMORY + { + RAM1: + start $0800 + size $9800; + ROM1: + start $A000 + size $2000; + RAM2: + start $C000 + size $1000; + ROM2: + start $E000 + size $2000; + } +</verb></tscreen> + +There are of course more attributes for a memory section than just start and +size. Start and size are mandatory attributes, that means, each memory area +defined <em/must/ have these attributes given (the linker will check that). I +will cover other attributes later. As you may have noticed, I've used a +comment in the example above. Comments start with a hash mark (`#'), the +remainder of the line is ignored if this character is found. + + +<sect1>Segments<p> + +Let's assume you have written a program for your trusty old C64, and you would +like to run it. For testing purposes, it should run in the <tt/RAM/ area. So +we will start to assign segments to memory sections in the <tt/SEGMENTS/ +section: + +<tscreen><verb> + SEGMENTS { + CODE: load = RAM1, type = ro; + RODATA: load = RAM1, type = ro; + DATA: load = RAM1, type = rw; + BSS: load = RAM1, type = bss, define = yes; + } +</verb></tscreen> + +What we are doing here is telling the linker, that all segments go into the +<tt/RAM1/ memory area in the order specified in the <tt/SEGMENTS/ section. So +the linker will first write the <tt/CODE/ segment, then the <tt/RODATA/ +segment, then the <tt/DATA/ segment - but it will not write the <tt/BSS/ +segment. Why? Here enters the segment type: For each segment specified, you may also +specify a segment attribute. There are four possible segment attributes: + +<tscreen><verb> + ro means readonly + rw means read/write + bss means that this is an uninitialized segment + zp a zeropage segment +</verb></tscreen> + +So, because we specified that the segment with the name BSS is of type bss, +the linker knows that this is uninitialized data, and will not write it to an +output file. This is an important point: For the assembler, the <tt/BSS/ +segment has no special meaning. You specify, which segments have the bss +attribute when linking. This approach is much more flexible than having one +fixed bss segment, and is a result of the design decision to supporting an +arbitrary segment count. + +If you specify "<tt/type = bss/" for a segment, the linker will make sure that +this segment does only contain uninitialized data (that is, zeroes), and issue +a warning if this is not the case. + +For a <tt/bss/ type segment to be useful, it must be cleared somehow by your +program (this happens usually in the startup code - for example the startup +code for cc65-generated programs takes care about that). But how does your +code know, where the segment starts, and how big it is? The linker is able to +give that information, but you must request it. This is, what we're doing with +the "<tt/define = yes/" attribute in the <tt/BSS/ definitions. For each +segment, where this attribute is true, the linker will export three symbols. + +<tscreen><verb> + __NAME_LOAD__ This is set to the address where the + segment is loaded. + __NAME_RUN__ This is set to the run address of the + segment. We will cover run addresses + later. + __NAME_SIZE__ This is set to the segment size. +</verb></tscreen> + +Replace <tt/NAME/ by the name of the segment, in the example above, this would +be <tt/BSS/. These symbols may be accessed by your code. + +Now, as we've configured the linker to write the first three segments and +create symbols for the last one, there's only one question left: Where does +the linker put the data? It would be very convenient to have the data in a +file, wouldn't it? + +<sect1>Output files<p> + +We don't have any files specified above, and indeed, this is not needed in a +simple configuration like the one above. There is an additional attribute +"file" that may be specified for a memory area, that gives a file name to +write the area data into. If there is no file name given, the linker will +assign the default file name. This is "a.out" or the one given with the +<tt><ref id="option-o" name="-o"></tt> option on the command line. Since the +default behaviour is OK for our purposes, I did not use the attribute in the +example above. Let's have a look at it now. + +The "file" attribute (the keyword may also be written as "FILE" if you like +that better) takes a string enclosed in double quotes (`&dquot;') that specifies the +file, where the data is written. You may specify the same file several times, +in that case the data for all memory areas having this file name is written +into this file, in the order of the memory areas defined in the <tt/MEMORY/ +section. Let's specify some file names in the <tt/MEMORY/ section used above: + +<tscreen><verb> + MEMORY { + RAM1: start = $0800, size = $9800, file = %O; + ROM1: start = $A000, size = $2000, file = "rom1.bin"; + RAM2: start = $C000, size = $1000, file = %O; + ROM2: start = $E000, size = $2000, file = "rom2.bin"; + } +</verb></tscreen> + +The <tt/%O/ used here is a way to specify the default behaviour explicitly: +<tt/%O/ is replaced by a string (including the quotes) that contains the +default output name, that is, "a.out" or the name specified with the <tt><ref +id="option-o" name="-o"></tt> option on the command line. Into this file, the +linker will first write any segments that go into <tt/RAM1/, and will append +then the segments for <tt/RAM2/, because the memory areas are given in this +order. So, for the RAM areas, nothing has really changed. + +We've not used the ROM areas, but we will do that below, so we give the file +names here. Segments that go into <tt/ROM1/ will be written to a file named +"rom1.bin", and segments that go into <tt/ROM2/ will be written to a file +named "rom2.bin". The name given on the command line is ignored in both cases. + +Assigning an empty file name for a memory area will discard the data written +to it. This is useful, if the memory area has segments assigned that are empty +(for example because they are of type bss). In that case, the linker will +create an empty output file. This may be suppressed by assigning an empty file +name to that memory area. + +The <tt/%O/ sequence is also allowed inside a string. So using + +<tscreen><verb> + MEMORY { + ROM1: start = $A000, size = $2000, file = "%O-1.bin"; + ROM2: start = $E000, size = $2000, file = "%O-2.bin"; + } +</verb></tscreen> + +would write two files that start with the name of the output file specified on +the command line, with "-1.bin" and "-2.bin" appended respectively. Because +'%' is used as an escape char, the sequence "%%" has to be used if a single +percent sign is required. + +<sect1>LOAD and RUN addresses (ROMable code)<p> + +Let us look now at a more complex example. Say, you've successfully tested +your new "Super Operating System" (SOS for short) for the C64, and you +will now go and replace the ROMs by your own code. When doing that, you +face a new problem: If the code runs in RAM, we need not to care about +read/write data. But now, if the code is in ROM, we must care about it. +Remember the default segments (you may of course specify your own): + +<tscreen><verb> + CODE read-only code + RODATA read-only data + DATA read/write data + BSS uninitialized data, read/write +</verb></tscreen> + +Since <tt/BSS/ is not initialized, we must not care about it now, but what +about <tt/DATA/? <tt/DATA/ contains initialized data, that is, data that was +explicitly assigned a value. And your program will rely on these values on +startup. Since there's no way to remember the contents of the data segment, +other than storing it into one of the ROMs, we have to put it there. But +unfortunately, ROM is not writable, so we have to copy it into RAM before +running the actual code. + +The linker won't copy the data from ROM into RAM for you (this must be done by +the startup code of your program), but it has some features that will help you +in this process. + +First, you may not only specify a "<tt/load/" attribute for a segment, but +also a "<tt/run/" attribute. The "<tt/load/" attribute is mandatory, and, if +you don't specify a "<tt/run/" attribute, the linker assumes that load area +and run area are the same. We will use this feature for our data area: + +<tscreen><verb> + SEGMENTS { + CODE: load = ROM1, type = ro; + RODATA: load = ROM2, type = ro; + DATA: load = ROM2, run = RAM2, type = rw, define = yes; + BSS: load = RAM2, type = bss, define = yes; + } +</verb></tscreen> + +Let's have a closer look at this <tt/SEGMENTS/ section. We specify that the +<tt/CODE/ segment goes into <tt/ROM1/ (the one at $A000). The readonly data +goes into <tt/ROM2/. Read/write data will be loaded into <tt/ROM2/ but is run +in <tt/RAM2/. That means that all references to labels in the <tt/DATA/ +segment are relocated to be in <tt/RAM2/, but the segment is written to +<tt/ROM2/. All your startup code has to do is, to copy the data from its +location in <tt/ROM2/ to the final location in <tt/RAM2/. + +So, how do you know, where the data is located? This is the second point, +where you get help from the linker. Remember the "<tt/define/" attribute? +Since we have set this attribute to true, the linker will define three +external symbols for the data segment that may be accessed from your code: + +<tscreen><verb> + __DATA_LOAD__ This is set to the address where the segment + is loaded, in this case, it is an address in + ROM2. + __DATA_RUN__ This is set to the run address of the segment, + in this case, it is an address in RAM2. + __DATA_SIZE__ This is set to the segment size. +</verb></tscreen> + +So, what your startup code must do, is to copy <tt/__DATA_SIZE__/ bytes from +<tt/__DATA_LOAD__/ to <tt/__DATA_RUN__/ before any other routines are called. +All references to labels in the <tt/DATA/ segment are relocated to <tt/RAM2/ +by the linker, so things will work properly. + +There's a library subroutine called <tt/copydata/ (in a module named +<tt/copydata.s/) that might be used to do actual copying. Be sure to have a +look at it's inner workings before using it! + + +<sect1>Other MEMORY area attributes<p> + +There are some other attributes not covered above. Before starting the +reference section, I will discuss the remaining things here. + +You may request symbols definitions also for memory areas. This may be +useful for things like a software stack, or an I/O area. + +<tscreen><verb> + MEMORY { + STACK: start = $C000, size = $1000, define = yes; + } +</verb></tscreen> + +This will define some external symbols that may be used in your code: + +<tscreen><verb> + __STACK_START__ This is set to the start of the memory + area, $C000 in this example. + __STACK_SIZE__ The size of the area, here $1000. + __STACK_LAST__ This is NOT the same as START+SIZE. + Instead, it is defined as the first + address that is not used by data. If we + don't define any segments for this area, + the value will be the same as START. + __STACK_FILEOFFS__ The binary offset in the output file. This + is not defined for relocatable output file + formats (o65). +</verb></tscreen> + +A memory section may also have a type. Valid types are + +<tscreen><verb> + ro for readonly memory + rw for read/write memory. +</verb></tscreen> + +The linker will assure, that no segment marked as read/write or bss is put +into a memory area that is marked as readonly. + +Unused memory in a memory area may be filled. Use the "<tt/fill = yes/" +attribute to request this. The default value to fill unused space is zero. If +you don't like this, you may specify a byte value that is used to fill these +areas with the "<tt/fillval/" attribute. If there is no "<tt/fillval/" +attribute for the segment, the "<tt/fillval/" attribute of the memory area (or +its default) is used instead. This means that the value may also be used to +fill unfilled areas generated by the assembler's <tt/.ALIGN/ and <tt/.RES/ +directives. + +The symbol <tt/%S/ may be used to access the default start address (that is, +the one defined in <ref id="FEATURES" name="the FEATURES section">, or the +value given on the command line with the <tt><ref id="option-S" name="-S"></tt> +option). + +To support systems with banked memory, a special attribute named <tt/bank/ is +available. The attribute value is an arbitrary 32-bit integer. The assembler +has a builtin function named <tt/.BANK/ which may be used with an argument +that has a segment reference (for example a symbol). The result of this +function is the value of the bank attribute for the run memory area of the +segment. + + +<sect1>Other SEGMENT attributes<p> + +Segments may be aligned to some memory boundary. Specify "<tt/align = num/" to +request this feature. Num must be a power of two. To align all segments on a +page boundary, use + +<tscreen><verb> + SEGMENTS { + CODE: load = ROM1, type = ro, align = $100; + RODATA: load = ROM2, type = ro, align = $100; + DATA: load = ROM2, run = RAM2, type = rw, define = yes, + align = $100; + BSS: load = RAM2, type = bss, define = yes, align = $100; + } +</verb></tscreen> + +If an alignment is requested, the linker will add enough space to the output +file, so that the new segment starts at an address that is dividable by the +given number without a remainder. All addresses are adjusted accordingly. To +fill the unused space, bytes of zero are used, or, if the memory area has a +"<tt/fillval/" attribute, that value. Alignment is always needed, if you have +used the <tt/.ALIGN/ command in the assembler. The alignment of a segment +must be equal or greater than the alignment used in the <tt/.ALIGN/ command. +The linker will check that, and issue a warning, if the alignment of a segment +is lower than the alignment requested in an <tt/.ALIGN/ command of one of the +modules making up this segment. + +For a given segment you may also specify a fixed offset into a memory area or +a fixed start address. Use this if you want the code to run at a specific +address (a prominent case is the interrupt vector table which must go at +address $FFFA). Only one of <tt/ALIGN/ or <tt/OFFSET/ or <tt/START/ may be +specified. If the directive creates empty space, it will be filled with zero, +of with the value specified with the "<tt/fillval/" attribute if one is given. +The linker will warn you if it is not possible to put the code at the +specified offset (this may happen if other segments in this area are too +large). Here's an example: + +<tscreen><verb> + SEGMENTS { + VECTORS: load = ROM2, type = ro, start = $FFFA; + } +</verb></tscreen> + +or (for the segment definitions from above) + +<tscreen><verb> + SEGMENTS { + VECTORS: load = ROM2, type = ro, offset = $1FFA; + } +</verb></tscreen> + +The "<tt/align/", "<tt/start/" and "<tt/offset/" attributes change placement +of the segment in the run memory area, because this is what is usually +desired. If load and run memory areas are equal (which is the case if only the +load memory area has been specified), the attributes will also work. There is +also an "<tt/align_load/" attribute that may be used to align the start of the +segment in the load memory area, in case different load and run areas have +been specified. There are no special attributes to set start or offset for +just the load memory area. + +A "<tt/fillval/" attribute may not only be specified for a memory area, but +also for a segment. The value must be an integer between 0 and 255. It is used +as the fill value for space reserved by the assembler's <tt/.ALIGN/ and <tt/.RES/ +commands. It is also used as the fill value for space between sections (part of a +segment that comes from one object file) caused by alignment, but not for +space that preceeds the first section. + +To suppress the warning, the linker issues if it encounters a segment that is +not found in any of the input files, use "<tt/optional=yes/" as an additional +segment attribute. Be careful when using this attribute, because a missing +segment may be a sign of a problem, and if you're suppressing the warning, +there is no one left to tell you about it. + +<sect1>The FILES section<p> + +The <tt/FILES/ section is used to support other formats than straight binary +(which is the default, so binary output files do not need an explicit entry +in the <tt/FILES/ section). + +The <tt/FILES/ section lists output files and as only attribute the format of +each output file. Assigning binary format to the default output file would +look like this: + +<tscreen><verb> + FILES { + %O: format = bin; + } +</verb></tscreen> + +The only other available output format is the o65 format specified by Andre +Fachat (see the <url url="http://www.6502.org/users/andre/o65/fileformat.html" +name="6502 binary relocation format specification">). It is defined like this: + +<tscreen><verb> + FILES { + %O: format = o65; + } +</verb></tscreen> + +The necessary o65 attributes are defined in a special section labeled +<ref id="FORMAT" name="FORMAT">. + + + +<sect1>The FORMAT section<label id="FORMAT"><p> + +The <tt/FORMAT/ section is used to describe file formats. The default (binary) +format has currently no attributes, so, while it may be listed in this +section, the attribute list is empty. The second supported format, +<url url="http://www.6502.org/users/andre/o65/fileformat.html" name="o65">, +has several attributes that may be defined here. + +<tscreen><verb> + FORMATS { + o65: os = lunix, version = 0, type = small, + import = LUNIXKERNEL, + export = _main; + } +</verb></tscreen> + + + +<sect1>The FEATURES section<label id="FEATURES"><p> + +In addition to the <tt/MEMORY/ and <tt/SEGMENTS/ sections described above, the +linker has features that may be enabled by an additional section labeled +<tt/FEATURES/. + + +<sect2>The CONDES feature<p> + +<tt/CONDES/ is used to tell the linker to emit module constructor/destructor +tables. + +<tscreen><verb> + FEATURES { + CONDES: segment = RODATA, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + } +</verb></tscreen> + +The <tt/CONDES/ feature has several attributes: + +<descrip> + + <tag><tt>segment</tt></tag> + + This attribute tells the linker into which segment the table should be + placed. If the segment does not exist, it is created. + + + <tag><tt>type</tt></tag> + + Describes the type of the routines to place in the table. Type may be one of + the predefined types <tt/constructor/, <tt/destructor/, <tt/interruptor/, or + a numeric value between 0 and 6. + + + <tag><tt>label</tt></tag> + + This specifies the label to use for the table. The label points to the start + of the table in memory and may be used from within user-written code. + + + <tag><tt>count</tt></tag> + + This is an optional attribute. If specified, an additional symbol is defined + by the linker using the given name. The value of this symbol is the number + of entries (<em/not/ bytes) in the table. While this attribute is optional, + it is often useful to define it. + + + <tag><tt>order</tt></tag> + + An optional attribute that takes one of the keywords <tt/increasing/ or + <tt/decreasing/ as an argument. Specifies the sorting order of the entries + within the table. The default is <tt/increasing/, which means that the + entries are sorted with increasing priority (the first entry has the lowest + priority). "Priority" is the priority specified when declaring a symbol as + <tt/.CONDES/ with the assembler, higher values mean higher priority. You may + change this behaviour by specifying <tt/decreasing/ as the argument, the + order of entries is reversed in this case. + + Please note that the order of entries with equal priority is undefined. + + <tag><tt>import</tt></tag> + + This attribute defines a valid symbol name, that is added as an import + to the modules defining a constructor/destructor of the given type. + This can be used to force linkage of a module if this module exports the + requested symbol. + +</descrip> + +Without specifying the <tt/CONDES/ feature, the linker will not create any +tables, even if there are <tt/condes/ entries in the object files. + +For more information see the <tt/.CONDES/ command in the <url +url="ca65.html" name="ca65 manual">. + + +<sect2>The STARTADDRESS feature<p> + +<tt/STARTADDRESS/ is used to set the default value for the start address, +which can be referenced by the <tt/%S/ symbol. The builtin default for the +linker is $200. + +<tscreen><verb> + FEATURES { + # Default start address is $1000 + STARTADDRESS: default = $1000; + } +</verb></tscreen> + +Please note that order is important: The default start address must be defined +<em/before/ the <tt/%S/ symbol is used in the config file. This does usually +mean, that the <tt/FEATURES/ section has to go to the top of the config file. + + + +<sect1>The SYMBOLS section<label id="SYMBOLS"><p> + +The configuration file may also be used to define symbols used in the link +stage or to force symbols imports. This is done in the SYMBOLS section. The +symbol name is followed by a colon and symbol attributes. + +The following symbol attributes are supported: + +<descrip> + + <tag><tt>addrsize</tt></tag> + + The <tt/addrsize/ attribute specifies the address size of the symbol and + may be one of +<itemize> + <item><tt/zp/, <tt/zeropage/ or <tt/direct/ + <item><tt/abs/, <tt/absolute/ or <tt/near/ + <item><tt/far/ + <item><tt/long/ or <tt/dword/. +</itemize> + +Without this attribute, the default address size is <tt/abs/. + + <tag><tt>type</tt></tag> + + This attribute is mandatory. Its value is one of <tt/export/, <tt/import/ or + <tt/weak/. <tt/export/ means that the symbol is defined and exported from + the linker config. <tt/import/ means that an import is generated for this + symbol, eventually forcing a module that exports this symbol to be included + in the output. <tt/weak/ is similar as <tt/export/. However, the symbol is + only defined if it is not defined elsewhere. + + <tag><tt>value</tt></tag> + + This must only be given for symbols of type <tt/export/ or <tt/weak/. It + defines the value of the symbol and may be an expression. + +</descrip> + +The following example defines the stack size for an application, but allows +the programmer to override the value by specifying <tt/--define +__STACKSIZE__=xxx/ on the command line. + +<tscreen><verb> + SYMBOLS { + # Define the stack size for the application + __STACKSIZE__: type = weak, value = $800; + } +</verb></tscreen> + + + +<sect>Special segments<p> + +The builtin config files do contain segments that have a special meaning for +the compiler and the libraries that come with it. If you replace the builtin +config files, you will need the following information. + +<sect1>INIT<p> + +The INIT segment is used for initialization code that may be reused once +execution reaches main() - provided that the program runs in RAM. You +may for example add the INIT segment to the heap in really memory +constrained systems. + +<sect1>LOWCODE<p> + +For the LOWCODE segment, it is guaranteed that it won't be banked out, so it +is reachable at any time by interrupt handlers or similar. + +<sect1>STARTUP<p> + +This segment contains the startup code which initializes the C software stack +and the libraries. It is placed in its own segment because it needs to be +loaded at the lowest possible program address on several platforms. + +<sect1>ZPSAVE<p> + +The ZPSAVE segment contains the original values of the zeropage locations used +by the ZEROPAGE segment. It is placed in its own segment because it must not be +initialized. + + + +<sect>Copyright<p> + +ld65 (and all cc65 binutils) are (C) Copyright 1998-2005 Ullrich von +Bassewitz. For usage of the binaries and/or sources the following +conditions do apply: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + + + +</article> diff --git a/doc/library.sgml b/doc/library.sgml new file mode 100644 index 000000000..9b923c308 --- /dev/null +++ b/doc/library.sgml @@ -0,0 +1,240 @@ +<!doctype linuxdoc system> + +<article> + +<title>cc65 Library Overview +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2014-04-12 + +<abstract> +An overview over the runtime and C libraries that come with the cc65 compiler, +including a discussion of the differences to the ISO standard. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains a short overview of the libraries available for the cc65 C +compiler. Please have a look at the <url url="funcref.html" name="function +reference"> for a list function by function. Since the function reference is +not complete (I'm working on that) it may happen that you don't find a +specific function. In this case, have a look into the header files. All +functions, that are not defined by the ISO C standard have a short comment in +the headers, explaining their use. + + + +<sect>ISO C compatible library<p> + +The C library contains a large subset of the ISO C library. Functions are +usually missing in areas, where there is no support on typical 6502 systems. +Wide character sets are an example for this. + +I will not go into detail about the ISO functions. If a function is not +mentioned here explicitly, expect it to be available and to behave as defined +in the C standard. + +Functions that are <em/not/ available: + +<itemize> + <item><tt>tmpfile/tmpnam</tt> + <p> + <item><tt>system</tt> + <p> + <item>All functions that handle floating point numbers in some manner. + <p> + <item>The <tt/ldiv/ function (cc65 is currently not able to return structs + with a size not equal to 1, 2 or 4 bytes by value). + <p> + <item>All functions handling wide character strings. + <p> + <item>Signals and all related functions (having <tt/SIGSEGV/ would be + cool:-) + <p> + <item><tt>setbuf/setvbuf</tt> +</itemize> + +Functions not available on all supported systems: + +<itemize> + <item><tt>fopen/fread/fwrite/fclose/fputs/fgets/fscanf</tt>: The functions + are built on open/read/write/close. These latter functions are not available + on all systems. + <p> + <item><tt>ftell/fseek/fgetpos/fsetpos</tt>: Support depends on the + capabilities of the target machine. + <p> + <item><tt>rename/remove/rewind</tt>: Support depends on the capabilities of + the target machine. + <p> + <item><tt>time</tt>: Since many of the supported systems do not have a real + time clock, which means that the <tt/time/ function is not available. Please + note that the other functions from <tt/time.h/ <em/are/ available. +</itemize> + + +Functions that are limited in any way: + +<itemize> + <item><tt>strcspn/strpbrk/strspn</tt>: These functions have a length + limitation of 256 for the second string argument. Since this string gives a + character set, and there are only 256 distinct characters, this shouldn't be + a problem. + <p> + <item><tt>getenv</tt>: Since there is no such thing as an environment on all + supported systems, the <tt/getenv/ function will always return a <tt/NULL/ + pointer. + <p> + <item><tt>locale</tt>: There is no other locale than the "C" locale. The + native locale is identical to the "C" locale. +</itemize> + + +In addition to these limitations, some more functions are limited if inlined +versions are requested by using -Os: + +<itemize> + <item>The <tt/strlen/ function only works for strings with a maximum length + of 255 characters. + <p> + <item>The <tt/isxxx/ character classification functions from + <tt/<ctype.h>/ will give unpredictable results if the argument is not + in character range (0..255). This limitation may be removed by #undef'ing + the function name (when using <tt/-Os/, the functions are actually macros + that expand to inline assembler code, but the real functions are still + available if the macro definition is removed). +</itemize> + + + +<sect>CPU specific stuff - 6502.h<p> + +The header file 6502.h contains some functions that make only sense with the +6502 CPU. Examples are macros to insert more or less useful instructions into +your C code, or a function to call arbitrary machine language subroutines, +passing registers in and out. + + + +<sect>Target specific stuff<p> + +For each supported system there's a header file that contains calls or defines +specific for this system. So, when programming for the C64, include c64.h, for +the C128, include c128.h and so on. To make the task for the Commodore systems +easier, there is also a header file named cbm.h that will define stuff common +for all CBM systems, and include the header file for the specific target +system. + +The header files contain + +<itemize> + + <item>Defines for special keys (like function keys) + + <item>Defines for special characters (like the graphics characters) + + <item>Variables with a fixed address in memory that may be used to access + special hardware. For the C64 and C128 there is a variable struct named + <tt/SID/. Writing to the fields of this struct will write to the SID device + instead. Using these variables will make your program more readable and more + portable. Don't fear ineffective code when using these variables, the + compiler will translate reads and writes to these structs into direct memory + accesses. + + <item>Other routines that make only sense for a specific system. One example + are routines to write memory locations in the system bank for the CBM PET-II + family. + +</itemize> + + +<sect>Direct console I/O - <tt/conio.h/<p> + +The <tt/conio.h/ header file contains a large set of functions that do screen +and keyboard I/O. The functions will write directly to the screen or poll the +keyboard directly with no more help from the operating system than needed. +This has some disadvantages, but on the other side it's fast and reasonably +portable. conio implementations exist for the following targets: + + <itemize> + <item>apple2 + <item>apple2enh + <item>atari + <item>atarixl + <item>atmos + <item>c16 (works also for the c116 with up to 32K memory) + <item>c64 + <item>c128 + <item>plus4 (or expanded c16/c116) + <item>cbm510 (40 column video) + <item>cbm610 (all CBM series-II computers with 80 column video) + <item>geos-apple + <item>geos-cbm + <item>nes + <item>pet (all CBM PET systems except the 2001) + <item>vic20 + </itemize> + +The conio.h header file does also include the system specific header files +which define constants for special characters and keys. + + + +<sect>Using the joystick - <tt/joystick.h/<p> + +For systems that have a joystick, <tt/joystick.h/ will define a subroutine to +read the current value, including constants to evaluate the result of this +function. + + + +<sect>Using a mouse - <tt/mouse.h/<p> + +Some target machines support a mouse. Mouse support is currently available for +the following targets: + + <itemize> + <item>apple2 + <item>apple2enh + <item>atari + <item>atarixl + <item>c64 + <item>c128 + </itemize> + +The available functions are declared in <tt/mouse.h/. + + +<sect>Copyright<p> + +This C runtime library implementation for the cc65 compiler is (C) +Copyright 1998-2002 Ullrich von Bassewitz. For usage of the binaries +and/or sources the following conditions do apply: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> + + + diff --git a/doc/lynx.sgml b/doc/lynx.sgml new file mode 100644 index 000000000..73763f1dd --- /dev/null +++ b/doc/lynx.sgml @@ -0,0 +1,352 @@ +<!doctype linuxdoc system> + +<article> + +<title>Atari Lynx specific information for cc65 +<author> +<url url="mailto:karri@sipo.fi" name="Karri Kaksonen">,<newline> +<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2014-04-12 + +<abstract> +An overview over the Atari Lynx runtime system as it is implemented for the +cc65 C compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the Atari Lynx runtime system as it comes +with the cc65 C compiler. It describes the memory layout, Lynx specific header +files, available drivers, and any pitfalls specific to that platform. + +Please note that Lynx specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + + +<sect>Building your first Hello World application<p> + +Here is a small traditional Hello World program for the Atari Lynx. + +<tscreen><verb> +#include <lynx.h> +#include <tgi.h> +#include <6502.h> + +void main(void) { + tgi_install(tgi_static_stddrv); + tgi_init(); + CLI(); + while (tgi_busy()) + ; + tgi_clear(); + tgi_setcolor(COLOR_GREEN); + tgi_outtextxy(0, 0, "Hello World"); + tgi_updatedisplay(); + while (1) + ; +} +</verb></tscreen> + +The lynx.h contains all kind of system dependent things. + +The tgi.h contains the graphics driver functions. + +The 6502.h is needed for executing the CLI() command. + +As the Atari Lynx does not have ASCII characters available you need to use +the Tiny Graphics Interface library for producing letters on the screen. + +The cc65 compiler suite has a graphics library called "Tiny Graphics +Interface". This interface has some relocatable code. In order to use this +in your own program you need to load it at run time. + +Unfortunately the Lynx does not have a disk drive from where to load it. +Therefore you must already load it at compile time. The easiest way is to +automatically link it in statically from the Lynx C library. + +<tscreen><verb> +cl65 -t lynx -o game.lnx main.c +</verb></tscreen> + +This will create a bootable cart image called game.lnx + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the Lynx target +is a cart image. By specifying the config file lynx-bll.cfg the linker will +generate BLL download compatible binary files. + +It is of course possible to change this behaviour by using a modified startup +file and linker config. + +The bootloader used in the cc65 lynx library uses a very minimal bootloader +that does not check the cart or show a title screen. + +The advantage of this bootloader is that it allows creation of cart images to +many common formats. + +Cart sizes +<tscreen><verb> +Block size Rom size Description +512 bytes 128k Standard old games like Warbirds +1024 bytes 256k Most common format for homebrew. Also newer games like Lemmings +2048 bytes 512k Largest games like EOTB +</verb></tscreen> + +<sect>Memory layout<p> + +cc65 generated programs with the default setup run with the I/O area and the +kernal enabled, which gives a usable memory range of $200 - $C037. + +Special locations: +<tscreen><verb> + 0000 - 00FF Zero page + 0100 - 01FF Machine stack + + A058 - C037 Collision buffer + C038 - E017 Screen buffer 1 + E018 - FFF7 Screen buffer 0 + FFF8 - FFFF Hardware vectors +</verb></tscreen> + +<descrip> + <tag/Text screen/ + No conio support is currently available for the Lynx. + + <tag/Keyboard/ + The Lynx "flabode" keys, Opt 1, Pause and Opt 2 are implemented using the + conio interface. The only characters the keyboard is able to produce are + 'R' for Restart (Opt 1 + Pause), 'F' for flip (Opt 2 + Pause), + 'P' for pause, '1' for Opt 1, '2' for Opt 2, '3' for Opt 1 + Opt 2 and + '?' for all keys down at the same time. + + <tag/Stack/ + The C runtime stack is located at $C037 (or $A057 if collision + detection is enabled) and growing downwards. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + + <tag/Screen/ + The collision detection screen is at $A058 if it is enabled. The + double buffered screens are at $C038 and $E018. + +</descrip><p> + + + +<sect>Platform specific header files<p> + +Programs containing Lynx specific code may use the <tt/lynx.h/ header file. + + +<sect1>Lynx specific functions<p> + +<itemize> +<item>lynx_eeprom_erase +<item>lynx_eeprom_read +<item>lynx_eeprom_write +<item>lynx_eeread +<item>lynx_eewrite +<item>lynx_exec +<item>lynx_load +</itemize> + + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/lynx.h/ header file do +allow access to hardware located in the address space. Some variables are +structures, accessing the struct fields will access the chip registers. + +<descrip> + + <tag><tt/MIKEY/</tag> + The <tt/MIKEY/ structure allows access to MIKEY chip. See the <tt/_mikey.h/ + header file located in the include directory for the declaration of the + structure. + + <tag><tt/SUZY/</tag> + The <tt/SUZY/ structure allows access to SUZY chip. See the <tt/_suzy.h/ + header file located in the include directory for the declaration of the + structure. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +<descrip> + + <tag><tt/lynx-160-102-16.tgi (lynx_160_102_16_tgi)/</tag> + A TGI driver for the standard graphics mode (160×102 in 16 colors). + + The TGI driver is implemented as an interrupt driven dual buffering device. + To use it as a single-buffer device set draw page and view page to the same + value 0 or 1; + + The TGI driver has a few Lynx-specific extensions. + + Calling tgi_sprite(spr) or tgi_ioctl(0, spr) will display a standard Lynx + sprite on screen. + + Calling tgi_flip() or tgi_ioctl(1, 0) will do a flip screen. + + Calling tgi_setbgcolor(bgcolor) or tgi_ioctl(2, bgindex) will set the text + background color to the index defined by bgindex. If bgindex is 0 then the + background color is transparent. + + To set the framerate of the display hardware call tgi_setframerate(rate) or + tgi_ioctl(3, rate). The supported framerates are 50, 60 and 75 frames per + second. Actually there is no real reason to use anything else than 75 frames + per second. + + To check if the drawing engine is busy with the previous swap you can + call tgi_busy or tgi_ioctl(4, 0). It returns 0 if idle and 1 if busy + + To update displays you can call tgi_updatedisplay() or tgi_ioctl(4, 1) it + will wait for the next VBL interrupt and set the draw buffer to the + view buffer. The draw buffer is also changed to (drawbuffer xor 1). + + You can also enable or disable collision detection by a call to + tgi_setcollisiondetection(active) or tgi_ioctl(5, active). The collision + result is located before the sprite structure by default in this driver. + + In order to reserve memory for the collision detection buffer you need to + specify lynx-coll.cfg as the configuration file to the linker. + +</descrip><p> + + +<sect1>Extended memory drivers<p> + +No extended memory drivers are currently available for the Lynx. + + +<sect1>Joystick drivers<p> + +<descrip> + + <tag><tt/lynx-stdjoy.joy (lynx_stdjoy_joy)/</tag> + A joystick driver for the standard buttons. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +No mouse drivers are currently available for the Lynx. + + +<sect1>RS232 device drivers<p> + +<descrip> + + <tag><tt/lynx-comlynx.ser (lynx_comlynx_ser)/</tag> + A serial driver for the ComLynx port. + + The ComLynx port has Tx and Rx wired together. Every byte is sent + to all connected Lynxes. Only one Lynx can send at a time. There is no + protocol created for communication. You are on your own. + + If the Lynx returns framing error then it is likely that another Lynx is + sending data at the same time. + + The Lynx can also send a break and receive a break. The Lynx break is + recognized if the bit is down for 24 bit cycles or more. + + To send a break you just set the break bit. The length of the break depends + on how long this bit is down. + + The driver supports the baudrates: + <itemize> + <item>62500 + <item>31250 + <item>9600 + <item>7200 + <item>4800 + <item>3600 + <item>2400 + <item>1800 + <item>1200 + <item>600 + <item>300 + <item>150 + <item>134.5 + <item>110 + <item>75 + </itemize> + The parity bit supports MARK and SPACE. It also supports EVEN and ODD parity + but the parity bit is included in the calculation. Most of us don't want it + this way. But there is nothing we can do about it. + + The Lynx hardware will always check parity on incoming traffic. Currently + the driver cannot receive data from standard PC's due to this parity bug. + For working with Lynx to Lynx communication use EVEN parity. + + To send data to standard PC's use MARK or SPACE as parity setting. + + There is always only one stop bit. And the data length is always 8 bits. + + We have no handshaking available. Even software handshake is impossible + as ComLynx has only one wire for the data. + + Both transmit and receive are interrupt driven. + +</descrip><p> + + +<sect>Limitations<p> + + + +<sect>Cart access<p> + +At this point in time there is no support for the cart filesystem yet. I have +a <tt/lynx-cart-demo/ example project that uses an interrupt driven display, +has support for the cart filesystem and an abcmusic sound module. + +At some point in time we may find a way to rewrite these to fit the way the +cc65 drivers require. But for the time being you can create less portable +applications using these Lynx specific modules in <tt/lynx-cart-demo/. + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/nes.sgml b/doc/nes.sgml new file mode 100644 index 000000000..ca9ce72b3 --- /dev/null +++ b/doc/nes.sgml @@ -0,0 +1,189 @@ +<!doctype linuxdoc system> + +<article> + +<title>Nintendo Entertainment System specific information for cc65 +<author> +<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> +<url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> +<date>2014-04-12 + +<abstract> +An overview over the NES runtime system as it is implemented for the +cc65 C compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the NES runtime system as it comes +with the cc65 C compiler. It describes the memory layout, NES specific header +files, available drivers, and any pitfalls specific to that platform. + +Please note that NES specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the NES target +is a machine language program with an INES cartridge header. It is of course +possible to change this behaviour by using a modified startup file and linker +config. + +<sect>Memory layout<p> + +cc65 generated programs with the default setup run with the I/O area and a +CHR bank enabled, which gives a usable memory range of $8000 - $FFF3. +All boot ROM entry points may be called directly without additional code. + +Special locations: + +<descrip> + <tag/Text screen/ + The text screen is located at VRAM $2000. + + <tag/Stack/ + The C runtime stack is located at $7FFF and growing downwards. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + + + +<sect>Platform specific header files<p> + +Programs containing NES specific code may use the <tt/nes.h/ header file. + + +<sect1>NES specific functions<p> + +<itemize> +<item>waitvblank +<item>get_tv +</itemize> + + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/nes.inc/ include file do +allow access to hardware located in the address space. + +<descrip> + + <tag><tt/PPU/</tag> + The <tt/PPU/ defines allow access to the PPU chip. + + <tag><tt/APU/</tag> + The <tt/APU/ defines allow access to the APU chip. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +All drivers must be statically linked because no file I/O is available. +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +<descrip> + + <tag><tt/nes-64-56-2.tgi (nes_64_56_2)/</tag> + This driver features a resolution of 64×56 with 2 colors using the + CHR bank. + +</descrip><p> + + +<sect1>Extended memory drivers<p> + +No extended memory drivers are currently available for the NES. + + +<sect1>Joystick drivers<p> + +<descrip> + + <tag><tt/nes-stdjoy.joy (nes_stdjoy)/</tag> + A joystick driver for the standard four buttons joypad is available. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +No mouse drivers are currently available for the NES. + + +<sect1>RS232 device drivers<p> + +No serial drivers are currently available for the NES. + + + +<sect>Limitations<p> + +<sect1>Disk I/O<p> + +The existing library for the NES doesn't implement C file +I/O. There are no hacks for the <tt/read()/ and <tt/write()/ routines. + +To be more concrete, this limitation means that you cannot use any of the +following functions (and a few others): + +<itemize> +<item>fclose +<item>fopen +<item>fread +<item>fprintf +<item>fputc +<item>fscanf +<item>fwrite +<item>... +</itemize> + + + +<sect>Other hints<p> + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> + + + diff --git a/doc/od65.sgml b/doc/od65.sgml new file mode 100644 index 000000000..f5611a889 --- /dev/null +++ b/doc/od65.sgml @@ -0,0 +1,215 @@ +<!doctype linuxdoc system> + +<article> +<title>od65 Users Guide +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2014-04-14 + +<abstract> +od65 is the object file dump utility. It is able to output most parts of +<htmlurl url="ca65.html" name="ca65-generated"> object files in readable form. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + + +<sect>Overview<p> + +od65 is an object file dump utility. It is able to output most parts of +<htmlurl url="ca65.html" name="ca65-generated"> object files in readable form. +Since the contents and format of the object files are not documented +elsewhere and may change at any time, this tool is a portable way to look at +the contents. + +Apart from curiosity, most people don't need to use this tool. + + + +<sect>Usage<p> + +The od65 utility dumps contents of one or more ca65 generated object file to +standard output. It has no cross-version compatibility, so you have to use +a version that matches the version of ca65 used to create the object files. + + +<sect1>Command line option overview<p> + +The program may be called as follows: + +<tscreen><verb> +--------------------------------------------------------------------------- +Usage: od65 [options] file [options] [file] +Short options: + -h Help (this text) + -H Dump the object file header + -S Dump segments sizes + -V Print the version number and exit + +Long options: + --dump-all Dump all object file information + --dump-dbgsyms Dump debug symbols + --dump-exports Dump exported symbols + --dump-files Dump the source files + --dump-header Dump the object file header + --dump-imports Dump imported symbols + --dump-lineinfo Dump line information + --dump-options Dump object file options + --dump-segments Dump the segments in the file + --dump-segsize Dump segments sizes + --help Help (this text) + --version Print the version number and exit +--------------------------------------------------------------------------- +</verb></tscreen> + + +<sect1>Command line options in detail<label id="cmdline-opt-detail"><p> + +Here is a description of all the command line options: + +<descrip> + + <tag><tt>--dump-all</tt></tag> + + This will output all information, od65 is able to process. The option is a + shortcut for specifying all the other <tt/--dump/ options. + + + <tag><tt>--dump-dbgsyms</tt></tag> + + Dump all debug symbols contained in the object file. + + + <tag><tt>--dump-exports</tt></tag> + + Dump all exported symbols contained in the object file. + + + <tag><tt>--dump-files</tt></tag> + + Dump the file table contained in the object file. + + + <tag><tt>-H, --dump-header</tt></tag> + + Dump the object file header. + + + <tag><tt>--dump-imports</tt></tag> + + Dump the list of imported symbols contained in the object file. + + + <tag><tt>--dump-lineinfo</tt></tag> + + Dump the line info contained in the object file. + + + <tag><tt>--dump-segments</tt></tag> + + Dump the list of segments contained in the object file. + + + <tag><tt>--dump-scopes</tt></tag> + + Dump the scope (lexical level) information contained in the object file. + + + <tag><tt>-S, --dump-segsize</tt></tag> + + Dump the sizes of all segments contained in the object file. This option is + quite useful to determine the effect of measures that increase or decrease + code size. + + + <tag><tt>-h, --help</tt></tag> + + Print the short option summary shown above. + + + <tag><tt>-V, --version</tt></tag> + + Print the version number of the compiler. When submitting a bug report, + please include the operating system you're using, and the compiler + version. +</descrip> + + +<sect>Input and output<p> + +The converter will read one or more object files per invocation and write the +contents in readable format to standard output. Please note that you need to +specify any of the <tt/--dump/ options listed <ref id="cmdline-opt-detail" +name="above">, otherwise no useful output will be generated. + +Example output for the command +<tscreen><verb> +od65 --dump-header --dump-files t.o +</verb></tscreen> +<tscreen><verb> +t.o: + Header: + Magic: 0x616E7A55 + Version: 12 + Flags: 0x0001 (OBJ_FLAGS_DBGINFO) + Options: + Offset: 88 + Size: 9 + Files: + Offset: 97 + Size: 10 + Segments: + Offset: 107 + Size: 101 + Imports: + Offset: 208 + Size: 1 + Exports: + Offset: 209 + Size: 1 + Debug symbols: + Offset: 210 + Size: 55 + Line infos: + Offset: 265 + Size: 1 + String pool: + Offset: 266 + Size: 80 + Files: + Count: 1 + Index: 0 + Name: "t.s" + Size: 402 + Modification time: 1280498435 (Fri Jul 30 16:00:35 2010) +</verb></tscreen> + + +<sect>Copyright<p> + +od65 is (C) Copyright 2000-2009, Ullrich von Bassewitz. For usage of the +binaries and/or sources the following conditions apply: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> + diff --git a/doc/pet.sgml b/doc/pet.sgml new file mode 100644 index 000000000..7c5bd71ea --- /dev/null +++ b/doc/pet.sgml @@ -0,0 +1,256 @@ +<!doctype linuxdoc system> + +<article> + +<title>Commodore PET-specific information for cc65 +<author> +<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> +<url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> +<date>2014-04-12 + +<abstract> +An overview over the PET runtime system as it is implemented for the cc65 C +compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the PET runtime system as it comes with the +cc65 C compiler. It describes the memory layout, PET-specific header files, +available drivers, and any pitfalls specific to that platform. + +Please note that PET-specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the PET target +is a machine language program with a one line BASIC stub, which calls the +machine language part via SYS. This means that a program can be loaded as +BASIC program and started with RUN. It is of course possible to change this +behaviour by using a modified startup file and linker config. + + +<sect>Memory layout<p> + +cc65 generated programs with the default setup run with the I/O area and the +kernal and BASIC ROM enabled, which gives a usable memory range of +$0400 - $7FFF (32KB machine). +All ROM entry points may be called directly without additional code. + +Special locations: + +<descrip> + <tag/Text screen/ + The text screen is located at $8000. + + <tag/Stack/ + The C runtime stack is located at $7FFF and growing downwards. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + + + +<sect>Platform-specific header files<p> + +Programs containing PET-specific code may use the <tt/pet.h/ or <tt/cbm.h/ +header files. Using the later may be an option when writing code for more than +one CBM platform, since it includes <tt/pet.h/ and declares several functions +common to all CBM platforms. + + +<sect1>PET-specific functions<p> + +There are currently no special PET functions. + + + +<sect1>CBM-specific functions<p> + +Some functions are available for all (or at least most) of the Commodore +machines. See the <url url="funcref.html" name="function reference"> for +declaration and usage. + +<itemize> +<item>cbm_close +<item>cbm_closedir +<item>cbm_k_setlfs +<item>cbm_k_setnam +<item>cbm_k_load +<item>cbm_k_save +<item>cbm_k_open +<item>cbm_k_close +<item>cbm_k_readst +<item>cbm_k_chkin +<item>cbm_k_ckout +<item>cbm_k_basin +<item>cbm_k_bsout +<item>cbm_k_clrch +<item>cbm_load +<item>cbm_open +<item>cbm_opendir +<item>cbm_read +<item>cbm_readdir +<item>cbm_save +<item>cbm_write +<item>get_tv +</itemize> + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/pet.h/ header file do allow +access to hardware located in the address space. Some variables are +structures, accessing the struct fields will access the chip registers. + +<descrip> + + <tag><tt/PIA1, PIA2/</tag> + Access to the two PIA (peripheral interface adapter) chips is available via + the <tt/PIA1/ and <tt/PIA2/ variables. The structure behind these variables + is explained in <tt/_pia.h/. + + <tag><tt/VIA/</tag> + The <tt/VIA/ structure allows access to the VIA (versatile interface + adapter). See the <tt/_6522.h/ header file located in the include + directory for the declaration of the structure. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +No graphics drivers are currently available for the PET. + + +<sect1>Extended memory drivers<p> + +No extended memory drivers are currently available for the PET. + + +<sect1>Joystick drivers<p> + +The default drivers, <tt/joy_stddrv (joy_static_stddrv)/, point to <tt/pet-stdjoy.joy (pet_stdjoy_joy)/. + +<descrip> + + <tag><tt/pet-ptvjoy.joy (pet_ptvjoy_joy)/</tag> + Driver for the Protovision 4-player adapter contributed by Groepaz. See + <url url="http://www.protovision-online.de/hardw/hardwstart.htm"> for prices and + building instructions. Up to two joysticks are supported. + + <tag><tt/pet-stdjoy.joy (pet_stdjoy_joy)/</tag> + Driver for the standard PET userport joystick. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +No mouse drivers are currently available for the PET. + + +<sect1>RS232 device drivers<p> + +No serial drivers are currently available for the PET. + + + +<sect>Limitations<p> + + + +<sect>Other hints<p> + + +<sect1>Passing arguments to the program<p> + +Command-line arguments can be passed to <tt/main()/. Since that is not +supported directly by BASIC, the following syntax was chosen: + +<tscreen><verb> + RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 +</verb></tscreen> + +<enum> +<item>Arguments are separated by spaces. +<item>Arguments may be quoted. +<item>Leading and trailing spaces around an argument are ignored. Spaces within + a quoted argument are allowed. +<item>The first argument passed to <tt/main()/ is the program name. +<item>A maximum number of 10 arguments (including the program name) are + supported. +</enum> + + +<sect1>Program return code<p> + +The program return code (low byte) is passed back to BASIC by use of the +<tt/ST/ variable. + + +<sect1>Interrupts<p> + +The runtime for the PET uses routines marked as <tt/.INTERRUPTOR/ for +interrupt handlers. Such routines must be written as simple machine language +subroutines and will be called automatically by the interrupt handler code +when they are linked into a program. See the discussion of the <tt/.CONDES/ +feature in the <url url="ca65.html" name="assembler manual">. + + +<sect1>Using extended memory<p> + +The extended memory at $9000 of the CBM 8x96 may be added to the heap by using +the following code: + +<tscreen><verb> + /* Check for the existence of RAM */ + if (PEEK(0x9000) == POKE(0x9000, PEEK(0x9000)+1)) { + /* Add it to the heap */ + _heapadd ((void *) 0x9000, 0x2000); + } +</verb></tscreen> + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/plus4.sgml b/doc/plus4.sgml new file mode 100644 index 000000000..36d53e753 --- /dev/null +++ b/doc/plus4.sgml @@ -0,0 +1,260 @@ +<!doctype linuxdoc system> + +<article> + +<title>Commodore Plus/4 specific information for cc65 +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2014-04-12 + +<abstract> +An overview over the Plus/4 runtime system as it is implemented for the cc65 C +compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the Plus/4 runtime system as it comes with the +cc65 C compiler. It describes the memory layout, Plus/4 specific header files, +available drivers, and any pitfalls specific to that platform. + +Please note that Plus/4 specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + +Since the Plus/4 and the Commodore 16/116 are almost identical (the latter are +missing the 6551 ACIA and do only have 16KB of memory), the <url +url="c16.html" name="C16 documentation"> is also worth a look. The difference +between both cc65 targets is that the Plus/4 runtime uses banking to support +full 64K RAM, while the C16 does not use banking and supports up to 32K RAM. +Because banking is not needed, most C16 programs will be somewhat smaller than +the same program compiled for the Plus/4. However, programs compiled for the +C16 will always run on the Plus/4, while the reverse is not necessarily true. + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the Plus/4 +target is a machine language program with a one line BASIC stub, which calls +the machine language part via SYS. This means that a program can be loaded as +BASIC program and started with RUN. It is of course possible to change this +behaviour by using a modified startup file and linker config. + + +<sect>Memory layout<p> + +cc65 generated programs with the default setup run with the kernal and basic +banked out. This gives a usable memory range of $1000 - $FD00. +Having the kernal and basic ROMs banked out means, that no ROM entry points +may be called directly from user code. + +Special locations: + +<descrip> + <tag/Text screen/ + The text screen is located at $C00 (as in the standard setup). + + <tag/Color RAM/ + The color RAM is located at $800 (standard location). + + <tag/Stack/ + The C runtime stack is located at $FCFF and growing downwards. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + + + +<sect>Platform specific header files<p> + +Programs containing Plus/4 specific code may use the <tt/plus4.h/ or <tt/cbm.h/ +header files. Using the later may be an option when writing code for more than +one CBM platform, since it includes <tt/plus4.h/ and declares several functions +common to all CBM platforms. + +Please note that most of the header file declarations from the <tt/plus4.h/ +header file are shared between the C16 and Plus/4 configurations. For this +reason, most of it is located in a common header file named <tt/cbm264.h/. + + + +<sect1>Plus/4 specific functions<p> + +There are currently no special Plus/4 functions. + + +<sect1>CBM specific functions<p> + +Some functions are available for all (or at least most) of the Commodore +machines. See the <url url="funcref.html" name="function reference"> for +declaration and usage. + +<itemize> +<item>cbm_close +<item>cbm_closedir +<item>cbm_k_setlfs +<item>cbm_k_setnam +<item>cbm_k_load +<item>cbm_k_save +<item>cbm_k_open +<item>cbm_k_close +<item>cbm_k_readst +<item>cbm_k_chkin +<item>cbm_k_ckout +<item>cbm_k_basin +<item>cbm_k_bsout +<item>cbm_k_clrch +<item>cbm_load +<item>cbm_open +<item>cbm_opendir +<item>cbm_read +<item>cbm_readdir +<item>cbm_save +<item>cbm_write +<item>get_tv +</itemize> + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/plus4.h/ header file do +allow access to hardware located in the address space. Some variables are +structures, accessing the struct fields will access the chip registers. + +<descrip> + + <tag><tt/TED/</tag> + The <tt/TED/ structure allows access to the TED chip. See the + <tt/_ted.h/ header file located in the include directory for the + declaration of the structure. + + <tag><tt/COLOR_RAM/</tag> + A character array that mirrors the color RAM of the Plus/4 at $0800. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +No graphics drivers are currently available for the Plus/4. + + +<sect1>Extended memory drivers<p> + +No extended memory drivers are currently available for the Plus/4. + + +<sect1>Joystick drivers<p> + +<descrip> + + <tag><tt/plus4-stdjoy.joy (plus4_stdjoy_joy)/</tag> + Supports up to two joysticks connected to the standard joysticks port of + the Plus/4. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +No mouse drivers are currently available for the Plus/4. + + +<sect1>RS232 device drivers<p> + +<descrip> + + <tag><tt/plus4-stdser.ser (plus4_stdser_ser)/</tag> + Driver for the 6551 ACIA chip built into the Plus/4. Supports up to 19200 + baud, hardware flow control (RTS/CTS) and interrupt driven receives. Note + that because of the peculiarities of the 6551 chip transmits are not + interrupt driven, and the transceiver blocks if the receiver asserts flow + control because of a full buffer. + + You need an adapter to use the builtin port, since the output levels + available at the user port don't follow the RS232 standard. + +</descrip><p> + + + +<sect>Limitations<p> + + + +<sect>Other hints<p> + +<sect1>Passing arguments to the program<p> + +Command line arguments can be passed to <tt/main()/. Since this is not +supported by BASIC, the following syntax was chosen: + +<tscreen><verb> + RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 +</verb></tscreen> + +<enum> +<item>Arguments are separated by spaces. +<item>Arguments may be quoted. +<item>Leading and trailing spaces around an argument are ignored. Spaces within + a quoted argument are allowed. +<item>The first argument passed to <tt/main/ is the program name. +<item>A maximum number of 10 arguments (including the program name) are + supported. +</enum> + + + +<sect1>Program return code<p> + +The program return code (low byte) is passed back to BASIC by use of the +<tt/ST/ variable. + + +<sect1>Interrupts<p> + +The runtime for the Plus/4 uses routines marked as <tt/.INTERRUPTOR/ for +interrupt handlers. Such routines must be written as simple machine language +subroutines and will be called automatically by the interrupt handler code +when they are linked into a program. See the discussion of the <tt/.CONDES/ +feature in the <url url="ca65.html" name="assembler manual">. + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/smc.sgml b/doc/smc.sgml new file mode 100644 index 000000000..240c78e7b --- /dev/null +++ b/doc/smc.sgml @@ -0,0 +1,593 @@ +<!doctype linuxdoc system> + +<article> +<title>ca65 Macros for Self Modifying Code +<author>Christian Krüger +<date>2014-04-24 + +<abstract> +The 'smc.inc' macro package for ca65 eases the use, increases the safeness and +self-explanation of 'self-modifying-code' (SMC). +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> +When reading assembler sources, self modifying code is often hard to identify +and applying it needs a lot of discipline. + +Since the cacheless 6502 is a thankful target of such kind of code, the macro +package will not only reduce this complexness, but also document the use. The +resulting source is more self-explanatory and so easier to maintain. + +While for general purposes SMC is not a desired form for implementations, it +can be quite useful for a small range of scenarios. Normally SMC will be +introduced when optimizing code in respect to: + +<itemize> +<item>speed and/or +<item>size. +</itemize> + +Please mind that SMC can only be applied for code in RAM, which means that a +general purpose library with SMC excludes ROM targets! + +The ca65 SMC macro package consists of two files: + +<itemize> +<item><tt>smc.inc</tt> +<item><tt>opcodes.inc</tt> +</itemize> + +The latter is only needed if you also plan to modify opcodes and not only data +within your code. + +<sect>Usage<p> +The use of the macros is quite simple: + +Original: + +<tscreen><verb> + PHA + JSR SUBROUTINE + PLA +</verb></tscreen> + +By applying SMC, the speed will now be increased by once cycle: + +SMC: + +<tscreen><verb> + SMC_StoreValue RestoreAccu + JSR SUBROUTINE +SMC RestoreAccu, { LDA #SMC_Value } +</verb></tscreen> + +The first line stores the value of the accu into the '<tt>RestoreAccu</tt>' +labeled SMC target. + +Please note: +<enum> +<item> for all SMC store or transfer operations, a second argument can be + given. This determines the register for the operation: + '<tt>SMC_StoreValue Label, y</tt>' will store the value of the + Y-register. + + If the second argument is missing, the accu will be used automatically. + +<item> The label targets a 'special SMC namespace'. It fits only to + destinations which are introduced with the macro '<tt>SMC</tt>'. A + normal label '<tt>RestoreAccu</tt>' wouldn't match and could even + coexist (even if you should abstain from doing so). + +<item> The macro '<tt>SMC_StoreValue</tt>' takes care, that the store + operation will occur on the value-position of a SMC-instruction. As + you will see, other macros influence other instruction part positions. + There is no consistency check, if the targeted SMC instruction acually + contains a value. Storing a 'value' on an immplied SMC instruction + would corrupt the following memory cell! +</enum> + +The second line needs no further explanation, this is just a placeholder for +some code in the example. + +The third line is the code line which is about to be modified. It has to start +with the '<tt>SMC</tt>' macro and must be labeled, so that the modification +can be designated. Then the unmodified code is given in curly braces. + +Please note the usage of the value placeholder 'SMC_Value'. Using such a +placeholder has two advantages: + +<enum> +<item> The code is better documented. It is clearly visible that the given + value is about to be changed. +<item> When examining an (initial) disassembly (e.g. in a debugger), these + placegolders can be better identified: They are fixed and, you may + notice that below, quite eye catching defined. +</enum> + +<sect1>Argument placeholders<p> + +There are four kinds of placeholders: + +<descrip> + + <label id="Address placeholder"> + <tag><tt>SMC_AbsAdr</tt></tag> + + Used to indicate an address. The value is '<tt>$FADE</tt>'. + + Example: <tt>STA SMC_AbsAdr</tt> + + + <label id="Zero-Page-Address placeholder"> + <tag><tt>SMC_ZpAdr</tt></tag> + + Used to indicate a zero-page-address. The value is '<tt>$00</tt>'. + + Example: <tt>LDA SMC_ZpAdr</tt> + + + <label id="Opcode placeholder"> + <tag><tt>SMC_Opcode</tt></tag> + + Used to indicate an instruction. The value is '<tt>NOP</tt>'. + + Example: <tt>SMC_Opcode</tt> + + + <label id="Immediate value placeholder"> + <tag><tt>SMC_Value</tt></tag> + + Used to indicate a value. The value is '<tt>$42</tt>'. + + Example: <tt>LDX #SMC_Value</tt> +</descrip> + +Attention: Often code is modified after the initial use - where using the +placeholders does not makes sense. Please mind also, that in very variable +expressions (e.g. opcode and argument is about to be changed), placeholders +can lead to unidentifyable code for a debugger/disassembler: + +<tt>SMC Example, { SMC_Opcode SMC_AbsAdr } </tt> + +Since the opcode is '<tt/NOP/', the value '<tt/$DE/' from '<tt/$FADE/' will +interpreted as opcode in a disassembler too. This breaks the correct +disassembly, because '<tt/$DE/' is interpreted as '<tt/DEC abx/'. Establishing +a valid placeholder instruction may be better: + +<tt>SMC Example, { sta SMC_AbsAdr } ; Note: Opcode will be modified too!</tt> + +<sect1>Accessing opcodes<p> + +Some macros are designed to access the instruction of a code line. To increase +readability, please use the opcodes as defined in the '<tt>opcodes.inc</tt>' +file. + +<descrip> + + <label id="Transfer opcode"> + <tag><tt>SMC_TransferOpcode label, opcode (, register)</tt></tag> + Loads and store an opcode to given SMC instruction. + + Example: + +<tscreen><verb> +SMC SumRegister, { LDA #10 } + JSR OUTPUT + SMC_TransferOpcode SumRegister, OPC_ADC_imm, x +</verb></tscreen> + +The macro above will load the opcode '<tt>ADC #</tt>' into the x - register +and stores it at the place of the '<tt>LDA #</tt>'. + + <label id="Load opcode"> + <tag><tt>SMC_LoadOpcode label (, register)</tt></tag> + Loads the opcode of a SMC line to the given register. + + Example: +<tscreen><verb> +SMC ShiftOrNothing, { LSL } + SMC_LoadOpcode ShiftOrNothing, y + CPY #OPC_NOP + BEQ Exit +</verb></tscreen> + + <label id="Store opcode"> + <tag><tt>SMC_StoreOpcode label (, register)</tt></tag> + Stores the value of the given register at the opcode place of a SMC line. + + Example: +<tscreen><verb> +SetBoldMode: + LDA #OPC_INX + SMC_StoreOpcode AdaptCharWidth + SMC_StoreOpcode AdaptUnderlineWidth + RTS + ... +SMC AdaptCharWidth, { NOP } + ... +SMC AdaptUnderlineWidth, { NOP } +</verb></tscreen> + +</descrip> + +<sect1>Accessing arguments<p> + +These marcos are determined to get, set and change arguments of instructions: + +<descrip> + + <label id="Change branch"> + <tag><tt>SMC_ChangeBranch label, destination (, register)</tt></tag> + + Used to modify the destination of a branch instruction. If the adress offset + exceeds the supported range of 8-bit of the 6502, a error will be thrown. + + Example: +<tscreen><verb> +Disable Handler: + SMC_ChangeBranch BranchToHandler, Exit + RTS + ... + LDA warning +SMC BranchToHandler, { BNE Handler } +Exit: + RTS +</verb></tscreen> + + + <label id="Transfer value"> + <tag><tt>SMC_TransferValue label, value (, register)</tt></tag> + + Changes the value of a SMC line. + + Example: +<tscreen><verb> +ClearDefault: + SMC_TransferValue LoadDefault, 0 + RTS + ... +SMC LoadDefault, { LDX #25 } +</verb></tscreen> + + + <label id="Load value"> + <tag><tt>SMC_LoadValue label (, register)</tt></tag> + + Retreives the value of a SMC line. + + Example: +<tscreen><verb> +ShowDefault: + SMC_LoadValue LoadDefault + JSR PrintValue + RTS + ... +SMC LoadDefault, { LDX #25 } +</verb></tscreen> + + + <label id="Store value"> + <tag><tt>SMC_StoreValue label (, register)</tt></tag> + + Stores the value in the register to given SMC line. + + Example: +<tscreen><verb> +InitCounters: + LDY #0 + SMC_StoreValue GetI, y + SMC_StoreValue GetJ, y + SMC_StoreValue GetK, y + ... +SMC GetI, { LDX #SMC_Value } + ... +SMC GetJ, { LDX #SMC_Value } + ... +SMC GetK, { LDX #SMC_Value } +</verb></tscreen> + + + <label id="Transfer low-byte"> + <tag><tt>SMC_TransferLowByte label, value (, register)</tt></tag> + + Does the same as '<tt>SMC_TransferValue</tt>' but should be used for + low-bytes of adresses for better readability. + + Example: +<tscreen><verb> +ActivateSecondDataSet: + SMC_TransferLowByte LoadData, $40 + RTS + ... +SMC LoadData, { LDA $2000 } +</verb></tscreen> + + + <label id="Load low-byte"> + <tag><tt>SMC_LoadLowByte label (, register)</tt></tag> + + Does the same as '<tt>SMC_LoadValue</tt>' but should be used for low-bytes + of adresses for better readability. + + Example: +<tscreen><verb> +IsSecondDataSetActive: + SMC_LoadLowByte LoadData, y + CPY #$40 + BNE NotActive + ... +SMC LoadData, { LDA $2000 } +</verb></tscreen> + + + <label id="Store low-byte"> + <tag><tt>SMC_StoreLowByte label (, register)</tt></tag> + + Does the same as '<tt>SMC_StoreValue</tt>' but should be used for low-bytes + of adresses for better readability. + + Example: +<tscreen><verb> +InitStructureBaseAddresses: + LDX #0 + SMC_StoreLowByte GetPlayerGraphic, x + SMC_StoreLowByte GetObjectGraphic, x + SMC_StoreLowByte StoreCollisionData, x + RTS + ... +SMC GetPlayerGraphic, { LDX $2000 } + ... +SMC GetObjectGraphic, { LDA $2100,x } + ... +SMC StoreCollisionData, { STY $2200 } +</verb></tscreen> + + + <label id="Transfer high-byte"> + <tag><tt>SMC_TransferHighByte label, value (, register)</tt></tag> + + Loads and stores the given value via the named register to the high-byte + adress portion of an SMC-instruction. + + Example: +<tscreen><verb> +PlaySFX: +SMC GetVolume { LDA $3200,x } + STA SoundOut + INX + BNE PlaySFX + ... +PlayOtherSound: + SMC_TransferHighByte GetVolume, $34 +</verb></tscreen> + + + <label id="Load high-byte"> + <tag><tt>SMC_LoadHighByte label (, register)</tt></tag> + + Loads the high-byte part of an SMC-instruction adress to the given register. + + Example: +<tscreen><verb> +PlaySFX: +SMC GetVolume { LDA $3200,x } + ... + SMC_LoadHighByte GetVolume + cmp #$34 + beq OtherSoundPlaying + ... +</verb></tscreen> + + + <label id="Store high-byte"> + <tag><tt>SMC_StoreHighByte label (, register)</tt></tag> + + Stores the high-byte adress part of an SMC-instruction from the given + register. + + Example: +<tscreen><verb> +SetupLevel2: + LDX #(>Level2Base) + SMC_StoreHighByte GetLevelData, x + SMC_StoreHighByte GetScreenData, x + SMC_StoreHighByte GetSoundData, x + RTS + ... +SMC GetLevelData, { LDA Level1Base+Data } + ... +SMC GetScreenData, { LDA Level1Base+Screen, x } + ... +SMC GetSoundData, { LDA Level1Base+Sound, y } +</verb></tscreen> + + + <label id="Transfer single adress"> + <tag><tt>SMC_TransferAddressSingle label, address (, register)</tt></tag> + + Transfers the contents of the given address via the given register to the + designated SMC instruction. + + Example: +<tscreen><verb> +PrintHello: + SMC_TransferAddressSingle GetChar, #HelloMsg + ... + LDX #0 +NextChar: +SMC GetChar, { LDA SMC_AbsAdr, x } + BEQ leave + JSR CharOut + INX + BNE NextChar +</verb></tscreen> + + + <label id="Transfer adress"> + <tag><tt>SMC_TransferAddress label, address</tt></tag> + + Loads contents of given address to A/X and stores the result to SMC + instruction. Allows reuse of register contents by using + '<tt>SMC_StoreAddress</tt>' for multiple SMC instruction modifications. + + Example: +<tscreen><verb> + SMC_TransferAddress JumpTo, #CloseChannel + ... +SMC JumpTo, { JMP OpenChannel } +</verb></tscreen> + + + <label id="Store address"> + <tag><tt>SMC_StoreAddress label</tt></tag> + + Stores the address value in a/x to a SMC instruction address position. + + Example: +<tscreen><verb> + SMC_StoreAddress GetData + ... +SMC GetData, { LDA SMC_AbsAdr } +</verb></tscreen> + +</descrip> + +<sect1>Operational macros<p> + +These marcos are determined to let read/modify/write opcodes work on parts of +SMC instructions. + +<descrip> + + <label id="Operate on value"> + <tag><tt>SMC_OperateOnValue opcode, label</tt></tag> + + Let given opcode work on the value part of a SMC instruction. + + Example: +<tscreen><verb> + SMC_OperateOnValue ASL, LoadMask ; shift mask to left + ... +SMC LoadMask, { LDA #$20 } +</verb></tscreen> + + <label id="Operate on low-byte"> + <tag><tt>SMC_OperateOnLowByte opcode, label</tt></tag> + + Same as '<tt/SMC_OperateOnValue/' but renamed for better readability when + accessing low-bytes of address. + + Example: +<tscreen><verb> + SMC_OperateOnLowByte DEC, AccessData + ... +SMC AccessData, { LDX Data } +</verb></tscreen> + + <label id="Operate on high-byte"> + <tag><tt>SMC_OperateOnHighByte opcode, label</tt></tag> + + Let the given opcode work on the high-byte part on a SMC-instruction. + + Example: +<tscreen><verb> +NextPage: + SMC_OperateOnHighByte INC, GetPageData + ... +SMC GetPageData, { LDA SourceData, X } +</verb></tscreen> +</descrip> + +<sect1>Scope macros<p> + +These marcos are determined to export and import SMC labels out of the current +file scope. Please handle with care! If you cannot abstain from leaving the +file scope, you should at least document the exported SMC lines very well. On +import side no checking is available if the SMC line is correct accessed (e.g. +invalid access to the value of an implied instruction)! + +<descrip> + <label id="Export SMC line under given name"> + <tag><tt>SMC_Export alias, label</tt></tag> + + SMC label will be exported under given alias. + + Example: +<tscreen><verb> +.proc GetValue +SMC LoadValue, { LDA #12 } + rts +.endproc + +SMC_Export GetValueLoader, GetValue::LoadValue +</verb></tscreen> + + <label id="Import SMC alias"> + <tag><tt>SMC_Import alias</tt></tag> + + SMC line is made accessible under given alias. + + Example: +<tscreen><verb> +SMC_Import GetValueLoader + ... + SMC_TransferValue GetValueLoader, #47 + ... +</verb></tscreen> +</descrip> + +<sect>A complex example<p> +Let's have a look on a quite sophisticated example for the usage of SMC. It +not only modifies code, but also the modification of the code is modified - +allowing reuse of some instructions. + +<descrip> +<tag/The code is from my 'memset()'implementation:/ +<tscreen><verb> + 1: ... + 2: SMC_StoreAddress StoreAccuFirstSection + 3: + 4: StoreToFirstSection: + 5: SMC StoreAccuFirstSection, { sta SMC_AbsAdr, Y } + 6: ... + 7: RestoreCodeBranchBaseAdr: + 8: SMC FirstIncHighByte, { SMC_OperateOnHighByte inc, StoreAccuFirstSection } ; code will be overwritten to 'beq RestoreCode' (*) + 9: ... +10: SMC_TransferOpcode FirstIncHighByte, OPC_BEQ , x ; change code marked above with (*) +11: SMC_TransferValue FirstIncHighByte, #(restoreCode - RestoreCodeBranchBaseAdr-2), x ; set relative adress to 'RestoreCode' +12: ... +13: restoreCode: +14: SMC_TransferOpcode FirstIncHighByte, OPC_INC_abs , x ; restore original code... +15: SMC_TransferValue FirstIncHighByte, #(<(StoreToFirstSection+2)), x ; (second byte of inc contained low-byte of adress) +16: ... +</verb></tscreen> + +<tag/Some explanation:/ +Line 2: The register pair A/X contains an address, which is stored on the +address location of a SMC line called 'StoreAccuFirstSection'. According to +cc65's calling convention, the low-byte is in accu while the high-byte is in +the X-register. + +Line 5: The (modified) address is accessed. + +Line 8: We have a line here, which is about to be modified (it begins with +SMC), but itself modifies code. Please note: Contrary to the rest of SMC-line +modifying macros, the 'OperateOn'-macros just expand their given arguments +into a single instruction line. These can be changed of course too. + +Line 10,11: These lines construct a branch operation for line 8: The +X-register will be used to change it from 'inc StoreAccuFirstSection+2' +(high-byte operation) to 'beq restoreCode'. Please note: To calculate the +relaive branch offset, we introduced a second label +('RestoreCodeBranchBaseAdr') for to calculate it. Some could also use the +internal name of the SMC label, but you should abstain to do so - it may be +changed in the future... + +Line 14,15: The original code from line 8 is reestablished. +</descrip> +</article> diff --git a/doc/sp65.sgml b/doc/sp65.sgml new file mode 100644 index 000000000..909ac6d25 --- /dev/null +++ b/doc/sp65.sgml @@ -0,0 +1,415 @@ +<!doctype linuxdoc system> <!-- -*- text-mode -*- --> + +<article> +<title>sp65 Users Guide +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> +<date>2012-03-11 + +<abstract> +sp65 is a sprite and bitmap utility that is part of the cc65 development suite. +It is used to convert graphics and bitmaps into the target formats of the +supported machines. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +sp65 is a tool that converts images from common formats into formats used +on the 6502 platforms that are the targets of the cc65 compiler suite. In +addition, it allows some very simple operation with loaded graphics data, like +using part of an image for further processing. + +The utility has been designed in a way that adding additional source or target +formats is easy. The final output is either binary, or C/assembler source. + + + +<sect>Usage<p> + + +<sect1>Command line option overview<p> + +The sp65 utility accepts the following options: + +<tscreen><verb> +--------------------------------------------------------------------------- +Usage: sp65 [options] file [options] [file] +Short options: + -V Print the version number and exit + -c fmt[,attrlist] Convert into target format + -h Help (this text) + -lc List all possible conversions + -r file[,attrlist] Read an input file + -v Increase verbosity + -w file[,attrlist] Write the output to a file + +Long options: + --convert-to fmt[,attrlist] Convert into target format + --help Help (this text) + --list-conversions List all possible conversions + --pop Restore the original loaded image + --read file[,attrlist] Read an input file + --slice x,y,w,h Generate a slice from the loaded bitmap + --verbose Increase verbosity + --version Print the version number and exit + --write file[,attrlist] Write the output to a file +--------------------------------------------------------------------------- +</verb></tscreen> + + +<sect1>Command line options in detail<p> + +Below is a description of all the command line options. For the concept of +attribute lists see <ref id="attr-lists" name="below">. + +<descrip> + + <label id="option--convert-to"> + <tag><tt>-c, --convert-to format[,attrlist]</tt></tag> + + Convert a bitmap into one of the supported target formats. The option + argument must at least contain the "format" attribute. For more attributes, + see section <ref id="conversions" name="Conversions">. + + + <label id="option--help"> + <tag><tt>-h, --help</tt></tag> + + Print the short option summary shown above. + + + <label id="option--list-conversions"> + <tag><tt>-lc, --list-conversions</tt></tag> + + Print a list of possible conversions. + + + <label id="option--pop"> + <tag><tt>--pop</tt></tag> + + Restore the working copy of the bitmap from the one originally loaded from + the file. This may for example be used when creating several output files + from one input file. + + + <label id="option--read"> + <tag><tt>-r, --read filename[,attrlist]</tt></tag> + + Read an input file. The option argument must at least contain the "name" + attribute. See <ref id="input-formats" name="input formats"> for more + information. + + + <label id="option-v"> + <tag><tt>-v, --verbose</tt></tag> + + Increase verbosity. Usually only needed for debugging purposes. You may use + this option more than one time for even more verbose output. + + + <label id="option-V"> + <tag><tt>-V, --version</tt></tag> + + Print the version number of the assembler. If you send any suggestions or + bugfixes, please include the version number. + + + <label id="option--write"> + <tag><tt>-w, --write filename[,attrlist]</tt></tag> + + Write an output file. The option argument must at least contain the "name" + attribute. See <ref id="output-formats" name="output formats"> for more + information. + +</descrip> +<p> + + + +<sect>Processing pipeline<label id="processing-pipeline"><p> + +sp65 consists of + +<itemize> +<item>Front ends that read graphics data, +<item>processors for graphics data, +<item>converters +<item>and output modules for several formats. +</itemize> + +These modules can be combined to a pipeline that reads data, does some +optional bitmap processing, converts the bitmap into a target format, and +writes this binary data to disk in one of several forms. + + + +<sect>Attribute lists<label id="attr-lists"><p> + +As described in <ref id="processing-pipeline" name="Processing pipeline">, +sp65 consists of lots of different modules that may be combined in different +ways, to convert an input bitmap to some output. + +Many of the processors and converters have options to change the way, they're +working. To avoid having lots of command line options that must be parsed on +high level and passed down to the relevant parts of the program, sp65 features +something called "attribute lists". Attribute lists are lists of +attribute/value pairs. These lists are parsed by the main program module +without any knowledge about their meaning. Lower level parts just grab the +attributes they need. + +In general, attribute lists look like this: + +<tscreen><verb> + attr1=val1[,attr2=val2[,...]] +</verb></tscreen> + +Instead of the comma, colons may also be used (even mixed). + +To simplify things and to make the most common options look "normal", some +mandatory attributes may be given without an attribute name. If the attribute +name is missing, the default name is determined by the position. For example, +the option <tt/<ref id="option--read" name="--read">/ does always need a file +name. The attribute name for the file name is "name". To avoid having to type + +<tscreen><verb> + sp65 --read name=ball.pcx ... +</verb></tscreen> + +the first attribute gets the default name "name" assigned. So if the first +attribute doesn't have a name, it is assumed that it is the file name. This +means that instead of the line above, one can also use + +<tscreen><verb> + sp65 --read ball.pcx ... +</verb></tscreen> + +The second attribute for <tt/--read/ is the format of the input file. So when +using + +<tscreen><verb> + sp65 --read ball.pic:pcx ... +</verb></tscreen> + +a PCX file named "ball.pic" is read. The long form would be + +<tscreen><verb> + sp65 --read name=ball.pic:format=pcx ... +</verb></tscreen> + +Changing the order of the attributes is possible only when explicitly +specifying the names of the attributes. Using + +<tscreen><verb> + sp65 --read pcx:ball.pic ... +</verb></tscreen> + +will make sp65 complain, because it tries to read a file named "pcx" with an +(unknown) format of "ball.pic". The following however will work: + +<tscreen><verb> + sp65 --read format=pcx:name=ball.pic ... +</verb></tscreen> + +The attributes that are valid for each processor or converter are listed +below. + + + +<sect>Input formats<label id="input-formats"><p> + +Input formats are either specified explicitly when using <tt/<ref +id="option--read" name="--read">/, or are determined by looking at the +extension of the file name given. + +<sect1>PCX<p> + +While sp65 is prepared for more, this is currently the only possible input +format. There are no additional attributes for this format. + + + +<sect>Conversions<label id="conversions"><p> + +<sect1>GEOS bitmap<p> + +The current bitmap working copy is converted to a GEOS compacted bitmap. This +format is used by several GEOS functions (i.e. 'BitmapUp') and is described +in 'The Official GEOS Programmers Reference Guide', chapter 4, section +'Bit-Mapped Graphics'. + + +<sect1>GEOS icon<p> + +The current bitmap working copy is converted to GEOS icon format. A GEOS icon +has the same format as a C64 high resolution sprite (24x21, monochrome, 63 +bytes). There are no additional attributes for this conversion. + + +<sect1>Koala image<p> + + +<sect1>Lynx sprite<p> + +Lynx can handle 1, 2, 3 and 4 bits per pixel indexed sprites. The maximum size +of a sprite is roughly 508 pixels but in reality the Lynx screen is only 160 by +102 pixels which makes very large sprites useless. + +The number per pixels is taken from the number of colors of the input bitmap. + +There are a few attributes that you can give to the conversion software. + +<descrip> + + <tag/mode/ + The first is what kind of encoding to use for the sprite. The attribute for + this is called "mode" and the possible values are "literal", "packed" or + "transparent". The default is "packed" if no mode is specified. + + The "literal" is a totally literal mode with no packing. In this mode the + number of pixels per scanline will be a multiple of 8 both right and left from + the action point. + + If the source bitmap edge ends with a color where the least significant bit is + one then there will be an extra 8 zero bits on that scan line. + + So if you are using totally literal sprites and intend to change them at + runtime then please add a single pixel border far left and far right with + zeros in order to prevent graphical glitches in the game. + + The standard encoding is called "packed". In this mode the sprite is packed + using run-length encoding and literal coding mixed for optimisation to + produce a small sprite. + + The last encoding mode "transparent" is like packed. But here we know that + the index 0 will be transparent so we can clip off all 0 pixels from the left + and right edge of the sprite. This will produce the smallest sprite possible + on the Lynx. The sprite is not rectangular anymore. + + <tag/ax/ + The sprite is painted around the Anchor point. The anchor point x can be + between 0 and the width of the sprite - 1. If anchor point x is zero then + painting the sprite in location 10,20 will set the left edge of the sprite + 10 pixels from the left of the Lynx screen. When the sprite is scaled by + hardware the anchor point stays in place and the sprite grows or shrinks + around the anchor point. The default value is 0 (left). + + <tag/ay/ + The sprite is painted around the Anchor point. The anchor point y can be + between 0 and the height of the sprite - 1. If anchor point y is zero then + painting the sprite in location 10,20 will set the top of the sprite 20 + pixels from the top of the Lynx screen. When the sprite is scaled by + hardware the anchor point stays in place and the sprite grows or shrinks + around the anchor point. The default value is 0 (top). + +</descrip> + +<sect1>VIC2 sprite<p> + + + + +<sect>Output formats<label id="output-formats"><p> + +Using <tt/<ref id="option--write" name="--write">/ it is possible to write +processed data to an output file. An attribute "name" is mandatory, it is used +as the file name for the output. The output format can be specified using an +attribute named "format". If this attribute doesn't exist, the output format +is determined by looking at the file name extension. + + +<sect1>Binary<p> + +For this format, the processed data is written to the output file in raw +binary format. There are no additional attributes (besides "name" and +"format") for this output format. + + +<sect1>Assembler code<p> + +For this format, the processed data is written to the output file in ca65 +assembler format. There are several attributes for this output format: + +<descrip> + + <tag/base/ + The value for this attribute specifies the numeric base for the data + values. It may be either 2, 10 or 16. The default is 16. If the base is + 2, the numbers are prefixed by '%', if the base is 16, the numbers are + prefixed by '$'. For base 10, there is no prefix. + + <tag/bytesperline/ + The value for this attribute specifies the number of bytes output in one + line of the assembler file. The default is 16. + + <tag/ident/ + This is an optional attribute. When given, the output processor will wrap + the data into a <tt/.PROC/ with the given name. In addition, three constants + are added as local symbols within the <tt/.PROC/: <tt/COLORS/, <tt/WIDTH/ + and <tt/HEIGHT/. + +</descrip> + + + +<sect1>C code<p> + +When using C output format, a small piece of C source code is generated that +defines the data containing the output in an array of <tt/unsigned char/. + +Possible attributes for this format are: + +<descrip> + <tag/base/ + The value for this attribute specifies the numeric base for the data values. + It may be either 10 or 16. The default is 16. If the base is 16, the numbers + are prefixed by 0x. For base 10, there is no prefix. + + <tag/bytesperline/ + The value for this attribute specifies the number of bytes output in one + line of the C source code. The default is 16. + + <tag/ident/ + This is an optional attribute. When given, the output processor will wrap + the data into an array of unsigned char with the given name. In addition, + three <tt/#define/s are added for <tt/<ident>_COLORS/, + <tt/<ident>_WIDTH/ and <tt/<ident>_HEIGHT/. + +</descrip> + + + +<sect>Copyright<p> + +sp65 (and all cc65 binutils) are (C) Copyright 1998-2012 Ullrich von Bassewitz +and others. For usage of the binaries and/or sources the following conditions +do apply: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + + + +</article> + + + diff --git a/doc/supervision.sgml b/doc/supervision.sgml new file mode 100644 index 000000000..97495dea5 --- /dev/null +++ b/doc/supervision.sgml @@ -0,0 +1,170 @@ +<!doctype linuxdoc system> + +<article> + +<title>Watara Supervision specific information for cc65 +<author><url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> +<date>2014-04-12 + +<abstract> +An overview over the Supervision runtime system as it is implemented for the +cc65 C compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the Supervision runtime system as it comes +with the cc65 C compiler. It describes the memory layout, Supervision specific header +files, available drivers, and any pitfalls specific to that platform. + +Please note that Supervision specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more information. + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the Supervision target +is a 2×16 kbyte machine language program. It is of course +possible to change this behaviour by using one of the different linker configs. + +<sect>Memory layout<p> + +cc65 generated programs with the default setup run with the I/O area enabled, +which gives a usable memory range of $8000 - $FFF9. +More ROM may need additional bankswitching code. + +Special locations: + +<descrip> + <tag/Text screen/ +<!-- The text screen is located at VRAM $4000.--> + No conio support is currently available for the Supervision. + + <tag/Stack/ + The C runtime stack is located at $1FFF and growing downwards. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + + + +<sect>Platform specific header files<p> + +Programs containing Supervision specific code may use the <tt/supervision.h/ header file. + + +<sect1>Supervision specific functions<p> + +<itemize> +<item>waitvblank +</itemize> + + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/supervision.inc/ include file do +allow access to hardware located in the address space. + +<descrip> + + <tag><tt/IO/</tag> + The <tt/IO/ defines allow access to the IO chip. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +<sect1>Graphics drivers<p> + +No graphics drivers are currently available for the Supervision. +<!--A TGI driver for the standard graphics mode (160×160 in 4 colors) is +available, but must be statically linked, because no file I/O is available. +See the documentation for the <url url="co65.html" name="co65 utility"> +for information on how to do that.--> + +<sect1>Extended memory drivers<p> + +No extended memory drivers are currently available for the Supervision. + + +<sect1>Joystick drivers<p> + +No joystick drivers are currently available for the Supervision. +<!--A joystick driver for the standard buttons is available, but must be +statically linked, because no file I/O is available. See the documentation for +the <url url="co65.html" name="co65 utility"> for information on how to do +that.--> + +<sect1>Mouse drivers<p> + +No mouse drivers are currently available for the Supervision. + + +<sect1>RS232 device drivers<p> + +No communication port drivers are currently available for the Supervision. + + + +<sect>Limitations<p> + +<sect1>Disk I/O<p> + +The existing library for the Supervision doesn't implement C file +I/O. There are even no hacks for the <tt/read()/ and <tt/write()/ routines. + +To be more concrete, this limitation means that you cannot use any of the +following functions (and a few others): + +<itemize> +<item>fclose +<item>fopen +<item>fread +<item>fprintf +<item>fputc +<item>fscanf +<item>fwrite +<item>... +</itemize> + + + +<sect>Other hints<p> + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/using-make.sgml b/doc/using-make.sgml new file mode 100644 index 000000000..0c3c13a6e --- /dev/null +++ b/doc/using-make.sgml @@ -0,0 +1,156 @@ +<!doctype linuxdoc system> + +<article> + +<title>Using GNU Make with cc65 +<author><url url="mailto:ol.sc@web.de" name="Oliver Schmidt"> +<date>2014-04-12 + +<abstract> +How to build your program using the GNU Make utility. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This document describes how to build your programs using the cc65 development +tools and the GNU Make utility. + +The cc65 development package doesn't come with a make utility. However this is +no issue because GNU Make works very nicely with cc65. + + + +<sect>What is GNU Make?<p> + +GNU Make is a both very powerful and very popular make utility. It might even +be called the de facto standard for make utilities. For more information see +the GNU Make home page: + +<url url="http://www.gnu.org/software/make/"> + +The cc65 development package is available as binaries for several host systems +and can easily built for quite some additional systems. The very same is true +for GNU Make so a cc65-based project coming with a GNU Make Makefile can easily +be built by any cc65 developer no matter what host system is used. + +Because of the strong alignment of the cc65 compiler with the ISO C standard it +is very well feasible to compile a single C code base both with the cc65 +compiler and other C compilers like for example GCC. GNU Make turns out to be +very well suited to build projects for several target systems using multiple +compilers as it isn't tied to any C compiler. + + + +<sect>A sample Makefile<p> + +This Makefile is a fully functional sample for compiling several C sources +(here <tt/foo.c/ and <tt/bar.c/) and link the resulting object files into an +executable program (here <tt/foobar/): + +<tscreen><verb> +SOURCES = foo.c bar.c + +PROGRAM = foobar + +ifdef CC65_TARGET +CC = $(CC65_HOME)/bin/cl65 +CFLAGS = -t $(CC65_TARGET) --create-dep $(<:.c=.d) -O +LDFLAGS = -t $(CC65_TARGET) -m $(PROGRAM).map +else +CC = gcc +CFLAGS = -MMD -MP -O +LDFLAGS = -Wl,-Map,$(PROGRAM).map +endif + +######################################## + +.SUFFIXES: +.PHONY: all clean +all: $(PROGRAM) + +ifneq ($(MAKECMDGOALS),clean) +-include $(SOURCES:.c=.d) +endif + +%.o: %.c + $(CC) -c $(CFLAGS) -o $@ $< + +$(PROGRAM): $(SOURCES:.c=.o) + $(CC) $(LDFLAGS) -o $@ $^ + +clean: + $(RM) $(SOURCES:.c=.o) $(SOURCES:.c=.d) $(PROGRAM) $(PROGRAM).map +</verb></tscreen> + +<bf/Important:/ When using the sample Makefile above via copy & paste it is +necessary to replace the eight spaces at the beginning of command lines (lines +26, 29 and 32) with a tab character (ASCII code 9). + + +<sect1>Invoking the sample Makefile<p> + +Without any specific configuration the sample Makefile will compile and link +using GCC. In order to rather use cc65 the variable <tt/CC65_TARGET/ needs to be +defined. This may by done as an environment variable or simply as part of the +Makefile. However to quickly switch between compilers and/or cc65 targets it is +best done on the GNU Make command line like this: + +<tscreen><verb> +make CC65_TARGET=c64 +</verb></tscreen> + +The sample Makefile presumes the variable <tt/CC65_HOME/ to point to the +directory cc65 is located in. Again there are several ways to define this +variable but as its value typically won't change often it is best done as an +environment variable. On Windows the cc65 .exe installer package takes care +of creating a <tt/CC65_HOME/ environment variable. + + +<sect1>Understanding the sample Makefile<p> + +Most parts of the sample Makefile follow the guidelines in the +<url url="http://www.gnu.org/software/make/manual/make.html" name="GNU Make Manual"> +that can be searched online for background information. The automatic generation of +dependency however rather works as described by the GNU Make maintainer Paul D. Smith in +<url url="http://make.paulandlesley.org/autodep.html#advanced" name="&dquot;Advanced Auto-Dependencies&dquot;">. +Fortunately both GCC and cc65 directly support this method in the meantime. + + +<sect1>Invoking the sample Makefile on Windows<p> + +The recommended way to use GNU Make on Windows is to install it as part of a +Cygwin environment. For more information see the Cygwin home page: + +<url url="http://www.cygwin.com/"> + +If however installing Cygwin shouldn't be an option for one or the other reason +then the sample Makefile may be invoked from the Windows Command Prompt (cmd.exe) +by downloading the following programs: + +<itemize> +<item><url name="make.exe" url="http://gnuwin32.sourceforge.net/packages/make.htm"> +<item><url name="rm.exe" url="http://gnuwin32.sourceforge.net/packages/coreutils.htm"> +</itemize> + + + +<sect>Target-specific Variable Values<p> + +The very limited resources of the cc65 target machines now and then require +manual optimization of the build process by compiling individual source files +with different compiler options. GNU Make offers +<url url="http://www.gnu.org/software/make/manual/html_node/Target_002dspecific.html" name="Target-specific Variable Values"> +perfectly suited for doing so. For example placing the code of the two modules +<tt/foo/ and <tt/bar/ in the segment <tt/FOOBAR/ can be achieved with this +target-specific variable definition: + +<tscreen><verb> +foo.o bar.o: CFLAGS += --code-name FOOBAR +</verb></tscreen> + +</article> diff --git a/doc/vic20.sgml b/doc/vic20.sgml new file mode 100644 index 000000000..5fba59a13 --- /dev/null +++ b/doc/vic20.sgml @@ -0,0 +1,264 @@ +<!doctype linuxdoc system> + +<article> + +<title>Commodore VIC20 (aka VC20) specific information for cc65 +<author> +<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> +<url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> +<date>2014-04-12 + +<abstract> +An overview over the VIC20 runtime system as it is implemented for the cc65 C +compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the VIC20 runtime system as it comes with the +cc65 C compiler. It describes the memory layout, VIC20-specific header files, +available drivers, and any pitfalls specific to that platform. + +Please note that VIC20-specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the VIC20 target +is a machine language program with a one line BASIC stub, which calls the +machine language part via SYS. This means that a program can be loaded as +BASIC program and started with RUN. It is of course possible to change this +behaviour by using a modified startup file and linker config. + + +<sect>Memory layout<p> + +cc65 generated programs with the default setup run with unexpanded memory +(RAM at $A000 - $BFFF may be used for the heap), +which gives a usable memory range of $1000 - $1DFF. +All ROM entry points may be called directly without additional code. + +Special locations: + +<descrip> + <tag/Text screen/ + The text screen is located at $1E00 (as in the standard setup). + + <tag/Stack/ + The C runtime stack is located at $1DFF and growing downwards. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + +</descrip><p> + + + +<sect>Platform-specific header files<p> + +Programs containing VIC20-specific code may use the <tt/vic20.h/ or <tt/cbm.h/ +header files. Using the later may be an option when writing code for more than +one CBM platform, since it includes <tt/vic20.h/ and declares several functions +common to all CBM platforms. + + +<sect1>VIC20-specific functions<p> + +There are currently no special VIC20 functions. + + + +<sect1>CBM-specific functions<p> + +Some functions are available for all (or at least most) of the Commodore +machines. See the <url url="funcref.html" name="function reference"> for +declaration and usage. + +<itemize> +<item>cbm_close +<item>cbm_closedir +<item>cbm_k_setlfs +<item>cbm_k_setnam +<item>cbm_k_load +<item>cbm_k_save +<item>cbm_k_open +<item>cbm_k_close +<item>cbm_k_readst +<item>cbm_k_chkin +<item>cbm_k_ckout +<item>cbm_k_basin +<item>cbm_k_bsout +<item>cbm_k_clrch +<item>cbm_load +<item>cbm_open +<item>cbm_opendir +<item>cbm_read +<item>cbm_readdir +<item>cbm_save +<item>cbm_write +<item>get_tv +</itemize> + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/vic20.h/ header file do allow +access to hardware located in the address space. Some variables are +structures, accessing the struct fields will access the chip registers. + +<descrip> + + <tag><tt/VIC/</tag> + The <tt/VIC/ structure allows access to the VIC (the graphics + controller). See the <tt/_vic.h/ header file located in the include + directory for the declaration of the structure. + + <tag><tt/VIA1, VIA2/</tag> + Access to the two VIA (versatile interface adapter) chips is available via + the <tt/VIA1/ and <tt/VIA2/ variables. The structure behind these variables + is explained in <tt/_6522.h/. + + <tag><tt/COLOR_RAM/</tag> + A character array that mirrors the color RAM of the VIC20 at $9600. + +</descrip><p> + + + +<sect>Loadable drivers<p> + +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +No graphics drivers are currently available for the VIC20. + + +<sect1>Extended memory drivers<p> + +No extended memory drivers are currently available for the VIC20. + + +<sect1>Joystick drivers<p> + +The default drivers, <tt/joy_stddrv (joy_static_stddrv)/, point to <tt/vic20-stdjoy.joy (vic20_stdjoy_joy)/. + +<descrip> + + <tag><tt/vic20-stdjoy.joy (vic20_stdjoy_joy)/</tag> + Supports one standard joystick connected to the joysticks port of the VIC20. + + <tag><tt/vic20-ptvjoy.joy (vic20_ptvjoy_joy)/</tag> + Driver for the Protovision 4-player adapter contributed by Groepaz. See + <url url="http://www.protovision-online.de/hardw/hardwstart.htm"> for prices and + building instructions. Up to three joysticks are supported. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +No mouse drivers are currently available for the VIC20. + + +<sect1>RS232 device drivers<p> + +No VIC1011 drivers are currently available for the VIC20. + + + +<sect>Limitations<p> + + + +<sect>Other hints<p> + + +<sect1>Escape code<p> + +For an Esc, press CTRL and the <tt/[/ key. + + +<sect1>Passing arguments to the program<p> + +Command-line arguments can be passed to <tt/main()/. Since that is not +supported directly by BASIC, the following syntax was chosen: + +<tscreen><verb> + RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 +</verb></tscreen> + +<enum> +<item>Arguments are separated by spaces. +<item>Arguments may be quoted. +<item>Leading and trailing spaces around an argument are ignored. Spaces within + a quoted argument are allowed. +<item>The first argument passed to <tt/main()/ is the program name. +<item>A maximum number of 10 arguments (including the program name) are + supported. +</enum> + + +<sect1>Program return code<p> + +The program return code (low byte) is passed back to BASIC by use of the +<tt/ST/ variable. + + +<sect1>Using extended memory<p> + +The extended memory at $A000 may be added to the heap by using the following +code: + +<tscreen><verb> + /* Check for the existence of RAM */ + if (PEEK(0xA000) == POKE(0xA000, PEEK(0xA000)+1)) { + /* Add it to the heap */ + _heapadd ((void *) 0xA000, 0x2000); + } +</verb></tscreen> + + +<sect1>Interrupts<p> + +The runtime for the VIC20 uses routines marked as <tt/.INTERRUPTOR/ for +interrupt handlers. Such routines must be written as simple machine language +subroutines and will be called automatically by the interrupt handler code +when they are linked into a program. See the discussion of the <tt/.CONDES/ +feature in the <url url="ca65.html" name="assembler manual">. + + + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/include/6502.h b/include/6502.h index 706418516..6c104c83a 100644 --- a/include/6502.h +++ b/include/6502.h @@ -82,21 +82,21 @@ struct regs { #define F6502_C 0x01 /* C flag */ /* Function to call any machine language subroutine. All registers in the - * regs structure are passed into the routine and the results are passed - * out. The B flag is ignored on input. The called routine must end with - * an RTS. - */ +** regs structure are passed into the routine and the results are passed +** out. The B flag is ignored on input. The called routine must end with +** an RTS. +*/ void __fastcall__ _sys (struct regs* r); /* Set and reset the break vector. The given user function is called if - * a break occurs. The values of the registers may be read from the brk_... - * variables. The value in brk_pc will point to the address that contains - * the brk instruction. - * The set_brk function will install an exit handler that will reset the - * vector if the program ends. - */ +** a break occurs. The values of the registers may be read from the brk_... +** variables. The value in brk_pc will point to the address that contains +** the brk instruction. +** The set_brk function will install an exit handler that will reset the +** vector if the program ends. +*/ extern unsigned char brk_a; /* A register value */ extern unsigned char brk_x; /* X register value */ diff --git a/include/_6522.h b/include/_6522.h index 1072e6779..d6eedcf75 100644 --- a/include/_6522.h +++ b/include/_6522.h @@ -36,10 +36,10 @@ /* Define a structure with the 6522 register offsets. - * NOTE: The timer registers are not declared as 16 bit registers, because - * the order in which the two 8 bit halves are written is important, and - * the compiler doesn't guarantee any order when writing 16 bit values. - */ +** NOTE: The timer registers are not declared as 16 bit registers, because +** the order in which the two 8 bit halves are written is important, and +** the compiler doesn't guarantee any order when writing 16 bit values. +*/ struct __6522 { unsigned char prb; /* Port register B */ unsigned char pra; /* Port register A */ diff --git a/include/_6525.h b/include/_6525.h index dee0ba459..128839c83 100644 --- a/include/_6525.h +++ b/include/_6525.h @@ -39,9 +39,9 @@ /* Define a structure with the 6525 register offsets. The shadow registers - * (if port C is unused) are currently not implemented, we would need a - * union to do that, however that would introduce an additional name. - */ +** (if port C is unused) are currently not implemented, we would need a +** union to do that, however that would introduce an additional name. +*/ struct __6525 { unsigned char pra; /* Port register A */ unsigned char prb; /* Port register B */ diff --git a/include/_6526.h b/include/_6526.h index 5f8cb7d10..aa3158dc8 100644 --- a/include/_6526.h +++ b/include/_6526.h @@ -39,10 +39,10 @@ /* Define a structure with the 6526 register offsets. - * NOTE: The timer registers are not declared as 16 bit registers, because - * the order in which the two 8 bit halves are written is important, and - * the compiler doesn't guarantee any order when writing 16 bit values. - */ +** NOTE: The timer registers are not declared as 16 bit registers, because +** the order in which the two 8 bit halves are written is important, and +** the compiler doesn't guarantee any order when writing 16 bit values. +*/ struct __6526 { unsigned char pra; /* Port register A */ unsigned char prb; /* Port register B */ diff --git a/include/_heap.h b/include/_heap.h index 76bad35c3..c054cfa34 100644 --- a/include/_heap.h +++ b/include/_heap.h @@ -1,9 +1,9 @@ /* - * _heap.h - * - * Ullrich von Bassewitz, 1998-06-03, 2004-12-19 - * - */ +** _heap.h +** +** Ullrich von Bassewitz, 1998-06-03, 2004-12-19 +** +*/ @@ -12,11 +12,11 @@ -/* Structure that preceeds a user block in most cases. - * The aligned_malloc function may generate blocks where the start pointer - * and size are splitted to handle a memory hole that is needed for - * alignment. - */ +/* Structure that preceeds a user block in most cases. +** The aligned_malloc function may generate blocks where the start pointer +** and size are splitted to handle a memory hole that is needed for +** alignment. +*/ struct usedblock { unsigned size; struct usedblock* start; @@ -26,8 +26,8 @@ struct usedblock { #define HEAP_ADMIN_SPACE sizeof (struct usedblock) /* The data type used to implement the free list. - * Beware: Field order is significant! - */ +** Beware: Field order is significant! +*/ struct freeblock { unsigned size; struct freeblock* next; diff --git a/include/_vic2.h b/include/_vic2.h index 2031944bb..a28067b24 100644 --- a/include/_vic2.h +++ b/include/_vic2.h @@ -39,8 +39,8 @@ /* Define a structure with the vic register offsets. In cc65 mode, there - * are aliases for the field accessible as arrays. - */ +** are aliases for the field accessible as arrays. +*/ #if __CC65_STD__ == __CC65_STD_CC65__ struct __vic2 { union { diff --git a/include/apple2.h b/include/apple2.h index 310e697b1..a1b094d4d 100644 --- a/include/apple2.h +++ b/include/apple2.h @@ -109,23 +109,23 @@ extern unsigned char _dos_type; /* Valid _dos_type values: - * - * AppleDOS 3.3 - 0x00 - * ProDOS 8 1.0.1 - 0x10 - * ProDOS 8 1.0.2 - 0x10 - * ProDOS 8 1.1.1 - 0x11 - * ProDOS 8 1.2 - 0x12 - * ProDOS 8 1.3 - 0x13 - * ProDOS 8 1.4 - 0x14 - * ProDOS 8 1.5 - 0x15 - * ProDOS 8 1.6 - 0x16 - * ProDOS 8 1.7 - 0x17 - * ProDOS 8 1.8 - 0x18 - * ProDOS 8 1.9 - 0x18 (!) - * ProDOS 8 2.0.1 - 0x21 - * ProDOS 8 2.0.2 - 0x22 - * ProDOS 8 2.0.3 - 0x23 - */ +** +** AppleDOS 3.3 - 0x00 +** ProDOS 8 1.0.1 - 0x10 +** ProDOS 8 1.0.2 - 0x10 +** ProDOS 8 1.1.1 - 0x11 +** ProDOS 8 1.2 - 0x12 +** ProDOS 8 1.3 - 0x13 +** ProDOS 8 1.4 - 0x14 +** ProDOS 8 1.5 - 0x15 +** ProDOS 8 1.6 - 0x16 +** ProDOS 8 1.7 - 0x17 +** ProDOS 8 1.8 - 0x18 +** ProDOS 8 1.9 - 0x18 (!) +** ProDOS 8 2.0.1 - 0x21 +** ProDOS 8 2.0.2 - 0x22 +** ProDOS 8 2.0.3 - 0x23 +*/ @@ -136,9 +136,9 @@ extern unsigned char _dos_type; /* The file stream implementation and the POSIX I/O functions will use the - * following variables to determine the file type, aux type and creation time - * stamp to use. - */ +** following variables to determine the file type, aux type and creation time +** stamp to use. +*/ extern unsigned char _filetype; /* Default: 6 */ extern unsigned int _auxtype; /* Default: 0 */ extern struct { @@ -179,18 +179,18 @@ void rebootafterexit (void); #define ser_apple2_slot(num) ser_ioctl (0, (void*) (num)) /* Select a slot number from 1 to 7 prior to ser_open. - * The default slot number is 2. - */ +** The default slot number is 2. +*/ #define tgi_apple2_mix(onoff) tgi_ioctl (0, (void*) (onoff)) /* If onoff is 1, graphics/text mixed mode is enabled. - * If onoff is 0, graphics/text mixed mode is disabled. - */ +** If onoff is 0, graphics/text mixed mode is disabled. +*/ /* The following #defines will cause the matching functions calls in conio.h - * to be overlaid by macros with the same names, saving the function call - * overhead. - */ +** to be overlaid by macros with the same names, saving the function call +** overhead. +*/ #define _textcolor(color) COLOR_WHITE #define _bgcolor(color) COLOR_BLACK #define _bordercolor(color) COLOR_BLACK diff --git a/include/apple2enh.h b/include/apple2enh.h index 9fb093b45..cc62f70b7 100644 --- a/include/apple2enh.h +++ b/include/apple2enh.h @@ -109,8 +109,8 @@ extern void a2e_lo_tgi[]; void __fastcall__ textframe (unsigned char width, unsigned char height, unsigned char style); /* Output a frame on the text screen with the given width and height - * starting at the current cursor position and using the given style. - */ +** starting at the current cursor position and using the given style. +*/ void __fastcall__ textframexy (unsigned char x, unsigned char y, unsigned char width, unsigned char height, @@ -119,8 +119,8 @@ void __fastcall__ textframexy (unsigned char x, unsigned char y, unsigned __fastcall__ videomode (unsigned mode); /* Set the video mode, return the old mode. Call with one of the VIDEOMODE_xx - * constants. - */ +** constants. +*/ diff --git a/include/atari.h b/include/atari.h index ff23526ee..82cd07330 100644 --- a/include/atari.h +++ b/include/atari.h @@ -169,9 +169,16 @@ extern char *_getdefdev(void); /* get default floppy device */ /* global variables */ extern unsigned char _dos_type; /* the DOS flavour */ +#ifndef __ATARIXL__ extern void atr130_emd[]; extern void atrstd_joy[]; /* referred to by joy_static_stddrv[] */ extern void atrmj8_joy[]; +extern void atrjoy_mou[]; +extern void atrst_mou[]; /* referred to by mouse_static_stddrv[] */ +extern void atrami_mou[]; +extern void atrtrk_mou[]; +extern void atrtt_mou[]; +extern void atrrdev_ser[]; extern void atr3_tgi[]; extern void atr4_tgi[]; extern void atr5_tgi[]; @@ -187,6 +194,32 @@ extern void atr11_tgi[]; extern void atr14_tgi[]; extern void atr15_tgi[]; extern void atr15p2_tgi[]; +#else +extern void atrx130_emd[]; +extern void atrxstd_joy[]; /* referred to by joy_static_stddrv[] */ +extern void atrxmj8_joy[]; +extern void atrxjoy_mou[]; +extern void atrxst_mou[]; /* referred to by mouse_static_stddrv[] */ +extern void atrxami_mou[]; +extern void atrxtrk_mou[]; +extern void atrxtt_mou[]; +extern void atrxrdev_ser[]; +extern void atrx3_tgi[]; +extern void atrx4_tgi[]; +extern void atrx5_tgi[]; +extern void atrx6_tgi[]; +extern void atrx7_tgi[]; +extern void atrx8_tgi[]; /* referred to by tgi_static_stddrv[] */ +extern void atrx8p2_tgi[]; +extern void atrx9_tgi[]; +extern void atrx9p2_tgi[]; +extern void atrx10_tgi[]; +extern void atrx10p2_tgi[]; +extern void atrx11_tgi[]; +extern void atrx14_tgi[]; +extern void atrx15_tgi[]; +extern void atrx15p2_tgi[]; +#endif /* provide old names for backwards compatibility */ #ifdef ATARI_COMPAT_PRE_2_11 diff --git a/include/atari5200.h b/include/atari5200.h new file mode 100644 index 000000000..4bd5bc0fd --- /dev/null +++ b/include/atari5200.h @@ -0,0 +1,107 @@ +/*****************************************************************************/ +/* */ +/* atari5200.h */ +/* */ +/* Atari 5200 system specific definitions */ +/* */ +/* */ +/* */ +/* (C) 2014 Christian Groessler <chris@groessler.org> */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#ifndef _ATARI5200_H +#define _ATARI5200_H + + + +/* Check for errors */ +#if !defined(__ATARI5200__) +# error This module may only be used when compiling for the Atari 5200! +#endif + +/* no support for dynamically loadable drivers */ +#define DYN_DRV 0 + +/* the addresses of the static drivers */ +extern void atr5200std_joy[]; /* referred to by joy_static_stddrv[] */ + +/* make GTIA color value */ +#define _gtia_mkcolor(hue,lum) (((hue) << 4) | ((lum) << 1)) + +/* luminance values go from 0 (black) to 7 (white) */ + +/* hue values */ +#define HUE_GREY 0 +#define HUE_GOLD 1 +#define HUE_GOLDORANGE 2 +#define HUE_REDORANGE 3 +#define HUE_ORANGE 4 +#define HUE_MAGENTA 5 +#define HUE_PURPLE 6 +#define HUE_BLUE 7 +#define HUE_BLUE2 8 +#define HUE_CYAN 9 +#define HUE_BLUEGREEN 10 +#define HUE_BLUEGREEN2 11 +#define HUE_GREEN 12 +#define HUE_YELLOWGREEN 13 +#define HUE_YELLOW 14 +#define HUE_YELLOWRED 15 + +/* Color defines, similar to c64 colors (untested) */ +#define COLOR_BLACK _gtia_mkcolor(HUE_GREY,0) +#define COLOR_WHITE _gtia_mkcolor(HUE_GREY,7) +#define COLOR_RED _gtia_mkcolor(HUE_REDORANGE,1) +#define COLOR_CYAN _gtia_mkcolor(HUE_CYAN,3) +#define COLOR_VIOLET _gtia_mkcolor(HUE_PURPLE,4) +#define COLOR_GREEN _gtia_mkcolor(HUE_GREEN,2) +#define COLOR_BLUE _gtia_mkcolor(HUE_BLUE,2) +#define COLOR_YELLOW _gtia_mkcolor(HUE_YELLOW,7) +#define COLOR_ORANGE _gtia_mkcolor(HUE_ORANGE,5) +#define COLOR_BROWN _gtia_mkcolor(HUE_YELLOW,2) +#define COLOR_LIGHTRED _gtia_mkcolor(HUE_REDORANGE,6) +#define COLOR_GRAY1 _gtia_mkcolor(HUE_GREY,2) +#define COLOR_GRAY2 _gtia_mkcolor(HUE_GREY,3) +#define COLOR_LIGHTGREEN _gtia_mkcolor(HUE_GREEN,6) +#define COLOR_LIGHTBLUE _gtia_mkcolor(HUE_BLUE,6) +#define COLOR_GRAY3 _gtia_mkcolor(HUE_GREY,5) + +/* get_tv return values */ +#define AT_NTSC 0 +#define AT_PAL 1 + +/* Define hardware */ +#include <_gtia.h> +#define GTIA_READ (*(struct __gtia_read*)0xC000) +#define GTIA_WRITE (*(struct __gtia_write*)0xC000) + +#include <_pokey.h> +#define POKEY_READ (*(struct __pokey_read*)0xE800) +#define POKEY_WRITE (*(struct __pokey_write*)0xE800) + +#include <_antic.h> +#define ANTIC (*(struct __antic*)0xD400) + +/* End of atari5200.h */ +#endif /* #ifndef _ATARI5200_H */ diff --git a/include/c128.h b/include/c128.h index 2ca559d49..565fbc9ce 100644 --- a/include/c128.h +++ b/include/c128.h @@ -129,7 +129,7 @@ extern void c128_reu_emd[]; extern void c128_vdc_emd[]; extern void c128_ptvjoy_joy[]; extern void c128_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ -extern void c128_1351_mous[]; /* Referred to by mouse_static_stddrv[] */ +extern void c128_1351_mou[]; /* Referred to by mouse_static_stddrv[] */ extern void c128_joy_mou[]; extern void c128_inkwell_mou[]; extern void c128_pot_mou[]; @@ -141,21 +141,21 @@ extern void c128_vdc2_tgi[]; unsigned __fastcall__ videomode (unsigned Mode); /* Set the video mode, return the old mode. Call with one of the VIDEOMODE_xx - * constants. - */ +** constants. +*/ void toggle_videomode (void); /* Toggle the video mode between 40 and 80 chars (calls SWAPPER). - * THIS FUNCTION IS DEPRECATED, please use videomode instead! - */ +** THIS FUNCTION IS DEPRECATED, please use videomode instead! +*/ void c64mode (void); /* Switch the C128 into C64 mode. Note: This function will not return! */ void fast (void); /* Switch the CPU into 2MHz mode. Note: This will disable video when in - * 40 column mode. - */ +** 40 column mode. +*/ void slow (void); /* Switch the CPU into 1MHz mode. */ diff --git a/include/cbm.h b/include/cbm.h index ed7397849..730b0b49e 100644 --- a/include/cbm.h +++ b/include/cbm.h @@ -82,8 +82,8 @@ /* The file stream implementation and the POSIX I/O functions will - * use the following variable to determine the file type to use. - */ +** use the following variable to determine the file type to use. +*/ extern char _filetype; /* Defaults to 's' */ @@ -162,10 +162,10 @@ unsigned char get_tv (void); /* Constants to use with cbm_open() for openning a file for reading or - * writing without the need to append ",r" or ",w" to the filename. - * - * e.g., cbm_open(2, 8, CBM_READ, "0:data,s"); - */ +** writing without the need to append ",r" or ",w" to the filename. +** +** e.g., cbm_open(2, 8, CBM_READ, "0:data,s"); +*/ #define CBM_READ 0 /* default is ",p" */ #define CBM_WRITE 1 /* ditto */ #define CBM_SEQ 2 /* default is ",r" -- or ",s" when writing */ @@ -202,79 +202,79 @@ void cbm_k_unlsn (void); /* The cbm_* I/O functions below set _oserror (see errno.h), - * in case of an error. - * - * error-code BASIC error - * ---------- ----------- - * 1 = too many files - * 2 = file open - * 3 = file not open - * 4 = file not found - * 5 = device not present - * 6 = not input-file - * 7 = not output-file - * 8 = missing file-name - * 9 = illegal device-number - * - * 10 = STOP-key pushed - * 11 = general I/O-error - */ +** in case of an error. +** +** error-code BASIC error +** ---------- ----------- +** 1 = too many files +** 2 = file open +** 3 = file not open +** 4 = file not found +** 5 = device not present +** 6 = not input-file +** 7 = not output-file +** 8 = missing file-name +** 9 = illegal device-number +** +** 10 = STOP-key pushed +** 11 = general I/O-error +*/ unsigned int cbm_load (const char* name, unsigned char device, void* data); /* Loads file "name", from given device, to given address -- or, to the load - * address of the file if "data" is the null pointer (like load"name",8,1 - * in BASIC). - * Returns number of bytes that were loaded if loading was successful; - * otherwise 0, "_oserror" contains an error-code, then (see table above). - */ +** address of the file if "data" is the null pointer (like load"name",8,1 +** in BASIC). +** Returns number of bytes that were loaded if loading was successful; +** otherwise 0, "_oserror" contains an error-code, then (see table above). +*/ unsigned char __fastcall__ cbm_save (const char* name, unsigned char device, const void* addr, unsigned int size); /* Saves "size" bytes, starting at "addr", to a file. - * Returns 0 if saving was successful, otherwise an error-code (see table - * above). - */ +** Returns 0 if saving was successful, otherwise an error-code (see table +** above). +*/ unsigned char __fastcall__ cbm_open (unsigned char lfn, unsigned char device, unsigned char sec_addr, const char* name); /* Opens a file. Works just like the BASIC command. - * Returns 0 if openning was successful, otherwise an error-code (see table - * above). - */ +** Returns 0 if openning was successful, otherwise an error-code (see table +** above). +*/ void __fastcall__ cbm_close (unsigned char lfn); /* Closes a file */ int __fastcall__ cbm_read (unsigned char lfn, void* buffer, unsigned int size); /* Reads up to "size" bytes from a file into "buffer". - * Returns the number of actually-read bytes, 0 if there are no bytes left. - * -1 in case of an error; then, _oserror contains an error-code (see table - * above). (Remember: 0 means end-of-file; -1 means error.) - */ +** Returns the number of actually-read bytes, 0 if there are no bytes left. +** -1 in case of an error; then, _oserror contains an error-code (see table +** above). (Remember: 0 means end-of-file; -1 means error.) +*/ int __fastcall__ cbm_write (unsigned char lfn, const void* buffer, unsigned int size); /* Writes up to "size" bytes from "buffer" to a file. - * Returns the number of actually-written bytes, or -1 in case of an error; - * _oserror contains an error-code, then (see above table). - */ +** Returns the number of actually-written bytes, or -1 in case of an error; +** _oserror contains an error-code, then (see above table). +*/ unsigned char cbm_opendir (unsigned char lfn, unsigned char device, ...); /* Opens directory listing. Returns 0 if opening directory was successful; - * otherwise, an error-code corresponding to cbm_open(). As an optional - * argument, the name of the directory may be passed to the function. If - * no explicit name is specified, "$" is used. - */ +** otherwise, an error-code corresponding to cbm_open(). As an optional +** argument, the name of the directory may be passed to the function. If +** no explicit name is specified, "$" is used. +*/ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, struct cbm_dirent* l_dirent); /* Reads one directory line into cbm_dirent structure. - * Returns 0 if reading directory-line was successful. - * Returns non-zero if reading directory failed, or no more file-names to read. - * Returns 2 on last line. Then, l_dirent->size = the number of "blocks free." - */ +** Returns 0 if reading directory-line was successful. +** Returns non-zero if reading directory failed, or no more file-names to read. +** Returns 2 on last line. Then, l_dirent->size = the number of "blocks free." +*/ void __fastcall__ cbm_closedir (unsigned char lfn); /* Closes directory by cbm_close(lfn) */ diff --git a/include/cbm610.h b/include/cbm610.h index 84ea12ece..79d498431 100644 --- a/include/cbm610.h +++ b/include/cbm610.h @@ -138,9 +138,9 @@ void __fastcall__ pokewsys (unsigned addr, unsigned val); /* The following #defines will cause the matching functions calls in conio.h - * to be overlaid by macros with the same names, saving the function call - * overhead. - */ +** to be overlaid by macros with the same names, saving the function call +** overhead. +*/ #define _textcolor(color) COLOR_WHITE #define _bgcolor(color) COLOR_BLACK #define _bordercolor(color) COLOR_BLACK diff --git a/include/cbm_filetype.h b/include/cbm_filetype.h index 0263f33ae..e049eb306 100644 --- a/include/cbm_filetype.h +++ b/include/cbm_filetype.h @@ -52,9 +52,9 @@ /* CBM FILE TYPES. The definitions are used within standard headers, so we - * be careful with identifiers in the user name space. - * "Regular" files have a special bit set so it's easier to pick them out. - */ +** be careful with identifiers in the user name space. +** "Regular" files have a special bit set so it's easier to pick them out. +*/ #define _CBM_T_REG 0x10U /* Bit set for regular files */ #define _CBM_T_SEQ 0x10U #define _CBM_T_PRG 0x11U @@ -93,12 +93,12 @@ unsigned char __fastcall__ _cbm_filetype (unsigned char c); /* Map the start character for a file type to one of the file types above. - * Note: 'd' will always mapped to CBM_T_DEL. The calling function has to - * look at the following character to determine if the file type is actually - * CBM_T_DIR. - * This is a function used by the implementation. There is usually no need - * to call it from user code. - */ +** Note: 'd' will always mapped to CBM_T_DEL. The calling function has to +** look at the following character to determine if the file type is actually +** CBM_T_DIR. +** This is a function used by the implementation. There is usually no need +** to call it from user code. +*/ diff --git a/include/cc65.h b/include/cc65.h index 5607eab7b..4f9f3067f 100644 --- a/include/cc65.h +++ b/include/cc65.h @@ -46,17 +46,17 @@ long __fastcall__ cc65_idiv32by16r16 (long rhs, int lhs); /* Divide a 32 bit signed value by a 16 bit signed value yielding a 16 - * bit result and a 16 bit remainder. The former is returned in the lower 16 - * bit of the result, the latter in the upper. If you don't need the - * remainder, just assign (or cast) to an int. - */ +** bit result and a 16 bit remainder. The former is returned in the lower 16 +** bit of the result, the latter in the upper. If you don't need the +** remainder, just assign (or cast) to an int. +*/ unsigned long __fastcall__ cc65_udiv32by16r16 (unsigned long rhs, unsigned lhs); /* Divide a 32 bit unsigned value by a 16 bit unsigned value yielding a 16 - * bit result and a 16 bit remainder. The former is returned in the lower 16 - * bit of the result, the latter in the upper. If you don't need the - * remainder, just assign (or cast) to an unsigned. - */ +** bit result and a 16 bit remainder. The former is returned in the lower 16 +** bit of the result, the latter in the upper. If you don't need the +** remainder, just assign (or cast) to an unsigned. +*/ int __fastcall__ cc65_imul8x8r16 (signed char lhs, signed char rhs); /* Multiplicate two signed 8 bit to yield an signed 16 bit result */ @@ -69,21 +69,21 @@ unsigned __fastcall__ cc65_umul8x8r16 (unsigned char lhs, unsigned char rhs); unsigned long __fastcall__ cc65_umul16x8r32 (unsigned lhs, unsigned char rhs); /* Multiplicate an unsigned 16 bit by an unsigned 8 bit number yielding a 24 - * bit unsigned result that is extended to 32 bits for easier handling from C. - */ +** bit unsigned result that is extended to 32 bits for easier handling from C. +*/ unsigned long __fastcall__ cc65_umul16x16r32 (unsigned lhs, unsigned rhs); /* Multiplicate two unsigned 16 bit to yield an unsigned 32 bit result */ int __fastcall__ cc65_sin (unsigned x); /* Return the sine of the argument, which must be in range 0..360. The result - * is in 8.8 fixed point format, which means that 1.0 = $100 and -1.0 = $FF00. - */ +** is in 8.8 fixed point format, which means that 1.0 = $100 and -1.0 = $FF00. +*/ int __fastcall__ cc65_cos (unsigned x); /* Return the cosine of the argument, which must be in range 0..360. The result - * is in 8.8 fixed point format, which means that 1.0 = $100 and -1.0 = $FF00. - */ +** is in 8.8 fixed point format, which means that 1.0 = $100 and -1.0 = $FF00. +*/ diff --git a/include/conio.h b/include/conio.h index cd6bf3651..54667a3ca 100644 --- a/include/conio.h +++ b/include/conio.h @@ -34,18 +34,18 @@ /* - * This is the direct console interface for cc65. I do not like the function - * names very much, but the first version started as a rewrite of Borland's - * conio, and, even if the interface has changed, the names did not. - * - * The interface does direct screen I/O, so it is fast enough for most - * programs. I did not implement text windows, since many applications do - * not need them and should not pay for the additional overhead. It should - * be easy to add text windows on a higher level if needed, - * - * Most routines do not check the parameters. This may be unfortunate but is - * also related to speed. The coordinates are always 0/0 based. - */ +** This is the direct console interface for cc65. I do not like the function +** names very much, but the first version started as a rewrite of Borland's +** conio, and, even if the interface has changed, the names did not. +** +** The interface does direct screen I/O, so it is fast enough for most +** programs. I did not implement text windows, since many applications do +** not need them and should not pay for the additional overhead. It should +** be easy to add text windows on a higher level if needed, +** +** Most routines do not check the parameters. This may be unfortunate but is +** also related to speed. The coordinates are always 0/0 based. +*/ @@ -128,9 +128,9 @@ int __fastcall__ vcprintf (const char* format, va_list ap); char cgetc (void); /* Return a character from the keyboard. If there is no character available, - * the function waits until the user does press a key. If cursor is set to - * 1 (see below), a blinking cursor is displayed while waiting. - */ +** the function waits until the user does press a key. If cursor is set to +** 1 (see below), a blinking cursor is displayed while waiting. +*/ int cscanf (const char* format, ...); /* Like scanf(), but uses direct keyboard input */ @@ -140,14 +140,14 @@ int __fastcall__ vcscanf (const char* format, va_list ap); unsigned char __fastcall__ cursor (unsigned char onoff); /* If onoff is 1, a cursor is displayed when waiting for keyboard input. If - * onoff is 0, the cursor is hidden when waiting for keyboard input. The - * function returns the old cursor setting. - */ +** onoff is 0, the cursor is hidden when waiting for keyboard input. The +** function returns the old cursor setting. +*/ unsigned char __fastcall__ revers (unsigned char onoff); /* Enable/disable reverse character display. This may not be supported by - * the output device. Return the old setting. - */ +** the output device. Return the old setting. +*/ unsigned char __fastcall__ textcolor (unsigned char color); /* Set the color for text output. The old color setting is returned. */ @@ -160,16 +160,16 @@ unsigned char __fastcall__ bordercolor (unsigned char color); void __fastcall__ chline (unsigned char length); /* Output a horizontal line with the given length starting at the current - * cursor position. - */ +** cursor position. +*/ void __fastcall__ chlinexy (unsigned char x, unsigned char y, unsigned char length); /* Same as "gotoxy (x, y); chline (length);" */ void __fastcall__ cvline (unsigned char length); /* Output a vertical line with the given length at the current cursor - * position. - */ +** position. +*/ void __fastcall__ cvlinexy (unsigned char x, unsigned char y, unsigned char length); /* Same as "gotoxy (x, y); cvline (length);" */ @@ -196,14 +196,14 @@ void __fastcall__ cputhex16 (unsigned val); /* On some platforms, functions are not available or are dummys. To suppress - * the call to these functions completely, the platform header files may - * define macros for these functions that start with an underline. If such a - * macro exists, a new macro is defined here, that expands to the one with the - * underline. The reason for this two stepped approach is that it is sometimes - * necessary to take the address of the function, which is not possible when - * using a macro. Since the function prototype is still present, #undefining - * the macro will give access to the actual function. - */ +** the call to these functions completely, the platform header files may +** define macros for these functions that start with an underline. If such a +** macro exists, a new macro is defined here, that expands to the one with the +** underline. The reason for this two stepped approach is that it is sometimes +** necessary to take the address of the function, which is not possible when +** using a macro. Since the function prototype is still present, #undefining +** the macro will give access to the actual function. +*/ #if defined(_textcolor) # define textcolor(x) _textcolor(x) diff --git a/include/ctype.h b/include/ctype.h index 4c7f976d2..b440bfb70 100644 --- a/include/ctype.h +++ b/include/ctype.h @@ -85,12 +85,12 @@ unsigned char __fastcall__ toascii (unsigned char c); /* When inlining-of-known-functions is enabled, overload most of the above - * functions by macroes. The function prototypes are available again after - * #undef'ing the macroes. - * Please note that the following macroes do NOT handle EOF correctly, as - * stated in the manual. If you need correct behaviour for EOF, don't - * use -Os, or #undefine the following macroes. - */ +** functions by macroes. The function prototypes are available again after +** #undef'ing the macroes. +** Please note that the following macroes do NOT handle EOF correctly, as +** stated in the manual. If you need correct behaviour for EOF, don't +** use -Os, or #undefine the following macroes. +*/ #ifdef __OPT_s__ #define isalnum(c) (__AX__ = (c), \ diff --git a/include/dbg.h b/include/dbg.h index 5156658f0..734ca06b8 100644 --- a/include/dbg.h +++ b/include/dbg.h @@ -34,24 +34,24 @@ /* - * This is the interface to the cc65 debugger. Since many of the functions - * used for the debugger are quite usable even in another context, they - * are declared here. - * - * To use the debugger, just call DbgInit in your application. Once it has - * been called, the debugger will catch any BRK opcode. Use the BREAK macro - * defined below to insert breakpoints into your code. - * - * There are currently a lot of things that cannot be debugged, graphical - * applications are an example. The debugger does not save your screen - * contents, so even your text screen gets destroyed. However, you can - * debug the C and runtime library, even if the debugger is using this - * stuff itself. - * - * Note: When using the debugger, there are some other identifiers with - * external linkage, that start with Dbg. Avoid those names if you use the - * module. - */ +** This is the interface to the cc65 debugger. Since many of the functions +** used for the debugger are quite usable even in another context, they +** are declared here. +** +** To use the debugger, just call DbgInit in your application. Once it has +** been called, the debugger will catch any BRK opcode. Use the BREAK macro +** defined below to insert breakpoints into your code. +** +** There are currently a lot of things that cannot be debugged, graphical +** applications are an example. The debugger does not save your screen +** contents, so even your text screen gets destroyed. However, you can +** debug the C and runtime library, even if the debugger is using this +** stuff itself. +** +** Note: When using the debugger, there are some other identifiers with +** external linkage, that start with Dbg. Avoid those names if you use the +** module. +*/ @@ -68,35 +68,35 @@ unsigned __fastcall__ DbgDisAsm (unsigned Addr, char* Buf, unsigned char Len); /* Disassemble one instruction at address addr into the given buffer. - * The resulting line has the format, "AAAA__BB_BB_BB___OPC_OPERAND", - * where AAAA is the hexadecimal representation of addr, BB are the - * bytes (in hex) that make the instruction, OPC is the mnemonic, and - * OPERAND is an operand for the instruction. - * The buffer is filled with spaces up to the given length and terminated as - * a usual C string. NOTE: Buf must be able to hold Len+1 characters. - * The function returns the length of the disassembled instruction, so, - * to disassemble the next instruction, add the return value to addr - * and call the function again. - */ +** The resulting line has the format, "AAAA__BB_BB_BB___OPC_OPERAND", +** where AAAA is the hexadecimal representation of addr, BB are the +** bytes (in hex) that make the instruction, OPC is the mnemonic, and +** OPERAND is an operand for the instruction. +** The buffer is filled with spaces up to the given length and terminated as +** a usual C string. NOTE: Buf must be able to hold Len+1 characters. +** The function returns the length of the disassembled instruction, so, +** to disassemble the next instruction, add the return value to addr +** and call the function again. +*/ unsigned __fastcall__ DbgDisAsmLen (unsigned Addr); /* Disassemble one instruction, but do only return the length, do not - * create a visible representation. This function is useful when - * disassembling backwards, it is much faster than DbgDisAsm. - */ +** create a visible representation. This function is useful when +** disassembling backwards, it is much faster than DbgDisAsm. +*/ int __fastcall__ DbgIsRAM (unsigned Addr); /* Return true if we can read and write the given address */ char* DbgMemDump (unsigned Addr, char* Buf, unsigned char Len); /* Create a line of a memory dump in the given buffer. The buffer contains - * the starting address (4 digits hex), then Len bytes in this format: - * "AAAA__XX_YY_ZZ_...". The passed char buffer must hold Len*3+5 bytes - * plus a terminator byte. - * The function does not work correctly if the created string is longer - * than 255 bytes. - * The return value is Buf. - */ +** the starting address (4 digits hex), then Len bytes in this format: +** "AAAA__XX_YY_ZZ_...". The passed char buffer must hold Len*3+5 bytes +** plus a terminator byte. +** The function does not work correctly if the created string is longer +** than 255 bytes. +** The return value is Buf. +*/ @@ -108,8 +108,8 @@ char* DbgMemDump (unsigned Addr, char* Buf, unsigned char Len); void __fastcall__ DbgInit (unsigned unused); /* Initialize the debugger. Use 0 as parameter. The debugger will popup on - * next brk encountered. - */ +** next brk encountered. +*/ #define BREAK() __asm__ ("brk") /* Use this to insert breakpoints into your code */ diff --git a/include/dio.h b/include/dio.h index 1ccc1ab7c..4201728cc 100644 --- a/include/dio.h +++ b/include/dio.h @@ -36,10 +36,10 @@ /* Please note: All functions in this file will set _oserror *and* return its - * value. The only exception is dio_open, which will return NULL, but _oserror - * will be set. All function will also set _oserror in case of successful - * execution, effectively clearing it. - */ +** value. The only exception is dio_open, which will return NULL, but _oserror +** will be set. All function will also set _oserror in case of successful +** execution, effectively clearing it. +*/ diff --git a/include/em.h b/include/em.h index 28836f2b1..b151800ae 100644 --- a/include/em.h +++ b/include/em.h @@ -56,10 +56,10 @@ #define EM_ERR_INSTALLED 5 /* A driver is already installed */ /* Parameters for the em_copy_... functions. NOTE: The first seven bytes - * have the same order and alignment as needed for the Commodore REU, so - * don't change the order without changing the assembler file that defines - * the struct offsets and the code in the REU driver. - */ +** have the same order and alignment as needed for the Commodore REU, so +** don't change the order without changing the assembler file that defines +** the struct offsets and the code in the REU driver. +*/ struct em_copy { void* buf; /* Memory buffer to copy from or to */ unsigned char offs; /* Offset into page */ @@ -87,44 +87,44 @@ unsigned char __fastcall__ em_install (void* driver); unsigned char em_uninstall (void); /* Uninstall the currently loaded driver and return an error code. - * Note: This call does not free allocated memory. - */ +** Note: This call does not free allocated memory. +*/ unsigned em_pagecount (void); /* Return the total number of 256 byte pages available in extended memory. */ void* __fastcall__ em_map (unsigned page); /* Unmap the current page from memory and map a new one. The function returns - * a pointer to the location of the page in memory. Note: Without calling - * em_commit, the old contents of the memory window may be lost! - */ +** a pointer to the location of the page in memory. Note: Without calling +** em_commit, the old contents of the memory window may be lost! +*/ void* __fastcall__ em_use (unsigned page); /* Tell the driver that the memory window is associated with a given page. - * This call is very similar to em_map. The difference is that the driver - * does not necessarily transfer the current contents of the extended - * memory into the returned window. If you're going to just write to the - * window and the current contents of the window are invalid or no longer - * use, this call may perform better than em_map. - */ +** This call is very similar to em_map. The difference is that the driver +** does not necessarily transfer the current contents of the extended +** memory into the returned window. If you're going to just write to the +** window and the current contents of the window are invalid or no longer +** use, this call may perform better than em_map. +*/ void em_commit (void); /* Commit changes in the memory window to extended storage. If the contents - * of the memory window have been changed, these changes may be lost if - * em_map, em_copyfrom or em_copyto are called without calling em_commit - * first. Note: Not calling em_commit does not mean that the changes are - * discarded, it does just mean that some drivers will discard the changes. - */ +** of the memory window have been changed, these changes may be lost if +** em_map, em_copyfrom or em_copyto are called without calling em_commit +** first. Note: Not calling em_commit does not mean that the changes are +** discarded, it does just mean that some drivers will discard the changes. +*/ void __fastcall__ em_copyfrom (const struct em_copy* copy_data); /* Copy from extended into linear memory. Note: This may invalidate the - * currently mapped page. - */ +** currently mapped page. +*/ void __fastcall__ em_copyto (const struct em_copy* copy_data); /* Copy from linear into extended memory. Note: This may invalidate the - * currently mapped page. - */ +** currently mapped page. +*/ diff --git a/include/em/em-kernel.h b/include/em/em-kernel.h index 48cbbe8f7..e5df80321 100644 --- a/include/em/em-kernel.h +++ b/include/em/em-kernel.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2002-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -45,8 +45,8 @@ /* A structure that describes the header of an extended memory driver loaded - * into memory. - */ +** into memory. +*/ typedef struct { /* Driver header */ diff --git a/include/errno.h b/include/errno.h index 468e7d4ea..0b3d67bc7 100644 --- a/include/errno.h +++ b/include/errno.h @@ -84,23 +84,23 @@ extern int _errno; int __fastcall__ _osmaperrno (unsigned char oserror); /* Map an operating system specific error code (for example from _oserror) - * into one of the E... codes above. It is user callable. - */ +** into one of the E... codes above. It is user callable. +*/ unsigned char __fastcall__ _seterrno (unsigned char code); /* Set errno to a specific error code and return zero. Used by the library */ int __fastcall__ _directerrno (unsigned char code); /* Set errno to a specific error code, clear _oserror and return -1. Used - * by the library. - */ +** by the library. +*/ int __fastcall__ _mappederrno (unsigned char code); /* Set _oserror to the given platform specific error code. If it is a real - * error code (not zero) set errno to the corresponding system error code - * and return -1. Otherwise return zero. - * Used by the library. - */ +** error code (not zero) set errno to the corresponding system error code +** and return -1. Otherwise return zero. +** Used by the library. +*/ diff --git a/include/inttypes.h b/include/inttypes.h index dd1ba822b..65003f887 100644 --- a/include/inttypes.h +++ b/include/inttypes.h @@ -34,9 +34,9 @@ /* Note: This file is not fully ISO 9899-1999 compliant because cc65 lacks - * a 64 bit data types and is not able to return structs > 4 bytes. The - * declarations have been adjusted accordingly or left out. - */ +** a 64 bit data types and is not able to return structs > 4 bytes. The +** declarations have been adjusted accordingly or left out. +*/ diff --git a/include/joystick.h b/include/joystick.h index 18b552f08..710d9b5a6 100644 --- a/include/joystick.h +++ b/include/joystick.h @@ -99,8 +99,8 @@ unsigned char __fastcall__ joy_install (void* driver); unsigned char joy_uninstall (void); /* Uninstall the currently loaded driver and return an error code. - * Note: This call does not free allocated memory. - */ +** Note: This call does not free allocated memory. +*/ unsigned char joy_count (void); /* Return the number of joysticks supported by the driver */ diff --git a/include/joystick/joy-kernel.h b/include/joystick/joy-kernel.h index e617a43c5..bb571de3d 100644 --- a/include/joystick/joy-kernel.h +++ b/include/joystick/joy-kernel.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2002-2006, Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -45,8 +45,8 @@ /* A structure that describes the header of a joystick driver loaded into - * memory. - */ +** memory. +*/ typedef struct { /* Driver header */ @@ -88,4 +88,3 @@ void joy_clear_ptr (void); - diff --git a/include/modload.h b/include/modload.h index 04ad54d79..421641a90 100644 --- a/include/modload.h +++ b/include/modload.h @@ -34,8 +34,8 @@ /* Exports structures and functions to load relocatable o65 modules at - * runtime. - */ +** runtime. +*/ @@ -45,22 +45,22 @@ /* The following struct is passed to the module loader. It contains stuff, - * the loader needs to work, and another area where the loader will place - * informational data if it was successful. You will have to check the return - * code of mod_load before accessing any of these additional struct members. - */ +** the loader needs to work, and another area where the loader will place +** informational data if it was successful. You will have to check the return +** code of mod_load before accessing any of these additional struct members. +*/ struct mod_ctrl { /* Parameters passed into the loader routine. The member callerdata - * is an opaque 16 bit datatype that may be used by the caller to - * pass data through to the read routine. The read routine is used by the - * loader to load any required data. There are several calls where the - * read routine is passed a count of 1, so you may choose to make this - * a special case when implementing read(). The read() should return the - * number of bytes actually read. If the return value differs from the - * passed count, this is considered an error. - * NOTE: read() is designed so that the POSIX read() routine can be used - * for this vector, if you're loading from disk. - */ + ** is an opaque 16 bit datatype that may be used by the caller to + ** pass data through to the read routine. The read routine is used by the + ** loader to load any required data. There are several calls where the + ** read routine is passed a count of 1, so you may choose to make this + ** a special case when implementing read(). The read() should return the + ** number of bytes actually read. If the return value differs from the + ** passed count, this is considered an error. + ** NOTE: read() is designed so that the POSIX read() routine can be used + ** for this vector, if you're loading from disk. + */ int __fastcall__ (*read) (int callerdata, void* buffer, unsigned count); int callerdata; @@ -74,15 +74,15 @@ struct mod_ctrl { unsigned char __fastcall__ mod_load (struct mod_ctrl* ctrl); /* Load a module into memory and relocate it. The function will return an - * error code (see below). If MLOAD_OK is returned, the outgoing fields in - * the passed mod_ctrl struct contain information about the module just - * loaded. - */ +** error code (see below). If MLOAD_OK is returned, the outgoing fields in +** the passed mod_ctrl struct contain information about the module just +** loaded. +*/ void __fastcall__ mod_free (void* module); /* Free a loaded module. Note: The given pointer is the pointer to the - * module memory, not a pointer to a control structure. - */ +** module memory, not a pointer to a control structure. +*/ diff --git a/include/mouse.h b/include/mouse.h index 5e69c7ff6..ac75956c0 100644 --- a/include/mouse.h +++ b/include/mouse.h @@ -79,26 +79,36 @@ struct mouse_box { }; /* Structure containing mouse callback functions. These functions are declared - * in C notation here, but they cannot be C functions (at least not easily), - * since they may be called from within an interrupt. - */ +** in C notation here, but they cannot be C functions (at least not easily), +** since they may be called from within an interrupt. +*/ struct mouse_callbacks { void (*hide) (void); /* Hide the mouse cursor. */ void (*show) (void); - /* Show the mouse cursor */ + /* Show the mouse cursor. */ + + void (*prep) (void); + /* Prepare to move the mouse cursor. This function is called, + ** even when the cursor is currently invisible. + */ + + void (*draw) (void); + /* Draw the mouse cursor. This function is called, + ** even when the cursor is currently invisible. + */ void __fastcall__ (*movex) (int x); /* Move the mouse cursor to the new X coordinate. This function is called, - * even when the cursor is currently invisible. - */ + ** even when the cursor is currently invisible. + */ void __fastcall__ (*movey) (int y); /* Move the mouse cursor to the new Y coordinate. This function is called, - * even when the cursor is currently invisible. - */ + ** even when the cursor is currently invisible. + */ }; @@ -145,43 +155,43 @@ const char* __fastcall__ mouse_geterrormsg (unsigned char code); void mouse_hide (void); /* Hide the mouse. The function manages a counter and may be called more than - * once. For each call to mouse_hide there must be a call to mouse_show to make - * the mouse visible again. - */ +** once. For each call to mouse_hide there must be a call to mouse_show to make +** the mouse visible again. +*/ void mouse_show (void); /* Show the mouse. See mouse_hide() for more information. */ void __fastcall__ mouse_setbox (const struct mouse_box* box); /* Set the bounding box for the mouse pointer movement. The mouse X and Y - * coordinates will never go outside the given box. - * NOTE: The function does *not* check if the mouse is currently inside the - * given margins. The proper way to use this function therefore is: - * - * - Hide the mouse - * - Set the bounding box - * - Place the mouse at the desired position - * - Show the mouse again. - * - * NOTE2: When setting the box to something that is larger than the actual - * screen, the positioning of the mouse cursor can fail. If such margins - * are really what you want, you have to use your own cursor routines. - */ +** coordinates will never go outside the given box. +** NOTE: The function does *not* check if the mouse is currently inside the +** given margins. The proper way to use this function therefore is: +** +** - Hide the mouse +** - Set the bounding box +** - Place the mouse at the desired position +** - Show the mouse again. +** +** NOTE2: When setting the box to something that is larger than the actual +** screen, the positioning of the mouse cursor can fail. If such margins +** are really what you want, you have to use your own cursor routines. +*/ void __fastcall__ mouse_getbox (struct mouse_box* box); /* Get the current bounding box for the mouse pointer movement. */ void __fastcall__ mouse_move (int x, int y); /* Set the mouse cursor to the given position. If a mouse cursor is defined - * and currently visible, the mouse cursor is also moved. - * NOTE: This function does not check if the given position is valid and - * inside the bounding box. - */ +** and currently visible, the mouse cursor is also moved. +** NOTE: This function does not check if the given position is valid and +** inside the bounding box. +*/ unsigned char mouse_buttons (void); /* Return a bit mask encoding the states of the mouse buttons. Use the - * MOUSE_BTN_XXX flags to decode a specific button. - */ +** MOUSE_BTN_XXX flags to decode a specific button. +*/ void __fastcall__ mouse_pos (struct mouse_pos* pos); /* Return the current mouse position. */ @@ -191,8 +201,8 @@ void __fastcall__ mouse_info (struct mouse_info* info); unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data); /* Call the driver-specific ioctl function. Return an error code. - * NON-PORTABLE! - */ +** NON-PORTABLE! +*/ diff --git a/include/o65.h b/include/o65.h index 2321cfe10..a50bf2fdd 100644 --- a/include/o65.h +++ b/include/o65.h @@ -34,12 +34,12 @@ /* This files exports structures and constants to handle the o65 relocatable - * file format as defined by Andre Fachat. See the original document under - * - * http://www.6502.org/users/andre/o65/fileformat.html - * - * for more information. - */ +** file format as defined by Andre Fachat. See the original document under +** +** http://www.6502.org/users/andre/o65/fileformat.html +** +** for more information. +*/ diff --git a/include/pen.h b/include/pen.h index bab6997df..e17f030b5 100644 --- a/include/pen.h +++ b/include/pen.h @@ -54,20 +54,20 @@ extern void __fastcall__ (*pen_adjuster) (unsigned char *pValue); void __fastcall__ pen_calibrate (unsigned char *XOffset); /* Ask the user to help to calibrate a lightpen. Changes the screen! - * A pointer to this function can be put into pen_adjuster. - */ +** A pointer to this function can be put into pen_adjuster. +*/ void __fastcall__ pen_adjust (const char *filename); /* Get a lightpen calibration value from a file if it exists. Otherwise, call - * pen_calibrate() to create a value; then, write it into a file, so that it - * will be available at the next time that the lightpen is used. - * Might change the screen. - * pen_adjust() is optional; if you want to use its feature, - * then it must be called before a driver is installed. - * Note: This function merely saves the file-name pointer, and sets - * the pen_adjuster pointer. The file will be read only when a driver - * is installed, and only if that driver wants to be calibrated. - */ +** pen_calibrate() to create a value; then, write it into a file, so that it +** will be available at the next time that the lightpen is used. +** Might change the screen. +** pen_adjust() is optional; if you want to use its feature, +** then it must be called before a driver is installed. +** Note: This function merely saves the file-name pointer, and sets +** the pen_adjuster pointer. The file will be read only when a driver +** is installed, and only if that driver wants to be calibrated. +*/ diff --git a/include/pet.h b/include/pet.h index 0588ee8bf..720e40a78 100644 --- a/include/pet.h +++ b/include/pet.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2005 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -92,9 +92,9 @@ extern void pet_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ /* The following #defines will cause the matching functions calls in conio.h - * to be overlaid by macros with the same names, saving the function call - * overhead. - */ +** to be overlaid by macros with the same names, saving the function call +** overhead. +*/ #define _textcolor(color) COLOR_WHITE #define _bgcolor(color) COLOR_BLACK #define _bordercolor(color) COLOR_BLACK diff --git a/include/serial.h b/include/serial.h index f88ab114e..990f66521 100644 --- a/include/serial.h +++ b/include/serial.h @@ -67,6 +67,7 @@ #define SER_BAUD_230400 0x13 #define SER_BAUD_31250 0x14 #define SER_BAUD_62500 0x15 +#define SER_BAUD_56_875 0x16 /* Data bit settings */ #define SER_BITS_5 0x00 @@ -91,8 +92,8 @@ #define SER_HS_SW 0x02 /* Software handshake */ /* Bit masks to mask out things from the status returned by ser_status. - * These are 6551 specific and must be mapped by drivers for other chips. - */ +** These are 6551 specific and must be mapped by drivers for other chips. +*/ #define SER_STATUS_PE 0x01 /* Parity error */ #define SER_STATUS_FE 0x02 /* Framing error */ #define SER_STATUS_OE 0x04 /* Overrun error */ @@ -111,6 +112,7 @@ #define SER_ERR_INIT_FAILED 0x08 /* Initialization failed */ #define SER_ERR_INV_IOCTL 0x09 /* IOCTL not supported */ #define SER_ERR_INSTALLED 0x0A /* A driver is already installed */ +#define SER_ERR_NOT_OPEN 0x0B /* Driver is not open */ /* Struct containing parameters for the serial port */ struct ser_params { @@ -139,8 +141,8 @@ unsigned char __fastcall__ ser_install (void* driver); unsigned char ser_uninstall (void); /* Uninstall the currently loaded driver and return an error code. - * Note: This call does not free allocated memory. - */ +** Note: This call does not free allocated memory. +*/ unsigned char __fastcall__ ser_open (const struct ser_params* params); /* "Open" the port by setting the port parameters and enable interrupts. */ @@ -150,14 +152,14 @@ unsigned char ser_close (void); unsigned char __fastcall__ ser_get (char* b); /* Get a character from the serial port. If no characters are available, the - * function will return SER_ERR_NO_DATA, so this is not a fatal error. - */ +** function will return SER_ERR_NO_DATA, so this is not a fatal error. +*/ unsigned char __fastcall__ ser_put (char b); /* Send a character via the serial port. There is a transmit buffer, but - * transmitting is not done via interrupt. The function returns - * SER_ERR_OVERFLOW if there is no space left in the transmit buffer. - */ +** transmitting is not done via interrupt. The function returns +** SER_ERR_OVERFLOW if there is no space left in the transmit buffer. +*/ unsigned char __fastcall__ ser_status (unsigned char* status); /* Return the serial port status. */ diff --git a/include/stdint.h b/include/stdint.h index 0053a9bba..5d6f04769 100644 --- a/include/stdint.h +++ b/include/stdint.h @@ -34,8 +34,8 @@ /* Note: This file is not fully ISO 9899-1999 compliant because cc65 lacks - * a 64 bit data types. The declarations have been adjusted accordingly. - */ +** a 64 bit data types. The declarations have been adjusted accordingly. +*/ diff --git a/include/stdlib.h b/include/stdlib.h index 026e19198..eac5629a8 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -71,13 +71,13 @@ void __fastcall__ free (void* block); #if __CC65_STD__ == __CC65_STD_CC65__ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size); /* Allocate a block of memory with the given "size", which is aligned to a - * memory address that is a multiple of "alignment". "alignment" MUST NOT be - * zero, and MUST be a power of two; otherwise, this function will return - * EINVAL. The function returns ENOMEM if not enough memory is available - * to satisfy the request. "memptr" must point to a variable; that variable - * will return the address of the allocated memory. Use free() to release that - * allocated block. - */ +** memory address that is a multiple of "alignment". "alignment" MUST NOT be +** zero, and MUST be a power of two; otherwise, this function will return +** EINVAL. The function returns ENOMEM if not enough memory is available +** to satisfy the request. "memptr" must point to a variable; that variable +** will return the address of the allocated memory. Use free() to release that +** allocated block. +*/ #endif void __fastcall__ _heapadd (void* mem, size_t size); diff --git a/include/string.h b/include/string.h index 19cfba27e..46095a525 100644 --- a/include/string.h +++ b/include/string.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2008 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2014, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -65,8 +65,8 @@ void* __fastcall__ memmove (void* dest, const void* src, size_t count); void* __fastcall__ memset (void* s, int c, size_t count); /* The following is an internal function, the compiler will replace memset - * with it if the fill value is zero. Never use this one directly! - */ +** with it if the fill value is zero. Never use this one directly! +*/ void* __fastcall__ _bzero (void* ptr, size_t n); /* Non standard: */ @@ -81,6 +81,7 @@ char* __fastcall__ strlwr (char* s); char* __fastcall__ strlower (char* s); char* __fastcall__ strupr (char* s); char* __fastcall__ strupper (char* s); +char* __fastcall__ strqtok (char* s1, const char* s2); #endif const char* __fastcall__ _stroserror (unsigned char errcode); @@ -90,6 +91,3 @@ const char* __fastcall__ _stroserror (unsigned char errcode); /* End of string.h */ #endif - - - diff --git a/include/supervision.h b/include/supervision.h index 332fe973b..ffece4ecb 100644 --- a/include/supervision.h +++ b/include/supervision.h @@ -98,9 +98,9 @@ struct __sv_dma { /* Counters incremented asynchronously! - * If you want more complex, copy the crt0.s file from the libsrc/supervision - * directory and code them yourself (in assembler) - */ +** If you want more complex, copy the crt0.s file from the libsrc/supervision +** directory and code them yourself (in assembler) +*/ extern unsigned char sv_nmi_counter; extern unsigned char sv_timer_irq_counter; extern unsigned char sv_timer_dma_counter; diff --git a/include/sys/utsname.h b/include/sys/utsname.h index 28feecc46..a601d9eed 100644 --- a/include/sys/utsname.h +++ b/include/sys/utsname.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -45,30 +45,30 @@ /* - * Suggested field contents: - * - * sysname - * Should contain the name of the underlying operating system, or "cc65" - * if the program runs on the bare machine. - * - * nodename - * Is empty or may be defined by the implementor. - * - * release - * Contains the operating system release or the major/minor cc65 version - * if sysname contains "cc65". - * - * version - * Contains the operating system version or the cc65 patch version if - * sysname contains "cc65". - * - * machine - * Contains the complete name of the machine, like "Commodore 64", - * "Oric Atmos" or similar. - * - * Beware: The library sources written in assembler have knowledge about this - * struct! - */ +** Suggested field contents: +** +** sysname +** Should contain the name of the underlying operating system, or "cc65" +** if the program runs on the bare machine. +** +** nodename +** Is empty or may be defined by the implementor. +** +** release +** Contains the operating system release or the major/minor cc65 version +** if sysname contains "cc65". +** +** version +** Contains the operating system version or the cc65 patch version if +** sysname contains "cc65". +** +** machine +** Contains the complete name of the machine, like "Commodore 64", +** "Oric Atmos" or similar. +** +** Beware: The library sources written in assembler have knowledge about this +** struct! +*/ struct utsname { char sysname[17]; char nodename[9]; diff --git a/include/tgi.h b/include/tgi.h index a43eb0cc3..02dff8868 100644 --- a/include/tgi.h +++ b/include/tgi.h @@ -80,44 +80,44 @@ void __fastcall__ tgi_load_driver (const char* name); void tgi_unload (void); /* Uninstall, then unload the currently loaded driver. Will call tgi_done if - * necessary. - */ +** necessary. +*/ void __fastcall__ tgi_install (void* driver); /* Install an already loaded driver. */ void tgi_uninstall (void); /* Uninstall the currently loaded driver but do not unload it. Will call - * tgi_done if necessary. - */ +** tgi_done if necessary. +*/ void tgi_init (void); /* Initialize the already loaded graphics driver. */ void tgi_done (void); /* End graphics mode, switch back to text mode. Will NOT uninstall or unload - * the driver! - */ +** the driver! +*/ const tgi_vectorfont* __fastcall__ tgi_load_vectorfont (const char* name); /* Load a vector font into memory and return it. In case of errors, NULL is - * returned and an error is set, which can be retrieved using tgi_geterror. - * To use the font, it has to be installed using tgi_install_vectorfont. - */ +** returned and an error is set, which can be retrieved using tgi_geterror. +** To use the font, it has to be installed using tgi_install_vectorfont. +*/ void __fastcall__ tgi_install_vectorfont (const tgi_vectorfont* font); /* Install a vector font for use. More than one vector font can be loaded, - * but only one can be active. This function is used to tell which one. Call - * with a NULL pointer to uninstall the currently installed font. - */ +** but only one can be active. This function is used to tell which one. Call +** with a NULL pointer to uninstall the currently installed font. +*/ void __fastcall__ tgi_free_vectorfont (const tgi_vectorfont* font); /* Free a vector font that was previously loaded into memory. */ unsigned char tgi_geterror (void); /* Return the error code for the last operation. This will also clear the - * error. - */ +** error. +*/ const char* __fastcall__ tgi_geterrormsg (unsigned char code); /* Get an error message describing the error in code. */ @@ -139,8 +139,8 @@ unsigned char tgi_getcolorcount (void); unsigned char tgi_getmaxcolor (void); /* Return the maximum supported color number (the number of colors would - * then be getmaxcolor()+1). - */ +** then be getmaxcolor()+1). +*/ void __fastcall__ tgi_setcolor (unsigned char color); /* Set the current drawing color. */ @@ -150,8 +150,8 @@ unsigned char tgi_getcolor (void); void __fastcall__ tgi_setpalette (const unsigned char* palette); /* Set the palette (not available with all drivers/hardware). palette is - * a pointer to as many entries as there are colors. - */ +** a pointer to as many entries as there are colors. +*/ const unsigned char* tgi_getpalette (void); /* Return the current palette. */ @@ -164,26 +164,26 @@ unsigned tgi_getxres (void); unsigned tgi_getmaxx (void); /* Return the maximum x coordinate. The resolution in x direction is - * getmaxx() + 1 - */ +** getmaxx() + 1 +*/ unsigned tgi_getyres (void); /* Return the resolution in Y direction. */ unsigned tgi_getmaxy (void); /* Return the maximum y coordinate. The resolution in y direction is - * getmaxy() + 1 - */ +** getmaxy() + 1 +*/ unsigned tgi_getaspectratio (void); /* Returns the aspect ratio for the loaded driver. The aspect ratio is an - * 8.8 fixed point value. - */ +** 8.8 fixed point value. +*/ void __fastcall__ tgi_setaspectratio (unsigned aspectratio); /* Set a new aspect ratio for the loaded driver. The aspect ratio is an - * 8.8 fixed point value. - */ +** 8.8 fixed point value. +*/ unsigned char __fastcall__ tgi_getpixel (int x, int y); /* Get the color value of a pixel. */ @@ -196,84 +196,89 @@ void __fastcall__ tgi_gotoxy (int x, int y); void __fastcall__ tgi_line (int x1, int y1, int x2, int y2); /* Draw a line in the current drawing color. The graphics cursor will - * be set to x2/y2 by this call. - */ +** be set to x2/y2 by this call. +*/ void __fastcall__ tgi_lineto (int x2, int y2); /* Draw a line in the current drawing color from the graphics cursor to the - * new end point. The graphics cursor will be updated to x2/y2. - */ +** new end point. The graphics cursor will be updated to x2/y2. +*/ void __fastcall__ tgi_circle (int x, int y, unsigned char radius); /* Draw a circle in the current drawing color. */ void __fastcall__ tgi_ellipse (int x, int y, unsigned char rx, unsigned char ry); /* Draw a full ellipse with center at x/y and radii rx/ry using the current - * drawing color. - */ +** drawing color. +*/ void __fastcall__ tgi_arc (int x, int y, unsigned char rx, unsigned char ry, unsigned sa, unsigned ea); /* Draw an ellipse arc with center at x/y and radii rx/ry using the current - * drawing color. The arc covers the angle between sa and ea (startangle and - * endangle), which must be in the range 0..360 (otherwise the function may - * bevave unextectedly). - */ +** drawing color. The arc covers the angle between sa and ea (startangle and +** endangle), which must be in the range 0..360 (otherwise the function may +** bevave unextectedly). +*/ void __fastcall__ tgi_pieslice (int x, int y, unsigned char rx, unsigned char ry, unsigned sa, unsigned ea); /* Draw an ellipse pie slice with center at x/y and radii rx/ry using the - * current drawing color. The pie slice covers the angle between sa and ea - * (startangle and endangle), which must be in the range 0..360 (otherwise the - * function may behave unextectedly). - */ +** current drawing color. The pie slice covers the angle between sa and ea +** (startangle and endangle), which must be in the range 0..360 (otherwise the +** function may behave unextectedly). +*/ void __fastcall__ tgi_bar (int x1, int y1, int x2, int y2); /* Draw a bar (a filled rectangle) using the current color. */ void __fastcall__ tgi_settextdir (unsigned char dir); /* Set the direction for text output. dir is one of the TGI_TEXT_XXX - * constants. - */ +** constants. +*/ void __fastcall__ tgi_settextscale (unsigned width, unsigned height); /* Set the scaling for text output. The scaling factors for width and height - * are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. - */ +** are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. +*/ void __fastcall__ tgi_settextstyle (unsigned width, unsigned height, unsigned char dir, unsigned char font); /* Set the style for text output. The scaling factors for width and height - * are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. - * dir is one of the TGI_TEXT_XXX constants. font is one of the TGI_FONT_XXX - * constants. - */ +** are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. +** dir is one of the TGI_TEXT_XXX constants. font is one of the TGI_FONT_XXX +** constants. +*/ unsigned __fastcall__ tgi_gettextwidth (const char* s); /* Calculate the width of the text in pixels according to the current text - * style. - */ +** style. +*/ unsigned __fastcall__ tgi_gettextheight (const char* s); /* Calculate the height of the text in pixels according to the current text - * style. - */ +** style. +*/ void __fastcall__ tgi_outtext (const char* s); /* Output text at the current graphics cursor position. The graphics cursor - * is moved to the end of the text. - */ +** is moved to the end of the text. +*/ void __fastcall__ tgi_outtextxy (int x, int y, const char* s); /* Output text at the given cursor position. The graphics cursor is moved to - * the end of the text. - */ +** the end of the text. +*/ unsigned __fastcall__ tgi_ioctl (unsigned char code, void* data); /* Call the driver specific control function. What this function does for - * a specific code depends on the driver. The driver will set an error - * for unknown codes or values. - */ +** a specific code depends on the driver. The driver will set an error +** for unknown codes or values. +*/ + +int __fastcall__ tgi_imulround (int rhs, int lhs); +/* Helper function for functions using sine/cosine: Multiply two values, one +** being an 8.8 fixed point one, and return the rounded and scaled result. +*/ diff --git a/include/tgi/tgi-kernel.h b/include/tgi/tgi-kernel.h index 8367e4453..bc5fdc3c6 100644 --- a/include/tgi/tgi-kernel.h +++ b/include/tgi/tgi-kernel.h @@ -67,19 +67,6 @@ extern unsigned tgi_charheight; /* Height of scaled bitmap font */ -/*****************************************************************************/ -/* Code */ -/*****************************************************************************/ - - - -int __fastcall__ tgi_imulround (int rhs, int lhs); -/* Helper function for functions using sine/cosine: Multiply two values, one - * being an 8.8 fixed point one, and return the rounded and scaled result. - */ - - - /* End of tgi-kernel.h */ #endif diff --git a/include/tgi/tgi-vectorfont.h b/include/tgi/tgi-vectorfont.h index 82513b271..9cbfc30fc 100644 --- a/include/tgi/tgi-vectorfont.h +++ b/include/tgi/tgi-vectorfont.h @@ -78,8 +78,8 @@ struct tgi_vectorfont { void __fastcall__ tgi_vectorchar (char C); /* Draw one character of the vector font at the current graphics cursor - * position using the current font magnification. - */ +** position using the current font magnification. +*/ diff --git a/include/time.h b/include/time.h index 507d7e29a..c70ffa718 100644 --- a/include/time.h +++ b/include/time.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2012 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -81,6 +81,9 @@ extern struct _timezone { unsigned _clocks_per_sec (void); # define CLK_TCK _clocks_per_sec() # define CLOCKS_PER_SEC _clocks_per_sec() +#elif defined(__ATARI5200__) +# define CLK_TCK 60 /* POSIX */ +# define CLOCKS_PER_SEC 60 /* ANSI */ #elif defined(__ATMOS__) # define CLK_TCK 100 /* POSIX */ # define CLOCKS_PER_SEC 100 /* ANSI */ @@ -101,7 +104,8 @@ unsigned _clocks_per_sec (void); # define CLOCKS_PER_SEC 1 /* ANSI */ #elif defined(__LYNX__) /* The clock-rate depends on the video scan-rate; -** so, read it at run-time. */ +** so, read it at run-time. +*/ extern clock_t _clk_tck (void); # define CLK_TCK _clk_tck() # define CLOCKS_PER_SEC _clk_tck() @@ -111,10 +115,10 @@ extern clock_t _clk_tck (void); time_t _systime (void); /* Similar to time(), but: - * - Is not ISO C - * - Does not take the additional pointer - * - Does not set errno when returning -1 - */ +** - Is not ISO C +** - Does not take the additional pointer +** - Does not set errno when returning -1 +*/ /* ISO C function prototypes */ char* __fastcall__ asctime (const struct tm* timep); diff --git a/libsrc/Makefile b/libsrc/Makefile index 9955d6d77..b35ae1e38 100644 --- a/libsrc/Makefile +++ b/libsrc/Makefile @@ -1,3 +1,7 @@ +ifneq ($(shell echo),) + CMD_EXE = 1 +endif + CBMS = c128 \ c16 \ c64 \ @@ -14,6 +18,7 @@ TARGETS = apple2 \ apple2enh \ atari \ atarixl \ + atari5200 \ atmos \ c1p \ $(CBMS) \ @@ -30,6 +35,27 @@ DRVTYPES = emd \ ser \ tgi +OUTPUTDIRS := lib \ + $(DRVTYPES) \ + targetutil \ + asminc \ + cfg \ + include \ + $(subst ../,,$(filter-out $(wildcard ../include/*.*),$(wildcard ../include/*))) + +.PHONY: all mostlyclean clean install zip lib $(TARGETS) + +.SUFFIXES: + +ifdef CMD_EXE + DIRLIST = $(strip $(foreach dir,$1,$(wildcard $(dir)))) + MKDIR = mkdir $(subst /,\,$1) + RMDIR = $(if $(DIRLIST),rmdir /s /q $(subst /,\,$(DIRLIST))) +else + MKDIR = mkdir -p $1 + RMDIR = $(RM) -r $1 +endif + # Every target requires its individual vpath setting but the vpath directive # acts globally. Therefore each target is built in a separate make instance. @@ -39,37 +65,55 @@ ifeq ($(words $(MAKECMDGOALS)),1) endif endif -DIRLIST = $(strip $(foreach dir,$1,$(wildcard $(dir)))) - -ifeq ($(shell echo),) - MKDIR = mkdir -p $1 - RMDIR = $(RM) -r $1 -else - MKDIR = mkdir $(subst /,\,$1) - RMDIR = $(if $(DIRLIST),rmdir /s /q $(subst /,\,$(DIRLIST))) -endif - -.SUFFIXES: - -.PHONY: all lib $(TARGETS) mostlyclean clean - ifndef TARGET +datadir = $(prefix)/share/cc65 + all lib: $(TARGETS) +mostlyclean: + $(call RMDIR,../libwrk) + +clean: + $(call RMDIR,../libwrk ../lib ../targetutil $(addprefix ../,$(DRVTYPES))) + +ifdef CMD_EXE + +install: + +else # CMD_EXE + +INSTALL = install + +define INSTALL_recipe + +$(if $(prefix),,$(error variable `prefix' must be set)) +$(INSTALL) -d $(DESTDIR)$(datadir)/$(dir) +$(INSTALL) -m644 ../$(dir)/*.* $(DESTDIR)$(datadir)/$(dir) + +endef # INSTALL_recipe + +install: + $(foreach dir,$(OUTPUTDIRS),$(INSTALL_recipe)) + +endif # CMD_EXE + +define ZIP_recipe + +@cd .. && zip cc65 $(dir)/*.* + +endef # ZIP_recipe + +zip: + $(foreach dir,$(OUTPUTDIRS),$(ZIP_recipe)) + $(TARGETS): @$(MAKE) --no-print-directory $@ -mostlyclean: - $(call RMDIR,../wrk) - -clean: - $(call RMDIR,../wrk ../lib ../targetutil $(addprefix ../,$(DRVTYPES))) - else # TARGET CA65FLAGS = -CC65FLAGS = -Osir -W error +CC65FLAGS = -Or -W error EXTZP = cbm510 \ cbm610 \ @@ -77,9 +121,12 @@ EXTZP = cbm510 \ MKINC = $(GEOS) \ atari \ + atarixl \ nes -TARGETUTIL = apple2 \ +TARGETUTIL = apple2 \ + apple2enh \ + atari \ geos-apple GEOSDIRS = common \ @@ -137,7 +184,7 @@ vpath %.c $(SRCDIRS) OBJS := $(patsubst %.s,%.o,$(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.s))) OBJS += $(patsubst %.c,%.o,$(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c))) -OBJS := $(addprefix ../wrk/$(TARGET)/,$(sort $(notdir $(OBJS)))) +OBJS := $(addprefix ../libwrk/$(TARGET)/,$(sort $(notdir $(OBJS)))) DEPS = $(OBJS:.o=.d) @@ -145,106 +192,96 @@ EXTRA_SRCPAT = $(SRCDIR)/extra/%.s EXTRA_OBJPAT = ../lib/$(TARGET)-%.o EXTRA_OBJS := $(patsubst $(EXTRA_SRCPAT),$(EXTRA_OBJPAT),$(wildcard $(SRCDIR)/extra/*.s)) -ZPOBJ = ../wrk/$(TARGET)/zeropage.o +ZPOBJ = ../libwrk/$(TARGET)/zeropage.o ifeq ($(TARGET),$(filter $(TARGET),$(EXTZP))) - ZPOBJ += ../wrk/$(TARGET)/extzp.o + ZPOBJ += ../libwrk/$(TARGET)/extzp.o endif -ifeq ($(SRCDIR),$(filter $(SRCDIR),$(MKINC))) +ifeq ($(TARGET),$(filter $(TARGET),$(MKINC))) include $(SRCDIR)/Makefile.inc endif -ifeq ($(SRCDIR),$(filter $(SRCDIR),$(TARGETUTIL))) +ifeq ($(TARGET),$(filter $(TARGET),$(TARGETUTIL))) include $(SRCDIR)/targetutil/Makefile.inc endif -########## - define DRVTYPE_template $1_SRCDIR = $$(SRCDIR)/$1 -$1_OBJDIR = ../wrk/$$(TARGET)/$1 +$1_STCDIR = ../libwrk/$$(TARGET) +$1_DYNDIR = ../libwrk/$$(TARGET)/$1 $1_DRVDIR = ../$1 -$1_OBJPAT = $$($1_OBJDIR)/$$(OBJPFX)%.o +$1_SRCPAT = $$($1_SRCDIR)/$$(OBJPFX)%.s +$1_STCPAT = $$($1_STCDIR)/$$(OBJPFX)%-$1.o +$1_DYNPAT = $$($1_DYNDIR)/$$(OBJPFX)%.o $1_DRVPAT = $$($1_DRVDIR)/$$(DRVPFX)%.$1 -$1_STCPAT = ../wrk/$$(TARGET)/$$(DRVPFX)%-$1.o -$1_OBJS := $$(patsubst $$($1_SRCDIR)/%.s,$$($1_OBJDIR)/%.o,$$(wildcard $$($1_SRCDIR)/*.s)) +$1_SRCS := $$(wildcard $$($1_SRCDIR)/*.s) +$1_STCS = $$(patsubst $$($1_SRCPAT),$$($1_STCPAT),$$($1_SRCS)) +$1_DYNS = $$(patsubst $$($1_SRCPAT),$$($1_DYNPAT),$$($1_SRCS)) +$1_DRVS = $$(patsubst $$($1_DYNPAT),$$($1_DRVPAT),$$($1_DYNS)) -$1_DRVS = $$(patsubst $$($1_OBJPAT),$$($1_DRVPAT),$$($1_OBJS)) +$$($1_STCPAT): $$($1_SRCPAT) + @echo $$(TARGET) - $$< - static + @$$(CA65) -t $$(TARGET) -D DYN_DRV=0 $$(CA65FLAGS) --create-dep $$(@:.o=.d) -o $$@ $$< -$1_STCS = $$(patsubst $$($1_DRVPAT),$$($1_STCPAT),$$($1_DRVS)) +OBJS += $$($1_STCS) +DEPS += $$($1_STCS:.o=.d) -$$($1_OBJS): | $$($1_OBJDIR) +$$($1_DYNS): | $$($1_DYNDIR) -$$($1_DRVPAT): $$($1_OBJPAT) $$(ZPOBJ) | $$($1_DRVDIR) - @echo $$(TARGET) - $$(@F) +$$($1_DRVPAT): $$($1_DYNPAT) $$(ZPOBJ) | $$($1_DRVDIR) + @echo $$(TARGET) - $$(<F) @$$(LD65) -o $$@ -t module $$^ -$$($1_OBJDIR) $$($1_DRVDIR): +$$($1_DYNDIR) $$($1_DRVDIR): @$$(call MKDIR,$$@) $(TARGET): $$($1_DRVS) -$$($1_STCPAT): $$($1_DRVPAT) - @echo $$(TARGET) - $$(<F) - @$$(CO65) -o $$(@:.o=.s) --code-label _$$(subst -,_,$$(subst .,_,$$(<F))) $$< - @$$(CA65) -t $$(TARGET) -o $$@ $$(@:.o=.s) +DEPS += $$($1_DYNS:.o=.d) -OBJS += $$($1_STCS) - -DEPS += $$($1_OBJS:.o=.d) - -endef - -########## +endef # DRVTYPE_template $(foreach drvtype,$(DRVTYPES),$(eval $(call DRVTYPE_template,$(drvtype)))) AR65 := $(if $(wildcard ../bin/ar65*),../bin/ar65,ar65) CA65 := $(if $(wildcard ../bin/ca65*),../bin/ca65,ca65) CC65 := $(if $(wildcard ../bin/cc65*),../bin/cc65,cc65) -CO65 := $(if $(wildcard ../bin/co65*),../bin/co65,co65) LD65 := $(if $(wildcard ../bin/ld65*),../bin/ld65,ld65) export CC65_HOME := $(abspath ..) -########## - define ASSEMBLE_recipe -$(if $(TRAVIS),,@echo $(TARGET) - $<) +$(if $(QUIET),,@echo $(TARGET) - $<) @$(CA65) -t $(TARGET) $(CA65FLAGS) --create-dep $(@:.o=.d) -o $@ $< -endef - -########## +endef # ASSEMBLE_recipe define COMPILE_recipe -$(if $(TRAVIS),,@echo $(TARGET) - $<) +$(if $(QUIET),,@echo $(TARGET) - $<) @$(CC65) -t $(TARGET) $(CC65FLAGS) --create-dep $(@:.o=.d) --dep-target $@ -o $(@:.o=.s) $< @$(CA65) -t $(TARGET) -o $@ $(@:.o=.s) -endef +endef # COMPILE_recipe -########## - -../wrk/$(TARGET)/%.o: %.s | ../wrk/$(TARGET) +../libwrk/$(TARGET)/%.o: %.s | ../libwrk/$(TARGET) $(ASSEMBLE_recipe) -../wrk/$(TARGET)/%.o: %.c | ../wrk/$(TARGET) +../libwrk/$(TARGET)/%.o: %.c | ../libwrk/$(TARGET) $(COMPILE_recipe) $(EXTRA_OBJPAT): $(EXTRA_SRCPAT) | ../lib - @echo $(TARGET) - $(@F) + @echo $(TARGET) - $(<F) @$(CA65) -t $(TARGET) $(CA65FLAGS) -o $@ $< ../lib/$(TARGET).lib: $(OBJS) | ../lib $(AR65) a $@ $? -../wrk/$(TARGET) ../lib ../targetutil: +../libwrk/$(TARGET) ../lib ../targetutil: @$(call MKDIR,$@) $(TARGET): $(EXTRA_OBJS) ../lib/$(TARGET).lib diff --git a/libsrc/apple2/crt0.s b/libsrc/apple2/crt0.s index 27c44f016..4a7463b27 100644 --- a/libsrc/apple2/crt0.s +++ b/libsrc/apple2/crt0.s @@ -24,76 +24,76 @@ ldx #$FF txs ; Init stack pointer - ; Switch in LC bank 2 for W/O + ; Switch in LC bank 2 for W/O. bit $C081 bit $C081 - ; Set source start address + ; Set the source start address. lda #<(__ZPSAVE_RUN__ + __INIT_SIZE__) ldy #>(__ZPSAVE_RUN__ + __INIT_SIZE__) sta $9B sty $9C - ; Set source last address + ; Set the source last address. lda #<(__ZPSAVE_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__) ldy #>(__ZPSAVE_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__) sta $96 sty $97 - ; Set destination last address + ; Set the destination last address. lda #<__LC_LAST__ ldy #>__LC_LAST__ sta $94 sty $95 - ; Call into Applesoft Block Transfer Utility - which handles zero - ; sized blocks well - to move content of the LC memory area + ; Call into the Applesoft Block Transfer Utility -- which handles zero- + ; sized blocks well -- to move the content of the LC memory area. jsr $D396 ; BLTU + 3 - ; Set source start address + ; Set the source start address. lda #<__ZPSAVE_RUN__ ldy #>__ZPSAVE_RUN__ sta $9B sty $9C - ; Set source last address + ; Set the source last address. lda #<(__ZPSAVE_RUN__ + __INIT_SIZE__) ldy #>(__ZPSAVE_RUN__ + __INIT_SIZE__) sta $96 sty $97 - ; Set destination last address + ; Set the destination last address. lda #<(__INIT_RUN__ + __INIT_SIZE__) ldy #>(__INIT_RUN__ + __INIT_SIZE__) sta $94 sty $95 - ; Call into Applesoft Block Transfer Utility - which handles moving - ; overlapping blocks upwards well - to move the INIT segment + ; Call into the Applesoft Block Transfer Utility -- which handles moving + ; overlapping blocks upwards well -- to move the INIT segment. jsr $D396 ; BLTU + 3 - ; Delegate all further processing to keep the STARTUP segment small + ; Delegate all further processing, to keep the STARTUP segment small. jsr init - ; Avoid re-entrance of donelib. This is also the _exit entry + ; Avoid a re-entrance of donelib. This is also the exit() entry. _exit: ldx #<exit lda #>exit jsr reset ; Setup RESET vector - ; Switch in ROM in case it wasn't already switched in by a RESET + ; Switch in ROM, in case it wasn't already switched in by a RESET. bit $C082 - ; Call module destructors + ; Call the module destructors. jsr donelib - ; Restore the original RESET vector + ; Restore the original RESET vector. exit: ldx #$02 : lda rvsave,x sta SOFTEV,x dex bpl :- - ; Copy back the zero page stuff + ; Copy back the zero-page stuff. ldx #zpspace-1 : lda zpsave,x sta sp,x @@ -107,21 +107,21 @@ exit: ldx #$02 txs ; Re-init stack pointer ; We're done - jmp (done) + jmp done .segment "INIT" - ; Save the zero page locations we need + ; Save the zero-page locations that we need. init: ldx #zpspace-1 : lda sp,x sta zpsave,x dex bpl :- - ; Clear the BSS data + ; Clear the BSS data. jsr zerobss - ; Save the original RESET vector + ; Save the original RESET vector. ldx #$02 : lda SOFTEV,x sta rvsave,x @@ -135,58 +135,58 @@ init: ldx #zpspace-1 lda #>_exit jsr reset ; Setup RESET vector - ; Check for ProDOS + ; Check for ProDOS. ldy $BF00 ; MLI call entry point cpy #$4C ; Is MLI present? (JMP opcode) bne basic - - ; Check ProDOS system bit map + + ; Check the ProDOS system bit map. lda $BF6F ; Protection for pages $B8 - $BF cmp #%00000001 ; Exactly system global page is protected bne basic - ; No BASIC.SYSTEM so quit to ProDOS dispatcher instead + ; No BASIC.SYSTEM; so, quit to the ProDOS dispatcher instead. lda #<quit ldx #>quit - sta done - stx done+1 - - ; No BASIC.SYSTEM so use addr of ProDOS system global page + sta done+1 + stx done+2 + + ; No BASIC.SYSTEM; so, use the addr of the ProDOS system global page. lda #<$BF00 ldx #>$BF00 bne :+ ; Branch always - ; Get highest available mem addr from BASIC interpreter + ; Get the highest available mem addr from the BASIC interpreter. basic: lda HIMEM ldx HIMEM+1 - ; Setup the C stack + ; Set up the C stack. : sta sp stx sp+1 - ; Enable interrupts as old ProDOS versions (i.e. 1.1.1) - ; jump to SYS and BIN programs with interrupts disabled + ; Enable interrupts, as old ProDOS versions (i.e. 1.1.1) + ; jump to SYS and BIN programs with interrupts disabled. cli - ; Call module constructors + ; Call the module constructors. jsr initlib - ; Switch in LC bank 2 for R/O + ; Switch in LC bank 2 for R/O. bit $C080 - ; Push arguments and call main() + ; Push the command-line arguments; and, call main(). jmp callmain .code - ; Setup RESET vector + ; Set up the RESET vector. reset: stx SOFTEV sta SOFTEV+1 eor #$A5 sta PWREDUP return: rts - ; Quit to ProDOS dispatcher + ; Quit to the ProDOS dispatcher. quit: jsr $BF00 ; MLI call entry point .byte $65 ; Quit .word q_param @@ -202,8 +202,8 @@ q_param:.byte $04 ; param_count .data - ; Location to jump to when we're done -done: .addr DOSWARM + ; Final jump when we're done +done: jmp DOSWARM ; Potentially patched at runtime .segment "ZPSAVE" diff --git a/libsrc/apple2/emd/a2.auxmem.s b/libsrc/apple2/emd/a2.auxmem.s index 0ceb083b9..5ef2564b1 100644 --- a/libsrc/apple2/emd/a2.auxmem.s +++ b/libsrc/apple2/emd/a2.auxmem.s @@ -10,10 +10,16 @@ .include "em-kernel.inc" .include "em-error.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + .ifdef __APPLE2ENH__ + module_header _a2e_auxmem_emd + .else + module_header _a2_auxmem_emd + .endif ; Driver signature diff --git a/libsrc/apple2/exec.s b/libsrc/apple2/exec.s index 914e10c50..c486306bb 100644 --- a/libsrc/apple2/exec.s +++ b/libsrc/apple2/exec.s @@ -161,8 +161,8 @@ setbuf: lda #$00 ; Low byte ; Call loader stub after C libary shutdown lda #<target ldx #>target - sta done - stx done+1 + sta done+1 + stx done+2 ; Initiate C libary shutdown jmp _exit diff --git a/libsrc/apple2/joy/a2.stdjoy.s b/libsrc/apple2/joy/a2.stdjoy.s index 043b7814e..e4097e043 100644 --- a/libsrc/apple2/joy/a2.stdjoy.s +++ b/libsrc/apple2/joy/a2.stdjoy.s @@ -13,6 +13,8 @@ .include "joy-error.inc" .include "apple2.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Constants @@ -29,7 +31,11 @@ PREAD := $FB1E ; Read paddle in X, return AD conv. value in Y ; Header. Includes jump table. - .segment "JUMPTABLE" + .ifdef __APPLE2ENH__ + module_header _a2e_stdjoy_joy + .else + module_header _a2_stdjoy_joy + .endif ; Driver signature diff --git a/libsrc/apple2/mcbdefault.s b/libsrc/apple2/mcbdefault.s index 2ade00aef..cada4173a 100644 --- a/libsrc/apple2/mcbdefault.s +++ b/libsrc/apple2/mcbdefault.s @@ -16,6 +16,7 @@ .bss backup: .res 1 +visible:.res 1 ; ------------------------------------------------------------------------ @@ -25,6 +26,8 @@ backup: .res 1 _mouse_def_callbacks: .addr hide .addr show + .addr prep + .addr draw .addr movex .addr movey @@ -65,10 +68,15 @@ done: .ifdef __APPLE2ENH__ bit LOWSCR ; Doesn't hurt in 40 column mode .endif - rts +return: rts ; Hide the mouse cursor. hide: + dec visible + ; Fall through + +; Prepare to move the mouse cursor. +prep: jsr getcursor ; Cursor visible at current position? bne done ; No, we're done lda backup ; Get character at cursor position @@ -76,6 +84,13 @@ hide: ; Show the mouse cursor. show: + inc visible + ; Fall through + +; Draw the mouse cursor. +draw: + lda visible + beq return jsr getcursor ; Cursor visible at current position? beq done ; Yes, we're done sta backup ; Save character at cursor position diff --git a/libsrc/apple2/mou/a2.stdmou.s b/libsrc/apple2/mou/a2.stdmou.s index 8414cde36..c3d10f057 100644 --- a/libsrc/apple2/mou/a2.stdmou.s +++ b/libsrc/apple2/mou/a2.stdmou.s @@ -8,6 +8,8 @@ .include "mouse-kernel.inc" .include "apple2.inc" + .macpack module + ; ------------------------------------------------------------------------ SETMOUSE = $12 ; Sets mouse mode @@ -28,7 +30,11 @@ status := $0778 ; ------------------------------------------------------------------------ - .segment "JUMPTABLE" + .ifdef __APPLE2ENH__ + module_header _a2e_stdmou_mou + .else + module_header _a2_stdmou_mou + .endif ; Driver signature .byte $6D, $6F, $75 ; "mou" @@ -57,6 +63,8 @@ status := $0778 ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord @@ -67,7 +75,6 @@ CMOVEY: jmp $0000 ; Move the cursor to Y coord box: .tag MOUSE_BOX info: .tag MOUSE_INFO slot: .res 1 -visible:.res 1 ; ------------------------------------------------------------------------ @@ -321,7 +328,6 @@ MOVE: ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: - dec visible sei jsr CHIDE cli @@ -333,7 +339,9 @@ HIDE: ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: - inc visible + sei + jsr CSHOW + cli rts ; BUTTONS: Return the button mask in A/X. @@ -409,7 +417,7 @@ done: rts beq :+ ; Remove the cursor at the old position -update: jsr CHIDE +update: jsr CPREP ; Get and set the new X position ldy slot @@ -427,11 +435,7 @@ update: jsr CHIDE stx info + MOUSE_POS::YCOORD+1 jsr CMOVEY - ; Check for visibility -: lda visible - beq :+ - ; Draw the cursor at the new position - jsr CSHOW -: sec ; Interrupt handled +: jsr CDRAW + sec ; Interrupt handled rts diff --git a/libsrc/apple2/reboot.s b/libsrc/apple2/reboot.s index 89c34bdf0..8ee1ba067 100644 --- a/libsrc/apple2/reboot.s +++ b/libsrc/apple2/reboot.s @@ -16,6 +16,6 @@ initreboot: ; Quit to PWRUP lda #<$FAA6 ldx #>$FAA6 - sta done - stx done+1 + sta done+1 + stx done+2 rts diff --git a/libsrc/apple2/ser/a2.ssc.s b/libsrc/apple2/ser/a2.ssc.s index 19deefd39..d5c567165 100644 --- a/libsrc/apple2/ser/a2.ssc.s +++ b/libsrc/apple2/ser/a2.ssc.s @@ -25,10 +25,16 @@ .include "ser-kernel.inc" .include "ser-error.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table - .segment "JUMPTABLE" + .ifdef __APPLE2ENH__ + module_header _a2e_ssc_ser + .else + module_header _a2_ssc_ser + .endif ; Driver signature .byte $73, $65, $72 ; "ser" diff --git a/libsrc/apple2/systime.s b/libsrc/apple2/systime.s index 98d39a278..9bf4fe904 100644 --- a/libsrc/apple2/systime.s +++ b/libsrc/apple2/systime.s @@ -3,10 +3,10 @@ ; ; time_t _systime (void); ; /* Similar to time(), but: -; * - Is not ISO C -; * - Does not take the additional pointer -; * - Does not set errno when returning -1 -; */ +; ** - Is not ISO C +; ** - Does not take the additional pointer +; ** - Does not set errno when returning -1 +; */ ; .include "time.inc" diff --git a/libsrc/apple2/targetutil/Makefile.inc b/libsrc/apple2/targetutil/Makefile.inc index 7904607b3..105a5324f 100644 --- a/libsrc/apple2/targetutil/Makefile.inc +++ b/libsrc/apple2/targetutil/Makefile.inc @@ -1,9 +1,9 @@ -DEPS += ../wrk/$(TARGET)/loader.d +DEPS += ../libwrk/$(TARGET)/loader.d -../wrk/$(TARGET)/loader.o: $(SRCDIR)/targetutil/loader.s | ../wrk/$(TARGET) +../libwrk/$(TARGET)/loader.o: $(SRCDIR)/targetutil/loader.s | ../libwrk/$(TARGET) $(ASSEMBLE_recipe) -../targetutil/loader.system: ../wrk/$(TARGET)/loader.o $(SRCDIR)/targetutil/loader.cfg | ../targetutil +../targetutil/loader.system: ../libwrk/$(TARGET)/loader.o $(SRCDIR)/targetutil/loader.cfg | ../targetutil $(LD65) -o $@ -C $(filter %.cfg,$^) $(filter-out %.cfg,$^) $(TARGET): ../targetutil/loader.system diff --git a/libsrc/apple2/targetutil/loader.txt b/libsrc/apple2/targetutil/loader.txt deleted file mode 100644 index d3ec87266..000000000 --- a/libsrc/apple2/targetutil/loader.txt +++ /dev/null @@ -1,80 +0,0 @@ -LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt) -============================================================================= - - -Background ----------- - -Apple][ ProDOS 8 system programs (filetype SYS) are always loaded into memory -starting at location $2000. This poses the problem of how to make efficient -use of the memory in the range $0800-$2000. The usual approach of relocation -has two downsides: -- Relocating e.g. 30 kB from $2000-$9800 to $0800-$8000 takes a considerable - amount of time. -- Really large programs just don't fit into memory when loaded starting at - location $2000. - -The relocation can be eliminated by loading the major part(s) of the program -from disk right to the final location by a rather small system program. - -LOADER.SYSTEM is such a small program. In fact it's so small that it fits into -a single block in the ProDOS 8 file system making it a so-called seedling file, -which are loaded really fast. LOADER.SYSTEM can load cc65 programs into memory -anywhere in the range $0800-$BB00 (44,75 kB). - - -Usage ------ - -Link the cc65 program to the start address $0803 (or any other address) and -store it as binary program (filetype BIN). This is in fact no different from -a binary program to be run by BASIC.SYSTEM's BRUN command in the usual way. - -If however the cc65 program isn't run by BASIC.SYSTEM but is rather run by -LOADER.SYSTEM then it behaves like a system program which means: -- It uses memory up to the ProDOS 8 system global page located at $BF00. -- It supports the ProDOS 8 startup file mechanism (mapped to argv[1]). -- It quits to the ProDOS 8 dispatcher. - -Obviously LOADER.SYSTEM has to be told which cc65 program to run. Unfortunately -the ProDOS 8 dispatcher has no notion of system program parameters so the usual -approach would have been to make LOADER.SYSTEM bring up yet another menu to -select the cc65 program to run. - -But to allow to select the cc65 program directly from the ProDOS 8 dispatcher -anyway LOADER.SYSTEM detects the path to the cc65 program from its own path by -just removing the '.SYSTEM' from its name. So if you want to run the cc65 -program MYPROGRAM you'll need a copy of LOADER.SYSTEM in the same directory -being renamed to MYPROGRAM.SYSTEM. - -This means you will end up with a copy of LOADER.SYSTEM for every cc65 program -to be run by it. But as LOADER.SYSTEM is a ProDOS 8 seedling file using up only -a single block in the ProDOS 8 file system this should be no issue. - - -Build ------ - -In case you want to build 'loader.system' from the source code yourself you can -do so using the following commands: - -ca65 loader.s -ld65 -C loader.cfg -o loader.system loader.o - - -Installation ------------- - -The file 'loader.system' as generated by the cc65 linker with the command above -does NOT include the 4-byte address/length header that is generated for Apple][ -programs by default. This is because ProDOS 8 system programs are always loaded -into memory starting at location $2000. - -The recommended way to transfer 'loader.system' from your native file system to -a ProDOS 8 file system disk image is to use AppleCommander which is available at -http://applecommander.sourceforge.net/ - -If you want to put the file 'loader.system' onto a disk image 'mydisk.dsk' as -system program MYPROGRAM.SYSTEM you can do so using the following command: - -java -jar ac.jar -p mydisk.dsk MYPROGRAM.SYSTEM sys < loader.system diff --git a/libsrc/apple2/tgi/a2.hi.s b/libsrc/apple2/tgi/a2.hi.s index 2f00c83da..18f5724b5 100644 --- a/libsrc/apple2/tgi/a2.hi.s +++ b/libsrc/apple2/tgi/a2.hi.s @@ -11,6 +11,8 @@ .include "tgi-error.inc" .include "apple2.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Zero page stuff @@ -68,7 +70,11 @@ Y2 := ptr4 ; ------------------------------------------------------------------------ - .segment "JUMPTABLE" + .ifdef __APPLE2ENH__ + module_header _a2e_hi_tgi + .else + module_header _a2_hi_tgi + .endif ; Header. Includes jump table and constants. diff --git a/libsrc/apple2/tgi/a2.lo.s b/libsrc/apple2/tgi/a2.lo.s index 5c20ca4d2..045b0044f 100644 --- a/libsrc/apple2/tgi/a2.lo.s +++ b/libsrc/apple2/tgi/a2.lo.s @@ -11,6 +11,8 @@ .include "tgi-error.inc" .include "apple2.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Zero page stuff @@ -38,7 +40,11 @@ Y2 := ptr4 ; ------------------------------------------------------------------------ - .segment "JUMPTABLE" + .ifdef __APPLE2ENH__ + module_header _a2e_lo_tgi + .else + module_header _a2_lo_tgi + .endif ; Header. Includes jump table and constants. diff --git a/libsrc/atari/Makefile.inc b/libsrc/atari/Makefile.inc index af5a17e59..4488ddf22 100644 --- a/libsrc/atari/Makefile.inc +++ b/libsrc/atari/Makefile.inc @@ -31,3 +31,7 @@ CA65FLAGS += -D NUMDRVS=4 -D LINEBUF=80 -D UCASE_FILENAME=1 -D DEFAULT_DEVICE=1 # Disabled by default, you should enable it if the linker script relocates the # character generator (like atarixl-largehimem.cfg). #CA65FLAGS += -D CHARGEN_RELOC -D USEWSYNC + +# Disable if you don't want to use page 6 for mouse P/M data. +# If disabled, top of the RAM is used for P/M data. +CA65FLAGS += -D USE_PAGE6 diff --git a/libsrc/atari/carthdr.s b/libsrc/atari/carthdr.s new file mode 100644 index 000000000..fedd36a1b --- /dev/null +++ b/libsrc/atari/carthdr.s @@ -0,0 +1,23 @@ +; Cartridge "header" +; (In fact, it's at the end of the cartridge, so more a "trailer".) +; +; Christian Groessler, 06-Jan-2014 + +.ifndef __ATARIXL__ + +.export __CART_HEADER__: absolute = 1 + +.import __CARTSIZE__, __CARTFLAGS__, cartinit, cartstart + +.include "atari.inc" + +.segment "CARTHDR" + + .word cartstart ; start routine + .byte 0 ; must be zero + .byte <__CARTFLAGS__ + .word cartinit ; init routine + +.assert (__CARTSIZE__ = $2000 || __CARTSIZE__ = $4000), error, "Cartridge size must either be $2000 or $4000" + +.endif ; .ifndef __ATARIXL__ diff --git a/libsrc/atari/cartinit.s b/libsrc/atari/cartinit.s new file mode 100644 index 000000000..d3035d60c --- /dev/null +++ b/libsrc/atari/cartinit.s @@ -0,0 +1,11 @@ +; Cartridge init routine +; +; Christian Groessler, 06-Jan-2014 + +.ifndef __ATARIXL__ + +.export cartinit + +cartinit: rts + +.endif ; .ifndef __ATARIXL__ diff --git a/libsrc/atari/cartstart.s b/libsrc/atari/cartstart.s new file mode 100644 index 000000000..a30ab79c8 --- /dev/null +++ b/libsrc/atari/cartstart.s @@ -0,0 +1,20 @@ +; Cartridge start routine +; +; Christian Groessler, 06-Jan-2014 + +.ifndef __ATARIXL__ + +.export cartstart + +.import start, copydata + +.include "atari.inc" + +; start routine of cartridge +; copy data segment to RAM and chain to entry point of crt0.s + +cartstart: jsr copydata + jsr start ; run program + jmp (DOSVEC) ; return to DOS + +.endif ; .ifndef __ATARIXL__ diff --git a/libsrc/atari/cashdr.s b/libsrc/atari/cashdr.s new file mode 100644 index 000000000..99aefe68f --- /dev/null +++ b/libsrc/atari/cashdr.s @@ -0,0 +1,37 @@ +; +; Cassette boot file header +; +; Christian Groessler, chris@groessler.org, 2014 +; + +;DEBUG = 1 + +.ifndef __ATARIXL__ + + .include "atari.inc" + + .import __BSS_RUN__, __STARTADDRESS__, _cas_init + .export _cas_hdr + +.assert ((__BSS_RUN__ - __STARTADDRESS__ + 127) / 128) < $101, error, "File to big to load from cassette" + + +; for a description of the cassette header, see De Re Atari, appendix C + +.segment "CASHDR" + +_cas_hdr: + .byte 0 ; ignored + .byte <((__BSS_RUN__ - __STARTADDRESS__ + 127) / 128) ; # of 128-byte records to read + .word __STARTADDRESS__ ; load address + .word _cas_init ; init address + +.ifdef DEBUG + lda #33 + ldy #80 + sta (SAVMSC),y +.endif + clc + rts + +.endif ; .ifdef __ATARIXL__ diff --git a/libsrc/atari/casinit.s b/libsrc/atari/casinit.s new file mode 100644 index 000000000..c91989aad --- /dev/null +++ b/libsrc/atari/casinit.s @@ -0,0 +1,31 @@ +; +; Cassette boot file init routine +; +; Christian Groessler, chris@groessler.org, 2014 +; + +;DEBUG = 1 + +.ifndef __ATARIXL__ + + .include "atari.inc" + + .import start + .export _cas_init + +.segment "INIT" + +_cas_init: +.ifdef DEBUG + lda #34 + ldy #81 + sta (SAVMSC),y +.endif + + lda #<start + sta DOSVEC + lda #>start + sta DOSVEC+1 + rts + +.endif ; .ifdef __ATARIXL__ diff --git a/libsrc/atari/cgetc.s b/libsrc/atari/cgetc.s index 54fe85bb4..2e9ebcb31 100644 --- a/libsrc/atari/cgetc.s +++ b/libsrc/atari/cgetc.s @@ -14,10 +14,10 @@ _cgetc: jsr setcursor lda #12 sta ICAX1Z ; fix problems with direct call to KEYBDV -.ifndef __ATARIXL__ - jsr @1 -.else +.ifdef __ATARIXL__ jsr KEYBDV_handler +.else + jsr @1 .endif ldx #0 rts diff --git a/libsrc/atari/chline.s b/libsrc/atari/chline.s index 46eb0f35d..a096f35a0 100644 --- a/libsrc/atari/chline.s +++ b/libsrc/atari/chline.s @@ -9,6 +9,12 @@ .import popa, _gotoxy, cputdirect, setcursor .importzp tmp1 +.ifdef __ATARI5200__ +CHRCODE = 14 +.else +CHRCODE = $12+64 +.endif + _chlinexy: pha ; Save the length jsr popa ; Get y @@ -19,12 +25,8 @@ _chline: cmp #0 ; Is the length zero? beq L9 ; Jump if done sta tmp1 -L1: lda #$12+64 ; Horizontal line, screen code +L1: lda #CHRCODE ; Horizontal line, screen code jsr cputdirect ; Direct output dec tmp1 bne L1 L9: jmp setcursor - - - - diff --git a/libsrc/atari/crt0.s b/libsrc/atari/crt0.s index fb434b5de..0ea6e390f 100644 --- a/libsrc/atari/crt0.s +++ b/libsrc/atari/crt0.s @@ -32,8 +32,8 @@ .segment "STARTUP" rts ; fix for SpartaDOS / OS/A+ - ; they first call the entry point from AUTOSTRT and - ; then the load addess (this rts here). + ; They first call the entry point from AUTOSTRT; and + ; then, the load address (this rts here). ; We point AUTOSTRT directly after the rts. ; Real entry point: @@ -44,18 +44,25 @@ start: jsr sram_init .endif -; Clear the BSS data +; Clear the BSS data. jsr zerobss -; Setup the stack +; Set up the stack. tsx stx SP_save -.ifndef __ATARIXL__ +.ifdef __ATARIXL__ -; Report memory usage + lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) + sta sp + lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) + sta sp+1 + +.else + +; Report the memory usage. lda APPMHI sta APPMHI_save ; remember old APPMHI value @@ -66,67 +73,60 @@ start: lda MEMTOP sbc #<__RESERVED_MEMORY__ sta APPMHI ; initialize our APPMHI value - sta sp ; setup runtime stack part 1 + sta sp ; set up runtime stack part 1 lda MEMTOP+1 sbc #>__RESERVED_MEMORY__ sta APPMHI+1 - sta sp+1 ; setup runtime stack part 2 - -.else - - lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) - sta sp - lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) - sta sp+1 + sta sp+1 ; set up runtime stack part 2 .endif -; Call module constructors +; Call the module constructors. jsr initlib -; Set left margin to 0 +; Set the left margin to 0. lda LMARGN sta LMARGN_save ldy #0 sty LMARGN -; Set keyb to upper/lowercase mode +; Set the keyboard to upper-/lower-case mode. ldx SHFLOK stx SHFLOK_save sty SHFLOK -; Initialize conio stuff +; Initialize the conio stuff. - dey ; Set X to $FF - sty CH + dey ; Set Y to $FF + sty CH ; remove keypress which might be in the input buffer -; Push arguments and call main +; Push the command-line arguments; and, call main(). jsr callmain -; Call module destructors. This is also the _exit entry. +; Call the module destructors. This is also the exit() entry. _exit: jsr donelib ; Run module destructors -; Restore system stuff +; Restore the system stuff. ldx SP_save txs ; Restore stack pointer -; Restore left margin +; Restore the left margin. lda LMARGN_save sta LMARGN -; Restore kb mode +; Restore the kb mode. lda SHFLOK_save sta SHFLOK -; Restore APPMHI +; Restore APPMHI. lda APPMHI_save sta APPMHI @@ -147,8 +147,8 @@ _exit: jsr donelib ; Run module destructors sta MEMTOP+1 -; Issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers) in -; order to restore screen memory to its defailt location just +; Issue a GRAPHICS 0 call (copied'n'pasted from the TGI drivers), in +; order to restore screen memory to its default location just ; before the ROM. jsr findfreeiocb @@ -169,7 +169,7 @@ _exit: jsr donelib ; Run module destructors lda #0 sta ICBLH,x jsr CIOV_org -; No error checking here, shouldn't happen(tm), and no way to +; No error checking here, shouldn't happen(TM); and, no way to ; recover anyway. lda #CLOSE @@ -178,12 +178,12 @@ _exit: jsr donelib ; Run module destructors .endif -; Turn on cursor +; Turn on the cursor. ldx #0 stx CRSINH -; Back to DOS +; Back to DOS. rts diff --git a/libsrc/atari/cvline.s b/libsrc/atari/cvline.s index 608da23de..da6c8dca4 100644 --- a/libsrc/atari/cvline.s +++ b/libsrc/atari/cvline.s @@ -10,6 +10,12 @@ .import popa, _gotoxy, putchar, setcursor .importzp tmp1 +.ifdef __ATARI5200__ +CHRCODE = 1 ; exclamation mark +.else +CHRCODE = $7C ; Vertical bar +.endif + _cvlinexy: pha ; Save the length jsr popa ; Get y @@ -22,7 +28,7 @@ _cvline: sta tmp1 L1: lda COLCRS pha - lda #$7C ; Vertical bar + lda #CHRCODE ; Vertical bar jsr putchar ; Write, no cursor advance pla sta COLCRS @@ -30,6 +36,3 @@ L1: lda COLCRS dec tmp1 bne L1 L9: jmp setcursor - - - diff --git a/libsrc/atari/emd/atr130.s b/libsrc/atari/emd/atr130.s index 7d663e446..f2d5777d5 100644 --- a/libsrc/atari/emd/atr130.s +++ b/libsrc/atari/emd/atr130.s @@ -31,12 +31,17 @@ .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" +.ifdef __ATARIXL__ + module_header _atrx130_emd +.else + module_header _atr130_emd +.endif ; Driver signature diff --git a/libsrc/atari/exetrailer.s b/libsrc/atari/exetrailer.s index 8cae0bdf0..bac9356f5 100644 --- a/libsrc/atari/exetrailer.s +++ b/libsrc/atari/exetrailer.s @@ -1,7 +1,7 @@ ; This file defines the EXE file "trailer" which sets the entry point .export __AUTOSTART__: absolute = 1 - .import start + .import start .include "atari.inc" diff --git a/libsrc/atari/tvtype.s b/libsrc/atari/get_tv.s similarity index 100% rename from libsrc/atari/tvtype.s rename to libsrc/atari/get_tv.s diff --git a/libsrc/atari/irq.s b/libsrc/atari/irq.s index 8ec1b12df..0a8efe466 100644 --- a/libsrc/atari/irq.s +++ b/libsrc/atari/irq.s @@ -16,26 +16,24 @@ .segment "INIT" initirq: - lda VVBLKI - ldx VVBLKI+1 + lda VVBLKD + ldx VVBLKD+1 sta IRQInd+1 stx IRQInd+2 - lda #6 + lda #7 ldy #<IRQStub ldx #>IRQStub - jsr SETVBV - rts + jmp SETVBV ; ------------------------------------------------------------------------ .code doneirq: - lda #6 + lda #7 ldy IRQInd+1 ldx IRQInd+2 - jsr SETVBV - rts + jmp SETVBV ; ------------------------------------------------------------------------ @@ -44,7 +42,6 @@ doneirq: IRQStub: cld ; Just to be sure .ifdef __ATARIXL__ - pha .ifdef CHARGEN_RELOC lda CHBAS pha @@ -64,7 +61,6 @@ IRQStub: sta CHBAS sta CHBASE .endif - pla .endif jmp IRQInd ; Jump to the saved IRQ vector diff --git a/libsrc/atari/joy/atrmj8.s b/libsrc/atari/joy/atrmj8.s index 04840fc99..46766070b 100644 --- a/libsrc/atari/joy/atrmj8.s +++ b/libsrc/atari/joy/atrmj8.s @@ -14,12 +14,17 @@ .include "atari.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" +.ifdef __ATARIXL__ + module_header _atrxmj8_joy +.else + module_header _atrmj8_joy +.endif ; Driver signature diff --git a/libsrc/atari/joy/atrstd.s b/libsrc/atari/joy/atrstd.s index 34034b554..fc7aa55f4 100644 --- a/libsrc/atari/joy/atrstd.s +++ b/libsrc/atari/joy/atrstd.s @@ -13,12 +13,17 @@ .include "atari.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" +.ifdef __ATARIXL__ + module_header _atrxstd_joy +.else + module_header _atrstd_joy +.endif ; Driver signature diff --git a/libsrc/atari/joy_stat_stddrv.s b/libsrc/atari/joy_stat_stddrv.s index cbaf344d0..4528aa20d 100644 --- a/libsrc/atari/joy_stat_stddrv.s +++ b/libsrc/atari/joy_stat_stddrv.s @@ -7,8 +7,16 @@ ; .export _joy_static_stddrv + .ifdef __ATARIXL__ + .import _atrxstd_joy + .else .import _atrstd_joy + .endif .rodata + .ifdef __ATARIXL__ +_joy_static_stddrv := _atrxstd_joy + .else _joy_static_stddrv := _atrstd_joy + .endif diff --git a/libsrc/atari/joy_stddrv.s b/libsrc/atari/joy_stddrv.s index f3ab74e7b..e82dadb73 100644 --- a/libsrc/atari/joy_stddrv.s +++ b/libsrc/atari/joy_stddrv.s @@ -10,4 +10,9 @@ .rodata -_joy_stddrv: .asciiz "atrstd.joy" +_joy_stddrv: + .ifdef __ATARIXL__ + .asciiz "atrxstd.joy" + .else + .asciiz "atrstd.joy" + .endif diff --git a/libsrc/atari/mcbdefault.s b/libsrc/atari/mcbdefault.s new file mode 100644 index 000000000..75a7c74bc --- /dev/null +++ b/libsrc/atari/mcbdefault.s @@ -0,0 +1,8 @@ +; +; This file defines the default mouse callback +; + +.import _mouse_pm_callbacks +.export _mouse_def_callbacks + +_mouse_def_callbacks := _mouse_pm_callbacks diff --git a/libsrc/atari/mcbpm-shape.s b/libsrc/atari/mcbpm-shape.s new file mode 100644 index 000000000..abedb15ab --- /dev/null +++ b/libsrc/atari/mcbpm-shape.s @@ -0,0 +1,31 @@ +; +; P/M mouse shape default definition +; +; Christian Groessler, 11.04.2014 +; +; Note that the height of the mouse cursor must not exceed 32 +; lines, otherwise the display routines won't do The Right +; Thing(tm). +; + + .export mouse_pm_bits + .export mouse_pm_height : zeropage + .export mouse_pm_hotspot_x : zeropage + .export mouse_pm_hotspot_y : zeropage + + .rodata + +mouse_pm_bits: + .byte %11110000 + .byte %11000000 + .byte %10100000 + .byte %10010000 + .byte %10001000 + .byte %00000100 + .byte %00000010 + +mouse_pm_height = <(* - mouse_pm_bits) + +; hot spot is upper left corner +mouse_pm_hotspot_x = 0 +mouse_pm_hotspot_y = 0 diff --git a/libsrc/atari/mcbpm.s b/libsrc/atari/mcbpm.s new file mode 100644 index 000000000..b546faced --- /dev/null +++ b/libsrc/atari/mcbpm.s @@ -0,0 +1,237 @@ +; +; P/M mouse callbacks for the Ataris +; +; Christian Groessler, 11.04.2014 +; +; All functions in this module should be interrupt safe, because they may +; be called from an interrupt handler +; + + .include "atari.inc" + .importzp sp + .export _mouse_pm_callbacks + .constructor pm_init,27 + .destructor pm_down,7 + +; get mouse shape data + .import mouse_pm_bits + .importzp mouse_pm_height + .importzp mouse_pm_hotspot_x + .importzp mouse_pm_hotspot_y + + +; P/M definitions. The MOUSE_PM_NUM value can be changed to adjust the +; number of the P/M used for the mouse. All others depend on this value. +; Valid P/M numbers are 0 to 4. When 4 is used, the missiles are used +; as a player. +.ifdef USE_PAGE6 +MOUSE_PM_NUM = 2 ; P/M used for the mouse + ; This cannot be changed since only player #2 uses the memory at $600. +.else +MOUSE_PM_NUM = 4 ; P/M used for the mouse + ; Using player #4 (missiles) wastes the least amount of memory on the + ; atari target, since top of memory is typically at $xC20, and the + ; missiles use the space at $xB00-$xBFF. + ; On the atarixl target this configuration (not using page 6) is not + ; really satisfying since the top of memory typically lies beneath + ; the ROM and there is flickering visible while the ROM is banked in. +.endif +MOUSE_PM_BASE = pm_base ; ZP location pointing to the hw area used by the selected P/M + +.if MOUSE_PM_NUM = 4 +MOUSE_PM_RAW = 0 ; MOUSE_PM_RAW is the hardware P/M number for MOUSE_PM_NUM +.macro set_mouse_x + ; assume CF = 0 + sta HPOSM3 + adc #2 + sta HPOSM2 + adc #2 + sta HPOSM1 + adc #2 + sta HPOSM0 +.endmacro +.else +MOUSE_PM_RAW = MOUSE_PM_NUM + 1 +.macro set_mouse_x + sta HPOSP0 + MOUSE_PM_NUM +.endmacro +.endif + +; ------------------------------------------------------------------------ + + .rodata + + ; Callback structure +_mouse_pm_callbacks: + .addr hide + .addr show + .addr prep + .addr draw + .addr movex + .addr movey + +; ------------------------------------------------------------------------ + + .bss + +omy: .res 1 ; old Mouse Y position +colhlp: .res 1 ; helper variable to set P/M color + +; ------------------------------------------------------------------------ + + .segment "EXTZP" : zeropage + +pm_base:.res 2 + +; ------------------------------------------------------------------------ + + .code + +; Hide the mouse cursor. +hide: lda #0 + sta GRACTL + rts + +; Show the mouse cursor. +show: +.if MOUSE_PM_NUM < 4 + lda #2 +.else + lda #1 +.endif + sta GRACTL + jmp update_colors + +prep: +draw: + rts + +; Move the mouse cursor x position to the value in A/X. +movex: cpx #1 + ror a + clc + adc #48 + sbc #(mouse_pm_hotspot_x - 1) & $FF + set_mouse_x + jmp update_colors + +; Move the mouse cursor y position to the value in A/X. +movey: clc + adc #32 + sbc #(mouse_pm_hotspot_y - 1) & $FF + pha + lda omy + jsr clr_pm ; remove player at old position + jsr update_colors + pla + sta omy + ;jmp set_pm ; put player to new position + ; fall thru + +; Set P/M data from 'mouse_pm_bits' +set_pm: tay + ldx #0 +set_l: lda mouse_pm_bits,x + sta (MOUSE_PM_BASE),y + inx + iny + beq set_end + cpx #mouse_pm_height + bcc set_l +set_end:rts + +; Clear (zero) P/M data +clr_pm: ldx #mouse_pm_height + tay + lda #0 +clr_l: sta (MOUSE_PM_BASE),y + iny + beq clr_end + dex + bne clr_l +clr_end:rts + + +pm_down = hide + + +; this assumes a GRAPHICS 0 screen +update_colors: + lda COLOR2 ; get background color + and #$F0 + sta colhlp + lda COLOR1 + and #$0F + ora colhlp + +.if MOUSE_PM_NUM = 4 + sta PCOLR0 + sta PCOLR1 + sta PCOLR2 + sta PCOLR3 + lda #0 + sta SIZEM +.else + sta PCOLR0 + MOUSE_PM_NUM + lda #0 + sta SIZEP0 + MOUSE_PM_NUM +.endif + rts + +; ------------------------------------------------------------------------ + + .segment "INIT" + +pm_init: + lda #0 + +.ifdef USE_PAGE6 + + sta MOUSE_PM_BASE + ldx #6 ; page 6 + stx MOUSE_PM_BASE+1 + +.else + +; use top of memory and lower sp accordingly + sta sp + sta MOUSE_PM_BASE + lda sp+1 + and #7 ; offset within 2K + cmp #3 + MOUSE_PM_RAW + 1 ; can we use it? + bcc @decr ; no + + lda sp+1 + and #$F8 +@set: adc #3 + MOUSE_PM_RAW - 1 ; CF is set, so adding MOUSE_PM_RAW + 3 + sta MOUSE_PM_BASE+1 + sta sp+1 + bne @cont ; jump always + +@decr: lda sp+1 + and #$F8 + sbc #8 - 1 ; CF is clear, subtracts 8 + bcs @set ; jump always + +@cont: lda #0 + +.endif + + tay +@iniloo:sta (MOUSE_PM_BASE),y + iny + bne @iniloo + +.ifndef USE_PAGE6 + lda MOUSE_PM_BASE+1 + and #$F8 +.endif + sta PMBASE + + lda #62 + sta SDMCTL + + lda #1 + sta GPRIOR + + jmp update_colors diff --git a/libsrc/atari/mcbtxtchar-char.s b/libsrc/atari/mcbtxtchar-char.s new file mode 100644 index 000000000..1f0862129 --- /dev/null +++ b/libsrc/atari/mcbtxtchar-char.s @@ -0,0 +1,7 @@ +; +; Default text mode mouse cursor character +; +; Christian Groessler, 11.04.2014 +; + + .export mouse_txt_char : zp = 96 ; 'diamond' screen code diff --git a/libsrc/atari/mcbtxtchar.s b/libsrc/atari/mcbtxtchar.s new file mode 100644 index 000000000..90a25f673 --- /dev/null +++ b/libsrc/atari/mcbtxtchar.s @@ -0,0 +1,125 @@ +; +; Text mode character mouse callbacks for the Ataris +; +; Christian Groessler, 03.01.2014 +; +; derived from Apple2 version by +; Oliver Schmidt, 22.09.2005 +; +; All functions in this module should be interrupt safe, because they may +; be called from an interrupt handler +; + + .export _mouse_txt_callbacks + .importzp tmp4 + .import mul40,loc_tmp + .importzp mouse_txt_char ; screen code of mouse cursor + + .include "atari.inc" + +; ------------------------------------------------------------------------ + + .bss + +backup: .res 1 +visible:.res 1 + +; ------------------------------------------------------------------------ + + .segment "EXTZP" : zeropage +scrptr: .res 2 + +; ------------------------------------------------------------------------ + + + .rodata + + ; Callback structure +_mouse_txt_callbacks: + .addr hide + .addr show + .addr prep + .addr draw + .addr movex + .addr movey + +; ------------------------------------------------------------------------ + + .data + +; setcursor + +getcursor: +column: ldy #$00 ; Patched at runtime + lda (scrptr),y + rts + +setcursor: +column2:ldy #$00 ; Patched at runtime + sta (scrptr),y + rts + +; ------------------------------------------------------------------------ + + .code + +done: + rts + +; Hide the mouse cursor. +hide: + dec visible + +prep: + jsr getcursor ; Get character at cursor position + cmp #mouse_txt_char ; "mouse" character + bne overwr ; no, probably program has overwritten it + lda backup ; + jmp setcursor ; Draw character +overwr: sta backup + rts + +; Show the mouse cursor. +show: + inc visible + +draw: + lda visible + beq done + jsr getcursor ; Cursor visible at current position? + sta backup ; Save character at cursor position + lda #mouse_txt_char + jmp setcursor ; Draw cursor + + +; Move the mouse cursor x position to the value in A/X. +movex: + cpx #1 + ror a + lsr a ; convert to character position + lsr a + sta column+1 + sta column2+1 + rts + +; Move the mouse cursor y position to the value in A/X. +movey: + tax + ldy tmp4 ; mul40 uses tmp4 + lda loc_tmp ; and this local variable + pha + txa ; get parameter back + lsr a ; convert y position to character line + lsr a + lsr a + jsr mul40 + clc + adc SAVMSC + sta scrptr + txa + adc SAVMSC+1 + sta scrptr+1 + pla + sta loc_tmp + sty tmp4 + rts diff --git a/libsrc/atari/mou/atrami.s b/libsrc/atari/mou/atrami.s new file mode 100644 index 000000000..21e1b4c81 --- /dev/null +++ b/libsrc/atari/mou/atrami.s @@ -0,0 +1,2 @@ +AMIGA_MOUSE = 1 +.include "atrst.s" diff --git a/libsrc/atari/mou/atrjoy.s b/libsrc/atari/mou/atrjoy.s new file mode 100644 index 000000000..7f1085fb8 --- /dev/null +++ b/libsrc/atari/mou/atrjoy.s @@ -0,0 +1,440 @@ +; +; Driver for a "joystick mouse". +; +; C128 version: Ullrich von Bassewitz, 2004-04-05, 2009-09-26 +; Adapted to Atari: Christian Groessler, 2014-01-02 +; + + .include "zeropage.inc" + .include "mouse-kernel.inc" + .include "atari.inc" + + .macpack generic + .macpack module + +; ------------------------------------------------------------------------ +; Header. Includes jump table + +.ifdef __ATARIXL__ + module_header _atrxjoy_mou +.else + module_header _atrjoy_mou +.endif + +HEADER: + +; Driver signature + + .byte $6d, $6f, $75 ; "mou" + .byte MOUSE_API_VERSION ; Mouse driver API version number + +; Library reference + + .addr $0000 + +; Jump table + + .addr INSTALL + .addr UNINSTALL + .addr HIDE + .addr SHOW + .addr SETBOX + .addr GETBOX + .addr MOVE + .addr BUTTONS + .addr POS + .addr INFO + .addr IOCTL + .addr IRQ + +; Mouse driver flags + + .byte MOUSE_FLAG_LATE_IRQ + +; Callback table, set by the kernel before INSTALL is called + +CHIDE: jmp $0000 ; Hide the cursor +CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor +CMOVEX: jmp $0000 ; Move the cursor to X coord +CMOVEY: jmp $0000 ; Move the cursor to Y coord + + +;---------------------------------------------------------------------------- +; Constants + +SCREEN_HEIGHT = 191 +SCREEN_WIDTH = 319 + +.enum JOY + UP = $01 + DOWN = $02 + LEFT = $04 + RIGHT = $08 +.endenum + +;---------------------------------------------------------------------------- +; Global variables. The bounding box values are sorted so that they can be +; written with the least effort in the SETBOX and GETBOX routines, so don't +; reorder them. + +.bss + +Vars: +YPos: .res 2 ; Current mouse position, Y +XPos: .res 2 ; Current mouse position, X +XMin: .res 2 ; X1 value of bounding box +YMin: .res 2 ; Y1 value of bounding box +XMax: .res 2 ; X2 value of bounding box +YMax: .res 2 ; Y2 value of bounding box +Buttons: .res 1 ; Button mask + + +Temp: .res 1 ; Temporary value used in the int handler + +; Default values for above variables + +.rodata + +; (We use ".proc" because we want to define both a label and a scope.) + +.proc DefVars + .word SCREEN_HEIGHT/2 ; YPos + .word SCREEN_WIDTH/2 ; XPos + .word 0 ; XMin + .word 0 ; YMin + .word SCREEN_WIDTH ; XMax + .word SCREEN_HEIGHT ; YMax + .byte 0 ; Buttons +.endproc + +.code + +;---------------------------------------------------------------------------- +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return an MOUSE_ERR_xx code in a/x. + +INSTALL: + +; Initialize variables. Just copy the default stuff over + + ldx #.sizeof(DefVars)-1 +@L1: lda DefVars,x + sta Vars,x + dex + bpl @L1 + +; Make sure the mouse cursor is at the default location. + + lda XPos + ldx XPos+1 + jsr CMOVEX + lda YPos + ldx YPos+1 + jsr CMOVEY + +; Done, return zero (= MOUSE_ERR_OK) + + ldx #$00 + txa + rts + +;---------------------------------------------------------------------------- +; UNINSTALL routine. Is called before the driver is removed from memory. +; No return code required (the driver is removed from memory on return). + +UNINSTALL = HIDE ; Hide cursor on exit + +;---------------------------------------------------------------------------- +; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently visible and should get hidden. For most drivers, +; no special action is required besides hiding the mouse cursor. +; No return code required. + +HIDE: php + sei + jsr CHIDE + plp + rts + +;---------------------------------------------------------------------------- +; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently hidden and should become visible. For most drivers, +; no special action is required besides enabling the mouse cursor. +; No return code required. + +SHOW: php + sei + jsr CSHOW + plp + rts + +;---------------------------------------------------------------------------- +; SETBOX: Set the mouse bounding box. The parameters are passed as they come +; from the C program, that is, a pointer to a mouse_box struct in a/x. +; No checks are done if the mouse is currently inside the box, this is the job +; of the caller. It is not necessary to validate the parameters, trust the +; caller and save some code here. No return code required. + +SETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + php + sei + +@L1: lda (ptr1),y + sta XMin,y + dey + bpl @L1 + + plp + rts + +;---------------------------------------------------------------------------- +; GETBOX: Return the mouse bounding box. The parameters are passed as they +; come from the C program, that is, a pointer to a mouse_box struct in a/x. + +GETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + php + sei + +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + + plp + rts + +;---------------------------------------------------------------------------- +; MOVE: Move the mouse to a new position. The position is passed as it comes +; from the C program, that is: X on the stack and Y in a/x. The C wrapper will +; remove the parameter from the stack on return. +; No checks are done if the new position is valid (within the bounding box or +; the screen). No return code required. +; + +MOVE: php + sei ; No interrupts + + pha + txa + pha + jsr CPREP + pla + tax + pla + + sta YPos + stx YPos+1 ; New Y position + jsr CMOVEY ; Set it + + ldy #$01 + lda (sp),y + sta XPos+1 + tax + dey + lda (sp),y + sta XPos ; New X position + jsr CMOVEX ; Move the cursor + + jsr CDRAW + + plp ; Restore interrupt flag + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in a/x. + +BUTTONS: + lda Buttons + ldx #$00 + rts + +;---------------------------------------------------------------------------- +; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. +; No return code required. + +POS: ldy #MOUSE_POS::XCOORD ; Structure offset + + php + sei ; Disable interrupts + lda XPos ; Transfer the position + sta (ptr1),y + lda XPos+1 + iny + sta (ptr1),y + lda YPos + iny + sta (ptr1),y + lda YPos+1 + plp ; Restore interrupt flag + + iny + sta (ptr1),y ; Store last byte + + rts ; Done + +;---------------------------------------------------------------------------- +; INFO: Returns mouse position and current button mask in the MOUSE_INFO +; struct pointed to by ptr1. No return code required. +; +; We're cheating here to keep the code smaller: The first fields of the +; mouse_info struct are identical to the mouse_pos struct, so we will just +; call _mouse_pos to initialize the struct pointer and fill the position +; fields. + +INFO: jsr POS + +; Fill in the button state + + lda Buttons + ldy #MOUSE_INFO::BUTTONS + sta (ptr1),y + + rts + +;---------------------------------------------------------------------------- +; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl +; specific data in ptr1, and the ioctl code in A. +; Must return an error code in a/x. +; + +IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #>MOUSE_ERR_INV_IOCTL + rts + +;---------------------------------------------------------------------------- +; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context +; (so be careful). The routine MUST return carry set if the interrupt has been +; 'handled' - which means that the interrupt source is gone. Otherwise it +; MUST return carry clear. +; + +IRQ: + +; Check for a pressed button and place the result into Buttons + + ldx #0 + lda TRIG0 ; joystick #0 trigger + bne @L0 ; not pressed + ldx #MOUSE_BTN_LEFT +@L0: stx Buttons + + lda PORTA ; get joystick direction bits + and #15 ; clear joystick #1 bits + eor #15 + sta Temp + + jsr CPREP + +; Check left/right + + lda Temp ; Read joystick #0 + and #(JOY::LEFT | JOY::RIGHT) + beq @SkipX ; + +; We will cheat here and rely on the fact that either the left, OR the right +; bit can be active + + and #JOY::RIGHT ; Check RIGHT bit + bne @Right + lda #$FF + tax + bne @AddX ; Branch always +@Right: lda #$01 + ldx #$00 + +; Calculate the new X coordinate (--> a/y) + +@AddX: add XPos + tay ; Remember low byte + txa + adc XPos+1 + tax + +; Limit the X coordinate to the bounding box + + cpy XMin + sbc XMin+1 + bpl @L1 + ldy XMin + ldx XMin+1 + jmp @L2 +@L1: txa + + cpy XMax + sbc XMax+1 + bmi @L2 + ldy XMax + ldx XMax+1 +@L2: sty XPos + stx XPos+1 + +; Move the mouse pointer to the new X pos + + tya + jsr CMOVEX + +; Calculate the Y movement vector + +@SkipX: lda Temp ; Read joystick #0 + and #(JOY::UP | JOY::DOWN) ; Check up/down + beq @SkipY ; + +; We will cheat here and rely on the fact that either the up, OR the down +; bit can be active + + lsr a + bcc @Down + lda #$FF + tax + bne @AddY +@Down: lda #$01 + ldx #$00 + +; Calculate the new Y coordinate (--> a/y) + +@AddY: add YPos + tay ; Remember low byte + txa + adc YPos+1 + tax + +; Limit the Y coordinate to the bounding box + + cpy YMin + sbc YMin+1 + bpl @L3 + ldy YMin + ldx YMin+1 + jmp @L4 +@L3: txa + + cpy YMax + sbc YMax+1 + bmi @L4 + ldy YMax + ldx YMax+1 +@L4: sty YPos + stx YPos+1 + +; Move the mouse pointer to the new X pos + + tya + jsr CMOVEY + +; Done + +@SkipY: jsr CDRAW + clc ; Interrupt not "handled" + rts + diff --git a/libsrc/atari/mou/atrst.s b/libsrc/atari/mou/atrst.s new file mode 100644 index 000000000..17d2affb5 --- /dev/null +++ b/libsrc/atari/mou/atrst.s @@ -0,0 +1,823 @@ +; +; Mouse driver for ST & Amiga mouses and Atari trakball. +; +; Original access routines: 05/07/2000 Freddy Offenga +; Converted to driver: Christian Groessler, 2014-01-04 +; +; Defines: +; AMIGA_MOUSE - builds Amiga mouse version +; TRAK_MOUSE - builds trakball version +; If none of these defines are active, the ST mouse version +; is being built. +; + +;DEBUG = 1 + +DISABLE_TIMEOUT = 30 ; # of vertical blank interrupts after which, if + ; no mouse motion occurred, the polling IRQ gets + ; disabled. + ; VBI frequency is 50Hz for PAL and 60Hz for NTSC + + .include "zeropage.inc" + .include "mouse-kernel.inc" + .include "atari.inc" + + .macpack generic + .macpack module + +.if .not ( .defined (AMIGA_MOUSE) .or .defined (TRAK_MOUSE)) + ST_MOUSE = 1 +.endif + +; ------------------------------------------------------------------------ +; Header. Includes jump table + +.if .defined (ST_MOUSE) + +.ifdef __ATARIXL__ + module_header _atrxst_mou +.else + module_header _atrst_mou +.endif + +.elseif .defined (AMIGA_MOUSE) + +.ifdef __ATARIXL__ + module_header _atrxami_mou +.else + module_header _atrami_mou +.endif + +.elseif .defined (TRAK_MOUSE) + +.ifdef __ATARIXL__ + module_header _atrxtrk_mou +.else + module_header _atrtrk_mou +.endif + +.endif + +HEADER: + +; Driver signature + + .byte $6d, $6f, $75 ; "mou" + .byte MOUSE_API_VERSION ; Mouse driver API version number + +; Library reference + +libref: .addr $0000 + +; Jump table + + .addr INSTALL + .addr UNINSTALL + .addr HIDE + .addr SHOW + .addr SETBOX + .addr GETBOX + .addr MOVE + .addr BUTTONS + .addr POS + .addr INFO + .addr IOCTL + .addr IRQ + +; Mouse driver flags + + .byte MOUSE_FLAG_LATE_IRQ + +; Callback table, set by the kernel before INSTALL is called + +CHIDE: jmp $0000 ; Hide the cursor +CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor +CMOVEX: jmp $0000 ; Move the cursor to X coord +CMOVEY: jmp $0000 ; Move the cursor to Y coord + + +;---------------------------------------------------------------------------- +; Constants + +SCREEN_HEIGHT = 191 +SCREEN_WIDTH = 319 + +.enum JOY + UP = $01 + DOWN = $02 + LEFT = $04 + RIGHT = $08 +.endenum + +;---------------------------------------------------------------------------- +; Global variables. The bounding box values are sorted so that they can be +; written with the least effort in the SETBOX and GETBOX routines, so don't +; reorder them. + +.bss + +Vars: +YPos: .res 2 ; Current mouse position, Y +XPos: .res 2 ; Current mouse position, X +XMin: .res 2 ; X1 value of bounding box +YMin: .res 2 ; Y1 value of bounding box +XMax: .res 2 ; X2 value of bounding box +YMax: .res 2 ; Y2 value of bounding box +Buttons: .res 1 ; Button mask + +XPosWrk: .res 2 +YPosWrk: .res 2 + +irq_enabled: .res 1 ; flag indicating that the high frequency polling interrupt is enabled +old_porta_vbi: .res 1 ; previous PORTA value of the VBI interrupt (IRQ) +how_long: .res 1 ; counter for how many VBI interrupts the mouse hasn't been moved + +.if .defined (AMIGA_MOUSE) .or .defined (ST_MOUSE) +dumx: .res 1 +dumy: .res 1 +.endif + +.ifdef TRAK_MOUSE +oldval: .res 1 +.endif + +.ifndef __ATARIXL__ +OldT1: .res 2 +.else + +.data +set_VTIMR1_handler: + .byte $4C, 0, 0 +.endif + +.rodata + +; Default values for some of the above variables +; (We use ".proc" because we want to define both a label and a scope.) + +.proc DefVars + .word (SCREEN_HEIGHT+1)/2 ; YPos + .word (SCREEN_WIDTH+1)/2 ; XPos + .word 0 ; XMin + .word 0 ; YMin + .word SCREEN_WIDTH ; XMax + .word SCREEN_HEIGHT ; YMax + .byte 0 ; Buttons +.endproc + +.ifdef ST_MOUSE + +; ST mouse lookup table + +STTab: .byte $FF,$01,$00,$01 + .byte $00,$FF,$00,$01 + .byte $01,$00,$FF,$00 + .byte $01,$00,$01,$FF + +.endif + +.ifdef AMIGA_MOUSE + +; Amiga mouse lookup table + +AmiTab: .byte $FF,$01,$00,$FF + .byte $00,$FF,$FF,$01 + .byte $01,$FF,$FF,$00 + .byte $FF,$00,$01,$FF + +.endif + +.code + +;---------------------------------------------------------------------------- +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return an MOUSE_ERR_xx code in a/x. + +INSTALL: + +; Initialize variables. Just copy the default stuff over + + ldx #.sizeof(DefVars)-1 +@L1: lda DefVars,x + sta Vars,x + dex + bpl @L1 + +; Make sure the mouse cursor is at the default location. + + lda XPos + sta XPosWrk + ldx XPos+1 + stx XPosWrk+1 + jsr CMOVEX + lda YPos + sta YPosWrk + ldx YPos+1 + stx YPosWrk+1 + jsr CMOVEY + +; Install timer irq routine to poll mouse. + +.ifdef __ATARIXL__ + + ; Setup pointer to wrapper install/deinstall function. + lda libref + sta set_VTIMR1_handler+1 + lda libref+1 + sta set_VTIMR1_handler+2 + + ; Install my handler. + sec + lda #<T1Han + ldx #>T1Han + jsr set_VTIMR1_handler + +.else + + lda VTIMR1 + sta OldT1 + lda VTIMR1+1 + sta OldT1+1 + + php + sei + lda #<T1Han + sta VTIMR1 + lda #>T1Han + sta VTIMR1+1 + plp + +.endif + + lda #%00000001 + sta AUDCTL + + lda #0 + sta AUDC1 + + lda #15 + sta AUDF1 + sta STIMER + +.if 0 ; the IRQ will now be dynamically enabled when the mouse is moved + lda POKMSK + ora #%00000001 ; timer 1 enable + sta POKMSK + sta IRQEN + sta irq_enabled +.endif + + lda PORTA + and #$0f + sta old_porta_vbi + +; Done, return zero (= MOUSE_ERR_OK) + + ldx #$00 + txa + rts + +;---------------------------------------------------------------------------- +; UNINSTALL routine. Is called before the driver is removed from memory. +; No return code required (the driver is removed from memory on return). + +UNINSTALL: + +; uninstall timer irq routine + + lda POKMSK + and #%11111110 ; timer 1 disable + sta IRQEN + sta POKMSK + +.ifdef __ATARIXL__ + + clc + jsr set_VTIMR1_handler + +.else + + php + sei + lda OldT1 + sta VTIMR1 + lda OldT1+1 + sta VTIMR1+1 + plp + +.endif + ; fall thru... + +;---------------------------------------------------------------------------- +; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently visible and should get hidden. For most drivers, +; no special action is required besides hiding the mouse cursor. +; No return code required. + +HIDE: php + sei + jsr CHIDE + plp + rts + +;---------------------------------------------------------------------------- +; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently hidden and should become visible. For most drivers, +; no special action is required besides enabling the mouse cursor. +; No return code required. + +SHOW: php + sei + jsr CSHOW + plp + rts + +;---------------------------------------------------------------------------- +; SETBOX: Set the mouse bounding box. The parameters are passed as they come +; from the C program, that is, a pointer to a mouse_box struct in a/x. +; No checks are done if the mouse is currently inside the box, this is the job +; of the caller. It is not necessary to validate the parameters, trust the +; caller and save some code here. No return code required. + +SETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + php + sei + +@L1: lda (ptr1),y + sta XMin,y + dey + bpl @L1 + + plp + rts + +;---------------------------------------------------------------------------- +; GETBOX: Return the mouse bounding box. The parameters are passed as they +; come from the C program, that is, a pointer to a mouse_box struct in a/x. + +GETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + php + sei + +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + + plp + rts + +;---------------------------------------------------------------------------- +; MOVE: Move the mouse to a new position. The position is passed as it comes +; from the C program, that is: X on the stack and Y in a/x. The C wrapper will +; remove the parameter from the stack on return. +; No checks are done if the new position is valid (within the bounding box or +; the screen). No return code required. +; + +MOVE: php + sei ; No interrupts + + pha + txa + pha + jsr CPREP + pla + tax + pla + + sta YPos + sta YPosWrk + stx YPos+1 ; New Y position + stx YPosWrk+1 + jsr CMOVEY ; Set it + + ldy #$01 + lda (sp),y + sta XPos+1 + sta XPosWrk+1 + tax + dey + lda (sp),y + sta XPos ; New X position + sta XPosWrk + jsr CMOVEX ; Move the cursor + + jsr CDRAW + + plp ; Restore interrupt flag + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in a/x. + +BUTTONS: + lda Buttons + ldx #$00 + rts + +;---------------------------------------------------------------------------- +; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. +; No return code required. + +POS: ldy #MOUSE_POS::XCOORD ; Structure offset + + php + sei ; Disable interrupts + lda XPos ; Transfer the position + sta (ptr1),y + lda XPos+1 + iny + sta (ptr1),y + lda YPos + iny + sta (ptr1),y + lda YPos+1 + plp ; Restore interrupt flag + + iny + sta (ptr1),y ; Store last byte + + rts ; Done + +;---------------------------------------------------------------------------- +; INFO: Returns mouse position and current button mask in the MOUSE_INFO +; struct pointed to by ptr1. No return code required. +; +; We're cheating here to keep the code smaller: The first fields of the +; mouse_info struct are identical to the mouse_pos struct, so we will just +; call _mouse_pos to initialize the struct pointer and fill the position +; fields. + +INFO: jsr POS + +; Fill in the button state + + lda Buttons + ldy #MOUSE_INFO::BUTTONS + sta (ptr1),y + + rts + +;---------------------------------------------------------------------------- +; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl +; specific data in ptr1, and the ioctl code in A. +; Must return an error code in a/x. +; + +IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #>MOUSE_ERR_INV_IOCTL + rts + +;---------------------------------------------------------------------------- +; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context +; (so be careful). The routine MUST return carry set if the interrupt has been +; 'handled' - which means that the interrupt source is gone. Otherwise it +; MUST return carry clear. +; + +IRQ: lda PORTA ; mouse port contents + and #$0f ; check port 1 only + ldx irq_enabled + bne @L1 + +; IRQ is disabled, check for mouse motion and enable IRQ if mouse motion detected + + cmp old_porta_vbi + beq @L3 ; no motion + +; Turn mouse polling IRQ back on + + lda POKMSK + ora #%00000001 ; timer 1 enable + sta POKMSK + sta IRQEN + sta irq_enabled + bne @L3 + ; not reached + +; IRQ is enabled + +@L1: cmp old_porta_vbi ; mouse motion since last VBI? + sta old_porta_vbi + beq @L2 ; no, increment timeout to disable IRQ + + lda #0 + sta how_long ; yes, reinitialize wait counter + beq @L3 + ; not reached + +@L2: inc how_long ; no motion, increment wait counter + lda how_long + cmp #DISABLE_TIMEOUT ; timeout? + bcc @L3 ; no + + lda #0 ; yes, turn off IRQ + sta how_long + +; no mouse input -- turn IRQ off + + sta irq_enabled + lda POKMSK + and #%11111110 ; timer 1 disable + sta IRQEN + sta POKMSK + +; Check for a pressed button and place the result into Buttons + +@L3: ldx #0 + lda TRIG0 ; joystick #0 trigger + bne @L4 ; not pressed + ldx #MOUSE_BTN_LEFT +@L4: stx Buttons + + jsr CPREP + +; Limit the X coordinate to the bounding box + + lda XPosWrk+1 + ldy XPosWrk + tax + cpy XMin + sbc XMin+1 + bpl @L5 + ldy XMin + ldx XMin+1 + jmp @L6 + +@L5: txa + cpy XMax + sbc XMax+1 + bmi @L6 + ldy XMax + ldx XMax+1 +@L6: sty XPos + stx XPos+1 + tya + jsr CMOVEX + +; Limit the Y coordinate to the bounding box + + lda YPosWrk+1 + ldy YPosWrk + tax + cpy YMin + sbc YMin+1 + bpl @L7 + ldy YMin + ldx YMin+1 + jmp @L8 + +@L7: txa + cpy YMax + sbc YMax+1 + bmi @L8 + ldy YMax + ldx YMax+1 +@L8: sty YPos + stx YPos+1 + tya + jsr CMOVEY + + jsr CDRAW + +.ifdef DEBUG + ; print on upper right corner 'E' or 'D', indicating the IRQ is enabled or disabled + ldy irq_enabled + beq @L9 + lda #37 ; screen code for 'E' + .byte $2c ; bit opcode, eats next 2 bytes +@L9: lda #36 ; screen code for 'D' + ldy #39 + sta (SAVMSC),y +.endif + + clc + rts + + +;---------------------------------------------------------------------------- +; T1Han: Local IRQ routine to poll mouse +; + +T1Han: lda CRITIC ; if CRITIC flag is set, disable the + bne disable_me ; high frequency polling IRQ, in order + ; not to interfere with SIO I/O (e.g. + ; floppy access) + + tya + pha + txa + pha + +.ifdef DEBUG + lda RANDOM + sta COLBK +.endif + + lda PORTA + tay + +.ifdef ST_MOUSE + +; ST mouse version + + and #%00000011 + ora dumx + tax + lda STTab,x + bmi nxst + + beq xist + + dec XPosWrk + lda XPosWrk + cmp #255 + bne nxst + dec XPosWrk+1 + jmp nxst + +xist: inc XPosWrk + bne nxst + inc XPosWrk+1 + +nxst: tya + and #%00001100 + ora dumy + tax + lda STTab,x + bmi nyst + + bne yst + + dec YPosWrk + lda YPosWrk + cmp #255 + bne nyst + dec YPosWrk+1 + jmp nyst + +yst: inc YPosWrk + bne nyst + inc YPosWrk+1 + +; store old readings + +nyst: tya + and #%00000011 + asl + asl + sta dumx + tya + and #%00001100 + lsr + lsr + sta dumy + +.elseif .defined (AMIGA_MOUSE) + +; Amiga mouse version + + lsr + and #%00000101 + ora dumx + tax + lda AmiTab,x + bmi nxami + + bne xiami + + dec XPosWrk + lda XPosWrk + cmp #255 + bne nxami + dec XPosWrk+1 + jmp nxami + +xiami: inc XPosWrk + bne nxami + inc XPosWrk+1 + +nxami: tya + + and #%00000101 + ora dumy + tax + lda AmiTab,x + bmi nyami + + bne yiami + + dec YPosWrk + lda YPosWrk + cmp #255 + bne nyami + dec YPosWrk+1 + jmp nyami + +yiami: inc YPosWrk + bne nyami + inc YPosWrk+1 + +; store old readings + +nyami: tya + and #%00001010 + sta dumx + tya + and #%00000101 + asl + sta dumy + +.elseif .defined (TRAK_MOUSE) + +; trakball version + + eor oldval + and #%00001000 + beq horiz + + tya + and #%00000100 + beq mmup + + inc YPosWrk + bne horiz + inc YPosWrk+1 + bne horiz + +mmup: dec YPosWrk + lda YPosWrk + cmp #255 + bne horiz + dec YPosWrk+1 + +horiz: tya + eor oldval + and #%00000010 + beq mmexit + + tya + and #%00000001 + beq mmleft + + inc XPosWrk + bne mmexit + inc XPosWrk+1 + bne mmexit + +mmleft: dec XPosWrk + lda XPosWrk + cmp #255 + bne mmexit + dec XPosWrk+1 + +mmexit: sty oldval + +.endif + + pla + tax + pla + tay +.ifdef __ATARIXL__ + rts +.else + pla + rti +.endif + + +; Disable the interrupt source which caused us to be called. +; The interrupt will be enabled again by the "IRQ" routine. +; The "IRQ" routine, despite its name, is called from the +; vertical blank NMI interrupt *only* if the CRITIC flag has +; been cleared. + +disable_me: + lda POKMSK + and #%11111110 ; timer 1 disable + sta IRQEN + sta POKMSK + lda #0 + sta irq_enabled + lda PORTA + and #$0f + sta old_porta_vbi +.ifdef __ATARIXL__ + rts +.else + pla + rti +.endif diff --git a/libsrc/atari/mou/atrtrk.s b/libsrc/atari/mou/atrtrk.s new file mode 100644 index 000000000..699d12a0d --- /dev/null +++ b/libsrc/atari/mou/atrtrk.s @@ -0,0 +1,2 @@ +TRAK_MOUSE = 1 +.include "atrst.s" diff --git a/libsrc/atari/mou/atrtt.s b/libsrc/atari/mou/atrtt.s new file mode 100644 index 000000000..f1f2cde63 --- /dev/null +++ b/libsrc/atari/mou/atrtt.s @@ -0,0 +1,482 @@ +; +; Mouse driver for Atari Touch Tablet +; +; Christian Groessler, 2014-01-05 +; + + .include "zeropage.inc" + .include "mouse-kernel.inc" + .include "atari.inc" + + .macpack generic + .macpack module + +; ------------------------------------------------------------------------ +; Header. Includes jump table + +.ifdef __ATARIXL__ + module_header _atrxtt_mou +.else + module_header _atrtt_mou +.endif + +HEADER: + +; Driver signature + + .byte $6d, $6f, $75 ; "mou" + .byte MOUSE_API_VERSION ; Mouse driver API version number + +; Library reference + + .addr $0000 + +; Jump table + + .addr INSTALL + .addr UNINSTALL + .addr HIDE + .addr SHOW + .addr SETBOX + .addr GETBOX + .addr MOVE + .addr BUTTONS + .addr POS + .addr INFO + .addr IOCTL + .addr IRQ + +; Mouse driver flags + + .byte MOUSE_FLAG_LATE_IRQ + +; Callback table, set by the kernel before INSTALL is called + +CHIDE: jmp $0000 ; Hide the cursor +CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor +CMOVEX: jmp $0000 ; Move the cursor to X coord +CMOVEY: jmp $0000 ; Move the cursor to Y coord + + +;---------------------------------------------------------------------------- +; Constants + +SCREEN_HEIGHT = 191 +SCREEN_WIDTH = 319 + +.enum JOY + UP = $01 + DOWN = $02 + LEFT = $04 + RIGHT = $08 +.endenum + +;---------------------------------------------------------------------------- +; Global variables. The bounding box values are sorted so that they can be +; written with the least effort in the SETBOX and GETBOX routines, so don't +; reorder them. + +.bss + +Vars: +YPos: .res 2 ; Current mouse position, Y +XPos: .res 2 ; Current mouse position, X +XMin: .res 2 ; X1 value of bounding box +YMin: .res 2 ; Y1 value of bounding box +XMax: .res 2 ; X2 value of bounding box +YMax: .res 2 ; Y2 value of bounding box +Buttons: .res 1 ; Button mask + +; Default values for above variables + +.rodata + +; (We use ".proc" because we want to define both a label and a scope.) + +.proc DefVars + .word SCREEN_HEIGHT/2 ; YPos + .word SCREEN_WIDTH/2 ; XPos + .word 0 ; XMin + .word 0 ; YMin + .word SCREEN_WIDTH ; XMax + .word SCREEN_HEIGHT ; YMax + .byte 0 ; Buttons +.endproc + +.code + +;---------------------------------------------------------------------------- +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return an MOUSE_ERR_xx code in a/x. + +INSTALL: + +; Initialize variables. Just copy the default stuff over + + ldx #.sizeof(DefVars)-1 +@L1: lda DefVars,x + sta Vars,x + dex + bpl @L1 + +; Make sure the mouse cursor is at the default location. + + lda XPos + ldx XPos+1 + jsr CMOVEX + lda YPos + ldx YPos+1 + jsr CMOVEY + +; Done, return zero (= MOUSE_ERR_OK) + + ldx #$00 + txa + rts + +;---------------------------------------------------------------------------- +; UNINSTALL routine. Is called before the driver is removed from memory. +; No return code required (the driver is removed from memory on return). + +UNINSTALL = HIDE ; Hide cursor on exit + +;---------------------------------------------------------------------------- +; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently visible and should get hidden. For most drivers, +; no special action is required besides hiding the mouse cursor. +; No return code required. + +HIDE: php + sei + jsr CHIDE + plp + rts + +;---------------------------------------------------------------------------- +; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently hidden and should become visible. For most drivers, +; no special action is required besides enabling the mouse cursor. +; No return code required. + +SHOW: php + sei + jsr CSHOW + plp + rts + +;---------------------------------------------------------------------------- +; SETBOX: Set the mouse bounding box. The parameters are passed as they come +; from the C program, that is, a pointer to a mouse_box struct in a/x. +; No checks are done if the mouse is currently inside the box, this is the job +; of the caller. It is not necessary to validate the parameters, trust the +; caller and save some code here. No return code required. + +SETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + php + sei + +@L1: lda (ptr1),y + sta XMin,y + dey + bpl @L1 + + plp + rts + +;---------------------------------------------------------------------------- +; GETBOX: Return the mouse bounding box. The parameters are passed as they +; come from the C program, that is, a pointer to a mouse_box struct in a/x. + +GETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + php + sei + +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + + plp + rts + +;---------------------------------------------------------------------------- +; MOVE: Move the mouse to a new position. The position is passed as it comes +; from the C program, that is: X on the stack and Y in a/x. The C wrapper will +; remove the parameter from the stack on return. +; No checks are done if the new position is valid (within the bounding box or +; the screen). No return code required. +; + +MOVE: php + sei ; No interrupts + + pha + txa + pha + jsr CPREP + pla + tax + pla + + sta YPos + stx YPos+1 ; New Y position + jsr CMOVEY ; Set it + + ldy #$01 + lda (sp),y + sta XPos+1 + tax + dey + lda (sp),y + sta XPos ; New X position + jsr CMOVEX ; Move the cursor + + jsr CSHOW + + plp ; Restore interrupt flag + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in a/x. + +BUTTONS: + lda Buttons + ldx #$00 + rts + +;---------------------------------------------------------------------------- +; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. +; No return code required. + +POS: ldy #MOUSE_POS::XCOORD ; Structure offset + + php + sei ; Disable interrupts + lda XPos ; Transfer the position + sta (ptr1),y + lda XPos+1 + iny + sta (ptr1),y + lda YPos + iny + sta (ptr1),y + lda YPos+1 + plp ; Restore interrupt flag + + iny + sta (ptr1),y ; Store last byte + + rts ; Done + +;---------------------------------------------------------------------------- +; INFO: Returns mouse position and current button mask in the MOUSE_INFO +; struct pointed to by ptr1. No return code required. +; +; We're cheating here to keep the code smaller: The first fields of the +; mouse_info struct are identical to the mouse_pos struct, so we will just +; call _mouse_pos to initialize the struct pointer and fill the position +; fields. + +INFO: jsr POS + +; Fill in the button state + + lda Buttons + ldy #MOUSE_INFO::BUTTONS + sta (ptr1),y + + rts + +;---------------------------------------------------------------------------- +; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl +; specific data in ptr1, and the ioctl code in A. +; Must return an error code in a/x. +; + +IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #>MOUSE_ERR_INV_IOCTL + rts + +;---------------------------------------------------------------------------- +; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context +; (so be careful). The routine MUST return carry set if the interrupt has been +; 'handled' - which means that the interrupt source is gone. Otherwise it +; MUST return carry clear. +; + +IRQ: + +; Check for a pressed button and place the result into Buttons + + ldx #0 + stx Buttons + + lda PORTA ; get other buttons + eor #255 + tax + and #5 ; pen button and left button are mapped to left mouse button + beq @L01 + lda #MOUSE_BTN_LEFT + ora Buttons + sta Buttons +@L01: txa + and #8 + beq @L02 + lda #MOUSE_BTN_RIGHT + ora Buttons + sta Buttons + +; If we read 228 for X or Y positions, we assume the user has lifted the pen +; and don't change the cursor position. + +@L02: lda PADDL0 + cmp #228 + beq @Cont ; CF set if equal + lda PADDL1 + cmp #228 ; CF set if equal + +@Cont: php ; remember CF + jsr CPREP + plp ; restore CF + + bcc @L03 + jmp @Show + +@L03: ldx #0 + stx XPos+1 + stx YPos+1 + +; Get cursor position +; ------------------- +; The touch pad is read thru the paddle potentiometers. The possible +; values are 1..228. Since the maximum value is less than the X +; dimension we have to "stretch" this value. In order to use only +; divisions by powers of two, we use the following appoximation: +; 320/227 = 1.4096 +; 1+1/2-1/8+1/32 = 1.4062 +; For Y we subtract 1/8 of it to get in the YMax ballpark. +; 228-228/8=199.5 +; A small area in the Y dimension of the touchpad isn't used with +; this approximation. The Y value is inverted, (0,0) is the bottom +; left corner of the touchpad. + +; X + + ldx PADDL0 ; get X postion + dex ; decrement, since it's 1-based + stx XPos + txa + lsr a + tax + clc + adc XPos + sta XPos + bcc @L04 + inc XPos+1 +@L04: txa + lsr a ; port value / 4 + lsr a ; port value / 8 + tax + sec + lda XPos + stx XPos + sbc XPos + sta XPos + bcs @L05 + dec XPos+1 +@L05: txa + lsr a ; port value / 16 + lsr a ; port value / 32 + clc + adc XPos + sta XPos + bcc @L06 + inc XPos+1 + +@L06: tay + lda XPos+1 + tax + +; Limit the X coordinate to the bounding box + + cpy XMin + sbc XMin+1 + bpl @L07 + ldy XMin + ldx XMin+1 + jmp @L08 +@L07: txa + + cpy XMax + sbc XMax+1 + bmi @L08 + ldy XMax + ldx XMax+1 +@L08: sty XPos + stx XPos+1 + +; Move the mouse pointer to the new X pos + + tya + jsr CMOVEX + +; Y + + ldx PADDL1 ; get Y postion + dex ; decrement, since it's 1-based + stx YPos + lda #228 + sec + sbc YPos ; invert value + tax + lsr a + lsr a + lsr a + sta YPos + txa + sec + sbc YPos + sta YPos + tay + lda YPos+1 + tax + +; Limit the Y coordinate to the bounding box + + cpy YMin + sbc YMin+1 + bpl @L09 + ldy YMin + ldx YMin+1 + jmp @L10 +@L09: txa + + cpy YMax + sbc YMax+1 + bmi @L10 + ldy YMax + ldx YMax+1 +@L10: sty YPos + stx YPos+1 + +; Move the mouse pointer to the new X pos + + tya + jsr CMOVEY + +@Show: jsr CDRAW + + clc ; Interrupt not "handled" + rts + diff --git a/libsrc/atari/mouse.s_ b/libsrc/atari/mouse.s_ deleted file mode 100644 index 9c722b49c..000000000 --- a/libsrc/atari/mouse.s_ +++ /dev/null @@ -1,576 +0,0 @@ -;-------------------------------------------------------------------- -; Atari 8-bit mouse routines -- 05/07/2000 Freddy Offenga -; Some changes by Christian Groessler, Ullrich von Bassewitz -; -; The following devices are supported: -; - Atari trak-ball -; - ST mouse -; - Amiga mouse -; -; Mouse checks are done in the timer 1 IRQ and the mouse arrow is -; drawn in player 0 during the vertical blank -;-------------------------------------------------------------------- - - .export _mouse_init, _mouse_done, _mouse_box - .export _mouse_show, _mouse_hide, _mouse_move - .export _mouse_buttons, _mouse_pos, _mouse_info - .constructor initmouse,27 - - .import popax - .importzp ptr1 - - .include "atari.inc" - -TRAK_BALL = 0 ; device Atari trak-ball -ST_MOUSE = 1 ; device ST mouse -AMIGA_MOUSE = 2 ; device Amiga mouse -MAX_TYPE = 3 ; first illegal device type - -; the default values force the mouse cursor inside the test screen (no access to border) -defxmin = 48 ; default x minimum -defymin = 31 ; default y minimum -defxmax = 204 ; default x maximum -defymax = 211 ; default y maximum - -pmsize = 16 ; y size pm shape - -xinit = defxmin ; init. x pos. -yinit = defymin ; init. y pos. - -;-------------------------------------------------------------------- -; reserve memory for the mouse pointer - -initmouse: - lda APPMHI+1 - and #%11111000 ; make 2k aligned - sec - sbc #%00001000 ; reserve 2k - tax - adc #3 ; add 4 (C = 1) - sta mouse_pm0 - lda #0 - sta APPMHI - stx APPMHI+1 - rts - - -;-------------------------------------------------------------------- -; Initialize mouse routines -; void __fastcall__ mouse_init (unsigned char type); - -_mouse_init: - cmp #MAX_TYPE+1 ; Check for a valid type - bcc setup - -ifail: lda #0 ; init. failed - tax - rts - -setup: tax - lda lvectab,x - sta mouse_vec+1 - lda hvectab,x - sta mouse_vec+2 - - jsr pminit - - lda VTIMR1 - sta old_t1 - lda VTIMR1+1 - sta old_t1+1 - - lda #<t1_vec - sta VTIMR1 - lda #>t1_vec - sta VTIMR1+1 - - lda #%00000001 - sta AUDCTL - - lda #0 - sta AUDC1 - - lda #15 - sta AUDF1 - sta STIMER - - sei - lda POKMSK - ora #%00000001 ; timer 1 enable - sta POKMSK - sta IRQEN - cli - - lda VVBLKI - sta vbi_jmp+1 - lda VVBLKI+1 - sta vbi_jmp+2 - - lda #6 - ldy #<vbi - ldx #>vbi - jsr SETVBV - - lda #$C0 - sta NMIEN - - ldx #0 - lda #1 - sta mouse_off - rts - -;-------------------------------------------------------------------- -; Finish mouse routines -; void mouse_done(void) - -_mouse_done: - sei - lda POKMSK - and #%11111110 ; timer 1 disable - sta IRQEN - sta POKMSK - cli - - lda old_t1 - sta VTIMR1 - lda old_t1+1 - sta VTIMR1+1 - - lda #$40 - sta NMIEN - - lda #6 - ldy vbi_jmp+1 - ldx vbi_jmp+2 - jsr SETVBV - - ldx #0 - stx GRACTL - stx HPOSP0 - inx - stx mouse_off - rts - -;-------------------------------------------------------------------- -; Set mouse limits -; void __fastcall__ mouse_box(int xmin, int ymin, int xmax, int ymax) - -_mouse_box: - sta ymax - jsr popax ; always ignore high byte - sta xmax - jsr popax - sta ymin - jsr popax - sta xmin - rts - -;-------------------------------------------------------------------- -; Set mouse position -; void __fastcall__ mouse_move(int xpos, int ypos) - -_mouse_move: - sta mousey ; always ignore high byte - jsr popax - sta mousex - rts - -;-------------------------------------------------------------------- -; Show mouse arrow -; void mouse_show(void) - -_mouse_show: - lda mouse_off ; Already on? - beq @L1 - dec mouse_off -@L1: rts - -;-------------------------------------------------------------------- -; Hide mouse arrow -; void mouse_hide(void) - -_mouse_hide: - inc mouse_off - rts - -;-------------------------------------------------------------------- -; Ask mouse button -; unsigned char mouse_buttons(void) - -_mouse_buttons: - ldx #0 - lda STRIG0 - bne nobut -; lda #14 -;??? sta COLOR1 - lda #1 - rts -nobut: txa - rts - -;-------------------------------------------------------------------- -; Get the mouse position -; void mouse_pos (struct mouse_pos* pos); - -_mouse_pos: - sta ptr1 - stx ptr1+1 ; Store argument pointer - ldy #0 - lda mousex ; X position - sta (ptr1),y - lda #0 - iny - sta (ptr1),y - lda mousey ; Y position - iny - sta (ptr1),y - lda #0 - iny - sta (ptr1),y - rts - -;-------------------------------------------------------------------- -; Get the mouse position and button information -; void mouse_info (struct mouse_info* info); - -_mouse_info: - -; We're cheating here to keep the code smaller: The first fields of the -; mouse_info struct are identical to the mouse_pos struct, so we will just -; call _mouse_pos to initialize the struct pointer and fill the position -; fields. - - jsr _mouse_pos - -; Fill in the button state - - jsr _mouse_buttons ; Will not touch ptr1 - ldy #4 - sta (ptr1),y - - rts - -;-------------------------------------------------------------------- -; Atari trak-ball check, A,Y = 4-bit port value - -trak_check: - eor oldval - and #%00001000 - beq horiz - - tya - and #%00000100 - beq mmup - - inc mousey - bne horiz - -mmup: dec mousey - -horiz: tya - eor oldval - and #%00000010 - beq mmexit - - tya - and #%00000001 - beq mmleft - - inc mousex - bne mmexit - -mmleft: dec mousex - -mmexit: sty oldval - rts - -;-------------------------------------------------------------------- -; ST mouse check, A,Y = 4-bit port value - -st_check: - and #%00000011 - ora dumx - tax - lda sttab,x - bmi nxst - - beq xist - dec mousex ; 1 = left - bne nxst -xist: inc mousex ; 0 = right - -nxst: tya - and #%00001100 - ora dumy - tax - lda sttab,x - bmi nyst - - bne yst - dec mousey ; 0 = up - bne nyst -yst: inc mousey ; 1 = down - -; store old readings - -nyst: tya - and #%00000011 - asl - asl - sta dumx - tya - and #%00001100 - lsr - lsr - sta dumy - rts - -;-------------------------------------------------------------------- -; Amiga mouse check, A,Y = 4-bit port value - -amiga_check: - - lsr - and #%00000101 - ora dumx - tax - lda amitab,x - bmi nxami - - bne xiami - dec mousex ; 0 = left - bne nxami -xiami: inc mousex ; 1 = right - -nxami: tya - - and #%00000101 - ora dumy - tax - lda amitab,x - bmi nyami - - bne yiami - dec mousey ; 0 = up - bne nyami -yiami: inc mousey ; 1 = down - -; store old readings - -nyami: tya - and #%00001010 - sta dumx - tya - and #%00000101 - asl - sta dumy - rts - -;-------------------------------------------------------------------- -; timer 1 IRQ routine - check mouse - -t1_vec: tya - pha - txa - pha - -.ifdef DEBUG - lda RANDOM - sta COLBK ; debug -.endif - - lda PORTA - tay - -mouse_vec: - jsr st_check ; will be modified; won't be ROMmable - - pla - tax - pla - tay - pla - rti - -;-------------------------------------------------------------------- -; VBI - check mouse limits and display mouse arrow - -vbi: lda mousex - cmp xmin - bcs ok1 ; xmin <= mousex - lda xmin - sta mousex - -ok1: lda mousey - cmp ymin - bcs ok2 ; ymin <= mousey - lda ymin - sta mousey - -ok2: lda xmax - cmp mousex - bcs ok3 ; xmax >= mousex - lda xmax - sta mousex - -ok3: lda ymax - cmp mousey - bcs ok4 ; ymax >= mousey - lda ymax - sta mousey - -ok4: jsr clrpm - - lda mouse_off - beq mon - lda #0 - sta HPOSP0 - beq moff - -mon: jsr drwpm - lda mousey - sta omy - - lda #3 -moff: sta GRACTL - -vbi_jmp: - jmp SYSVBV ; will be modified; won't be ROMmable - -;-------------------------------------------------------------------- -; initialize mouse pm - -pminit: lda mouse_pm0 - sta mpatch1+2 - sta mpatch2+2 - sta mpatch3+2 - - ldx #0 - txa -mpatch1: -clpm: sta $1000,x ; will be patched - inx - bne clpm - - lda mouse_pm0 - sec - sbc #4 - sta PMBASE - - lda #62 - sta SDMCTL - - lda #1 - sta GPRIOR - - lda #0 - sta PCOLR0 - sta SIZEP0 - rts - -;-------------------------------------------------------------------- -; draw new mouse pm - -drwpm: lda mousex - sta HPOSP0 - - lda mousey - tax - - ldy #0 -fmp2: lda mskpm,y -mpatch2: - sta $1000,x ; will be patched - inx - iny - cpy #pmsize - bne fmp2 - rts - -;-------------------------------------------------------------------- -; clear old mouse pm - -clrpm: lda omy - tax - - ldy #0 - tya -mpatch3: -fmp1: sta $1000,x ; will be patched - inx - iny - cpy #pmsize - bne fmp1 - rts - -;-------------------------------------------------------------------- - .rodata - -; mouse arrow - pm shape - -mskpm: .byte %00000000 - .byte %10000000 - .byte %11000000 - .byte %11000000 - - .byte %11100000 - .byte %11100000 - .byte %11110000 - .byte %11100000 - - .byte %11100000 - .byte %00100000 - .byte %00100000 - .byte %00110000 - - .byte %00110000 - .byte %00000000 - .byte %00000000 - .byte %00000000 - -; ST mouse lookup table - -sttab: .byte $FF,$01,$00,$01 - .byte $00,$FF,$00,$01 - .byte $01,$00,$FF,$00 - .byte $01,$00,$01,$FF - -; Amiga mouse lookup table - -amitab: .byte $FF,$01,$00,$FF - .byte $00,$FF,$FF,$01 - .byte $01,$FF,$FF,$00 - .byte $FF,$00,$01,$FF - -; Device vectors - -lvectab: - .byte <trak_check, <st_check, <amiga_check -hvectab: - .byte >trak_check, >st_check, >amiga_check - -; default values - -xmin: .byte defxmin -ymin: .byte defymin -xmax: .byte defxmax -ymax: .byte defymax - -mousex: .byte xinit -mousey: .byte yinit - -;-------------------------------------------------------------------- - .bss - -; Misc. vars - -old_t1: .res 2 ; old timer interrupt vector -oldval: .res 1 ; used by trakball routines -dumx: .res 1 -dumy: .res 1 -omy: .res 1 ; old y pos - -mouse_off: - .res 1 -mouse_pm0: - .res 1 diff --git a/libsrc/atari/mouse_stat_stddrv.s b/libsrc/atari/mouse_stat_stddrv.s new file mode 100644 index 000000000..55e29878b --- /dev/null +++ b/libsrc/atari/mouse_stat_stddrv.s @@ -0,0 +1,22 @@ +; +; Address of the static standard mouse driver +; +; Christian Groessler, 2014-01-02 +; +; const void mouse_static_stddrv[]; +; + + .export _mouse_static_stddrv + .ifdef __ATARIXL__ + .import _atrxst_mou + .else + .import _atrst_mou + .endif + +.rodata + + .ifdef __ATARIXL__ +_mouse_static_stddrv := _atrxst_mou + .else +_mouse_static_stddrv := _atrst_mou + .endif diff --git a/libsrc/atari/mouse_stddrv.s b/libsrc/atari/mouse_stddrv.s new file mode 100644 index 000000000..493c90d77 --- /dev/null +++ b/libsrc/atari/mouse_stddrv.s @@ -0,0 +1,18 @@ +; +; Name of the standard mouse driver +; +; Christian Groessler, 2014-01-02 +; +; const char mouse_stddrv[]; +; + + .export _mouse_stddrv + +.rodata + +_mouse_stddrv: + .ifdef __ATARIXL__ + .asciiz "ATRXST.MOU" + .else + .asciiz "ATRST.MOU" + .endif diff --git a/libsrc/atari/mouseref.s b/libsrc/atari/mouseref.s new file mode 100644 index 000000000..b75df93d1 --- /dev/null +++ b/libsrc/atari/mouseref.s @@ -0,0 +1,13 @@ +; +; Christian Groessler, 2014-04-22 +; + + .export mouse_libref + +.ifdef __ATARIXL__ + .import set_VTIMR1_handler +mouse_libref := set_VTIMR1_handler +.else + .import _exit +mouse_libref := _exit +.endif diff --git a/libsrc/atari/mul40.s b/libsrc/atari/mul40.s index b94ab5c52..96235bf6c 100644 --- a/libsrc/atari/mul40.s +++ b/libsrc/atari/mul40.s @@ -6,7 +6,7 @@ ; uses tmp4 .importzp tmp4 - .export mul40 + .export mul40,loc_tmp .proc mul40 diff --git a/libsrc/atari/read.s b/libsrc/atari/read.s index acb415efd..f8d10fd15 100644 --- a/libsrc/atari/read.s +++ b/libsrc/atari/read.s @@ -48,13 +48,13 @@ _inviocb: .segment "EXTZP" : zeropage index: .res 1 ; index into line buffer -buflen: .res 1 ; length of used part of buffer cbs: .res 1 ; current buffer size: buflen - index dataptr:.res 2 ; temp pointer to user buffer copylen:.res 1 ; temp counter .bss +buflen: .res 1 ; length of used part of buffer linebuf:.res LINEBUF ; the line buffer .code diff --git a/libsrc/atari/rs232.s_ b/libsrc/atari/rs232.s_ deleted file mode 100644 index 35f20ca4f..000000000 --- a/libsrc/atari/rs232.s_ +++ /dev/null @@ -1,389 +0,0 @@ -; -; Christian Groessler, Dec-2001 -; -; RS232 routines using the R: device (currently tested with an 850 only) -; -; unsigned char __fastcall__ rs232_init (char hacked); -; unsigned char __fastcall__ rs232_params (unsigned char params, unsigned char parity); -; unsigned char __fastcall__ rs232_done (void); -; unsigned char __fastcall__ rs232_get (char* B); -; unsigned char __fastcall__ rs232_put (char B); -; unsigned char __fastcall__ rs232_pause (void); [TODO] -; unsigned char __fastcall__ rs232_unpause (void); [TODO] -; unsigned char __fastcall__ rs232_status (unsigned char* status, -; unsigned char* errors); [TODO] -; - - .import findfreeiocb - .import __do_oserror - .import fddecusage - .import fdtoiocb - .import __inviocb - .import clriocb - .import newfd - .import _close, pushax, popax, popa - .importzp ptr1, tmp2, tmp3 - - .export _rs232_init, _rs232_params, _rs232_done, _rs232_get - .export _rs232_put, _rs232_pause, _rs232_unpause, _rs232_status - - .include "atari.inc" - .include "errno.inc" - .include "rs232.inc" - - .rodata - -rdev: .byte "R:", ATEOL, 0 - - .bss - -; receive buffer -RECVBUF_SZ = 256 -recv_buf: .res RECVBUF_SZ - -cm_run: .res 1 ; concurrent mode running? - - .data - -rshand: .word $ffff - - .code - -;---------------------------------------------------------------------------- -; -; unsigned char __fastcall__ rs232_init (char hacked); -; /* Initialize the serial port. The parameter is ignored in the Atari version. -; * return 0/-1 for OK/Error -; */ -; - -.proc _rs232_init - - jsr findfreeiocb - bne init_err - txa - tay ; move iocb # into Y - lda #3 - sta tmp3 ; name length + 1 - lda #<rdev - ldx #>rdev - jsr newfd - tya - bcs doopen ; C set: open needed / device not already open - - pha - jsr _rs232_done ;** shut down if started @@@TODO check this out!! - pla - -doopen: tax - pha - jsr clriocb - pla - tax - lda #<rdev - sta ICBAL,x - lda #>rdev - sta ICBAH,x - lda #OPEN - sta ICCOM,x - - lda #$0D ; mode in+out+concurrent - sta ICAX1,x - lda #0 - sta ICAX2,x - sta ICBLL,x ; zap buf len - sta ICBLH,x - jsr CIOV - bmi cioerr1 - - lda tmp2 ; get fd - sta rshand - ldx #0 - stx rshand+1 - txa - rts - -cioerr1:jsr fddecusage ; decrement usage counter of fd as open failed - -init_err: - ldx #0 - lda #RS_ERR_INIT_FAILED - rts - -.endproc ; _rs232_init - - -;---------------------------------------------------------------------------- -; -; unsigned char __fastcall__ rs232_params (unsigned char params, unsigned char parity); -; -; Set communication parameters. -; -; params contains baud rate, stop bits and word size -; parity contains parity -; -; 850 manual documents restrictions on the baud rate (not > 300), when not -; using 8 bit word size. So only 8 bit is currently tested. -; - -.proc _rs232_params - - sta tmp2 - lda rshand - cmp #$ff - bne work ; work only if initialized - lda #RS_ERR_NOT_INITIALIZED - bne done -work: lda rshand - ldx #0 - jsr fdtoiocb ; get iocb index into X - bmi inverr ; shouldn't happen - tax - - ; set handshake lines - - lda #34 ; xio 34, set cts, dtr etc - sta ICCOM,x - lda #192+48+3 ; DTR on, RTS on, XMT on - sta ICAX1,x - lda #0 - sta ICBLL,x - sta ICBLH,x - sta ICBAL,x - sta ICBAH,x - sta ICAX2,x - jsr CIOV - bmi cioerr - - ; set baud rate, word size, stop bits and ready monitoring - - lda #36 ; xio 36, baud rate - sta ICCOM,x - jsr popa ; get parameter - sta ICAX1,x - ;ICAX2 = 0, monitor nothing - jsr CIOV - bmi cioerr - - ; set translation and parity - - lda #38 ; xio 38, translation and parity - sta ICCOM,x - lda tmp2 - ora #32 ; no translation - sta ICAX1,x - jsr CIOV - bmi cioerr - - lda #0 -done: ldx #0 - rts - -inverr: jmp __inviocb - -.endproc ;_rs232_params - -cioerr: jmp __do_oserror - - -;---------------------------------------------------------------------------- -; -; unsigned char __fastcall__ rs232_done (void); -; /* Close the port, deinstall the interrupt hander. You MUST call this function -; * before terminating the program, otherwise the machine may crash later. If -; * in doubt, install an exit handler using atexit(). The function will do -; * nothing, if it was already called. -; */ -; - -.proc _rs232_done - - lda rshand - cmp #$ff - beq done -work: ldx rshand+1 - jsr pushax - jsr _close - pha - txa - pha - ldx #$ff - stx rshand - stx rshand+1 - inx - stx cm_run - pla - tax - pla -done: rts - -.endproc ;rs232_done - - -;---------------------------------------------------------------------------- -; -; unsigned char __fastcall__ rs232_get (char* B); -; /* Get a character from the serial port. If no characters are available, the -; * function will return RS_ERR_NO_DATA, so this is not a fatal error. -; */ -; - -.proc _rs232_get - - ldy rshand - cpy #$ff - bne work ; work only if initialized - lda #RS_ERR_NOT_INITIALIZED - bne nierr - -work: sta ptr1 - stx ptr1+1 ; store pointer to received char - - lda rshand - ldx #0 - jsr fdtoiocb - tax - lda cm_run ; concurrent mode already running? - bne go - jsr ena_cm ; turn on concurrent mode - -go: ; check whether there is any input available - - lda #STATIS ; status request, returns bytes pending - sta ICCOM,x - jsr CIOV - bmi cioerr ; @@@ error handling - - lda DVSTAT+1 ; get byte count pending - ora DVSTAT+2 - beq nix_da ; no input waiting... - - ; input is available: get it! - - lda #GETCHR ; get raw bytes - sta ICCOM,x ; in command code - lda #0 - sta ICBLL,x - sta ICBLH,x - sta ICBAL,x - sta ICBAH,x - jsr CIOV ; go get it - bmi cioerr ; @@@ error handling - - ldx #0 - sta (ptr1,x) ; return received byte - txa - rts - -nierr: ldx #0 - rts - -nix_da: lda #RS_ERR_NO_DATA - ldx #0 - rts - -.endproc ;_rs232_get - - -;---------------------------------------------------------------------------- -; -; unsigned char __fastcall__ rs232_put (char B); -; /* Send a character via the serial port. There is a transmit buffer, but -; * transmitting is not done via interrupt. The function returns -; * RS_ERR_OVERFLOW if there is no space left in the transmit buffer. -; */ -; - -.proc _rs232_put - - ldy rshand - cpy #$ff - bne work ; work only if initialized - lda #RS_ERR_NOT_INITIALIZED - bne nierr - -work: pha - lda rshand - ldx #0 - jsr fdtoiocb - tax - lda cm_run ; concurrent mode already running? - bne go - jsr ena_cm ; turn on concurrent mode - - ; @@@TODO: check output buffer overflow -go: lda #PUTCHR ; put raw bytes - sta ICCOM,x ; in command code - lda #0 - sta ICBLL,x - sta ICBLH,x - sta ICBAL,x - sta ICBAH,x - pla ; get the char back - jsr CIOV ; go do it - rts - -nierr: ldx #0 - rts - -.endproc ;_rs232_put - -;---------------------------------------------------------------------------- -; -; unsigned char __fastcall__ rs232_pause (void); -; /* Assert flow control and disable interrupts. */ -; - -_rs232_pause: - - -;---------------------------------------------------------------------------- -; -; unsigned char __fastcall__ rs232_unpause (void); -; /* Re-enable interrupts and release flow control */ -; - -_rs232_unpause: - - -;---------------------------------------------------------------------------- -; -; unsigned char __fastcall__ rs232_status (unsigned char* status, -; unsigned char* errors); -; /* Return the serial port status. */ -; - -_rs232_status: - - lda #255 - tax - rts - - -; enable concurrent rs232 mode -; gets iocb index in X -; all registers destroyed - -.proc ena_cm - - lda #40 ; XIO 40, start concurrent IO - sta ICCOM,x - sta cm_run ; indicate concurrent mode is running - lda #0 - sta ICAX1,x - sta ICAX2,x - lda #<recv_buf - sta ICBAL,x - lda #>recv_buf - sta ICBAH,x - lda #<RECVBUF_SZ - sta ICBLL,x - lda #>RECVBUF_SZ - sta ICBLH,x - lda #$0D ; value from 850 man, p62. must be 0D?, - sta ICAX1,x ; or any non-zero? - jmp CIOV - -.endproc ;ena_cm - - .end diff --git a/libsrc/atari/ser/atrrdev.s b/libsrc/atari/ser/atrrdev.s new file mode 100644 index 000000000..3a7bc21c2 --- /dev/null +++ b/libsrc/atari/ser/atrrdev.s @@ -0,0 +1,585 @@ +; +; Christian Groessler, Dec-2001 +; converted to driver interface Dec-2013 +; +; RS232 routines using the R: device (currently tested with an 850 only) +; + + .include "zeropage.inc" + .include "ser-kernel.inc" + .include "ser-error.inc" + .include "atari.inc" + + .macpack module + + +; ------------------------------------------------------------------------ +; Header. Includes jump table + +.ifdef __ATARIXL__ + module_header _atrxrdev_ser +.else + module_header _atrrdev_ser +.endif + +; Driver signature + + .byte $73, $65, $72 ; "ser" + .byte SER_API_VERSION ; Serial API version number + +; Library reference + +libref: .addr $0000 + +; Jump table + + .word SER_INSTALL + .word SER_UNINSTALL + .word SER_OPEN + .word SER_CLOSE + .word SER_GET + .word SER_PUT + .word SER_STATUS + .word SER_IOCTL + .word SER_IRQ + + + .rodata + +rdev: .byte "R:", ATEOL, 0 +bauds: .byte 1 ; SER_BAUD_45_5 + .byte 2 ; SER_BAUD_50 + .byte 4 ; SER_BAUD_75 + .byte 5 ; SER_BAUD_110 + .byte 6 ; SER_BAUD_134_5 + .byte 7 ; SER_BAUD_150 + .byte 8 ; SER_BAUD_300 + .byte 9 ; SER_BAUD_600 + .byte 10 ; SER_BAUD_1200 + .byte 11 ; SER_BAUD_1800 + .byte 12 ; SER_BAUD_2400 + .byte 0 ; SER_BAUD_3600 + .byte 13 ; SER_BAUD_4800 + .byte 0 ; SER_BAUD_7200 + .byte 14 ; SER_BAUD_9600 + .byte 0 ; SER_BAUD_19200 + .byte 0 ; SER_BAUD_38400 + .byte 0 ; SER_BAUD_57600 + .byte 0 ; SER_BAUD_115200 + .byte 0 ; SER_BAUD_230400 + .byte 0 ; SER_BAUD_31250 + .byte 0 ; SER_BAUD_62500 + .byte 3 ; SER_BAUD_56_875 +num_bauds = * - bauds +databits: + .byte 48 ; SER_BITS_5 + .byte 32 ; SER_BITS_6 + .byte 16 ; SER_BITS_7 + .byte 0 ; SER_BITS_8 +num_databits = * - databits +parities: + .byte 0 ; SER_PAR_NONE + .byte 4+1 ; SER_PAR_ODD + .byte 2+8 ; SER_PAR_EVEN + ;.byte 0 ; SER_PAR_MARK + ;.byte 0 ; SER_PAR_SPACE +num_parities = * - parities + + .bss + +; receive buffer +RECVBUF_SZ = 256 +recv_buf: .res RECVBUF_SZ + +cm_run: .res 1 ; concurrent mode running? + + .data + +rshand: .word $ffff + +; jump table into main program, initialized from libref +my_newfd: + .byte $4C + .word 0 +my__close: + .byte $4C + .word 0 +my_pushax: + .byte $4C + .word 0 +my_popax: + .byte $4C + .word 0 +my_findfreeiocb: + .byte $4C + .word 0 +my___do_oserror: + .byte $4C + .word 0 +my_fddecusage: + .byte $4C + .word 0 +my_fdtoiocb: + .byte $4C + .word 0 +my___inviocb: + .byte $4C + .word 0 +my_clriocb: + .byte $4C + .word 0 +my_CIOV: + .byte $4C + .word 0 + + .code + +invbaud: + lda #<SER_ERR_BAUD_UNAVAIL + ldx #>SER_ERR_BAUD_UNAVAIL +openerr: + rts + + +;---------------------------------------------------------------------------- +; SER_OPEN: A pointer to a ser_params structure is passed in ptr1. +; Must return an SER_ERR_xx code in a/x. + +SER_OPEN: + jsr do_open + bne openerr + +; set line parameters + lda rshand + ldx #0 + jsr my_fdtoiocb ; get iocb index into X + bmi openerr ; shouldn't happen + tax + + ; set baud rate, word size, stop bits and ready monitoring + + ; build ICAX1 value + ldy #SER_PARAMS::BAUDRATE + lda (ptr1),y + cmp #num_bauds + bcs invbaud + + tay + lda bauds,y + beq invbaud + sta ICAX1,x + + ldy #SER_PARAMS::DATABITS + lda (ptr1),y + cmp #num_databits + bcs init_err + + tay + lda databits,y + ora ICAX1,x + sta ICAX1,x + + ldy #SER_PARAMS::STOPBITS + lda (ptr1),y + clc + ror a + ror a + ora ICAX1,x + sta ICAX1,x + + lda #36 ; xio 36, baud rate + sta ICCOM,x + lda #0 + ;ICAX2 = 0, monitor nothing + sta ICAX2,x + sta ICBLL,x + sta ICBLH,x + sta ICBAL,x + sta ICBAH,x + jsr my_CIOV + bmi cioerr + + ; check if the handshake setting is valid + ldy #SER_PARAMS::HANDSHAKE + lda (ptr1),y + cmp #SER_HS_HW ; this is all we support + bne init_err + + ; set handshake lines + lda #34 ; xio 34, set cts, dtr etc + sta ICCOM,x + lda #192+48+3 ; DTR on, RTS on, XMT on + sta ICAX1,x + jsr my_CIOV + bmi cioerr + + ; set translation and parity + ldy #SER_PARAMS::PARITY + lda (ptr1),y + cmp #num_parities + bcs init_err + + tay + lda parities,y + ora #32 ; no translation + sta ICAX1,x + + lda #38 ; xio 38, translation and parity + sta ICCOM,x + jsr my_CIOV + bmi cioerr + + lda #<SER_ERR_OK + tax ; A is zero + rts + +inverr: jmp my___inviocb + +cioerr: + ; @@@ need to close IOCB here + jsr my_fddecusage ; decrement usage counter of fd as open failed + +init_err: + ldx #0 + lda #SER_ERR_INIT_FAILED + rts + +;---- open the device + +do_open: + jsr my_findfreeiocb + bne init_err + txa + tay ; move iocb # into Y + lda #3 + sta tmp3 ; name length + 1 + lda #<rdev + ldx #>rdev + jsr my_newfd + tya + bcs @doopen ; C set: open needed / device not already open + + pha + jsr SER_CLOSE ;** shut down if started @@@TODO check this out!! + pla + +@doopen:tax + pha + jsr my_clriocb + pla + tax + lda #<rdev + sta ICBAL,x + lda #>rdev + sta ICBAH,x + lda #OPEN + sta ICCOM,x + + lda #$0D ; mode in+out+concurrent + sta ICAX1,x + lda #0 + sta ICAX2,x + sta ICBLL,x ; zap buf len + sta ICBLH,x + jsr my_CIOV + bmi cioerr + + lda tmp2 ; get fd (from newfd) + sta rshand + ldx #0 + stx rshand+1 + txa + rts + +;---------------------------------------------------------------------------- +; CLOSE: Close the port, disable interrupts and flush the buffer. Called +; without parameters. Must return an error code in a/x. +; +;---------------------------------------------------------------------------- +; SER_UNINSTALL routine. Is called before the driver is removed from memory. +; Must return an SER_ERR_xx code in a/x. +; + +SER_UNINSTALL: +SER_CLOSE: + lda rshand + cmp #$ff + beq @done + + ldx rshand+1 + jsr my__close + ldx #$ff + stx rshand + stx rshand+1 + inx + stx cm_run +@done: lda #<SER_ERR_OK + ldx #>SER_ERR_OK + rts + +;---------------------------------------------------------------------------- +; SER_GET: Will fetch a character from the receive buffer and store it into the +; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is +; return. +; + +SER_GET: + ldy rshand + cpy #$ff + beq ni_err ; work only if initialized + + lda rshand + ldx #0 + jsr my_fdtoiocb + tax + lda cm_run ; concurrent mode already running? + bne @go + jsr ena_cm ; turn on concurrent mode + +@go: ; check whether there is any input available + + lda #STATIS ; status request, returns bytes pending + sta ICCOM,x + jsr my_CIOV + bmi ser_error + + lda DVSTAT+1 ; get byte count pending + ora DVSTAT+2 + beq @nix_da ; no input waiting... + + ; input is available: get it! + + lda #GETCHR ; get raw bytes + sta ICCOM,x ; in command code + lda #0 + sta ICBLL,x + sta ICBLH,x + sta ICBAL,x + sta ICBAH,x + jsr my_CIOV ; go get it + bmi ser_error + + ldx #0 + sta (ptr1,x) ; return received byte + txa + rts + +@nix_da:lda #SER_ERR_NO_DATA + ldx #0 + rts + +ser_error: + lda #SER_ERR_OVERFLOW ; there is no large selection of serial error codes... :-/ + ldx #0 + rts + +ni_err: lda #SER_ERR_NOT_OPEN + ldx #0 + rts + +;---------------------------------------------------------------------------- +; SER_PUT: Output character in A. +; Must return an error code in a/x. +; + +SER_PUT: + ldy rshand + cpy #$ff + beq ni_err ; work only if initialized + + pha ; remember char to write + lda rshand + ldx #0 + jsr my_fdtoiocb + tax + + lda cm_run ; concurrent mode already running? + bne @go + jsr ena_cm ; turn on concurrent mode + + ; @@@TODO: check output buffer overflow +@go: lda #PUTCHR ; put raw bytes + sta ICCOM,x ; in command code + lda #0 + sta ICBLL,x + sta ICBLH,x + sta ICBAL,x + sta ICBAH,x + pla ; get the char back + jsr my_CIOV ; go do it + bmi ser_error + lda #0 + tax + rts + +;---------------------------------------------------------------------------- +; SER_STATUS: Return the status in the variable pointed to by ptr1. +; Must return an error code in a/x. +; + +SER_STATUS: + ; fall through to SER_IOCTL + +;---------------------------------------------------------------------------- +; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl +; specific data in ptr1, and the ioctl code in A. +; Must return an error code in a/x. +; + +SER_IOCTL: + lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #>SER_ERR_INV_IOCTL + rts + +;---------------------------------------------------------------------------- +; SER_IRQ: Not used on the Atari +; + +SER_IRQ = $0000 + +;---------------------------------------------------------------------------- +; SER_INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return an SER_ERR_xx code in a/x. + +SER_INSTALL: + ; check if R: device is installed + ldy #0 +search: lda HATABS,y ; get device name + cmp #'R' + beq found + iny + iny + iny + cpy #MAXDEV + bcc search + +; R: device not found, return error + + lda #<SER_ERR_NO_DEVICE + ldx #0 + rts + +; R: device found, initialize jump table into main program + +found: lda ptr3 + pha + lda ptr3+1 + pha + lda libref + sta ptr3 + lda libref+1 + sta ptr3+1 + + ldy #0 + lda (ptr3),y + sta my_newfd+1 + iny + lda (ptr3),y + sta my_newfd+2 + iny + + lda (ptr3),y + sta my__close+1 + iny + lda (ptr3),y + sta my__close+2 + iny + + lda (ptr3),y + sta my_pushax+1 + iny + lda (ptr3),y + sta my_pushax+2 + iny + + lda (ptr3),y + sta my_popax+1 + iny + lda (ptr3),y + sta my_popax+2 + iny + + lda (ptr3),y + sta my_findfreeiocb+1 + iny + lda (ptr3),y + sta my_findfreeiocb+2 + iny + + lda (ptr3),y + sta my___do_oserror+1 + iny + lda (ptr3),y + sta my___do_oserror+2 + iny + + lda (ptr3),y + sta my_fddecusage+1 + iny + lda (ptr3),y + sta my_fddecusage+2 + iny + + lda (ptr3),y + sta my_fdtoiocb+1 + iny + lda (ptr3),y + sta my_fdtoiocb+2 + iny + + lda (ptr3),y + sta my___inviocb+1 + iny + lda (ptr3),y + sta my___inviocb+2 + iny + + lda (ptr3),y + sta my_clriocb+1 + iny + lda (ptr3),y + sta my_clriocb+2 + iny + + lda (ptr3),y + sta my_CIOV+1 + iny + lda (ptr3),y + sta my_CIOV+2 + ;iny + + pla + sta ptr3+1 + pla + sta ptr3 + + lda #<SER_ERR_OK + tax ; A is zero + rts + + +; enable concurrent rs232 mode +; gets iocb index in X +; all registers destroyed + +.proc ena_cm + + lda #40 ; XIO 40, start concurrent IO + sta ICCOM,x + sta cm_run ; indicate concurrent mode is running + lda #$0D ; value from 850 manual, p62. must be $0D?, + sta ICAX1,x ; or any non-zero? + lda #0 + sta ICAX2,x + lda #<recv_buf + sta ICBAL,x + lda #>recv_buf + sta ICBAH,x + lda #<RECVBUF_SZ + sta ICBLL,x + lda #>RECVBUF_SZ + sta ICBLH,x + jmp my_CIOV + +.endproc ;ena_cm diff --git a/libsrc/atari/serref.s b/libsrc/atari/serref.s new file mode 100644 index 000000000..89ef1e519 --- /dev/null +++ b/libsrc/atari/serref.s @@ -0,0 +1,33 @@ +; +; Christian Groessler, 2014-04-22 +; + + .include "atari.inc" + + .export ser_libref + + .import _close, pushax, popax + .import findfreeiocb + .import __do_oserror + .import fddecusage + .import fdtoiocb + .import __inviocb + .import clriocb + .import newfd + +ser_libref := atari_ser_libref + +.rodata + +atari_ser_libref: + .word newfd + .word _close + .word pushax + .word popax + .word findfreeiocb + .word __do_oserror + .word fddecusage + .word fdtoiocb + .word __inviocb + .word clriocb + .word CIOV diff --git a/libsrc/atari/shadow_ram_timerirq1.s b/libsrc/atari/shadow_ram_timerirq1.s new file mode 100644 index 000000000..f8a3e9b4d --- /dev/null +++ b/libsrc/atari/shadow_ram_timerirq1.s @@ -0,0 +1,81 @@ +; +; Atari XL shadow RAM timer IRQ #1 handler +; +; Christian Groessler, chris@groessler.org, 2014 +; + +;DEBUG = 1 + +.ifdef __ATARIXL__ + +SHRAM_HANDLERS = 1 + .include "atari.inc" + .include "romswitch.inc" + .export set_VTIMR1_handler + + +.segment "LOWBSS" + +VTIMR1_handler: .res 3 + + +.segment "BSS" + +old_VTIMR1_handler: + .res 2 + + +.segment "LOWCODE" + +; timer interrupt handler: +; disable ROM, call user handler, enable ROM again + +my_VTIMR1_handler: + disable_rom_quick + jsr VTIMR1_handler + enable_rom_quick + pla + rti + +.segment "CODE" + +; install or remove VTIMR1 handler +; input: CF - 0/1 for remove/install handler +; AX - pointer to handler (if CF=1) +; registers destroyed + +set_VTIMR1_handler: + + bcc @remove + +; install vector + + stx VTIMR1_handler+2 + sta VTIMR1_handler+1 ; save passed vector in low memory + lda #$4C ; "JMP" opcode + sta VTIMR1_handler + + lda VTIMR1 + sta old_VTIMR1_handler + lda VTIMR1+1 + sta old_VTIMR1_handler+1 + + lda #<my_VTIMR1_handler + php + sei + sta VTIMR1 + lda #>my_VTIMR1_handler + sta VTIMR1+1 + plp + rts + +@remove: php + sei + lda old_VTIMR1_handler + sta VTIMR1 + lda old_VTIMR1_handler+1 + sta VTIMR1+1 + plp + rts + +.endif ; .ifdef __ATARIXL__ diff --git a/libsrc/atari/sysrename.s b/libsrc/atari/sysrename.s index fef18bded..e526af5c8 100644 --- a/libsrc/atari/sysrename.s +++ b/libsrc/atari/sysrename.s @@ -45,13 +45,7 @@ iocbok: stx tmp4 ; remember IOCB index ldy #0 sty sspc+1 ; initialize stack space -.ifndef UCASE_FILENAME - - sta ptr3 - stx ptr3+1 - sty sspc - -.else +.ifdef UCASE_FILENAME ; uppercase first (old) name and prepend device if needed @@ -100,6 +94,12 @@ ucok2: sta ptr2 ; remember pointer to uppercased new name inc sspc+1 ukok4: +.else + + sta ptr3 + stx ptr3+1 + sty sspc + .endif ; create a string on the stack with the old filename and the new filename separated by an invalid character (space in our case) diff --git a/libsrc/atari/system_check.s b/libsrc/atari/system_check.s index dbc0b5dfb..2f1feefc4 100644 --- a/libsrc/atari/system_check.s +++ b/libsrc/atari/system_check.s @@ -194,7 +194,7 @@ delay1: ldx #0 end: .ifndef __ATARIXL__ -tmp: ; outside of the load chunk, some kind of poor man's .bss +tmp: ; outside of the load chunk, some kind of poor man's .bss .endif ; ------------------------------------------------------------------------ diff --git a/libsrc/atari/systime.s b/libsrc/atari/systime.s index d22b8c596..273e394a4 100644 --- a/libsrc/atari/systime.s +++ b/libsrc/atari/systime.s @@ -3,10 +3,10 @@ ; ; time_t _systime (void); ; /* Similar to time(), but: -; * - Is not ISO C -; * - Does not take the additional pointer -; * - Does not set errno when returning -1 -; */ +; ** - Is not ISO C +; ** - Does not take the additional pointer +; ** - Does not set errno when returning -1 +; */ ; .export __systime diff --git a/libsrc/atari/targetutil/Makefile.inc b/libsrc/atari/targetutil/Makefile.inc new file mode 100644 index 000000000..05405f2e6 --- /dev/null +++ b/libsrc/atari/targetutil/Makefile.inc @@ -0,0 +1,9 @@ +DEPS += ../libwrk/$(TARGET)/w2cas.d + +../libwrk/$(TARGET)/w2cas.o: $(SRCDIR)/targetutil/w2cas.c | ../libwrk/$(TARGET) + $(COMPILE_recipe) + +../targetutil/w2cas.com: ../libwrk/$(TARGET)/w2cas.o ../lib/$(TARGET).lib | ../targetutil + $(LD65) -o $@ -t $(TARGET) $^ + +$(TARGET): ../targetutil/w2cas.com diff --git a/libsrc/atari/targetutil/w2cas.c b/libsrc/atari/targetutil/w2cas.c new file mode 100644 index 000000000..4d574da07 --- /dev/null +++ b/libsrc/atari/targetutil/w2cas.c @@ -0,0 +1,186 @@ +/* w2cas.c -- write file to cassette +** +** This program writes a boot file (typically linked with +** 'atari-cassette.cfg') to the cassette. +** Only files < 32K are supported, since the loading of +** larger files requires a special loader inside the program. +** +** Christian Groessler, chris@groessler.org, 2014 +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <6502.h> +#include <atari.h> +#include <conio.h> + +static int verbose = 1; +static char C_dev[] = "C:"; + +static struct __iocb *findfreeiocb(void) +{ + struct __iocb *iocb = &IOCB; /* first IOCB (#0) */ + int i; + + for (i = 0; i < 8; i++) { + if (iocb->handler == 0xff) + return iocb; + iocb++; + } + return NULL; +} + +int main(int argc, char **argv) +{ + char *filename, *x; + char buf[20]; + FILE *file; + unsigned char *buffer; + size_t filen, buflen = 32768l + 1; + struct regs regs; + struct __iocb *iocb = findfreeiocb(); + int iocb_num; + + if (! iocb) { + fprintf(stderr, "couldn't find a free iocb\n"); + if (_dos_type != 1) + cgetc(); + return 1; + } + iocb_num = (iocb - &IOCB) * 16; + if (verbose) + printf("using iocb index $%02X ($%04X)\n", iocb_num, iocb); + + if (argc < 2) { + printf("\nfilename: "); + x = fgets(buf, 19, stdin); + printf("\n"); + if (! x) + return 1; + if (*x && *(x + strlen(x) - 1) == '\n') + *(x + strlen(x) - 1) = 0; + filename = x; + } + else { + filename = *(argv+1); + } + + /* allocate buffer */ + buffer = malloc(buflen); + if (! buffer) { + buflen = _heapmaxavail(); /* get as much as we can */ + buffer = malloc(buflen); + if (! buffer) { + fprintf(stderr, "cannot alloc %ld bytes -- aborting...\n", (long)buflen); + if (_dos_type != 1) + cgetc(); + return 1; + } + } + if (verbose) + printf("buffer size: %ld bytes\n", (long)buflen); + + /* open file */ + file = fopen(filename, "rb"); + if (! file) { + free(buffer); + fprintf(stderr, "cannot open '%s': %s\n", filename, strerror(errno)); + if (_dos_type != 1) + cgetc(); + return 1; + } + + /* read file -- file length must be < 32K */ + if (verbose) + printf("reading input file...\n"); + filen = fread(buffer, 1, buflen, file); + if (! filen) { + fprintf(stderr, "read error\n"); + file_err: + fclose(file); + free(buffer); + if (_dos_type != 1) + cgetc(); + return 1; + } + if (filen > 32767l) { + fprintf(stderr, "file is too large (must be < 32768)\n"); + goto file_err; + } + if (filen == buflen) { /* we have a buffer < 32768 and the file fits into it (and is most probably larger) */ + fprintf(stderr, "not enough memory\n"); + goto file_err; + } + if (verbose) + printf("file size: %ld bytes\n", (long)filen); + + /* close input file */ + fclose(file); + + /* open cassette */ + if (verbose) + printf("opening cassette...\n"); + iocb->buffer = C_dev; + iocb->aux1 = 8; /* open for output */ + iocb->aux2 = 128; /* short breaks and no stop between data blocks */ + iocb->command = IOCB_OPEN; + regs.x = iocb_num; + regs.pc = 0xe456; /* CIOV */ + + _sys(®s); + if (regs.y != 1) { + fprintf(stderr, "CIO call to open cassette returned %d\n", regs.y); + free(buffer); + if (_dos_type != 1) + cgetc(); + return 1; + } + + /* write file */ + if (verbose) + printf("writing to cassette...\n"); + iocb->buffer = buffer; + iocb->buflen = filen; + iocb->command = IOCB_PUTCHR; + regs.x = iocb_num; + regs.pc = 0xe456; /* CIOV */ + + _sys(®s); + if (regs.y != 1) { + fprintf(stderr, "CIO call to write file returned %d\n", regs.y); + free(buffer); + + iocb->command = IOCB_CLOSE; + regs.x = iocb_num; + regs.pc = 0xe456; /* CIOV */ + _sys(®s); + + if (_dos_type != 1) + cgetc(); + return 1; + } + + /* free buffer */ + free(buffer); + + /* close cassette */ + iocb->command = IOCB_CLOSE; + regs.x = iocb_num; + regs.pc = 0xe456; /* CIOV */ + _sys(®s); + + if (regs.y != 1) { + fprintf(stderr, "CIO call to close cassette returned %d\n", regs.y); + if (_dos_type != 1) + cgetc(); + return 1; + } + + /* all is fine */ + printf("success\n"); + if (_dos_type != 1) + cgetc(); + return 0; +} diff --git a/libsrc/atari/tgi/atari_tgi_common.inc b/libsrc/atari/tgi/atari_tgi_common.inc index 0d7972d34..f4ef68165 100644 --- a/libsrc/atari/tgi/atari_tgi_common.inc +++ b/libsrc/atari/tgi/atari_tgi_common.inc @@ -3,6 +3,7 @@ ; .macpack longbranch +.macpack module .ifdef __ATARIXL__ CIO_vec := my_CIOV @@ -18,7 +19,19 @@ ; ; ---------------------------------------------------------------------- -.segment "JUMPTABLE" +.ifdef __ATARIXL__ + .define LABEL_X "x" +.else + .define LABEL_X "" +.endif + +.if pages = 2 + .define LABEL_P2 "p2" +.else + .define LABEL_P2 "" +.endif + + module_header .ident (.sprintf ("_atr%s%d%s_tgi", LABEL_X, ::grmode, LABEL_P2)) ; Header diff --git a/libsrc/atari/tgi_stat_stddrv.s b/libsrc/atari/tgi_stat_stddrv.s index 5f1be70f8..dc3b7cc71 100644 --- a/libsrc/atari/tgi_stat_stddrv.s +++ b/libsrc/atari/tgi_stat_stddrv.s @@ -7,8 +7,16 @@ ; .export _tgi_static_stddrv + .ifdef __ATARIXL__ + .import _atrx8_tgi + .else .import _atr8_tgi + .endif .rodata + .ifdef __ATARIXL__ +_tgi_static_stddrv := _atrx8_tgi + .else _tgi_static_stddrv := _atr8_tgi + .endif diff --git a/libsrc/atari/tgi_stddrv.s b/libsrc/atari/tgi_stddrv.s index bec030511..e2f68a50e 100644 --- a/libsrc/atari/tgi_stddrv.s +++ b/libsrc/atari/tgi_stddrv.s @@ -10,4 +10,9 @@ .rodata -_tgi_stddrv: .asciiz "atr8.tgi" +_tgi_stddrv: + .ifdef __ATARIXL__ + .asciiz "atrx8.tgi" + .else + .asciiz "atr8.tgi" + .endif diff --git a/libsrc/atari5200/cartentry.s b/libsrc/atari5200/cartentry.s new file mode 100644 index 000000000..431843a55 --- /dev/null +++ b/libsrc/atari5200/cartentry.s @@ -0,0 +1,13 @@ +; Cartridge entry point +; +; Christian Groessler, 01-Mar-2014 + +.export __CART_ENTRY__: absolute = 1 +.import __CARTSIZE__, start +.forceimport __CART_YEAR__, __CART_NAME__ + +.segment "CARTENTRY" + + .word start ; entry point + +.assert (__CARTSIZE__ = $4000 || __CARTSIZE__ = $8000), error, "Cartridge size must either be $4000 or $8000" diff --git a/libsrc/atari5200/cartname.s b/libsrc/atari5200/cartname.s new file mode 100644 index 000000000..c6a701884 --- /dev/null +++ b/libsrc/atari5200/cartname.s @@ -0,0 +1,13 @@ +; default cartridge name +; +; Christian Groessler, 01-Mar-2014 + +.include "atari.mac" + +.export __CART_NAME__: absolute = 1 + +.segment "CARTNAME" + + scrcode " cc" + .byte '6' + 32, '5' + 32 ; use playfield 1 + scrcode " compiled" diff --git a/libsrc/atari5200/cartyear.s b/libsrc/atari5200/cartyear.s new file mode 100644 index 000000000..4efb24f5e --- /dev/null +++ b/libsrc/atari5200/cartyear.s @@ -0,0 +1,9 @@ +; Cartridge copyright year +; +; Christian Groessler, 01-Mar-2014 + +.export __CART_YEAR__: absolute = 1 + +.segment "CARTYEAR" + + .byte '9' + 32,'8' + 32 ; "98", but using playfield 1 diff --git a/libsrc/atari5200/cclear.s b/libsrc/atari5200/cclear.s new file mode 100644 index 000000000..4bdc8ddf1 --- /dev/null +++ b/libsrc/atari5200/cclear.s @@ -0,0 +1 @@ +.include "../atari/cclear.s" diff --git a/libsrc/atari5200/chline.s b/libsrc/atari5200/chline.s new file mode 100644 index 000000000..d5872f149 --- /dev/null +++ b/libsrc/atari5200/chline.s @@ -0,0 +1 @@ +.include "../atari/chline.s" diff --git a/libsrc/atari5200/clock.s b/libsrc/atari5200/clock.s new file mode 100644 index 000000000..f2ef85b0b --- /dev/null +++ b/libsrc/atari5200/clock.s @@ -0,0 +1,26 @@ +; +; from Atari computer version by Christian Groessler, 2014 +; +; clock_t clock (void); +; unsigned _clocks_per_sec (void); +; + + .export _clock + .importzp sreg + + .include "atari5200.inc" + + +.proc _clock + + ldx #5 ; Synchronize with Antic, so the interrupt won't change RTCLOK + stx WSYNC ; while we're reading it. The synchronization is done same as +@L1: dex ; in SETVBLV function in Atari OS. + bne @L1 + stx sreg+1 ; Byte 3 is always zero + stx sreg ; Byte 2 is always zero, too + lda RTCLOK+1 + ldx RTCLOK + rts + +.endproc diff --git a/libsrc/atari5200/clrscr.s b/libsrc/atari5200/clrscr.s new file mode 100644 index 000000000..041f34a67 --- /dev/null +++ b/libsrc/atari5200/clrscr.s @@ -0,0 +1,34 @@ +; +; Christian Groessler, May-2014 +; +; void clrscr (void); +; + + .export _clrscr + .include "atari5200.inc" + .importzp ptr1 + +SCRSIZE = 480 ; 20x24: size of default conio atari5200 screen + +_clrscr:lda SAVMSC ; screen memory + sta ptr1 + lda SAVMSC+1 + clc + adc #>(SCRSIZE-1) + sta ptr1+1 + lda #0 ; screen code of space char + ldy #<(SCRSIZE-1) + ldx #>(SCRSIZE-1) +_clr1: sta (ptr1),y + dey + bne _clr1 + sta (ptr1),y + dex + bmi done + dec ptr1+1 + dey + jmp _clr1 + +done: sta COLCRS_5200 + sta ROWCRS_5200 + rts diff --git a/libsrc/atari5200/conioscreen.s b/libsrc/atari5200/conioscreen.s new file mode 100644 index 000000000..412dd582d --- /dev/null +++ b/libsrc/atari5200/conioscreen.s @@ -0,0 +1,83 @@ +; setup default CONIO screen (20x24, Antic mode 6, BASIC mode 1) +; +; 28-May-2014, Christian Groessler <chris@groessler.org> + + .include "atari5200.inc" + +SCREEN_BUF_SIZE = 20 * 24 +SCREEN_BUF = $4000 - SCREEN_BUF_SIZE + + .code + .export screen_setup_20x24 + +screen_setup_20x24: + + ; initialize SAVMSC + lda #<SCREEN_BUF + sta SAVMSC + lda #>SCREEN_BUF + sta SAVMSC+1 + + ; initialize cursor position + lda #0 + sta COLCRS_5200 + sta ROWCRS_5200 + + ; clear screen buffer + ldy #<(SCREEN_BUF_SIZE-1) + ldx #>(SCREEN_BUF_SIZE-1) +clrscr: sta (SAVMSC),y + dey + cpy #$FF + bne clrscr + dex + cpx #$FF + bne clrscr + + ; set default colors + + lda #40 + sta COLOR0 + lda #202 + sta COLOR1 + lda #148 + sta COLOR2 + lda #70 + sta COLOR3 + lda #0 + sta COLOR4 + + ; set display list + + lda #<dlist + sta SDLSTL + lda #>dlist + sta SDLSTH + + rts + + + .segment "RODATA" + +; display list for 20x24 text mode + +dlist: .repeat 3 + .byte DL_BLK8 + .endrepeat + + .byte DL_CHR20x8x2 | DL_LMS + .word SCREEN_BUF + + .repeat 23 + .byte DL_CHR20x8x2 + .endrepeat + + .byte DL_JVB + .word dlist + +; end of display list + +.assert ((* >> 10) = (dlist >> 10)), error, "Display list crosses 1K boundary" + + + .end diff --git a/libsrc/atari5200/cputc.s b/libsrc/atari5200/cputc.s new file mode 100644 index 000000000..4bee0fba2 --- /dev/null +++ b/libsrc/atari5200/cputc.s @@ -0,0 +1,94 @@ +; +; adapted from Atari version +; Christian Groessler, 2014 +; +; void cputcxy (unsigned char x, unsigned char y, char c); +; void cputc (char c); +; + + .include "atari5200.inc" + + .export _cputcxy, _cputc + .export plot, cputdirect, putchar + .import popa, _gotoxy, mul20 + .importzp ptr4 + .import setcursor + + .constructor screen_setup, 26 + .import screen_setup_20x24 +screen_setup = screen_setup_20x24 + + +_cputcxy: + pha ; Save C + jsr popa ; Get Y + jsr _gotoxy ; Set cursor, drop x + pla ; Restore C + +_cputc: + cmp #$0D ; CR + bne L4 + lda #0 + sta COLCRS_5200 + beq plot ; return + +L4: cmp #$0A ; LF + beq newline + cmp #ATEOL ; Atari-EOL? + beq newline + + tay + rol a + rol a + rol a + rol a + and #3 + tax + tya + and #$9f + ora ataint,x + +cputdirect: ; accepts screen code + jsr putchar + +; advance cursor + inc COLCRS_5200 + lda COLCRS_5200 + cmp #20 + bcc plot + lda #0 + sta COLCRS_5200 + + .export newline +newline: + inc ROWCRS_5200 + lda ROWCRS_5200 + cmp #24 + bne plot + lda #0 + sta ROWCRS_5200 +plot: jsr setcursor + ldy COLCRS_5200 + ldx ROWCRS_5200 + rts + +putchar: + pha ; save char + + lda ROWCRS_5200 + jsr mul20 ; destroys tmp4 + clc + adc SAVMSC ; add start of screen memory + sta ptr4 + txa + adc SAVMSC+1 + sta ptr4+1 + pla ; get char again + + ldy COLCRS_5200 + sta (ptr4),y + jmp setcursor + + .rodata +ataint: .byte 64,0,32,96 + diff --git a/libsrc/atari5200/crt0.s b/libsrc/atari5200/crt0.s new file mode 100644 index 000000000..7073bb2a7 --- /dev/null +++ b/libsrc/atari5200/crt0.s @@ -0,0 +1,48 @@ +; +; Startup code for cc65 (Atari5200 version) +; +; Christian Groessler (chris@groessler.org), 2014 +; + + .export _exit, start + .export __STARTUP__ : absolute = 1 ; Mark as startup + .import __RAM_START__, __RAM_SIZE__ + .import __RESERVED_MEMORY__ + + .import initlib, donelib, callmain + .import zerobss, copydata + + .include "zeropage.inc" + .include "atari5200.inc" + +start: + +; Clear the BSS data. + + jsr zerobss + +; Initialize the data. + jsr copydata + +; Set up the stack. + + lda #<(__RAM_START__ + __RAM_SIZE__ - __RESERVED_MEMORY__) + sta sp + lda #>(__RAM_START__ + __RAM_SIZE__ - __RESERVED_MEMORY__) + sta sp+1 ; Set argument stack ptr + +; Call the module constructors. + + jsr initlib + +; Push the command-line arguments; and, call main(). + + jsr callmain + +; Call the module destructors. This is also the exit() entry. + +_exit: jsr donelib ; Run module destructors + +; A 5200 program isn't supposed to exit. + +halt: jmp halt diff --git a/libsrc/atari5200/ctype.s b/libsrc/atari5200/ctype.s new file mode 100644 index 000000000..432f46240 --- /dev/null +++ b/libsrc/atari5200/ctype.s @@ -0,0 +1,5 @@ +; Character specification table. +; +; same as for "atari" target + +.include "../atari/ctype.s" diff --git a/libsrc/atari5200/cvline.s b/libsrc/atari5200/cvline.s new file mode 100644 index 000000000..d987bcb62 --- /dev/null +++ b/libsrc/atari5200/cvline.s @@ -0,0 +1 @@ +.include "../atari/cvline.s" diff --git a/libsrc/atari5200/get_tv.s b/libsrc/atari5200/get_tv.s new file mode 100644 index 000000000..99cac3c48 --- /dev/null +++ b/libsrc/atari5200/get_tv.s @@ -0,0 +1,20 @@ +; +; Christian Groessler, 2014 +; +; unsigned char get_tv (void); +; /* Return the video mode the machine is using */ +; + + .include "get_tv.inc" + + +;-------------------------------------------------------------------------- +; _get_tv + +.proc _get_tv + + lda #<TV::NTSC + ldx #>TV::NTSC + rts + +.endproc diff --git a/libsrc/atari5200/gotox.s b/libsrc/atari5200/gotox.s new file mode 100644 index 000000000..99f7cfd22 --- /dev/null +++ b/libsrc/atari5200/gotox.s @@ -0,0 +1,13 @@ +; +; Christian Groessler, 13-Mar-2014 +; +; void gotox (unsigned char x); +; + + .include "atari5200.inc" + .export _gotox + .import setcursor + +_gotox: + sta COLCRS_5200 ; Set X + jmp setcursor diff --git a/libsrc/atari5200/gotoxy.s b/libsrc/atari5200/gotoxy.s new file mode 100644 index 000000000..a4b7c61d0 --- /dev/null +++ b/libsrc/atari5200/gotoxy.s @@ -0,0 +1,17 @@ +; +; Christian Groessler, 13-Mar-2014 +; +; void gotoxy (unsigned char x, unsigned char y); +; + + .include "atari5200.inc" + + .export _gotoxy + .import popa + .import setcursor + +_gotoxy: ; Set the cursor position + sta ROWCRS_5200 ; Set Y + jsr popa ; Get X + sta COLCRS_5200 ; Set X + jmp setcursor diff --git a/libsrc/atari5200/gotoy.s b/libsrc/atari5200/gotoy.s new file mode 100644 index 000000000..fcdd05e4c --- /dev/null +++ b/libsrc/atari5200/gotoy.s @@ -0,0 +1,13 @@ +; +; Christian Groessler, 13-Mar-2014 +; +; void gotoy (unsigned char y); +; + + .include "atari5200.inc" + .export _gotoy + .import setcursor + +_gotoy: + sta ROWCRS_5200 ; Set Y + jmp setcursor diff --git a/libsrc/atari5200/irq.s b/libsrc/atari5200/irq.s new file mode 100644 index 000000000..720113f82 --- /dev/null +++ b/libsrc/atari5200/irq.s @@ -0,0 +1,59 @@ +; +; IRQ handling (ATARI 5200 version) +; + + .export initirq, doneirq + .import callirq + + .include "atari5200.inc" + +; ------------------------------------------------------------------------ + +.segment "INIT" + +initirq: + lda VVBLKD + ldx VVBLKD+1 + sta IRQInd+1 + stx IRQInd+2 + ldy #<IRQStub + ldx #>IRQStub + jmp SETVBV + +; ------------------------------------------------------------------------ + +.code + +doneirq: + ldy IRQInd+1 + ldx IRQInd+2 + ;jmp SETVBV + ; fall thru + +; ------------------------------------------------------------------------ +; Set deferred vertical blank interrupt +; logic copied from Atari computer ROM + +SETVBV: txa + ldx #5 + sta WSYNC ; waste 20 CPU cycles +@1: dex ; to allow VBLANK to happen + bne @1 ; if this is line "7C" + sta VVBLKD+1 + sty VVBLKD + rts + +; ------------------------------------------------------------------------ + +.segment "LOWCODE" + +IRQStub: + cld ; Just to be sure + jsr callirq ; Call the functions + jmp IRQInd ; Jump to the saved IRQ vector + +; ------------------------------------------------------------------------ + +.data + +IRQInd: jmp $0000 diff --git a/libsrc/atari5200/joy/atr5200std.s b/libsrc/atari5200/joy/atr5200std.s new file mode 100644 index 000000000..3483cc11a --- /dev/null +++ b/libsrc/atari5200/joy/atr5200std.s @@ -0,0 +1,132 @@ +; +; Standard joystick driver for the Atari 5200. +; +; Christian Groessler, 2014-05-28 +; + + .include "zeropage.inc" + + .include "joy-kernel.inc" + .include "joy-error.inc" + .include "atari5200.inc" + + .macpack module + + +; ------------------------------------------------------------------------ +; Header. Includes jump table + + module_header _atr5200std_joy + +; Driver signature + + .byte $6A, $6F, $79 ; "joy" + .byte JOY_API_VERSION ; Driver API version number + +; Library reference + + .addr $0000 + +; Button state masks (8 values) + + .byte $01 ; JOY_UP + .byte $02 ; JOY_DOWN + .byte $04 ; JOY_LEFT + .byte $08 ; JOY_RIGHT + .byte $10 ; JOY_FIRE + .byte $20 ; JOY_FIRE2 + .byte $00 ; Future expansion + .byte $00 ; Future expansion + +; Jump table. + + .addr INSTALL + .addr UNINSTALL + .addr COUNT + .addr READJOY + .addr 0 ; IRQ entry not used + +.code + +; ------------------------------------------------------------------------ +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present and determine the amount of +; memory available. +; Must return an JOY_ERR_xx code in a/x. +; + +INSTALL: + lda #JOY_ERR_OK + ldx #0 +; rts ; Run into UNINSTALL instead + +; ------------------------------------------------------------------------ +; UNINSTALL routine. Is called before the driver is removed from memory. +; Can do cleanup or whatever. Must not return anything. +; + +UNINSTALL: + rts + + +; ------------------------------------------------------------------------ +; COUNT: Return the total number of available joysticks in a/x. +; + +COUNT: + lda $FD32 ; check ROM version + cmp #$E8 + bne @2port + lda #4 + .byte $2C ; bit opcode, eats the next 2 bytes +@2port: lda #2 + ldx #0 + rts + +; ------------------------------------------------------------------------ +; READ: Read a particular joystick passed in A. +; + +CENTER = 228 / 2 +SENSIVITY = 16 + +READJOY: + and #3 ; put joystick number in range, just in case + tay + asl a + tax ; Joystick number * 2 (0-6) into X, index into ZP shadow registers + + lda #0 ; Initialize return value + cmp TRIG0,y + bne @notrg + lda #$10 ; JOY_FIRE + +; Read joystick + +@notrg: ldy PADDL0,x ; get horizontal position + cpy #CENTER-SENSIVITY + bcs @chkleft + + ora #4 ; JOY_LEFT + bne @updown + +@chkleft: + cpy #CENTER+SENSIVITY + bcc @updown + + ora #8 ; JOY_RIGHT + +@updown:ldy PADDL0+1,x ; get vertical position + cpy #CENTER-SENSIVITY + bcs @chkdown + + ora #1 ; JOY_UP + bne @done + +@chkdown: + cpy #CENTER+SENSIVITY + bcc @done + + ora #2 ; JOY_DOWN + +@done: rts diff --git a/libsrc/atari5200/joy_stat_stddrv.s b/libsrc/atari5200/joy_stat_stddrv.s new file mode 100644 index 000000000..9924eab73 --- /dev/null +++ b/libsrc/atari5200/joy_stat_stddrv.s @@ -0,0 +1,12 @@ +; +; Address of the static standard joystick driver +; +; Christian Groessler, 2014-05-12 +; +; const void joy_static_stddrv[]; +; + + .export _joy_static_stddrv + .import _atr5200std_joy + +_joy_static_stddrv := _atr5200std_joy diff --git a/libsrc/atari5200/libref.s b/libsrc/atari5200/libref.s new file mode 100644 index 000000000..8a5fbe4e0 --- /dev/null +++ b/libsrc/atari5200/libref.s @@ -0,0 +1,8 @@ +; +; Christian Groessler, 2014-05-12 +; + + .export joy_libref + .import _exit + +joy_libref := _exit diff --git a/libsrc/atari5200/mul20.s b/libsrc/atari5200/mul20.s new file mode 100644 index 000000000..fc67b34e4 --- /dev/null +++ b/libsrc/atari5200/mul20.s @@ -0,0 +1,33 @@ +; +; Christian Groessler, April 2014 +; +; mul20 +; multiplies A by 20 and returns result in AX +; uses tmp4 + + .importzp tmp4 + .export mul20,loc_tmp + +.proc mul20 + + ldx #0 + stx tmp4 + sta loc_tmp + asl a + rol tmp4 + asl a + rol tmp4 ; val * 4 + adc loc_tmp + bcc L1 + inc tmp4 ; val * 5 +L1: asl a + rol tmp4 ; val * 10 + asl a + rol tmp4 ; val * 20 + ldx tmp4 + rts + +.endproc + + .bss +loc_tmp:.res 1 diff --git a/libsrc/atari5200/randomize.s b/libsrc/atari5200/randomize.s new file mode 100644 index 000000000..ef462827e --- /dev/null +++ b/libsrc/atari5200/randomize.s @@ -0,0 +1,17 @@ +; +; Christian Groessler, 01-Mar-2014 +; +; void _randomize (void); +; /* Initialize the random number generator */ +; + + .export __randomize + .import _srand + + .include "atari5200.inc" + +__randomize: + ldx VCOUNT ; Use vertical line counter as high byte + lda RTCLOK+1 ; Use clock as low byte + jmp _srand ; Initialize generator + diff --git a/libsrc/atari5200/setcursor.s b/libsrc/atari5200/setcursor.s new file mode 100644 index 000000000..4cf8ebac7 --- /dev/null +++ b/libsrc/atari5200/setcursor.s @@ -0,0 +1,11 @@ +; Dummy version, there is no visible cursor in the default CONIO screen +; +; 28-May-2014, Christian Groessler <chris@groessler.org> + + .export setcursor + +.proc setcursor + + rts + +.endproc diff --git a/libsrc/atari5200/sysuname.s b/libsrc/atari5200/sysuname.s new file mode 100644 index 000000000..7fd9281a1 --- /dev/null +++ b/libsrc/atari5200/sysuname.s @@ -0,0 +1,39 @@ +; +; Ullrich von Bassewitz, 2003-08-12 +; +; unsigned char __fastcall__ _sysuname (struct utsname* buf); +; + + .export __sysuname, utsdata + + .import utscopy + + __sysuname = utscopy + +;-------------------------------------------------------------------------- +; Data. We define a fixed utsname struct here and just copy it. + +.rodata + +utsdata: + ; sysname + .asciiz "cc65" + + ; nodename + .asciiz "" + + ; release + .byte ((.VERSION >> 8) & $0F) + '0' + .byte '.' + .byte ((.VERSION >> 4) & $0F) + '0' + .byte $00 + + ; version + .byte (.VERSION & $0F) + '0' + .byte $00 + + ; machine + .asciiz "Atari5200" + + + diff --git a/libsrc/atari5200/y2k.inc b/libsrc/atari5200/y2k.inc new file mode 100644 index 000000000..a44d027a1 --- /dev/null +++ b/libsrc/atari5200/y2k.inc @@ -0,0 +1,41 @@ +;----------------------------------------------------------- +; Y2K FIX by Alan Davis, Dennis Debro, and Ronen Habot +;----------------------------------------------------------- +Y2K LDY #$00 ; Copy BIOS opening screen to RAM + LDA #$FD + STA TEMPH + LDA #$58 ; Assume 2 port system + LDX $FD32 + CPX #$E8 ; Is this a 4 port? + BNE Y2K0 ; Jump if not + LDA #$42 ; Yes, 4 port system +Y2K0 STA TEMPL +Y2K1 LDA (TEMPL),Y + STA $0600,Y + INY + BNE Y2K1 + LDY #$50 + INC TEMPH +Y2K2 LDA (TEMPL),Y + STA $0700,Y + DEY + BPL Y2K2 + LDA #$D4 ; Point to copyright string + STA $0724 + LDA #$BF + STA $0725 + LDX #$0B ; Store NOP's @ end + LDA #$EA +Y2K3 STA $0732,X + DEX + BPL Y2K3 + LDA #$60 ; Store RTS opcode @ end + STA $0750 + JSR $0600 ; Show title screen + LDY #$00 ; Clear RAM from $0600-$3FFF + STY $80 + LDA #$06 + STA $81 + JSR CLRRAM + RTS + diff --git a/libsrc/atmos/capslock.s b/libsrc/atmos/capslock.s new file mode 100644 index 000000000..0ed6e70da --- /dev/null +++ b/libsrc/atmos/capslock.s @@ -0,0 +1,49 @@ +; +; When Oric computers are in BASIC's command mode, the keyboard is in CAPS lock +; mode (because Oric BASIC keywords must be typed in upper-case). This +; constructor disables that mode, so that text will be typed as lower-case +; (which is the default on other cc65 platforms). +; This module is linked by the conio and POSIX input functions. +; +; 2014-09-04, Greg King +; + + .constructor disable_caps + .destructor restore_caps + + .include "atmos.inc" + + +;-------------------------------------------------------------------------- +; Put this constructor into a segment that can be re-used by programs. +; +.segment "INIT" + +; Turn the capitals lock off. + +disable_caps: + lda CAPSLOCK + sta capsave + lda #$7F + sta CAPSLOCK + rts + + +;-------------------------------------------------------------------------- + +.code + +; Restore the old capitals-lock state. + +restore_caps: + lda capsave + sta CAPSLOCK + rts + + +;-------------------------------------------------------------------------- + +.bss + +capsave: + .res 1 diff --git a/libsrc/atmos/cgetc.s b/libsrc/atmos/cgetc.s index e13d143d2..e4ea15ac6 100644 --- a/libsrc/atmos/cgetc.s +++ b/libsrc/atmos/cgetc.s @@ -1,13 +1,15 @@ ; ; 2003-04-13, Ullrich von Bassewitz -; 2013-07-26, Greg King +; 2014-09-04, Greg King ; ; char cgetc (void); ; .export _cgetc .constructor initcgetc + .import cursor + .forceimport disable_caps .include "atmos.inc" @@ -22,11 +24,11 @@ ; No character, enable cursor and wait - lda cursor ; Cursor currently off? + lda cursor ; Should cursor be off? beq @L1 ; Skip if so - lda STATUS - ora #%00000001 ; Cursor ON - sta STATUS + lsr STATUS + sec ; Cursor ON + rol STATUS @L1: lda KEYBUF bpl @L1 @@ -34,17 +36,17 @@ ldx cursor beq @L2 - ldx #$00 ; Zero high byte dec STATUS ; Clear bit zero -; We have the character, clear avail flag +; We have the character, clear the "available" flag @L2: and #$7F ; Mask out avail flag sta KEYBUF + ldx #>$0000 ldy MODEKEY cpy #FUNCTKEY bne @L3 - ora #$80 ; FUNCT pressed + ora #$80 ; FUNCT-key pressed ; Done @@ -53,16 +55,12 @@ .endproc ; ------------------------------------------------------------------------ -; Switch the cursor off, disable capslock. Code goes into the INIT segment +; Switch the cursor off. Code goes into the INIT segment ; which may be reused after it is run. .segment "INIT" initcgetc: - lda STATUS - and #%11111110 - sta STATUS - lda #$7F - sta CAPSLOCK + lsr STATUS + asl STATUS ; Clear bit zero rts - diff --git a/libsrc/atmos/crt0.s b/libsrc/atmos/crt0.s index 1588cbec0..1d919f348 100644 --- a/libsrc/atmos/crt0.s +++ b/libsrc/atmos/crt0.s @@ -2,6 +2,7 @@ ; Startup code for cc65 (Oric version) ; ; By Debrune Jérôme <jede@oric.org> and Ullrich von Bassewitz <uz@cc65.org> +; 2014-08-22, Greg King ; .export _exit @@ -39,26 +40,26 @@ .segment "STARTUP" -; Save the zero page area we're about to use +; Save the zero-page area that we're about to use. ldx #zpspace-1 L1: lda sp,x - sta zpsave,x ; Save the zero page locations we need + sta zpsave,x dex bpl L1 -; Clear the BSS data +; Clear the BSS data. jsr zerobss -; Unprotect columns 0 and 1 +; Unprotect screen columns 0 and 1. lda STATUS sta stsave and #%11011111 sta STATUS -; Save system stuff and setup the stack +; Save some system stuff; and, set up the stack. tsx stx spsave ; Save system stk ptr @@ -68,26 +69,26 @@ L1: lda sp,x lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) sta sp+1 ; Set argument stack ptr -; Call module constructors +; Call the module constructors. jsr initlib -; Push arguments and call main() +; Push the command-line arguments; and, call main(). jsr callmain -; Call module destructors. This is also the _exit entry. +; Call the module destructors. This is also the exit() entry. _exit: jsr donelib ; Run module destructors -; Restore system stuff +; Restore the system stuff. ldx spsave txs lda stsave sta STATUS -; Copy back the zero page stuff +; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x @@ -95,7 +96,7 @@ L2: lda zpsave,x dex bpl L2 -; Back to BASIC +; Back to BASIC. rts diff --git a/libsrc/atmos/joy/atmos-pase.s b/libsrc/atmos/joy/atmos-pase.s index 0c657584b..26d7c74d8 100644 --- a/libsrc/atmos/joy/atmos-pase.s +++ b/libsrc/atmos/joy/atmos-pase.s @@ -11,11 +11,13 @@ .include "joy-error.inc" .include "atmos.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _atmos_pase_joy ; Driver signature diff --git a/libsrc/atmos/mainargs.s b/libsrc/atmos/mainargs.s index 42a94da51..d6d9ed1ef 100644 --- a/libsrc/atmos/mainargs.s +++ b/libsrc/atmos/mainargs.s @@ -1,9 +1,9 @@ ; ; 2003-03-07, Ullrich von Bassewitz ; 2011-01-28, Stefan Haubenthal -; 2013-07-15, Greg King +; 2014-09-10, Greg King ; -; Setup arguments for main +; Set up arguments for main ; .constructor initmainargs, 24 @@ -40,11 +40,21 @@ L0: lda CFOUND_NAME,y ; ldx #0 L2: lda BASIC_BUF,x - beq done ; no "rem," no args. + beq done ; no "rem", no args. inx cmp #REM bne L2 - ldy #1 * 2 + +; The arguments must be copied to a safe place because BASIC's input buffer +; might be re-used by the stdin console. + + ldy #(SCREEN_XSIZE * 2 - 1) - 1 +L3: lda BASIC_BUF,y + sta args,y + dey + bpl L3 + + ldy #1 * 2 ; Point to second argv slot ; Find the next argument @@ -65,12 +75,14 @@ found: cmp #'"' ; Is the argument quoted? lda #' ' ; A space ends the argument setterm:sta term ; Set end of argument marker -; Now store a pointer to the argument into the next slot. Since the BASIC -; input buffer is located at the zero page, no calculations are necessary. +; Now, store a pointer, to the argument, into the next slot. txa ; Get low byte - add #<BASIC_BUF ; Not at page boundary + add #<args sta argv,y ; argv[y]= &arg + lda #>$0000 + adc #>args + sta argv+1,y iny iny inc __argc ; Found another arg @@ -87,8 +99,8 @@ argloop:lda BASIC_BUF,x ; A contains the terminating character. To make the argument a valid C string, ; replace the terminating character by a zero. - lda #0 - sta BASIC_BUF-1,x + lda #$00 + sta args-1,x ; Check if the maximum number of command line arguments is reached. If not, ; parse the next one. @@ -103,7 +115,6 @@ done: lda #<argv ldx #>argv sta __argv stx __argv + 1 - rts .endproc @@ -115,7 +126,8 @@ done: lda #<argv .bss term: .res 1 name: .res FNAME_LEN + 1 +args: .res SCREEN_XSIZE * 2 - 1 .data argv: .addr name - .res MAXARGS * 2 + .res MAXARGS * 2, $00 diff --git a/libsrc/atmos/read.s b/libsrc/atmos/read.s new file mode 100644 index 000000000..324ac789e --- /dev/null +++ b/libsrc/atmos/read.s @@ -0,0 +1,86 @@ +; +; 2014-08-22, Greg King +; +; int read (int fd, void* buf, unsigned count); +; +; This function is a hack! It lets us get text from the stdin console. +; + + .export _read + .constructor initstdin + + .import popax + .importzp ptr1, ptr2, ptr3 + .forceimport disable_caps + + .macpack generic + .include "atmos.inc" + +.proc _read + + sta ptr3 + stx ptr3+1 ; save count as result + eor #$FF + sta ptr2 + txa + eor #$FF + sta ptr2+1 ; Remember -count-1 + + jsr popax ; get buf + sta ptr1 + stx ptr1+1 + jsr popax ; get fd and discard + +L1: inc ptr2 + bnz L2 + inc ptr2+1 + bze L9 ; no more room in buf + +; If there are no more characters in BASIC's input buffer, then get a line from +; the console into that buffer. + +L2: ldx text_count + bpl L3 + jsr GETLINE + ldx #<(0 - 1) + +L3: inx + lda BASIC_BUF,x + bnz L4 ; (zero-terminated buffer) + ldx #<-1 + lda #$0A ; return newline char. at end of line +L4: stx text_count + ldy #0 + sta (ptr1),y + inc ptr1 + bnz L1 + inc ptr1+1 + bnz L1 ; branch always + +; No error, return count. + +L9: lda ptr3 + ldx ptr3+1 + rts + +.endproc + + +;-------------------------------------------------------------------------- +; initstdin: Reset the stdin console. + +.segment "INIT" + +initstdin: + ldx #<-1 + stx text_count + rts + + +;-------------------------------------------------------------------------- + +.bss + +text_count: + .res 1 + diff --git a/libsrc/atmos/ser/atmos-acia.s b/libsrc/atmos/ser/atmos-acia.s index c3d465d12..79fbc1bbe 100644 --- a/libsrc/atmos/ser/atmos-acia.s +++ b/libsrc/atmos/ser/atmos-acia.s @@ -28,10 +28,13 @@ .include "ser-error.inc" .include "atmos.inc" + .macpack module + + ; ------------------------------------------------------------------------ ; Header. Includes jump table - .segment "JUMPTABLE" + module_header _atmos_acia_ser ; Driver signature .byte $73, $65, $72 ; "ser" diff --git a/libsrc/atmos/systime.s b/libsrc/atmos/systime.s index d22b8c596..273e394a4 100644 --- a/libsrc/atmos/systime.s +++ b/libsrc/atmos/systime.s @@ -3,10 +3,10 @@ ; ; time_t _systime (void); ; /* Similar to time(), but: -; * - Is not ISO C -; * - Does not take the additional pointer -; * - Does not set errno when returning -1 -; */ +; ** - Is not ISO C +; ** - Does not take the additional pointer +; ** - Does not set errno when returning -1 +; */ ; .export __systime diff --git a/libsrc/atmos/tgi/atmos-228-200-3.s b/libsrc/atmos/tgi/atmos-228-200-3.s index ea7dc7ff3..ae9b0f775 100644 --- a/libsrc/atmos/tgi/atmos-228-200-3.s +++ b/libsrc/atmos/tgi/atmos-228-200-3.s @@ -2,7 +2,7 @@ ; Graphics driver for the 228x200x3 palette mode on the Atmos ; ; Stefan Haubenthal <polluks@sdf.lonestar.org> -; 2013-07-15, Greg King <gregdk@users.sf.net> +; 2014-09-10, Greg King <gregdk@users.sf.net> ; .include "zeropage.inc" @@ -12,6 +12,7 @@ .include "atmos.inc" .macpack generic + .macpack module XSIZE = 6 ; System font width YSIZE = 8 ; System font height @@ -19,7 +20,7 @@ YSIZE = 8 ; System font height ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. -.segment "JUMPTABLE" + module_header _atmos_228_200_3_tgi ; The first part of the header is a structure that has a signature, ; and defines the capabilities of the driver. @@ -274,7 +275,7 @@ mymode: sta PARAM3 lda X1 add #2 * XSIZE ; Skip screen attribute columns sta PARAM1 - lda #0 + lda #>$0000 sta PARAM1+1 sta PARAM2+1 sta PARAM3+1 @@ -290,13 +291,13 @@ GETPIXEL: sta PARAM1 lda Y1 sta PARAM2 - lda #0 + lda #>$0000 sta PARAM1+1 sta PARAM2+1 jsr POINT lda PARAM1 and #%00000001 - ldx #0 + ldx #>$0000 rts ; ------------------------------------------------------------------------ @@ -322,7 +323,7 @@ LINE: sta PARAM2+1 lda MODE sta PARAM3 - ldx #>0 + ldx #>$0000 stx PARAM3+1 jmp DRAW @@ -358,7 +359,7 @@ BAR: ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in the x -; and y directions is passend in X/Y, the text direction is passed in A. +; and y directions is passed in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; @@ -368,7 +369,7 @@ TEXTSTYLE: ; ------------------------------------------------------------------------ -; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the +; OUTTEXT: Output text at x/y = ptr1/ptr2, using the current color and the ; current text style. The text to output is given as a zero-terminated ; string with its address in ptr3. ; diff --git a/libsrc/atmos/tgi/atmos-240-200-2.s b/libsrc/atmos/tgi/atmos-240-200-2.s index 762c7c02d..943ec5389 100644 --- a/libsrc/atmos/tgi/atmos-240-200-2.s +++ b/libsrc/atmos/tgi/atmos-240-200-2.s @@ -2,7 +2,7 @@ ; Graphics driver for the 240x200x2 monochrome mode on the Atmos ; ; Stefan Haubenthal <polluks@sdf.lonestar.org> -; 2013-07-16, Greg King <gregdk@users.sf.net> +; 2014-09-10, Greg King <gregdk@users.sf.net> ; .include "zeropage.inc" @@ -12,6 +12,7 @@ .include "atmos.inc" .macpack generic + .macpack module XSIZE = 6 ; System font width YSIZE = 8 ; System font height @@ -19,7 +20,7 @@ YSIZE = 8 ; System font height ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. -.segment "JUMPTABLE" + module_header _atmos_240_200_2_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver @@ -253,7 +254,7 @@ SETPIXEL: mymode: sta PARAM3 lda X1 sta PARAM1 - lda #0 + lda #>$0000 sta PARAM1+1 sta PARAM2+1 sta PARAM3+1 @@ -269,13 +270,13 @@ GETPIXEL: sta PARAM1 lda Y1 sta PARAM2 - lda #0 + lda #>$0000 sta PARAM1+1 sta PARAM2+1 jsr POINT lda PARAM1 and #%00000001 - ldx #0 + ldx #>$0000 rts ; ------------------------------------------------------------------------ @@ -301,7 +302,7 @@ LINE: sta PARAM2+1 lda MODE sta PARAM3 - ldx #>0 + ldx #>$0000 stx PARAM3+1 jmp DRAW diff --git a/libsrc/atmos/toascii.s b/libsrc/atmos/toascii.s index 69e0cf07a..77f050021 100644 --- a/libsrc/atmos/toascii.s +++ b/libsrc/atmos/toascii.s @@ -8,7 +8,7 @@ .proc _toascii ; .X must be zero, on return. - ldx #>0 + ldx #>$0000 rts .endproc diff --git a/libsrc/c128/crt0.s b/libsrc/c128/crt0.s index cd104decd..9bfdca49f 100644 --- a/libsrc/c128/crt0.s +++ b/libsrc/c128/crt0.s @@ -22,21 +22,21 @@ Start: -; Switch to the second charset +; Switch to the second charset. lda #14 jsr BSOUT -; Before doing anything else, we have to setup our banking configuration. -; Otherwise just the lowest 16K are actually RAM. Writing through the ROM -; to the underlying RAM works, but it is bad style. +; Before doing anything else, we have to set up our banking configuration. +; Otherwise, just the lowest 16K are actually RAM. Writing through the ROM +; to the underlying RAM works; but, it is bad style. lda MMU_CR ; Get current memory configuration... pha ; ...and save it for later - lda #MMU_CFG_CC65 ; Bank0 with kernal ROM + lda #MMU_CFG_CC65 ; Bank0 with Kernal ROM sta MMU_CR -; Save the zero page locations we need +; Save the zero-page locations that we need. ldx #zpspace-1 L1: lda sp,x @@ -44,11 +44,11 @@ L1: lda sp,x dex bpl L1 -; Clear the BSS data +; Clear the BSS data. jsr zerobss -; Save system stuff and setup the stack +; Save some system stuff; and, set up the stack. pla ; Get MMU setting sta mmusave @@ -61,27 +61,27 @@ L1: lda sp,x lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) sta sp+1 ; Set argument stack ptr -; Call module constructors +; Call the module constructors. jsr initlib -; Set the bank for the file name to our execution bank. We must do this, -; *after* calling constructors, because some of them may depend on the -; original value of this register. +; Set the bank for the file name to our execution bank. We must do this +; *after* calling the constructors because some of them might depend on +; the original value of this register. lda #0 sta FNAM_BANK -; Push arguments and call main() +; Push the command-line arguments; and, call main(). jsr callmain -; Back from main (this is also the _exit entry). Run module destructors +; Back from main() [this is also the exit() entry]. Run the module destructors. _exit: pha ; Save the return code on stack jsr donelib -; Copy back the zero page stuff +; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x @@ -89,19 +89,19 @@ L2: lda zpsave,x dex bpl L2 -; Place the program return code into ST +; Place the program return code into BASIC's status variable. pla sta ST -; Reset the stack and the memory configuration +; Reset the stack and the memory configuration. ldx spsave txs ldx mmusave stx MMU_CR -; Done, return to BASIC +; Done, return to BASIC. rts diff --git a/libsrc/c128/emd/c128-georam.s b/libsrc/c128/emd/c128-georam.s index f2de80916..7511c6841 100644 --- a/libsrc/c128/emd/c128-georam.s +++ b/libsrc/c128/emd/c128-georam.s @@ -13,14 +13,14 @@ .include "em-kernel.inc" .include "em-error.inc" - .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c128_georam_emd ; Driver signature diff --git a/libsrc/c128/emd/c128-ram.s b/libsrc/c128/emd/c128-ram.s index f382e9b87..bef0a15ee 100644 --- a/libsrc/c128/emd/c128-ram.s +++ b/libsrc/c128/emd/c128-ram.s @@ -11,14 +11,14 @@ .include "em-error.inc" .include "c128.inc" - .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c128_ram_emd ; Driver signature diff --git a/libsrc/c128/emd/c128-ram2.s b/libsrc/c128/emd/c128-ram2.s index 8a0ba0fac..7d2703fa5 100644 --- a/libsrc/c128/emd/c128-ram2.s +++ b/libsrc/c128/emd/c128-ram2.s @@ -14,14 +14,14 @@ .include "em-error.inc" .include "c128.inc" - .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c128_ram2_emd ; Driver signature diff --git a/libsrc/c128/emd/c128-ramcart.s b/libsrc/c128/emd/c128-ramcart.s index 6d6a91bbe..e72d053ac 100644 --- a/libsrc/c128/emd/c128-ramcart.s +++ b/libsrc/c128/emd/c128-ramcart.s @@ -12,14 +12,14 @@ .include "em-kernel.inc" .include "em-error.inc" - .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c128_ramcart_emd ; Driver signature diff --git a/libsrc/c128/emd/c128-reu.s b/libsrc/c128/emd/c128-reu.s index 094ad1d39..a858c591e 100644 --- a/libsrc/c128/emd/c128-reu.s +++ b/libsrc/c128/emd/c128-reu.s @@ -11,14 +11,14 @@ .include "em-error.inc" .include "c128.inc" - .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c128_reu_emd ; Driver signature diff --git a/libsrc/c128/emd/c128-vdc.s b/libsrc/c128/emd/c128-vdc.s index dd28ae774..d915fdf25 100644 --- a/libsrc/c128/emd/c128-vdc.s +++ b/libsrc/c128/emd/c128-vdc.s @@ -9,14 +9,14 @@ .include "em-kernel.inc" .include "em-error.inc" - .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c128_vdc_emd ; Driver signature diff --git a/libsrc/c128/fast.s b/libsrc/c128/fast.s index 9e032f915..6c4c8c21e 100644 --- a/libsrc/c128/fast.s +++ b/libsrc/c128/fast.s @@ -3,8 +3,8 @@ ; ; void fast (void); ; /* Switch the CPU into 2MHz mode. Note: This will disable video when in -; * 40 column mode. -; */ +; ** 40 column mode. +; */ ; .export _fast diff --git a/libsrc/c128/irq.s b/libsrc/c128/irq.s index aed1f3a25..79aa8faaa 100644 --- a/libsrc/c128/irq.s +++ b/libsrc/c128/irq.s @@ -7,8 +7,6 @@ .include "c128.inc" -IRQInd = $2FD ; JMP $0000 - used as indirect IRQ vector - ; ------------------------------------------------------------------------ .segment "INIT" diff --git a/libsrc/c128/joy/c128-ptvjoy.s b/libsrc/c128/joy/c128-ptvjoy.s index d128b0ee0..6f65ce5eb 100644 --- a/libsrc/c128/joy/c128-ptvjoy.s +++ b/libsrc/c128/joy/c128-ptvjoy.s @@ -13,11 +13,13 @@ .include "c128.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table - .segment "JUMPTABLE" + module_header _c128_ptvjoy_joy ; Driver signature diff --git a/libsrc/c128/joy/c128-stdjoy.s b/libsrc/c128/joy/c128-stdjoy.s index 860dab1ae..119d3784f 100644 --- a/libsrc/c128/joy/c128-stdjoy.s +++ b/libsrc/c128/joy/c128-stdjoy.s @@ -13,12 +13,13 @@ .include "c128.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c128_stdjoy_joy ; Driver signature diff --git a/libsrc/c128/mcbdefault.s b/libsrc/c128/mcbdefault.s index cdedf4904..01c54efca 100644 --- a/libsrc/c128/mcbdefault.s +++ b/libsrc/c128/mcbdefault.s @@ -1,5 +1,5 @@ ; -; Default mouse callbacks for the C64 +; Default mouse callbacks for the C128 ; ; Ullrich von Bassewitz, 2004-03-20 ; @@ -22,37 +22,41 @@ MOUSE_SPR_NMASK = .lobyte(.not MOUSE_SPR_MASK) ; Negative mask VIC_SPR_X = (VIC_SPR0_X + 2*MOUSE_SPR) ; Sprite X register VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register -.code - ; -------------------------------------------------------------------------- ; Hide the mouse pointer. Always called with interrupts disabled. -.proc hide - +hide: lda #MOUSE_SPR_NMASK and VIC_SPR_ENA sta VIC_SPR_ENA rts -.endproc - ; -------------------------------------------------------------------------- ; Show the mouse pointer. Always called with interrupts disabled. -.proc show - +show: lda #MOUSE_SPR_MASK ora VIC_SPR_ENA sta VIC_SPR_ENA - rts + ; Fall through -.endproc +; -------------------------------------------------------------------------- +; Prepare to move the mouse pointer. Always called with interrupts disabled. + +prep: + ; Fall through + +; -------------------------------------------------------------------------- +; Draw the mouse pointer. Always called with interrupts disabled. + +draw: + rts ; -------------------------------------------------------------------------- ; Move the mouse pointer X position to the value in a/x. Always called with ; interrupts disabled. -.proc movex +movex: ; Add the X correction and set the low byte. This frees A. @@ -74,27 +78,22 @@ VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register sta VIC_SPR_HI_X rts -.endproc - ; -------------------------------------------------------------------------- ; Move the mouse pointer Y position to the value in a/x. Always called with ; interrupts disabled. -.proc movey - +movey: clc ldx PALFLAG - bne @L1 + bne @L2 adc #50 ; FIXME: Should be NTSC, is PAL value sta VIC_SPR_Y ; Set Y position rts -@L1: adc #50 ; Add PAL correction +@L2: adc #50 ; Add PAL correction sta VIC_SPR_Y ; Set Y position rts -.endproc - ; -------------------------------------------------------------------------- ; Callback structure @@ -103,7 +102,7 @@ VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register _mouse_def_callbacks: .addr hide .addr show + .addr prep + .addr draw .addr movex .addr movey - - diff --git a/libsrc/c128/mou/c128-1351.s b/libsrc/c128/mou/c128-1351.s index f2a71647c..d06e942c4 100644 --- a/libsrc/c128/mou/c128-1351.s +++ b/libsrc/c128/mou/c128-1351.s @@ -2,7 +2,9 @@ ; Driver for the 1351 proportional mouse. Parts of the code are from ; the Commodore 1351 mouse users guide. ; -; Ullrich von Bassewitz, 2003-12-29, 2009-09-26 +; 2009-09-26, Ullrich von Bassewitz +; 2014-04-26, Christian Groessler +; 2014-04-30, Greg King ; .include "zeropage.inc" @@ -10,11 +12,13 @@ .include "c128.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c128_1351_mou HEADER: @@ -25,7 +29,7 @@ HEADER: ; Library reference - .addr $0000 +libref: .addr $0000 ; Jump table @@ -50,6 +54,8 @@ HEADER: CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord @@ -81,18 +87,30 @@ YMax: .res 2 ; Y2 value of bounding box OldValue: .res 1 ; Temp for MoveCheck routine NewValue: .res 1 ; Temp for MoveCheck routine -; Default values for above variables +INIT_save: .res 1 +Buttons: .res 1 ; Button mask + +; Keyboard buffer fill level at start of interrupt + +old_key_count: .res 1 + +; original IRQ vector + +old_irq: .res 2 .rodata +; Default values for above variables +; (We use ".proc" because we want to define both a label and a scope.) + .proc DefVars .byte 0, 0 ; OldPotX/OldPotY .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin - .word SCREEN_WIDTH ; XMax - .word SCREEN_HEIGHT ; YMax + .word SCREEN_WIDTH - 1 ; XMax + .word SCREEN_HEIGHT - 1 ; YMax .endproc .code @@ -104,6 +122,14 @@ NewValue: .res 1 ; Temp for MoveCheck routine INSTALL: +; Disable the BASIC interpreter's interrupt-driven sprite-motion code. +; That allows direct access to the VIC-IIe's sprite registers. + + lda INIT_STATUS + sta INIT_save + lda #%11000000 + sta INIT_STATUS + ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @@ -124,19 +150,72 @@ INSTALL: lda YPos ldx YPos+1 jsr CMOVEY + +; Initialize our IRQ magic + + ; remember ROM IRQ continuation address + lda IRQInd+2 + sta old_irq+1 + lda IRQInd+1 + sta old_irq + + lda libref + sta ptr3 + lda libref+1 + sta ptr3+1 + + ; set ROM IRQ continuation address to point to the provided routine + ldy #2 + lda (ptr3),y + sta IRQInd+1 + iny + lda (ptr3),y + sta IRQInd+2 + + ; set address of our IRQ callback routine + ; since it's called via "rts" we have to use "address-1" + iny + lda #<(callback-1) + sta (ptr3),y + iny + lda #>(callback-1) + sta (ptr3),y + iny + + ; set ROM entry point vector + ; since it's called via "rts" we have to decrement it by one + lda old_irq + sec + sbc #1 + sta (ptr3),y + iny + lda old_irq+1 + sbc #0 + sta (ptr3),y cli ; Done, return zero (= MOUSE_ERR_OK) ldx #$00 txa - rts ; Run into UNINSTALL instead + rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). -UNINSTALL = HIDE ; Hide cursor on exit +UNINSTALL: + lda old_irq + sei + sta IRQInd+1 + lda old_irq+1 + sta IRQInd+2 + ;cli ; This will be done at end of HIDE + + jsr HIDE ; Hide cursor on exit + lda INIT_save + sta INIT_STATUS + rts ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages @@ -232,14 +311,8 @@ MOVE: sei ; No interrupts ; BUTTONS: Return the button mask in a/x. BUTTONS: - lda #$7F - sei - sta CIA1_PRA - lda CIA1_PRB ; Read joystick #0 - cli - ldx #0 - and #$1F - eor #$1F + lda Buttons + ldx #$00 rts ;---------------------------------------------------------------------------- @@ -278,7 +351,7 @@ INFO: jsr POS ; Fill in the button state - jsr BUTTONS ; Will not touch ptr1 + lda Buttons ldy #MOUSE_INFO::BUTTONS sta (ptr1),y @@ -290,7 +363,7 @@ INFO: jsr POS ; Must return an error code in a/x. ; -IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now +IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now ldx #>MOUSE_ERR_INV_IOCTL rts @@ -301,7 +374,17 @@ IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ; MUST return carry clear. ; -IRQ: lda SID_ADConv1 ; Get mouse X movement +IRQ: jsr CPREP + lda KEY_COUNT + sta old_key_count + lda #$7F + sta CIA1_PRA + lda CIA1_PRB ; Read joystick #0 + and #$1F + eor #$1F ; Make all bits active high + sta Buttons + + lda SID_ADConv1 ; Get mouse X movement ldy OldPotX jsr MoveCheck ; Calculate movement vector sty OldPotX @@ -388,8 +471,9 @@ IRQ: lda SID_ADConv1 ; Get mouse X movement ; Done - clc ; Interrupt not "handled" -@SkipY: rts +@SkipY: jsr CDRAW + clc ; Interrupt not "handled" + rts ; -------------------------------------------------------------------------- ; @@ -430,3 +514,5 @@ MoveCheck: clc rts +.define OLD_BUTTONS Buttons ; tells callback.inc where the old port status is stored +.include "callback.inc" diff --git a/libsrc/c128/mou/c128-inkwell.s b/libsrc/c128/mou/c128-inkwell.s index dc3469aac..45d42f2db 100644 --- a/libsrc/c128/mou/c128-inkwell.s +++ b/libsrc/c128/mou/c128-inkwell.s @@ -1,7 +1,8 @@ ; ; Driver for the Inkwell Systems 170-C and 184-C lightpens. ; -; 2013-07-01, Greg King +; 2014-04-26, Christian Groessler +; 2014-09-10, Greg King ; .include "zeropage.inc" @@ -9,11 +10,13 @@ .include "c128.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table. -.segment "JUMPTABLE" + module_header _c128_inkwell_mou HEADER: @@ -24,7 +27,7 @@ HEADER: ; Library reference -LIBREF: .addr $0000 +libref: .addr $0000 ; Jump table @@ -49,6 +52,8 @@ LIBREF: .addr $0000 CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X co-ord. CMOVEY: jmp $0000 ; Move the cursor to Y co-ord. @@ -100,11 +105,21 @@ OldPenY: .res 1 INIT_save: .res 1 +; Keyboard buffer fill level at start of interrupt + +old_key_count: .res 1 + +; Original IRQ vector + +old_irq: .res 2 + .data ; Default Inkwell calibration. ; The first number is the width of the left border; ; the second number is the actual calibration value. +; See a comment below (at "Calculate the new X co-ordinate") +; for the reason for the third number. XOffset: .byte (24 + 24) / 2 ; x-offset @@ -129,7 +144,7 @@ INSTALL: lda #%11000000 sta INIT_STATUS -; Initiate variables. Just copy the default stuff over. +; Initiate some variables. Just copy the default stuff over. ldx #.sizeof (DefVars) - 1 @L0: lda DefVars,x @@ -142,18 +157,57 @@ INSTALL: stx OldPenX sty OldPenY +; Initiate our IRQ magic. + + ; Remember the ROM IRQ continuation address. + ldx IRQInd+2 + lda IRQInd+1 + stx old_irq+1 + sta old_irq + + lda libref + ldx libref+1 + sta ptr3 ; Point to mouse_adjuster + stx ptr3+1 + + ; Set the ROM IRQ continuation address to point to the provided routine. + ldy #2 + lda (ptr3),y + iny + sei + sta IRQInd+1 + lda (ptr3),y + sta IRQInd+2 + + ; Set the address of our IRQ callback routine. + ; Because it's called via "rts", we must use "address-1". + iny + lda #<(callback-1) + sta (ptr3),y + iny + lda #>(callback-1) + sta (ptr3),y + + ; Set the ROM entry-point vector. + ; Because it's called via "rts", we must decrement it by one. + iny + lda old_irq + sub #<$0001 + sta (ptr3),y + iny + lda old_irq+1 + sbc #>$0001 + sta (ptr3),y + cli + ; Call a calibration function through the library-reference. - lda LIBREF - ldx LIBREF+1 - sta ptr1 ; Point to mouse_adjuster - stx ptr1+1 ldy #1 - lda (ptr1),y + lda (ptr3),y bze @L1 ; Don't call pointer if it's NULL sta Calibrate+2 ; Point to function dey - lda (ptr1),y + lda (ptr3),y sta Calibrate+1 lda #<XOffset ; Function will set this variable ldx #>XOffset @@ -185,6 +239,13 @@ INSTALL: ; No return code required (the driver is removed from memory on return). UNINSTALL: + lda old_irq + ldx old_irq+1 + sei + sta IRQInd+1 + stx IRQInd+2 + ;cli ; This will be done at end of HIDE + jsr HIDE ; Hide cursor on exit lda INIT_save sta INIT_STATUS @@ -275,7 +336,7 @@ MOVE: sei ; No interrupts BUTTONS: lda Buttons - ldx #>0 + ldx #>$0000 ; Make the lightpen buttons look like a 1351 mouse. @@ -343,7 +404,9 @@ IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now ; MUST return carry clear. ; -IRQ: +IRQ: jsr CPREP + lda KEY_COUNT + sta old_key_count ; Record the state of the buttons. ; Try to avoid crosstalk between the keyboard and the lightpen. @@ -351,18 +414,16 @@ IRQ: ldy #%00000000 ; Set ports A and B to input sty CIA1_DDRB sty CIA1_DDRA ; Keyboard won't look like buttons - lda CIA1_PRB ; Read Control-Port 1 + ;lda #%01111111 ; (Keyboard scan leaves this in port A) + ;sta CIA1_PRA + lda CIA1_PRB ; Read Control Port 1 dec CIA1_DDRA ; Set port A back to output eor #%11111111 ; Bit goes up when button goes down sta Buttons - bze @L0 - lda #%11101111 ; (Don't change bit that feeds VIC-II) - sta CIA1_DDRB ; Buttons won't look like keyboard - sty CIA1_PRB ; Set "all keys pushed" ; Read the VIC-II lightpen registers. -@L0: lda VIC_LPEN_Y + lda VIC_LPEN_Y cmp OldPenY ; Skip processing if nothing has changed. @@ -375,7 +436,7 @@ IRQ: sub #50 tay ; Remember low byte - ldx #>0 + ldx #>$0000 ; Limit the Y co-ordinate to the bounding box. @@ -416,7 +477,7 @@ IRQ: asl a tay ; Remember low byte - lda #>0 + lda #>$0000 rol a tax ; Remember high byte @@ -441,7 +502,8 @@ IRQ: ; Done -@SkipX: clc ; Interrupt not "handled" +@SkipX: jsr CDRAW + clc ; Interrupt not "handled" rts ; Move the lightpen pointer to the new Y pos. @@ -455,3 +517,6 @@ MoveY: sta YPos MoveX: sta XPos stx XPos+1 jmp CMOVEX + +.define OLD_BUTTONS Buttons ; Tells callback.inc where the old port status is stored +.include "callback.inc" diff --git a/libsrc/c128/mou/c128-joy.s b/libsrc/c128/mou/c128-joy.s index 8c3bd779d..7718b89b7 100644 --- a/libsrc/c128/mou/c128-joy.s +++ b/libsrc/c128/mou/c128-joy.s @@ -1,7 +1,9 @@ ; ; Driver for a "joystick mouse". ; -; Ullrich von Bassewitz, 2004-04-05, 2009-09-26 +; 2009-09-26, Ullrich von Bassewitz +; 2014-04-26, Christian Groessler +; 2014-05-01, Greg King ; .include "zeropage.inc" @@ -9,11 +11,13 @@ .include "c128.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c128_joy_mou HEADER: @@ -24,7 +28,7 @@ HEADER: ; Library reference - .addr $0000 +libref: .addr $0000 ; Jump table @@ -49,6 +53,8 @@ HEADER: CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord @@ -83,21 +89,28 @@ XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button mask -; Temporary value used in the int handler +INIT_save: .res 1 -Temp: .res 1 +; Keyboard buffer fill level at start of interrupt -; Default values for above variables +old_key_count: .res 1 + +; original IRQ vector + +old_irq: .res 2 .rodata +; Default values for above variables +; (We use ".proc" because we want to define both a label and a scope.) + .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin - .word SCREEN_WIDTH ; XMax - .word SCREEN_HEIGHT ; YMax + .word SCREEN_WIDTH - 1 ; XMax + .word SCREEN_HEIGHT - 1 ; YMax .byte 0 ; Buttons .endproc @@ -110,6 +123,14 @@ Temp: .res 1 INSTALL: +; Disable the BASIC interpreter's interrupt-driven sprite-motion code. +; That allows direct access to the VIC-IIe's sprite registers. + + lda INIT_STATUS + sta INIT_save + lda #%11000000 + sta INIT_STATUS + ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @@ -130,6 +151,48 @@ INSTALL: lda YPos ldx YPos+1 jsr CMOVEY + +; Initialize our IRQ magic + + ; remember ROM IRQ continuation address + lda IRQInd+2 + sta old_irq+1 + lda IRQInd+1 + sta old_irq + + lda libref + sta ptr3 + lda libref+1 + sta ptr3+1 + + ; set ROM IRQ continuation address to point to the provided routine + ldy #2 + lda (ptr3),y + sta IRQInd+1 + iny + lda (ptr3),y + sta IRQInd+2 + + ; set address of our IRQ callback routine + ; since it's called via "rts" we have to use "address-1" + iny + lda #<(callback-1) + sta (ptr3),y + iny + lda #>(callback-1) + sta (ptr3),y + iny + + ; set ROM entry point vector + ; since it's called via "rts" we have to decrement it by one + lda old_irq + sec + sbc #1 + sta (ptr3),y + iny + lda old_irq+1 + sbc #0 + sta (ptr3),y cli ; Done, return zero (= MOUSE_ERR_OK) @@ -142,7 +205,18 @@ INSTALL: ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). -UNINSTALL = HIDE ; Hide cursor on exit +UNINSTALL: + lda old_irq + sei + sta IRQInd+1 + lda old_irq+1 + sta IRQInd+2 + ;cli ; This will be done at end of HIDE + + jsr HIDE ; Hide cursor on exit + lda INIT_save + sta INIT_STATUS + rts ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages @@ -240,6 +314,7 @@ MOVE: sei ; No interrupts BUTTONS: lda Buttons ldx #$00 + and #MOUSE_BTN_LEFT ; Left button -- same as JOY::FIRE rts ;---------------------------------------------------------------------------- @@ -278,7 +353,7 @@ INFO: jsr POS ; Fill in the button state - lda Buttons + jsr BUTTONS ldy #MOUSE_INFO::BUTTONS sta (ptr1),y @@ -290,7 +365,7 @@ INFO: jsr POS ; Must return an error code in a/x. ; -IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now +IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls for now ldx #>MOUSE_ERR_INV_IOCTL rts @@ -301,24 +376,18 @@ IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ; MUST return carry clear. ; -IRQ: lda #$7F +IRQ: jsr CPREP + lda KEY_COUNT + sta old_key_count + lda #$7F sta CIA1_PRA lda CIA1_PRB ; Read joystick #0 and #$1F eor #$1F ; Make all bits active high - sta Temp - -; Check for a pressed button and place the result into Buttons - - ldx #$00 ; Assume no button pressed - and #JOY::FIRE ; Check fire button - beq @L0 ; Jump if not pressed - ldx #MOUSE_BTN_LEFT ; Left (only) button is pressed -@L0: stx Buttons + sta Buttons ; Check left/right - lda Temp ; Read joystick #0 and #(JOY::LEFT | JOY::RIGHT) beq @SkipX ; @@ -366,7 +435,7 @@ IRQ: lda #$7F ; Calculate the Y movement vector -@SkipX: lda Temp ; Read joystick #0 +@SkipX: lda Buttons ; Read joystick #0 and #(JOY::UP | JOY::DOWN) ; Check up/down beq @SkipY ; @@ -414,6 +483,9 @@ IRQ: lda #$7F ; Done -@SkipY: clc ; Interrupt not "handled" +@SkipY: jsr CDRAW + clc ; Interrupt not "handled" rts +.define OLD_BUTTONS Buttons ; tells callback.inc where the old port status is stored +.include "callback.inc" diff --git a/libsrc/c128/mou/c128-pot.s b/libsrc/c128/mou/c128-pot.s index ab6922896..f61f88d5d 100644 --- a/libsrc/c128/mou/c128-pot.s +++ b/libsrc/c128/mou/c128-pot.s @@ -1,8 +1,10 @@ ; -; Driver for a potentiometer "mouse" e.g. Koala Pad +; Driver for a potentiometer "mouse", e.g. Koala Pad ; -; Ullrich von Bassewitz, 2004-03-29, 2009-09-26 -; Stefan Haubenthal, 2006-08-20 +; 2006-08-20, Stefan Haubenthal +; 2009-09-26, Ullrich von Bassewitz +; 2014-04-26, Christian Groessler +; 2014-05-05, Greg King ; .include "zeropage.inc" @@ -10,11 +12,13 @@ .include "c128.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c128_pot_mou HEADER: @@ -25,7 +29,7 @@ HEADER: ; Library reference - .addr $0000 +libref: .addr $0000 ; Jump table @@ -42,10 +46,16 @@ HEADER: .addr IOCTL .addr IRQ +; Mouse driver flags + + .byte MOUSE_FLAG_LATE_IRQ + ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord @@ -80,21 +90,28 @@ XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button mask -; Temporary value used in the int handler +INIT_save: .res 1 -Temp: .res 1 +; Keyboard buffer fill level at start of interrupt -; Default values for above variables +old_key_count: .res 1 + +; Original IRQ vector + +old_irq: .res 2 .rodata +; Default values for above variables +; (We use ".proc" because we want to define both a label and a scope.) + .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin - .word SCREEN_WIDTH ; XMax - .word SCREEN_HEIGHT ; YMax + .word SCREEN_WIDTH - 1 ; XMax + .word SCREEN_HEIGHT - 1 ; YMax .byte 0 ; Buttons .endproc @@ -107,6 +124,14 @@ Temp: .res 1 INSTALL: +; Disable the BASIC interpreter's interrupt-driven sprite-motion code. +; That allows direct access to the VIC-IIe's sprite registers. + + lda INIT_STATUS + sta INIT_save + lda #%11000000 + sta INIT_STATUS + ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @@ -127,6 +152,47 @@ INSTALL: lda YPos ldx YPos+1 jsr CMOVEY + +; Initiate our IRQ magic. + + ; Remember the ROM IRQ continuation address. + ldx IRQInd+2 + lda IRQInd+1 + stx old_irq+1 + sta old_irq + + lda libref + ldx libref+1 + sta ptr3 + stx ptr3+1 + + ; Set the ROM IRQ continuation address to point to the provided routine. + ldy #2 + lda (ptr3),y + sta IRQInd+1 + iny + lda (ptr3),y + sta IRQInd+2 + + ; Set the address of our IRQ callback routine. + ; Because it's called via "rts", we must use "address-1". + iny + lda #<(callback-1) + sta (ptr3),y + iny + lda #>(callback-1) + sta (ptr3),y + + ; Set the ROM entry-point vector. + ; Because it's called via "rts", we must decrement it by one. + iny + lda old_irq + sub #<1 + sta (ptr3),y + iny + lda old_irq+1 + sbc #>1 + sta (ptr3),y cli ; Done, return zero (= MOUSE_ERR_OK) @@ -139,7 +205,18 @@ INSTALL: ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). -UNINSTALL = HIDE ; Hide cursor on exit +UNINSTALL: + lda old_irq + ldx old_irq+1 + sei + sta IRQInd+1 + stx IRQInd+2 + ;cli ; This will be done at end of HIDE + + jsr HIDE ; Hide cursor on exit + lda INIT_save + sta INIT_STATUS + rts ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages @@ -237,6 +314,15 @@ MOVE: sei ; No interrupts BUTTONS: lda Buttons ldx #$00 + +; Make the buttons look like a 1351 mouse. + + and #JOY::LEFT | JOY::RIGHT + lsr a + lsr a + ;clc ; ("lsr" shifted zero into carry flag) + adc #%00001110 ; Shift bit 1 over to bit 4 + and #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT rts ;---------------------------------------------------------------------------- @@ -275,7 +361,7 @@ INFO: jsr POS ; Fill in the button state - lda Buttons + jsr BUTTONS ldy #MOUSE_INFO::BUTTONS sta (ptr1),y @@ -287,7 +373,7 @@ INFO: jsr POS ; Must return an error code in a/x. ; -IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now +IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls for now ldx #>MOUSE_ERR_INV_IOCTL rts @@ -296,22 +382,18 @@ IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ; (so be careful). ; -IRQ: lda #$7F +IRQ: jsr CPREP + lda KEY_COUNT + sta old_key_count + lda #$7F sta CIA1_PRA lda CIA1_PRB ; Read port #1 - and #%00001100 - eor #%00001100 ; Make all bits active high - asl + eor #%11111111 ; Make all bits active high sta Buttons - lsr - lsr - lsr - and #%00000001 - ora Buttons - sta Buttons - ldx #%01000000 + + ldx #%01000000 ; Read port 1 paddles stx CIA1_PRA - ldy #0 + ldy #<256 : dey bne :- ldx SID_ADConv1 @@ -391,4 +473,10 @@ IRQ: lda #$7F ; Move the mouse pointer to the new X pos tya - jmp CMOVEY + jsr CMOVEY + jsr CDRAW + clc ; Interrupt not "handled" + rts + +.define OLD_BUTTONS Buttons ; Tells callback.inc where the old port status is stored +.include "callback.inc" diff --git a/libsrc/c128/mou/callback.inc b/libsrc/c128/mou/callback.inc new file mode 100644 index 000000000..9f1d749a7 --- /dev/null +++ b/libsrc/c128/mou/callback.inc @@ -0,0 +1,29 @@ +; +; Callback routine called from the IRQ handler after the ROM IRQ handler +; had been run. +; +; Christian Groessler, 24.04.2014 +; +; Check if there was button/joystick activity before and/or after the ROM handler. +; If there was activity, discard the key presses since they are most +; probably "phantom" key presses. + +callback: + ldx old_key_count + cpx KEY_COUNT + beq @nokey + + lda OLD_BUTTONS ; keypress before? + bne @discard_key ; yes, discard key + + lda #$7F + sta CIA1_PRA + lda CIA1_PRB ; Read joystick #0 + and #$1F + eor #$1F ; keypress after + beq @nokey ; no, probably a real key press + +@discard_key: + stx KEY_COUNT ; set old keyboard buffer fill level + +@nokey: rts diff --git a/libsrc/c128/mouseref.s b/libsrc/c128/mouseref.s index 90aeedf3a..243eda804 100644 --- a/libsrc/c128/mouseref.s +++ b/libsrc/c128/mouseref.s @@ -1,8 +1,14 @@ ; ; Pointer for library references by device drivers. ; -; 2013-07-25, Greg King +; Helper-routines for the interrupt handler that rejects bogus keypresses +; that are caused by mouse-like devices. ; +; 2013-07-25, Greg King +; 2014-04-26, Christian Groessler +; + + .include "c128.inc" .export mouse_libref, _pen_adjuster @@ -21,3 +27,77 @@ mouse_libref: ; generic label for mouse-kernel ; _pen_adjuster: .addr $0000 + + .addr IRQStub2 +callback: ; callback into mouse driver after ROM IRQ handler has been run + .addr $0000 ; (filled in by mouse driver) +jmp_rom_hdlr: ; original ROM indirect IRQ handler address + .addr $0000 ; (filled in by mouse driver) + + +.segment "LOWCODE" + +; Called from irq.s when it thinks it chains to the original handler. +; ROM is banked in again. In order to call the callback we have to +; bank it out one more time. + +IRQStub2: + +; Call ROM handler and prepare stack so that it will return to us. + + ; setup fake IRQ stack frame which will return to "IRQCont" + lda #>@IRQCont + pha + lda #<@IRQCont + pha + php + + ; mimic the contents saved on the stack by the ROM IRQ entry handler + pha ; A + pha ; X + pha ; Y + lda #MMU_CFG_CC65 ; MMU configuration which will be active after the ROM handler returns + pha + + ; map out ROM + ldy MMU_CR + sta MMU_CR + + ; push address of ROM handler on stack and jump to it + lda jmp_rom_hdlr+1 + pha + lda jmp_rom_hdlr + pha + + sty MMU_CR ; map in ROM + rts ; jump to ROM handler + + ; our MMU configuration byte we pushed on the stack before (MMU_CFG_CC65) is now active + +@IRQCont: + + ; call mouse driver callback routine + lda #>(@IRQCont2-1) + pha + lda #<(@IRQCont2-1) + pha + lda callback+1 + pha + lda callback + pha + rts ; jump to callback routine + +@IRQCont2: + + ; return from interrupt + ; We could just jump to $FF33, but since I don't know whether this address is valid in all + ; ROM versions, duplicate that code here. + + pla + sta MMU_CR ; MMU configuration register + pla + tay + pla + tax + pla + rti diff --git a/libsrc/c128/ser/c128-swlink.s b/libsrc/c128/ser/c128-swlink.s index 02336d688..98411d4f8 100644 --- a/libsrc/c128/ser/c128-swlink.s +++ b/libsrc/c128/ser/c128-swlink.s @@ -26,11 +26,13 @@ .include "ser-error.inc" .include "c128.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c128_swlink_ser ; Driver signature diff --git a/libsrc/c128/systime.s b/libsrc/c128/systime.s index bea2164f5..0a7f8f367 100644 --- a/libsrc/c128/systime.s +++ b/libsrc/c128/systime.s @@ -3,10 +3,10 @@ ; ; time_t _systime (void); ; /* Similar to time(), but: -; * - Is not ISO C -; * - Does not take the additional pointer -; * - Does not set errno when returning -1 -; */ +; ** - Is not ISO C +; ** - Does not take the additional pointer +; ** - Does not set errno when returning -1 +; */ ; .include "time.inc" diff --git a/libsrc/c128/tgi/c128-vdc.s b/libsrc/c128/tgi/c128-vdc.s index 394f4080a..5100f7f7d 100644 --- a/libsrc/c128/tgi/c128-vdc.s +++ b/libsrc/c128/tgi/c128-vdc.s @@ -25,8 +25,9 @@ .include "tgi-kernel.inc" .include "tgi-error.inc" - .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Constants @@ -48,7 +49,7 @@ VDC_DATA = 31 ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. -.segment "JUMPTABLE" + module_header _c128_vdc_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver diff --git a/libsrc/c128/tgi/c128-vdc2.s b/libsrc/c128/tgi/c128-vdc2.s index 2e1d26ae5..a7238e877 100644 --- a/libsrc/c128/tgi/c128-vdc2.s +++ b/libsrc/c128/tgi/c128-vdc2.s @@ -26,8 +26,9 @@ .include "tgi-kernel.inc" .include "tgi-error.inc" - .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Constants @@ -49,7 +50,7 @@ VDC_DATA = 31 ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. -.segment "JUMPTABLE" + module_header _c128_vdc2_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver diff --git a/libsrc/c16/crt0.s b/libsrc/c16/crt0.s index 2875aff49..0180ad671 100644 --- a/libsrc/c16/crt0.s +++ b/libsrc/c16/crt0.s @@ -1,8 +1,8 @@ ; ; Startup code for cc65 (C16 version) ; -; Note: The C16 is actually the Plus/4 with just 16KB of memory. So many -; things are similar here, and we even use the plus4.inc include file. +; Note: The C16 is actually the Plus/4 with just 16KB of memory. So, many +; things are similar here; and, we even use the plus4.inc include file. ; .export _exit @@ -22,7 +22,7 @@ Start: -; Save the zero page locations we need +; Save the zero-page locations that we need. ldx #zpspace-1 L1: lda sp,x @@ -30,16 +30,16 @@ L1: lda sp,x dex bpl L1 -; Switch to second charset +; Switch to the second charset. lda #14 jsr BSOUT -; Clear the BSS data +; Clear the BSS data. jsr zerobss -; Save system stuff and setup the stack +; Save some system stuff; and, set up the stack. tsx stx spsave ; save system stk ptr @@ -53,20 +53,20 @@ L1: lda sp,x MemOk: stx sp sty sp+1 ; set argument stack ptr -; Call module constructors +; Call the module constructors. jsr initlib -; Push arguments and call main() +; Push the command-line arguments; and, call main(). jsr callmain -; Call module destructors. This is also the _exit entry. +; Call the module destructors. This is also the exit() entry. _exit: pha ; Save the return code on stack jsr donelib ; Run module destructors -; Copy back the zero page stuff +; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x @@ -74,17 +74,17 @@ L2: lda zpsave,x dex bpl L2 -; Store the return code into ST +; Store the return code into BASIC's status variable. pla sta ST -; Restore the stack pointer +; Restore the stack pointer. ldx spsave txs -; Back to BASIC +; Back to BASIC. rts diff --git a/libsrc/c16/emd/c16-ram.s b/libsrc/c16/emd/c16-ram.s index 1d7d41ae0..a8083aca4 100644 --- a/libsrc/c16/emd/c16-ram.s +++ b/libsrc/c16/emd/c16-ram.s @@ -12,12 +12,13 @@ .include "plus4.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c16_ram_emd ; Driver signature diff --git a/libsrc/c16/joy/c16-stdjoy.s b/libsrc/c16/joy/c16-stdjoy.s index 54ba47e19..0b99d93a3 100644 --- a/libsrc/c16/joy/c16-stdjoy.s +++ b/libsrc/c16/joy/c16-stdjoy.s @@ -5,5 +5,6 @@ ; Ullrich von Bassewitz, 2002-12-21 ; - .include "../../plus4/joy/plus4-stdjoy.s" + .define MODULE_LABEL _c16_stdjoy_joy + .include "../../plus4/joy/plus4-stdjoy.s" diff --git a/libsrc/c16/systime.s b/libsrc/c16/systime.s index d22b8c596..273e394a4 100644 --- a/libsrc/c16/systime.s +++ b/libsrc/c16/systime.s @@ -3,10 +3,10 @@ ; ; time_t _systime (void); ; /* Similar to time(), but: -; * - Is not ISO C -; * - Does not take the additional pointer -; * - Does not set errno when returning -1 -; */ +; ** - Is not ISO C +; ** - Does not take the additional pointer +; ** - Does not set errno when returning -1 +; */ ; .export __systime diff --git a/libsrc/c64/crt0.s b/libsrc/c64/crt0.s index ab44e9033..24fe4376b 100644 --- a/libsrc/c64/crt0.s +++ b/libsrc/c64/crt0.s @@ -23,7 +23,7 @@ Start: -; Save the zero page locations we need +; Save the zero-page locations that we need. ldx #zpspace-1 L1: lda sp,x @@ -31,24 +31,24 @@ L1: lda sp,x dex bpl L1 -; Switch to second charset +; Switch to the second charset. lda #14 jsr BSOUT -; Switch off the BASIC ROM +; Switch off the BASIC ROM. lda $01 pha ; Remember the value and #$F8 - ora #$06 ; Enable kernal+I/O, disable basic + ora #$06 ; Enable Kernal+I/O, disable BASIC sta $01 -; Clear the BSS data +; Clear the BSS data. jsr zerobss -; Save system settings and setup the stack +; Save some system settings; and, set up the stack. pla sta mmusave ; Save the memory configuration @@ -61,20 +61,20 @@ L1: lda sp,x lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) sta sp+1 ; Set argument stack ptr -; Call module constructors +; Call the module constructors. jsr initlib -; Push arguments and call main +; Push the command-line arguments; and, call main(). jsr callmain -; Back from main (This is also the _exit entry). Run module destructors +; Back from main() [this is also the exit() entry]. Run the module destructors. _exit: pha ; Save the return code on stack jsr donelib -; Copy back the zero page stuff +; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x @@ -82,19 +82,19 @@ L2: lda zpsave,x dex bpl L2 -; Place the program return code into ST +; Place the program return code into BASIC's status variable. pla sta ST -; Restore system stuff +; Restore the system stuff. ldx spsave txs ; Restore stack pointer ldx mmusave stx $01 ; Restore memory configuration -; Back to basic +; Back to BASIC. rts diff --git a/libsrc/c64/emd/c64-c256k.s b/libsrc/c64/emd/c64-c256k.s index 8508b8b56..79706e8fb 100644 --- a/libsrc/c64/emd/c64-c256k.s +++ b/libsrc/c64/emd/c64-c256k.s @@ -10,12 +10,13 @@ .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_c256k_emd ; Driver signature diff --git a/libsrc/c64/emd/c64-dqbb.s b/libsrc/c64/emd/c64-dqbb.s index c06a83daf..986c5939d 100644 --- a/libsrc/c64/emd/c64-dqbb.s +++ b/libsrc/c64/emd/c64-dqbb.s @@ -10,12 +10,13 @@ .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_dqbb_emd ; Driver signature diff --git a/libsrc/c64/emd/c64-georam.s b/libsrc/c64/emd/c64-georam.s index f2de80916..97f1a7cc4 100644 --- a/libsrc/c64/emd/c64-georam.s +++ b/libsrc/c64/emd/c64-georam.s @@ -15,12 +15,13 @@ .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_georam_emd ; Driver signature diff --git a/libsrc/c64/emd/c64-isepic.s b/libsrc/c64/emd/c64-isepic.s index 67a33ecf6..3764443e2 100644 --- a/libsrc/c64/emd/c64-isepic.s +++ b/libsrc/c64/emd/c64-isepic.s @@ -10,12 +10,13 @@ .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_isepic_emd ; Driver signature diff --git a/libsrc/c64/emd/c64-ram.s b/libsrc/c64/emd/c64-ram.s index b73ccc547..f8a4a1819 100644 --- a/libsrc/c64/emd/c64-ram.s +++ b/libsrc/c64/emd/c64-ram.s @@ -12,12 +12,13 @@ .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_ram_emd ; Driver signature diff --git a/libsrc/c64/emd/c64-ramcart.s b/libsrc/c64/emd/c64-ramcart.s index d424024c7..8998bb6d6 100644 --- a/libsrc/c64/emd/c64-ramcart.s +++ b/libsrc/c64/emd/c64-ramcart.s @@ -14,12 +14,13 @@ .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_ramcart_emd ; Driver signature diff --git a/libsrc/c64/emd/c64-reu.s b/libsrc/c64/emd/c64-reu.s index c397a739d..0779505be 100644 --- a/libsrc/c64/emd/c64-reu.s +++ b/libsrc/c64/emd/c64-reu.s @@ -12,12 +12,13 @@ .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_reu_emd ; Driver signature diff --git a/libsrc/c64/emd/c64-vdc.s b/libsrc/c64/emd/c64-vdc.s index cd09d33f4..2448f09d4 100644 --- a/libsrc/c64/emd/c64-vdc.s +++ b/libsrc/c64/emd/c64-vdc.s @@ -15,12 +15,13 @@ .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_vdc_emd ; Driver signature diff --git a/libsrc/c64/emd/dtv-himem.s b/libsrc/c64/emd/dtv-himem.s index 62bc2007b..6dde874f7 100644 --- a/libsrc/c64/emd/dtv-himem.s +++ b/libsrc/c64/emd/dtv-himem.s @@ -14,12 +14,13 @@ .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _dtv_himem_emd ; Driver signature diff --git a/libsrc/c64/joy/c64-hitjoy.s b/libsrc/c64/joy/c64-hitjoy.s index 28495ee11..a798100a7 100644 --- a/libsrc/c64/joy/c64-hitjoy.s +++ b/libsrc/c64/joy/c64-hitjoy.s @@ -12,11 +12,13 @@ .include "c64.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table - .segment "JUMPTABLE" + module_header _c64_hitjoy_joy ; Driver signature diff --git a/libsrc/c64/joy/c64-numpad.s b/libsrc/c64/joy/c64-numpad.s index 6eeebcc74..5f6464215 100644 --- a/libsrc/c64/joy/c64-numpad.s +++ b/libsrc/c64/joy/c64-numpad.s @@ -13,12 +13,13 @@ .include "c64.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_numpad_joy ; Driver signature diff --git a/libsrc/c64/joy/c64-ptvjoy.s b/libsrc/c64/joy/c64-ptvjoy.s index bb1ba0982..31850488c 100644 --- a/libsrc/c64/joy/c64-ptvjoy.s +++ b/libsrc/c64/joy/c64-ptvjoy.s @@ -12,11 +12,13 @@ .include "c64.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table - .segment "JUMPTABLE" + module_header _c64_ptvjoy_joy ; Driver signature diff --git a/libsrc/c64/joy/c64-stdjoy.s b/libsrc/c64/joy/c64-stdjoy.s index 18722032a..2932c77fd 100644 --- a/libsrc/c64/joy/c64-stdjoy.s +++ b/libsrc/c64/joy/c64-stdjoy.s @@ -12,12 +12,13 @@ .include "c64.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_stdjoy_joy ; Driver signature diff --git a/libsrc/c64/mcbdefault.s b/libsrc/c64/mcbdefault.s index 96c7c9ef4..ffeed45b3 100644 --- a/libsrc/c64/mcbdefault.s +++ b/libsrc/c64/mcbdefault.s @@ -22,37 +22,41 @@ MOUSE_SPR_NMASK = .lobyte(.not MOUSE_SPR_MASK) ; Negative mask VIC_SPR_X = (VIC_SPR0_X + 2*MOUSE_SPR) ; Sprite X register VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register -.code - ; -------------------------------------------------------------------------- ; Hide the mouse pointer. Always called with interrupts disabled. -.proc hide - +hide: lda #MOUSE_SPR_NMASK and VIC_SPR_ENA sta VIC_SPR_ENA rts -.endproc - ; -------------------------------------------------------------------------- ; Show the mouse pointer. Always called with interrupts disabled. -.proc show - +show: lda #MOUSE_SPR_MASK ora VIC_SPR_ENA sta VIC_SPR_ENA - rts + ; Fall through -.endproc +; -------------------------------------------------------------------------- +; Prepare to move the mouse pointer. Always called with interrupts disabled. + +prep: + ; Fall through + +; -------------------------------------------------------------------------- +; Draw the mouse pointer. Always called with interrupts disabled. + +draw: + rts ; -------------------------------------------------------------------------- ; Move the mouse pointer X position to the value in a/x. Always called with ; interrupts disabled. -.proc movex +movex: ; Add the X correction and set the low byte. This frees A. @@ -74,20 +78,15 @@ VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register sta VIC_SPR_HI_X rts -.endproc - ; -------------------------------------------------------------------------- ; Move the mouse pointer Y position to the value in a/x. Always called with ; interrupts disabled. -.proc movey - +movey: add #50 ; Y correction (first visible line) sta VIC_SPR_Y ; Set Y position rts -.endproc - ; -------------------------------------------------------------------------- ; Callback structure @@ -96,7 +95,7 @@ VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register _mouse_def_callbacks: .addr hide .addr show + .addr prep + .addr draw .addr movex .addr movey - - diff --git a/libsrc/c64/mou/c64-1351.s b/libsrc/c64/mou/c64-1351.s index ec053b0b2..a7d042c7b 100644 --- a/libsrc/c64/mou/c64-1351.s +++ b/libsrc/c64/mou/c64-1351.s @@ -29,11 +29,13 @@ .include "c64.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_1351_mou HEADER: @@ -69,6 +71,8 @@ HEADER: CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord @@ -101,10 +105,9 @@ Buttons: .res 1 ; button status bits OldValue: .res 1 ; Temp for MoveCheck routine NewValue: .res 1 ; Temp for MoveCheck routine -; Default values for above variables - .rodata +; Default values for above variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars @@ -315,7 +318,7 @@ IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ; MUST return carry clear. ; -IRQ: +IRQ: jsr CPREP ; Record the state of the buttons. ; Avoid crosstalk between the keyboard and the mouse. @@ -418,8 +421,9 @@ IRQ: ; Done +@SkipY: jsr CDRAW clc ; Interrupt not "handled" -@SkipY: rts + rts ; -------------------------------------------------------------------------- ; diff --git a/libsrc/c64/mou/c64-inkwell.s b/libsrc/c64/mou/c64-inkwell.s index 070d8f108..9c876a7c8 100644 --- a/libsrc/c64/mou/c64-inkwell.s +++ b/libsrc/c64/mou/c64-inkwell.s @@ -1,7 +1,7 @@ ; ; Driver for the Inkwell Systems 170-C and 184-C lightpens. ; -; 2013-07-01, Greg King +; 2014-09-10, Greg King ; .include "zeropage.inc" @@ -9,11 +9,13 @@ .include "c64.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table. -.segment "JUMPTABLE" + module_header _c64_inkwell_mou HEADER: @@ -49,6 +51,8 @@ LIBREF: .addr $0000 CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X co-ord. CMOVEY: jmp $0000 ; Move the cursor to Y co-ord. @@ -98,6 +102,8 @@ OldPenY: .res 1 ; Default Inkwell calibration. ; The first number is the width of the left border; ; the second number is the actual calibration value. +; See a comment below (at "Calculate the new X co-ordinate") +; for the reason for the third number. XOffset: .byte (24 + 24) / 2 ; x-offset @@ -256,7 +262,7 @@ MOVE: sei ; No interrupts BUTTONS: lda Buttons - ldx #>0 + ldx #>$0000 ; Make the lightpen buttons look like a 1351 mouse. @@ -324,7 +330,7 @@ IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now ; MUST return carry clear. ; -IRQ: +IRQ: jsr CPREP ; Record the state of the buttons. ; Try to avoid crosstalk between the keyboard and the lightpen. @@ -356,7 +362,7 @@ IRQ: sub #50 tay ; Remember low byte - ldx #>0 + ldx #>$0000 ; Limit the Y co-ordinate to the bounding box. @@ -397,7 +403,7 @@ IRQ: asl a tay ; Remember low byte - lda #>0 + lda #>$0000 rol a tax ; Remember high byte @@ -422,7 +428,8 @@ IRQ: ; Done -@SkipX: clc ; Interrupt not "handled" +@SkipX: jsr CDRAW + clc ; Interrupt not "handled" rts ; Move the lightpen pointer to the new Y pos. diff --git a/libsrc/c64/mou/c64-joy.s b/libsrc/c64/mou/c64-joy.s index 05f0ce50e..f2a501000 100644 --- a/libsrc/c64/mou/c64-joy.s +++ b/libsrc/c64/mou/c64-joy.s @@ -2,7 +2,7 @@ ; Driver for a "joystick mouse". ; ; Ullrich von Bassewitz, 2004-03-29, 2009-09-26 -; 2010-02-08, Greg King +; 2014-03-17, Greg King ; ; The driver prevents the keyboard from interfering by changing the ; keyboard's output port into an input port while the driver reads its @@ -28,11 +28,13 @@ .include "c64.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_joy_mou HEADER: @@ -68,6 +70,8 @@ HEADER: CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord @@ -106,17 +110,18 @@ Buttons: .res 1 ; Button mask Temp: .res 1 -; Default values for above variables - .rodata +; Default values for above variables +; (We use ".proc" because we want to define both a label and a scope.) + .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin - .word SCREEN_WIDTH ; XMax - .word SCREEN_HEIGHT ; YMax + .word SCREEN_WIDTH - 1 ; XMax + .word SCREEN_HEIGHT - 1 ; YMax .byte 0 ; Buttons .endproc @@ -318,9 +323,11 @@ IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ; MUST return carry clear. ; +IRQ: jsr CPREP + ; Avoid crosstalk between the keyboard and a joystick. -IRQ: ldy #%00000000 ; Set ports A and B to input + ldy #%00000000 ; Set ports A and B to input sty CIA1_DDRB sty CIA1_DDRA ; Keyboard won't look like joystick lda CIA1_PRB ; Read Control-Port 1 @@ -437,6 +444,7 @@ IRQ: ldy #%00000000 ; Set ports A and B to input ; Done -@SkipY: clc ; Interrupt not handled +@SkipY: jsr CDRAW + clc ; Interrupt not "handled" rts diff --git a/libsrc/c64/mou/c64-pot.s b/libsrc/c64/mou/c64-pot.s index 3eb977477..102ca351c 100644 --- a/libsrc/c64/mou/c64-pot.s +++ b/libsrc/c64/mou/c64-pot.s @@ -1,8 +1,9 @@ ; -; Driver for a potentiometer "mouse" e.g. Koala Pad +; Driver for a potentiometer "mouse", e.g. Koala Pad ; -; Ullrich von Bassewitz, 2004-03-29, 2009-09-26 -; Stefan Haubenthal, 2006-08-20 +; 2006-08-20, Stefan Haubenthal +; 2009-09-26, Ullrich von Bassewitz +; 2014-05-05, Greg King ; .include "zeropage.inc" @@ -10,11 +11,13 @@ .include "c64.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_pot_mou HEADER: @@ -42,10 +45,16 @@ HEADER: .addr IOCTL .addr IRQ +; Mouse driver flags + + .byte MOUSE_FLAG_LATE_IRQ + ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord @@ -84,17 +93,18 @@ Buttons: .res 1 ; Button mask Temp: .res 1 -; Default values for above variables - .rodata +; Default values for above variables +; (We use ".proc" because we want to define both a label and a scope.) + .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin - .word SCREEN_WIDTH ; XMax - .word SCREEN_HEIGHT ; YMax + .word SCREEN_WIDTH - 1 ; XMax + .word SCREEN_HEIGHT - 1 ; YMax .byte 0 ; Buttons .endproc @@ -296,7 +306,8 @@ IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ; (so be careful). ; -IRQ: lda #$7F +IRQ: jsr CPREP + lda #$7F sta CIA1_PRA lda CIA1_PRB ; Read port #1 and #%00001100 @@ -391,4 +402,7 @@ IRQ: lda #$7F ; Move the mouse pointer to the new X pos tya - jmp CMOVEY + jsr CMOVEY + jsr CDRAW + clc ; Interrupt not "handled" + rts diff --git a/libsrc/c64/ser/c64-swlink.s b/libsrc/c64/ser/c64-swlink.s index d95e63d9c..813067239 100644 --- a/libsrc/c64/ser/c64-swlink.s +++ b/libsrc/c64/ser/c64-swlink.s @@ -26,11 +26,13 @@ .include "ser-error.inc" .include "c64.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _c64_swlink_ser ; Driver signature diff --git a/libsrc/c64/systime.s b/libsrc/c64/systime.s index eb5f999f6..a00df1397 100644 --- a/libsrc/c64/systime.s +++ b/libsrc/c64/systime.s @@ -3,10 +3,10 @@ ; ; time_t _systime (void); ; /* Similar to time(), but: -; * - Is not ISO C -; * - Does not take the additional pointer -; * - Does not set errno when returning -1 -; */ +; ** - Is not ISO C +; ** - Does not take the additional pointer +; ** - Does not set errno when returning -1 +; */ ; .include "time.inc" diff --git a/libsrc/c64/tgi/c64-hi.s b/libsrc/c64/tgi/c64-hi.s index d91196649..6d33f00a8 100644 --- a/libsrc/c64/tgi/c64-hi.s +++ b/libsrc/c64/tgi/c64-hi.s @@ -9,14 +9,14 @@ .include "tgi-kernel.inc" .include "tgi-error.inc" - .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. -.segment "JUMPTABLE" + module_header _c64_hi_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver diff --git a/libsrc/cbm/cbm_load.c b/libsrc/cbm/cbm_load.c index 297910615..695af504b 100644 --- a/libsrc/cbm/cbm_load.c +++ b/libsrc/cbm/cbm_load.c @@ -1,20 +1,21 @@ /* - * Marc 'BlackJack' Rintsch, 06.03.2001 - * - * unsigned int cbm_load(const char* name, - * unsigned char device, - * const unsigned char* data); - */ +** Marc 'BlackJack' Rintsch, 06.03.2001 +** +** unsigned int cbm_load(const char* name, +** unsigned char device, +** const unsigned char* data); +*/ #include <cbm.h> /* loads file "name" from given device to given address or to the load address - * of the file if "data" is 0 - */ +** of the file if "data" is 0 +*/ unsigned int cbm_load(const char* name, unsigned char device, void* data) { - /* LFN is set to 0 but it's not needed for loading. - * (BASIC V2 sets it to the value of the SA for LOAD) */ + /* LFN is set to 0; but, it's not needed for loading + ** (BASIC V2 sets it to the value of the SA for LOAD). + */ cbm_k_setlfs(0, device, data == 0); cbm_k_setnam(name); return (cbm_k_load(0, (unsigned int)data) - (unsigned int)data); diff --git a/libsrc/cbm/cbm_open.s b/libsrc/cbm/cbm_open.s index 4d1cec040..1842fc149 100644 --- a/libsrc/cbm/cbm_open.s +++ b/libsrc/cbm/cbm_open.s @@ -8,9 +8,9 @@ ; unsigned char sec_addr, ; const char* name); ; /* Opens a file. Works just like the BASIC command. -; * Returns 0 if opening was successful, otherwise an errorcode (see table -; * below). -; */ +; ** Returns 0 if opening was successful, otherwise an errorcode (see table +; ** below). +; */ ; { ; cbm_k_setlfs(lfn, device, sec_addr); ; cbm_k_setnam(name); diff --git a/libsrc/cbm/cbm_read.s b/libsrc/cbm/cbm_read.s index d97ccbd8b..c84ff65aa 100644 --- a/libsrc/cbm/cbm_read.s +++ b/libsrc/cbm/cbm_read.s @@ -5,10 +5,10 @@ ; ; int __fastcall__ cbm_read (unsigned char lfn, void* buffer, unsigned int size) ; /* Reads up to "size" bytes from a file to "buffer". -; * Returns the number of actually read bytes, 0 if there are no bytes left -; * (EOF) or -1 in case of an error. _oserror contains an errorcode then (see -; * table below). -; */ +; ** Returns the number of actually read bytes, 0 if there are no bytes left +; ** (EOF) or -1 in case of an error. _oserror contains an errorcode then (see +; ** table below). +; */ ; { ; static unsigned int bytesread; ; static unsigned char tmp; @@ -22,9 +22,10 @@ ; tmp = cbm_k_basin(); ; ; /* the kernal routine BASIN sets ST to EOF if the end of file -; * is reached the first time, then we have store tmp. -; * every subsequent call returns EOF and READ ERROR in ST, then -; * we have to exit the loop here immidiatly. */ +; ** is reached the first time, then we have store tmp. +; ** every subsequent call returns EOF and READ ERROR in ST, then +; ** we have to exit the loop here immediatly. +; */ ; if (cbm_k_readst() & 0xBF) break; ; ; ((unsigned char*)buffer)[bytesread++] = tmp; diff --git a/libsrc/cbm/cbm_save.c b/libsrc/cbm/cbm_save.c index b88eed4ee..7f774b1b6 100644 --- a/libsrc/cbm/cbm_save.c +++ b/libsrc/cbm/cbm_save.c @@ -1,17 +1,17 @@ /* - * Marc 'BlackJack' Rintsch, 11.03.2001 - * - * unsigned char cbm_save(const char* name, - * char device, - * unsigned char* data, - * unsigned int size); - */ +** Marc 'BlackJack' Rintsch, 11.03.2001 +** +** unsigned char cbm_save(const char* name, +** char device, +** unsigned char* data, +** unsigned int size); +*/ #include <cbm.h> #include <errno.h> /* saves a memory area from start to end-1 to a file. - */ +*/ unsigned char __fastcall__ cbm_save (const char* name, unsigned char device, const void* data, diff --git a/libsrc/cbm/dir.h b/libsrc/cbm/dir.h index c206e6ed9..08cb022a0 100644 --- a/libsrc/cbm/dir.h +++ b/libsrc/cbm/dir.h @@ -1,7 +1,7 @@ /* - * Internal include file, do not use directly. - * Written by Ullrich von Bassewitz. Based on code by Groepaz. - */ +** Internal include file, do not use directly. +** Written by Ullrich von Bassewitz. Based on code by Groepaz. +*/ @@ -36,15 +36,15 @@ struct DIR { unsigned char __fastcall__ _dirread (DIR* dir, void* buf, unsigned char count); /* Read characters from the directory into the supplied buffer. Makes sure, - * errno is set in case of a short read. Return true if the read was - * successful and false otherwise. - */ +** errno is set in case of a short read. Return true if the read was +** successful and false otherwise. +*/ unsigned char __fastcall__ _dirread1 (DIR* dir, void* buf); /* Read one byte from the directory into the supplied buffer. Makes sure, - * errno is set in case of a short read. Return true if the read was - * successful and false otherwise. - */ +** errno is set in case of a short read. Return true if the read was +** successful and false otherwise. +*/ diff --git a/libsrc/cbm/dir.s b/libsrc/cbm/dir.s index 1916a4104..fddd71d7c 100644 --- a/libsrc/cbm/dir.s +++ b/libsrc/cbm/dir.s @@ -16,9 +16,9 @@ ; ; unsigned char __fastcall__ _dirread1 (DIR* dir, void* buf); ; /* Read one byte from the directory into the supplied buffer. Makes sure, -; * errno is set in case of a short read. Return true if the read was -; * successful and false otherwise. -; */ +; ** errno is set in case of a short read. Return true if the read was +; ** successful and false otherwise. +; */ __dirread1: @@ -31,9 +31,9 @@ __dirread1: ; ; unsigned char __fastcall__ _dirread (DIR* dir, void* buf, unsigned char count); ; /* Read characters from the directory into the supplied buffer. Makes sure, -; * errno is set in case of a short read. Return true if the read was -; * successful and false otherwise. -; */ +; ** errno is set in case of a short read. Return true if the read was +; ** successful and false otherwise. +; */ __dirread: diff --git a/libsrc/cbm/diskinit.s b/libsrc/cbm/diskinit.s index d84123a06..8a83a0212 100644 --- a/libsrc/cbm/diskinit.s +++ b/libsrc/cbm/diskinit.s @@ -21,7 +21,7 @@ tax jsr isdisk bcc open - lda #9 ; "Ilegal device" + lda #9 ; "Illegal device" rts ; Open channel diff --git a/libsrc/cbm/opendir.c b/libsrc/cbm/opendir.c index fe7fecb20..b39e6b77e 100644 --- a/libsrc/cbm/opendir.c +++ b/libsrc/cbm/opendir.c @@ -1,6 +1,6 @@ /* - * Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz. - */ +** Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz. +*/ #include <stdlib.h> #include <string.h> @@ -18,8 +18,8 @@ DIR* __fastcall__ opendir (register const char* name) DIR d; /* Setup the actual file name that is sent to the disk. We accept "0:", - * "1:" and "." as directory names. - */ + ** "1:" and "." as directory names. + */ d.name[0] = '$'; if (name == 0 || name[0] == '\0' || (name[0] == '.' && name[1] == '\0')) { d.name[1] = '\0'; diff --git a/libsrc/cbm/oserrlist.s b/libsrc/cbm/oserrlist.s index c85723910..a8e64c7cb 100644 --- a/libsrc/cbm/oserrlist.s +++ b/libsrc/cbm/oserrlist.s @@ -1,15 +1,16 @@ ; -; Ullrich von Bassewitz, 18.07.2002 +; 2002-07-18, Ullrich von Bassewitz +; 2014-05-28, Greg King ; -; Defines the platform specific error list. +; Defines the platform-specific error list. ; -; The table is built as a list of entries +; The table is built as a list of entries: ; ; .byte entrylen ; .byte errorcode ; .asciiz errormsg ; -; and terminated by an entry with length zero that is returned if the +; and, terminated by an entry with length zero that is returned if the ; error code could not be found. ; @@ -48,23 +49,24 @@ __sys_oserrlist: sys_oserr_entry 6, "File not input" sys_oserr_entry 7, "File not output" sys_oserr_entry 8, "Filename missing" - sys_oserr_entry 9, "Ilegal device" - sys_oserr_entry 20, "Read error" - sys_oserr_entry 21, "Read error" - sys_oserr_entry 22, "Read error" - sys_oserr_entry 23, "Read error" - sys_oserr_entry 24, "Read error" - sys_oserr_entry 25, "Write error" - sys_oserr_entry 26, "Write protect on" - sys_oserr_entry 27, "Read error" - sys_oserr_entry 28, "Write error" + sys_oserr_entry 9, "Illegal device" + sys_oserr_entry 20, "Read error (No sector header)" + sys_oserr_entry 21, "Read error (No sync mark)" + sys_oserr_entry 22, "Read error (No sector data)" + sys_oserr_entry 23, "Read error (Bad data checksum)" + sys_oserr_entry 24, "Read error (Decoding problem)" + sys_oserr_entry 25, "Write error (Verify failed)" + sys_oserr_entry 26, "Write protected" + sys_oserr_entry 27, "Read error (Bad header checksum)" + sys_oserr_entry 28, "Write error (overrun)" sys_oserr_entry 29, "Disk ID mismatch" - sys_oserr_entry 30, "Syntax error" - sys_oserr_entry 31, "Syntax error" - sys_oserr_entry 32, "Syntax error" - sys_oserr_entry 33, "Syntax error (invalid file name)" - sys_oserr_entry 34, "Syntax error (no file given)" - sys_oserr_entry 39, "Syntax error" + sys_oserr_entry 30, "Syntax error (Command not recognized)" + sys_oserr_entry 31, "Syntax error (Command not implemented)" + sys_oserr_entry 32, "Syntax error (Command too long)" + sys_oserr_entry 33, "Syntax error (Invalid write filename)" + sys_oserr_entry 34, "Syntax error (No file given)" + sys_oserr_entry 39, "System file not found" + sys_oserr_entry 49, "Invalid format" sys_oserr_entry 50, "Record not present" sys_oserr_entry 51, "Overflow in record" sys_oserr_entry 52, "File too large" @@ -77,10 +79,11 @@ __sys_oserrlist: sys_oserr_entry 66, "Illegal track or sector" sys_oserr_entry 67, "Illegal system track or sector" sys_oserr_entry 70, "No channel" - sys_oserr_entry 71, "Directory error" + sys_oserr_entry 71, "BAM error" sys_oserr_entry 72, "Disk full" sys_oserr_entry 73, "DOS version mismatch" sys_oserr_entry 74, "Drive not ready" + sys_oserr_entry 75, "Format error" + sys_oserr_entry 77, "Illegal partition" + sys_oserr_entry 78, "Bad system area" sys_oserr_sentinel "Unknown error" - - diff --git a/libsrc/cbm/oserror.s b/libsrc/cbm/oserror.s index 29980548a..872c75912 100644 --- a/libsrc/cbm/oserror.s +++ b/libsrc/cbm/oserror.s @@ -1,8 +1,9 @@ ; -; Ullrich von Bassewitz, 17.05.2000 +; 2000-05-17, Ullrich von Bassewitz +; 2014-05-28, Greg King ; ; int __fastcall__ _osmaperrno (unsigned char oserror); -; /* Map a system specific error into a system independent code */ +; /* Map a system-specific error into a system-independent code. */ ; .include "errno.inc" @@ -40,38 +41,42 @@ ErrTab: .byte 6, EINVAL ; File not input .byte 7, EINVAL ; File not output .byte 8, EINVAL ; Filename missing - .byte 9, ENODEV ; Ilegal device -; .byte 20, ; Read error -; .byte 21, ; Read error -; .byte 22, ; Read error -; .byte 23, ; Read error -; .byte 24, ; Read error -; .byte 25, ; Write error - .byte 26, EACCES ; Write protect on -; .byte 27, ; Read error -; .byte 28, ; Write error -; .byte 29, ; Disk ID mismatch -; .byte 30, ; Syntax error -; .byte 31, ; Syntax error -; .byte 32, ; Syntax error - .byte 33, EINVAL ; Syntax error (invalid file name) - .byte 34, EINVAL ; Syntax error (no file given) -; .byte 39, ; Syntax error -; .byte 50, ; Record not present -; .byte 51, ; Overflow in record -; .byte 52, ; File too large - .byte 60, EINVAL ; Write file open + .byte 9, ENODEV ; Illegal device + .byte 20, EBUSY ; No sector header + .byte 21, EBUSY ; No sync mark + .byte 22, EIO ; No sector data + .byte 23, EIO ; Checksum error + .byte 24, EIO ; Decode error + .byte 25, EIO ; Verify error + .byte 26, EACCES ; Write protected + .byte 27, EIO ; Checksum error + .byte 28, EIO ; Write overrun + .byte 29, EBUSY ; Disk ID mismatch + .byte 30, EINVAL ; Command not recognized + .byte 31, ENOSYS ; Command not implemented + .byte 32, EINVAL ; Command too long + .byte 33, EINVAL ; Invalid write filename + .byte 34, EINVAL ; No file given + .byte 39, ENOENT ; System file not found + .byte 49, EACCES ; Invalid format + .byte 50, ESPIPE ; Record not present + .byte 51, ENOSPC ; Overflow in record + .byte 52, ENOSPC ; File too large + .byte 60, EBUSY ; Write file open .byte 61, EINVAL ; File not open .byte 62, ENOENT ; File not found .byte 63, EEXIST ; File exists .byte 64, EINVAL ; File type mismatch -; .byte 65, ; No block -; .byte 66, ; Illegal track or sector -; .byte 67, ; Illegal system track or sector + .byte 65, ESPIPE ; No block + .byte 66, EINVAL ; Illegal track or sector + .byte 67, EIO ; Illegal system track or sector .byte 70, EBUSY ; No channel -; .byte 71, ; Directory error -; .byte 72, ; Disk full -; .byte 73, ; DOS version mismatch + .byte 71, EIO ; BAM error + .byte 72, ENOSPC ; Disk full + .byte 73, EACCES ; DOS version mismatch .byte 74, ENODEV ; Drive not ready + .byte 75, EIO ; Format error + .byte 77, EINVAL ; Illegal partition + .byte 78, EIO ; Bad system area ErrTabSize = (* - ErrTab) diff --git a/libsrc/cbm/read.s b/libsrc/cbm/read.s index 92d7ac6da..aa692a34a 100644 --- a/libsrc/cbm/read.s +++ b/libsrc/cbm/read.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 16.11.2002 +; 2002-11-16, Ullrich von Bassewitz +; 2013-12-23, Greg King ; ; int read (int fd, void* buf, unsigned count); ; @@ -7,7 +8,7 @@ .export _read .constructor initstdin - .import SETLFS, OPEN, CHKIN, BASIN, CLRCH, READST + .import SETLFS, OPEN, CHKIN, BASIN, CLRCH, BSOUT, READST .import rwcommon .import popax .importzp ptr1, ptr2, ptr3, tmp1, tmp2, tmp3 @@ -51,14 +52,20 @@ adc #LFN_OFFS ; Carry is already clear tax lda fdtab-LFN_OFFS,x; Get flags for this handle + tay and #LFN_READ ; File open for writing? beq invalidfd ; Check the EOF flag. If it is set, don't read anything - lda fdtab-LFN_OFFS,x; Get flags for this handle + tya ; Get flags again bmi eof +; Remember the device number. + + ldy unittab-LFN_OFFS,x + sty unit + ; Valid lfn. Make it the input file jsr CHKIN @@ -69,8 +76,13 @@ @L0: jsr BASIN sta tmp1 ; Save the input byte + ldx unit + bne @L0_1 ; Not keyboard/screen-editor + cmp #$0D ; Is it a Carriage Return? + bne @L0_1 + jsr BSOUT ; Yes, echo it (because editor didn't) - jsr READST ; Read the IEEE status +@L0_1: jsr READST ; Read the IEEE status sta tmp3 ; Save it and #%10111111 ; Check anything but the EOI bit bne devnotpresent ; Assume device not present @@ -138,4 +150,10 @@ invalidfd: .endproc +;-------------------------------------------------------------------------- + +.bss + +unit: .res 1 + diff --git a/libsrc/cbm/readdir.c b/libsrc/cbm/readdir.c index d6947316b..8d6968977 100644 --- a/libsrc/cbm/readdir.c +++ b/libsrc/cbm/readdir.c @@ -1,6 +1,6 @@ /* - * Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz. - */ +** Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz. +*/ @@ -53,9 +53,9 @@ struct dirent* __fastcall__ readdir (register DIR* dir) dir->off += count + 4; /* End of directory is reached if the buffer contains "blocks free". It is - * sufficient here to check for the leading 'b'. buffer will contain at - * least one byte if we come here. - */ + ** sufficient here to check for the leading 'b'. buffer will contain at + ** least one byte if we come here. + */ if (buffer[0] == 'b') { goto exitpoint; } diff --git a/libsrc/cbm/seekdir.c b/libsrc/cbm/seekdir.c index 0a4fe0781..8ccfadb96 100644 --- a/libsrc/cbm/seekdir.c +++ b/libsrc/cbm/seekdir.c @@ -1,6 +1,7 @@ /* - * Ullrich von Bassewitz, 2012-06-03. Based on code by Groepaz. - */ +** 2012-06-03, Ullrich von Bassewitz. Based on code by Groepaz. +** 2014-07-16, Greg King +*/ #include <fcntl.h> #include <unistd.h> @@ -15,8 +16,10 @@ void __fastcall__ seekdir (register DIR* dir, long offs) unsigned char count; unsigned char buf[128]; - /* Make sure we have a reasonable value for offs */ - if (offs > 0x1000) { + /* Make sure that we have a reasonable value for offs. We reject + ** negative numbers by converting them to (very high) unsigned values. + */ + if ((unsigned long)offs > 0x1000uL) { errno = EINVAL; return; } @@ -32,15 +35,15 @@ void __fastcall__ seekdir (register DIR* dir, long offs) } /* Skip until we've reached the target offset in the directory */ - o = dir->off = offs; + o = dir->off = (unsigned)offs; while (o) { /* Determine size of next chunk to read */ - if (o > sizeof (buf)) { + if (o > sizeof (buf)) { count = sizeof (buf); o -= sizeof (buf); } else { - count = offs; + count = (unsigned char)o; o = 0; } diff --git a/libsrc/cbm/syschdir.s b/libsrc/cbm/syschdir.s index 78b2df82d..a4a83cd21 100644 --- a/libsrc/cbm/syschdir.s +++ b/libsrc/cbm/syschdir.s @@ -1,5 +1,6 @@ ; -; Oliver Schmidt, 2012-10-16 +; 2012-10-16, Oliver Schmidt +; 2014-07-16, Greg King ; ; unsigned char __fastcall__ _syschdir (const char* name); ; @@ -39,18 +40,14 @@ ; Multiply first digit by 10 - ldx #8 -@L0: asl - asl tmp1 - bcc @L1 - clc - adc #10 -@L1: dex - bne @L0 + txa + asl a ; * 2 + asl a ; * 4, carry cleared + adc tmp1 ; * 5 + asl a ; * 10, carry cleared ; Add second digit to product - clc adc tmp2 tax @@ -74,13 +71,14 @@ init: txa ; Return with error in A -err: lda #9 ; "Ilegal device" +err: lda #9 ; "Illegal device" done: rts .endproc ;-------------------------------------------------------------------------- -; getdigit +; getdigit -- Converts PetSCII to binary. +; Sets carry if the character is outside of '0'-'9'. .proc getdigit @@ -92,4 +90,4 @@ done: rts @L0: cmp #10 rts -.endproc \ No newline at end of file +.endproc diff --git a/libsrc/cbm510/crt0.s b/libsrc/cbm510/crt0.s index 836038a06..86137b1ca 100644 --- a/libsrc/cbm510/crt0.s +++ b/libsrc/cbm510/crt0.s @@ -18,14 +18,14 @@ ; ------------------------------------------------------------------------ -; BASIC header and a small BASIC program. Since it is not possible to start +; The BASIC header and a small BASIC program. Since it isn't possible to start ; programs in other banks using SYS, the BASIC program will write a small -; machine code program into memory at $100 and start that machine code +; machine code program into memory at $100; and, start that machine code ; program. The machine code program will then start the machine language ; code in bank 0, which will initialize the system by copying stuff from ; the system bank, and start the application. ; -; Here's the basic program that's in the following lines: +; Here's the BASIC program that's in the following lines: ; ; 10 for i=0 to 4 ; 20 read j @@ -40,9 +40,9 @@ ; lda #$00 ; sta $00 <-- Switch to bank 0 after this command ; -; Initialization is not only complex because of the jumping from one bank -; into another. but also because we want to save memory, and because of -; this, we will use the system memory ($00-$3FF) for initialization stuff +; Initialization is complex not only because of the jumping from one bank +; into another, but also because we want to save memory; and because of +; that, we will use the system memory ($00-$3FF) for initialization stuff ; that is overwritten later. ; @@ -55,13 +55,15 @@ .byte $30,$2c,$31,$36,$39,$2c,$30,$2c,$31,$33,$33,$2c,$30,$00,$00,$00 ;------------------------------------------------------------------------------ -; A table that contains values that must be transfered from the system zero -; page into our zero page. Contains pairs of bytes; first one is the address -; in the system ZP, second one is our ZP address. The table goes into page 2, -; but is declared here because it is needed earlier. +; A table that contains values that must be transferred from the system zero- +; page into our zero-page. Contains pairs of bytes; first one is the address +; in the system ZP, second one is our ZP address. The table goes into page 2; +; but, is declared here because it is needed earlier. .SEGMENT "PAGE2" +; (We use .proc because we need both a label and a scope.) + .proc transfer_table .byte $9F, DEVNUM @@ -78,7 +80,7 @@ ; Page 3 data. This page contains the break vector and the bankswitch ; subroutine that is copied into high memory on startup. The space occupied by ; this routine will later be used for a copy of the bank 15 stack. It must be -; saved, since we're going to destroy it when calling bank 15. +; saved since we're going to destroy it when calling bank 15. .segment "PAGE3" @@ -92,7 +94,7 @@ BRKVec: .addr _exit ; BRK indirect vector entry: php pha - lda #$0F ; Bank 15 + lda #$0F ; Bank 15 sta IndReg txa pha @@ -115,7 +117,7 @@ entry: php tya sec sbc #7 - sta $1FF ; Save new sp + sta $1FF ; Save new sp tay tsx @@ -143,7 +145,7 @@ entry: php iny sta (sysp1),y - ldy $1FF ; Restore sp in bank 15 + ldy $1FF ; Restore sp in bank 15 lda #.hibyte(expull-1) sta (sysp1),y @@ -170,7 +172,7 @@ expull: pla rts .if (expull <> $FF26) -.error "Symbol expull must be aligned with kernal in bank 15" +.error "Symbol expull must be aligned with Kernal in bank 15" .endif .reloc @@ -180,15 +182,15 @@ expull: pla ;------------------------------------------------------------------------------ ; The code in the target bank when switching back will be put at the bottom ; of the stack. We will jump here to switch segments. The range $F2..$FF is -; not used by any kernal routine. +; not used by any Kernal routine. .segment "STARTUP" Back: sta ExecReg ; We are at $100 now. The following snippet is a copy of the code that is poked -; in the system bank memory by the basic header program, it's only for -; documentation and not actually used here: +; in the system bank memory by the BASIC header program; it's only for +; documentation, and not actually used here: sei lda #$00 @@ -196,23 +198,23 @@ Back: sta ExecReg ; This is the actual starting point of our code after switching banks for ; startup. Beware: The following code will get overwritten as soon as we -; use the stack (since it's in page 1)! We jump to another location, since +; use the stack (since it's in page 1)! We jump to another location since ; we need some space for subroutines that aren't used later. jmp Origin -; Hardware vectors, copied to $FFFA +; Hardware vectors, copied to $FFF6 .proc vectors sta ExecReg rts nop .word nmi ; NMI vector - .word 0 ; Reset - not used + .word 0 ; Reset -- not used .word irq ; IRQ vector .endproc -; Initializers for the extended zeropage. See extzp.s +; Initializers for the extended zero-page. See "extzp.s". .proc extzp .word $0100 ; sysp1 @@ -230,12 +232,12 @@ Back: sta ExecReg .word $ebd1 ; ktab4 .endproc -; Switch the indirect segment to the system bank +; Switch the indirect segment to the system bank. Origin: lda #$0F sta IndReg -; Initialize the extended zeropage +; Initialize the extended zero-page. ldx #.sizeof(extzp)-1 L1: lda extzp,x @@ -243,16 +245,16 @@ L1: lda extzp,x dex bpl L1 -; Save the old stack pointer from the system bank and setup our hw sp +; Save the old stack pointer from the system bank; and, set up our hw sp. tsx txa ldy #$FF sta (sysp1),y ; Save system stack point into $F:$1FF - ldx #$FE ; Leave $1FF untouched for cross bank calls + ldx #$FE ; Leave $1FF untouched for cross-bank calls txs ; Set up our own stack -; Copy stuff from the system zeropage to ours +; Copy stuff from the system zero-page to ours. lda #.sizeof(transfer_table) sta ktmp @@ -266,7 +268,7 @@ L2: ldx ktmp dec ktmp bne L2 -; Set the interrupt, NMI and other vectors +; Set the interrupt, NMI, and other vectors. ldx #.sizeof(vectors)-1 L3: lda vectors,x @@ -274,14 +276,14 @@ L3: lda vectors,x dex bpl L3 -; Setup the C stack +; Set up the C stack. lda #.lobyte(callbank15::entry) sta sp lda #.hibyte(callbank15::entry) sta sp+1 -; Setup the subroutine and jump vector table that redirects kernal calls to +; Set up the subroutine and jump vector table that redirects Kernal calls to ; the system bank. ldy #.sizeof(callbank15) @@ -290,10 +292,10 @@ L3: lda vectors,x dey bne @L1 -; Setup the jump vector table. Y is zero on entry. +; Set up the jump vector table. Y is zero on entry. - ldx #45-1 ; Number of vectors -@L2: lda #$20 ; JSR opcode + ldx #45-1 ; Number of vectors +@L2: lda #$20 ; JSR opcode sta $FF6F,y iny lda #.lobyte(callbank15::entry) @@ -305,13 +307,13 @@ L3: lda vectors,x dex bpl @L2 -; Set the indirect segment to bank we're executing in +; Set the indirect segment to the bank that we're executing in. lda ExecReg sta IndReg -; Zero the BSS segment. We will do that here instead calling the routine -; in the common library, since we have the memory anyway, and this way, +; Zero the BSS segment. We will do that here instead of calling the routine +; in the common library, since we have the memory anyway; and this way, ; it's reused later. lda #<__BSS_RUN__ @@ -321,18 +323,18 @@ L3: lda vectors,x lda #0 tay -; Clear full pages +; Clear full pages. ldx #>__BSS_SIZE__ beq Z2 Z1: sta (ptr1),y iny bne Z1 - inc ptr1+1 ; Next page + inc ptr1+1 ; Next page dex bne Z1 -; Clear the remaining page +; Clear the remaining page. Z2: ldx #<__BSS_SIZE__ beq Z4 @@ -343,12 +345,12 @@ Z3: sta (ptr1),y Z4: jmp Init ; ------------------------------------------------------------------------ -; We are at $200 now. We may now start calling subroutines safely, since +; We are at $200 now. We may now start calling subroutines safely since ; the code we execute is no longer in the stack page. .segment "PAGE2" -; Copy the character rom from the system bank into the execution bank +; Copy the character ROM from the system bank into the execution bank. Init: lda #<$C000 sta ptr1 @@ -362,7 +364,7 @@ Init: lda #<$C000 sta tmp1 ldy #$00 ccopy: lda #$0F - sta IndReg ; Access the system bank + sta IndReg ; Access the system bank ccopy1: lda (ptr1),y sta __VIDRAM_START__,y iny @@ -374,22 +376,22 @@ ccopy2: lda __VIDRAM_START__,y iny bne ccopy2 inc ptr1+1 - inc ptr2+1 ; Bump high pointer bytes + inc ptr2+1 ; Bump high pointer bytes dec tmp1 bne ccopy -; Clear the video memory. We will do this before switching the video to bank 0 +; Clear the video memory. We will do this before switching the video to bank 0, ; to avoid garbage when doing so. jsr _clrscr -; Reprogram the VIC so that the text screen and the character ROM is in the +; Reprogram the VIC so that the text screen and the character ROM are in the ; execution bank. This is done in three steps: - lda #$0F ; We need access to the system bank + lda #$0F ; We need access to the system bank sta IndReg -; Place the VIC video RAM into bank 0 +; Place the VIC video RAM into bank 0. ; CA (STATVID) = 0 ; CB (VICDOTSEL) = 0 @@ -400,7 +402,7 @@ ccopy2: lda __VIDRAM_START__,y ora #%10100000 sta (tpi1),y -; Set bit 14/15 of the VIC address range to the high bits of __VIDRAM_START__ +; Set bit 14/15 of the VIC address range to the high bits of __VIDRAM_START__. ; PC6/PC7 (VICBANKSEL 0/1) = 11 ldy #TPI::PRC @@ -422,12 +424,12 @@ ccopy2: lda __VIDRAM_START__,y ; ora #<(((>__VIDRAM_START__) << 2) & $F0) sta (vic),y -; Switch back to the execution bank +; Switch back to the execution bank. lda ExecReg sta IndReg -; Activate chained interrupt handlers, then enable interrupts. +; Activate the chained interrupt handlers; then, enable interrupts. lda #.lobyte(__INTERRUPTOR_COUNT__*2) sta irqcount @@ -437,11 +439,11 @@ ccopy2: lda __VIDRAM_START__,y jsr initlib -; Push arguments and call main() +; Push the command-line arguments; and, call main(). jsr callmain -; Call module destructors. This is also the _exit entry and the default entry +; Call the module destructors. This is also the exit() entry and the default entry ; point for the break vector. _exit: pha ; Save the return code on stack @@ -449,12 +451,12 @@ _exit: pha ; Save the return code on stack lda #$00 sta irqcount ; Disable custom irq handlers -; Address the system bank +; Address the system bank. lda #$0F sta IndReg -; Switch back the video to the system bank +; Switch back the video to the system bank. ldy #TPI::CR lda vidsave+0 @@ -468,7 +470,7 @@ _exit: pha ; Save the return code on stack lda vidsave+2 sta (vic),y -; Copy stuff back from our zeropage to the systems +; Copy stuff back from our zero-page to the system's. .if 0 lda #.sizeof(transfer_table) @@ -484,13 +486,13 @@ _exit: pha ; Save the return code on stack bne @L0 .endif -; Place the program return code into ST +; Place the program return code into BASIC's status variable. pla ldy #$9C ; ST sta (sysp0),y -; Setup the welcome code at the stack bottom in the system bank. +; Set up the welcome code at the stack bottom in the system bank. ldy #$FF lda (sysp1),y ; Load system bank sp @@ -511,14 +513,14 @@ _exit: pha ; Save the return code on stack ; easier chaining, we do handle the IRQs in the execution bank (instead of ; passing them to the system bank). -; This is the mapping of the active irq register of the 6525 (tpi1): +; This is the mapping of the active IRQ register of the 6525 (tpi1): ; ; Bit 7 6 5 4 3 2 1 0 -; | | | | ^ 50 Hz +; | | | | ^ 50 Hz. ; | | | ^ SRQ IEEE 488 -; | | ^ cia +; | | ^ CIA ; | ^ IRQB ext. Port -; ^ acia +; ^ ACIA irq: pha txa @@ -528,41 +530,41 @@ irq: pha lda IndReg pha lda ExecReg - sta IndReg ; Be sure to address our segment + sta IndReg ; Be sure to address our segment tsx - lda $105,x ; Get the flags from the stack - and #$10 ; Test break flag + lda $105,x ; Get the flags from the stack + and #$10 ; Test break flag bne dobrk -; It's an IRQ +; It's an IRQ. cld -; Call chained IRQ handlers +; Call the chained IRQ handlers. ldy irqcount beq irqskip - jsr callirq_y ; Call the functions + jsr callirq_y ; Call the functions -; Done with chained IRQ handlers, check the TPI for IRQs and handle them +; Done with the chained IRQ handlers; check the TPI for IRQs, and handle them. irqskip:lda #$0F sta IndReg ldy #TPI::AIR - lda (tpi1),y ; Interrupt Register 6525 + lda (tpi1),y ; Interrupt Register 6525 beq noirq -; 50/60Hz interrupt +; 50/60Hz. interrupt - cmp #%00000001 ; ticker irq? + cmp #%00000001 ; ticker IRQ? bne irqend - jsr scnkey ; Poll the keyboard - jsr UDTIM ; Bump the time + jsr scnkey ; Poll the keyboard + jsr UDTIM ; Bump the time -; Done +; Done. irqend: ldy #TPI::AIR - sta (tpi1),y ; Clear interrupt + sta (tpi1),y ; Clear interrupt noirq: pla sta IndReg @@ -583,5 +585,3 @@ vidsave:.res 3 .bss irqcount: .byte 0 - - diff --git a/libsrc/cbm510/emd/cbm510-ram.s b/libsrc/cbm510/emd/cbm510-ram.s index df7e17dc7..f724c7360 100644 --- a/libsrc/cbm510/emd/cbm510-ram.s +++ b/libsrc/cbm510/emd/cbm510-ram.s @@ -12,12 +12,13 @@ .include "cbm510.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _cbm510_ram_emd ; Driver signature diff --git a/libsrc/cbm510/joy/cbm510-std.s b/libsrc/cbm510/joy/cbm510-std.s index 1d8b242a6..7133f9379 100644 --- a/libsrc/cbm510/joy/cbm510-std.s +++ b/libsrc/cbm510/joy/cbm510-std.s @@ -13,12 +13,13 @@ .include "cbm510.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _cbm510_std_joy ; Driver signature diff --git a/libsrc/cbm510/mainargs.s b/libsrc/cbm510/mainargs.s index 7ed8d46f4..7eebccbb3 100644 --- a/libsrc/cbm510/mainargs.s +++ b/libsrc/cbm510/mainargs.s @@ -1,24 +1,156 @@ +; mainargs.s ; -; Ullrich von Bassewitz, 2003-03-07 +; 2003-03-07, Ullrich von Bassewitz, +; based on code from Stefan A. Haubenthal, <polluks@web.de> +; 2005-02-26, Ullrich von Bassewitz +; 2014-09-10, Greg King ; -; Setup arguments for main +; Scan a group of arguments that are in BASIC's input-buffer. +; Build an array that points to the beginning of each argument. +; Send, to main(), that array and the count of the arguments. ; - +; Command-lines look like these lines: +; +; run +; run : rem +; run:rem arg1 " arg 2 is quoted " arg3 "" arg5 +; +; "run" and "rem" are entokenned; the args. are not. Leading and trailing +; spaces outside of quotes are ignored. +; +; TO-DO: +; - The "file-name" might be a path-name; don't copy the directory-components. +; - Add a control-character quoting mechanism. .constructor initmainargs, 24 .import __argc, __argv + .import sys_bank, restore_bank + .import sysp0:zp, ptr1:zp + + .include "cbm510.inc" + .macpack generic -;--------------------------------------------------------------------------- + +MAXARGS = 10 ; Maximum number of arguments allowed +REM = $8f ; BASIC token-code +NAME_LEN = 16 ; maximum length of command-name + ; Get possible command-line arguments. Goes into the special INIT segment, -; which may be reused after the startup code is run - +; which may be reused after the startup code is run. +; .segment "INIT" -.proc initmainargs +initmainargs: +; Assume that the program was loaded, a moment ago, by the traditional LOAD +; statement. Save the "most-recent filename" as argument #0. +; Because the buffer, that we're copying into, was zeroed out, +; we don't need to add a NUL character. +; + jsr sys_bank + ldy #FNAM + lda (sysp0),y ; Get file-name pointer from system bank + sta ptr1 + iny + lda (sysp0),y + sta ptr1+1 + iny ; FNAM_BANK + lda (sysp0),y + tax + ldy #FNAM_LEN + lda (sysp0),y + tay + stx IndReg ; Look for name in correct bank + cpy #NAME_LEN + 1 + blt L1 + ldy #NAME_LEN - 1 ; limit the length +L0: lda (ptr1),y + sta name,y +L1: dey + bpl L0 + jsr restore_bank + inc __argc ; argc always is equal to at least 1 + +; Find a "rem" token. +; + ldx #0 +L2: lda BASIC_BUF,x + bze done ; no "rem," no args. + inx + cmp #REM + bne L2 + ldy #1 * 2 + +; Find the next argument. +; +next: lda BASIC_BUF,x + bze done ; End of line reached + inx + cmp #' ' ; Skip leading spaces + beq next ; + +; Found start of next argument. We've incremented the pointer in X already, so +; it points to the second character of the argument. That is useful because we +; will check now for a quoted argument; in which case, we will have to skip that +; first character. +; +found: cmp #'"' ; Is the argument quoted? + beq setterm ; Jump if so + dex ; Reset pointer to first argument character + lda #' ' ; A space ends the argument +setterm:sta term ; Set end-of-argument marker + +; Now, store a pointer to the argument into the next slot. +; + txa ; Get low byte + add #<BASIC_BUF + sta argv,y ; argv[y]= &arg + lda #>$0000 + adc #>BASIC_BUF + sta argv+1,y + iny + iny + inc __argc ; Found another arg + +; Search for the end of the argument. +; +argloop:lda BASIC_BUF,x + bze done + inx + cmp term + bne argloop + +; We've found the end of the argument. X points one character behind it, and +; A contains the terminating character. To make the argument a valid C string, +; replace the terminating character by a zero. +; + lda #$00 + sta BASIC_BUF-1,x + +; Check if the maximum number of command-line arguments is reached. If not, +; parse the next one. +; + lda __argc ; Get low byte of argument count + cmp #MAXARGS ; Maximum number of arguments reached? + blt next ; Parse next one if not + +; (The last vector in argv[] already is NULL.) +; +done: lda #<argv + ldx #>argv + sta __argv + stx __argv + 1 rts -.endproc - +; These arrays are zeroed before initmainargs is called. +; char name[16+1]; +; char* argv[MAXARGS+1]={name}; +; +.bss +term: .res 1 +name: .res NAME_LEN + 1 +.data +argv: .addr name + .res MAXARGS * 2, $00 diff --git a/libsrc/cbm510/mcbdefault.s b/libsrc/cbm510/mcbdefault.s index a6504ae30..028fb4ec1 100644 --- a/libsrc/cbm510/mcbdefault.s +++ b/libsrc/cbm510/mcbdefault.s @@ -27,8 +27,7 @@ VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register ; -------------------------------------------------------------------------- ; Hide the mouse pointer. Always called with interrupts disabled. -.proc hide - +hide: ldy #15 sty IndReg @@ -41,13 +40,10 @@ VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register sty IndReg rts -.endproc - ; -------------------------------------------------------------------------- ; Show the mouse pointer. Always called with interrupts disabled. -.proc show - +show: ldy #15 sty IndReg @@ -58,16 +54,25 @@ VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register ldy ExecReg sty IndReg - rts + ; Fall through -.endproc +; -------------------------------------------------------------------------- +; Prepare to move the mouse pointer. Always called with interrupts disabled. + +prep: + ; Fall through + +; -------------------------------------------------------------------------- +; Draw the mouse pointer. Always called with interrupts disabled. + +draw: + rts ; -------------------------------------------------------------------------- ; Move the mouse pointer x position to the value in .XA. Always called with ; interrupts disabled. -.proc movex - +movex: ldy #15 sty IndReg @@ -94,16 +99,13 @@ VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register @L1: lda (vic),y ; Get high x bits of all sprites ora #MOUSE_SPR_MASK ; Set high bit for sprite sta (vic),y - bnz @L0 ; branch always - -.endproc + bnz @L0 ; Branch always ; -------------------------------------------------------------------------- ; Move the mouse pointer y position to the value in .XA. Always called with ; interrupts disabled. -.proc movey - +movey: ldy #15 sty IndReg @@ -115,8 +117,6 @@ VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register sty IndReg rts -.endproc - ; -------------------------------------------------------------------------- ; Callback structure @@ -125,7 +125,7 @@ VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register _mouse_def_callbacks: .addr hide .addr show + .addr prep + .addr draw .addr movex .addr movey - - diff --git a/libsrc/cbm510/mou/cbm510-inkwl.s b/libsrc/cbm510/mou/cbm510-inkwl.s index 8502a7034..91bc52fcd 100644 --- a/libsrc/cbm510/mou/cbm510-inkwl.s +++ b/libsrc/cbm510/mou/cbm510-inkwl.s @@ -3,7 +3,7 @@ ; ; This driver reads only the main button on the 184-C. ; -; 2013-09-05, Greg King +; 2014-09-10, Greg King ; .include "zeropage.inc" @@ -13,11 +13,13 @@ .include "cbm510.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table. -.segment "JUMPTABLE" + module_header _cbm510_inkwl_mou HEADER: @@ -53,6 +55,8 @@ LIBREF: .addr $0000 CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X co-ord. CMOVEY: jmp $0000 ; Move the cursor to Y co-ord. @@ -99,6 +103,8 @@ OldPenY: .res 1 ; Default Inkwell calibration. ; The first number is the width of the left border; ; the second number is the actual calibration value. +; See a comment below (at "Calculate the new X co-ordinate") +; for the reason for the third number. XOffset: .byte (24 + 24) / 2 ; x-offset @@ -276,7 +282,7 @@ BUTTONS: asl a ; ... to fire-button bit eor #MOUSE_BTN_LEFT and #MOUSE_BTN_LEFT - ldx #>0 + ldx #>$0000 rts ;---------------------------------------------------------------------------- @@ -336,7 +342,8 @@ IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now ; MUST return carry clear. ; -IRQ: ldx #15 ; To system bank +IRQ: jsr CPREP + ldx #15 ; To system bank stx IndReg ; Read the VIC-II lightpen registers. @@ -357,7 +364,7 @@ IRQ: ldx #15 ; To system bank sub #50 tay ; Remember low byte - ldx #>0 + ldx #>$0000 ; Limit the Y co-ordinate to the bounding box. @@ -403,7 +410,7 @@ IRQ: ldx #15 ; To system bank asl a tay ; Remember low byte - lda #>0 + lda #>$0000 rol a tax ; Remember high byte @@ -428,7 +435,8 @@ IRQ: ldx #15 ; To system bank ; Done -@SkipX: clc ; Interrupt not "handled" +@SkipX: jsr CDRAW + clc ; Interrupt not "handled" rts ; Move the lightpen pointer to the new Y pos. diff --git a/libsrc/cbm510/mou/cbm510-joy.s b/libsrc/cbm510/mou/cbm510-joy.s index 9381cf761..8aa3a778e 100644 --- a/libsrc/cbm510/mou/cbm510-joy.s +++ b/libsrc/cbm510/mou/cbm510-joy.s @@ -2,7 +2,7 @@ ; Driver for a "joystick mouse". ; ; 2009-09-26, Ullrich von Bassewitz -; 2013-09-05, Greg King +; 2014-09-10, Greg King ; .include "zeropage.inc" @@ -12,11 +12,13 @@ .include "cbm510.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _cbm510_joy_mou HEADER: @@ -52,6 +54,8 @@ HEADER: CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to x co-ord. CMOVEY: jmp $0000 ; Move the cursor to y co-ord. @@ -89,10 +93,11 @@ YMax: .res 2 ; Y2 value of bounding box Temp: .res 1 -; Default values for above variables - .rodata +; Default values for above variables +; (We use ".proc" because we want to define both a label and a scope.) + .proc DefVars .word SCREEN_HEIGHT / 2 ; YPos .word SCREEN_WIDTH / 2 ; XPos @@ -261,7 +266,7 @@ BUTTONS: ; Bits go up when buttons go down. eor #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT - ldx #>0 + ldx #>$0000 rts ;---------------------------------------------------------------------------- @@ -322,7 +327,8 @@ IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now ; Reads joystick 2. ; -IRQ: ldy #15 ; Switch to the system bank +IRQ: jsr CPREP + ldy #15 ; Switch to the system bank sty IndReg ; Get the direction bits. @@ -352,11 +358,11 @@ IRQ: ldy #15 ; Switch to the system bank and #JOY::RIGHT << 4 ; Check RIGHT bit bnz @Right - lda #<-1 + lda #<-$0001 tax bnz @AddX ; Branch always -@Right: lda #<1 - ldx #>1 +@Right: lda #<$0001 + ldx #>$0001 ; Calculate the new x co-ordinate (--> .YA). @@ -395,11 +401,11 @@ IRQ: ldy #15 ; Switch to the system bank and #JOY::UP << 4 ; Check UP bit bze @Down - lda #<-1 + lda #<-$0001 tax bnz @AddY -@Down: lda #<1 - ldx #>1 +@Down: lda #<$0001 + ldx #>$0001 ; Calculate the new y co-ordinate (--> .YA). @@ -429,7 +435,8 @@ IRQ: ldy #15 ; Switch to the system bank ; Done -@SkipY: clc ; Interrupt not handled +@SkipY: jsr CDRAW + clc ; Interrupt not "handled" rts ; Move the mouse pointer to the new x pos. diff --git a/libsrc/cbm510/ser/cbm510-std.s b/libsrc/cbm510/ser/cbm510-std.s index be17a027b..7629892e0 100644 --- a/libsrc/cbm510/ser/cbm510-std.s +++ b/libsrc/cbm510/ser/cbm510-std.s @@ -27,11 +27,13 @@ .include "ser-error.inc" .include "cbm510.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _cbm510_std_ser ; Driver signature diff --git a/libsrc/cbm510/systime.s b/libsrc/cbm510/systime.s index 8a3858cef..daac36d8d 100644 --- a/libsrc/cbm510/systime.s +++ b/libsrc/cbm510/systime.s @@ -4,10 +4,10 @@ ; ; time_t _systime (void); ; /* Similar to time(), but: -; * - Is not ISO C -; * - Does not take the additional pointer -; * - Does not set errno when returning -1 -; */ +; ** - Is not ISO C +; ** - Does not take the additional pointer +; ** - Does not set errno when returning -1 +; */ ; .include "time.inc" diff --git a/libsrc/cbm610/crt0.s b/libsrc/cbm610/crt0.s index cc59148cc..0ad343d7f 100644 --- a/libsrc/cbm610/crt0.s +++ b/libsrc/cbm610/crt0.s @@ -17,14 +17,14 @@ ; ------------------------------------------------------------------------ -; BASIC header and a small BASIC program. Since it is not possible to start +; The BASIC header and a small BASIC program. Since it isn't possible to start ; programs in other banks using SYS, the BASIC program will write a small -; machine code program into memory at $100 and start that machine code +; machine code program into memory at $100; and, start that machine code ; program. The machine code program will then start the machine language ; code in bank 1, which will initialize the system by copying stuff from ; the system bank, and start the application. ; -; Here's the basic program that's in the following lines: +; Here's the BASIC program that's in the following lines: ; ; 10 for i=0 to 4 ; 20 read j @@ -39,9 +39,9 @@ ; lda #$01 ; sta $00 <-- Switch to bank 1 after this command ; -; Initialization is not only complex because of the jumping from one bank -; into another. but also because we want to save memory, and because of -; this, we will use the system memory ($00-$3FF) for initialization stuff +; Initialization is complex not only because of the jumping from one bank +; into another. but also because we want to save memory; and because of +; that, we will use the system memory ($00-$3FF) for initialization stuff ; that is overwritten later. ; @@ -54,13 +54,15 @@ .byte $30,$2c,$31,$36,$39,$2c,$31,$2c,$31,$33,$33,$2c,$30,$00,$00,$00 ;------------------------------------------------------------------------------ -; A table that contains values that must be transfered from the system zero -; page into out zero page. Contains pairs of bytes, first one is the address -; in the system ZP, second one is our ZP address. The table goes into page 2, -; but is declared here, because it is needed earlier. +; A table that contains values that must be transferred from the system zero- +; page into our zero-page. Contains pairs of bytes, first one is the address +; in the system ZP, second one is our ZP address. The table goes into page 2; +; but, is declared here because it is needed earlier. .SEGMENT "PAGE2" +; (We use .proc because we need both a label and a scope.) + .proc transfer_table .byte $9F, DEVNUM @@ -76,7 +78,7 @@ ; Page 3 data. This page contains the break vector and the bankswitch ; subroutine that is copied into high memory on startup. The space occupied by ; this routine will later be used for a copy of the bank 15 stack. It must be -; saved, since we're going to destroy it when calling bank 15. +; saved since we're going to destroy it when calling bank 15. .segment "PAGE3" @@ -84,13 +86,13 @@ BRKVec: .addr _exit ; BRK indirect vector .proc callbank15 - excrts := $FF05 ; In bank 15 rom + excrts := $FF05 ; In bank 15 ROM .org $FECB entry: php pha - lda #$0F ; Bank 15 + lda #$0F ; Bank 15 sta IndReg txa pha @@ -113,7 +115,7 @@ entry: php tya sec sbc #7 - sta $1FF ; Save new sp + sta $1FF ; Save new sp tay tsx @@ -141,7 +143,7 @@ entry: php iny sta (sysp1),y - ldy $1FF ; Restore sp in bank 15 + ldy $1FF ; Restore sp in bank 15 lda #.hibyte(expull-1) sta (sysp1),y @@ -168,7 +170,7 @@ expull: pla rts .if (expull <> $FF2E) -.error "Symbol expull must be aligned with kernal in bank 15" +.error "Symbol expull must be aligned with Kernal in bank 15" .endif .reloc @@ -178,15 +180,15 @@ expull: pla ;------------------------------------------------------------------------------ ; The code in the target bank when switching back will be put at the bottom ; of the stack. We will jump here to switch segments. The range $F2..$FF is -; not used by any kernal routine. +; not used by any Kernal routine. .segment "STARTUP" Back: sta ExecReg ; We are at $100 now. The following snippet is a copy of the code that is poked -; in the system bank memory by the basic header program, it's only for -; documentation and not actually used here: +; in the system bank memory by the BASIC header program; it's only for +; documentation, and not actually used here: sei lda #$01 @@ -194,7 +196,7 @@ Back: sta ExecReg ; This is the actual starting point of our code after switching banks for ; startup. Beware: The following code will get overwritten as soon as we -; use the stack (since it's in page 1)! We jump to another location, since +; use the stack (since it's in page 1)! We jump to another location since ; we need some space for subroutines that aren't used later. jmp Origin @@ -206,11 +208,11 @@ Back: sta ExecReg rts nop .word nmi ; NMI vector - .word 0 ; Reset - not used + .word 0 ; Reset -- not used .word irq ; IRQ vector .endproc -; Initializers for the extended zeropage. See extzp.s +; Initializers for the extended zero-page. See "extzp.s". .proc extzp .word $0100 ; sysp1 @@ -228,12 +230,12 @@ Back: sta ExecReg .word $eb49 ; ktab4 .endproc -; Switch the indirect segment to the system bank +; Switch the indirect segment to the system bank. Origin: lda #$0F sta IndReg -; Initialize the extended zeropage +; Initialize the extended zero-page. ldx #.sizeof(extzp)-1 L1: lda extzp,x @@ -241,16 +243,16 @@ L1: lda extzp,x dex bpl L1 -; Save the old stack pointer from the system bank and setup our hw sp +; Save the old stack pointer from the system bank; and, set up our hw sp. tsx txa ldy #$FF sta (sysp1),y ; Save system stack point into $F:$1FF - ldx #$FE ; Leave $1FF untouched for cross bank calls + ldx #$FE ; Leave $1FF untouched for cross-bank calls txs ; Set up our own stack -; Copy stuff from the system zeropage to ours +; Copy stuff from the system zero-page to ours. lda #.sizeof(transfer_table) sta ktmp @@ -264,7 +266,7 @@ L2: ldx ktmp dec ktmp bne L2 -; Set the interrupt, NMI and other vectors +; Set the interrupt, NMI, and other vectors. ldx #.sizeof(vectors)-1 L3: lda vectors,x @@ -272,14 +274,14 @@ L3: lda vectors,x dex bpl L3 -; Setup the C stack +; Set up the C stack. lda #.lobyte(callbank15::entry) sta sp lda #.hibyte(callbank15::entry) sta sp+1 -; Setup the subroutine and jump vector table that redirects kernal calls to +; Set up the subroutine and jump vector table that redirects Kernal calls to ; the system bank. ldy #.sizeof(callbank15) @@ -288,10 +290,10 @@ L3: lda vectors,x dey bne @L1 -; Setup the jump vector table. Y is zero on entry. +; Set up the jump vector table. Y is zero on entry. - ldx #45-1 ; Number of vectors -@L2: lda #$20 ; JSR opcode + ldx #45-1 ; Number of vectors +@L2: lda #$20 ; JSR opcode sta $FF6F,y iny lda #.lobyte(callbank15::entry) @@ -303,13 +305,13 @@ L3: lda vectors,x dex bpl @L2 -; Set the indirect segment to bank we're executing in +; Set the indirect segment to the bank that we're executing in. lda ExecReg sta IndReg -; Zero the BSS segment. We will do that here instead calling the routine -; in the common library, since we have the memory anyway, and this way, +; Zero the BSS segment. We will do that here instead of calling the routine +; in the common library, since we have the memory anyway; and this way, ; it's reused later. lda #<__BSS_RUN__ @@ -319,18 +321,18 @@ L3: lda vectors,x lda #0 tay -; Clear full pages +; Clear full pages. ldx #>__BSS_SIZE__ beq Z2 Z1: sta (ptr1),y iny bne Z1 - inc ptr1+1 ; Next page + inc ptr1+1 ; Next page dex bne Z1 -; Clear the remaining page +; Clear the remaining page. Z2: ldx #<__BSS_SIZE__ beq Z4 @@ -341,12 +343,12 @@ Z3: sta (ptr1),y Z4: jmp Init ; ------------------------------------------------------------------------ -; We are at $200 now. We may now start calling subroutines safely, since +; We are at $200 now. We may now start calling subroutines safely since ; the code we execute is no longer in the stack page. .segment "PAGE2" -; Activate chained interrupt handlers, then enable interrupts. +; Activate the chained interrupt handlers; then, enable interrupts. Init: lda #.lobyte(__INTERRUPTOR_COUNT__*2) sta irqcount @@ -356,11 +358,11 @@ Init: lda #.lobyte(__INTERRUPTOR_COUNT__*2) jsr initlib -; Push arguments and call main() +; Push the command-line arguments; and, call main(). jsr callmain -; Call module destructors. This is also the _exit entry and the default entry +; Call the module destructors. This is also the exit() entry and the default entry ; point for the break vector. _exit: pha ; Save the return code @@ -368,12 +370,12 @@ _exit: pha ; Save the return code lda #$00 sta irqcount ; Disable custom irq handlers -; Address the system bank +; Address the system bank. lda #$0F sta IndReg -; Copy stuff back from our zeropage to the systems +; Copy stuff back from our zero-page to the system's. .if 0 lda #.sizeof(transfer_table) @@ -389,13 +391,13 @@ _exit: pha ; Save the return code bne @L0 .endif -; Place the program return code into ST +; Place the program return code into BASIC's status variable. pla ldy #$9C ; ST sta (sysp0),y -; Setup the welcome code at the stack bottom in the system bank. +; Set up the welcome code at the stack bottom in the system bank. ldy #$FF lda (sysp1),y ; Load system bank sp @@ -416,14 +418,14 @@ _exit: pha ; Save the return code ; easier chaining, we do handle the IRQs in the execution bank (instead of ; passing them to the system bank). -; This is the mapping of the active irq register of the 6525 (tpi1): +; This is the mapping of the active IRQ register of the 6525 (tpi1): ; ; Bit 7 6 5 4 3 2 1 0 -; | | | | ^ 50 Hz +; | | | | ^ 50 Hz. ; | | | ^ SRQ IEEE 488 -; | | ^ cia +; | | ^ CIA ; | ^ IRQB ext. Port -; ^ acia +; ^ ACIA irq: pha txa @@ -433,41 +435,41 @@ irq: pha lda IndReg pha lda ExecReg - sta IndReg ; Be sure to address our segment + sta IndReg ; Be sure to address our segment tsx - lda $105,x ; Get the flags from the stack - and #$10 ; Test break flag + lda $105,x ; Get the flags from the stack + and #$10 ; Test break flag bne dobrk -; It's an IRQ +; It's an IRQ. cld -; Call chained IRQ handlers +; Call the chained IRQ handlers. ldy irqcount beq irqskip - jsr callirq_y ; Call the functions + jsr callirq_y ; Call the functions -; Done with chained IRQ handlers, check the TPI for IRQs and handle them +; Done with the chained IRQ handlers; check the TPI for IRQs, and handle them. irqskip:lda #$0F sta IndReg ldy #TPI::AIR - lda (tpi1),y ; Interrupt Register 6525 + lda (tpi1),y ; Interrupt Register 6525 beq noirq -; 50/60Hz interrupt +; 50/60Hz. interrupt - cmp #%00000001 ; ticker irq? + cmp #%00000001 ; ticker IRQ? bne irqend - jsr scnkey ; Poll the keyboard - jsr UDTIM ; Bump the time + jsr scnkey ; Poll the keyboard + jsr UDTIM ; Bump the time -; Done +; Done. irqend: ldy #TPI::AIR - sta (tpi1),y ; Clear interrupt + sta (tpi1),y ; Clear interrupt noirq: pla sta IndReg @@ -481,8 +483,7 @@ nmi: rti dobrk: jmp (BRKVec) ; ------------------------------------------------------------------------- -; Data area. +; Data area .bss irqcount: .byte 0 - diff --git a/libsrc/cbm610/emd/cbm610-ram.s b/libsrc/cbm610/emd/cbm610-ram.s index 6131d0093..5c67df7a4 100644 --- a/libsrc/cbm610/emd/cbm610-ram.s +++ b/libsrc/cbm610/emd/cbm610-ram.s @@ -12,12 +12,13 @@ .include "cbm610.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _cbm610_ram_emd ; Driver signature diff --git a/libsrc/cbm610/mainargs.s b/libsrc/cbm610/mainargs.s index 7ed8d46f4..9388eac81 100644 --- a/libsrc/cbm610/mainargs.s +++ b/libsrc/cbm610/mainargs.s @@ -1,24 +1,156 @@ +; mainargs.s ; -; Ullrich von Bassewitz, 2003-03-07 +; 2003-03-07, Ullrich von Bassewitz, +; based on code from Stefan A. Haubenthal, <polluks@web.de> +; 2005-02-26, Ullrich von Bassewitz +; 2014-09-10, Greg King ; -; Setup arguments for main +; Scan a group of arguments that are in BASIC's input-buffer. +; Build an array that points to the beginning of each argument. +; Send, to main(), that array and the count of the arguments. ; - +; Command-lines look like these lines: +; +; run +; run : rem +; run:rem arg1 " arg 2 is quoted " arg3 "" arg5 +; +; "run" and "rem" are entokenned; the args. are not. Leading and trailing +; spaces outside of quotes are ignored. +; +; TO-DO: +; - The "file-name" might be a path-name; don't copy the directory-components. +; - Add a control-character quoting mechanism. .constructor initmainargs, 24 .import __argc, __argv + .import sys_bank, restore_bank + .import sysp0:zp, ptr1:zp + + .include "cbm610.inc" + .macpack generic -;--------------------------------------------------------------------------- + +MAXARGS = 10 ; Maximum number of arguments allowed +REM = $8f ; BASIC token-code +NAME_LEN = 16 ; maximum length of command-name + ; Get possible command-line arguments. Goes into the special INIT segment, -; which may be reused after the startup code is run - +; which may be reused after the startup code is run. +; .segment "INIT" -.proc initmainargs +initmainargs: +; Assume that the program was loaded, a moment ago, by the traditional LOAD +; statement. Save the "most-recent filename" as argument #0. +; Because the buffer, that we're copying into, was zeroed out, +; we don't need to add a NUL character. +; + jsr sys_bank + ldy #FNAM + lda (sysp0),y ; Get file-name pointer from system bank + sta ptr1 + iny + lda (sysp0),y + sta ptr1+1 + iny ; FNAM_BANK + lda (sysp0),y + tax + ldy #FNAM_LEN + lda (sysp0),y + tay + stx IndReg ; Look for name in correct bank + cpy #NAME_LEN + 1 + blt L1 + ldy #NAME_LEN - 1 ; limit the length +L0: lda (ptr1),y + sta name,y +L1: dey + bpl L0 + jsr restore_bank + inc __argc ; argc always is equal to at least 1 + +; Find a "rem" token. +; + ldx #0 +L2: lda BASIC_BUF,x + bze done ; no "rem," no args. + inx + cmp #REM + bne L2 + ldy #1 * 2 + +; Find the next argument. +; +next: lda BASIC_BUF,x + bze done ; End of line reached + inx + cmp #' ' ; Skip leading spaces + beq next ; + +; Found start of next argument. We've incremented the pointer in X already, so +; it points to the second character of the argument. That is useful because we +; will check now for a quoted argument; in which case, we will have to skip that +; first character. +; +found: cmp #'"' ; Is the argument quoted? + beq setterm ; Jump if so + dex ; Reset pointer to first argument character + lda #' ' ; A space ends the argument +setterm:sta term ; Set end-of-argument marker + +; Now, store a pointer to the argument into the next slot. +; + txa ; Get low byte + add #<BASIC_BUF + sta argv,y ; argv[y]= &arg + lda #>$0000 + adc #>BASIC_BUF + sta argv+1,y + iny + iny + inc __argc ; Found another arg + +; Search for the end of the argument. +; +argloop:lda BASIC_BUF,x + bze done + inx + cmp term + bne argloop + +; We've found the end of the argument. X points one character behind it, and +; A contains the terminating character. To make the argument a valid C string, +; replace the terminating character by a zero. +; + lda #$00 + sta BASIC_BUF-1,x + +; Check if the maximum number of command-line arguments is reached. If not, +; parse the next one. +; + lda __argc ; Get low byte of argument count + cmp #MAXARGS ; Maximum number of arguments reached? + blt next ; Parse next one if not + +; (The last vector in argv[] already is NULL.) +; +done: lda #<argv + ldx #>argv + sta __argv + stx __argv + 1 rts -.endproc - +; These arrays are zeroed before initmainargs is called. +; char name[16+1]; +; char* argv[MAXARGS+1]={name}; +; +.bss +term: .res 1 +name: .res NAME_LEN + 1 +.data +argv: .addr name + .res MAXARGS * 2, $00 diff --git a/libsrc/cbm610/ser/cbm610-std.s b/libsrc/cbm610/ser/cbm610-std.s index 2d090bf41..1b2d38aa5 100644 --- a/libsrc/cbm610/ser/cbm610-std.s +++ b/libsrc/cbm610/ser/cbm610-std.s @@ -27,11 +27,13 @@ .include "ser-error.inc" .include "cbm610.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _cbm610_std_ser ; Driver signature diff --git a/libsrc/cbm610/systime.s b/libsrc/cbm610/systime.s index a6e72e8a5..be2bedf6f 100644 --- a/libsrc/cbm610/systime.s +++ b/libsrc/cbm610/systime.s @@ -4,10 +4,10 @@ ; ; time_t _systime (void); ; /* Similar to time(), but: -; * - Is not ISO C -; * - Does not take the additional pointer -; * - Does not set errno when returning -1 -; */ +; ** - Is not ISO C +; ** - Does not take the additional pointer +; ** - Does not set errno when returning -1 +; */ ; .include "time.inc" diff --git a/libsrc/common/_afailed.c b/libsrc/common/_afailed.c index 6600bf860..4e56b93f2 100644 --- a/libsrc/common/_afailed.c +++ b/libsrc/common/_afailed.c @@ -1,8 +1,8 @@ /* - * _afailed.c - * - * Ullrich von Bassewitz, 06.06.1998 - */ +** _afailed.c +** +** Ullrich von Bassewitz, 06.06.1998 +*/ diff --git a/libsrc/common/_file.h b/libsrc/common/_file.h index 66c8af828..8cd12c15e 100644 --- a/libsrc/common/_file.h +++ b/libsrc/common/_file.h @@ -1,9 +1,9 @@ /* - * _file.h - * - * (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org) - * - */ +** _file.h +** +** (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org) +** +*/ diff --git a/libsrc/common/_heapmaxavail.s b/libsrc/common/_heapmaxavail.s index 16fc10dde..4d44fadc1 100644 --- a/libsrc/common/_heapmaxavail.s +++ b/libsrc/common/_heapmaxavail.s @@ -61,7 +61,7 @@ __heapmaxavail: ; F = F->next; -@L2: iny ; Points to F->next +@L2: iny ; Points to F->next lda (ptr1),y tax iny @@ -69,8 +69,17 @@ __heapmaxavail: stx ptr1 jmp @L1 -; return Size; +; if (Size < HEAP_ADMIN_SPACE) return 0; @L3: lda ptr2 + sub #HEAP_ADMIN_SPACE ldx ptr2+1 + bcs @L5 + bne @L4 + txa rts + +; return Size - HEAP_ADMIN_SPACE; + +@L4: dex +@L5: rts diff --git a/libsrc/common/_hextab.c b/libsrc/common/_hextab.c index d4f24b2ea..4c172abb5 100644 --- a/libsrc/common/_hextab.c +++ b/libsrc/common/_hextab.c @@ -1,9 +1,9 @@ /* - * Ullrich von Bassewitz, 11.08.1998 - * - * Hex conversion table. Must be in C since the compiler will convert - * to the correct character set for the target platform. - */ +** Ullrich von Bassewitz, 11.08.1998 +** +** Hex conversion table. Must be in C since the compiler will convert +** to the correct character set for the target platform. +*/ diff --git a/libsrc/common/_longminstr.c b/libsrc/common/_longminstr.c index 290c7f155..ffc35aa77 100644 --- a/libsrc/common/_longminstr.c +++ b/libsrc/common/_longminstr.c @@ -1,11 +1,11 @@ /* - * Ullrich von Bassewitz, 2012-11-26 - * - * Minimum value of a long. Is used in ascii conversions, since this value - * has no positive counterpart than can be represented in 32 bits. In C, - * since the compiler will convert to the correct character set for the - * target platform. - */ +** Ullrich von Bassewitz, 2012-11-26 +** +** Minimum value of a long. Is used in ascii conversions, since this value +** has no positive counterpart than can be represented in 32 bits. In C, +** since the compiler will convert to the correct character set for the +** target platform. +*/ diff --git a/libsrc/common/_printf.h b/libsrc/common/_printf.h index e965b0d85..ffb2443bd 100644 --- a/libsrc/common/_printf.h +++ b/libsrc/common/_printf.h @@ -1,9 +1,9 @@ /* - * _printf.h - * - * (C) Copyright 1998 Ullrich von Bassewitz (uz@cc65.org) - * - */ +** _printf.h +** +** (C) Copyright 1998 Ullrich von Bassewitz (uz@cc65.org) +** +*/ @@ -21,9 +21,9 @@ typedef void (*outfunc) (struct outdesc* desc, const char* buf, unsigned count); /* Control structure passed to the low level worker function. - * Beware: This function will access the structure on the assembly level, - * so check this when altering the structure. - */ +** Beware: This function will access the structure on the assembly level, +** so check this when altering the structure. +*/ struct outdesc { int ccount; /* Character counter */ outfunc fout; /* Routine used to output data */ diff --git a/libsrc/common/_scanf.c b/libsrc/common/_scanf.c index 108fc6095..c18f1e289 100644 --- a/libsrc/common/_scanf.c +++ b/libsrc/common/_scanf.c @@ -1,13 +1,13 @@ /* - * _scanf.c - * - * (c) Copyright 2001-2005, Ullrich von Bassewitz <uz@cc65.org> - * 2005-01-24, Greg King <gngking@erols.com> - * - * This is the basic layer for all scanf-type functions. It should be - * rewritten in assembly, at some time in the future. So, some of the code - * is not as elegant as it could be. - */ +** _scanf.c +** +** (c) Copyright 2001-2005, Ullrich von Bassewitz <uz@cc65.org> +** 2014-09-10, Greg King <greg.king5@verizon.net> +** +** This is the basic layer for all scanf-type functions. It should be +** rewritten in assembly, at some time in the future. So, some of the code +** is not as elegant as it could be. +*/ @@ -76,12 +76,12 @@ static const unsigned char Bits[CHAR_BIT] = { }; /* We need C to be 16 bits since we cannot check for EOF otherwise. - * Unfortunately, this causes the code to be quite larger, even if for most - * purposes, checking the low byte would be enough, since if C is EOF, the - * low byte will not match any useful character anyway (at least for the - * supported platforms - I know that this is not portable). So the following - * macro is used to access just the low byte of C. - */ +** Unfortunately, this causes the code to be quite larger, even if for most +** purposes, checking the low byte would be enough, since if C is EOF, the +** low byte will not match any useful character anyway (at least for the +** supported platforms - I know that this is not portable). So the following +** macro is used to access just the low byte of C. +*/ #define CHAR(c) (*((unsigned char*)&(c))) @@ -93,16 +93,16 @@ static const unsigned char Bits[CHAR_BIT] = { /* We don't want the optimizer to ruin our "perfect" ;-) - * assembly code! - */ +** assembly code! +*/ #pragma optimize (push, off) static unsigned FindBit (void) /* Locate the character's bit in the charset array. - * < .A - Argument character - * > .X - Offset of the byte in the character-set mask - * > .A - Bit-mask - */ +** < .A - Argument character +** > .X - Offset of the byte in the character-set mask +** > .A - Bit-mask +*/ { asm ("pha"); asm ("lsr a"); /* Divide by CHAR_BIT */ @@ -250,8 +250,8 @@ static void ReadChar (void) asm ("stx %v+1", C); /* If C is EOF, don't bump the character counter. - * Only the high-byte needs to be checked. - */ + ** Only the high-byte needs to be checked. + */ asm ("inx"); asm ("beq %g", Done); @@ -275,7 +275,7 @@ static void __fastcall__ Error (unsigned char /* Code */) (char*) __AX__ = JumpBuf; asm ("jsr pushax"); asm ("pla"); - asm ("ldx #>0"); + asm ("ldx #>$0000"); asm ("jmp %v", longjmp); } @@ -311,12 +311,12 @@ static void SkipWhite (void) static void ReadSign (void) /* Read an optional sign and skip it. Store 1 in Positive if the value is - * positive, store 0 otherwise. - */ +** positive, store 0 otherwise. +*/ { /* We can ignore the high byte of C here, since if it is EOF, the lower - * byte won't match anyway. - */ + ** byte won't match anyway. + */ asm ("lda %v", C); asm ("cmp #'-'"); asm ("bne %g", NotNeg); @@ -380,11 +380,11 @@ static void __fastcall__ ReadInt (unsigned char Base) static void AssignInt (void) /* Assign the integer value in Val to the next argument. The function makes - * several non-portable assumptions, to reduce code size: - * - signed and unsigned types have the same representation. - * - short and int have the same representation. - * - all pointer types have the same representation. - */ +** several non-portable assumptions, to reduce code size: +** - signed and unsigned types have the same representation. +** - short and int have the same representation. +** - all pointer types have the same representation. +*/ { if (NoAssign == false) { @@ -416,8 +416,8 @@ Done: ; static void __fastcall__ ScanInt (unsigned char Base) /* Scan an integer including white space, sign and optional base spec, - * and store it into IntVal. - */ +** and store it into IntVal. +*/ { /* Skip whitespace */ SkipWhite (); @@ -440,8 +440,8 @@ static void __fastcall__ ScanInt (unsigned char Base) Base = 8; /* Restart at the beginning of the number because it might - * be only a single zero digit (which already was read). - */ + ** be only a single zero digit (which already was read). + */ PushBack (); C = '0'; } @@ -474,7 +474,7 @@ static char GetFormat (void) ++format; asm ("ldy #0"); asm ("lda (regsave),y"); - asm ("ldx #>0"); + asm ("ldx #>$0000"); return (F = (char) __AX__); } @@ -483,8 +483,8 @@ static char GetFormat (void) int __fastcall__ _scanf (const struct scanfdata* D, const char* format_, va_list ap_) /* This is the routine used to do the actual work. It is called from several - * types of wrappers to implement the actual ISO xxscanf functions. - */ +** types of wrappers to implement the actual ISO xxscanf functions. +*/ { register char* S; bool HaveWidth; /* True if a width was given */ @@ -492,9 +492,9 @@ int __fastcall__ _scanf (const struct scanfdata* D, char Start; /* Walks over a range */ /* Place copies of the arguments into global variables. This is not very - * nice, but on a 6502 platform it gives better code, since the values - * do not have to be passed as parameters. - */ + ** nice, but on a 6502 platform it gives better code, since the values + ** do not have to be passed as parameters. + */ D_ = D; format = format_; ap = ap_; @@ -505,8 +505,8 @@ int __fastcall__ _scanf (const struct scanfdata* D, CharCount = 0; /* Set up the jump "label". CheckEnd() will use that label when EOF - * is reached. ReadInt() will use it when number-conversion fails. - */ + ** is reached. ReadInt() will use it when number-conversion fails. + */ if ((unsigned char) setjmp (JumpBuf) == RC_OK) { Again: @@ -523,9 +523,9 @@ Again: if ((bool) isspace ((int) F)) { /* Special white space handling: Any whitespace in the - * format string matches any amount of whitespace including - * none(!). So this match will never fail. - */ + ** format string matches any amount of whitespace including + ** none(!). So this match will never fail. + */ SkipWhite (); continue; } @@ -537,8 +537,8 @@ Percent: if (C != (int) F) { /* A mismatch -- we will stop scanning the input, - * and return the number of assigned conversions. - */ + ** and return the number of assigned conversions. + */ goto NoConv; } @@ -572,18 +572,18 @@ Percent: if (Width == 0) { /* Invalid specification */ /* Note: This method of leaving the function might seem - * to be crude, but it optimizes very well because - * the four exits can share this code. - */ + ** to be crude, but it optimizes very well because + ** the four exits can share this code. + */ _seterrno (EINVAL); Assignments = EOF; PushBack (); return Assignments; } /* Increment-and-test makes better code than test-and-decrement - * does. So, change the width into a form that can be used in - * that way. - */ + ** does. So, change the width into a form that can be used in + ** that way. + */ Width = ~Width; /* 3. Length modifier */ @@ -618,9 +618,9 @@ Percent: /* 4. Conversion specifier */ switch (F) { /* 'd' and 'u' conversions are actually the same, since the - * standard says that even the 'u' modifier allows an - * optionally signed integer. - */ + ** standard says that even the 'u' modifier allows an + ** optionally signed integer. + */ case 'd': /* Optionally signed decimal integer */ case 'u': ScanInt (10); @@ -676,9 +676,9 @@ Percent: if (NoAssign == false) { S = va_arg (ap, char*); /* ## This loop is convenient for us, but it isn't - * standard C. The standard implies that a failure - * shouldn't put anything into the array argument. - */ + ** standard C. The standard implies that a failure + ** shouldn't put anything into the array argument. + */ while (++Width) { CheckEnd (); /* Is it a matching failure? */ *S++ = C; @@ -705,8 +705,8 @@ Percent: } if (F == ']') { /* Empty sets aren't allowed; so, a right-bracket - * at the beginning must be a member of the set. - */ + ** at the beginning must be a member of the set. + */ AddCharToSet (F); GetFormat (); } @@ -725,8 +725,8 @@ Percent: break; default: /* Include all characters - * that are in the range. - */ + ** that are in the range. + */ while (1) { AddCharToSet (Start); if (Start == F) { @@ -756,9 +756,9 @@ Percent: } /* We have the set in CharSet. Read characters and - * store them into a string while they are part of - * the set. - */ + ** store them into a string while they are part of + ** the set. + */ Match = false; if (NoAssign == false) { S = va_arg (ap, char*); @@ -782,10 +782,10 @@ Percent: case 'p': /* Pointer, general format is 0xABCD. - * %hhp --> zero-page pointer - * %hp --> near pointer - * %lp --> far pointer - */ + ** %hhp --> zero-page pointer + ** %hp --> near pointer + ** %lp --> far pointer + */ SkipWhite (); if (CHAR (C) != '0') { goto NoConv; @@ -806,8 +806,8 @@ Percent: case 'n': /* Store the number of characters consumed so far - * (the read-ahead character hasn't been consumed). - */ + ** (the read-ahead character hasn't been consumed). + */ IntVal = (long) (CharCount - (C == EOF ? 0u : 1u)); AssignInt (); /* Don't count it. */ @@ -849,9 +849,9 @@ Percent: NoConv: /* Coming here means a failure. If that happens at EOF, with no - * conversion attempts, then it is considered an error; otherwise, - * the number of assignments is returned (the default behaviour). - */ + ** conversion attempts, then it is considered an error; otherwise, + ** the number of assignments is returned (the default behaviour). + */ if (C == EOF && Converted == false) { Assignments = EOF; /* Special case: error */ } diff --git a/libsrc/common/_scanf.h b/libsrc/common/_scanf.h index 0a8b09b7d..179be5de7 100644 --- a/libsrc/common/_scanf.h +++ b/libsrc/common/_scanf.h @@ -1,9 +1,9 @@ /* - * _scanf.h - * - * (c) Copyright 2004, Ullrich von Bassewitz <uz@cc65.org> - * - */ +** _scanf.h +** +** (c) Copyright 2004, Ullrich von Bassewitz <uz@cc65.org> +** +*/ @@ -13,8 +13,8 @@ /* Type of the function that is called to input data. The function will - * return EOF if no more data is available. - */ +** return EOF if no more data is available. +*/ typedef int __fastcall__ (*getfunc) (void* data); /* Type of the function that is called to put back unused data */ @@ -23,9 +23,9 @@ typedef int __fastcall__ (*ungetfunc) (int c, void* data); /* Control structure passed to the low level worker function. - * Beware: This structure is mirrored in the _scanf.inc assembler include - * file, so check this when altering the structure. - */ +** Beware: This structure is mirrored in the _scanf.inc assembler include +** file, so check this when altering the structure. +*/ struct scanfdata { getfunc get; /* Pointer to input routine */ ungetfunc unget; /* Pointer to pushback routine */ diff --git a/libsrc/common/abort.c b/libsrc/common/abort.c index 298ff0adb..43ad676a7 100644 --- a/libsrc/common/abort.c +++ b/libsrc/common/abort.c @@ -1,8 +1,8 @@ /* - * abort.c - * - * Ullrich von Bassewitz, 02.06.1998 - */ +** abort.c +** +** Ullrich von Bassewitz, 02.06.1998 +*/ diff --git a/libsrc/common/bsearch.c b/libsrc/common/bsearch.c index 7d64dbbe9..f6d32a5b5 100644 --- a/libsrc/common/bsearch.c +++ b/libsrc/common/bsearch.c @@ -1,8 +1,8 @@ /* - * bsearch.c - * - * Ullrich von Bassewitz, 17.06.1998 - */ +** bsearch.c +** +** Ullrich von Bassewitz, 17.06.1998 +*/ @@ -33,9 +33,9 @@ void* __fastcall__ bsearch (const void* key, const void* base, size_t n, last = current - 1; if (result == 0) { /* Found one entry that matches the search key. However there may be - * more than one entry with the same key value and ANSI guarantees - * that we return the first of a row of items with the same key. - */ + ** more than one entry with the same key value and ANSI guarantees + ** that we return the first of a row of items with the same key. + */ found = 1; } } diff --git a/libsrc/common/cc65_imul8x8r16.s b/libsrc/common/cc65_imul8x8r16.s new file mode 100644 index 000000000..0e7d5479b --- /dev/null +++ b/libsrc/common/cc65_imul8x8r16.s @@ -0,0 +1,22 @@ +; +; 2014-03-27, Oliver Schmidt +; 2014-05-08, Greg King +; +; CC65 library: 8x8 => 16 signed multiplication +; + + .export _cc65_imul8x8r16 + .import imul8x8r16, popa, ptr1:zp + + +;--------------------------------------------------------------------------- +; 8x8 => 16 signed multiplication routine. + + +.proc _cc65_imul8x8r16 + + sta ptr1 + jsr popa + jmp imul8x8r16 + +.endproc diff --git a/libsrc/common/cc65_umul8x8r16.s b/libsrc/common/cc65_umul8x8r16.s new file mode 100644 index 000000000..cf3b26bb1 --- /dev/null +++ b/libsrc/common/cc65_umul8x8r16.s @@ -0,0 +1,21 @@ +; +; Oliver Schmidt, 2014-03-27 +; +; CC65 library: 8x8 => 16 unsigned multiplication +; + + .export _cc65_umul8x8r16 + .import umul8x8r16, popa, ptr1:zp + + +;--------------------------------------------------------------------------- +; 8x8 => 16 unsigned multiplication routine. + + +.proc _cc65_umul8x8r16 + + sta ptr1 + jsr popa + jmp umul8x8r16 + +.endproc diff --git a/libsrc/common/errno.s b/libsrc/common/errno.s index 5c2bf288e..3a1f1b6c8 100644 --- a/libsrc/common/errno.s +++ b/libsrc/common/errno.s @@ -12,8 +12,8 @@ ; ---------------------------------------------------------------------------- ; int __fastcall__ _directerrno (unsigned char code); ; /* Set errno to a specific error code, clear _oserror and return -1. Used -; * by the library. -; */ +; ** by the library. +; */ __directerrno: jsr __seterrno ; Set errno, returns with A = 0 @@ -23,10 +23,10 @@ __directerrno: ; ---------------------------------------------------------------------------- ; int __fastcall__ _mappederrno (unsigned char code); ; /* Set _oserror to the given platform specific error code. If it is a real -; * error code (not zero) set errno to the corresponding system error code -; * and return -1. Otherwise return zero. -; * Used by the library. -; */ +; ** error code (not zero) set errno to the corresponding system error code +; ** and return -1. Otherwise return zero. +; ** Used by the library. +; */ __mappederrno: sta __oserror ; Store the error code diff --git a/libsrc/common/errormsg.c b/libsrc/common/errormsg.c index d73ca652c..162dad085 100644 --- a/libsrc/common/errormsg.c +++ b/libsrc/common/errormsg.c @@ -1,11 +1,8 @@ /* - * errormsg.c - * - * Ullrich von Bassewitz, 17.05.2000 - * - * Must be a C function, since we have otherwise problems with the different - * character sets. - */ +** errormsg.c +** +** Ullrich von Bassewitz, 17.05.2000 +*/ diff --git a/libsrc/common/fdopen.c b/libsrc/common/fdopen.c index 43559ce8b..a3e482ffe 100644 --- a/libsrc/common/fdopen.c +++ b/libsrc/common/fdopen.c @@ -1,8 +1,8 @@ /* - * fdopen.c - * - * Ullrich von Bassewitz, 17.06.1998 - */ +** fdopen.c +** +** Ullrich von Bassewitz, 17.06.1998 +*/ diff --git a/libsrc/common/fgetc.c b/libsrc/common/fgetc.c index c873cd1d0..b4ba18d73 100644 --- a/libsrc/common/fgetc.c +++ b/libsrc/common/fgetc.c @@ -1,9 +1,9 @@ /* - * fgetc.c - * - * (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org) - * - */ +** fgetc.c +** +** (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org) +** +*/ diff --git a/libsrc/common/fgetpos.c b/libsrc/common/fgetpos.c index 796792afa..67fee5907 100644 --- a/libsrc/common/fgetpos.c +++ b/libsrc/common/fgetpos.c @@ -1,8 +1,8 @@ /* - * fgetpos.c - * - * Christian Groessler, 07-Aug-2000 - */ +** fgetpos.c +** +** Christian Groessler, 07-Aug-2000 +*/ diff --git a/libsrc/common/fgets.c b/libsrc/common/fgets.c index 259f3904e..21a991fd6 100644 --- a/libsrc/common/fgets.c +++ b/libsrc/common/fgets.c @@ -1,8 +1,8 @@ /* - * Ullrich von Bassewitz, 11.08.1998 - * - * char* fgets (char* s, int size, FILE* f); - */ +** Ullrich von Bassewitz, 11.08.1998 +** +** char* fgets (char* s, int size, FILE* f); +*/ diff --git a/libsrc/common/fputc.c b/libsrc/common/fputc.c index 73d4860a7..b623949d3 100644 --- a/libsrc/common/fputc.c +++ b/libsrc/common/fputc.c @@ -1,8 +1,8 @@ /* - * fputc.c - * - * Ullrich von Bassewitz, 02.06.1998 - */ +** fputc.c +** +** Ullrich von Bassewitz, 02.06.1998 +*/ diff --git a/libsrc/common/fputs.c b/libsrc/common/fputs.c index 26c20cbe2..be476a3f0 100644 --- a/libsrc/common/fputs.c +++ b/libsrc/common/fputs.c @@ -1,8 +1,8 @@ /* - * int fputs (const char* s, FILE* f); - * - * Ullrich von Bassewitz, 11.08.1998 - */ +** int fputs (const char* s, FILE* f); +** +** Ullrich von Bassewitz, 11.08.1998 +*/ diff --git a/libsrc/common/free.s b/libsrc/common/free.s index b6b77aae8..00b5e63f8 100644 --- a/libsrc/common/free.s +++ b/libsrc/common/free.s @@ -10,8 +10,8 @@ ; ; void free (void* block) ; /* Release an allocated memory block. The function will accept NULL pointers -; * (and do nothing in this case). -; */ +; ** (and do nothing in this case). +; */ ; { ; unsigned* b; ; unsigned size; @@ -34,8 +34,8 @@ ; _hptr = (unsigned*) (((int) _hptr) - size); ; ; /* Check if the last block in the freelist is now at heap top. If so, -; * remove this block from the freelist. -; */ +; ** remove this block from the freelist. +; */ ; if (f = _hlast) { ; if (((int) f) + f->size == (int) _hptr) { ; /* Remove the last block */ @@ -185,10 +185,10 @@ _free: sta ptr2 ; ; void _hadd (void* mem, size_t size) ; /* Add an arbitrary memory block to the heap. This function is used by -; * free(), but it does also allow usage of otherwise unused memory -; * blocks as heap space. The given block is entered in the free list -; * without any checks, so beware! -; */ +; ** free(), but it does also allow usage of otherwise unused memory +; ** blocks as heap space. The given block is entered in the free list +; ** without any checks, so beware! +; */ ; { ; struct freeblock* f; ; struct freeblock* left; @@ -212,10 +212,10 @@ _free: sta ptr2 ; } else { ; ; /* We have to search the free list. As we are doing so, we check -; * if it is possible to combine this block with another already -; * existing block. Beware: The block may be the "missing link" -; * between *two* other blocks. -; */ +; ** if it is possible to combine this block with another already +; ** existing block. Beware: The block may be the "missing link" +; ** between *two* other blocks. +; */ ; left = 0; ; right = _hfirst; ; while (right && f > right) { @@ -224,10 +224,10 @@ _free: sta ptr2 ; } ; ; -; /* Ok, the current block must be inserted between left and right (but -; * beware: one of the two may be zero!). Also check for the condition -; * that we have to merge two or three blocks. -; */ +; /* OK, the current block must be inserted between left and right (but +; ** beware: one of the two may be zero!). Also check for the condition +; ** that we have to merge two or three blocks. +; */ ; if (right) { ; /* Check if we must merge the block with the right one */ ; if (((unsigned) f) + size == (unsigned) right) { diff --git a/libsrc/common/freopen.c b/libsrc/common/freopen.c index 3c4d92ee0..d79d3cf15 100644 --- a/libsrc/common/freopen.c +++ b/libsrc/common/freopen.c @@ -1,8 +1,8 @@ /* - * freopen.c - * - * Ullrich von Bassewitz, 17.06.1998 - */ +** freopen.c +** +** Ullrich von Bassewitz, 17.06.1998 +*/ @@ -28,8 +28,8 @@ FILE* __fastcall__ freopen (const char* name, const char* mode, FILE* f) } /* Close the file. Don't bother setting the flag, it will get - * overwritten by _fopen. - */ + ** overwritten by _fopen. + */ if (close (f->f_fd) < 0) { /* An error occured, errno is already set */ return 0; diff --git a/libsrc/common/fscanf.s b/libsrc/common/fscanf.s index e519fbdd8..a3d1ec0a1 100644 --- a/libsrc/common/fscanf.s +++ b/libsrc/common/fscanf.s @@ -27,8 +27,8 @@ ParamSize: .res 1 ; Number of parameter bytes ; va_start (ap, format); ; ; /* Call vfscanf(). Since we know that va_end won't do anything, we will -; * save the call and return the value directly. -; */ +; ** save the call and return the value directly. +; */ ; return vfscanf (f, format, ap); ; } ; diff --git a/libsrc/common/fseek.c b/libsrc/common/fseek.c index bd47383fd..5ad511ecd 100644 --- a/libsrc/common/fseek.c +++ b/libsrc/common/fseek.c @@ -1,9 +1,9 @@ /* - * fseek.c - * - * Christian Groessler, 2000-08-07 - * Ullrich von Bassewitz, 2004-05-12 - */ +** fseek.c +** +** Christian Groessler, 2000-08-07 +** Ullrich von Bassewitz, 2004-05-12 +*/ @@ -31,8 +31,8 @@ int __fastcall__ fseek (register FILE* f, long offset, int whence) } /* If we have a pushed back character, and whence is relative to the - * current position, correct the offset. - */ + ** current position, correct the offset. + */ if ((f->f_flags & _FPUSHBACK) && whence == SEEK_CUR) { --offset; } @@ -41,11 +41,11 @@ int __fastcall__ fseek (register FILE* f, long offset, int whence) res = lseek(f->f_fd, offset, whence); /* If the seek was successful. Discard any effects of the ungetc function, - * and clear the end-of-file indicator. Otherwise set the error indicator - * on the stream, and return -1. We will check for >= 0 here, because that - * saves some code, and we don't have files with 2 gigabytes in size - * anyway:-) - */ + ** and clear the end-of-file indicator. Otherwise set the error indicator + ** on the stream, and return -1. We will check for >= 0 here, because that + ** saves some code, and we don't have files with 2 gigabytes in size + ** anyway:-) + */ if (res >= 0) { f->f_flags &= ~(_FEOF | _FPUSHBACK); return 0; diff --git a/libsrc/common/fsetpos.c b/libsrc/common/fsetpos.c index 9f57ca415..14690f520 100644 --- a/libsrc/common/fsetpos.c +++ b/libsrc/common/fsetpos.c @@ -1,8 +1,8 @@ /* - * fsetpos.c - * - * Christian Groessler, 07-Aug-2000 - */ +** fsetpos.c +** +** Christian Groessler, 07-Aug-2000 +*/ diff --git a/libsrc/common/ftell.c b/libsrc/common/ftell.c index efc2e7ce0..3a4134c72 100644 --- a/libsrc/common/ftell.c +++ b/libsrc/common/ftell.c @@ -1,9 +1,9 @@ /* - * ftell.c - * - * Christian Groessler, 2000-08-07 - * Ullrich von Bassewitz, 2004-05-13 - */ +** ftell.c +** +** Christian Groessler, 2000-08-07 +** Ullrich von Bassewitz, 2004-05-13 +*/ @@ -34,8 +34,8 @@ long __fastcall__ ftell (register FILE* f) pos = lseek (f->f_fd, 0L, SEEK_CUR); /* If we didn't have an error, correct the return value in case we have - * a pushed back character. - */ + ** a pushed back character. + */ if (pos > 0 && (f->f_flags & _FPUSHBACK)) { --pos; } diff --git a/libsrc/common/getchar.c b/libsrc/common/getchar.c index 363be0200..913a4f5d6 100644 --- a/libsrc/common/getchar.c +++ b/libsrc/common/getchar.c @@ -1,8 +1,8 @@ /* - * getchar.c - * - * Ullrich von Bassewitz, 11.12.1998 - */ +** getchar.c +** +** Ullrich von Bassewitz, 11.12.1998 +*/ diff --git a/libsrc/common/getopt.c b/libsrc/common/getopt.c index 9faca33a2..34b13b1e6 100644 --- a/libsrc/common/getopt.c +++ b/libsrc/common/getopt.c @@ -1,17 +1,17 @@ /* - * This is part of a changed public domain getopt implementation that - * had the following text on top: - * - * I got this off net.sources from Henry Spencer. - * It is a public domain getopt(3) like in System V. - * I have made the following modifications: - * - * A test main program was added, ifdeffed by GETOPT. - * This main program is a public domain implementation - * of the getopt(1) program like in System V. The getopt - * program can be used to standardize shell option handling. - * e.g. cc -DGETOPT getopt.c -o getopt - */ +** This is part of a changed public domain getopt implementation that +** had the following text on top: +** +** I got this off net.sources from Henry Spencer. +** It is a public domain getopt(3) like in System V. +** I have made the following modifications: +** +** A test main program was added, ifdeffed by GETOPT. +** This main program is a public domain implementation +** of the getopt(1) program like in System V. The getopt +** program can be used to standardize shell option handling. +** e.g. cc -DGETOPT getopt.c -o getopt +*/ #include <stdio.h> #include <stdlib.h> diff --git a/libsrc/common/gets.c b/libsrc/common/gets.c index 4da352430..2936c70de 100644 --- a/libsrc/common/gets.c +++ b/libsrc/common/gets.c @@ -1,8 +1,8 @@ /* - * gets.c - * - * Ullrich von Bassewitz, 11.08.1998 - */ +** gets.c +** +** Ullrich von Bassewitz, 11.08.1998 +*/ diff --git a/libsrc/common/isgraph.s b/libsrc/common/isgraph.s index 7b1daa62e..bf94014ec 100644 --- a/libsrc/common/isgraph.s +++ b/libsrc/common/isgraph.s @@ -1,6 +1,6 @@ ; ; 1998-06-02, Ullrich von Bassewitz -; 2013-05-01, Greg King +; 2014-09-10, Greg King ; ; int isgraph (int c); ; @@ -9,7 +9,7 @@ .include "ctype.inc" _isgraph: - cpx #>0 ; Char range OK? + cpx #>$0000 ; Char range OK? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification diff --git a/libsrc/common/ispunct.s b/libsrc/common/ispunct.s index bf31efb1a..087532940 100644 --- a/libsrc/common/ispunct.s +++ b/libsrc/common/ispunct.s @@ -1,6 +1,6 @@ ; ; 1998-06-02, Ullrich von Bassewitz -; 2013-05-01, Greg King +; 2014-09-10, Greg King ; ; int ispunct (int c); ; @@ -9,7 +9,7 @@ .include "ctype.inc" _ispunct: - cpx #>0 ; Char range OK? + cpx #>$0000 ; Char range OK? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification diff --git a/libsrc/common/locale.c b/libsrc/common/locale.c index 3b9c7506a..078d54119 100644 --- a/libsrc/common/locale.c +++ b/libsrc/common/locale.c @@ -1,8 +1,8 @@ /* - * locale.c - * - * Ullrich von Bassewitz, 11.12.1998 - */ +** locale.c +** +** Ullrich von Bassewitz, 11.12.1998 +*/ diff --git a/libsrc/common/localtime.c b/libsrc/common/localtime.c index db2528444..cc6298f8c 100644 --- a/libsrc/common/localtime.c +++ b/libsrc/common/localtime.c @@ -55,9 +55,9 @@ struct tm* __fastcall__ localtime (const time_t* timep) } /* Since our ints are just 16 bits, split the given time into seconds, - * hours and days. Each of the values will fit in a 16 bit variable. - * The mktime routine will then do the rest. - */ + ** hours and days. Each of the values will fit in a 16 bit variable. + ** The mktime routine will then do the rest. + */ timebuf.tm_sec = t % 3600; timebuf.tm_min = 0; timebuf.tm_hour = (t / 3600) % 24; diff --git a/libsrc/common/malloc.s b/libsrc/common/malloc.s index 19add25a7..3118e2e56 100644 --- a/libsrc/common/malloc.s +++ b/libsrc/common/malloc.s @@ -10,17 +10,17 @@ ; ; void* malloc (size_t size) ; /* Allocate memory from the given heap. The function returns a pointer to the -; * allocated memory block or a NULL pointer if not enough memory is available. -; * Allocating a zero size block is not allowed. -; */ +; ** allocated memory block or a NULL pointer if not enough memory is available. +; ** Allocating a zero size block is not allowed. +; */ ; { ; struct freeblock* f; ; unsigned* p; ; ; ; /* Check for a size of zero, then add the administration space and round -; * up the size if needed. -; */ +; ** up the size if needed. +; */ ; if (size == 0) { ; return 0; ; } @@ -39,10 +39,10 @@ ; if (f) { ; ; /* We found a block big enough. If the block can hold just the -; * requested size, use the block in full. Beware: When slicing blocks, -; * there must be space enough to create a new one! If this is not the -; * case, then use the complete block. -; */ +; ** requested size, use the block in full. Beware: When slicing blocks, +; ** there must be space enough to create a new one! If this is not the +; ** case, then use the complete block. +; */ ; if (f->size - size < sizeof (struct freeblock)) { ; ; /* Use the actual size */ @@ -66,9 +66,9 @@ ; ; } else { ; -; /* We must slice the block found. Cut off space from the upper -; * end, so we can leave the actual free block chain intact. -; */ +; /* We must slice the block found. Cut off space from the upper +; ** end, so we can leave the actual free block chain intact. +; */ ; ; /* Decrement the size of the block */ ; f->size -= size; @@ -84,8 +84,8 @@ ; } else { ; ; /* We did not find a block big enough. Try to use new space from the -; * heap top. -; */ +; ** heap top. +; */ ; if (((unsigned) _hend) - ((unsigned) _hptr) < size) { ; /* Out of heap space */ ; return 0; diff --git a/libsrc/common/mktime.c b/libsrc/common/mktime.c index 691e61f6d..423727751 100644 --- a/libsrc/common/mktime.c +++ b/libsrc/common/mktime.c @@ -77,9 +77,9 @@ static unsigned char __fastcall__ IsLeapYear (unsigned Year) time_t __fastcall__ mktime (register struct tm* TM) /* Make a time in seconds since 1/1/1970 from the broken down time in TM. - * A call to mktime does also correct the time in TM to contain correct - * values. - */ +** A call to mktime does also correct the time in TM to contain correct +** values. +*/ { register div_t D; int Max; @@ -118,8 +118,8 @@ time_t __fastcall__ mktime (register struct tm* TM) TM->tm_mday += D.quot; /* Adjust month and year. This is an iterative process, since changing - * the month will change the allowed days for this month. - */ + ** the month will change the allowed days for this month. + */ while (1) { /* Make sure, month is in the range 0..11 */ @@ -131,8 +131,8 @@ time_t __fastcall__ mktime (register struct tm* TM) TM->tm_year += D.quot; /* Now check if mday is in the correct range, if not, correct month - * and eventually year and repeat the process. - */ + ** and eventually year and repeat the process. + */ if (TM->tm_mon == FEBRUARY && IsLeapYear (TM->tm_year + 1900)) { Max = 29; } else { @@ -154,18 +154,18 @@ time_t __fastcall__ mktime (register struct tm* TM) } /* Ok, all time/date fields are now correct. Calculate the days in this - * year. - */ + ** year. + */ TM->tm_yday = MonthDays[TM->tm_mon] + TM->tm_mday - 1; if (TM->tm_mon > FEBRUARY && IsLeapYear (TM->tm_year + 1900)) { ++TM->tm_yday; } /* Calculate days since 1/1/1970. In the complete epoch (1/1/1970 to - * somewhere in 2038) all years dividable by 4 are leap years, so - * dividing by 4 gives the days that must be added cause of leap years. - * (and the last leap year before 1970 was 1968) - */ + ** somewhere in 2038) all years dividable by 4 are leap years, so + ** dividing by 4 gives the days that must be added cause of leap years. + ** (and the last leap year before 1970 was 1968) + */ DayCount = ((unsigned) (TM->tm_year-70)) * 365U + (((unsigned) (TM->tm_year-(68+1))) / 4) + TM->tm_yday; diff --git a/libsrc/common/pmemalign.c b/libsrc/common/pmemalign.c index e1dc497a2..8f055a3fc 100644 --- a/libsrc/common/pmemalign.c +++ b/libsrc/common/pmemalign.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2004-2005 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -43,23 +43,23 @@ /* This is a very simple version of an aligned memory allocator. We will - * allocate a greater block, so that we can place the aligned block (that is - * returned) within it. We use our knowledge about the internal heap - * structures to free the unused parts of the bigger block (the two chunks - * below and above the aligned block). - */ +** allocate a greater block, so that we can place the aligned block (that is +** returned) within it. We use our knowledge about the internal heap +** structures to free the unused parts of the bigger block (the two chunks +** below and above the aligned block). +*/ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size) /* Allocate a block of memory with the given "size", which is aligned to a - * memory address that is a multiple of "alignment". "alignment" MUST NOT be - * zero, and MUST be a power of two; otherwise, this function will return - * EINVAL. The function returns ENOMEM if not enough memory is available - * to satisfy the request. "memptr" must point to a variable; that variable - * will return the address of the allocated memory. Use free() to release that - * allocated block. - */ +** memory address that is a multiple of "alignment". "alignment" MUST NOT be +** zero, and MUST be a power of two; otherwise, this function will return +** EINVAL. The function returns ENOMEM if not enough memory is available +** to satisfy the request. "memptr" must point to a variable; that variable +** will return the address of the allocated memory. Use free() to release that +** allocated block. +*/ { size_t rawsize; size_t uppersize; @@ -81,11 +81,11 @@ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size) } /* Augment the block size up to the alignment, and allocate memory. - * We don't need to account for the additional admin. data that's needed to - * manage the used block, because the block returned by malloc() has that - * overhead added one time; and, the worst thing that might happen is that - * we cannot free the upper and lower blocks. - */ + ** We don't need to account for the additional admin. data that's needed to + ** manage the used block, because the block returned by malloc() has that + ** overhead added one time; and, the worst thing that might happen is that + ** we cannot free the upper and lower blocks. + */ b = malloc (size + alignment); /* Handle out-of-memory */ @@ -95,26 +95,26 @@ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size) } /* Create (and return) a new pointer that points to the user-visible - * aligned block. - */ + ** aligned block. + */ u = *memptr = (struct usedblock*) (((unsigned)b + alignment) & ~alignment); /* Get a pointer to the (raw) upper block */ p = (struct usedblock*) ((char*)u + size); /* Get the raw-block pointer, which is located just below the visible - * unaligned block. The first word of this raw block is the total size - * of the block, including the admin. space. - */ + ** unaligned block. The first word of this raw block is the total size + ** of the block, including the admin. space. + */ b = (b-1)->start; rawsize = b->size; /* Check if we can free the space above the user block. That is the case - * if the size of the block is at least sizeof (struct freeblock) bytes, - * and the size of the remaining block is at least that size, too. - * If the upper block is smaller, then we just will pass it to the caller, - * together with the requested aligned block. - */ + ** if the size of the block is at least sizeof (struct freeblock) bytes, + ** and the size of the remaining block is at least that size, too. + ** If the upper block is smaller, then we just will pass it to the caller, + ** together with the requested aligned block. + */ uppersize = rawsize - (lowersize = (char*)p - (char*)b); if (uppersize >= sizeof (struct freeblock) && lowersize >= sizeof (struct freeblock)) { @@ -131,20 +131,20 @@ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size) } /* Check if we can free the space below the user block. That is the case - * if the size of the block is at least sizeof (struct freeblock) bytes, - * and the size of the remaining block is at least that size, too. If the - * lower block is smaller, we just will pass it to the caller, together - * with the requested aligned block. - * Beware: We need an additional struct usedblock, in the lower block, - * which is part of the block that is passed back to the caller. - */ + ** if the size of the block is at least sizeof (struct freeblock) bytes, + ** and the size of the remaining block is at least that size, too. If the + ** lower block is smaller, we just will pass it to the caller, together + ** with the requested aligned block. + ** Beware: We need an additional struct usedblock, in the lower block, + ** which is part of the block that is passed back to the caller. + */ lowersize = ((char*)u - (char*)b) - sizeof (struct usedblock); if ( lowersize >= sizeof (struct freeblock) && (rawsize - lowersize) >= sizeof (struct freeblock)) { /* b already points to the raw lower-block. - * Set up the usedblock structure. - */ + ** Set up the usedblock structure. + */ b->size = lowersize; b->start = b; @@ -159,11 +159,11 @@ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size) } /* u points to the user-visible block, while b points to the raw block, - * and rawsize contains the length of the raw block. Set up the usedblock - * structure, but beware: If we didn't free the lower block, then it is - * split; which means that we must use b to write the size, - * and u to write the start field. - */ + ** and rawsize contains the length of the raw block. Set up the usedblock + ** structure, but beware: If we didn't free the lower block, then it is + ** split; which means that we must use b to write the size, + ** and u to write the start field. + */ b->size = rawsize; (u-1)->start = b; diff --git a/libsrc/common/puts.c b/libsrc/common/puts.c index b0ad5180f..dbca603f2 100644 --- a/libsrc/common/puts.c +++ b/libsrc/common/puts.c @@ -1,8 +1,8 @@ /* - * puts.c - * - * Ullrich von Bassewitz, 11.08.1998 - */ +** puts.c +** +** Ullrich von Bassewitz, 11.08.1998 +*/ diff --git a/libsrc/common/qsort.c b/libsrc/common/qsort.c index 383962934..df02095ed 100644 --- a/libsrc/common/qsort.c +++ b/libsrc/common/qsort.c @@ -1,8 +1,8 @@ /* - * qsort.c - * - * Ullrich von Bassewitz, 09.12.1998 - */ +** qsort.c +** +** Ullrich von Bassewitz, 09.12.1998 +*/ @@ -14,8 +14,8 @@ static void QuickSort (register unsigned char* Base, int Lo, int Hi, register size_t Size, int (*Compare)(const void*, const void*)) /* Internal recursive function. Works with ints, but this shouldn't be - * a problem. - */ +** a problem. +*/ { int I, J; @@ -62,5 +62,3 @@ void __fastcall__ qsort (void* base, size_t nmemb, size_t size, - - diff --git a/libsrc/common/realloc.c b/libsrc/common/realloc.c index d9850b591..c47dbbb98 100644 --- a/libsrc/common/realloc.c +++ b/libsrc/common/realloc.c @@ -66,10 +66,10 @@ void* __fastcall__ realloc (void* block, register size_t size) } /* The word below the user block contains a pointer to the start of the - * raw memory block. The first word of this raw memory block is the full - * size of the block. Get a pointer to the real block, get the old block - * size. - */ + ** raw memory block. The first word of this raw memory block is the full + ** size of the block. Get a pointer to the real block, get the old block + ** size. + */ b = (((struct usedblock*) block) - 1)->start; oldsize = b->size; @@ -87,16 +87,16 @@ void* __fastcall__ realloc (void* block, register size_t size) } /* The given block was not located on top of the heap, or there's no - * room left. Try to allocate a new block and copy the data. - */ + ** room left. Try to allocate a new block and copy the data. + */ if (newblock = malloc (size)) { /* Adjust the old size to the user visible portion */ oldsize -= HEAP_ADMIN_SPACE; /* If the new block is larger than the old one, copy the old - * data only - */ + ** data only + */ if (size > oldsize) { size = oldsize; } @@ -110,4 +110,3 @@ void* __fastcall__ realloc (void* block, register size_t size) - diff --git a/libsrc/common/rewind.c b/libsrc/common/rewind.c index 583b779f9..a4cdfa97c 100644 --- a/libsrc/common/rewind.c +++ b/libsrc/common/rewind.c @@ -1,8 +1,8 @@ /* - * rewind.c - * - * Christian Groessler, 07-Aug-2000 - */ +** rewind.c +** +** Christian Groessler, 07-Aug-2000 +*/ diff --git a/libsrc/common/sleep.c b/libsrc/common/sleep.c index 3a8e8e2e0..b31174746 100644 --- a/libsrc/common/sleep.c +++ b/libsrc/common/sleep.c @@ -1,10 +1,10 @@ /* - * sleep.c - * - * Stefan Haubenthal, 2003-06-11 - * Ullrich von Bassewitz, 2003-06-12 - * - */ +** sleep.c +** +** Stefan Haubenthal, 2003-06-11 +** Ullrich von Bassewitz, 2003-06-12 +** +*/ diff --git a/libsrc/common/sscanf.s b/libsrc/common/sscanf.s index 5e580e91f..941f54e92 100644 --- a/libsrc/common/sscanf.s +++ b/libsrc/common/sscanf.s @@ -28,8 +28,8 @@ ParamSize: .res 1 ; Number of parameter bytes ; va_start (ap, format); ; ; /* Call vsscanf(). Since we know that va_end won't do anything, we will -; * save the call and return the value directly. -; */ +; ** save the call and return the value directly. +; */ ; return vsscanf (str, format, ap); ; } ; diff --git a/libsrc/common/strftime.c b/libsrc/common/strftime.c index 49d2677cf..25cfd0606 100644 --- a/libsrc/common/strftime.c +++ b/libsrc/common/strftime.c @@ -114,7 +114,7 @@ size_t __fastcall__ strftime (char* buf, size_t bufsize, const char* format, break; case 'I': - sprintf (arg, "%02d", tm->tm_hour % 12); + sprintf (arg, "%02d", (tm->tm_hour + 11) % 12 + 1); break; case 'M': diff --git a/libsrc/common/strqtok.c b/libsrc/common/strqtok.c new file mode 100644 index 000000000..1eb4fa80a --- /dev/null +++ b/libsrc/common/strqtok.c @@ -0,0 +1,86 @@ +/* +** strqtok() is like strtok(): It finds pieces of text, in a string, that are +** surrounded by given delimiter characters. It returns each piece, in turn, +** as a string, until every piece has been found. Then, it returns NULL. But, +** strqtok() recognizes quotation marks. A mark makes delimiters look ordinary +** until another quotation mark is seen. That allows us to include delimiters +** in tokens. (This version doesn't allow escaped quotation marks.) +** +** 2014-04-19, Daniel Serpell +** 2014-04-21, Paul Foerster +** 2014-04-25, Greg King +*/ + + +#include <string.h> + + +char* __fastcall__ strqtok (register char* s1, const char* s2) +{ + static char c; + static char* start; + static char* next = ""; + + if (s1 == NULL) { + s1 = next; + if (c == '\"') { + goto inQuote; + } + } + + /* Search for the start of a token. */ + while (strchr (s2, c = *s1)) { + if (c == '\0') { + /* No more tokens. */ + return NULL; + } + ++s1; + } + if (c == '\"') { + goto skipQuote; + } + + /* Save the start of the token. */ + start = s1; + + /* Search for the end of a non-quoted token. */ + while ((c = *s1) != '\"' && !strchr (s2, c)) { + ++s1; + } + if (c == '\0') { + /* The end of the last token is the end of the token list; + ** don't go beyond it. + */ + goto found; + } + + /* (A possible begin-quote mark will be rememberred.) */ + goto terminate; + + skipQuote: + ++s1; + + inQuote: + /* Don't let a quote mark be rememberred. */ + c = '\0'; + + /* Save the start of the token. */ + start = s1; + + /* Search for the end of a quoted token. */ + if ((s1 = strchr (s1, '\"')) == NULL) { + /* The quoted token ended with '\0'; therefore, point to a '\0', + ** so that the next call will return NULL. + */ + next = ""; + return start; + } + + terminate: + *s1 = '\0'; + ++s1; + + found: + next = s1; + return start; +} diff --git a/libsrc/common/strtok.c b/libsrc/common/strtok.c index 30e3e81e4..47a2829ed 100644 --- a/libsrc/common/strtok.c +++ b/libsrc/common/strtok.c @@ -1,8 +1,8 @@ /* - * strtok.c - * - * Ullrich von Bassewitz, 11.12.1998 - */ +** strtok.c +** +** Ullrich von Bassewitz, 11.12.1998 +*/ @@ -43,8 +43,8 @@ char* __fastcall__ strtok (register char* s1, const char* s2) } /* Search the address of the first element in s1 that equals none - * of the characters in s2. - */ + ** of the characters in s2. + */ while ((c = *s1) && strchr (s2, c) != 0) { ++s1; } diff --git a/libsrc/common/strtol.c b/libsrc/common/strtol.c index f3ce08a35..bf328edfd 100644 --- a/libsrc/common/strtol.c +++ b/libsrc/common/strtol.c @@ -33,8 +33,8 @@ long __fastcall__ strtol (const char* nptr, char** endptr, int base) } /* If base is zero, we may have a 0 or 0x prefix. If base is 16, we may - * have a 0x prefix. - */ + ** have a 0x prefix. + */ if (base == 0) { if (*S == '0') { ++S; @@ -52,8 +52,8 @@ long __fastcall__ strtol (const char* nptr, char** endptr, int base) } /* Determine the maximum valid number and (if the number is equal to this - * value) the maximum valid digit. - */ + ** value) the maximum valid digit. + */ if (Minus) { MaxVal = LONG_MIN; } else { @@ -98,8 +98,8 @@ long __fastcall__ strtol (const char* nptr, char** endptr, int base) } /* Store the end pointer. If no conversion was performed, the value of - * nptr is returned in endptr. - */ + ** nptr is returned in endptr. + */ if (endptr) { if (CvtCount > 0) { *endptr = (char*) S; diff --git a/libsrc/common/strtoul.c b/libsrc/common/strtoul.c index 54466db36..a186fc681 100644 --- a/libsrc/common/strtoul.c +++ b/libsrc/common/strtoul.c @@ -33,8 +33,8 @@ unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base) } /* If base is zero, we may have a 0 or 0x prefix. If base is 16, we may - * have a 0x prefix. - */ + ** have a 0x prefix. + */ if (base == 0) { if (*S == '0') { ++S; @@ -52,8 +52,8 @@ unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base) } /* Determine the maximum valid number and (if the number is equal to this - * value) the maximum valid digit. - */ + ** value) the maximum valid digit. + */ MaxDigit = ULONG_MAX % base; MaxVal = ULONG_MAX / base; @@ -93,8 +93,8 @@ unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base) } /* Store the end pointer. If no conversion was performed, the value of - * nptr is returned in endptr. - */ + ** nptr is returned in endptr. + */ if (endptr) { if (CvtCount > 0) { *endptr = (char*) S; diff --git a/libsrc/common/strxfrm.c b/libsrc/common/strxfrm.c index 8bf9795b9..fb0891919 100644 --- a/libsrc/common/strxfrm.c +++ b/libsrc/common/strxfrm.c @@ -1,8 +1,8 @@ /* - * strxfrm.c - * - * Ullrich von Bassewitz, 11.12.1998 - */ +** strxfrm.c +** +** Ullrich von Bassewitz, 11.12.1998 +*/ diff --git a/libsrc/common/system.c b/libsrc/common/system.c index 6626ace87..01dec1ad8 100644 --- a/libsrc/common/system.c +++ b/libsrc/common/system.c @@ -1,9 +1,9 @@ /* - * system.c - * - * Stefan Haubenthal, 2003-05-26 - * Ullrich von Bassewitz, 2003-05-27 - */ +** system.c +** +** Stefan Haubenthal, 2003-05-26 +** Ullrich von Bassewitz, 2003-05-27 +*/ #include <stdio.h> #include <stdlib.h> diff --git a/libsrc/common/vfscanf.s b/libsrc/common/vfscanf.s index 2123085c8..c7d6e5564 100644 --- a/libsrc/common/vfscanf.s +++ b/libsrc/common/vfscanf.s @@ -31,9 +31,9 @@ d: .addr _fgetc ; GET ; /* Standard C function */ ; { ; /* Initialize the data struct. We do only need the given file as user data, -; * because the (getfunc) and (ungetfunc) functions are crafted so that they -; * match the standard-I/O fgetc() and ungetc(). -; */ +; ** because the (getfunc) and (ungetfunc) functions are crafted so that they +; ** match the standard-I/O fgetc() and ungetc(). +; */ ; static struct scanfdata d = { ; ( getfunc) fgetc, ; (ungetfunc) ungetc diff --git a/libsrc/common/vsscanf.s b/libsrc/common/vsscanf.s index a04404a0a..335712b20 100644 --- a/libsrc/common/vsscanf.s +++ b/libsrc/common/vsscanf.s @@ -3,7 +3,7 @@ ; /* Standard C function */ ; ; 2004-11-28, Ullrich von Bassewitz -; 2004-12-21, Greg King +; 2014-09-10, Greg King ; .export _vsscanf @@ -65,7 +65,7 @@ ; Return EOF if we are at the end of the string bne L1 - lda #$FF + lda #<-1 tax rts @@ -74,17 +74,17 @@ L1: tax ; Save return value tya ; Low byte of index ldy #SSCANFDATA::INDEX - add #<1 + add #<$0001 sta (ptr1),y iny lda (ptr1),y - adc #>1 + adc #>$0001 sta (ptr1),y ; Return the char just read txa - ldx #>0 + ldx #>$0000 rts .endproc @@ -94,8 +94,8 @@ L1: tax ; Save return value ; /* Push back a character onto the input stream */ ; { ; /* We do assume here that the _scanf routine will not push back anything -; * not read, so we can ignore c safely and won't check the index. -; */ +; ** not read, so we can ignore c safely and won't check the index. +; */ ; --d->index; ; return c; ; } @@ -111,11 +111,11 @@ L1: tax ; Save return value ldy #SSCANFDATA::INDEX lda (ptr1),y - sub #<1 + sub #<$0001 sta (ptr1),y iny lda (ptr1),y - sbc #>1 + sbc #>$0001 sta (ptr1),y ; Return c @@ -129,8 +129,8 @@ L1: tax ; Save return value ; /* Standard C function */ ; { ; /* Initialize the data structs. The sscanfdata struct will be passed back -; * to the get and unget functions by _scanf(). -; */ +; ** to the get and unget functions by _scanf(). +; */ ; static struct sscanfdata sd; ; static const struct scanfdata d = { ; ( getfunc) get, diff --git a/libsrc/conio/vcscanf.s b/libsrc/conio/vcscanf.s index eb1c5a43a..67d5f664f 100644 --- a/libsrc/conio/vcscanf.s +++ b/libsrc/conio/vcscanf.s @@ -1,7 +1,7 @@ ; ; int fastcall vcscanf(const char* format, va_list ap); ; -; 2005-01-02, Greg King +; 2014-09-10, Greg King ; .export _vcscanf @@ -44,7 +44,7 @@ get: ldx pushed ; Return the old, pushed-back character (instead of getting a new one). ; - dex ; ldx #>0 + dex ; ldx #>$0000 stx pushed lda back rts @@ -58,7 +58,7 @@ L1: jsr _cgetc pha jsr _cputc pla - ldx #>0 + ldx #>$0000 rts diff --git a/libsrc/dbg/dbg.c b/libsrc/dbg/dbg.c index 00ff28722..8b09484f6 100644 --- a/libsrc/dbg/dbg.c +++ b/libsrc/dbg/dbg.c @@ -1,9 +1,9 @@ /* - * dbg.c - * - * Ullrich von Bassewitz, 08.08.1998 - * - */ +** dbg.c +** +** Ullrich von Bassewitz, 08.08.1998 +** +*/ @@ -335,8 +335,8 @@ BreakPoint* DbgGetBreakSlot (void); BreakPoint* DbgIsBreak (unsigned Addr); /* Check if there is a user breakpoint at the given address, if so, return - * a pointer to the slot, else return 0. - */ +** a pointer to the slot, else return 0. +*/ @@ -729,8 +729,8 @@ static void DbgResetTmpBreaks (void) static unsigned char DbgTmpBreaksOk (void) /* Check if the temporary breakpoints can be set, if so, return 1, if not, - * reset them all and return 0. - */ +** reset them all and return 0. +*/ { unsigned char i; BreakPoint* B = DbgBreaks; @@ -755,8 +755,8 @@ static unsigned char DbgTmpBreaksOk (void) static unsigned AsmBack (unsigned mem, unsigned char lines) /* Go back in the assembler window the given number of lines (calculate - * new start address). - */ +** new start address). +*/ { unsigned cur; unsigned adr [32]; @@ -776,8 +776,8 @@ static unsigned AsmBack (unsigned mem, unsigned char lines) return adr [(in - lines - 1) & 0x1F]; } else { /* The requested address is inside an instruction, go back - * one more byte and try again. - */ + ** one more byte and try again. + */ ++offs; break; } @@ -1347,8 +1347,8 @@ static void SingleStep (char StepInto) case OPC_BNE: case OPC_BEQ: /* Be sure not to set the breakpoint twice if this is a jump to - * the following instruction. - */ + ** the following instruction. + */ Offs = ((signed char*)brk_pc)[1]; if (Offs) { DbgSetTmpBreak (brk_pc + Offs + 2); @@ -1491,8 +1491,8 @@ void DbgEntry (void) } /* Only initialize variables here, don't do a display update. The actual - * display update will be done while waiting for user input. - */ + ** display update will be done while waiting for user input. + */ AsmHome (); UpdateReg (); /* Must update this (static later) */ StackHome (); diff --git a/libsrc/em/em-kernel.s b/libsrc/em/em-kernel.s index 21203d250..c982dac88 100644 --- a/libsrc/em/em-kernel.s +++ b/libsrc/em/em-kernel.s @@ -94,8 +94,8 @@ copy: lda (ptr1),y ;---------------------------------------------------------------------------- ; unsigned char em_uninstall (void); ; /* Uninstall the currently loaded driver and return an error code. -; * Note: This call does not free allocated memory. -; */ +; ** Note: This call does not free allocated memory. +; */ _em_uninstall: jsr emd_uninstall ; Call driver routine diff --git a/libsrc/em/em_commit.s b/libsrc/em/em_commit.s index 66af02df9..8be970b39 100644 --- a/libsrc/em/em_commit.s +++ b/libsrc/em/em_commit.s @@ -3,11 +3,11 @@ ; ; void em_commit (void); ; /* Commit changes in the memory window to extended storage. If the contents -; * of the memory window have been changed, these changes may be lost if -; * em_map, em_copyfrom or em_copyto are called without calling em_commit -; * first. Note: Not calling em_commit does not mean that the changes are -; * discarded, it does just mean that some drivers will discard the changes. -; */ +; ** of the memory window have been changed, these changes may be lost if +; ** em_map, em_copyfrom or em_copyto are called without calling em_commit +; ** first. Note: Not calling em_commit does not mean that the changes are +; ** discarded, it does just mean that some drivers will discard the changes. +; */ .include "em-kernel.inc" diff --git a/libsrc/em/em_map.s b/libsrc/em/em_map.s index 9897243a3..825d68efc 100644 --- a/libsrc/em/em_map.s +++ b/libsrc/em/em_map.s @@ -3,8 +3,8 @@ ; ; void* __fastcall__ em_map (unsigned page); ; /* Unmap the current page from memory and map a new one. The function returns -; * a pointer to the location of the page in memory. -; */ +; ** a pointer to the location of the page in memory. +; */ .include "em-kernel.inc" diff --git a/libsrc/em/em_use.s b/libsrc/em/em_use.s index 8e4d57df0..e4fb7722e 100644 --- a/libsrc/em/em_use.s +++ b/libsrc/em/em_use.s @@ -3,12 +3,12 @@ ; ; void* __fastcall__ em_use (unsigned page); ; /* Tell the driver that the memory window is associated with a given page. -; * This call is very similar to em_map. The difference is that the driver -; * does not necessarily transfer the current contents of the extended -; * memory into the returned window. If you're going to just write to the -; * window and the current contents of the window are invalid or no longer -; * use, this call may perform better than em_map. -; */ +; ** This call is very similar to em_map. The difference is that the driver +; ** does not necessarily transfer the current contents of the extended +; ** memory into the returned window. If you're going to just write to the +; ** window and the current contents of the window are invalid or no longer +; ** use, this call may perform better than em_map. +; */ .include "em-kernel.inc" diff --git a/libsrc/geos-apple/targetutil/Makefile.inc b/libsrc/geos-apple/targetutil/Makefile.inc index 01ae3f55c..fbe31981c 100644 --- a/libsrc/geos-apple/targetutil/Makefile.inc +++ b/libsrc/geos-apple/targetutil/Makefile.inc @@ -1,14 +1,14 @@ -DEPS += ../wrk/$(TARGET)/convert.d +DEPS += ../libwrk/$(TARGET)/convert.d -../wrk/$(TARGET)/convert.o: TARGET = apple2enh +../libwrk/$(TARGET)/convert.o: TARGET = apple2enh -../wrk/$(TARGET)/convert.o: $(SRCDIR)/targetutil/convert.c | ../wrk/$(TARGET) +../libwrk/$(TARGET)/convert.o: $(SRCDIR)/targetutil/convert.c | ../libwrk/$(TARGET) $(COMPILE_recipe) ../lib/apple2enh.lib: @$(MAKE) --no-print-directory apple2enh -../targetutil/convert.system: ../wrk/$(TARGET)/convert.o ../lib/apple2enh.lib | ../targetutil +../targetutil/convert.system: ../libwrk/$(TARGET)/convert.o ../lib/apple2enh.lib | ../targetutil $(LD65) -o $@ -C apple2enh-system.cfg $^ $(TARGET): ../targetutil/convert.system diff --git a/libsrc/geos-cbm/emd/geos-vdc.s b/libsrc/geos-cbm/emd/geos-vdc.s index 60a805c4e..791d2a0a8 100644 --- a/libsrc/geos-cbm/emd/geos-vdc.s +++ b/libsrc/geos-cbm/emd/geos-vdc.s @@ -10,11 +10,13 @@ .include "em-error.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _geos_vdc_emd ; Driver signature diff --git a/libsrc/geos-cbm/joy/geos-stdjoy.s b/libsrc/geos-cbm/joy/geos-stdjoy.s index 9fb5461bb..6afe46092 100644 --- a/libsrc/geos-cbm/joy/geos-stdjoy.s +++ b/libsrc/geos-cbm/joy/geos-stdjoy.s @@ -11,12 +11,14 @@ .include "geossym.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" - + module_header _geos_stdjoy_joy + ; Driver signature .byte $6A, $6F, $79 ; "joy" diff --git a/libsrc/geos-cbm/tgi/geos-tgi.s b/libsrc/geos-cbm/tgi/geos-tgi.s index 617e322ff..5a1af65e4 100644 --- a/libsrc/geos-cbm/tgi/geos-tgi.s +++ b/libsrc/geos-cbm/tgi/geos-tgi.s @@ -10,8 +10,10 @@ .include "jumptab.inc" .include "geossym.inc" .include "geossym2.inc" - + .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Constants @@ -33,7 +35,7 @@ VDC_DATA = 31 ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. -.segment "JUMPTABLE" + module_header _geos_tgi_tgi ; First part of the header is a structure that has a magic signature, ; and defines the capabilities of the driver. diff --git a/libsrc/geos-common/common/_afailed.c b/libsrc/geos-common/common/_afailed.c index e446cf565..2448534c0 100644 --- a/libsrc/geos-common/common/_afailed.c +++ b/libsrc/geos-common/common/_afailed.c @@ -1,8 +1,8 @@ /* - * _afailed.c - * - * Maciej 'YTM/Elysium' Witkowiak 28.10.2001 - */ +** _afailed.c +** +** Maciej 'YTM/Elysium' Witkowiak 28.10.2001 +*/ #include <stdio.h> #include <stdlib.h> diff --git a/libsrc/geos-common/common/_poserror.c b/libsrc/geos-common/common/_poserror.c index e0a7723a1..eeb3f368e 100644 --- a/libsrc/geos-common/common/_poserror.c +++ b/libsrc/geos-common/common/_poserror.c @@ -1,8 +1,8 @@ /* - * _poserror.c - * - * Maciej 'YTM/Elysium' Witkowiak, 25.04.2003 - */ +** _poserror.c +** +** Maciej 'YTM/Elysium' Witkowiak, 25.04.2003 +*/ #include <stdio.h> #include <string.h> diff --git a/libsrc/geos-common/common/abort.c b/libsrc/geos-common/common/abort.c index 9bc839c7a..b7cb35eb9 100644 --- a/libsrc/geos-common/common/abort.c +++ b/libsrc/geos-common/common/abort.c @@ -1,8 +1,8 @@ /* - * abort.c - * - * Maciej 'YTM/Elysium' Witkowiak 15.7.2001 - */ +** abort.c +** +** Maciej 'YTM/Elysium' Witkowiak 15.7.2001 +*/ #include <stdlib.h> #include <geos.h> diff --git a/libsrc/geos-common/common/perror.c b/libsrc/geos-common/common/perror.c index 022968bf2..5c6ec2117 100644 --- a/libsrc/geos-common/common/perror.c +++ b/libsrc/geos-common/common/perror.c @@ -1,8 +1,8 @@ /* - * perror.c - * - * Maciej 'YTM/Elysium' Witkowiak, 15.07.2001 - */ +** perror.c +** +** Maciej 'YTM/Elysium' Witkowiak, 15.07.2001 +*/ #include <stdio.h> #include <string.h> diff --git a/libsrc/geos-common/common/sleep.c b/libsrc/geos-common/common/sleep.c index 94bd9fe79..ea18f8ead 100644 --- a/libsrc/geos-common/common/sleep.c +++ b/libsrc/geos-common/common/sleep.c @@ -1,9 +1,9 @@ /* - * sleep.c - * - * Maciej 'YTM/Elysium' Witkowiak, 16.08.2003 - * - */ +** sleep.c +** +** Maciej 'YTM/Elysium' Witkowiak, 16.08.2003 +** +*/ #include <geos.h> diff --git a/libsrc/geos-common/dlgbox/messagebox.c b/libsrc/geos-common/dlgbox/messagebox.c index a8774c3c0..533267be1 100644 --- a/libsrc/geos-common/dlgbox/messagebox.c +++ b/libsrc/geos-common/dlgbox/messagebox.c @@ -1,10 +1,9 @@ - /* - * char MessageBox (char mode, const char *format, ...) - * - * Maciej 'YTM/Elysium' Witkowiak, 17.08.2003 - * - */ +** char MessageBox (char mode, const char *format, ...) +** +** Maciej 'YTM/Elysium' Witkowiak, 17.08.2003 +** +*/ #include <geos.h> #include <stdio.h> diff --git a/libsrc/geos-common/drivers/mcbdefault.s b/libsrc/geos-common/drivers/mcbdefault.s index 5b5806685..2576f6aad 100644 --- a/libsrc/geos-common/drivers/mcbdefault.s +++ b/libsrc/geos-common/drivers/mcbdefault.s @@ -32,26 +32,32 @@ hide := MouseOff show := MouseUp +; -------------------------------------------------------------------------- +; Prepare to move the mouse pointer. Always called with interrupts disabled. + +prep: + ; Fall through + +; -------------------------------------------------------------------------- +; Draw the mouse pointer. Always called with interrupts disabled. + +draw: + ; Fall through + ; -------------------------------------------------------------------------- ; Move the mouse pointer X position to the value in .XA. Always called with ; interrupts disabled. -.proc movex - - rts - -.endproc +movex: + ; Fall through ; -------------------------------------------------------------------------- ; Move the mouse pointer Y position to the value in .XA. Always called with ; interrupts disabled. -.proc movey - +movey: rts -.endproc - ; -------------------------------------------------------------------------- ; Callback structure @@ -60,7 +66,7 @@ show := MouseUp _mouse_def_callbacks: .addr hide .addr show + .addr prep + .addr draw .addr movex .addr movey - - diff --git a/libsrc/geos-common/system/crt0.s b/libsrc/geos-common/system/crt0.s index 0e82031af..47cec74f2 100644 --- a/libsrc/geos-common/system/crt0.s +++ b/libsrc/geos-common/system/crt0.s @@ -1,5 +1,5 @@ ; -; Startup code for geos +; Startup code for GEOS ; ; Maciej 'YTM/Elysium' Witkowiak ; 26.10.99, 10.3.2000, 15.8.2001, 23.12.2002 @@ -23,9 +23,9 @@ .segment "STARTUP" ; GEOS 64/128 initializes the screen before starting an application while -; Apple GEOS does not. In order to provide identical startup conditions -; we initialize the screen here on Apple GEOS. For the same reason we set -; the pattern and dispBufferOn even on GEOS 64/128 although we don't use +; Apple GEOS does not. In order to provide identical startup conditions, +; we initialize the screen here, on Apple GEOS. For the same reason, we set +; the pattern and dispBufferOn, even on GEOS 64/128, although we don't use ; them here. lda #2 ; Checkerboard pattern @@ -44,23 +44,23 @@ jsr zerobss -; Setup stack. +; Set up the stack. lda #<(__STACKADDR__ + __STACKSIZE__) ldx #>(__STACKADDR__ + __STACKSIZE__) sta sp stx sp+1 -; Call module constructors. +; Call the module constructors. jsr initlib -; Push arguments and call main(). +; Push the command-line arguments; and, call main(). cli jsr callmain -; Call module destructors. +; Call the module destructors. _exit: jsr donelib diff --git a/libsrc/geos-common/system/systime.c b/libsrc/geos-common/system/systime.c index 75b0fabb7..5eb87fef8 100644 --- a/libsrc/geos-common/system/systime.c +++ b/libsrc/geos-common/system/systime.c @@ -1,8 +1,8 @@ /* - * systime.c - * - * Maciej 'YTM/Elysium' Witkowiak, 22.11.2002 - */ +** systime.c +** +** Maciej 'YTM/Elysium' Witkowiak, 22.11.2002 +*/ #include <time.h> #include <geos.h> diff --git a/libsrc/joystick/joy-kernel.s b/libsrc/joystick/joy-kernel.s index d21727089..1ba3056d8 100644 --- a/libsrc/joystick/joy-kernel.s +++ b/libsrc/joystick/joy-kernel.s @@ -116,8 +116,8 @@ set: sta joy_vectors,x ;---------------------------------------------------------------------------- ; unsigned char joy_uninstall (void); ; /* Uninstall the currently loaded driver. Note: This call does not free -; * allocated memory. -; */ +; ** allocated memory. +; */ _joy_uninstall: lda #$60 ; RTS opcode diff --git a/libsrc/lynx/crt0.s b/libsrc/lynx/crt0.s index 116b39f76..725f74ebd 100644 --- a/libsrc/lynx/crt0.s +++ b/libsrc/lynx/crt0.s @@ -9,9 +9,9 @@ ; ; *** ; -; Startup code for cc65 (Lynx version). Based on Atari 8-bit startup +; Startup code for cc65 (Lynx version). Based on the Atari 8-bit startup ; code structure. The C stack is located at the end of the RAM memory -; segment and grows downward. Bastian Schick's executable header is put +; segment, and grows downward. Bastian Schick's executable header is put ; on the front of the fully linked binary (see EXEHDR segment.) ; @@ -44,19 +44,19 @@ MikeyInitData: .byte $9e,$18,$68,$1f,$00,$00,$00,$00,$00,$ff,$1a,$1b,$04,$0d,$2 .segment "STARTUP" -; set up system +; Set up the system. sei cld ldx #$FF txs -; init bank switching +; Init the bank switching. lda #$C sta MAPCTL ; $FFF9 -; disable all timer interrupts +; Disable all timer interrupts. lda #$80 trb TIM0CTLA @@ -67,24 +67,24 @@ MikeyInitData: .byte $9e,$18,$68,$1f,$00,$00,$00,$00,$00,$ff,$1a,$1b,$04,$0d,$2 trb TIM6CTLA trb TIM7CTLA -; disable TX/RX IRQ, set to 8E1 +; Disable the TX/RX IRQ; set to 8E1. lda #%11101 sta SERCTL -; clear all pending interrupts +; Clear all pending interrupts. lda INTSET sta INTRST -; setup the stack +; Set up the stack. lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) sta sp lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) sta sp+1 -; Init Mickey +; Init Mickey. ldx #.sizeof(MikeyInitReg)-1 mloop: ldy MikeyInitReg,x @@ -93,7 +93,7 @@ mloop: ldy MikeyInitReg,x dex bpl mloop -; these are RAM-shadows of read only regs +; These are RAM-shadows of read-only regs. ldx #$1b stx __iodat @@ -102,7 +102,7 @@ mloop: ldy MikeyInitReg,x ldx #$d stx __viddma -; Init Suzy +; Init Suzy. ldx #.sizeof(SuzyInitReg)-1 sloop: ldy SuzyInitReg,x @@ -115,19 +115,19 @@ sloop: ldy SuzyInitReg,x sta __sprsys cli -; Clear the BSS data +; Clear the BSS data. jsr zerobss -; Call module constructors +; Call the module constructors. jsr initlib -; Push arguments and call main +; Push the command-line arguments; and, call main(). jsr callmain -; Call module destructors. This is also the _exit entry. +; Call the module destructors. This is also the exit() entry. _exit: jsr donelib ; Run module destructors diff --git a/libsrc/lynx/defdir.s b/libsrc/lynx/defdir.s index 5ab61ac14..08358563b 100644 --- a/libsrc/lynx/defdir.s +++ b/libsrc/lynx/defdir.s @@ -7,7 +7,7 @@ .import __STARTOFDIRECTORY__ .import __RAM_START__ .import __CODE_SIZE__,__DATA_SIZE__,__RODATA_SIZE__ - .import __STARTUP_SIZE__,__INIT_SIZE__ + .import __STARTUP_SIZE__,__INIT_SIZE__,__LOWCODE_SIZE__ .import __BLOCKSIZE__ .export __DEFDIR__: absolute = 1 @@ -21,7 +21,7 @@ off0=__STARTOFDIRECTORY__+(__DIRECTORY_END__-__DIRECTORY_START__) blocka=off0/__BLOCKSIZE__ ; Entry 0 - first executable block0=off0/__BLOCKSIZE__ -len0=__STARTUP_SIZE__+__INIT_SIZE__+__CODE_SIZE__+__DATA_SIZE__+__RODATA_SIZE__ +len0=__STARTUP_SIZE__+__INIT_SIZE__+__CODE_SIZE__+__DATA_SIZE__+__RODATA_SIZE__+__LOWCODE_SIZE__ .byte <block0 .word off0 & (__BLOCKSIZE__ - 1) .byte $88 diff --git a/libsrc/lynx/joy/lynx-stdjoy.s b/libsrc/lynx/joy/lynx-stdjoy.s index da7b4612c..114647072 100644 --- a/libsrc/lynx/joy/lynx-stdjoy.s +++ b/libsrc/lynx/joy/lynx-stdjoy.s @@ -14,12 +14,13 @@ .include "lynx.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _lynx_stdjoy_joy ; Driver signature diff --git a/libsrc/lynx/ser/lynx-comlynx.s b/libsrc/lynx/ser/lynx-comlynx.s index acd91a999..1fd24ad94 100644 --- a/libsrc/lynx/ser/lynx-comlynx.s +++ b/libsrc/lynx/ser/lynx-comlynx.s @@ -9,10 +9,13 @@ .include "ser-kernel.inc" .include "ser-error.inc" + .macpack module + + ; ------------------------------------------------------------------------ ; Header. Includes jump table - .segment "JUMPTABLE" + module_header _lynx_comlynx_ser ; Driver signature .byte $73, $65, $72 ; "ser" diff --git a/libsrc/lynx/tgi/lynx-160-102-16.s b/libsrc/lynx/tgi/lynx-160-102-16.s index ef2eabf1d..e6659631b 100644 --- a/libsrc/lynx/tgi/lynx-160-102-16.s +++ b/libsrc/lynx/tgi/lynx-160-102-16.s @@ -16,11 +16,13 @@ .include "lynx.inc" .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. -.segment "JUMPTABLE" + module_header _lynx_160_102_16_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver diff --git a/libsrc/mouse/mouse_buttons.s b/libsrc/mouse/mouse_buttons.s index 459c0a8e6..afca40c37 100644 --- a/libsrc/mouse/mouse_buttons.s +++ b/libsrc/mouse/mouse_buttons.s @@ -3,8 +3,8 @@ ; ; unsigned char mouse_buttons (void); ; /* Return a bit mask encoding the states of the mouse buttons. Use the -; * MOUSE_BTN_XXX flags to decode a specific button. -; */ +; ** MOUSE_BTN_XXX flags to decode a specific button. +; */ ; .include "mouse-kernel.inc" diff --git a/libsrc/mouse/mouse_hide.s b/libsrc/mouse/mouse_hide.s index 81b3573b7..1f565867f 100644 --- a/libsrc/mouse/mouse_hide.s +++ b/libsrc/mouse/mouse_hide.s @@ -3,9 +3,9 @@ ; ; void mouse_hide (void); ; /* Hide the mouse. The function manages a counter and may be called more than -; * once. For each call to mouse_hide there must be a call to mouse_show to make -; * the mouse visible again. -; */ +; ** once. For each call to mouse_hide there must be a call to mouse_show to make +; ** the mouse visible again. +; */ ; .include "mouse-kernel.inc" diff --git a/libsrc/mouse/mouse_ioctl.s b/libsrc/mouse/mouse_ioctl.s index 31a8ba791..52d201c48 100644 --- a/libsrc/mouse/mouse_ioctl.s +++ b/libsrc/mouse/mouse_ioctl.s @@ -3,8 +3,8 @@ ; ; unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data); ; /* Call the driver specific ioctl function. NON PORTABLE! Returns an error -; * code. -; */ +; ** code. +; */ ; .import popa diff --git a/libsrc/mouse/mouse_move.s b/libsrc/mouse/mouse_move.s index 2245221f6..b25716b37 100644 --- a/libsrc/mouse/mouse_move.s +++ b/libsrc/mouse/mouse_move.s @@ -3,10 +3,10 @@ ; ; void __fastcall__ mouse_move (int x, int y); ; /* Set the mouse cursor to the given position. If a mouse cursor is defined -; * and currently visible, the mouse cursor is also moved. -; * NOTE: This function does not check if the given position is valid and -; * inside the bounding box. -; */ +; ** and currently visible, the mouse cursor is also moved. +; ** NOTE: This function does not check if the given position is valid and +; ** inside the bounding box. +; */ ; .import incsp2 diff --git a/libsrc/mouse/mouse_setbox.s b/libsrc/mouse/mouse_setbox.s index d211289b5..6dafc8365 100644 --- a/libsrc/mouse/mouse_setbox.s +++ b/libsrc/mouse/mouse_setbox.s @@ -3,19 +3,19 @@ ; ; void __fastcall__ mouse_setbox (const struct mouse_box* box); ; /* Set the bounding box for the mouse pointer movement. The mouse X and Y -; * coordinates will never go outside the given box. -; * NOTE: The function does *not* check if the mouse is currently inside the -; * given margins. The proper way to use this function therefore is: -; * -; * - Hide the mouse -; * - Set the bounding box -; * - Place the mouse at the desired position -; * - Show the mouse again. -; * -; * NOTE2: When setting the box to something that is larger than the actual -; * screen, the positioning of the mouse cursor can fail. If such margins -; * are really what you want, you have to use your own cursor routines. -; */ +; ** coordinates will never go outside the given box. +; ** NOTE: The function does *not* check if the mouse is currently inside the +; ** given margins. The proper way to use this function therefore is: +; ** +; ** - Hide the mouse +; ** - Set the bounding box +; ** - Place the mouse at the desired position +; ** - Show the mouse again. +; ** +; ** NOTE2: When setting the box to something that is larger than the actual +; ** screen, the positioning of the mouse cursor can fail. If such margins +; ** are really what you want, you have to use your own cursor routines. +; */ ; ; diff --git a/libsrc/nes/Makefile.inc b/libsrc/nes/Makefile.inc index 1be43497f..f1dcbf18e 100644 --- a/libsrc/nes/Makefile.inc +++ b/libsrc/nes/Makefile.inc @@ -1,8 +1,8 @@ -../tgi/nes-64-56-2.tgi: ../wrk/nes/clrscr.o \ - ../wrk/nes/cputc.o \ - ../wrk/nes/get_tv.o \ - ../wrk/nes/gotoxy.o \ - ../wrk/nes/popa.o \ - ../wrk/nes/ppu.o \ - ../wrk/nes/ppubuf.o \ - ../wrk/nes/setcursor.o +../tgi/nes-64-56-2.tgi: ../libwrk/nes/clrscr.o \ + ../libwrk/nes/cputc.o \ + ../libwrk/nes/get_tv.o \ + ../libwrk/nes/gotoxy.o \ + ../libwrk/nes/popa.o \ + ../libwrk/nes/ppu.o \ + ../libwrk/nes/ppubuf.o \ + ../libwrk/nes/setcursor.o diff --git a/libsrc/nes/crt0.s b/libsrc/nes/crt0.s index 68b489dac..de874d363 100644 --- a/libsrc/nes/crt0.s +++ b/libsrc/nes/crt0.s @@ -70,7 +70,7 @@ start: -; setup the CPU and System-IRQ +; Set up the CPU and System-IRQ. sei cld @@ -90,40 +90,40 @@ start: inx bne @l -; Clear the BSS data +; Clear the BSS data. jsr zerobss -; initialize data +; Initialize the data. jsr copydata -; setup the stack +; Set up the stack. lda #<(__SRAM_START__ + __SRAM_SIZE__) sta sp lda #>(__SRAM_START__ + __SRAM_SIZE__) sta sp+1 ; Set argument stack ptr -; Call module constructors +; Call the module constructors. jsr initlib -; Push arguments and call main() +; Push the command-line arguments; and, call main(). jsr callmain -; Call module destructors. This is also the _exit entry. +; Call the module destructors. This is also the exit() entry. _exit: jsr donelib ; Run module destructors -; Reset the NES +; Reset the NES. jmp start ; ------------------------------------------------------------------------ -; System V-Blank Interupt -; updates PPU Memory (buffered) -; updates VBLANK_FLAG and tickcount +; System V-Blank Interrupt +; Updates PPU Memory (buffered). +; Updates VBLANK_FLAG and tickcount. ; ------------------------------------------------------------------------ nmi: pha @@ -141,13 +141,13 @@ nmi: pha @s: jsr ppubuf_flush - ; reset the video counter + ; Reset the video counter. lda #$20 sta PPU_VRAM_ADDR2 lda #$00 sta PPU_VRAM_ADDR2 - ; reset scrolling + ; Reset scrolling. sta PPU_VRAM_ADDR1 sta PPU_VRAM_ADDR1 diff --git a/libsrc/nes/joy/nes-stdjoy.s b/libsrc/nes/joy/nes-stdjoy.s index 1ff8395c9..b50c2124d 100644 --- a/libsrc/nes/joy/nes-stdjoy.s +++ b/libsrc/nes/joy/nes-stdjoy.s @@ -12,11 +12,13 @@ .include "joy-error.inc" .include "nes.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _nes_stdjoy_joy ; Driver signature diff --git a/libsrc/nes/tgi/nes-64-56-2.s b/libsrc/nes/tgi/nes-64-56-2.s index 512810b4c..70e23e119 100644 --- a/libsrc/nes/tgi/nes-64-56-2.s +++ b/libsrc/nes/tgi/nes-64-56-2.s @@ -15,11 +15,13 @@ .import paldata .macpack generic + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. -.segment "JUMPTABLE" + module_header _nes_64_56_2_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver diff --git a/libsrc/pet/crt0.s b/libsrc/pet/crt0.s index e828870ab..66aed0366 100644 --- a/libsrc/pet/crt0.s +++ b/libsrc/pet/crt0.s @@ -21,7 +21,7 @@ Start: -; Save the zero page locations we need +; Save the zero-page locations that we need. ldx #zpspace-1 L1: lda sp,x @@ -29,9 +29,9 @@ L1: lda sp,x dex bpl L1 -; Switch to second charset. The routine that is called by BSOUT to switch the -; character set will use FNLEN as temporary storage - YUCK! Since the -; initmainargs routine, which parses the command line for arguments needs this +; Switch to the second charset. The routine that is called by BSOUT to switch the +; character set will use FNLEN as temporary storage -- YUCK! Since the +; initmainargs routine, which parses the command line for arguments, needs that ; information, we need to save and restore it here. ; Thanks to Stefan Haubenthal for this information! @@ -43,11 +43,11 @@ L1: lda sp,x pla sta FNLEN ; Restore FNLEN -; Clear the BSS data +; Clear the BSS data. jsr zerobss -; Save system stuff and setup the stack +; Save some system stuff; and, set up the stack. tsx stx spsave ; Save the system stack ptr @@ -57,20 +57,20 @@ L1: lda sp,x lda MEMSIZE+1 sta sp+1 ; Set argument stack ptr -; Call module constructors +; Call the module constructors. jsr initlib -; Push arguments and call main() +; Push the command-line arguments; and, call main(). jsr callmain -; Call module destructors. This is also the _exit entry. +; Call the module destructors. This is also the exit() entry. _exit: pha ; Save the return code on stack jsr donelib -; Copy back the zero page stuff +; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x @@ -78,17 +78,17 @@ L2: lda zpsave,x dex bpl L2 -; Store the program return code into ST +; Store the program return code into BASIC's status variable. pla sta ST -; Restore the stack pointer +; Restore the stack pointer. ldx spsave txs ; Restore stack pointer -; Back to basic +; Back to BASIC. rts diff --git a/libsrc/pet/joy/pet-ptvjoy.s b/libsrc/pet/joy/pet-ptvjoy.s index 19c2ca876..229055fcb 100644 --- a/libsrc/pet/joy/pet-ptvjoy.s +++ b/libsrc/pet/joy/pet-ptvjoy.s @@ -10,14 +10,14 @@ .include "joy-kernel.inc" .include "joy-error.inc" -; .include "pet.inc" -VIA_PRA := $E841 ; Port register A -VIA_DDRA := $E843 ; Data direction register A + + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table - .segment "JUMPTABLE" + module_header _pet_ptvjoy_joy ; Driver signature @@ -50,7 +50,10 @@ VIA_DDRA := $E843 ; Data direction register A ; ------------------------------------------------------------------------ ; Constants -JOY_COUNT = 2 ; Number of joysticks we support +JOY_COUNT = 2 ; Number of joysticks we support + +VIA_PRA := $E841 ; Port register A +VIA_DDRA := $E843 ; Data direction register A .code diff --git a/libsrc/pet/joy/pet-stdjoy.s b/libsrc/pet/joy/pet-stdjoy.s index 3377c8f81..5847c2b09 100644 --- a/libsrc/pet/joy/pet-stdjoy.s +++ b/libsrc/pet/joy/pet-stdjoy.s @@ -10,11 +10,13 @@ .include "joy-error.inc" .include "pet.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table - .segment "JUMPTABLE" + module_header _pet_stdjoy_joy ; Driver signature diff --git a/libsrc/plus4/crt0.s b/libsrc/plus4/crt0.s index 92faadf52..b732459e0 100644 --- a/libsrc/plus4/crt0.s +++ b/libsrc/plus4/crt0.s @@ -29,7 +29,7 @@ IRQInd = $500 ; JMP $0000 - used as indirect IRQ vector Start: -; Save the zero page locations we need +; Save the zero-page locations that we need. sei ; No interrupts since we're banking out the ROM sta ENABLE_RAM @@ -41,13 +41,13 @@ L1: lda sp,x sta ENABLE_ROM cli -; Switch to second charset +; Switch to the second charset. lda #14 jsr $FFD2 ; BSOUT -; Save system stuff and setup the stack. The stack starts at the top of the -; usable RAM. +; Save some system stuff; and, set up the stack. The stack starts at the top +; of the usable RAM. tsx stx spsave ; save system stk ptr @@ -57,7 +57,7 @@ L1: lda sp,x lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) sta sp+1 -; Setup the IRQ vector in the banked RAM and switch off the ROM +; Set up the IRQ vector in the banked RAM; and, switch off the ROM. ldx #<IRQ ldy #>IRQ @@ -67,35 +67,35 @@ L1: lda sp,x sty $FFFF cli ; Allow interrupts -; Clear the BSS data +; Clear the BSS data. jsr zerobss -; Initialize irqcount, which means that from now own custom linked in IRQ -; handlers (via condes) will be called. +; Initialize irqcount, which means that, from now on, custom linked-in IRQ +; handlers will be called (via condes). lda #.lobyte(__INTERRUPTOR_COUNT__*2) sta irqcount -; Call module constructors +; Call the module constructors. jsr initlib -; Push arguments and call main() +; Push the command-line arguments; and, call main(). jsr callmain -; Back from main (this is also the _exit entry). Run module destructors. +; Back from main() [this is also the exit() entry]. Run the module destructors. _exit: pha ; Save the return code jsr donelib ; Run module destructors -; Disable chained IRQ handlers +; Disable the chained IRQ handlers. lda #0 sta irqcount ; Disable custom IRQ handlers -; Copy back the zero page stuff +; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x @@ -103,28 +103,28 @@ L2: lda zpsave,x dex bpl L2 -; Place the program return code into ST +; Place the program return code into BASIC's status variable. pla sta ST -; Restore the stack pointer +; Restore the stack pointer. ldx spsave txs -; Enable the ROM and return to BASIC +; Enable the ROM; and, return to BASIC. sta ENABLE_ROM rts ; ------------------------------------------------------------------------ -; IRQ handler. The handler in the ROM enables the kernal and jumps to -; $CE00, where the ROM code checks for a BRK or IRQ and branches via the +; IRQ handler. The handler in the ROM enables the Kernal, and jumps to +; $CE00, where the ROM code checks for a BRK or IRQ, and branches via the ; indirect vectors at $314/$316. ; To make our stub as fast as possible, we skip the whole part of the ROM -; handler and jump to the indirect vectors directly. We do also call our -; own interrupt handlers if we have any, so they need not use $314. +; handler, and jump to the indirect vectors directly. We do also call our +; own interrupt handlers if we have any; so, they need not use $314. .segment "LOWCODE" @@ -139,7 +139,7 @@ IRQ: cld ; Just to be sure and #$10 ; Test for BRK bit bne dobreak -; It's an IRQ and RAM is enabled. If we have handlers, call them. We will use +; It's an IRQ; and, RAM is enabled. If we have handlers, call them. We will use ; a flag here instead of loading __INTERRUPTOR_COUNT__ directly, since the ; condes function is not reentrant. The irqcount flag will be set/reset from ; the main code, to avoid races. @@ -149,8 +149,8 @@ IRQ: cld ; Just to be sure jsr callirq_y ; Call the IRQ functions ; Since the ROM handler will end with an RTI, we have to fake an IRQ return -; on stack, so we get control of the CPU after the ROM handler and can switch -; back to RAM. +; on the stack, so that we get control of the CPU after the ROM handler, +; and can switch back to RAM. @L1: lda #>irq_ret ; Push new return address pha @@ -161,7 +161,7 @@ IRQ: cld ; Just to be sure pha ; Push faked X register pha ; Push faked Y register sta ENABLE_ROM ; Switch to ROM - jmp (IRQVec) ; Jump indirect to kernal irq handler + jmp (IRQVec) ; Jump indirect to Kernal IRQ handler irq_ret: sta ENABLE_RAM ; Switch back to RAM @@ -177,7 +177,7 @@ dobreak: beq nohandler jmp brk_jmp ; Jump to the handler -; No break handler installed, jump to ROM +; No break handler installed, jump to ROM. nohandler: sta ENABLE_ROM diff --git a/libsrc/plus4/joy/plus4-stdjoy.s b/libsrc/plus4/joy/plus4-stdjoy.s index f67487781..29316bf22 100644 --- a/libsrc/plus4/joy/plus4-stdjoy.s +++ b/libsrc/plus4/joy/plus4-stdjoy.s @@ -12,12 +12,17 @@ .include "plus4.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + .if .xmatch ("MODULE_LABEL", .string(MODULE_LABEL)) + module_header _plus4_stdjoy_joy + .else + module_header MODULE_LABEL + .endif ; Driver signature diff --git a/libsrc/plus4/ser/plus4-stdser.s b/libsrc/plus4/ser/plus4-stdser.s index 86377b89c..47dd96042 100644 --- a/libsrc/plus4/ser/plus4-stdser.s +++ b/libsrc/plus4/ser/plus4-stdser.s @@ -26,11 +26,13 @@ .include "ser-error.inc" .include "plus4.inc" + .macpack module + ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _plus4_stdser_ser ; Driver signature diff --git a/libsrc/plus4/systime.s b/libsrc/plus4/systime.s index d22b8c596..273e394a4 100644 --- a/libsrc/plus4/systime.s +++ b/libsrc/plus4/systime.s @@ -3,10 +3,10 @@ ; ; time_t _systime (void); ; /* Similar to time(), but: -; * - Is not ISO C -; * - Does not take the additional pointer -; * - Does not set errno when returning -1 -; */ +; ** - Is not ISO C +; ** - Does not take the additional pointer +; ** - Does not set errno when returning -1 +; */ ; .export __systime diff --git a/libsrc/runtime/imul16x16r32.s b/libsrc/runtime/imul16x16r32.s index f41d13602..6fad9abf0 100644 --- a/libsrc/runtime/imul16x16r32.s +++ b/libsrc/runtime/imul16x16r32.s @@ -13,9 +13,9 @@ ;--------------------------------------------------------------------------- ; 16x16 => 32 signed multiplication routine. ; -; lhs rhs result result also in +; LHS RHS result result also in ; ------------------------------------------------------------- -; ptr1 ax ax:sreg +; ax ptr1 ax:sreg ; ; There is probably a faster way to do this. ; diff --git a/libsrc/runtime/imul8x8r16.s b/libsrc/runtime/imul8x8r16.s new file mode 100644 index 000000000..e1aea30ae --- /dev/null +++ b/libsrc/runtime/imul8x8r16.s @@ -0,0 +1,75 @@ +; +; 2010-11-02, Ullrich von Bassewitz +; 2014-09-10, Greg King +; +; CC65 runtime: 8x8 => 16 signed multiplication +; + + .export imul8x8r16, imul8x8r16m + .importzp ptr1, ptr3, tmp1 + + .macpack generic + +;--------------------------------------------------------------------------- +; 8x8 => 16 signed multiplication routine. +; +; multiplicand multiplier product +; LHS RHS result +; ------------------------------------------------------------- +; .A (ptr3-low) ptr1-low .XA +; + +imul8x8r16: + sta ptr3 + +imul8x8r16m: + ldx #>$0000 + bit ptr3 + bpl @L7 + dex +@L7: stx ptr3+1 ; Extend sign of Left-Hand Side + ldy #<$0000 ; Clear .XY accumulator + ldx #>$0000 + lda ptr1 + bmi NegMult + bpl @L2 ; Branch always + +@L0: tya ; Add current multiplicand + add ptr3 + tay + txa + adc ptr3+1 + tax + +@L1: asl ptr3 + rol ptr3+1 +@L2: lsr ptr1 ; Get next bit of Right-Hand Side into carry + bcs @L0 + bnz @L1 ; Loop if more one-bits in multiplier + + tya ; Put result into cc65's accumulator + rts + +; The multiplier is negative. +; Therefore, make it positive; and, subtract when multiplying. +NegMult: + eor #%11111111 + sta ptr1 + inc ptr1 + bnz @L2 ; Branch always + +@L0: tya ; Subtract current multiplicand + sub ptr3 + tay + txa + sbc ptr3+1 + tax + +@L1: asl ptr3 + rol ptr3+1 +@L2: lsr ptr1 ; Get next bit of Right-Hand Side into carry + bcs @L0 + bnz @L1 ; Loop if more one-bits in multiplier + + tya ; Put result into cc65's accumulator + rts diff --git a/libsrc/runtime/umul16x16r32.s b/libsrc/runtime/umul16x16r32.s index c02cf8bb2..9ecd1596e 100644 --- a/libsrc/runtime/umul16x16r32.s +++ b/libsrc/runtime/umul16x16r32.s @@ -13,14 +13,14 @@ ;--------------------------------------------------------------------------- ; 16x16 => 32 unsigned multiplication routine. Because the overhead for a ; 16x16 => 16 unsigned multiplication routine is small, we will tag it with -; the matching labels as well. +; the matching labels, as well. ; -; routine lhs rhs result result also in +; routine LHS RHS result result also in ; ----------------------------------------------------------------------- -; umul16x16r32 ptr1 ax ax:sreg ptr1:sreg -; umul16x16r32m ptr1 ptr3 ax:sreg ptr1:sreg -; umul16x16r16 ptr1 ax ax ptr1 -; umul16x16r16m ptr1 ptr3 ax ptr1 +; umul16x16r32 ax ptr1 ax:sreg ptr1:sreg +; umul16x16r32m ptr3 ptr1 ax:sreg ptr1:sreg +; umul16x16r16 ax ptr1 ax ptr1 +; umul16x16r16m ptr3 ptr1 ax ptr1 ; ; ptr3 is left intact by the routine. ; diff --git a/libsrc/runtime/umul8x16r24.s b/libsrc/runtime/umul8x16r24.s index 64653f5f4..ff7d0bae6 100644 --- a/libsrc/runtime/umul8x16r24.s +++ b/libsrc/runtime/umul8x16r24.s @@ -13,14 +13,14 @@ ;--------------------------------------------------------------------------- ; 8x16 => 24 unsigned multiplication routine. Because the overhead for a ; 8x16 => 16 unsigned multiplication routine is small, we will tag it with -; the matching labels as well. +; the matching labels, as well. ; -; routine lhs rhs result result also in +; routine LHS RHS result result also in ; ----------------------------------------------------------------------- -; umul8x16r24 ptr1-lo ax ax:sreg-lo ptr1:sreg-lo -; umul8x16r24m ptr1-lo ptr3 ax:sreg-lo ptr1:sreg-lo +; umul8x16r24 ax ptr1-low ax:sreg-low ptr1:sreg-low +; umul8x16r24m ptr3 ptr1-low ax:sreg-low ptr1:sreg-low ; -; ptr3 ist left intact by the routine. +; ptr3 is left intact by the routine. ; umul8x16r24: diff --git a/libsrc/runtime/umul8x8r16.s b/libsrc/runtime/umul8x8r16.s index 34ff82872..aba758e1a 100644 --- a/libsrc/runtime/umul8x8r16.s +++ b/libsrc/runtime/umul8x8r16.s @@ -1,7 +1,7 @@ ; ; Ullrich von Bassewitz, 2010-11-02 ; -; CC65 runtime: 8x8 => 16 multiplication +; CC65 runtime: 8x8 => 16 unsigned multiplication ; .export umul8x8r16, umul8x8r16m @@ -9,11 +9,11 @@ ;--------------------------------------------------------------------------- -; 8x8 => 16 multiplication routine. +; 8x8 => 16 unsigned multiplication routine. ; -; lhs rhs result result also in +; LHS RHS result result in also ; ------------------------------------------------------------- -; ptr1-lo ptr3-lo ax ptr1 +; .A (ptr3-low) ptr1-low .XA ptr1 ; umul8x8r16: @@ -21,7 +21,7 @@ umul8x8r16: umul8x8r16m: lda #0 ; Clear byte 1 ldy #8 ; Number of bits - lsr ptr1 ; Get first bit of lhs into carry + lsr ptr1 ; Get first bit of RHS into carry @L0: bcc @L1 clc adc ptr3 @@ -30,8 +30,6 @@ umul8x8r16m: dey bne @L0 tax - stx ptr1+1 ; Result in a/x and ptr1 + stx ptr1+1 ; Result in .XA and ptr1 lda ptr1 ; Load the result rts ; Done - - diff --git a/libsrc/serial/ser-kernel.s b/libsrc/serial/ser-kernel.s index 438189edb..4c5b455b6 100644 --- a/libsrc/serial/ser-kernel.s +++ b/libsrc/serial/ser-kernel.s @@ -103,8 +103,8 @@ copy: lda (ptr1),y ;---------------------------------------------------------------------------- ; unsigned char ser_uninstall (void); ; /* Uninstall the currently loaded driver and return an error code. -; * Note: This call does not free allocated memory. -; */ +; ** Note: This call does not free allocated memory. +; */ _ser_uninstall: jsr ser_uninstall ; Call driver routine diff --git a/libsrc/serial/ser_get.s b/libsrc/serial/ser_get.s index dccd92000..74a079eaa 100644 --- a/libsrc/serial/ser_get.s +++ b/libsrc/serial/ser_get.s @@ -3,8 +3,8 @@ ; ; unsigned char __fastcall__ ser_get (char* b); ; /* Get a character from the serial port. If no characters are available, the -; * function will return SER_ERR_NO_DATA, so this is not a fatal error. -; */ +; ** function will return SER_ERR_NO_DATA, so this is not a fatal error. +; */ .importzp ptr1 diff --git a/libsrc/serial/ser_put.s b/libsrc/serial/ser_put.s index 7bbdbdeb4..bab6062eb 100644 --- a/libsrc/serial/ser_put.s +++ b/libsrc/serial/ser_put.s @@ -3,9 +3,9 @@ ; ; unsigned char __fastcall__ ser_put (char b); ; /* Send a character via the serial port. There is a transmit buffer, but -; * transmitting is not done via interrupt. The function returns -; * SER_ERR_OVERFLOW if there is no space left in the transmit buffer. -; */ +; ** transmitting is not done via interrupt. The function returns +; ** SER_ERR_OVERFLOW if there is no space left in the transmit buffer. +; */ .include "ser-kernel.inc" diff --git a/libsrc/supervision/crt0.s b/libsrc/supervision/crt0.s index 11d239277..d78bfeab5 100644 --- a/libsrc/supervision/crt0.s +++ b/libsrc/supervision/crt0.s @@ -28,7 +28,7 @@ _sv_nmi_counter: .byte 0 reset: jsr zerobss - ; initialize data + ; Initialize data. jsr copydata lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) @@ -63,12 +63,12 @@ not_dma: rti .endproc -; removing this segment gives only a warning +; Removing this segment gives only a warning. .segment "FFF0" .proc reset32kcode lda #(6<<5) sta sv_bank -; now the 32kbyte image can reside in the top of 64kbyte, 128kbyte roms +; Now, the 32Kbyte image can reside in the top of 64Kbyte and 128Kbyte ROMs. jmp reset .endproc diff --git a/libsrc/tgi/tgi-kernel.s b/libsrc/tgi/tgi-kernel.s index 3781795f6..ed65760af 100644 --- a/libsrc/tgi/tgi-kernel.s +++ b/libsrc/tgi/tgi-kernel.s @@ -198,8 +198,8 @@ tgi_set_ptr: ;---------------------------------------------------------------------------- ; void tgi_uninstall (void); ; /* Uninstall the currently loaded driver but do not unload it. Will call -; * tgi_done if necessary. -; */ +; ** tgi_done if necessary. +; */ _tgi_uninstall: jsr _tgi_done ; Switch off graphics diff --git a/libsrc/tgi/tgi_arc.c b/libsrc/tgi/tgi_arc.c index d4bb84f2b..e505b7b69 100644 --- a/libsrc/tgi/tgi_arc.c +++ b/libsrc/tgi/tgi_arc.c @@ -48,10 +48,10 @@ void __fastcall__ tgi_arc (int x, int y, unsigned char rx, unsigned char ry, unsigned sa, unsigned ea) /* Draw an ellipse arc with center at x/y and radii rx/ry using the current - * drawing color. The arc covers the angle between sa and ea (startangle and - * endangle), which must be in the range 0..360 (otherwise the function may - * bevave unextectedly). - */ +** drawing color. The arc covers the angle between sa and ea (startangle and +** endangle), which must be in the range 0..360 (otherwise the function may +** bevave unextectedly). +*/ { int x1, y1, x2, y2; unsigned char inc; diff --git a/libsrc/tgi/tgi_ellipse.s b/libsrc/tgi/tgi_ellipse.s index 1471f9156..dc6160aef 100644 --- a/libsrc/tgi/tgi_ellipse.s +++ b/libsrc/tgi/tgi_ellipse.s @@ -3,8 +3,8 @@ ; ; void __fastcall__ tgi_ellipse (int x, int y, unsigned char rx, unsigned char ry); ; /* Draw a full ellipse with center at x/y and radii rx/ry using the current -; * drawing color. -; */ +; ** drawing color. +; */ ; diff --git a/libsrc/tgi/tgi_getaspectratio.s b/libsrc/tgi/tgi_getaspectratio.s index f6081b1ee..f4ac4814f 100644 --- a/libsrc/tgi/tgi_getaspectratio.s +++ b/libsrc/tgi/tgi_getaspectratio.s @@ -3,8 +3,8 @@ ; ; unsigned tgi_getaspectratio (void); ; /* Returns the aspect ratio for the loaded driver. The aspect ratio is an -; * 8.8 fixed point value. -; */ +; ** 8.8 fixed point value. +; */ ; .include "tgi-kernel.inc" diff --git a/libsrc/tgi/tgi_getdefpalette.s b/libsrc/tgi/tgi_getdefpalette.s index a95301389..4df4f4b26 100644 --- a/libsrc/tgi/tgi_getdefpalette.s +++ b/libsrc/tgi/tgi_getdefpalette.s @@ -3,8 +3,8 @@ ; ; const unsigned char* tgi_getdefpalette (void); ; /* Return the default palette. Will return NULL for drivers that do not -; * support palettes. -; */ +; ** support palettes. +; */ ; .include "tgi-kernel.inc" diff --git a/libsrc/tgi/tgi_geterror.s b/libsrc/tgi/tgi_geterror.s index c34b08ba9..8d0e4db12 100644 --- a/libsrc/tgi/tgi_geterror.s +++ b/libsrc/tgi/tgi_geterror.s @@ -3,8 +3,8 @@ ; ; unsigned char tgi_geterror (void); ; /* Return the error code for the last operation. This will also clear the -; * error. -; */ +; ** error. +; */ .include "tgi-kernel.inc" diff --git a/libsrc/tgi/tgi_getmaxcolor.s b/libsrc/tgi/tgi_getmaxcolor.s index d10ac0e3f..4db8078d2 100644 --- a/libsrc/tgi/tgi_getmaxcolor.s +++ b/libsrc/tgi/tgi_getmaxcolor.s @@ -3,8 +3,8 @@ ; ; unsigned char tgi_getmaxcolor (void); ; /* Return the maximum supported color number (the number of colors would -; * then be getmaxcolor()+1). -; */ +; ** then be getmaxcolor()+1). +; */ ; .include "tgi-kernel.inc" diff --git a/libsrc/tgi/tgi_getmaxx.s b/libsrc/tgi/tgi_getmaxx.s index ccf0eb8d5..1a706956f 100644 --- a/libsrc/tgi/tgi_getmaxx.s +++ b/libsrc/tgi/tgi_getmaxx.s @@ -3,8 +3,8 @@ ; ; unsigned tgi_getmaxx (void); ; /* Return the maximum x coordinate. The resolution in x direction is -; * getmaxx() + 1 -; */ +; ** getmaxx() + 1 +; */ .include "tgi-kernel.inc" diff --git a/libsrc/tgi/tgi_getmaxy.s b/libsrc/tgi/tgi_getmaxy.s index 3fc7bdb86..6f28fc176 100644 --- a/libsrc/tgi/tgi_getmaxy.s +++ b/libsrc/tgi/tgi_getmaxy.s @@ -3,8 +3,8 @@ ; ; unsigned tgi_getmaxy (void); ; /* Return the maximum y coordinate. The resolution in y direction is -; * getmaxy() + 1 -; */ +; ** getmaxy() + 1 +; */ .include "tgi-kernel.inc" diff --git a/libsrc/tgi/tgi_getpalette.s b/libsrc/tgi/tgi_getpalette.s index a91aefb71..f28710ce3 100644 --- a/libsrc/tgi/tgi_getpalette.s +++ b/libsrc/tgi/tgi_getpalette.s @@ -3,8 +3,8 @@ ; ; const unsigned char* tgi_getpalette (void); ; /* Return the current palette. Will return NULL for drivers that do not -; * support palettes. -; */ +; ** support palettes. +; */ ; .include "tgi-kernel.inc" diff --git a/libsrc/tgi/tgi_gettextheight.s b/libsrc/tgi/tgi_gettextheight.s index 8daad941b..38df6a69a 100644 --- a/libsrc/tgi/tgi_gettextheight.s +++ b/libsrc/tgi/tgi_gettextheight.s @@ -11,8 +11,8 @@ ;----------------------------------------------------------------------------- ; unsigned __fastcall__ tgi_gettextheight (const char* s); ; /* Calculate the height of the text in pixels according to the current text -; * style. -; */ +; ** style. +; */ ; .proc _tgi_gettextheight diff --git a/libsrc/tgi/tgi_gettextwidth.s b/libsrc/tgi/tgi_gettextwidth.s index c7bbcffd1..9a935b6b7 100644 --- a/libsrc/tgi/tgi_gettextwidth.s +++ b/libsrc/tgi/tgi_gettextwidth.s @@ -22,8 +22,8 @@ Text := ptr3 ;----------------------------------------------------------------------------- ; unsigned __fastcall__ tgi_gettextwidth (const char* s); ; /* Calculate the width of the text in pixels according to the current text -; * style. -; */ +; ** style. +; */ ; ; Result is strlen (s) * tgi_textmagw * tgi_fontsizex ; diff --git a/libsrc/tgi/tgi_install_vectorfont.s b/libsrc/tgi/tgi_install_vectorfont.s index ff174896e..91df3059a 100644 --- a/libsrc/tgi/tgi_install_vectorfont.s +++ b/libsrc/tgi/tgi_install_vectorfont.s @@ -8,9 +8,9 @@ ;----------------------------------------------------------------------------- ; void __fastcall__ tgi_install_vectorfont (const tgi_vectorfont* font); ; /* Install a vector font for use. More than one vector font can be loaded, -; * but only one can be active. This function is used to tell which one. Call -; * with a NULL pointer to uninstall the currently installed font. -; */ +; ** but only one can be active. This function is used to tell which one. Call +; ** with a NULL pointer to uninstall the currently installed font. +; */ ; .code diff --git a/libsrc/tgi/tgi_ioctl.s b/libsrc/tgi/tgi_ioctl.s index fd4db7dcd..434c33757 100644 --- a/libsrc/tgi/tgi_ioctl.s +++ b/libsrc/tgi/tgi_ioctl.s @@ -3,9 +3,9 @@ ; ; unsigned __fastcall__ tgi_ioctl (unsigned char code, void* data); ; /* Call the driver specific control function. What this function does for -; * a specific code depends on the driver. The driver will set an error -; * for unknown codes or values. -; */ +; ** a specific code depends on the driver. The driver will set an error +; ** for unknown codes or values. +; */ ; .include "tgi-kernel.inc" diff --git a/libsrc/tgi/tgi_lineto.s b/libsrc/tgi/tgi_lineto.s index 868f4cf42..abe4b3f96 100644 --- a/libsrc/tgi/tgi_lineto.s +++ b/libsrc/tgi/tgi_lineto.s @@ -3,8 +3,8 @@ ; ; void __fastcall__ tgi_lineto (int x2, int y2); ; /* Draw a line in the current drawing color from the graphics cursor to the -; * new end point. -; */ +; ** new end point. +; */ .include "tgi-kernel.inc" diff --git a/libsrc/tgi/tgi_load_vectorfont.c b/libsrc/tgi/tgi_load_vectorfont.c index 0d5af23c9..55e1bf7b6 100644 --- a/libsrc/tgi/tgi_load_vectorfont.c +++ b/libsrc/tgi/tgi_load_vectorfont.c @@ -52,9 +52,9 @@ const tgi_vectorfont* __fastcall__ tgi_load_vectorfont (const char* name) /* Load a vector font into memory and return it. In case of errors, NULL is - * returned and an error is set, which can be retrieved using tgi_geterror. - * To use the font, it has to be installed using tgi_install_vectorfont. - */ +** returned and an error is set, which can be retrieved using tgi_geterror. +** To use the font, it has to be installed using tgi_install_vectorfont. +*/ { static const char Magic[4] = { 0x54, 0x43, 0x48, TGI_VF_VERSION @@ -108,10 +108,10 @@ const tgi_vectorfont* __fastcall__ tgi_load_vectorfont (const char* name) close (F); /* Fix the offset pointers. When loaded, they contain numeric offsets - * into the VectorOps, with the start of the VectorOps at offset zero. - * We will add a pointer to the VectorOps to make them actual pointers - * that may be used independently from anything else. - */ + ** into the VectorOps, with the start of the VectorOps at offset zero. + ** We will add a pointer to the VectorOps to make them actual pointers + ** that may be used independently from anything else. + */ V = (unsigned) &Font->vec_ops; for (I = 0; I < TGI_VF_CCOUNT; ++I) { Font->chars[I] += V; @@ -125,8 +125,8 @@ const tgi_vectorfont* __fastcall__ tgi_load_vectorfont (const char* name) LoadError: /* Some sort of load problem. If the file is still open, be sure to - * close it - */ + ** close it + */ if (F >= 0) { close (F); } diff --git a/libsrc/tgi/tgi_pieslice.c b/libsrc/tgi/tgi_pieslice.c index f78d7a672..60d2f1d13 100644 --- a/libsrc/tgi/tgi_pieslice.c +++ b/libsrc/tgi/tgi_pieslice.c @@ -48,10 +48,10 @@ void __fastcall__ tgi_pieslice (int x, int y, unsigned char rx, unsigned char ry, unsigned sa, unsigned ea) /* Draw an ellipse pie slice with center at x/y and radii rx/ry using the - * current drawing color. The pie slice covers the angle between sa and ea - * (startangle and endangle), which must be in the range 0..360 (otherwise the - * function may behave unextectedly). - */ +** current drawing color. The pie slice covers the angle between sa and ea +** (startangle and endangle), which must be in the range 0..360 (otherwise the +** function may behave unexpectedly). +*/ { /* Draw an arc ... */ tgi_arc (x, y, rx, ry, sa, ea); diff --git a/libsrc/tgi/tgi_setaspectratio.s b/libsrc/tgi/tgi_setaspectratio.s index c46d6dede..bb511af0c 100644 --- a/libsrc/tgi/tgi_setaspectratio.s +++ b/libsrc/tgi/tgi_setaspectratio.s @@ -3,8 +3,8 @@ ; ; void __fastcall__ tgi_setaspectratio (unsigned aspectratio); ; /* Set a new aspect ratio for the loaded driver. The aspect ratio is an -; * 8.8 fixed point value. -; */ +; ** 8.8 fixed point value. +; */ ; .include "tgi-kernel.inc" diff --git a/libsrc/tgi/tgi_setpalette.s b/libsrc/tgi/tgi_setpalette.s index b8f269b9e..86411a52a 100644 --- a/libsrc/tgi/tgi_setpalette.s +++ b/libsrc/tgi/tgi_setpalette.s @@ -3,8 +3,8 @@ ; ; void __fastcall__ tgi_setpalette (const unsigned char* palette); ; /* Set the palette (not available with all drivers/hardware). palette is -; * a pointer to as many entries as there are colors. -; */ +; ** a pointer to as many entries as there are colors. +; */ ; .include "tgi-kernel.inc" diff --git a/libsrc/tgi/tgi_settextdir.s b/libsrc/tgi/tgi_settextdir.s index d6c6dc838..897e74e30 100644 --- a/libsrc/tgi/tgi_settextdir.s +++ b/libsrc/tgi/tgi_settextdir.s @@ -8,8 +8,8 @@ ;----------------------------------------------------------------------------- ; void __fastcall__ tgi_settextdir (unsigned char dir); ; /* Set the direction for text output. dir is one of the TGI_TEXT_XXX -; * constants. -; */ +; ** constants. +; */ ; .proc _tgi_settextdir diff --git a/libsrc/tgi/tgi_settextstyle.s b/libsrc/tgi/tgi_settextstyle.s index ba3cb188b..b62d6904c 100644 --- a/libsrc/tgi/tgi_settextstyle.s +++ b/libsrc/tgi/tgi_settextstyle.s @@ -15,10 +15,10 @@ ; void __fastcall__ tgi_settextstyle (unsigned width, unsigned height, ; unsigned char dir, unsigned char font); ; /* Set the style for text output. The scaling factors for width and height -; * are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. -; * dir is one of the TGI_TEXT_XXX constants. font is one of the TGI_FONT_XXX -; * constants. -; */ +; ** are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. +; ** dir is one of the TGI_TEXT_XXX constants. font is one of the TGI_FONT_XXX +; ** constants. +; */ ; .proc _tgi_settextstyle @@ -36,8 +36,8 @@ ;----------------------------------------------------------------------------- ; void __fastcall__ tgi_settextscale (unsigned width, unsigned height); ; /* Set the scaling for text output. The scaling factors for width and height -; * are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. -; */ +; ** are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. +; */ .proc _tgi_settextscale diff --git a/libsrc/tgi/tgi_vectorchar.s b/libsrc/tgi/tgi_vectorchar.s index 76f585dcd..bd4cc84c4 100644 --- a/libsrc/tgi/tgi_vectorchar.s +++ b/libsrc/tgi/tgi_vectorchar.s @@ -3,8 +3,8 @@ ; ; void __fastcall__ tgi_vectorchar (const unsigned char* Ops); ; /* Draw one character of the vector font at the current graphics cursor -; * position using the current font magnification. -; */ +; ** position using the current font magnification. +; */ ; .import imul16x16r32, umul16x16r32, negax, negeax diff --git a/libsrc/vic20/crt0.s b/libsrc/vic20/crt0.s index dae6424dd..e04881987 100644 --- a/libsrc/vic20/crt0.s +++ b/libsrc/vic20/crt0.s @@ -22,7 +22,7 @@ Start: -; Save the zero page locations we need +; Save the zero-page locations that we need. ldx #zpspace-1 L1: lda sp,x @@ -30,16 +30,16 @@ L1: lda sp,x dex bpl L1 -; Switch to second charset +; Switch to the second charset. lda #14 jsr BSOUT -; Clear the BSS data +; Clear the BSS data. jsr zerobss -; Save system stuff and setup the stack +; Save some system stuff; and, set up the stack. tsx stx spsave ; Save the system stack ptr @@ -49,20 +49,20 @@ L1: lda sp,x lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) sta sp+1 ; Set argument stack ptr -; Call module constructors +; Call the module constructors. jsr initlib -; Push arguments and call main() +; Push the command-line arguments; and, call main(). jsr callmain -; Back from main (This is also the _exit entry). Run module destructors +; Back from main() [this is also the exit() entry]. Run the module destructors. _exit: pha ; Save the return code on stack jsr donelib -; Copy back the zero page stuff +; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x @@ -70,17 +70,17 @@ L2: lda zpsave,x dex bpl L2 -; Place the program return code into ST +; Place the program return code into BASIC's status variable. pla sta ST -; Restore the stack pointer +; Restore the stack pointer. ldx spsave txs -; Back to basic +; Back to BASIC. rts diff --git a/libsrc/vic20/joy/vic20-ptvjoy.s b/libsrc/vic20/joy/vic20-ptvjoy.s index 533726c7b..cdd4c274f 100644 --- a/libsrc/vic20/joy/vic20-ptvjoy.s +++ b/libsrc/vic20/joy/vic20-ptvjoy.s @@ -13,10 +13,13 @@ .include "joy-error.inc" .include "vic20.inc" + .macpack module + + ; ------------------------------------------------------------------------ ; Header. Includes jump table - .segment "JUMPTABLE" + module_header _vic20_ptvjoy_joy ; Driver signature diff --git a/libsrc/vic20/joy/vic20-stdjoy.s b/libsrc/vic20/joy/vic20-stdjoy.s index 722aa8ea5..56fb35ae4 100644 --- a/libsrc/vic20/joy/vic20-stdjoy.s +++ b/libsrc/vic20/joy/vic20-stdjoy.s @@ -13,12 +13,13 @@ .include "vic20.inc" .macpack generic + .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table -.segment "JUMPTABLE" + module_header _vic20_stdjoy_joy ; Driver signature diff --git a/libsrc/zlib/uncompress.c b/libsrc/zlib/uncompress.c index 3cff19ad3..7810eb4f8 100644 --- a/libsrc/zlib/uncompress.c +++ b/libsrc/zlib/uncompress.c @@ -1,8 +1,8 @@ /* - * uncompress.c - * - * Piotr Fusik, 18.11.2001 - */ +** uncompress.c +** +** Piotr Fusik, 18.11.2001 +*/ #include <zlib.h> diff --git a/samples/Makefile b/samples/Makefile index a17288ced..79988ea70 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -43,6 +43,25 @@ endif # This one comes with VICE C1541 = c1541 +# -------------------------------------------------------------------------- +# System dependent settings + +# The Apple machines need the start address adjusted when using TGI +LDFLAGS_mandelbrot_apple2 = --start-addr 0x4000 +LDFLAGS_tgidemo_apple2 = --start-addr 0x4000 +LDFLAGS_mandelbrot_apple2enh = --start-addr 0x4000 +LDFLAGS_tgidemo_apple2enh = --start-addr 0x4000 + +# The Apple ][ needs the start address adjusted for the mousetest +LDFLAGS_mousetest_apple2 = --start-addr 0x4000 + +# The atarixl target needs the start address adjusted when using TGI +LDFLAGS_mandelbrot_atarixl = --start-addr 0x4000 +LDFLAGS_tgidemo_atarixl = --start-addr 0x4000 + +# The atari target needs to reserve some memory when using TGI +LDFLAGS_mandelbrot_atari = -D __RESERVED_MEMORY__=0x2000 +LDFLAGS_tgidemo_atari = -D __RESERVED_MEMORY__=0x2000 # -------------------------------------------------------------------------- # Generic rules @@ -59,9 +78,10 @@ C1541 = c1541 @echo $< @$(AS) $(AFLAGS) -t $(SYS) $< -.o: - @$(LD) -o $@ -t $(SYS) -m $@.map $^ $(CLIB) +.PRECIOUS: %.o +.o: + @$(LD) $(LDFLAGS_$(basename $@)_$(SYS)) -o $@ -t $(SYS) -m $@.map $^ $(CLIB) # -------------------------------------------------------------------------- # List of executables. This list could be made target dependent by checking @@ -88,62 +108,6 @@ EXELIST = ascii \ .PHONY: all all: $(EXELIST) -ascii: ascii.o - -diodemo: diodemo.o - -fire: fire.o - -gunzip65: gunzip65.o - -hello: hello.o - -# The Apple machines need the start address adjusted for the mandelbrot demo -ifeq "$(SYS)" "apple2" -mandelbrot: mandelbrot.o - @$(LD) -o $@ -t $(SYS) -m $@.map --start-addr 0x4000 $^ $(CLIB) -else -ifeq "$(SYS)" "apple2enh" -mandelbrot: mandelbrot.o - @$(LD) -o $@ -t $(SYS) -m $@.map --start-addr 0x4000 $^ $(CLIB) -else -mandelbrot: mandelbrot.o -endif -endif - -# The Apple ][ needs the start address adjusted for the mousetest -ifeq "$(SYS)" "apple2" -mousetest: mousetest.o - @$(LD) -o $@ -t $(SYS) -m $@.map --start-addr 0x4000 $^ $(CLIB) -else -mousetest: mousetest.o -endif - -multdemo: multidemo.o - @$(LD) -o $@ -m $@.map -C $(SYS)-overlay.cfg $^ $(CLIB) - -nachtm: nachtm.o - -ovrldemo: overlaydemo.o - @$(LD) -o $@ -m $@.map -C $(SYS)-overlay.cfg $^ $(CLIB) - -plasma: plasma.o - -sieve: sieve.o - -# The Apple machines need the start address adjusted for the tgidemo -ifeq "$(SYS)" "apple2" -tgidemo: tgidemo.o - @$(LD) -o $@ -t $(SYS) -m $@.map --start-addr 0x4000 $^ $(CLIB) -else -ifeq "$(SYS)" "apple2enh" -tgidemo: tgidemo.o - @$(LD) -o $@ -t $(SYS) -m $@.map --start-addr 0x4000 $^ $(CLIB) -else -tgidemo: tgidemo.o -endif -endif - # -------------------------------------------------------------------------- # Rule to make a disk with all samples. Needs the c1541 program that comes # with the VICE emulator. diff --git a/samples/enumdevdir.c b/samples/enumdevdir.c index 5969c2339..f270b43af 100644 --- a/samples/enumdevdir.c +++ b/samples/enumdevdir.c @@ -1,9 +1,9 @@ /* - * Enumerate devices, directories and files. - * - * 2012-10-15, Oliver Schmidt (ol.sc@web.de) - * - */ +** Enumerate devices, directories and files. +** +** 2012-10-15, Oliver Schmidt (ol.sc@web.de) +** +*/ @@ -30,21 +30,21 @@ void printdir (char *newdir) if (chdir (newdir)) { /* If chdir() fails we just print the - * directory name - as done for files. - */ + ** directory name - as done for files. + */ printf (" Dir %s\n", newdir); return; } /* We call getcwd() in order to print the - * absolute pathname for a subdirectory. - */ + ** absolute pathname for a subdirectory. + */ getcwd (curdir, sizeof (curdir)); printf (" Dir %s:\n", curdir); /* Calling opendir() always with "." avoids - * fiddling around with pathname separators. - */ + ** fiddling around with pathname separators. + */ dir = opendir ("."); while (ent = readdir (dir)) { @@ -54,9 +54,9 @@ void printdir (char *newdir) } /* We defer handling of subdirectories until we're done with the - * current one as several targets don't support other disk i/o - * while reading a directory (see cc65 readdir() doc for more). - */ + ** current one as several targets don't support other disk i/o + ** while reading a directory (see cc65 readdir() doc for more). + */ if (_DE_ISDIR (ent->d_type)) { subdirs = realloc (subdirs, FILENAME_MAX * (dirnum + 1)); strcpy (subdirs + FILENAME_MAX * dirnum++, ent->d_name); @@ -79,15 +79,15 @@ void main (void) char devicedir[FILENAME_MAX]; /* Calling getfirstdevice()/getnextdevice() does _not_ turn on the motor - * of a drive-type device and does _not_ check for a disk in the drive. - */ + ** of a drive-type device and does _not_ check for a disk in the drive. + */ device = getfirstdevice (); while (device != INVALID_DEVICE) { printf ("Device %d:\n", device); /* Calling getdevicedir() _does_ check for a (formatted) disk in a - * floppy-disk-type device and returns NULL if that check fails. - */ + ** floppy-disk-type device and returns NULL if that check fails. + */ if (getdevicedir (device, devicedir, sizeof (devicedir))) { printdir (devicedir); } else { diff --git a/samples/fire.c b/samples/fire.c index cae922509..44eb07c88 100644 --- a/samples/fire.c +++ b/samples/fire.c @@ -1,12 +1,12 @@ -/***************************************************************************** - * fire test program for cc65. * - * * - * (w)2002 by groepaz/hitmen * - * * - * Cleanup and porting by Ullrich von Bassewitz. * - * 2004-06-08, Greg King * - * * - *****************************************************************************/ +/*****************************************************************************\ +** fire test program for cc65. ** +** ** +** (w)2002 by groepaz/hitmen ** +** ** +** Cleanup and porting by Ullrich von Bassewitz. ** +** 2004-06-08, Greg King ** +** ** +\*****************************************************************************/ @@ -187,8 +187,8 @@ int main (void) #endif #if defined(__C128__) /* Save and change some flags, so that kernal/basic interrupt handler will - * not interfere with our routine. - */ + ** not interfere with our routine. + */ initflag = *(unsigned char*) 0xA04; *(unsigned char*) 0xA04 &= 0xFE; graphflag = *(unsigned char*) 0xD8; diff --git a/samples/geos/bitmap-demo.c b/samples/geos/bitmap-demo.c index 0e7d0d2aa..48daede9d 100644 --- a/samples/geos/bitmap-demo.c +++ b/samples/geos/bitmap-demo.c @@ -1,12 +1,12 @@ /* - * Minimalistic GEOSLib bitmap demo program - * - * 2012-06-10, Oliver Schmidt (ol.sc@web.de) - * - * To create bitmap.c use the sp65 sprite and bitmap utility: - * sp65 -r logo.pcx -c geos-bitmap -w bitmap.c,ident=bitmap - * - */ +** Minimalistic GEOSLib bitmap demo program +** +** 2012-06-10, Oliver Schmidt (ol.sc@web.de) +** +** To create bitmap.c use the sp65 sprite and bitmap utility: +** sp65 -r logo.pcx -c geos-bitmap -w bitmap.c,ident=bitmap +** +*/ #include <conio.h> diff --git a/samples/geos/dialog.c b/samples/geos/dialog.c index 55f98bf01..27199a493 100644 --- a/samples/geos/dialog.c +++ b/samples/geos/dialog.c @@ -1,7 +1,7 @@ /* Note: - * This is just a sample piece of code that shows how to use some structs - - * it may not even run. - */ +** This is just a sample piece of code that shows how to use some structs - +** it may not even run. +*/ #include <geos.h> diff --git a/samples/geos/grphstr.c b/samples/geos/grphstr.c index 928e7a06c..0e36ec021 100644 --- a/samples/geos/grphstr.c +++ b/samples/geos/grphstr.c @@ -1,7 +1,7 @@ /* Note: - * This is just a sample piece of code that shows how to use some structs - - * it may not even run. - */ +** This is just a sample piece of code that shows how to use some structs - +** it may not even run. +*/ #include <geos.h> diff --git a/samples/geos/inittab.c b/samples/geos/inittab.c index 843275e69..c0d75c2ec 100644 --- a/samples/geos/inittab.c +++ b/samples/geos/inittab.c @@ -1,7 +1,7 @@ /* Note: - * This is just a sample piece of code that shows how to use some structs - - * it may not even run. - */ +** This is just a sample piece of code that shows how to use some structs - +** it may not even run. +*/ #include <geos.h> diff --git a/samples/geos/menu.c b/samples/geos/menu.c index 3b5f9da82..54f72c4ab 100644 --- a/samples/geos/menu.c +++ b/samples/geos/menu.c @@ -1,7 +1,7 @@ /* Note: - * This is just a sample piece of code that shows how to use some structs - - * it may not even run. - */ +** This is just a sample piece of code that shows how to use some structs - +** it may not even run. +*/ #include <geos.h> diff --git a/samples/geos/overlay-demo.c b/samples/geos/overlay-demo.c index 1f0bbf6f7..a37f6bdcb 100644 --- a/samples/geos/overlay-demo.c +++ b/samples/geos/overlay-demo.c @@ -1,9 +1,9 @@ /* - * Minimalistic GEOSLib overlay demo program - * - * 2012-01-01, Oliver Schmidt (ol.sc@web.de) - * - */ +** Minimalistic GEOSLib overlay demo program +** +** 2012-01-01, Oliver Schmidt (ol.sc@web.de) +** +*/ #include <stdio.h> @@ -12,9 +12,9 @@ /* Functions resident in an overlay can call back functions resident in the - * main program at any time without any precautions. The function show() is - * an example for such a function resident in the main program. - */ +** main program at any time without any precautions. The function show() is +** an example for such a function resident in the main program. +*/ void show(char *name) { char line1[40]; @@ -24,18 +24,18 @@ void show(char *name) } /* In a real-world overlay program one would probably not use a #pragma but - * rather place the all the code of certain source files into the overlay by - * compiling them with --code-name OVERLAY1. - */ +** rather place the all the code of certain source files into the overlay by +** compiling them with --code-name OVERLAY1. +*/ #pragma code-name(push, "OVERLAY1"); void foo(void) { /* Functions resident in an overlay can access all program variables and - * constants at any time without any precautions because those are never - * placed in overlays. The string constant "One" is an example for such - * a constant resident in the main program. - */ + ** constants at any time without any precautions because those are never + ** placed in overlays. The string constant "One" is an example for such + ** a constant resident in the main program. + */ show("One"); } @@ -78,18 +78,18 @@ void main(int /*argc*/, char *argv[]) } /* The macro definitions OVERLAY_ADDR and OVERLAY_SIZE were generated in - * overlay-demores.h by grc65. They contain the overlay area address and - * size specific to a certain program. - */ + ** overlay-demores.h by grc65. They contain the overlay area address and + ** size specific to a certain program. + */ if (ReadRecord(OVERLAY_ADDR, OVERLAY_SIZE)) { _poserror("ReadRecord.1"); return; } /* The linker makes sure that the call to foo() ends up at the right mem - * addr. However it's up to user to make sure that the - right - overlay - * is actually loaded before making the the call. - */ + ** addr. However, it's up to user to make sure that the -- right -- overlay + ** actually is loaded before making the call. + */ foo(); DlgBoxOk(CBOLDON "Overlay Demo - Main" CPLAINTEXT, @@ -101,8 +101,8 @@ void main(int /*argc*/, char *argv[]) } /* Replacing one overlay with another one can only happen from the main - * program. This implies that an overlay can never load another overlay. - */ + ** program. This implies that an overlay can never load another overlay. + */ if (ReadRecord(OVERLAY_ADDR, OVERLAY_SIZE)) { _poserror("ReadRecord.2"); return; diff --git a/samples/gunzip65.c b/samples/gunzip65.c index bc515f0ee..2ad029467 100644 --- a/samples/gunzip65.c +++ b/samples/gunzip65.c @@ -1,14 +1,14 @@ /* - * gunzip65 - a gunzip utility for 6502-based machines. - * - * Piotr Fusik <fox@scene.pl> - * - * This should be considered as a test of my zlib-compatible library - * rather than a real application. - * It's not user-friendly, fault-tolerant, whatever. - * However, it really works for real GZIP files, provided they are small - * enough to fit in buffer[] (after decompression!). - */ +** gunzip65 - a gunzip utility for 6502-based machines. +** +** Piotr Fusik <fox@scene.pl> +** +** This should be considered as a test of my zlib-compatible library +** rather than a real application. +** It's not user-friendly, fault-tolerant, whatever. +** However, it really works for real GZIP files, provided they are small +** enough to fit in buffer[] (after decompression!). +*/ #include <stdio.h> #include <string.h> @@ -16,9 +16,9 @@ #ifndef __CC65__ /* - * Emulate inflatemem() if using original zlib. - * As you can see, this program is quite portable. - */ +** Emulate inflatemem() if using original zlib. +** As you can see, this program is quite portable. +*/ unsigned inflatemem(char* dest, const char* source) { z_stream stream; @@ -41,26 +41,26 @@ unsigned inflatemem(char* dest, const char* source) #endif /* __CC65__ */ /* - * Structure of a GZIP file: - * - * 1. GZIP header: - * Offset 0: Signature (2 bytes: 0x1f, 0x8b) - * Offset 2: Compression method (1 byte: 8 == "deflate") - * Offset 3: Flags (1 byte: see below) - * Offset 4: File date and time (4 bytes) - * Offset 8: Extra flags (1 byte) - * Offset 9: Target OS (1 byte: DOS, Amiga, Unix, etc.) - * if (flags & FEXTRA) { 2 bytes of length, then length bytes } - * if (flags & FNAME) { ASCIIZ filename } - * if (flags & FCOMMENT) { ASCIIZ comment } - * if (flags & FHCRC) { 2 bytes of CRC } - * - * 2. Deflate compressed data. - * - * 3. GZIP trailer: - * Offset 0: CRC-32 (4 bytes) - * Offset 4: uncompressed file length (4 bytes) - */ +** Structure of a GZIP file: +** +** 1. GZIP header: +** Offset 0: Signature (2 bytes: 0x1f, 0x8b) +** Offset 2: Compression method (1 byte: 8 == "deflate") +** Offset 3: Flags (1 byte: see below) +** Offset 4: File date and time (4 bytes) +** Offset 8: Extra flags (1 byte) +** Offset 9: Target OS (1 byte: DOS, Amiga, Unix, etc.) +** if (flags & FEXTRA) { 2 bytes of length, then length bytes } +** if (flags & FNAME) { ASCIIZ filename } +** if (flags & FCOMMENT) { ASCIIZ comment } +** if (flags & FHCRC) { 2 bytes of CRC } +** +** 2. Deflate compressed data. +** +** 3. GZIP trailer: +** Offset 0: CRC-32 (4 bytes) +** Offset 4: uncompressed file length (4 bytes) +*/ /* Flags in the GZIP header. */ #define FTEXT 1 /* Extra text */ @@ -70,28 +70,28 @@ unsigned inflatemem(char* dest, const char* source) #define FCOMMENT 16 /* File comment */ /* - * We read whole GZIP file into this buffer. - * Then we use this buffer for the decompressed data. - */ +** We read whole GZIP file into this buffer. +** Then we use this buffer for the decompressed data. +*/ static unsigned char buffer[26000]; /* - * Get a 16-bit little-endian unsigned number, using unsigned char* p. - * On many machines this could be (*(unsigned short*) p), - * but I really like portability. :-) - */ +** Get a 16-bit little-endian unsigned number, using unsigned char* p. +** On many machines this could be (*(unsigned short*) p), +** but I really like portability. :-) +*/ #define GET_WORD(p) (*(p) + ((unsigned) (p)[1] << 8)) /* Likewise, for a 32-bit number. */ #define GET_LONG(p) (GET_WORD(p) + ((unsigned long) GET_WORD(p + 2) << 16)) /* - * Uncompress a GZIP file. - * On entry, buffer[] should contain the whole GZIP file contents, - * and the argument complen should be equal to the length of the GZIP file. - * On return, buffer[] contains the uncompressed data, and the returned - * value is the length of the uncompressed data. - */ +** Uncompress a GZIP file. +** On entry, buffer[] should contain the whole GZIP file contents, +** and the argument complen should be equal to the length of the GZIP file. +** On return, buffer[] contains the uncompressed data, and the returned +** value is the length of the uncompressed data. +*/ unsigned uncompress_buffer(unsigned complen) { unsigned char* ptr; @@ -134,19 +134,19 @@ unsigned uncompress_buffer(unsigned complen) ptr += 2; /* - * calculate length of raw "deflate" data - * (without the GZIP header and 8-byte trailer) - */ + ** calculate length of raw "deflate" data + ** (without the GZIP header and 8-byte trailer) + */ complen -= (ptr - buffer) + 8; /* - * We will move the compressed data to the end of buffer[]. - * Thus the compressed data and the decompressed data (written from - * the beginning of buffer[]) may overlap, as long as the decompressed - * data doesn't go further than unread compressed data. - * ptr2 points to the beginning of compressed data at the end - * of buffer[]. - */ + ** We will move the compressed data to the end of buffer[]. + ** Thus the compressed data and the decompressed data (written from + ** the beginning of buffer[]) may overlap, as long as the decompressed + ** data doesn't go further than unread compressed data. + ** ptr2 points to the beginning of compressed data at the end + ** of buffer[]. + */ ptr2 = buffer + sizeof(buffer) - complen; /* move the compressed data to end of buffer[] */ memmove(ptr2, ptr, complen); @@ -173,8 +173,8 @@ unsigned uncompress_buffer(unsigned complen) } /* - * Get a filename from standard input. - */ +** Get a filename from standard input. +*/ char* get_fname(void) { static char filename[100]; diff --git a/samples/hello.c b/samples/hello.c index dcd6d6884..90a1d4bdc 100644 --- a/samples/hello.c +++ b/samples/hello.c @@ -1,9 +1,9 @@ /* - * Fancy hello world program using cc65. - * - * Ullrich von Bassewitz (ullrich@von-bassewitz.de) - * - */ +** Fancy hello world program using cc65. +** +** Ullrich von Bassewitz (ullrich@von-bassewitz.de) +** +*/ diff --git a/samples/mandelbrot.c b/samples/mandelbrot.c index 0ba4ebd2c..5d3d661c9 100644 --- a/samples/mandelbrot.c +++ b/samples/mandelbrot.c @@ -1,8 +1,8 @@ -/***************************************************************************** - * mandelbrot sample program for cc65. * - * * - * (w)2002 by groepaz/hitmen, TGI support by Stefan Haubenthal * - *****************************************************************************/ +/*****************************************************************************\ +** mandelbrot sample program for cc65. ** +** ** +** (w) 2002 by groepaz/hitmen, TGI support by Stefan Haubenthal ** +\*****************************************************************************/ diff --git a/samples/multidemo.c b/samples/multidemo.c index 367ce39e1..74039cfd6 100644 --- a/samples/multidemo.c +++ b/samples/multidemo.c @@ -1,9 +1,12 @@ /* - * Extended memory overlay demo program. - * - * 2012-17-07, Oliver Schmidt (ol.sc@web.de) - * - */ +** Extended memory overlay demo program. +** +** Shows how to combine multiple cc65 features +** incl. overlays and extended memory drivers. +** +** 2012-17-07, Oliver Schmidt (ol.sc@web.de) +** +*/ @@ -22,9 +25,9 @@ /* The symbols _OVERLAY?_LOAD__ and _OVERLAY?_SIZE__ were generated by the - * linker. They contain the overlay area address and size specific to a - * certain program. - */ +** linker. They contain the overlay area address and size specific to a +** certain program. +*/ extern void _OVERLAY1_LOAD__[], _OVERLAY1_SIZE__[]; extern void _OVERLAY2_LOAD__[], _OVERLAY2_SIZE__[]; extern void _OVERLAY3_LOAD__[], _OVERLAY3_SIZE__[]; @@ -42,24 +45,24 @@ struct { /* Functions resident in an overlay can call back functions resident in the - * main program at any time without any precautions. The function log() is - * an example for such a function resident in the main program. - */ +** main program at any time without any precautions. The function log() is +** an example for such a function resident in the main program. +*/ void log (char *msg) { /* Functions resident in an overlay can access all program variables and - * constants at any time without any precautions because those are never - * placed in overlays. The string constant below is an example for such - * a constant resident in the main program. - */ + ** constants at any time without any precautions because those are never + ** placed in overlays. The string constant below is an example for such + ** a constant resident in the main program. + */ printf ("Log: %s\n", msg); } /* In a real-world overlay program one would probably not use a #pragma but - * rather place all the code of certain source files into the overlay by - * compiling them with --code-name OVERLAY1. - */ +** rather place all the code of certain source files into the overlay by +** compiling them with --code-name OVERLAY1. +*/ #pragma code-name (push, "OVERLAY1"); void foo (void) @@ -232,15 +235,15 @@ void main (void) log ("Calling overlay 1 from main"); /* The linker makes sure that the call to foo() ends up at the right mem - * addr. However it's up to user to make sure that the - right - overlay - * is actually loaded before making the the call. - */ + ** addr. However it's up to user to make sure that the - right - overlay + ** is actually loaded before making the the call. + */ foo (); } /* Replacing one overlay with another one can only happen from the main - * program. This implies that an overlay can never load another overlay. - */ + ** program. This implies that an overlay can never load another overlay. + */ if (loadoverlay (2)) { log ("Calling overlay 2 from main"); bar (); diff --git a/samples/nachtm.c b/samples/nachtm.c index 282df9abf..0b962fa5d 100644 --- a/samples/nachtm.c +++ b/samples/nachtm.c @@ -1,14 +1,14 @@ /* - * "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart, KV 525 - * - * First version in 1987 by - * Joachim von Bassewitz (joachim@von-bassewitz.de) and - * Ullrich von Bassewitz (ullrich@von-bassewitz.de). - * - * C conversion in 1998 by - * Ullrich von Bassewitz (ullrich@von-bassewitz.de) - * - */ +** "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart, KV 525 +** +** First version in 1987 by +** Joachim von Bassewitz (joachim@von-bassewitz.de) and +** Ullrich von Bassewitz (ullrich@von-bassewitz.de). +** +** C conversion in 1998 by +** Ullrich von Bassewitz (ullrich@von-bassewitz.de) +** +*/ @@ -28,17 +28,17 @@ /* Tables with voice data. - * - * Bit Description - * ------------------------------------------- - * 15 Pause bit. - * 12-14 Octave - * 8-11 Tone (index into frequency table) - * 7 Unused. Was thought as a control bit in the original version to - * change SID parameters, but this was never implemented. - * 0-6 Length of the tone in ticks. - * - */ +** +** Bit Description +** ------------------------------------------- +** 15 Pause bit. +** 12-14 Octave +** 8-11 Tone (index into frequency table) +** 7 Unused. Was thought as a control bit in the original version to +** change SID parameters, but this was never implemented. +** 0-6 Length of the tone in ticks. +** +*/ @@ -922,8 +922,8 @@ static clock_t StartTime; #define TICKS_PER_TONE 4 /* Done flag. Contains one bit for each voice. Will contain 0x07 if all - * voices have finished playing. - */ +** voices have finished playing. +*/ static unsigned char Done; @@ -1038,8 +1038,8 @@ static void DisplayTime (void) /* On the 510/610, the SID is in another bank (the system bank), so we cannot - * just write to the memory space. - */ +** just write to the memory space. +*/ #if defined(__CBM510__) || defined(__CBM610__) # define outb(addr,val) pokebsys ((unsigned)(addr), val) # define outw(addr,val) pokewsys ((unsigned)(addr), val) @@ -1149,9 +1149,9 @@ int main (void) } } else { /* Decrement the ticks. If this is the last tick of a tone, - * reset bit 0 of the trigger value and write it back to the - * SID to start the release phase. - */ + ** reset bit 0 of the trigger value and write it back to the + ** SID to start the release phase. + */ if (--(VC->Ticks) == 0) { outb (&Voice->ctrl, VC->Trigger & 0xFE); } diff --git a/samples/overlaydemo.c b/samples/overlaydemo.c index a3fb132e1..42e757153 100644 --- a/samples/overlaydemo.c +++ b/samples/overlaydemo.c @@ -1,9 +1,11 @@ /* - * Minimalistic overlay demo program. - * - * 2009-10-02, Oliver Schmidt (ol.sc@web.de) - * - */ +** Minimalistic overlay demo program. +** +** Shows how to load overlay files from disk. +** +** 2009-10-02, Oliver Schmidt (ol.sc@web.de) +** +*/ @@ -23,9 +25,9 @@ extern void _OVERLAY3_LOAD__[], _OVERLAY3_SIZE__[]; /* Functions resident in an overlay can call back functions resident in the - * main program at any time without any precautions. The function log() is - * an example for such a function resident in the main program. - */ +** main program at any time without any precautions. The function log() is +** an example for such a function resident in the main program. +*/ void log (char *msg) { printf ("Log: %s\n", msg); @@ -33,18 +35,18 @@ void log (char *msg) /* In a real-world overlay program one would probably not use a #pragma but - * rather place all the code of certain source files into the overlay by - * compiling them with --code-name OVERLAY1. - */ +** rather place all the code of certain source files into the overlay by +** compiling them with --code-name OVERLAY1. +*/ #pragma code-name (push, "OVERLAY1"); void foo (void) { /* Functions resident in an overlay can access all program variables and - * constants at any time without any precautions because those are never - * placed in overlays. The string constant below is an example for such - * a constant resident in the main program. - */ + ** constants at any time without any precautions because those are never + ** placed in overlays. The string constant below is an example for such + ** a constant resident in the main program. + */ log ("Calling main from overlay 1"); } @@ -102,23 +104,23 @@ void main (void) log ("Calling overlay 1 from main"); /* The symbols _OVERLAY1_LOAD__ and _OVERLAY1_SIZE__ were generated by the - * linker. They contain the overlay area address and size specific to a - * certain program. - */ + ** linker. They contain the overlay area address and size specific to a + ** certain program. + */ if (loadfile ("ovrldemo.1", _OVERLAY1_LOAD__, _OVERLAY1_SIZE__)) { /* The linker makes sure that the call to foo() ends up at the right mem - * addr. However it's up to user to make sure that the - right - overlay - * is actually loaded before making the the call. - */ + ** addr. However it's up to user to make sure that the - right - overlay + ** is actually loaded before making the the call. + */ foo (); } log ("Calling overlay 2 from main"); /* Replacing one overlay with another one can only happen from the main - * program. This implies that an overlay can never load another overlay. - */ + ** program. This implies that an overlay can never load another overlay. + */ if (loadfile ("ovrldemo.2", _OVERLAY2_LOAD__, _OVERLAY2_SIZE__)) { bar (); } diff --git a/samples/plasma.c b/samples/plasma.c index ef21ef60e..7b092ec81 100644 --- a/samples/plasma.c +++ b/samples/plasma.c @@ -1,11 +1,11 @@ -/***************************************************************************** - * plasma test program for cc65. * - * * - * (w)2001 by groepaz/hitmen * - * * - * Cleanup and porting by Ullrich von Bassewitz. * - * * - *****************************************************************************/ +/*****************************************************************************\ +** plasma test program for cc65. ** +** ** +** (w)2001 by groepaz/hitmen ** +** ** +** Cleanup and porting by Ullrich von Bassewitz. ** +** ** +\*****************************************************************************/ @@ -121,9 +121,9 @@ static void doplasma (register unsigned char* scrn) c2B -= 3; for (ii = 0; ii < 25; ++ii) { /* Unrolling the following loop will give a speed increase of - * nearly 100% (~24fps), but it will also increase the code - * size a lot. - */ + ** nearly 100% (~24fps), but it will also increase the code + ** size a lot. + */ for (i = 0; i < 40; ++i, ++scrn) { *scrn = (xbuf[i] + ybuf[ii]); } @@ -203,9 +203,9 @@ int main (void) outb (&CIA2.pra, (block & 0xFC) | ((SCREEN1 >> 14) ^ 0x03)); #endif #if defined(__C128__) - /* Save and change some flags, so that kernal/basic interupt handler will - * not interfere with our routine. - */ + /* Save and change some flags, so that kernal/basic interrupt handler will + ** not interfere with our routine. + */ initflag = *(unsigned char*) 0xA04; *(unsigned char*) 0xA04 &= 0xFE; graphflag = *(unsigned char*) 0xD8; diff --git a/samples/sieve.c b/samples/sieve.c index 9d166b768..9f110ec98 100644 --- a/samples/sieve.c +++ b/samples/sieve.c @@ -1,6 +1,6 @@ /* - * Calculate all primes up to a specific number. - */ +** Calculate all primes up to a specific number. +*/ diff --git a/samples/tgidemo.c b/samples/tgidemo.c index a7e3b10f6..a08020640 100644 --- a/samples/tgidemo.c +++ b/samples/tgidemo.c @@ -5,7 +5,6 @@ #include <ctype.h> #include <modload.h> #include <tgi.h> -#include <tgi/tgi-kernel.h> diff --git a/src/Makefile b/src/Makefile index 4a80a78fb..34706fab5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,6 @@ -ifeq ($(shell echo),) +ifneq ($(shell echo),) + CMD_EXE = 1 +endif PROGS = ar65 \ c1p65 \ @@ -13,38 +15,99 @@ PROGS = ar65 \ sim65 \ sp65 -ifdef prefix - CA65_INC = $(prefix)/lib/cc65/asminc - CC65_INC = $(prefix)/lib/cc65/include - LD65_LIB = $(prefix)/lib/cc65/lib - LD65_OBJ = $(prefix)/lib/cc65/lib - LD65_CFG = $(prefix)/lib/cc65/cfg +.PHONY: all mostlyclean clean install zip avail unavail bin $(PROGS) + +.SUFFIXES: + +bindir := $(prefix)/bin +datadir := $(if $(prefix),$(prefix)/share/cc65,$(abspath ..)) + +CA65_INC = $(datadir)/asminc +CC65_INC = $(datadir)/include +LD65_LIB = $(datadir)/lib +LD65_OBJ = $(datadir)/lib +LD65_CFG = $(datadir)/cfg + +ifdef CMD_EXE + NULLDEV = nul: + DIRLIST = $(strip $(foreach dir,$1,$(wildcard $(dir)))) + MKDIR = mkdir $(subst /,\,$1) + RMDIR = $(if $(DIRLIST),rmdir /s /q $(subst /,\,$(DIRLIST))) else - CA65_INC := $(abspath ../asminc) - CC65_INC := $(abspath ../include) - LD65_LIB := $(abspath ../lib) - LD65_OBJ := $(abspath ../lib) - LD65_CFG := $(abspath ../cfg) + NULLDEV = /dev/null + MKDIR = mkdir -p $1 + RMDIR = $(RM) -r $1 endif -CFLAGS += -MMD -MP -O -std=c89 -I common \ - -Wall -Wextra -Wno-char-subscripts -Werror \ - -DCA65_INC=$(CA65_INC) -DCC65_INC=$(CC65_INC) \ +CC = $(CROSS_COMPILE)gcc +AR = $(CROSS_COMPILE)ar + +ifdef CROSS_COMPILE + $(info CC: $(CC)) + $(info AR: $(AR)) +endif + +ifdef USER_CFLAGS + $(info USER_CFLAGS: $(USER_CFLAGS)) +endif + +ifdef GIT_SHA + $(info GIT_SHA: $(GIT_SHA)) +else + GIT_SHA := $(shell git rev-parse --short HEAD 2>$(NULLDEV)) + ifneq ($(words $(GIT_SHA)),1) + GIT_SHA := N/A + $(info GIT_SHA: N/A) + endif +endif + +CFLAGS += -MMD -MP -O -I common \ + -Wall -Wextra -Wno-char-subscripts $(USER_CFLAGS) \ + -DGIT_SHA=$(GIT_SHA) -DCA65_INC=$(CA65_INC) -DCC65_INC=$(CC65_INC) \ -DLD65_LIB=$(LD65_LIB) -DLD65_OBJ=$(LD65_OBJ) -DLD65_CFG=$(LD65_CFG) LDLIBS += -lm -.SUFFIXES: +ifdef CMD_EXE + EXE_SUFFIX=.exe +endif -.PHONY: all bin $(PROGS) mostlyclean clean avail unavail +ifdef CROSS_COMPILE + EXE_SUFFIX=.exe +endif all bin: $(PROGS) mostlyclean: - $(RM) -r ../wrk + $(call RMDIR,../wrk) clean: - $(RM) -r ../wrk ../bin + $(call RMDIR,../wrk ../bin) + +ifdef CMD_EXE + +install avail unavail: + +else # CMD_EXE + +INSTALL = install + +define AVAIL_recipe + +ln -s $(abspath ../bin/$(prog)) /usr/local/bin/$(prog) + +endef # AVAIL_recipe + +define UNAVAIL_recipe + +$(RM) /usr/local/bin/$(prog) + +endef # UNAVAIL_recipe + +install: + $(if $(prefix),,$(error variable `prefix' must be set)) + $(INSTALL) -d $(DESTDIR)$(bindir) + $(INSTALL) ../bin/* $(DESTDIR)$(bindir) avail: $(foreach prog,$(PROGS),$(AVAIL_recipe)) @@ -52,23 +115,10 @@ avail: unavail: $(foreach prog,$(PROGS),$(UNAVAIL_recipe)) -########## +endif # CMD_EXE -define AVAIL_recipe - -ln -s $(abspath ../bin/$(prog)) /usr/local/bin/$(prog) - -endef - -########## - -define UNAVAIL_recipe - -$(RM) /usr/local/bin/$(prog) - -endef - -########## +zip: + @cd .. && zip cc65 bin/* define OBJS_template @@ -77,55 +127,35 @@ $1_OBJS := $$(patsubst %.c,../wrk/%.o,$$(wildcard $1/*.c)) $$($1_OBJS): | ../wrk/$1 ../wrk/$1: - @mkdir -p $$@ + @$$(call MKDIR,$$@) DEPS += $$($1_OBJS:.o=.d) -endef - -########## +endef # OBJS_template define PROG_template $$(eval $$(call OBJS_template,$1)) -../bin/$1: $$($1_OBJS) ../wrk/common/common.a | ../bin +../bin/$1$(EXE_SUFFIX): $$($1_OBJS) ../wrk/common/common.a | ../bin $$(CC) $$(LDFLAGS) -o $$@ $$^ $$(LDLIBS) -$1: ../bin/$1 +$1: ../bin/$1$(EXE_SUFFIX) -endef - -########## +endef # PROG_template ../wrk/%.o: %.c @echo $< @$(CC) -c $(CFLAGS) -o $@ $< ../bin: - @mkdir $@ + @$(call MKDIR,$@) $(eval $(call OBJS_template,common)) + ../wrk/common/common.a: $(common_OBJS) $(AR) r $@ $? $(foreach prog,$(PROGS),$(eval $(call PROG_template,$(prog)))) -include $(DEPS) - -else # cmd.exe - -.SUFFIXES: - -.PHONY: all bin mostlyclean clean - -all bin: - msbuild cc65.sln /p:configuration=release /consoleloggerparameters:disableconsolecolor - -mostlyclean: - $(if $(wildcard ../wrk),rmdir /s /q ..\wrk) - -clean: - msbuild cc65.sln /p:configuration=release /consoleloggerparameters:disableconsolecolor /target:$@ - -endif # cmd.exe diff --git a/src/ar65.vcxproj b/src/ar65.vcxproj index e83f0f984..b077134ce 100644 --- a/src/ar65.vcxproj +++ b/src/ar65.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -18,10 +18,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -47,7 +49,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> @@ -62,7 +64,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> diff --git a/src/ar65/add.c b/src/ar65/add.c index cecb89292..a44524368 100644 --- a/src/ar65/add.c +++ b/src/ar65/add.c @@ -77,7 +77,3 @@ void AddObjFiles (int argc, char* argv []) /* Successful end */ exit (EXIT_SUCCESS); } - - - - diff --git a/src/ar65/add.h b/src/ar65/add.h index abaf017b6..c3de2bb0a 100644 --- a/src/ar65/add.h +++ b/src/ar65/add.h @@ -52,7 +52,3 @@ void AddObjFiles (int argc, char* argv []); /* End of add.h */ #endif - - - - diff --git a/src/ar65/del.c b/src/ar65/del.c index d95c012f9..0c1343de3 100644 --- a/src/ar65/del.c +++ b/src/ar65/del.c @@ -78,7 +78,3 @@ void DelObjFiles (int argc, char* argv []) /* Successful end */ exit (EXIT_SUCCESS); } - - - - diff --git a/src/ar65/del.h b/src/ar65/del.h index f25672609..6100fe60a 100644 --- a/src/ar65/del.h +++ b/src/ar65/del.h @@ -52,7 +52,3 @@ void DelObjFiles (int argc, char* argv []); /* End of del.h */ #endif - - - - diff --git a/src/ar65/error.c b/src/ar65/error.c index d21c9e9b7..47ee90aa5 100644 --- a/src/ar65/error.c +++ b/src/ar65/error.c @@ -89,6 +89,3 @@ void Internal (const char* Format, ...) va_end (ap); exit (EXIT_FAILURE); } - - - diff --git a/src/ar65/error.h b/src/ar65/error.h index abff5bd2a..4052ee3eb 100644 --- a/src/ar65/error.h +++ b/src/ar65/error.h @@ -63,6 +63,3 @@ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)) /* End of error.h */ #endif - - - diff --git a/src/ar65/exports.c b/src/ar65/exports.c index 75a1986e8..af176d019 100644 --- a/src/ar65/exports.c +++ b/src/ar65/exports.c @@ -130,8 +130,8 @@ void ExpInsert (const char* Name, const ObjData* Module) const ObjData* ExpFind (const char* Name) /* Check for an identifier in the list. Return NULL if not found, otherwise - * return a pointer to the module, that exports the identifer. - */ +** return a pointer to the module, that exports the identifer. +*/ { /* Get a pointer to the list with the symbols hash value */ HashEntry* L = HashTab [HashStr (Name) % HASHTAB_SIZE]; @@ -147,6 +147,3 @@ const ObjData* ExpFind (const char* Name) /* Not found */ return 0; } - - - diff --git a/src/ar65/exports.h b/src/ar65/exports.h index 272b19d63..054b5153c 100644 --- a/src/ar65/exports.h +++ b/src/ar65/exports.h @@ -59,14 +59,11 @@ void ExpInsert (const char* Name, const struct ObjData* Module); const struct ObjData* ExpFind (const char* Name); /* Check for an identifier in the list. Return NULL if not found, otherwise - * return a pointer to the module, that exports the identifer. - */ +** return a pointer to the module, that exports the identifer. +*/ /* End of exports.h */ #endif - - - diff --git a/src/ar65/extract.c b/src/ar65/extract.c index 43d7c5b3b..c1a8fd82b 100644 --- a/src/ar65/extract.c +++ b/src/ar65/extract.c @@ -77,6 +77,3 @@ void ExtractObjFiles (int argc, char* argv []) /* Successful end */ exit (EXIT_SUCCESS); } - - - diff --git a/src/ar65/extract.h b/src/ar65/extract.h index 705d2c8e1..d09368c73 100644 --- a/src/ar65/extract.h +++ b/src/ar65/extract.h @@ -52,7 +52,3 @@ void ExtractObjFiles (int argc, char* argv []); /* End of extract.h */ #endif - - - - diff --git a/src/ar65/fileio.c b/src/ar65/fileio.c index 0bd925f15..8e17cbfac 100644 --- a/src/ar65/fileio.c +++ b/src/ar65/fileio.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -84,10 +84,10 @@ void WriteVar (FILE* F, unsigned long V) /* Write a variable sized value to the file in special encoding */ { /* We will write the value to the file in 7 bit chunks. If the 8th bit - * is clear, we're done, if it is set, another chunk follows. This will - * allow us to encode smaller values with less bytes, at the expense of - * needing 5 bytes if a 32 bit value is written to file. - */ + ** is clear, we're done, if it is set, another chunk follows. This will + ** allow us to encode smaller values with less bytes, at the expense of + ** needing 5 bytes if a 32 bit value is written to file. + */ do { unsigned char C = (V & 0x7F); V >>= 7; @@ -156,8 +156,8 @@ unsigned long ReadVar (FILE* F) /* Read a variable size value from the file */ { /* The value was written to the file in 7 bit chunks LSB first. If there - * are more bytes, bit 8 is set, otherwise it is clear. - */ + ** are more bytes, bit 8 is set, otherwise it is clear. + */ unsigned char C; unsigned long V = 0; unsigned Shift = 0; @@ -201,54 +201,3 @@ void* ReadData (FILE* F, void* Data, unsigned Size) } return Data; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ar65/fileio.h b/src/ar65/fileio.h index 0c69f7c13..17a3d2d0d 100644 --- a/src/ar65/fileio.h +++ b/src/ar65/fileio.h @@ -89,6 +89,3 @@ void* ReadData (FILE* F, void* Data, unsigned Size); /* End of fileio.h */ #endif - - - diff --git a/src/ar65/global.c b/src/ar65/global.c index 02157f08b..75eadc0a7 100644 --- a/src/ar65/global.c +++ b/src/ar65/global.c @@ -40,6 +40,3 @@ /*****************************************************************************/ /* Data */ /*****************************************************************************/ - - - diff --git a/src/ar65/global.h b/src/ar65/global.h index f35452d5c..9b8f128f9 100644 --- a/src/ar65/global.h +++ b/src/ar65/global.h @@ -47,6 +47,3 @@ /* End of global.h */ #endif - - - diff --git a/src/ar65/library.c b/src/ar65/library.c index 9046e315f..c72e6e3cf 100644 --- a/src/ar65/library.c +++ b/src/ar65/library.c @@ -64,10 +64,11 @@ /* Name of the library file */ const char* LibName = 0; +static char* NewLibName = 0; /* File descriptor for the library file */ -FILE* NewLib = 0; static FILE* Lib = 0; +static FILE* NewLib = 0; /* The library header */ static LibHeader Header = { @@ -215,9 +216,9 @@ static void WriteIndex (void) void LibOpen (const char* Name, int MustExist, int NeedTemp) /* Open an existing library and a temporary copy. If MustExist is true, the - * old library is expected to exist. If NeedTemp is true, a temporary library - * is created. - */ +** old library is expected to exist. If NeedTemp is true, a temporary library +** is created. +*/ { /* Remember the name */ LibName = xstrdup (Name); @@ -246,10 +247,16 @@ void LibOpen (const char* Name, int MustExist, int NeedTemp) } if (NeedTemp) { + + /* Create the temporary library name */ + NewLibName = xmalloc (strlen (Name) + strlen (".temp") + 1); + strcpy (NewLibName, Name); + strcat (NewLibName, ".temp"); + /* Create the temporary library */ - NewLib = tmpfile (); + NewLib = fopen (NewLibName, "w+b"); if (NewLib == 0) { - Error ("Cannot create temporary file: %s", strerror (errno)); + Error ("Cannot create temporary library file: %s", strerror (errno)); } /* Write a dummy header to the temp file */ @@ -261,8 +268,8 @@ void LibOpen (const char* Name, int MustExist, int NeedTemp) unsigned long LibCopyTo (FILE* F, unsigned long Bytes) /* Copy data from F to the temp library file, return the start position in - * the temporary library file. - */ +** the temporary library file. +*/ { unsigned char Buf [4096]; @@ -304,8 +311,8 @@ void LibCopyFrom (unsigned long Pos, unsigned long Bytes, FILE* F) static void LibCheckExports (ObjData* O) /* Insert all exports from the given object file into the global list - * checking for duplicates. - */ +** checking for duplicates. +*/ { unsigned I; @@ -328,8 +335,8 @@ static void LibCheckExports (ObjData* O) void LibClose (void) /* Write remaining data, close both files and copy the temp file to the old - * filename - */ +** filename +*/ { /* Do we have a temporary library? */ if (NewLib) { @@ -339,9 +346,9 @@ void LibClose (void) size_t Count; /* Walk through the object file list, inserting exports into the - * export list checking for duplicates. Copy any data that is still - * in the old library into the new one. - */ + ** export list checking for duplicates. Copy any data that is still + ** in the old library into the new one. + */ for (I = 0; I < CollCount (&ObjPool); ++I) { /* Get a pointer to the object */ @@ -378,7 +385,7 @@ void LibClose (void) LibName, strerror (errno)); } - /* Copy the new library to the new one */ + /* Copy the temporary library to the new one */ fseek (NewLib, 0, SEEK_SET); while ((Count = fread (Buf, 1, sizeof (Buf), NewLib)) != 0) { if (fwrite (Buf, 1, Count, Lib) != Count) { @@ -394,7 +401,7 @@ void LibClose (void) if (NewLib && fclose (NewLib) != 0) { Error ("Problem closing temporary library file: %s", strerror (errno)); } + if (NewLibName && remove (NewLibName) != 0) { + Error ("Problem deleting temporary library file: %s", strerror (errno)); + } } - - - diff --git a/src/ar65/library.h b/src/ar65/library.h index abb8c475f..861d56a78 100644 --- a/src/ar65/library.h +++ b/src/ar65/library.h @@ -51,9 +51,6 @@ /* Name of the library file */ extern const char* LibName; -/* File descriptor for the new library file */ -extern FILE* NewLib; - /*****************************************************************************/ @@ -64,28 +61,25 @@ extern FILE* NewLib; void LibOpen (const char* Name, int MustExist, int NeedTemp); /* Open an existing library and a temporary copy. If MustExist is true, the - * old library is expected to exist. If NeedTemp is true, a temporary library - * is created. - */ +** old library is expected to exist. If NeedTemp is true, a temporary library +** is created. +*/ unsigned long LibCopyTo (FILE* F, unsigned long Bytes); /* Copy data from F to the temp library file, return the start position in - * the temporary library file. - */ +** the temporary library file. +*/ void LibCopyFrom (unsigned long Pos, unsigned long Bytes, FILE* F); /* Copy data from the library file into another file */ void LibClose (void); /* Write remaining data, close both files and copy the temp file to the old - * filename - */ +** filename +*/ /* End of library.h */ #endif - - - diff --git a/src/ar65/list.c b/src/ar65/list.c index a3536c7d2..656299860 100644 --- a/src/ar65/list.c +++ b/src/ar65/list.c @@ -84,6 +84,3 @@ void ListObjFiles (int argc, char* argv []) /* Successful end */ exit (EXIT_SUCCESS); } - - - diff --git a/src/ar65/list.h b/src/ar65/list.h index ea6a62512..f29323b2e 100644 --- a/src/ar65/list.h +++ b/src/ar65/list.h @@ -52,7 +52,3 @@ void ListObjFiles (int argc, char* argv []); /* End of list.h */ #endif - - - - diff --git a/src/ar65/main.c b/src/ar65/main.c index 9af480632..9b9097ea4 100644 --- a/src/ar65/main.c +++ b/src/ar65/main.c @@ -137,6 +137,3 @@ int main (int argc, char* argv []) /* Return an apropriate exit code */ return EXIT_SUCCESS; } - - - diff --git a/src/ar65/objdata.c b/src/ar65/objdata.c index b419fac4d..5a8f0c5fb 100644 --- a/src/ar65/objdata.c +++ b/src/ar65/objdata.c @@ -122,8 +122,8 @@ void ClearObjData (ObjData* O) ObjData* FindObjData (const char* Module) /* Search for the module with the given name and return it. Return NULL if the - * module is not in the list. - */ +** module is not in the list. +*/ { unsigned I; @@ -167,6 +167,3 @@ void DelObjData (const char* Module) /* Not found! */ Warning ("Module `%s' not found in library `%s'", Module, LibName); } - - - diff --git a/src/ar65/objdata.h b/src/ar65/objdata.h index 52e175e84..3ae8e2949 100644 --- a/src/ar65/objdata.h +++ b/src/ar65/objdata.h @@ -97,8 +97,8 @@ void ClearObjData (ObjData* O); ObjData* FindObjData (const char* Module); /* Search for the module with the given name and return it. Return NULL if the - * module is not in the list. - */ +** module is not in the list. +*/ void DelObjData (const char* Module); /* Delete the object module from the list */ @@ -108,6 +108,3 @@ void DelObjData (const char* Module); /* End of objdata.h */ #endif - - - diff --git a/src/ar65/objfile.c b/src/ar65/objfile.c index 4f937a5de..0434f7e59 100644 --- a/src/ar65/objfile.c +++ b/src/ar65/objfile.c @@ -168,8 +168,8 @@ static void SkipLineInfoList (FILE* F) void ObjReadData (FILE* F, ObjData* O) /* Read object file data from the given file. The function expects the Name - * and Start fields to be valid. Header and basic data are read. - */ +** and Start fields to be valid. Header and basic data are read. +*/ { unsigned long Count; @@ -239,14 +239,14 @@ void ObjAdd (const char* Name) Error ("Could not open `%s': %s", Name, strerror (errno)); } - /* Get the modification time of the object file. There a race condition - * here, since we cannot use fileno() (non standard identifier in standard - * header file), and therefore not fstat. When using stat with the - * file name, there's a risk that the file was deleted and recreated - * while it was open. Since mtime and size are only used to check - * if a file has changed in the debugger, we will ignore this problem - * here. - */ + /* Get the modification time of the object file. There's a race condition + ** here, since we cannot use fileno() (non-standard identifier in standard + ** header file), and therefore not fstat. When using stat with the + ** file name, there's a risk that the file was deleted and recreated + ** while it was open. Since mtime and size are only used to check + ** if a file has changed in the debugger, we will ignore this problem + ** here. + */ if (FileStat (Name, &StatBuf) != 0) { Error ("Cannot stat object file `%s': %s", Name, strerror (errno)); } @@ -264,8 +264,8 @@ void ObjAdd (const char* Name) O = NewObjData (); } else { /* Found - check the file modification times of the internal copy - * and the external one. - */ + ** and the external one. + */ if (difftime ((time_t)O->MTime, StatBuf.st_mtime) > 0.0) { Warning ("Replacing module `%s' by older version in library `%s'", O->Name, LibName); @@ -289,8 +289,8 @@ void ObjAdd (const char* Name) ObjReadData (Obj, O); /* Copy the complete object data to the library file and update the - * starting offset - */ + ** starting offset + */ fseek (Obj, 0, SEEK_SET); O->Start = LibCopyTo (Obj, O->Size); @@ -323,8 +323,8 @@ void ObjExtract (const char* Name) } /* Copy the complete object file data from the library to the new object - * file. - */ + ** file. + */ LibCopyFrom (O->Start, O->Size, Obj); /* Close the file */ @@ -337,6 +337,3 @@ void ObjExtract (const char* Name) Error ("Cannot set mod time on `%s': %s", Name, strerror (errno)); } } - - - diff --git a/src/ar65/objfile.h b/src/ar65/objfile.h index 3f24c7c50..bc564c470 100644 --- a/src/ar65/objfile.h +++ b/src/ar65/objfile.h @@ -60,8 +60,8 @@ struct ObjData; void ObjReadData (FILE* F, struct ObjData* O); /* Read object file data from the given file. The function expects the Name - * and Start fields to be valid. Header and basic data are read. - */ +** and Start fields to be valid. Header and basic data are read. +*/ void ObjAdd (const char* Name); /* Add an object file to the library */ @@ -74,6 +74,3 @@ void ObjExtract (const char* Name); /* End of objfile.h */ #endif - - - diff --git a/src/ca65.vcxproj b/src/ca65.vcxproj index 747b836cd..4e02fa2a9 100644 --- a/src/ca65.vcxproj +++ b/src/ca65.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -18,10 +18,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -47,7 +49,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <TreatWarningAsError>true</TreatWarningAsError> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> </ClCompile> @@ -62,7 +64,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <TreatWarningAsError>true</TreatWarningAsError> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> </ClCompile> diff --git a/src/ca65/anonname.c b/src/ca65/anonname.c index d01ae2aa1..90b73fcab 100644 --- a/src/ca65/anonname.c +++ b/src/ca65/anonname.c @@ -59,9 +59,9 @@ static const char AnonTag[] = "$anon"; StrBuf* AnonName (StrBuf* Buf, const char* Spec) /* Get a name for an anonymous scope, variable or type. Size is the size of - * the buffer passed to the function, Spec will be used as part of the - * identifier if given. A pointer to the buffer is returned. - */ +** the buffer passed to the function, Spec will be used as part of the +** identifier if given. A pointer to the buffer is returned. +*/ { static unsigned ACount = 0; SB_Printf (Buf, "%s-%s-%04X", AnonTag, Spec, ++ACount); @@ -79,6 +79,3 @@ int IsAnonName (const StrBuf* Name) } return (strncmp (SB_GetConstBuf (Name), AnonTag, sizeof (AnonTag) - 1) == 0); } - - - diff --git a/src/ca65/anonname.h b/src/ca65/anonname.h index bfefc05b5..142cd9f87 100644 --- a/src/ca65/anonname.h +++ b/src/ca65/anonname.h @@ -51,9 +51,9 @@ StrBuf* AnonName (StrBuf* Buf, const char* Spec); /* Get a name for an anonymous scope, variable or type. Size is the size of - * the buffer passed to the function, Spec will be used as part of the - * identifier if given. A pointer to the buffer is returned. - */ +** the buffer passed to the function, Spec will be used as part of the +** identifier if given. A pointer to the buffer is returned. +*/ int IsAnonName (const StrBuf* Name); /* Check if the given symbol name is that of an anonymous symbol */ @@ -61,7 +61,5 @@ int IsAnonName (const StrBuf* Name); /* End of anonname.h */ + #endif - - - diff --git a/src/ca65/asserts.c b/src/ca65/asserts.c index a1a61a117..0d4c856a3 100644 --- a/src/ca65/asserts.c +++ b/src/ca65/asserts.c @@ -176,8 +176,3 @@ void WriteAssertions (void) /* Done writing the assertions */ ObjEndAssertions (); } - - - - - diff --git a/src/ca65/asserts.h b/src/ca65/asserts.h index f860a1af3..c69fe3be1 100644 --- a/src/ca65/asserts.h +++ b/src/ca65/asserts.h @@ -74,6 +74,3 @@ void WriteAssertions (void); /* End of asserts.h */ #endif - - - diff --git a/src/ca65/condasm.c b/src/ca65/condasm.c index 8be5cb687..24cbae696 100644 --- a/src/ca65/condasm.c +++ b/src/ca65/condasm.c @@ -104,9 +104,9 @@ static int GetOverallIfCond (void) /* Get the overall condition based on all conditions on the stack. */ { /* Since the last entry contains the overall condition of the parent, we - * must check it in combination of the current condition. If there is no - * last entry, the overall condition is true. - */ + ** must check it in combination of the current condition. If there is no + ** last entry, the overall condition is true. + */ return (IfCount == 0) || ((IfStack[IfCount-1].Flags & (ifCond | ifParentCond)) == (ifCond | ifParentCond)); } @@ -114,7 +114,7 @@ static int GetOverallIfCond (void) static void CalcOverallIfCond (void) -/* Caclulate the overall condition based on all conditions on the stack. */ +/* Calculate the overall condition, based on all conditions on the stack. */ { IfCond = GetOverallIfCond (); } @@ -256,9 +256,9 @@ void DoConditionals (void) NextTok (); /* Ignore the new condition if we are inside a false .ELSE - * branch. This way we won't get any errors about undefined - * symbols or similar... - */ + ** branch. This way we won't get any errors about undefined + ** symbols or similar... + */ if (IfCond) { SetIfCond (D, ConstExpression ()); ExpectSep (); @@ -273,8 +273,8 @@ void DoConditionals (void) FreeIf (); /* Be sure not to read the next token until the .IF stack - * has been cleanup up, since we may be at end of file. - */ + ** has been cleanup up, since we may be at end of file. + */ NextTok (); ExpectSep (); @@ -440,9 +440,9 @@ void DoConditionals (void) int CheckConditionals (void) /* Check if the current token is one that starts a conditional directive, and - * call DoConditionals if so. Return true if a conditional directive was found, - * return false otherwise. - */ +** call DoConditionals if so. Return true if a conditional directive was found, +** return false otherwise. +*/ { switch (CurTok.Tok) { case TOK_ELSE: @@ -473,15 +473,15 @@ int CheckConditionals (void) void CheckOpenIfs (void) /* Called from the scanner before closing an input file. Will check for any - * open .ifs in this file. - */ +** open .ifs in this file. +*/ { const LineInfo* LI; while (1) { /* Get the current file number and check if the topmost entry on the - * .IF stack was inserted with this file number - */ + ** .IF stack was inserted with this file number + */ IfDesc* D = GetCurrentIf (); if (D == 0) { /* There are no open .IFs */ @@ -523,7 +523,3 @@ void CleanupIfStack (unsigned SP) /* Calculate the new overall .IF condition */ CalcOverallIfCond (); } - - - - diff --git a/src/ca65/condasm.h b/src/ca65/condasm.h index 3489310d5..334ec862b 100644 --- a/src/ca65/condasm.h +++ b/src/ca65/condasm.h @@ -60,14 +60,14 @@ void DoConditionals (void); int CheckConditionals (void); /* Check if the current token is one that starts a conditional directive, and - * call DoConditionals if so. Return true if a conditional directive was found, - * return false otherwise. - */ +** call DoConditionals if so. Return true if a conditional directive was found, +** return false otherwise. +*/ void CheckOpenIfs (void); /* Called from the scanner before closing an input file. Will check for any - * open .ifs in this file. - */ +** open .ifs in this file. +*/ unsigned GetIfStack (void); /* Get the current .IF stack pointer */ @@ -80,6 +80,3 @@ void CleanupIfStack (unsigned SP); /* End of condasm.h */ #endif - - - diff --git a/src/ca65/dbginfo.c b/src/ca65/dbginfo.c index b1b845fc9..8a55f9ddc 100644 --- a/src/ca65/dbginfo.c +++ b/src/ca65/dbginfo.c @@ -130,8 +130,8 @@ static unsigned HexValue (char C) static int ValidateType (StrBuf* Type) /* Check if the given type is valid and if so, return a string id for it. If - * the type isn't valid, return -1. Type is overwritten when checking. - */ +** the type isn't valid, return -1. Type is overwritten when checking. +*/ { unsigned I; const char* A; @@ -311,8 +311,8 @@ void DbgInfoLine (void) } /* If a parameters follow, this is actual line info. If no parameters - * follow, the last line info is terminated. - */ + ** follow, the last line info is terminated. + */ if (CurTok.Tok == TOK_SEP) { return; } @@ -445,10 +445,10 @@ void DbgInfoCheck (void) /* Do checks on all hll debug info symbols when assembly is complete */ { /* When parsing the debug statements for HLL symbols, we have already - * tagged the functions to their asm counterparts. This wasn't done for - * C symbols, since we will allow forward declarations. So we have to - * resolve the normal C symbols now. - */ + ** tagged the functions to their asm counterparts. This wasn't done for + ** C symbols, since we will allow forward declarations. So we have to + ** resolve the normal C symbols now. + */ unsigned I; for (I = 0; I < CollCount (&HLLDbgSyms); ++I) { @@ -456,8 +456,8 @@ void DbgInfoCheck (void) HLLDbgSym* S = CollAtUnchecked (&HLLDbgSyms, I); /* Ignore functions and auto symbols, because the later live on the - * stack and don't have corresponding asm symbols. - */ + ** stack and don't have corresponding asm symbols. + */ if (HLL_IS_FUNC (S->Flags) || HLL_GET_SC (S->Flags) == HLL_SC_AUTO) { continue; } @@ -501,8 +501,8 @@ void WriteHLLDbgSyms (void) unsigned SC = HLL_GET_SC (S->Flags); /* Remember if the symbol has debug info attached - * ### This should go into DbgInfoCheck - */ + ** ### This should go into DbgInfoCheck + */ if (S->Sym && S->Sym->DebugSymId != ~0U) { S->Flags |= HLL_DATA_SYM; } @@ -527,6 +527,3 @@ void WriteHLLDbgSyms (void) } } - - - diff --git a/src/ca65/dbginfo.h b/src/ca65/dbginfo.h index 32cb3ca51..9f8139f6c 100644 --- a/src/ca65/dbginfo.h +++ b/src/ca65/dbginfo.h @@ -67,8 +67,3 @@ void WriteHLLDbgSyms (void); /* End of dbginfo.h */ #endif - - - - - diff --git a/src/ca65/ea.h b/src/ca65/ea.h index 5a65638a0..9a038047c 100644 --- a/src/ca65/ea.h +++ b/src/ca65/ea.h @@ -63,6 +63,3 @@ struct EffAddr { /* End of ea.h */ #endif - - - diff --git a/src/ca65/ea65.c b/src/ca65/ea65.c index 48c4a2c07..5f76f2966 100644 --- a/src/ca65/ea65.c +++ b/src/ca65/ea65.c @@ -110,7 +110,7 @@ void GetEA (EffAddr* A) A->AddrModeSet = AM65_DIR_IND_LONG_Y; } else { /* [dir] */ - A->AddrModeSet = AM65_DIR_IND_LONG; + A->AddrModeSet = AM65_DIR_IND_LONG | AM65_ABS_IND_LONG; } } else if (CurTok.Tok == TOK_LPAREN) { @@ -150,19 +150,19 @@ void GetEA (EffAddr* A) A->AddrModeSet = AM65_DIR_IND_Y; } else { /* (adr) */ - A->AddrModeSet = AM65_ABS_IND | AM65_DIR_IND; + A->AddrModeSet = AM65_ABS_IND | AM65_ABS_IND_LONG | AM65_DIR_IND; } } } else { /* Remaining stuff: - * - * adr - * adr,x - * adr,y - * adr,s - */ + ** + ** adr + ** adr,x + ** adr,y + ** adr,s + */ A->Expr = Expression (); if (CurTok.Tok == TOK_COMMA) { @@ -200,7 +200,3 @@ void GetEA (EffAddr* A) /* Apply addressing mode overrides */ A->AddrModeSet &= Restrictions; } - - - - diff --git a/src/ca65/ea65.h b/src/ca65/ea65.h index f7f8c2018..066d9b0cc 100644 --- a/src/ca65/ea65.h +++ b/src/ca65/ea65.h @@ -62,6 +62,3 @@ void GetEA (EffAddr* A); /* End of ea65.h */ #endif - - - diff --git a/src/ca65/easw16.c b/src/ca65/easw16.c index 6b3fe4f4c..578a25734 100644 --- a/src/ca65/easw16.c +++ b/src/ca65/easw16.c @@ -51,9 +51,9 @@ static long RegNum () /* Try to read a register number specified not as a register (Rx) but as a - * numeric value between 0 and 15. Return the register number or -1 on - * failure. - */ +** numeric value between 0 and 15. Return the register number or -1 on +** failure. +*/ { long Val; ExprNode* Expr = Expression (); @@ -126,8 +126,8 @@ void GetSweet16EA (EffAddr* A) A->AddrModeSet = AMSW16_BRA; /* If the value is a constant between 0 and 15, it may also be a - * register number. - */ + ** register number. + */ if (IsConstExpr (A->Expr, &Reg) && Reg >= 0 && Reg <= 15) { FreeExpr (A->Expr); A->Reg = (unsigned) Reg; diff --git a/src/ca65/enum.c b/src/ca65/enum.c index 08ef52fa6..f0561b692 100644 --- a/src/ca65/enum.c +++ b/src/ca65/enum.c @@ -151,7 +151,3 @@ void DoEnum (void) /* Free the base expression */ FreeExpr (BaseExpr); } - - - - diff --git a/src/ca65/enum.h b/src/ca65/enum.h index 5e85255f0..7d73a97b8 100644 --- a/src/ca65/enum.h +++ b/src/ca65/enum.h @@ -52,6 +52,3 @@ void DoEnum (void); /* End of enum.h */ #endif - - - diff --git a/src/ca65/error.c b/src/ca65/error.c index ffda60ecd..38195d669 100644 --- a/src/ca65/error.c +++ b/src/ca65/error.c @@ -128,10 +128,10 @@ static void AddNotifications (const Collection* LineInfos) unsigned Skipped; /* The basic line info is always in slot zero. It has been used to - * output the actual error or warning. The following slots may contain - * more information. Check them and print additional notifications if - * they're present, but limit the number to a reasonable value. - */ + ** output the actual error or warning. The following slots may contain + ** more information. Check them and print additional notifications if + ** they're present, but limit the number to a reasonable value. + */ for (I = 1, Output = 0, Skipped = 0; I < CollCount (LineInfos); ++I) { /* Get next line info */ const LineInfo* LI = CollConstAt (LineInfos, I); @@ -400,6 +400,3 @@ void Internal (const char* Format, ...) exit (EXIT_FAILURE); } - - - diff --git a/src/ca65/error.h b/src/ca65/error.h index d86e68c42..c6fb4f44e 100644 --- a/src/ca65/error.h +++ b/src/ca65/error.h @@ -38,6 +38,12 @@ +#if defined( __MINGW32__) +# pragma GCC diagnostic ignored "-Wformat" +#endif + + + /* common */ #include "attrib.h" #include "coll.h" @@ -98,7 +104,3 @@ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)) /* End of error.h */ #endif - - - - diff --git a/src/ca65/expr.c b/src/ca65/expr.c index ecbd22a27..e4d6f7363 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -72,11 +72,11 @@ /* Since all expressions are first packed into expression trees, and each - * expression tree node is allocated on the heap, we add some type of special - * purpose memory allocation here: Instead of freeing the nodes, we save some - * number of freed nodes for later and remember them in a single linked list - * using the Left link. - */ +** expression tree node is allocated on the heap, we add some type of special +** purpose memory allocation here: Instead of freeing the nodes, we save some +** number of freed nodes for later and remember them in a single linked list +** using the Left link. +*/ #define MAX_FREE_NODES 64 static ExprNode* FreeExprNodes = 0; static unsigned FreeNodeCount = 0; @@ -172,9 +172,9 @@ int IsFarRange (long Val) int IsEasyConst (const ExprNode* E, long* Val) /* Do some light checking if the given node is a constant. Don't care if E is - * a complex expression. If E is a constant, return true and place its value - * into Val, provided that Val is not NULL. - */ +** a complex expression. If E is a constant, return true and place its value +** into Val, provided that Val is not NULL. +*/ { /* Resolve symbols, follow symbol chains */ while (E->Op == EXPR_SYMBOL) { @@ -322,8 +322,8 @@ static ExprNode* Symbol (SymEntry* S) /* Mark the symbol as referenced */ SymRef (S); /* If the symbol is a variable, return just its value, otherwise - * return a reference to the symbol. - */ + ** return a reference to the symbol. + */ if (SymIsVar (S)) { return CloneExpr (GetSymExpr (S)); } else { @@ -355,16 +355,16 @@ static ExprNode* FuncBlank (void) /* Handle the .BLANK builtin function */ { /* We have a list of tokens that ends with the closing paren. Skip - * the tokens, and count them. Allow optionally curly braces. - */ + ** the tokens, and count them. Allow optionally curly braces. + */ token_t Term = GetTokListTerm (TOK_RPAREN); unsigned Count = 0; while (CurTok.Tok != Term) { /* Check for end of line or end of input. Since the calling function - * will check for the closing paren, we don't need to print an error - * here, just bail out. - */ + ** will check for the closing paren, we don't need to print an error + ** here, just bail out. + */ if (TokIsSep (CurTok.Tok)) { break; } @@ -458,9 +458,9 @@ static ExprNode* DoMatch (enum TC EqualityLevel) TokNode* Node; /* A list of tokens follows. Read this list and remember it building a - * single linked list of tokens including attributes. The list is - * either enclosed in curly braces, or terminated by a comma. - */ + ** single linked list of tokens including attributes. The list is + ** either enclosed in curly braces, or terminated by a comma. + */ token_t Term = GetTokListTerm (TOK_COMMA); while (CurTok.Tok != Term) { @@ -494,9 +494,9 @@ static ExprNode* DoMatch (enum TC EqualityLevel) } /* Read the second list which is optionally enclosed in curly braces and - * terminated by the right parenthesis. Compare each token against the - * one in the first list. - */ + ** terminated by the right parenthesis. Compare each token against the + ** one in the first list. + */ Term = GetTokListTerm (TOK_RPAREN); Result = 1; Node = Root; @@ -674,8 +674,8 @@ static ExprNode* FuncSizeOf (void) } /* If ScopeName is empty, no explicit scope was specified. We have to - * search upper scope levels in this case. - */ + ** search upper scope levels in this case. + */ NoScope = SB_IsEmpty (&ScopeName); /* First search for a scope with the given name */ @@ -686,8 +686,8 @@ static ExprNode* FuncSizeOf (void) } /* If we did find a scope with the name, read the symbol defining the - * size, otherwise search for a symbol entry with the name and scope. - */ + ** size, otherwise search for a symbol entry with the name and scope. + */ if (Scope) { /* Yep, it's a scope */ SizeSym = GetSizeOfScope (Scope); @@ -755,8 +755,8 @@ static ExprNode* FuncStrAt (void) } /* Get the char, handle as unsigned. Be sure to translate it into - * the target character set. - */ + ** the target character set. + */ C = TgtTranslateChar (SB_At (&Str, (unsigned)Index)); ExitPoint: @@ -803,16 +803,16 @@ static ExprNode* FuncTCount (void) /* Handle the .TCOUNT function */ { /* We have a list of tokens that ends with the closing paren. Skip - * the tokens, and count them. Allow optionally curly braces. - */ + ** the tokens, and count them. Allow optionally curly braces. + */ token_t Term = GetTokListTerm (TOK_RPAREN); int Count = 0; while (CurTok.Tok != Term) { /* Check for end of line or end of input. Since the calling function - * will check for the closing paren, we don't need to print an error - * here, just bail out. - */ + ** will check for the closing paren, we don't need to print an error + ** here, just bail out. + */ if (TokIsSep (CurTok.Tok)) { break; } @@ -1131,8 +1131,8 @@ static ExprNode* Term (void) } /* Generate a literal expression and delete the old left and - * right sides. - */ + ** right sides. + */ FreeExpr (Left); FreeExpr (Right); Root = GenLiteralExpr (Val); @@ -1198,8 +1198,8 @@ static ExprNode* SimpleExpr (void) } /* Generate a literal expression and delete the old left and - * right sides. - */ + ** right sides. + */ FreeExpr (Left); FreeExpr (Right); Root = GenLiteralExpr (Val); @@ -1264,8 +1264,8 @@ static ExprNode* BoolExpr (void) } /* Generate a literal expression and delete the old left and - * right sides. - */ + ** right sides. + */ FreeExpr (Left); FreeExpr (Right); Root = GenLiteralExpr (Val); @@ -1327,8 +1327,8 @@ static ExprNode* Expr2 (void) } /* Generate a literal expression and delete the old left and - * right sides. - */ + ** right sides. + */ FreeExpr (Left); FreeExpr (Right); Root = GenLiteralExpr (Val); @@ -1385,8 +1385,8 @@ static ExprNode* Expr1 (void) } /* Generate a literal expression and delete the old left and - * right sides. - */ + ** right sides. + */ FreeExpr (Left); FreeExpr (Right); Root = GenLiteralExpr (Val); @@ -1453,8 +1453,8 @@ static ExprNode* Expr0 (void) ExprNode* Expression (void) /* Evaluate an expression, build the expression tree on the heap and return - * a pointer to the root of the tree. - */ +** a pointer to the root of the tree. +*/ { return Expr0 (); } @@ -1463,9 +1463,9 @@ ExprNode* Expression (void) long ConstExpression (void) /* Parse an expression. Check if the expression is const, and print an error - * message if not. Return the value of the expression, or a dummy, if it is - * not constant. - */ +** message if not. Return the value of the expression, or a dummy, if it is +** not constant. +*/ { long Val; @@ -1620,8 +1620,8 @@ ExprNode* GenSwapExpr (ExprNode* Expr) ExprNode* GenBranchExpr (unsigned Offs) /* Return an expression that encodes the difference between current PC plus - * offset and the target expression (that is, Expression() - (*+Offs) ). - */ +** offset and the target expression (that is, Expression() - (*+Offs) ). +*/ { ExprNode* N; ExprNode* Root; @@ -1637,11 +1637,11 @@ ExprNode* GenBranchExpr (unsigned Offs) FreeExpr (N); /* Generate the final expression: - * Val - (* + Offs) - * Val - ((Seg + PC) + Offs) - * Val - Seg - PC - Offs - * (Val - PC - Offs) - Seg - */ + ** Val - (* + Offs) + ** Val - ((Seg + PC) + Offs) + ** Val - Seg - PC - Offs + ** (Val - PC - Offs) - Seg + */ Root = GenLiteralExpr (Val - GetPC () - Offs); if (GetRelocMode ()) { N = Root; @@ -1653,11 +1653,11 @@ ExprNode* GenBranchExpr (unsigned Offs) } else { /* Generate the expression: - * N - (* + Offs) - * N - ((Seg + PC) + Offs) - * N - Seg - PC - Offs - * N - (PC + Offs) - Seg - */ + ** N - (* + Offs) + ** N - ((Seg + PC) + Offs) + ** N - Seg - PC - Offs + ** N - (PC + Offs) - Seg + */ Root = NewExprNode (EXPR_MINUS); Root->Left = N; Root->Right = GenLiteralExpr (GetPC () + Offs); @@ -1759,9 +1759,9 @@ ExprNode* GenNE (ExprNode* Expr, long Val) int IsConstExpr (ExprNode* Expr, long* Val) /* Return true if the given expression is a constant expression, that is, one - * with no references to external symbols. If Val is not NULL and the - * expression is constant, the constant value is stored here. - */ +** with no references to external symbols. If Val is not NULL and the +** expression is constant, the constant value is stored here. +*/ { int IsConst; @@ -1785,8 +1785,8 @@ int IsConstExpr (ExprNode* Expr, long* Val) ExprNode* CloneExpr (ExprNode* Expr) /* Clone the given expression tree. The function will simply clone symbol - * nodes, it will not resolve them. - */ +** nodes, it will not resolve them. +*/ { ExprNode* Clone; @@ -1843,8 +1843,8 @@ void WriteExpr (ExprNode* Expr) } /* If the is a leafnode, write the expression attribute, otherwise - * write the expression operands. - */ + ** write the expression operands. + */ switch (Expr->Op) { case EXPR_LITERAL: @@ -1884,12 +1884,12 @@ void WriteExpr (ExprNode* Expr) void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize) /* Mark the address size of the given expression tree as guessed. The address - * size passed as argument is the one NOT used, because the actual address - * size wasn't known. Example: Zero page addressing was not used because symbol - * is undefined, and absolute addressing was available. - * This function will actually parse the expression tree for undefined symbols, - * and mark these symbols accordingly. - */ +** size passed as argument is the one NOT used, because the actual address +** size wasn't known. Example: Zero page addressing was not used because symbol +** is undefined, and absolute addressing was available. +** This function will actually parse the expression tree for undefined symbols, +** and mark these symbols accordingly. +*/ { /* Accept NULL expressions */ if (Expr == 0) { @@ -1942,6 +1942,3 @@ ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size) { return MakeBoundedExpr (ExprFunc (), Size); } - - - diff --git a/src/ca65/expr.h b/src/ca65/expr.h index 17f547beb..03c2c26d8 100644 --- a/src/ca65/expr.h +++ b/src/ca65/expr.h @@ -62,14 +62,14 @@ struct ExprDesc; ExprNode* Expression (void); /* Evaluate an expression, build the expression tree on the heap and return - * a pointer to the root of the tree. - */ +** a pointer to the root of the tree. +*/ long ConstExpression (void); /* Parse an expression. Check if the expression is const, and print an error - * message if not. Return the value of the expression, or a dummy, if it is - * not constant. - */ +** message if not. Return the value of the expression, or a dummy, if it is +** not constant. +*/ void FreeExpr (ExprNode* Root); /* Free the expression tree, Root is pointing to. */ @@ -97,8 +97,8 @@ ExprNode* GenSwapExpr (ExprNode* Expr); ExprNode* GenBranchExpr (unsigned Offs); /* Return an expression that encodes the difference between current PC plus - * offset and the target expression (that is, Expression() - (*+Offs) ). - */ +** offset and the target expression (that is, Expression() - (*+Offs) ). +*/ ExprNode* GenULabelExpr (unsigned Num); /* Return an expression for an unnamed label with the given index */ @@ -120,9 +120,9 @@ ExprNode* GenNE (ExprNode* Expr, long Val); int IsConstExpr (ExprNode* Expr, long* Val); /* Return true if the given expression is a constant expression, that is, one - * with no references to external symbols. If Val is not NULL and the - * expression is constant, the constant value is stored here. - */ +** with no references to external symbols. If Val is not NULL and the +** expression is constant, the constant value is stored here. +*/ int IsByteExpr (ExprNode* Root); /* Return true if this is a byte expression */ @@ -138,26 +138,26 @@ int IsFarRange (long Val); int IsEasyConst (const ExprNode* E, long* Val); /* Do some light checking if the given node is a constant. Don't care if E is - * a complex expression. If E is a constant, return true and place its value - * into Val, provided that Val is not NULL. - */ +** a complex expression. If E is a constant, return true and place its value +** into Val, provided that Val is not NULL. +*/ ExprNode* CloneExpr (ExprNode* Expr); /* Clone the given expression tree. The function will simply clone symbol - * nodes, it will not resolve them. - */ +** nodes, it will not resolve them. +*/ void WriteExpr (ExprNode* Expr); /* Write the given expression to the object file */ void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize); /* Mark the address size of the given expression tree as guessed. The address - * size passed as argument is the one NOT used, because the actual address - * size wasn't known. Example: Zero page addressing was not used because symbol - * is undefined, and absolute addressing was available. - * This function will actually parse the expression tree for undefined symbols, - * and mark these symbols accordingly. - */ +** size passed as argument is the one NOT used, because the actual address +** size wasn't known. Example: Zero page addressing was not used because symbol +** is undefined, and absolute addressing was available. +** This function will actually parse the expression tree for undefined symbols, +** and mark these symbols accordingly. +*/ ExprNode* FuncBankByte (void); /* Handle the .BANKBYTE builtin function */ @@ -179,6 +179,3 @@ ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size); /* End of expr.h */ #endif - - - diff --git a/src/ca65/feature.c b/src/ca65/feature.c index c2532c595..c398d2b37 100644 --- a/src/ca65/feature.c +++ b/src/ca65/feature.c @@ -75,8 +75,8 @@ static const char* FeatureKeys[FEAT_COUNT] = { feature_t FindFeature (const StrBuf* Key) /* Find the feature in a table and return the corresponding enum value. If the - * feature is invalid, return FEAT_UNKNOWN. - */ +** feature is invalid, return FEAT_UNKNOWN. +*/ { feature_t F; @@ -96,9 +96,9 @@ feature_t FindFeature (const StrBuf* Key) feature_t SetFeature (const StrBuf* Key) /* Find the feature and set the corresponding flag if the feature is known. - * In any case, return the feature found. An invalid Key will return - * FEAT_UNKNOWN. - */ +** In any case, return the feature found. An invalid Key will return +** FEAT_UNKNOWN. +*/ { /* Map the string to an enum value */ feature_t Feature = FindFeature (Key); @@ -125,6 +125,3 @@ feature_t SetFeature (const StrBuf* Key) /* Return the value found */ return Feature; } - - - diff --git a/src/ca65/feature.h b/src/ca65/feature.h index 53016b21c..9682ad9b9 100644 --- a/src/ca65/feature.h +++ b/src/ca65/feature.h @@ -80,20 +80,17 @@ typedef enum { feature_t FindFeature (const StrBuf* Key); /* Find the feature in a table and return the corresponding enum value. If the - * feature is invalid, return FEAT_UNKNOWN. - */ +** feature is invalid, return FEAT_UNKNOWN. +*/ feature_t SetFeature (const StrBuf* Key); /* Find the feature and set the corresponding flag if the feature is known. - * In any case, return the feature found. An invalid Key will return - * FEAT_UNKNOWN. - */ +** In any case, return the feature found. An invalid Key will return +** FEAT_UNKNOWN. +*/ /* End of feature.h */ #endif - - - diff --git a/src/ca65/filetab.c b/src/ca65/filetab.c index bf5b32503..fbe163f51 100644 --- a/src/ca65/filetab.c +++ b/src/ca65/filetab.c @@ -66,9 +66,9 @@ static const void* HT_GetKey (const void* Entry); static int HT_Compare (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if - * Key1 is smaller than Key2, zero if both are equal, and a value greater - * than zero if Key1 is greater then Key2. - */ +** Key1 is smaller than Key2, zero if both are equal, and a value greater +** than zero if Key1 is greater then Key2. +*/ @@ -132,9 +132,9 @@ static const void* HT_GetKey (const void* Entry) static int HT_Compare (const void* Key1, const void* Key2) /* Compare two keys. The function must return a value less than zero if - * Key1 is smaller than Key2, zero if both are equal, and a value greater - * than zero if Key1 is greater then Key2. - */ +** Key1 is smaller than Key2, zero if both are equal, and a value greater +** than zero if Key1 is greater then Key2. +*/ { return (int)*(const unsigned*)Key1 - (int)*(const unsigned*)Key2; } @@ -183,9 +183,9 @@ const StrBuf* GetFileName (unsigned Name) if (Name == 0) { /* Name was defined outside any file scope, use the name of the first - * file instead. Errors are then reported with a file position of - * line zero in the first file. - */ + ** file instead. Errors are then reported with a file position of + ** line zero in the first file. + */ if (CollCount (&FileTab) == 0) { /* No files defined until now */ return &ErrorMsg; @@ -223,8 +223,8 @@ unsigned GetFileIndex (const StrBuf* Name) unsigned AddFile (const StrBuf* Name, FileType Type, unsigned long Size, unsigned long MTime) /* Add a new file to the list of input files. Return the index of the file in - * the table. - */ +** the table. +*/ { /* Create a new file entry and insert it into the tables */ FileEntry* F = NewFileEntry (GetStrBufId (Name), Type, Size, MTime); @@ -295,8 +295,8 @@ static void WriteDep (FILE* F, FileType Types) static void CreateDepFile (const char* Name, FileType Types) /* Create a dependency file with the given name and place dependencies for - * all files with the given types there. - */ +** all files with the given types there. +*/ { /* Open the file */ FILE* F = fopen (Name, "w"); @@ -336,5 +336,3 @@ void CreateDependencies (void) FT_MAIN | FT_INCLUDE | FT_BINARY | FT_DBGINFO); } } - - diff --git a/src/ca65/filetab.h b/src/ca65/filetab.h index af5909c4c..4e8cf5668 100644 --- a/src/ca65/filetab.h +++ b/src/ca65/filetab.h @@ -50,8 +50,8 @@ /* An enum that describes different types of input files. The members are - * choosen so that it is possible to combine them to bitsets - */ +** choosen so that it is possible to combine them to bitsets +*/ typedef enum { FT_MAIN = 0x01, /* Main input file */ FT_INCLUDE = 0x02, /* Normal include file */ @@ -76,8 +76,8 @@ unsigned GetFileIndex (const StrBuf* Name); unsigned AddFile (const StrBuf* Name, FileType Type, unsigned long Size, unsigned long MTime); /* Add a new file to the list of input files. Return the index of the file in - * the table. - */ +** the table. +*/ void WriteFiles (void); /* Write the list of input files to the object file */ @@ -90,8 +90,3 @@ void CreateDependencies (void); /* End of filetab.h */ #endif - - - - - diff --git a/src/ca65/fragment.c b/src/ca65/fragment.c index e1a55edb3..6a14a4cfc 100644 --- a/src/ca65/fragment.c +++ b/src/ca65/fragment.c @@ -49,8 +49,8 @@ Fragment* NewFragment (unsigned char Type, unsigned short Len) /* Create, initialize and return a new fragment. The fragment will be inserted - * into the current segment. - */ +** into the current segment. +*/ { /* Create a new fragment */ Fragment* F = xmalloc (sizeof (*F)); @@ -66,6 +66,3 @@ Fragment* NewFragment (unsigned char Type, unsigned short Len) /* And return it */ return F; } - - - diff --git a/src/ca65/fragment.h b/src/ca65/fragment.h index 99852202a..f89589501 100644 --- a/src/ca65/fragment.h +++ b/src/ca65/fragment.h @@ -76,14 +76,11 @@ struct Fragment { Fragment* NewFragment (unsigned char Type, unsigned short Len); /* Create, initialize and return a new fragment. The fragment will be inserted - * into the current segment. - */ +** into the current segment. +*/ /* End of fragment.h */ + #endif - - - - diff --git a/src/ca65/global.h b/src/ca65/global.h index 23bbe4884..378a776e6 100644 --- a/src/ca65/global.h +++ b/src/ca65/global.h @@ -90,6 +90,3 @@ extern unsigned char UnderlineInNumbers; /* Allow underlines in numbers */ /* End of global.h */ #endif - - - diff --git a/src/ca65/incpath.c b/src/ca65/incpath.c index 76ad3111a..ff21b175d 100644 --- a/src/ca65/incpath.c +++ b/src/ca65/incpath.c @@ -44,8 +44,8 @@ -SearchPath* IncSearchPath; /* Standard include path */ -SearchPath* BinSearchPath; /* Binary include path */ +SearchPaths* IncSearchPath; /* Standard include path */ +SearchPaths* BinSearchPath; /* Binary include path */ @@ -75,13 +75,10 @@ void FinishIncludePaths (void) AddSubSearchPathFromEnv (IncSearchPath, "CC65_HOME", "asminc"); /* Add some compiled-in search paths if defined at compile time. */ -#ifdef CA65_INC +#if defined(CA65_INC) && !defined(_WIN32) AddSearchPath (IncSearchPath, STRINGIZE (CA65_INC)); #endif /* Add paths relative to the parent directory of the Windows binary. */ AddSubSearchPathFromWinBin (IncSearchPath, "asminc"); } - - - diff --git a/src/ca65/incpath.h b/src/ca65/incpath.h index 841767e4b..818e36265 100644 --- a/src/ca65/incpath.h +++ b/src/ca65/incpath.h @@ -49,8 +49,8 @@ -extern SearchPath* IncSearchPath; /* Standard include path */ -extern SearchPath* BinSearchPath; /* Binary include path */ +extern SearchPaths* IncSearchPath; /* Standard include path */ +extern SearchPaths* BinSearchPath; /* Binary include path */ @@ -71,6 +71,3 @@ void FinishIncludePaths (void); /* End of incpath.h */ #endif - - - diff --git a/src/ca65/instr.c b/src/ca65/instr.c index 277676614..c2482577c 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -90,37 +90,37 @@ static void PutSEP (const InsDesc* Ins); static void PutTAMn (const InsDesc* Ins); /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with - * implicit addressing mode, the opcode byte in the table is actually the - * second operand byte. The TAM instruction is the more generic form, it takes - * an immediate argument. - */ +** implicit addressing mode, the opcode byte in the table is actually the +** second operand byte. The TAM instruction is the more generic form, it takes +** an immediate argument. +*/ static void PutTMA (const InsDesc* Ins); /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit - * in the argument byte may be set. - */ +** in the argument byte may be set. +*/ static void PutTMAn (const InsDesc* Ins); /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with - * implicit addressing mode, the opcode byte in the table is actually the - * second operand byte. The TAM instruction is the more generic form, it takes - * an immediate argument. - */ +** implicit addressing mode, the opcode byte in the table is actually the +** second operand byte. The TAM instruction is the more generic form, it takes +** an immediate argument. +*/ static void PutTST (const InsDesc* Ins); /* Emit a TST instruction (HuC6280). */ static void PutJMP (const InsDesc* Ins); /* Handle the jump instruction for the 6502. Problem is that these chips have - * a bug: If the address crosses a page, the upper byte gets not corrected and - * the instruction will fail. The PutJmp function will add a linker assertion - * to check for this case and is otherwise identical to PutAll. - */ +** a bug: If the address crosses a page, the upper byte gets not corrected and +** the instruction will fail. The PutJmp function will add a linker assertion +** to check for this case and is otherwise identical to PutAll. +*/ static void PutRTS (const InsDesc* Ins attribute ((unused))); /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if - * the enclosing scope is FAR. - */ +** the enclosing scope is FAR. +*/ static void PutAll (const InsDesc* Ins); /* Handle all other instructions */ @@ -516,8 +516,8 @@ static const struct { { "INC", 0x000006F, 0x00, 4, PutAll }, { "INX", 0x0000001, 0xe8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll }, - { "JML", 0x0000810, 0x5c, 1, PutAll }, - { "JMP", 0x0010818, 0x4c, 6, PutAll }, + { "JML", 0x4000010, 0x5c, 1, PutAll }, + { "JMP", 0x4010818, 0x4c, 6, PutAll }, { "JSL", 0x0000010, 0x20, 7, PutAll }, { "JSR", 0x0010018, 0x20, 7, PutAll }, { "LDA", 0x0b8f6fc, 0xa0, 0, PutAll }, @@ -585,11 +585,6 @@ static const struct { } }; -#ifdef SUNPLUS -/* Table for the SUNPLUS CPU */ -#include "sunplus.inc" -#endif - /* Instruction table for the SWEET16 pseudo CPU */ static const struct { unsigned Count; @@ -781,11 +776,6 @@ static const InsTable* InsTabs[CPU_COUNT] = { (const InsTable*) &InsTab65SC02, (const InsTable*) &InsTab65C02, (const InsTable*) &InsTab65816, -#ifdef SUNPLUS - (const InsTable*) &InsTabSunPlus, -#else - 0, -#endif (const InsTable*) &InsTabSweet16, (const InsTable*) &InsTabHuC6280, 0, /* Mitsubishi 740 */ @@ -793,74 +783,74 @@ static const InsTable* InsTabs[CPU_COUNT] = { const InsTable* InsTab = (const InsTable*) &InsTab6502; /* Table to build the effective 65xx opcode from a base opcode and an - * addressing mode. - */ +** addressing mode. +*/ static unsigned char EATab[10][AM65I_COUNT] = { { /* Table 0 */ 0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F, 0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01, 0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09, - 0x00, 0x00 + 0x00, 0x00, 0x00 }, { /* Table 1 */ 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00, 0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 + 0x00, 0x00, 0x80 }, { /* Table 2 */ 0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, - 0x00, 0x00 + 0x00, 0x00, 0x00 }, { /* Table 3 */ 0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 + 0x00, 0x00, 0x00 }, { /* Table 4 */ 0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 + 0x00, 0x00, 0x00 }, { /* Table 5 */ 0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 + 0x00, 0x00, 0x00 }, { /* Table 6 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 + 0x00, 0x00, 0x90 }, { /* Table 7 */ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 + 0x00, 0x00, 0x00 }, { /* Table 8 */ 0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00 + 0x00, 0x00, 0x00 }, { /* Table 9 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 + 0x00, 0x00, 0x00 }, }; /* Table to build the effective SWEET16 opcode from a base opcode and an - * addressing mode. - */ +** addressing mode. +*/ static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = { { /* Table 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, @@ -898,6 +888,7 @@ unsigned char ExtBytes[AM65I_COUNT] = { 1, /* Immidiate byte */ 2, /* Blockmove (65816) */ 7, /* Block transfer (HuC6280) */ + 2, /* Absolute Indirect long */ }; /* Table that encodes the additional bytes for each SWEET16 instruction */ @@ -919,21 +910,21 @@ static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = { static int EvalEA (const InsDesc* Ins, EffAddr* A) /* Evaluate the effective address. All fields in A will be valid after calling - * this function. The function returns true on success and false on errors. - */ +** this function. The function returns true on success and false on errors. +*/ { /* Get the set of possible addressing modes */ GetEA (A); /* From the possible addressing modes, remove the ones that are invalid - * for this instruction or CPU. - */ + ** for this instruction or CPU. + */ A->AddrModeSet &= Ins->AddrMode; /* If we have an expression, check it and remove any addressing modes that - * are too small for the expression size. Since we have to study the - * expression anyway, do also replace it by a simpler one if possible. - */ + ** are too small for the expression size. Since we have to study the + ** expression anyway, do also replace it by a simpler one if possible. + */ if (A->Expr) { ExprDesc ED; ED_Init (&ED); @@ -946,10 +937,10 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A) if (ED.AddrSize == ADDR_SIZE_DEFAULT) { /* We don't know how big the expression is. If the instruction - * allows just one addressing mode, assume this as address size - * for the expression. Otherwise assume the default address size - * for data. - */ + ** allows just one addressing mode, assume this as address size + ** for the expression. Otherwise assume the default address size + ** for data. + */ if ((A->AddrModeSet & ~AM65_ALL_ZP) == 0) { ED.AddrSize = ADDR_SIZE_ZP; } else if ((A->AddrModeSet & ~AM65_ALL_ABS) == 0) { @@ -959,12 +950,12 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A) } else { ED.AddrSize = DataAddrSize; /* If the default address size of the data segment is unequal - * to zero page addressing, but zero page addressing is - * allowed by the instruction, mark all symbols in the - * expression tree. This mark will be checked at end of - * assembly, and a warning is issued, if a zero page symbol - * was guessed wrong here. - */ + ** to zero page addressing, but zero page addressing is + ** allowed by the instruction, mark all symbols in the + ** expression tree. This mark will be checked at end of + ** assembly, and a warning is issued, if a zero page symbol + ** was guessed wrong here. + */ if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) { ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP); } @@ -996,11 +987,11 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A) A->AddrModeBit = (0x01UL << A->AddrMode); /* If the instruction has a one byte operand and immediate addressing is - * allowed but not used, check for an operand expression in the form - * <label or >label, where label is a far or absolute label. If found, - * emit a warning. This warning protects against a typo, where the '#' - * for the immediate operand is omitted. - */ + ** allowed but not used, check for an operand expression in the form + ** <label or >label, where label is a far or absolute label. If found, + ** emit a warning. This warning protects against a typo, where the '#' + ** for the immediate operand is omitted. + */ if (A->Expr && (Ins->AddrMode & AM65_ALL_IMM) && (A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) && ExtBytes[A->AddrMode] == 1) { @@ -1020,8 +1011,8 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A) A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode]; /* If feature force_range is active, and we have immediate addressing mode, - * limit the expression to the maximum possible value. - */ + ** limit the expression to the maximum possible value. + */ if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX || A->AddrMode == AM65I_IMM_IMPLICIT) { if (ForceRange && A->Expr) { @@ -1052,9 +1043,9 @@ static void EmitCode (EffAddr* A) case 2: if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) { /* This is a 16 bit mode that uses an address. If in 65816, - * mode, force this address into 16 bit range to allow - * addressing inside a 64K segment. - */ + ** mode, force this address into 16 bit range to allow + ** addressing inside a 64K segment. + */ Emit2 (A->Opcode, GenWordExpr (A->Expr)); } else { Emit2 (A->Opcode, A->Expr); @@ -1076,8 +1067,8 @@ static void EmitCode (EffAddr* A) static long PutImmed8 (const InsDesc* Ins) /* Parse and emit an immediate 8 bit instruction. Return the value of the - * operand if it's available and const. - */ +** operand if it's available and const. +*/ { EffAddr A; long Val = -1; @@ -1219,10 +1210,10 @@ static void PutSEP (const InsDesc* Ins) static void PutTAMn (const InsDesc* Ins) /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with - * implicit addressing mode, the opcode byte in the table is actually the - * second operand byte. The TAM instruction is the more generic form, it takes - * an immediate argument. - */ +** implicit addressing mode, the opcode byte in the table is actually the +** second operand byte. The TAM instruction is the more generic form, it takes +** an immediate argument. +*/ { /* Emit the TAM opcode itself */ Emit0 (0x53); @@ -1235,8 +1226,8 @@ static void PutTAMn (const InsDesc* Ins) static void PutTMA (const InsDesc* Ins) /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit - * in the argument byte may be set. - */ +** in the argument byte may be set. +*/ { /* Use the generic handler */ long Val = PutImmed8 (Ins); @@ -1257,10 +1248,10 @@ static void PutTMA (const InsDesc* Ins) static void PutTMAn (const InsDesc* Ins) /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with - * implicit addressing mode, the opcode byte in the table is actually the - * second operand byte. The TAM instruction is the more generic form, it takes - * an immediate argument. - */ +** implicit addressing mode, the opcode byte in the table is actually the +** second operand byte. The TAM instruction is the more generic form, it takes +** an immediate argument. +*/ { /* Emit the TMA opcode itself */ Emit0 (0x43); @@ -1312,10 +1303,10 @@ static void PutTST (const InsDesc* Ins) static void PutJMP (const InsDesc* Ins) /* Handle the jump instruction for the 6502. Problem is that these chips have - * a bug: If the address crosses a page, the upper byte gets not corrected and - * the instruction will fail. The PutJmp function will add a linker assertion - * to check for this case and is otherwise identical to PutAll. - */ +** a bug: If the address crosses a page, the upper byte gets not corrected and +** the instruction will fail. The PutJmp function will add a linker assertion +** to check for this case and is otherwise identical to PutAll. +*/ { EffAddr A; @@ -1326,9 +1317,9 @@ static void PutJMP (const InsDesc* Ins) if (A.AddrModeBit & AM65_ABS_IND) { /* Compare the low byte of the expression to 0xFF to check for - * a page cross. Be sure to use a copy of the expression otherwise - * things will go weird later. - */ + ** a page cross. Be sure to use a copy of the expression otherwise + ** things will go weird later. + */ ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF); /* Generate the message */ @@ -1347,8 +1338,8 @@ static void PutJMP (const InsDesc* Ins) static void PutRTS (const InsDesc* Ins attribute ((unused))) /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if - * the enclosing scope is FAR. - */ +** the enclosing scope is FAR. +*/ { if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) { Emit0 (0x6B); /* RTL */ @@ -1388,8 +1379,8 @@ static void PutSweet16 (const InsDesc* Ins) GetSweet16EA (&A); /* From the possible addressing modes, remove the ones that are invalid - * for this instruction or CPU. - */ + ** for this instruction or CPU. + */ A.AddrModeSet &= Ins->AddrMode; /* Check if we have any adressing modes left */ @@ -1475,16 +1466,16 @@ cpu_t GetCPU (void) int FindInstruction (const StrBuf* Ident) /* Check if Ident is a valid mnemonic. If so, return the index in the - * instruction table. If not, return -1. - */ +** instruction table. If not, return -1. +*/ { unsigned I; const InsDesc* ID; char Key[sizeof (ID->Mnemonic)]; /* Shortcut for the "none" CPU: If there are no instructions to search - * for, bail out early. - */ + ** for, bail out early. + */ if (InsTab->Count == 0) { /* Not found */ return -1; @@ -1494,8 +1485,8 @@ int FindInstruction (const StrBuf* Ident) I = 0; while (I < SB_GetLen (Ident)) { /* If the identifier is longer than the longest mnemonic, it cannot - * be one. - */ + ** be one. + */ if (I >= sizeof (Key) - 1) { /* Not found, no need for further action */ return -1; @@ -1530,6 +1521,3 @@ void HandleInstruction (unsigned Index) /* Call the handler */ InsTab->Ins[Index].Emit (&InsTab->Ins[Index]); } - - - diff --git a/src/ca65/instr.h b/src/ca65/instr.h index 9a219b424..1f2ce262b 100644 --- a/src/ca65/instr.h +++ b/src/ca65/instr.h @@ -51,13 +51,13 @@ /* Constants for the addressing mode. If an opcode is available in zero page - * and absolut adressing mode, both bits are set. When checking for valid - * modes, the zeropage bit is checked first. Similar, the implicit bit is set - * on accu adressing modes, so the 'A' for accu adressing is not needed (but - * may be specified). - * When assembling for the 6502 or 65C02, all addressing modes that are not - * available on these CPUs are removed before doing any checks. - */ +** and absolut adressing mode, both bits are set. When checking for valid +** modes, the zeropage bit is checked first. Similar, the implicit bit is set +** on accu adressing modes, so the 'A' for accu adressing is not needed (but +** may be specified). +** When assembling for the 6502 or 65C02, all addressing modes that are not +** available on these CPUs are removed before doing any checks. +*/ #define AM65_IMPLICIT 0x00000003UL #define AM65_ACCU 0x00000002UL #define AM65_DIR 0x00000004UL @@ -84,6 +84,7 @@ #define AM65_IMM_IMPLICIT 0x00800000UL #define AM65_BLOCKMOVE 0x01000000UL #define AM65_BLOCKXFER 0x02000000UL +#define AM65_ABS_IND_LONG 0x04000000UL /* Bitmask for all ZP operations that have correspondent ABS ops */ #define AM65_SET_ZP (AM65_DIR | AM65_DIR_X | AM65_DIR_Y | AM65_DIR_IND | AM65_DIR_X_IND) @@ -107,7 +108,7 @@ #define AM65I_IMM_ACCU 21 #define AM65I_IMM_INDEX 22 #define AM65I_IMM_IMPLICIT 23 -#define AM65I_COUNT 26 +#define AM65I_COUNT 27 @@ -167,8 +168,8 @@ cpu_t GetCPU (void); int FindInstruction (const StrBuf* Ident); /* Check if Ident is a valid mnemonic. If so, return the index in the - * instruction table. If not, return -1. - */ +** instruction table. If not, return -1. +*/ void HandleInstruction (unsigned Index); /* Handle the mnemonic with the given index */ @@ -178,8 +179,3 @@ void HandleInstruction (unsigned Index); /* End of instr.h */ #endif - - - - - diff --git a/src/ca65/istack.c b/src/ca65/istack.c index 507d56ba5..8cda7dd2f 100644 --- a/src/ca65/istack.c +++ b/src/ca65/istack.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -120,12 +120,12 @@ void PopInput (void) int InputFromStack (void) /* Try to get input from the input stack. Return true if we had such input, - * return false otherwise. - */ +** return false otherwise. +*/ { /* Repeatedly call the TOS routine until we have a token or if run out of - * routines. - */ + ** routines. + */ while (IStack) { if (IStack->Func (IStack->Data) != 0) { /* We have a token */ @@ -149,13 +149,10 @@ int HavePushedInput (void) void CheckInputStack (void) /* Called from the scanner before closing an input file. Will check for any - * stuff on the input stack. - */ +** stuff on the input stack. +*/ { if (IStack) { Error ("Open %s", IStack->Desc); } } - - - diff --git a/src/ca65/istack.h b/src/ca65/istack.h index 06ff066e4..aa37bab14 100644 --- a/src/ca65/istack.h +++ b/src/ca65/istack.h @@ -52,23 +52,19 @@ void PopInput (void); int InputFromStack (void); /* Try to get input from the input stack. Return true if we had such input, - * return false otherwise. - */ +** return false otherwise. +*/ int HavePushedInput (void); /* Return true if we have stacked input available, return false if not */ void CheckInputStack (void); /* Called from the scanner before closing an input file. Will check for any - * stuff on the input stack. - */ +** stuff on the input stack. +*/ /* End of istack.h */ #endif - - - - diff --git a/src/ca65/lineinfo.c b/src/ca65/lineinfo.c index dbc5b4d41..92fecec58 100644 --- a/src/ca65/lineinfo.c +++ b/src/ca65/lineinfo.c @@ -65,9 +65,9 @@ static const void* HT_GetKey (const void* Entry); static int HT_Compare (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if - * Key1 is smaller than Key2, zero if both are equal, and a value greater - * than zero if Key1 is greater then Key2. - */ +** Key1 is smaller than Key2, zero if both are equal, and a value greater +** than zero if Key1 is greater then Key2. +*/ @@ -145,9 +145,9 @@ static const void* HT_GetKey (const void* Entry) static int HT_Compare (const void* Key1, const void* Key2) /* Compare two keys. The function must return a value less than zero if - * Key1 is smaller than Key2, zero if both are equal, and a value greater - * than zero if Key1 is greater then Key2. - */ +** Key1 is smaller than Key2, zero if both are equal, and a value greater +** than zero if Key1 is greater then Key2. +*/ { /* Convert both parameters to FileInfoKey pointers */ const LineInfoKey* K1 = Key1; @@ -272,8 +272,8 @@ void InitLineInfo (void) CollGrow (&LineInfoList, 200); /* Create a LineInfo for the default source. This is necessary to allow - * error message to be generated without any input file open. - */ + ** error message to be generated without any input file open. + */ AsmLineInfo = StartLine (&DefaultPos, LI_TYPE_ASM, 0); } @@ -289,9 +289,9 @@ void DoneLineInfo (void) } /* Walk over the entries in the hash table and sort them into used and - * unused ones. Add the used ones to the line info list and assign them - * an id. - */ + ** unused ones. Add the used ones to the line info list and assign them + ** an id. + */ HT_Walk (&LineInfoTab, CheckLineInfo, 0); } @@ -304,14 +304,14 @@ void EndLine (LineInfo* LI) CloseSpanList (&LI->OpenSpans); /* Move the spans to the list of all spans for this line, then clear the - * list of open spans. - */ + ** list of open spans. + */ CollTransfer (&LI->Spans, &LI->OpenSpans); CollDeleteAll (&LI->OpenSpans); /* Line info is no longer active - remove it from the list of current - * line infos. - */ + ** line infos. + */ CollDeleteItem (&CurLineInfo, LI); } @@ -328,8 +328,8 @@ LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count) Key.Type = LI_MAKE_TYPE (Type, Count); /* Try to find a line info with this position and type in the hash table. - * If so, reuse it. Otherwise create a new one. - */ + ** If so, reuse it. Otherwise create a new one. + */ LI = HT_Find (&LineInfoTab, &Key); if (LI == 0) { /* Allocate a new LineInfo */ @@ -350,9 +350,9 @@ LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count) void NewAsmLine (void) /* Start a new assembler input line. Use this function when generating new - * line of LI_TYPE_ASM. It will check if line and/or file have actually - * changed, end the old and start the new line as necessary. - */ +** line of LI_TYPE_ASM. It will check if line and/or file have actually +** changed, end the old and start the new line as necessary. +*/ { /* Check if we can reuse the old line */ if (AsmLineInfo) { @@ -374,8 +374,8 @@ void NewAsmLine (void) LineInfo* GetAsmLineInfo (void) /* Return the line info for the current assembler file. The function will - * bump the reference counter before returning the line info. - */ +** bump the reference counter before returning the line info. +*/ { ++AsmLineInfo->RefCount; return AsmLineInfo; @@ -395,9 +395,9 @@ void ReleaseLineInfo (LineInfo* LI) void GetFullLineInfo (Collection* LineInfos) /* Return full line infos, that is line infos for currently active Slots. The - * infos will be added to the given collection, existing entries will be left - * intact. The reference count of all added entries will be increased. - */ +** infos will be added to the given collection, existing entries will be left +** intact. The reference count of all added entries will be increased. +*/ { unsigned I; @@ -414,8 +414,8 @@ void GetFullLineInfo (Collection* LineInfos) void ReleaseFullLineInfo (Collection* LineInfos) /* Decrease the reference count for a collection full of LineInfos, then clear - * the collection. - */ +** the collection. +*/ { unsigned I; @@ -501,6 +501,3 @@ void WriteLineInfos (void) /* End of line infos */ ObjEndLineInfos (); } - - - diff --git a/src/ca65/lineinfo.h b/src/ca65/lineinfo.h index 41b44c0bc..c5cf49519 100644 --- a/src/ca65/lineinfo.h +++ b/src/ca65/lineinfo.h @@ -77,28 +77,28 @@ LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count); void NewAsmLine (void); /* Start a new assembler input line. Use this function when generating new - * line of LI_TYPE_ASM. It will check if line and/or file have actually - * changed, end the old and start the new line as necessary. - */ +** line of LI_TYPE_ASM. It will check if line and/or file have actually +** changed, end the old and start the new line as necessary. +*/ LineInfo* GetAsmLineInfo (void); /* Return the line info for the current assembler file. The function will - * bump the reference counter before returning the line info. - */ +** bump the reference counter before returning the line info. +*/ void ReleaseLineInfo (LineInfo* LI); /* Decrease the reference count for a line info */ void GetFullLineInfo (Collection* LineInfos); /* Return full line infos, that is line infos for currently active Slots. The - * infos will be added to the given collection, existing entries will be left - * intact. The reference count of all added entries will be increased. - */ +** infos will be added to the given collection, existing entries will be left +** intact. The reference count of all added entries will be increased. +*/ void ReleaseFullLineInfo (Collection* LineInfos); /* Decrease the reference count for a collection full of LineInfos, then clear - * the collection. - */ +** the collection. +*/ const FilePos* GetSourcePos (const LineInfo* LI); /* Return the source file position from the given line info */ @@ -115,8 +115,5 @@ void WriteLineInfos (void); /* End of lineinfo.h */ + #endif - - - - diff --git a/src/ca65/listing.c b/src/ca65/listing.c index 8bd8833dd..b3f3d9282 100644 --- a/src/ca65/listing.c +++ b/src/ca65/listing.c @@ -131,8 +131,8 @@ void EnableListing (void) { if (SB_GetLen (&ListingName) > 0) { /* If we're about to enable the listing, do this for the current line - * also, so we will see the source line that did this. - */ + ** also, so we will see the source line that did this. + */ if (ListingEnabled++ == 0) { LineCur->Output = 1; } @@ -172,9 +172,9 @@ void InitListingLine (void) { if (SB_GetLen (&ListingName) > 0) { /* Make the last loaded line the current line */ - /* ###### This code is a hack! We really need to do it right - * as soon as we know, how:-( - */ + /* ###### This code is a hack! We really need to do it right -- + ** as soon as we know how. :-( + */ if (LineCur && LineCur->Next && LineCur->Next != LineLast) { ListLine* L = LineCur; do { @@ -217,8 +217,8 @@ static char* AddHex (char* S, unsigned Val) static void PrintPageHeader (FILE* F, const ListLine* L) /* Print the header for a new page. It is assumed that the given line is the - * last line of the previous page. - */ +** last line of the previous page. +*/ { /* Gte a pointer to the current input file */ const StrBuf* CurFile = GetFileName (L->File); @@ -250,8 +250,8 @@ static void PrintLine (FILE* F, const char* Header, const char* Line, const List ++PageLines; /* Switch to a new page if needed. Do not switch, if the current line is - * the last one, to avoid pages that consist of just the header. - */ + ** the last one, to avoid pages that consist of just the header. + */ if (PageLength > 0 && PageLines >= PageLength && L->Next != 0) { /* Do a formfeed */ putc ('\f', F); @@ -392,16 +392,16 @@ void CreateListing (void) } /* Output the data. The format of a listing line is: - * - * PPPPPPm I 11 22 33 44 - * - * where - * - * PPPPPP is the PC - * m is the mode ('r' or empty) - * I is the include level - * 11 .. are code or data bytes - */ + ** + ** PPPPPPm I 11 22 33 44 + ** + ** where + ** + ** PPPPPP is the PC + ** m is the mode ('r' or empty) + ** I is the include level + ** 11 .. are code or data bytes + */ Line = L->Line; B = Buf; while (Count) { @@ -420,9 +420,9 @@ void CreateListing (void) Count -= Chunk; /* Increment the program counter. Since we don't need the PC stored - * in the LineList object for anything else, just increment this - * variable. - */ + ** in the LineList object for anything else, just increment this + ** variable. + */ L->PC += Chunk; /* Copy the bytes into the line */ @@ -452,6 +452,3 @@ void CreateListing (void) /* Close the listing file */ (void) fclose (F); } - - - diff --git a/src/ca65/listing.h b/src/ca65/listing.h index bea716bf1..b1ae44291 100644 --- a/src/ca65/listing.h +++ b/src/ca65/listing.h @@ -123,6 +123,3 @@ void CreateListing (void); /* End of listing.h */ #endif - - - diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 75741c479..634f2107e 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -70,9 +70,9 @@ static const void* HT_GetKey (const void* Entry); static int HT_Compare (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if - * Key1 is smaller than Key2, zero if both are equal, and a value greater - * than zero if Key1 is greater then Key2. - */ +** Key1 is smaller than Key2, zero if both are equal, and a value greater +** than zero if Key1 is greater then Key2. +*/ @@ -176,9 +176,9 @@ static const void* HT_GetKey (const void* Entry) static int HT_Compare (const void* Key1, const void* Key2) /* Compare two keys. The function must return a value less than zero if - * Key1 is smaller than Key2, zero if both are equal, and a value greater - * than zero if Key1 is greater then Key2. - */ +** Key1 is smaller than Key2, zero if both are equal, and a value greater +** than zero if Key1 is greater then Key2. +*/ { return SB_Compare (Key1, Key2); } @@ -399,8 +399,8 @@ void MacDef (unsigned Style) return; } else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) { /* The identifier is a name of a 6502 instruction, which is not - * allowed if not explicitly enabled. - */ + ** allowed if not explicitly enabled. + */ Error ("Cannot use an instruction as macro name"); MacSkipDef (Style); return; @@ -423,8 +423,8 @@ void MacDef (unsigned Style) NextTok (); /* If we have a DEFINE style macro, we may have parameters in braces, - * otherwise we may have parameters without braces. - */ + ** otherwise we may have parameters without braces. + */ if (Style == MAC_STYLE_CLASSIC) { HaveParams = 1; } else { @@ -476,8 +476,8 @@ void MacDef (unsigned Style) } /* For class macros, we expect a separator token, for define style macros, - * we expect the closing paren. - */ + ** we expect the closing paren. + */ if (Style == MAC_STYLE_CLASSIC) { ConsumeSep (); } else if (HaveParams) { @@ -485,10 +485,10 @@ void MacDef (unsigned Style) } /* Preparse the macro body. We will read the tokens until we reach end of - * file, or a .endmacro (or end of line for DEFINE style macros) and store - * them into an token list internal to the macro. For classic macros, there - * the .LOCAL command is detected and removed at this time. - */ + ** file, or a .endmacro (or end of line for DEFINE style macros) and store + ** them into an token list internal to the macro. For classic macros, there + ** the .LOCAL command is detected and removed at this time. + */ while (1) { /* Check for end of macro */ @@ -597,8 +597,8 @@ Done: void MacUndef (const StrBuf* Name, unsigned char Style) /* Undefine the macro with the given name and style. A style mismatch is - * treated as if the macro didn't exist. - */ +** treated as if the macro didn't exist. +*/ { /* Search for the macro */ Macro* M = HT_Find (&MacroTab, Name); @@ -624,9 +624,9 @@ void MacUndef (const StrBuf* Name, unsigned char Style) static int MacExpand (void* Data) /* If we're currently expanding a macro, set the the scanner token and - * attribute to the next value and return true. If we are not expanding - * a macro, return false. - */ +** attribute to the next value and return true. If we are not expanding +** a macro, return false. +*/ { /* Cast the Data pointer to the actual data structure */ MacExp* Mac = (MacExp*) Data; @@ -645,8 +645,8 @@ static int MacExpand (void* Data) } /* We're expanding a macro. Check if we are expanding one of the - * macro parameters. - */ + ** macro parameters. + */ ExpandParam: if (Mac->ParamExp) { @@ -674,8 +674,8 @@ ExpandParam: } /* We're not expanding macro parameters. Check if we have tokens left from - * the macro itself. - */ + ** the macro itself. + */ if (Mac->Exp) { /* Use next macro token */ @@ -716,10 +716,10 @@ ExpandParam: while (I) { if (SB_Compare (&CurTok.SVal, &I->Id) == 0) { /* This is in fact a local symbol, change the name. Be sure - * to generate a local label name if the original name was - * a local label, and also generate a name that cannot be - * generated by a user. - */ + ** to generate a local label name if the original name was + ** a local label, and also generate a name that cannot be + ** generated by a user. + */ if (SB_At (&I->Id, 0) == LocalStart) { /* Must generate a local symbol */ SB_Printf (&CurTok.SVal, "%cLOCAL-MACRO_SYMBOL-%04X", @@ -753,14 +753,14 @@ ExpandParam: Mac->Final = 0; /* Problem: When a .define style macro is expanded within the call - * of a classic one, the latter may be terminated and removed while - * the expansion of the .define style macro is still active. Because - * line info slots are "stacked", this runs into a CHECK FAILED. For - * now, we will fix that by removing the .define style macro expansion - * immediately, once the final token is placed. The better solution - * would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot - * to be called in FIFO order, but this is a bigger change. - */ + ** of a classic one, the latter may be terminated and removed while + ** the expansion of the .define style macro is still active. Because + ** line info slots are "stacked", this runs into a CHECK FAILED. For + ** now, we will fix that by removing the .define style macro expansion + ** immediately, once the final token is placed. The better solution + ** would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot + ** to be called in FIFO order, but this is a bigger change. + */ /* End of macro expansion and pop the input function */ FreeMacExp (Mac); PopInput (); @@ -836,8 +836,8 @@ static void StartExpClassic (MacExp* E) ++E->ParamCount; /* If the macro argument was enclosed in curly braces, end-of-line - * is an error. Skip the closing curly brace. - */ + ** is an error. Skip the closing curly brace. + */ if (Term == TOK_RCURLY) { if (CurTok.Tok == TOK_SEP) { Error ("End of line encountered within macro argument"); @@ -867,8 +867,8 @@ static void StartExpDefine (MacExp* E) /* Start expanding a DEFINE style macro */ { /* A define style macro must be called with as many actual parameters - * as there are formal ones. Get the parameter count. - */ + ** as there are formal ones. Get the parameter count. + */ unsigned Count = E->M->ParamCount; /* Skip the current token */ @@ -915,8 +915,8 @@ static void StartExpDefine (MacExp* E) ++E->ParamCount; /* If the macro argument was enclosed in curly braces, end-of-line - * is an error. Skip the closing curly brace. - */ + ** is an error. Skip the closing curly brace. + */ if (Term == TOK_RCURLY) { if (TokIsSep (CurTok.Tok)) { Error ("End of line encountered within macro argument"); @@ -936,10 +936,10 @@ static void StartExpDefine (MacExp* E) } /* Macro expansion will overwrite the current token. This is a problem - * for define style macros since these are called from the scanner level. - * To avoid it, remember the current token and re-insert it, once macro - * expansion is done. - */ + ** for define style macros since these are called from the scanner level. + ** To avoid it, remember the current token and re-insert it, once macro + ** expansion is done. + */ E->Final = NewTokNode (); /* Insert a new token input function */ @@ -963,8 +963,8 @@ void MacExpandStart (Macro* M) } /* Don't allow too many nested macro expansions - otherwise it is possible - * to force an endless loop and assembler crash. - */ + ** to force an endless loop and assembler crash. + */ if (MacExpansions >= MAX_MACEXPANSIONS) { Error ("Too many nested macro expansions"); return; @@ -997,8 +997,8 @@ void MacAbort (void) Macro* FindMacro (const StrBuf* Name) /* Try to find the macro with the given name and return it. If no macro with - * this name was found, return NULL. - */ +** this name was found, return NULL. +*/ { Macro* M = HT_Find (&MacroTab, Name); return (M != 0 && M->Style == MAC_STYLE_CLASSIC)? M : 0; @@ -1008,8 +1008,8 @@ Macro* FindMacro (const StrBuf* Name) Macro* FindDefine (const StrBuf* Name) /* Try to find the define style macro with the given name and return it. If no - * such macro was found, return NULL. - */ +** such macro was found, return NULL. +*/ { Macro* M; @@ -1043,12 +1043,9 @@ void DisableDefineStyleMacros (void) void EnableDefineStyleMacros (void) /* Re-enable define style macros previously disabled with - * DisableDefineStyleMacros. - */ +** DisableDefineStyleMacros. +*/ { PRECONDITION (DisableDefines > 0); --DisableDefines; } - - - diff --git a/src/ca65/macro.h b/src/ca65/macro.h index 582b13524..bb7b817a8 100644 --- a/src/ca65/macro.h +++ b/src/ca65/macro.h @@ -75,8 +75,8 @@ void MacDef (unsigned Style); void MacUndef (const struct StrBuf* Name, unsigned char Style); /* Undefine the macro with the given name and style. A style mismatch is - * treated as if the macro didn't exist. - */ +** treated as if the macro didn't exist. +*/ void MacExpandStart (Macro* M); /* Start expanding a macro */ @@ -86,13 +86,13 @@ void MacAbort (void); Macro* FindMacro (const struct StrBuf* Name); /* Try to find the macro with the given name and return it. If no macro with - * this name was found, return NULL. - */ +** this name was found, return NULL. +*/ Macro* FindDefine (const struct StrBuf* Name); /* Try to find the define style macro with the given name and return it. If no - * such macro was found, return NULL. - */ +** such macro was found, return NULL. +*/ int InMacExpansion (void); /* Return true if we're currently expanding a macro */ @@ -102,14 +102,11 @@ void DisableDefineStyleMacros (void); void EnableDefineStyleMacros (void); /* Re-enable define style macros previously disabled with - * DisableDefineStyleMacros. - */ +** DisableDefineStyleMacros. +*/ /* End of macro.h */ #endif - - - diff --git a/src/ca65/main.c b/src/ca65/main.c index 5a9bf7083..50878f47a 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -1,3 +1,4 @@ +/*****************************************************************************/ /* */ /* main.c */ /* */ @@ -204,6 +205,10 @@ static void SetSys (const char* Sys) AbEnd ("Cannot use `module' as a target for the assembler"); break; + case TGT_ATARI5200: + NewSymbol ("__ATARI5200__", 1); + break; + case TGT_ATARI: NewSymbol ("__ATARI__", 1); break; @@ -518,8 +523,8 @@ static void OptListing (const char* Opt, const char* Arg) /* Create a listing file */ { /* Since the meaning of -l and --listing has changed, print an error if - * the filename is empty or begins with the option char. - */ + ** the filename is empty or begins with the option char. + */ if (Arg == 0 || *Arg == '\0' || *Arg == '-') { Fatal ("The meaning of `%s' has changed. It does now " "expect a file name as argument.", Opt); @@ -634,8 +639,8 @@ static void OneLine (void) int Instr = -1; /* Initialize the new listing line if we are actually reading from file - * and not from internally pushed input. - */ + ** and not from internally pushed input. + */ if (!HavePushedInput ()) { InitListingLine (); } @@ -647,25 +652,28 @@ static void OneLine (void) } /* If the first token on the line is an identifier, check for a macro or - * an instruction. - */ + ** an instruction. + */ if (CurTok.Tok == TOK_IDENT) { - if (!UbiquitousIdents) { - /* Macros and symbols cannot use instruction names */ + if (UbiquitousIdents) { + /* Macros CAN be instructions, so check for them first */ + Mac = FindMacro (&CurTok.SVal); + if (Mac == 0) { + Instr = FindInstruction (&CurTok.SVal); + } + } else { + /* Macros and symbols may NOT use the names of instructions */ Instr = FindInstruction (&CurTok.SVal); if (Instr < 0) { Mac = FindMacro (&CurTok.SVal); } - } else { - /* Macros and symbols may use the names of instructions */ - Mac = FindMacro (&CurTok.SVal); } } /* Handle an identifier. This may be a cheap local symbol, or a fully - * scoped identifier which may start with a namespace token (for global - * namespace) - */ + ** scoped identifier which may start with a namespace token (for global + ** namespace) + */ if (CurTok.Tok == TOK_LOCAL_IDENT || CurTok.Tok == TOK_NAMESPACE || (CurTok.Tok == TOK_IDENT && Instr < 0 && Mac == 0)) { @@ -677,8 +685,8 @@ static void OneLine (void) Sym = ParseAnySymName (SYM_ALLOC_NEW); /* If a colon follows, this is a label definition. If there - * is no colon, it's an assignment. - */ + ** is no colon, it's an assignment. + */ if (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_ASSIGN) { /* Determine the symbol flags from the assignment token */ @@ -705,8 +713,8 @@ static void OneLine (void) Expr = GenLiteralExpr (ConstExpression ()); /* Define the symbol with the constant expression following - * the '=' - */ + ** the '=' + */ SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_VAR); /* Don't allow anything after a symbol definition */ @@ -716,8 +724,8 @@ static void OneLine (void) } else { /* A label. Remember the current segment, so we can later - * determine the size of the data stored under the label. - */ + ** determine the size of the data stored under the label. + */ Seg = ActiveSeg; PC = GetPC (); @@ -725,9 +733,9 @@ static void OneLine (void) SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL); /* Skip the colon. If NoColonLabels is enabled, allow labels - * without a colon if there is no whitespace before the - * identifier. - */ + ** without a colon if there is no whitespace before the + ** identifier. + */ if (CurTok.Tok != TOK_COLON) { if (HadWS || !NoColonLabels) { Error ("`:' expected"); @@ -742,18 +750,21 @@ static void OneLine (void) } /* If we come here, a new identifier may be waiting, which may - * be a macro or instruction. - */ + ** be a macro or instruction. + */ if (CurTok.Tok == TOK_IDENT) { - if (!UbiquitousIdents) { - /* Macros and symbols cannot use instruction names */ + if (UbiquitousIdents) { + /* Macros CAN be instructions, so check for them first */ + Mac = FindMacro (&CurTok.SVal); + if (Mac == 0) { + Instr = FindInstruction (&CurTok.SVal); + } + } else { + /* Macros and symbols may NOT use the names of instructions */ Instr = FindInstruction (&CurTok.SVal); if (Instr < 0) { Mac = FindMacro (&CurTok.SVal); } - } else { - /* Macros and symbols may use the names of instructions */ - Mac = FindMacro (&CurTok.SVal); } } } @@ -766,8 +777,7 @@ static void OneLine (void) } else if (Mac != 0) { /* A macro expansion */ MacExpandStart (Mac); - } else if (Instr >= 0 || - (UbiquitousIdents && ((Instr = FindInstruction (&CurTok.SVal)) >= 0))) { + } else if (Instr >= 0) { /* A mnemonic - assemble one instruction */ HandleInstruction (Instr); } else if (PCAssignment && (CurTok.Tok == TOK_STAR || CurTok.Tok == TOK_PC)) { @@ -784,9 +794,9 @@ static void OneLine (void) } /* If we have defined a label, remember its size. Sym is also set by - * a symbol assignment, but in this case Done is false, so we don't - * come here. - */ + ** a symbol assignment, but in this case Done is false, so we don't + ** come here. + */ if (Sym) { unsigned long Size; if (Seg == ActiveSeg) { @@ -910,13 +920,13 @@ int main (int argc, char* argv []) SegInit (); /* Enter the base lexical level. We must do that here, since we may - * define symbols using -D. - */ + ** define symbols using -D. + */ SymEnterLevel (&GlobalNameSpace, SCOPE_FILE, ADDR_SIZE_DEFAULT, 0); /* Initialize the line infos. Must be done here, since we need line infos - * for symbol definitions. - */ + ** for symbol definitions. + */ InitLineInfo (); /* Check the parameters */ @@ -1098,8 +1108,8 @@ int main (int argc, char* argv []) DoneLineInfo (); /* If we didn't have any errors, create the object, listing and - * dependency files - */ + ** dependency files + */ if (ErrorCount == 0) { CreateObjFile (); if (SB_GetLen (&ListingName) > 0) { @@ -1114,6 +1124,3 @@ int main (int argc, char* argv []) /* Return an apropriate exit code */ return (ErrorCount == 0)? EXIT_SUCCESS : EXIT_FAILURE; } - - - diff --git a/src/ca65/nexttok.c b/src/ca65/nexttok.c index d52a8babd..1521ed0c2 100644 --- a/src/ca65/nexttok.c +++ b/src/ca65/nexttok.c @@ -70,9 +70,9 @@ static unsigned RawMode = 0; /* Raw token mode flag/counter */ static int LookAtStrCon (void) /* Make sure the next token is a string constant. If not, print an error - * messages skip the remainder of the line and return false. Otherwise return - * true. - */ +** messages skip the remainder of the line and return false. Otherwise return +** true. +*/ { if (CurTok.Tok != TOK_STRCON) { Error ("String constant expected"); @@ -93,10 +93,10 @@ static int LookAtStrCon (void) static TokList* CollectTokens (unsigned Start, unsigned Count) /* Read a list of tokens that is optionally enclosed in curly braces and - * terminated by a right paren. For all tokens starting at the one with index - * Start, and ending at (Start+Count-1), place them into a token list, and - * return this token list. - */ +** terminated by a right paren. For all tokens starting at the one with index +** Start, and ending at (Start+Count-1), place them into a token list, and +** return this token list. +*/ { /* Create the token list */ @@ -176,8 +176,8 @@ static void FuncConcat (void) } /* We expect a closing parenthesis, but will not skip it but replace it - * by the string token just created. - */ + ** by the string token just created. + */ if (CurTok.Tok != TOK_RPAREN) { Error ("`)' expected"); } else { @@ -220,8 +220,8 @@ static void FuncIdent (void) } /* Check that the string contains a valid identifier. While doing so, - * determine if it is a cheap local, or global one. - */ + ** determine if it is a cheap local, or global one. + */ SB_Reset (&CurTok.SVal); /* Check for a cheap local symbol */ @@ -248,8 +248,8 @@ static void FuncIdent (void) } /* If anything is ok, save and skip the string. Check that the next token - * is a right paren, then replace the token by an identifier token. - */ + ** is a right paren, then replace the token by an identifier token. + */ SB_Copy (&Buf, &CurTok.SVal); NextTok (); if (CurTok.Tok != TOK_RPAREN) { @@ -289,12 +289,12 @@ static void FuncLeft (void) List = CollectTokens (0, (unsigned) Count); /* Since we want to insert the list before the now current token, we have - * to save the current token in some way and then skip it. To do this, we - * will add the current token at the end of the token list (so the list - * will never be empty), push the token list, and then skip the current - * token. This will replace the current token by the first token from the - * list (which will be the old current token in case the list was empty). - */ + ** to save the current token in some way and then skip it. To do this, we + ** will add the current token at the end of the token list (so the list + ** will never be empty), push the token list, and then skip the current + ** token. This will replace the current token by the first token from the + ** list (which will be the old current token in case the list was empty). + */ AddCurTok (List); /* Insert it into the scanner feed */ @@ -320,8 +320,8 @@ static void FuncMid (void) ConsumeLParen (); /* Start argument. Since the start argument can get negative with - * expressions like ".tcount(arg)-2", we correct it to zero silently. - */ + ** expressions like ".tcount(arg)-2", we correct it to zero silently. + */ Start = ConstExpression (); if (Start < 0 || Start > 100) { Start = 0; @@ -329,8 +329,8 @@ static void FuncMid (void) ConsumeComma (); /* Count argument. Similar as above, we will accept negative counts and - * correct them to zero silently. - */ + ** correct them to zero silently. + */ Count = ConstExpression (); if (Count < 0) { Count = 0; @@ -341,12 +341,12 @@ static void FuncMid (void) List = CollectTokens ((unsigned) Start, (unsigned) Count); /* Since we want to insert the list before the now current token, we have - * to save the current token in some way and then skip it. To do this, we - * will add the current token at the end of the token list (so the list - * will never be empty), push the token list, and then skip the current - * token. This will replace the current token by the first token from the - * list (which will be the old current token in case the list was empty). - */ + ** to save the current token in some way and then skip it. To do this, we + ** will add the current token at the end of the token list (so the list + ** will never be empty), push the token list, and then skip the current + ** token. This will replace the current token by the first token from the + ** list (which will be the old current token in case the list was empty). + */ AddCurTok (List); /* Insert it into the scanner feed */ @@ -396,12 +396,12 @@ static void FuncRight (void) } /* Since we want to insert the list before the now current token, we have - * to save the current token in some way and then skip it. To do this, we - * will add the current token at the end of the token list (so the list - * will never be empty), push the token list, and then skip the current - * token. This will replace the current token by the first token from the - * list (which will be the old current token in case the list was empty). - */ + ** to save the current token in some way and then skip it. To do this, we + ** will add the current token at the end of the token list (so the list + ** will never be empty), push the token list, and then skip the current + ** token. This will replace the current token by the first token from the + ** list (which will be the old current token in case the list was empty). + */ AddCurTok (List); /* Insert it into the scanner feed */ @@ -474,15 +474,15 @@ static void FuncSPrintF (void) break; } - /* Since a format specifier follows, we do expect anotehr argument for - * the .sprintf function. - */ + /* Since a format specifier follows, we do expect another argument for + ** the .sprintf function. + */ ConsumeComma (); /* We will copy the format spec into F1 checking for the things we - * support, and later use xsprintf to do the actual formatting. This - * is easier than adding another printf implementation... - */ + ** support, and later use xsprintf to do the actual formatting. This + ** is easier than adding another printf implementation... + */ SB_Clear (&F1); SB_AppendChar (&F1, '%'); @@ -522,8 +522,8 @@ static void FuncSPrintF (void) case 'X': case 'x': /* Our ints are actually longs, so we use the 'l' modifier when - * calling xsprintf later. Terminate the format string. - */ + ** calling xsprintf later. Terminate the format string. + */ SB_AppendChar (&F1, 'l'); SB_AppendChar (&F1, SB_Get (&Format)); SB_Terminate (&F1); @@ -576,8 +576,8 @@ static void FuncSPrintF (void) } /* Format this argument according to the spec. Be sure to pass - * an int as the char value. - */ + ** an int as the char value. + */ SB_Printf (&R1, SB_GetConstBuf (&F1), (int) IVal); /* Append the formatted argument to the result */ @@ -597,8 +597,8 @@ static void FuncSPrintF (void) SB_Terminate (&R); /* We expect a closing parenthesis, but will not skip it but replace it - * by the string token just created. - */ + ** by the string token just created. + */ if (CurTok.Tok != TOK_RPAREN) { Error ("`)' expected"); } else { @@ -636,8 +636,8 @@ static void FuncString (void) } else if (CurTok.Tok == TOK_NAMESPACE || CurTok.Tok == TOK_IDENT) { /* Parse a fully qualified symbol name. We cannot use - * ParseScopedSymName here since the name may be invalid. - */ + ** ParseScopedSymName here since the name may be invalid. + */ int NameSpace; do { NameSpace = (CurTok.Tok == TOK_NAMESPACE); @@ -657,8 +657,8 @@ static void FuncString (void) } /* We expect a closing parenthesis, but will not skip it but replace it - * by the string token just created. - */ + ** by the string token just created. + */ if (CurTok.Tok != TOK_RPAREN) { Error ("`)' expected"); } else { @@ -680,8 +680,8 @@ void NextTok (void) NextRawTok (); /* In raw mode, or when output is suppressed via conditional assembly, - * pass the token unchanged. - */ + ** pass the token unchanged. + */ if (RawMode == 0 && IfCond) { /* Execute token handling functions */ @@ -787,8 +787,8 @@ void SkipUntilSep (void) void ExpectSep (void) /* Check if we've reached a line separator, and output an error if not. Do - * not skip the line separator. - */ +** not skip the line separator. +*/ { if (!TokIsSep (CurTok.Tok)) { ErrorSkip ("Unexpected trailing garbage characters"); @@ -799,11 +799,11 @@ void ExpectSep (void) void EnterRawTokenMode (void) /* Enter raw token mode. In raw mode, token handling functions are not - * executed, but the function tokens are passed untouched to the upper - * layer. Raw token mode is used when storing macro tokens for later - * use. - * Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested. - */ +** executed, but the function tokens are passed untouched to the upper +** layer. Raw token mode is used when storing macro tokens for later +** use. +** Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested. +*/ { ++RawMode; } @@ -816,6 +816,3 @@ void LeaveRawTokenMode (void) PRECONDITION (RawMode > 0); --RawMode; } - - - diff --git a/src/ca65/nexttok.h b/src/ca65/nexttok.h index d8d7c0101..68a371a0b 100644 --- a/src/ca65/nexttok.h +++ b/src/ca65/nexttok.h @@ -71,16 +71,16 @@ void SkipUntilSep (void); void ExpectSep (void); /* Check if we've reached a line separator, and output an error if not. Do - * not skip the line separator. - */ +** not skip the line separator. +*/ void EnterRawTokenMode (void); /* Enter raw token mode. In raw mode, token handling functions are not - * executed, but the function tokens are passed untouched to the upper - * layer. Raw token mode is used when storing macro tokens for later - * use. - * Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested. - */ +** executed, but the function tokens are passed untouched to the upper +** layer. Raw token mode is used when storing macro tokens for later +** use. +** Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested. +*/ void LeaveRawTokenMode (void); /* Leave raw token mode. */ @@ -90,7 +90,3 @@ void LeaveRawTokenMode (void); /* End of nexttok.h */ #endif - - - - diff --git a/src/ca65/objcode.c b/src/ca65/objcode.c index 3ab9b2ebe..d1ab4f6bd 100644 --- a/src/ca65/objcode.c +++ b/src/ca65/objcode.c @@ -278,6 +278,3 @@ void EmitFill (unsigned long Count) GenFragment (FRAG_FILL, Chunk); } } - - - diff --git a/src/ca65/objcode.h b/src/ca65/objcode.h index 68b967e3f..70a031164 100644 --- a/src/ca65/objcode.h +++ b/src/ca65/objcode.h @@ -94,6 +94,3 @@ void EmitFill (unsigned long Count); /* End of objcode.h */ #endif - - - diff --git a/src/ca65/objfile.c b/src/ca65/objfile.c index 818e5625b..dfa0d146e 100644 --- a/src/ca65/objfile.c +++ b/src/ca65/objfile.c @@ -100,8 +100,8 @@ static ObjHeader Header = { static void ObjWriteError (void) /* Called on a write error. Will try to close and remove the file, then - * print a fatal error. - */ +** print a fatal error. +*/ { /* Remember the error */ int Error = errno; @@ -162,8 +162,8 @@ void ObjOpen (void) /* Do we have a name for the output file? */ if (OutFile == 0) { /* We don't have an output name explicitly given, construct one from - * the name of the input file. - */ + ** the name of the input file. + */ OutFile = MakeFilename (InFile, OBJ_EXT); } @@ -269,10 +269,10 @@ void ObjWriteVar (unsigned long V) /* Write a variable sized value to the file in special encoding */ { /* We will write the value to the file in 7 bit chunks. If the 8th bit - * is clear, we're done, if it is set, another chunk follows. This will - * allow us to encode smaller values with less bytes, at the expense of - * needing 5 bytes if a 32 bit value is written to file. - */ + ** is clear, we're done, if it is set, another chunk follows. This will + ** allow us to encode smaller values with less bytes, at the expense of + ** needing 5 bytes if a 32 bit value is written to file. + */ do { unsigned char C = (V & 0x7F); V >>= 7; @@ -291,9 +291,9 @@ void ObjWriteStr (const char* S) unsigned Len = strlen (S); /* Write the string with the length preceeded (this is easier for - * the reading routine than the C format since the length is known in - * advance). - */ + ** the reading routine than the C format since the length is known in + ** advance). + */ ObjWriteVar (Len); ObjWriteData (S, Len); } @@ -304,9 +304,9 @@ void ObjWriteBuf (const StrBuf* S) /* Write a string to the object file */ { /* Write the string with the length preceeded (this is easier for - * the reading routine than the C format since the length is known in - * advance). - */ + ** the reading routine than the C format since the length is known in + ** advance). + */ ObjWriteVar (SB_GetLen (S)); ObjWriteData (SB_GetConstBuf (S), SB_GetLen (S)); } @@ -512,6 +512,3 @@ void ObjEndSpans (void) { Header.SpanSize = ftell (F) - Header.SpanOffs; } - - - diff --git a/src/ca65/objfile.h b/src/ca65/objfile.h index ab775ca24..c1d148725 100644 --- a/src/ca65/objfile.h +++ b/src/ca65/objfile.h @@ -160,6 +160,3 @@ void ObjEndSpans (void); /* End of objfile.h */ #endif - - - diff --git a/src/ca65/options.h b/src/ca65/options.h index 6b4184824..96eb90ba7 100644 --- a/src/ca65/options.h +++ b/src/ca65/options.h @@ -73,6 +73,3 @@ void WriteOptions (void); /* End of options.h */ #endif - - - diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 5c534b29c..0b066c7bd 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -112,12 +112,12 @@ static void DoUnexpected (void); static void DoInvalid (void); /* Handle a token that is invalid here, since it should have been handled on - * a much lower level of the expression hierarchy. Getting this sort of token - * means that the lower level code has bugs. - * This function differs to DoUnexpected in that the latter may be triggered - * by the user by using keywords in the wrong location. DoUnexpected is not - * an error in the assembler itself, while DoInvalid is. - */ +** a much lower level of the expression hierarchy. Getting this sort of token +** means that the lower level code has bugs. +** This function differs to DoUnexpected in that the latter may be triggered +** by the user by using keywords in the wrong location. DoUnexpected is not +** an error in the assembler itself, while DoInvalid is. +*/ @@ -129,8 +129,8 @@ static void DoInvalid (void); static unsigned char OptionalAddrSize (void) /* If a colon follows, parse an optional address size spec and return it. - * Otherwise return ADDR_SIZE_DEFAULT. - */ +** Otherwise return ADDR_SIZE_DEFAULT. +*/ { unsigned AddrSize = ADDR_SIZE_DEFAULT; if (CurTok.Tok == TOK_COLON) { @@ -183,8 +183,8 @@ static void ExportWithAssign (SymEntry* Sym, unsigned char AddrSize, unsigned Fl /* Allow to assign the value of an export in an .export statement */ { /* The name and optional address size spec may be followed by an assignment - * or equal token. - */ + ** or equal token. + */ if (CurTok.Tok == TOK_ASSIGN || CurTok.Tok == TOK_EQ) { /* Assignment means the symbol is a label */ @@ -249,8 +249,8 @@ static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned), static long IntArg (long Min, long Max) /* Read an integer argument and check a range. Accept the token "unlimited" - * and return -1 in this case. - */ +** and return -1 in this case. +*/ { if (CurTok.Tok == TOK_IDENT && SB_CompareStr (&CurTok.SVal, "unlimited") == 0) { NextTok (); @@ -301,9 +301,9 @@ static StrBuf* GenArrayType (StrBuf* Type, unsigned SpanSize, const char* ElementType, unsigned ElementTypeLen) /* Create an array (or single data) of the given type. SpanSize is the size - * of the span, ElementType is a string that encodes the element data type. - * The function returns Type. - */ +** of the span, ElementType is a string that encodes the element data type. +** The function returns Type. +*/ { /* Get the size of the element type */ unsigned ElementSize = GT_GET_SIZE (ElementType[0]); @@ -504,8 +504,8 @@ static void DoAssert (void) NextTok (); /* We can have an optional message. If no message is present, use - * "Assertion failed". - */ + ** "Assertion failed". + */ if (CurTok.Tok == TOK_COMMA) { /* Skip the comma */ @@ -518,8 +518,8 @@ static void DoAssert (void) } /* Translate the message into a string id. We can then skip the input - * string. - */ + ** string. + */ Msg = GetStrBufId (&CurTok.SVal); NextTok (); @@ -1253,14 +1253,14 @@ static void DoIncBin (void) fseek (F, 0, SEEK_END); Size = ftell (F); - /* Stat the file and remember the values. There a race condition here, - * since we cannot use fileno() (non standard identifier in standard - * header file), and therefore not fstat. When using stat with the - * file name, there's a risk that the file was deleted and recreated - * while it was open. Since mtime and size are only used to check - * if a file has changed in the debugger, we will ignore this problem - * here. - */ + /* Stat the file and remember the values. There's a race condition here, + ** since we cannot use fileno() (non-standard identifier in standard + ** header file), and therefore not fstat. When using stat with the + ** file name, there's a risk that the file was deleted and recreated + ** while it was open. Since mtime and size are only used to check + ** if a file has changed in the debugger, we will ignore this problem + ** here. + */ SB_Terminate (&Name); if (FileStat (SB_GetConstBuf (&Name), &StatBuf) != 0) { Fatal ("Cannot stat input file `%m%p': %s", &Name, strerror (errno)); @@ -1364,12 +1364,12 @@ static void DoInterruptor (void) static void DoInvalid (void) /* Handle a token that is invalid here, since it should have been handled on - * a much lower level of the expression hierarchy. Getting this sort of token - * means that the lower level code has bugs. - * This function differs to DoUnexpected in that the latter may be triggered - * by the user by using keywords in the wrong location. DoUnexpected is not - * an error in the assembler itself, while DoInvalid is. - */ +** a much lower level of the expression hierarchy. Getting this sort of token +** means that the lower level code has bugs. +** This function differs to DoUnexpected in that the latter may be triggered +** by the user by using keywords in the wrong location. DoUnexpected is not +** an error in the assembler itself, while DoInvalid is. +*/ { Internal ("Unexpected token: %m%p", &Keyword); } @@ -1494,8 +1494,8 @@ static void DoOut (void) ErrorSkip ("String constant expected"); } else { /* Output the string and be sure to flush the output to keep it in - * sync with any error messages if the output is redirected to a file. - */ + ** sync with any error messages if the output is redirected to a file. + */ printf ("%.*s\n", (int) SB_GetLen (&CurTok.SVal), SB_GetConstBuf (&CurTok.SVal)); @@ -1794,8 +1794,8 @@ static void DoSetCPU (void) SetCPU (CPU); /* Skip the identifier. If the CPU switch was successful, the scanner - * will treat the input now correctly for the new CPU. - */ + ** will treat the input now correctly for the new CPU. + */ NextTok (); } } @@ -1810,14 +1810,6 @@ static void DoSmart (void) -static void DoSunPlus (void) -/* Switch to the SUNPLUS CPU */ -{ - SetCPU (CPU_SUNPLUS); -} - - - static void DoTag (void) /* Allocate space for a struct */ { @@ -1869,10 +1861,10 @@ static void DoUnDef (void) /* Undefine a define style macro */ { /* The function is called with the .UNDEF token in place, because we need - * to disable .define macro expansions before reading the next token. - * Otherwise the name of the macro would be expanded, so we would never - * see it. - */ + ** to disable .define macro expansions before reading the next token. + ** Otherwise the name of the macro would be expanded, so we would never + ** see it. + */ DisableDefineStyleMacros (); NextTok (); EnableDefineStyleMacros (); @@ -2093,7 +2085,6 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoUnexpected }, /* .STRING */ { ccNone, DoUnexpected }, /* .STRLEN */ { ccNone, DoStruct }, - { ccNone, DoSunPlus }, { ccNone, DoTag }, { ccNone, DoUnexpected }, /* .TCOUNT */ { ccNone, DoUnexpected }, /* .TIME */ @@ -2154,6 +2145,3 @@ void CheckPseudo (void) Warning (1, "CPU stack is not empty"); } } - - - diff --git a/src/ca65/pseudo.h b/src/ca65/pseudo.h index 006b27909..6199f661e 100644 --- a/src/ca65/pseudo.h +++ b/src/ca65/pseudo.h @@ -55,6 +55,3 @@ void CheckPseudo (void); /* End of pseudo.h */ #endif - - - diff --git a/src/ca65/repeat.c b/src/ca65/repeat.c index 915c8a78f..90aa894f7 100644 --- a/src/ca65/repeat.c +++ b/src/ca65/repeat.c @@ -55,8 +55,8 @@ static TokList* CollectRepeatTokens (void) /* Collect all tokens inside the .REPEAT body in a token list and return - * this list. In case of errors, NULL is returned. - */ +** this list. In case of errors, NULL is returned. +*/ { /* Create the token list */ TokList* List = NewTokList (); @@ -97,8 +97,8 @@ static TokList* CollectRepeatTokens (void) static void RepeatTokenCheck (TokList* L) /* Called each time a token from a repeat token list is set. Is used to check - * for and replace identifiers that are the repeat counter. - */ +** for and replace identifiers that are the repeat counter. +*/ { if (CurTok.Tok == TOK_IDENT && L->Data != 0 && @@ -161,8 +161,8 @@ void ParseRepeat (void) List->Check = RepeatTokenCheck; /* If the list is empty, or repeat count zero, there is nothing - * to repeat. - */ + ** to repeat. + */ if (List->Count == 0 || RepCount == 0) { FreeTokList (List); goto Done; @@ -175,6 +175,3 @@ Done: /* Switch out of raw token mode */ LeaveRawTokenMode (); } - - - diff --git a/src/ca65/repeat.h b/src/ca65/repeat.h index 1cdccc0e3..3230fb657 100644 --- a/src/ca65/repeat.h +++ b/src/ca65/repeat.h @@ -52,7 +52,3 @@ void ParseRepeat (void); /* End of repeat.h */ #endif - - - - diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index aadb91d54..890e1c7a3 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -276,7 +276,6 @@ struct DotKeyword { { ".STRING", TOK_STRING }, { ".STRLEN", TOK_STRLEN }, { ".STRUCT", TOK_STRUCT }, - { ".SUNPLUS", TOK_SUNPLUS }, { ".TAG", TOK_TAG }, { ".TCOUNT", TOK_TCOUNT }, { ".TIME", TOK_TIME }, @@ -314,8 +313,8 @@ static void UseCharSource (CharSource* S) S->Func->NextChar (S); /* Setup the next token so it will be skipped on the next call to - * NextRawTok(). - */ + ** NextRawTok(). + */ CurTok.Tok = TOK_SEP; } @@ -379,8 +378,8 @@ static void IFNextChar (CharSource* S) } /* No more data - add an empty line to the listing. This - * is a small hack needed to keep the PC output in sync. - */ + ** is a small hack needed to keep the PC output in sync. + */ NewListingLine (&EmptyStrBuf, S->V.File.Pos.Name, FCount); C = EOF; return; @@ -402,9 +401,9 @@ static void IFNextChar (CharSource* S) /* If we come here, we have a new input line. To avoid problems - * with strange line terminators, remove all whitespace from the - * end of the line, the add a single newline. - */ + ** with strange line terminators, remove all whitespace from the + ** end of the line, the add a single newline. + */ Len = SB_GetLen (&S->V.File.Line); while (Len > 0 && IsSpace (SB_AtUnchecked (&S->V.File.Line, Len-1))) { --Len; @@ -436,11 +435,11 @@ void IFDone (CharSource* S) /* Close the current input file */ { /* We're at the end of an include file. Check if we have any - * open .IFs, or any open token lists in this file. This - * enforcement is artificial, using conditionals that start - * in one file and end in another are uncommon, and don't - * allowing these things will help finding errors. - */ + ** open .IFs, or any open token lists in this file. This + ** enforcement is artificial, using conditionals that start + ** in one file and end in another are uncommon, and don't + ** allowing these things will help finding errors. + */ CheckOpenIfs (); /* If we've added search paths for this file, remove them */ @@ -455,8 +454,8 @@ void IFDone (CharSource* S) SB_Done (&S->V.File.Line); /* Close the input file and decrement the file count. We will ignore - * errors here, since we were just reading from the file. - */ + ** errors here, since we were just reading from the file. + */ (void) fclose (S->V.File.F); --FCount; } @@ -474,8 +473,8 @@ static const CharSourceFunctions IFFunc = { int NewInputFile (const char* Name) /* Open a new input file. Returns true if the file could be successfully opened - * and false otherwise. - */ +** and false otherwise. +*/ { int RetCode = 0; /* Return code. Assume an error. */ char* PathName = 0; @@ -488,8 +487,8 @@ int NewInputFile (const char* Name) /* If this is the main file, just try to open it. If it's an include file, - * search for it using the include path list. - */ + ** search for it using the include path list. + */ if (FCount == 0) { /* Main file */ F = fopen (Name, "r"); @@ -498,8 +497,8 @@ int NewInputFile (const char* Name) } } else { /* We are on include level. Search for the file in the include - * directories. - */ + ** directories. + */ PathName = SearchFile (IncSearchPath, Name); if (PathName == 0 || (F = fopen (PathName, "r")) == 0) { /* Not found or cannot open, print an error and bail out */ @@ -511,14 +510,14 @@ int NewInputFile (const char* Name) Name = PathName; } - /* Stat the file and remember the values. There a race condition here, - * since we cannot use fileno() (non standard identifier in standard - * header file), and therefore not fstat. When using stat with the - * file name, there's a risk that the file was deleted and recreated - * while it was open. Since mtime and size are only used to check - * if a file has changed in the debugger, we will ignore this problem - * here. - */ + /* Stat the file and remember the values. There's a race condition here, + ** since we cannot use fileno() (non-standard identifier in standard + ** header file), and therefore not fstat. When using stat with the + ** file name, there's a risk that the file was deleted and recreated + ** while it was open. Since mtime and size are only used to check + ** if a file has changed in the debugger, we will ignore this problem + ** here. + */ if (FileStat (Name, &Buf) != 0) { Fatal ("Cannot stat input file `%s': %s", Name, strerror (errno)); } @@ -705,8 +704,8 @@ static int CmpDotKeyword (const void* K1, const void* K2) static token_t FindDotKeyword (void) /* Find the dot keyword in SVal. Return the corresponding token if found, - * return TOK_NONE if not found. - */ +** return TOK_NONE if not found. +*/ { struct DotKeyword K; struct DotKeyword* R; @@ -734,10 +733,10 @@ static token_t FindDotKeyword (void) static void ReadIdent (void) /* Read an identifier from the current input position into Ident. Filling SVal - * starts at the current position with the next character in C. It is assumed - * that any characters already filled in are ok, and the character in C is - * checked. - */ +** starts at the current position with the next character in C. It is assumed +** that any characters already filled in are ok, and the character in C is +** checked. +*/ { /* Read the identifier */ do { @@ -788,8 +787,8 @@ static void ReadStringConst (int StringTerm) static int Sweet16Reg (const StrBuf* Id) /* Check if the given identifier is a sweet16 register. Return -1 if this is - * not the case, return the register number otherwise. - */ +** not the case, return the register number otherwise. +*/ { unsigned RegNum; char Check; @@ -961,9 +960,9 @@ Again: } if (IsXDigit (C)) { /* Buf is big enough to allow any decimal and hex number to - * overflow, so ignore excess digits here, they will be detected - * when we convert the value. - */ + ** overflow, so ignore excess digits here, they will be detected + ** when we convert the value. + */ if (Digits < sizeof (Buf)) { Buf[Digits++] = C; } @@ -1035,8 +1034,8 @@ Again: } /* An identifier with a dot. Check if it's a define style - * macro. - */ + ** macro. + */ if ((M = FindDefine (&CurTok.SVal)) != 0) { /* This is a define style macro - expand it */ MacExpandStart (M); @@ -1052,8 +1051,8 @@ Again: } /* Indirect op for sweet16 cpu. Must check this before checking for local - * symbols, because these may also use the '@' symbol. - */ + ** symbols, because these may also use the '@' symbol. + */ if (CPU == CPU_SWEET16 && C == '@') { NextChar (); CurTok.Tok = TOK_AT; @@ -1085,8 +1084,8 @@ Again: ReadIdent (); /* Check for special names. Bail out if we have identified the type of - * the token. Go on if the token is an identifier. - */ + ** the token. Go on if the token is an identifier. + */ if (SB_GetLen (&CurTok.SVal) == 1) { switch (toupper (SB_AtUnchecked (&CurTok.SVal, 0))) { @@ -1358,9 +1357,9 @@ CharAgain: case '\'': /* Hack: If we allow ' as terminating character for strings, read - * the following stuff as a string, and check for a one character - * string later. - */ + ** the following stuff as a string, and check for a one character + ** string later. + */ if (LooseStringTerm) { ReadStringConst ('\''); if (SB_GetLen (&CurTok.SVal) == 1) { @@ -1425,8 +1424,8 @@ CharAgain: } /* If we go here, we could not identify the current character. Skip it - * and try again. - */ + ** and try again. + */ Error ("Invalid input character: 0x%02X", C & 0xFF); NextChar (); goto Again; @@ -1436,10 +1435,10 @@ CharAgain: int GetSubKey (const char** Keys, unsigned Count) /* Search for a subkey in a table of keywords. The current token must be an - * identifier and all keys must be in upper case. The identifier will be - * uppercased in the process. The function returns the index of the keyword, - * or -1 if the keyword was not found. - */ +** identifier and all keys must be in upper case. The identifier will be +** uppercased in the process. The function returns the index of the keyword, +** or -1 if the keyword was not found. +*/ { unsigned I; @@ -1467,9 +1466,9 @@ int GetSubKey (const char** Keys, unsigned Count) unsigned char ParseAddrSize (void) /* Check if the next token is a keyword that denotes an address size specifier. - * If so, return the corresponding address size constant, otherwise output an - * error message and return ADDR_SIZE_DEFAULT. - */ +** If so, return the corresponding address size constant, otherwise output an +** error message and return ADDR_SIZE_DEFAULT. +*/ { unsigned char AddrSize; @@ -1506,7 +1505,3 @@ void DoneScanner (void) { DoneCharSource (); } - - - - diff --git a/src/ca65/scanner.h b/src/ca65/scanner.h index b0fc3411f..c445aefa6 100644 --- a/src/ca65/scanner.h +++ b/src/ca65/scanner.h @@ -69,8 +69,8 @@ int IsIdStart (int C); int NewInputFile (const char* Name); /* Open a new input file. Returns true if the file could be successfully opened - * and false otherwise. - */ +** and false otherwise. +*/ void NewInputData (char* Text, int Malloced); /* Add a chunk of input data to the input stream */ @@ -86,16 +86,16 @@ void NextRawTok (void); int GetSubKey (const char** Keys, unsigned Count); /* Search for a subkey in a table of keywords. The current token must be an - * identifier and all keys must be in upper case. The identifier will be - * uppercased in the process. The function returns the index of the keyword, - * or -1 if the keyword was not found. - */ +** identifier and all keys must be in upper case. The identifier will be +** uppercased in the process. The function returns the index of the keyword, +** or -1 if the keyword was not found. +*/ unsigned char ParseAddrSize (void); /* Check if the next token is a keyword that denotes an address size specifier. - * If so, return the corresponding address size constant, otherwise output an - * error message and return ADDR_SIZE_DEFAULT. - */ +** If so, return the corresponding address size constant, otherwise output an +** error message and return ADDR_SIZE_DEFAULT. +*/ void InitScanner (const char* InFile); /* Initialize the scanner, open the given input file */ @@ -108,7 +108,3 @@ void DoneScanner (void); /* End of scanner.h */ #endif - - - - diff --git a/src/ca65/segdef.c b/src/ca65/segdef.c index 3c1a59992..bf735ef31 100644 --- a/src/ca65/segdef.c +++ b/src/ca65/segdef.c @@ -77,7 +77,3 @@ SegDef* DupSegDef (const SegDef* Def) { return NewSegDef (Def->Name, Def->AddrSize); } - - - - diff --git a/src/ca65/segdef.h b/src/ca65/segdef.h index c7431b9a2..824a59bed 100644 --- a/src/ca65/segdef.h +++ b/src/ca65/segdef.h @@ -81,6 +81,3 @@ SegDef* DupSegDef (const SegDef* D); /* End of segdef.h */ #endif - - - diff --git a/src/ca65/segment.c b/src/ca65/segment.c index 60a897324..35a41ffe1 100644 --- a/src/ca65/segment.c +++ b/src/ca65/segment.c @@ -68,8 +68,8 @@ /* If OrgPerSeg is false, all segments share the RelocMode flag and a PC - * used when in absolute mode. OrgPerSeg may be set by .feature org_per_seg - */ +** used when in absolute mode. OrgPerSeg may be set by .feature org_per_seg +*/ static int RelocMode = 1; static unsigned long AbsPC = 0; /* PC if in absolute mode */ @@ -97,8 +97,8 @@ Segment* ActiveSeg; static Segment* NewSegFromDef (SegDef* Def) /* Create a new segment from a segment definition. Used only internally, no - * checks. - */ +** checks. +*/ { /* Create a new segment */ Segment* S = xmalloc (sizeof (*S)); @@ -233,8 +233,8 @@ unsigned long GetPC (void) void EnterAbsoluteMode (unsigned long PC) /* Enter absolute (non relocatable mode). Depending on the OrgPerSeg flag, - * this will either switch the mode globally or for the current segment. - */ +** this will either switch the mode globally or for the current segment. +*/ { if (OrgPerSeg) { /* Relocatable mode is switched per segment */ @@ -265,8 +265,8 @@ int GetRelocMode (void) void EnterRelocMode (void) /* Enter relocatable mode. Depending on the OrgPerSeg flag, this will either - * switch the mode globally or for the current segment. - */ +** switch the mode globally or for the current segment. +*/ { if (OrgPerSeg) { /* Relocatable mode is switched per segment */ @@ -281,25 +281,25 @@ void EnterRelocMode (void) void SegAlign (unsigned long Alignment, int FillVal) /* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments - * (the actual fill value will be determined by the linker), otherwise use - * the given value. - */ +** (the actual fill value will be determined by the linker), otherwise use +** the given value. +*/ { unsigned char Data [4]; unsigned long CombinedAlignment; unsigned long Count; /* The segment must have the combined alignment of all separate alignments - * in the source. Calculate this alignment and check it for sanity. - */ + ** in the source. Calculate this alignment and check it for sanity. + */ CombinedAlignment = LeastCommonMultiple (ActiveSeg->Align, Alignment); if (CombinedAlignment > MAX_ALIGNMENT) { Error ("Combined alignment for active segment is %lu which exceeds %lu", CombinedAlignment, MAX_ALIGNMENT); /* Avoid creating large fills for an object file that is thrown away - * later. - */ + ** later. + */ Count = 1; } else { @@ -410,10 +410,10 @@ void SegDone (void) } else if (RelaxChecks == 0) { /* We cannot evaluate the expression now, leave the job for - * the linker. However, we can check if the address size - * matches the fragment size. Mismatches are errors in - * most situations. - */ + ** the linker. However, we can check if the address size + ** matches the fragment size. Mismatches are errors in + ** most situations. + */ if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP) || (F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) || (F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) { @@ -496,9 +496,9 @@ void SetSegmentSizes (void) /* Set the default segment sizes according to the memory model */ { /* Initialize segment sizes. The segment definitions do already contain - * the correct values for the default case (near), so we must only change - * things that should be different. - */ + ** the correct values for the default case (near), so we must only change + ** things that should be different. + */ switch (MemoryModel) { case MMODEL_NEAR: @@ -530,8 +530,8 @@ static void WriteOneSeg (Segment* Seg) unsigned long EndPos; /* Remember the file position, then write a dummy for the size of the - * following data - */ + ** following data + */ unsigned long SizePos = ObjGetFilePos (); ObjWrite32 (0); @@ -544,8 +544,8 @@ static void WriteOneSeg (Segment* Seg) ObjWriteVar (Seg->FragCount); /* Number of fragments */ /* Now walk through the fragment list for this segment and write the - * fragments. - */ + ** fragments. + */ Frag = Seg->Root; while (Frag) { @@ -627,7 +627,3 @@ void WriteSegments (void) /* Done writing segments */ ObjEndSegments (); } - - - - diff --git a/src/ca65/segment.h b/src/ca65/segment.h index 69a3eb833..231e43f83 100644 --- a/src/ca65/segment.h +++ b/src/ca65/segment.h @@ -131,9 +131,9 @@ INLINE unsigned char GetCurrentSegAddrSize (void) void SegAlign (unsigned long Alignment, int FillVal); /* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments - * (the actual fill value will be determined by the linker), otherwise use - * the given value. - */ +** (the actual fill value will be determined by the linker), otherwise use +** the given value. +*/ unsigned char GetSegAddrSize (unsigned SegNum); /* Return the address size of the segment with the given number */ @@ -146,13 +146,13 @@ int GetRelocMode (void); void EnterAbsoluteMode (unsigned long AbsPC); /* Enter absolute (non relocatable mode). Depending on the OrgPerSeg flag, - * this will either switch the mode globally or for the current segment. - */ +** this will either switch the mode globally or for the current segment. +*/ void EnterRelocMode (void); /* Enter relocatable mode. Depending on the OrgPerSeg flag, this will either - * switch the mode globally or for the current segment. - */ +** switch the mode globally or for the current segment. +*/ void SegDone (void); /* Check the segments for range and other errors. Do cleanup. */ @@ -174,6 +174,3 @@ void WriteSegments (void); /* End of segment.h */ #endif - - - diff --git a/src/ca65/sizeof.c b/src/ca65/sizeof.c index a29c83e9d..9a7d4024f 100644 --- a/src/ca65/sizeof.c +++ b/src/ca65/sizeof.c @@ -50,8 +50,8 @@ /* The name of the symbol used to encode the size. The name of this entry is - * choosen so that it cannot be accessed by the user. - */ +** choosen so that it cannot be accessed by the user. +*/ static const StrBuf SizeEntryName = LIT_STRBUF_INITIALIZER (".size"); @@ -64,8 +64,8 @@ static const StrBuf SizeEntryName = LIT_STRBUF_INITIALIZER (".size"); int IsSizeOfSymbol (const SymEntry* Sym) /* Return true if the given symbol is the one that encodes the size of some - * entity. Sym may also be a NULL pointer in which case false is returned. - */ +** entity. Sym may also be a NULL pointer in which case false is returned. +*/ { return (Sym != 0 && SB_Compare (GetSymName (Sym), &SizeEntryName) == 0); } @@ -74,8 +74,8 @@ int IsSizeOfSymbol (const SymEntry* Sym) SymEntry* FindSizeOfScope (SymTable* Scope) /* Get the size of a scope. The function returns the symbol table entry that - * encodes the size or NULL if there is no such entry. - */ +** encodes the size or NULL if there is no such entry. +*/ { return SymFind (Scope, &SizeEntryName, SYM_FIND_EXISTING); } @@ -84,8 +84,8 @@ SymEntry* FindSizeOfScope (SymTable* Scope) SymEntry* FindSizeOfSymbol (SymEntry* Sym) /* Get the size of a symbol table entry. The function returns the symbol table - * entry that encodes the size of the symbol or NULL if there is no such entry. - */ +** entry that encodes the size of the symbol or NULL if there is no such entry. +*/ { return SymFindLocal (Sym, &SizeEntryName, SYM_FIND_EXISTING); } @@ -94,8 +94,8 @@ SymEntry* FindSizeOfSymbol (SymEntry* Sym) SymEntry* GetSizeOfScope (SymTable* Scope) /* Get the size of a scope. The function returns the symbol table entry that - * encodes the size, and will create a new entry if it does not exist. - */ +** encodes the size, and will create a new entry if it does not exist. +*/ { return SymFind (Scope, &SizeEntryName, SYM_ALLOC_NEW); } @@ -104,9 +104,9 @@ SymEntry* GetSizeOfScope (SymTable* Scope) SymEntry* GetSizeOfSymbol (SymEntry* Sym) /* Get the size of a symbol table entry. The function returns the symbol table - * entry that encodes the size of the symbol and will create a new one if it - * does not exist. - */ +** entry that encodes the size of the symbol and will create a new one if it +** does not exist. +*/ { return SymFindLocal (Sym, &SizeEntryName, SYM_ALLOC_NEW); } @@ -130,6 +130,3 @@ SymEntry* DefSizeOfSymbol (SymEntry* Sym, long Size) SymDef (SizeSym, GenLiteralExpr (Size), ADDR_SIZE_DEFAULT, SF_NONE); return SizeSym; } - - - diff --git a/src/ca65/sizeof.h b/src/ca65/sizeof.h index 2bb400d83..02eb31fb0 100644 --- a/src/ca65/sizeof.h +++ b/src/ca65/sizeof.h @@ -62,29 +62,29 @@ struct SymTable; int IsSizeOfSymbol (const struct SymEntry* Sym); /* Return true if the given symbol is the one that encodes the size of some - * entity. Sym may also be a NULL pointer in which case false is returned. - */ +** entity. Sym may also be a NULL pointer in which case false is returned. +*/ struct SymEntry* FindSizeOfScope (struct SymTable* Scope); /* Get the size of a scope. The function returns the symbol table entry that - * encodes the size or NULL if there is no such entry. - */ +** encodes the size or NULL if there is no such entry. +*/ struct SymEntry* FindSizeOfSymbol (struct SymEntry* Sym); /* Get the size of a symbol table entry. The function returns the symbol table - * entry that encodes the size of the symbol or NULL if there is no such entry. - */ +** entry that encodes the size of the symbol or NULL if there is no such entry. +*/ struct SymEntry* GetSizeOfScope (struct SymTable* Scope); /* Get the size of a scope. The function returns the symbol table entry that - * encodes the size, and will create a new entry if it does not exist. - */ +** encodes the size, and will create a new entry if it does not exist. +*/ struct SymEntry* GetSizeOfSymbol (struct SymEntry* Sym); /* Get the size of a symbol table entry. The function returns the symbol table - * entry that encodes the size of the symbol and will create a new one if it - * does not exist. - */ +** entry that encodes the size of the symbol and will create a new one if it +** does not exist. +*/ struct SymEntry* DefSizeOfScope (struct SymTable* Scope, long Size); /* Define the size of a scope and return the size symbol */ @@ -95,7 +95,5 @@ struct SymEntry* DefSizeOfSymbol (struct SymEntry* Sym, long Size); /* End of sizeof.h */ + #endif - - - diff --git a/src/ca65/span.c b/src/ca65/span.c index ebec761fe..a4faea121 100644 --- a/src/ca65/span.c +++ b/src/ca65/span.c @@ -61,9 +61,9 @@ static const void* HT_GetKey (const void* Entry); static int HT_Compare (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if - * Key1 is smaller than Key2, zero if both are equal, and a value greater - * than zero if Key1 is greater then Key2. - */ +** Key1 is smaller than Key2, zero if both are equal, and a value greater +** than zero if Key1 is greater then Key2. +*/ @@ -113,9 +113,9 @@ static const void* HT_GetKey (const void* Entry) static int HT_Compare (const void* Key1, const void* Key2) /* Compare two keys. The function must return a value less than zero if - * Key1 is smaller than Key2, zero if both are equal, and a value greater - * than zero if Key1 is greater then Key2. - */ +** Key1 is smaller than Key2, zero if both are equal, and a value greater +** than zero if Key1 is greater then Key2. +*/ { /* Convert both parameters to Span pointers */ const Span* S1 = Key1; @@ -144,8 +144,8 @@ static int HT_Compare (const void* Key1, const void* Key2) static Span* NewSpan (Segment* Seg, unsigned long Start, unsigned long End) /* Create a new span. The segment is set to Seg, Start and End are set to the - * current PC of the segment. - */ +** current PC of the segment. +*/ { /* Allocate memory */ Span* S = xmalloc (sizeof (Span)); @@ -174,13 +174,13 @@ static void FreeSpan (Span* S) static Span* MergeSpan (Span* S) /* Check if we have a span with the same data as S already. If so, free S and - * return the already existing one. If not, remember S and return it. - */ +** return the already existing one. If not, remember S and return it. +*/ { /* Check if we have such a span already. If so use the existing - * one and free the one from the collection. If not, add the one to - * the hash table and return it. - */ + ** one and free the one from the collection. If not, add the one to + ** the hash table and return it. + */ Span* E = HT_Find (&SpanTab, S); if (E) { /* If S has a type and E not, move the type */ @@ -223,9 +223,9 @@ Span* OpenSpan (void) Span* CloseSpan (Span* S) /* Close the given span. Be sure to replace the passed span by the one - * returned, since the span will get deleted if it is empty or may be - * replaced if a duplicate exists. - */ +** returned, since the span will get deleted if it is empty or may be +** replaced if a duplicate exists. +*/ { /* Set the end offset */ if (S->Start == S->Seg->PC) { @@ -237,9 +237,9 @@ Span* CloseSpan (Span* S) S->End = S->Seg->PC; /* Check if we have such a span already. If so use the existing - * one and free the one from the collection. If not, add the one to - * the hash table and return it. - */ + ** one and free the one from the collection. If not, add the one to + ** the hash table and return it. + */ return MergeSpan (S); } } @@ -248,9 +248,9 @@ Span* CloseSpan (Span* S) void OpenSpanList (Collection* Spans) /* Open a list of spans for all existing segments to the given collection of - * spans. The currently active segment will be inserted first with all others - * following. - */ +** spans. The currently active segment will be inserted first with all others +** following. +*/ { unsigned I; @@ -275,8 +275,8 @@ void OpenSpanList (Collection* Spans) void CloseSpanList (Collection* Spans) /* Close a list of spans. This will add new segments to the list, mark the end - * of existing ones, and remove empty spans from the list. - */ +** of existing ones, and remove empty spans from the list. +*/ { unsigned I, J; @@ -385,9 +385,9 @@ void WriteSpans (void) CHECK (S->End > S->Start); /* Write data for the span We will write the size instead of the - * end offset to save some bytes, since most spans are expected - * to be rather small. - */ + ** end offset to save some bytes, since most spans are expected + ** to be rather small. + */ ObjWriteVar (S->Seg->Num); ObjWriteVar (S->Start); ObjWriteVar (S->End - S->Start); @@ -407,7 +407,3 @@ void WriteSpans (void) /* Done writing the spans */ ObjEndSpans (); } - - - - diff --git a/src/ca65/span.h b/src/ca65/span.h index 3ca99ee8f..633592044 100644 --- a/src/ca65/span.h +++ b/src/ca65/span.h @@ -93,15 +93,15 @@ Span* OpenSpan (void); Span* CloseSpan (Span* S); /* Close the given span. Be sure to replace the passed span by the one - * returned, since the span will get deleted if it is empty or may be - * replaced if a duplicate exists. - */ +** returned, since the span will get deleted if it is empty or may be +** replaced if a duplicate exists. +*/ void OpenSpanList (Collection* Spans); /* Open a list of spans for all existing segments to the given collection of - * spans. The currently active segment will be inserted first with all others - * following. - */ +** spans. The currently active segment will be inserted first with all others +** following. +*/ void CloseSpanList (Collection* Spans); /* Close all open spans by setting PC to the current PC for the segment. */ @@ -117,6 +117,3 @@ void WriteSpans (void); /* End of span.h */ #endif - - - diff --git a/src/ca65/spool.c b/src/ca65/spool.c index d30045195..a25702fdf 100644 --- a/src/ca65/spool.c +++ b/src/ca65/spool.c @@ -89,6 +89,3 @@ void InitStrPool (void) /* Insert an empty string. It will have string id 0 */ SP_AddStr (StrPool, ""); } - - - diff --git a/src/ca65/spool.h b/src/ca65/spool.h index 744e8e5bb..e8d115298 100644 --- a/src/ca65/spool.h +++ b/src/ca65/spool.h @@ -114,7 +114,3 @@ void InitStrPool (void); /* End of spool.h */ #endif - - - - diff --git a/src/ca65/struct.c b/src/ca65/struct.c index 1ad5832c0..195f29ba4 100644 --- a/src/ca65/struct.c +++ b/src/ca65/struct.c @@ -102,9 +102,9 @@ static long DoStructInternal (long Offs, unsigned Type) long Size = 0; /* Outside of other structs, we need a name. Inside another struct or - * union, the struct may be anonymous, in which case no new lexical level - * is started. - */ + ** union, the struct may be anonymous, in which case no new lexical level + ** is started. + */ int Anon = (CurTok.Tok != TOK_IDENT); if (!Anon) { /* Enter a new scope, then skip the name */ @@ -137,8 +137,8 @@ static long DoStructInternal (long Offs, unsigned Type) if (CurTok.Tok == TOK_IDENT) { /* Beware: An identifier may also be a macro, in which case we have - * to start over. - */ + ** to start over. + */ Macro* M = FindMacro (&CurTok.SVal); if (M) { MacExpandStart (M); @@ -245,11 +245,11 @@ static long DoStructInternal (long Offs, unsigned Type) } /* If this is not a anon struct, enter a special symbol named ".size" - * into the symbol table of the struct that holds the size of the - * struct. Since the symbol starts with a dot, it cannot be accessed - * by user code. - * Leave the struct scope level. - */ + ** into the symbol table of the struct that holds the size of the + ** struct. Since the symbol starts with a dot, it cannot be accessed + ** by user code. + ** Leave the struct scope level. + */ if (!Anon) { /* Add a symbol */ SymEntry* SizeSym = GetSizeOfScope (CurrentScope); @@ -299,6 +299,3 @@ void DoUnion (void) { DoStructInternal (0, UNION); } - - - diff --git a/src/ca65/struct.h b/src/ca65/struct.h index 9175a498c..1fdaf9d60 100644 --- a/src/ca65/struct.h +++ b/src/ca65/struct.h @@ -68,6 +68,3 @@ void DoUnion (void); /* End of struct.h */ #endif - - - diff --git a/src/ca65/studyexpr.c b/src/ca65/studyexpr.c index 5ff1cc369..366b50ff1 100644 --- a/src/ca65/studyexpr.c +++ b/src/ca65/studyexpr.c @@ -107,8 +107,8 @@ int ED_IsConst (const ExprDesc* D) static int ED_IsValid (const ExprDesc* D) /* Return true if the expression is valid, that is, neither the ERROR nor the - * TOO_COMPLEX flags are set. - */ +** TOO_COMPLEX flags are set. +*/ { return ((D->Flags & (ED_ERROR | ED_TOO_COMPLEX)) == 0); } @@ -164,22 +164,22 @@ static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right) { if (ED->AddrSize == ADDR_SIZE_DEFAULT) { /* If ED is valid, ADDR_SIZE_DEFAULT gets always overridden, otherwise - * it takes precedence over anything else. - */ + ** it takes precedence over anything else. + */ if (ED_IsValid (ED)) { ED->AddrSize = Right->AddrSize; } } else if (Right->AddrSize == ADDR_SIZE_DEFAULT) { /* If Right is valid, ADDR_SIZE_DEFAULT gets always overridden, - * otherwise it takes precedence over anything else. - */ + ** otherwise it takes precedence over anything else. + */ if (!ED_IsValid (Right)) { ED->AddrSize = Right->AddrSize; } } else { /* Neither ED nor Right has a default address size, use the larger of - * the two. - */ + ** the two. + */ if (Right->AddrSize > ED->AddrSize) { ED->AddrSize = Right->AddrSize; } @@ -190,8 +190,8 @@ static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right) static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym) /* Find a symbol reference and return it. Return NULL if the reference does - * not exist. - */ +** not exist. +*/ { unsigned I; ED_SymRef* SymRef; @@ -207,8 +207,8 @@ static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym) static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec) /* Find a section reference and return it. Return NULL if the reference does - * not exist. - */ +** not exist. +*/ { unsigned I; ED_SecRef* SecRef; @@ -224,8 +224,8 @@ static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec) static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym) /* Allocate a new symbol reference and return it. The count of the new - * reference will be set to zero, and the reference itself to Sym. - */ +** reference will be set to zero, and the reference itself to Sym. +*/ { ED_SymRef* SymRef; @@ -251,8 +251,8 @@ static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym) static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec) /* Allocate a new section reference and return it. The count of the new - * reference will be set to zero, and the reference itself to Sec. - */ +** reference will be set to zero, and the reference itself to Sec. +*/ { ED_SecRef* SecRef; @@ -278,8 +278,8 @@ static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec) static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym) /* Get a symbol reference and return it. If the symbol reference does not - * exist, a new one is created and returned. - */ +** exist, a new one is created and returned. +*/ { ED_SymRef* SymRef = ED_FindSymRef (ED, Sym); if (SymRef == 0) { @@ -292,8 +292,8 @@ static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym) static ED_SecRef* ED_GetSecRef (ExprDesc* ED, unsigned Sec) /* Get a section reference and return it. If the section reference does not - * exist, a new one is created and returned. - */ +** exist, a new one is created and returned. +*/ { ED_SecRef* SecRef = ED_FindSecRef (ED, Sec); if (SecRef == 0) { @@ -416,8 +416,8 @@ static void ED_Neg (ExprDesc* D) static void ED_Move (ExprDesc* From, ExprDesc* To) /* Move the data from one ExprDesc to another. Old data is freed, and From - * is prepared to that ED_Done may be called safely. - */ +** is prepared to that ED_Done may be called safely. +*/ { /* Delete old data */ ED_Done (To); @@ -460,12 +460,12 @@ static unsigned char GetConstAddrSize (long Val) static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D) /* Study a binary expression subtree. This is a helper function for StudyExpr - * used for operations that succeed when both operands are known and constant. - * It evaluates the two subtrees and checks if they are constant. If they - * aren't constant, it will set the TOO_COMPLEX flag, and merge references. - * Otherwise the first value is returned in D->Val, the second one in D->Right, - * so the actual operation can be done by the caller. - */ +** used for operations that succeed when both operands are known and constant. +** It evaluates the two subtrees and checks if they are constant. If they +** aren't constant, it will set the TOO_COMPLEX flag, and merge references. +** Otherwise the first value is returned in D->Val, the second one in D->Right, +** so the actual operation can be done by the caller. +*/ { ExprDesc Right; @@ -516,10 +516,10 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D) SymEntry* Sym = Expr->V.Sym; /* If the symbol is defined somewhere, it has an expression associated. - * In this case, just study the expression associated with the symbol, - * but mark the symbol so if we encounter it twice, we know that we have - * a circular reference. - */ + ** In this case, just study the expression associated with the symbol, + ** but mark the symbol so if we encounter it twice, we know that we have + ** a circular reference. + */ if (SymHasExpr (Sym)) { if (SymHasUserMark (Sym)) { @@ -542,9 +542,9 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D) } /* If the symbol has an explicit address size, use it. This may - * lead to range errors later (maybe even in the linker stage), if - * the user lied about the address size, but for now we trust him. - */ + ** lead to range errors later (maybe even in the linker stage), if + ** the user lied about the address size, but for now we trust him. + */ AddrSize = GetSymAddrSize (Sym); if (AddrSize != ADDR_SIZE_DEFAULT) { D->AddrSize = AddrSize; @@ -554,8 +554,8 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D) } else if (SymIsImport (Sym)) { /* The symbol is an import. Track the symbols used and update the - * address size. - */ + ** address size. + */ ED_SymRef* SymRef = ED_GetSymRef (D, Sym); ++SymRef->Count; ED_UpdateAddrSize (D, GetSymAddrSize (Sym)); @@ -566,17 +566,17 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D) SymTable* Parent; /* The symbol is undefined. Track symbol usage but set the "too - * complex" flag, since we cannot evaluate the final result. - */ + ** complex" flag, since we cannot evaluate the final result. + */ ED_SymRef* SymRef = ED_GetSymRef (D, Sym); ++SymRef->Count; ED_Invalidate (D); /* Since the symbol may be a forward, and we may need a statement - * about the address size, check higher lexical levels for a symbol - * with the same name and use its address size if we find such a - * symbol which is defined. - */ + ** about the address size, check higher lexical levels for a symbol + ** with the same name and use its address size if we find such a + ** symbol which is defined. + */ AddrSize = GetSymAddrSize (Sym); Parent = GetSymParentScope (Sym); if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) { @@ -612,8 +612,8 @@ static void StudyULabel (ExprNode* Expr, ExprDesc* D) /* Study an unnamed label expression node */ { /* If we can resolve the label, study the expression associated with it, - * otherwise mark the expression as too complex to evaluate. - */ + ** otherwise mark the expression as too complex to evaluate. + */ if (ULabCanResolve ()) { /* We can resolve the label */ StudyExprInternal (ULabResolve (Expr->V.IVal), D); @@ -707,8 +707,8 @@ static void StudyMul (ExprNode* Expr, ExprDesc* D) StudyExprInternal (Expr->Right, &Right); /* We can handle the operation if at least one of both operands is const - * and the other one is valid. - */ + ** and the other one is valid. + */ if (ED_IsConst (D) && ED_IsValid (&Right)) { /* Multiplicate both, result goes into Right */ @@ -1480,24 +1480,24 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D) } /* If we don't have an address size, assign one if the expression is a - * constant. - */ + ** constant. + */ if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) { D->AddrSize = GetConstAddrSize (D->Val); } /* If the expression is valid, throw away the address size and recalculate - * it using the data we have. This is more exact than the on-the-fly - * calculation done when evaluating the tree, because symbols may have - * been removed from the expression, and the final numeric value is now - * known. - */ + ** it using the data we have. This is more exact than the on-the-fly + ** calculation done when evaluating the tree, because symbols may have + ** been removed from the expression, and the final numeric value is now + ** known. + */ if (ED_IsValid (D)) { unsigned char AddrSize; /* If there are symbols or sections, use the largest one. If the - * expression resolves to a const, use the address size of the value. - */ + ** expression resolves to a const, use the address size of the value. + */ if (D->SymCount > 0 || D->SecCount > 0) { D->AddrSize = ADDR_SIZE_DEFAULT; @@ -1539,6 +1539,3 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D) printf ("%u sections:\n", D->SecCount); #endif } - - - diff --git a/src/ca65/studyexpr.h b/src/ca65/studyexpr.h index 504323e13..389bce5a3 100644 --- a/src/ca65/studyexpr.h +++ b/src/ca65/studyexpr.h @@ -118,7 +118,5 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D); /* End of studyexpr.h */ + #endif - - - diff --git a/src/ca65/symbol.c b/src/ca65/symbol.c index b9e2a6c16..0b02aab45 100644 --- a/src/ca65/symbol.c +++ b/src/ca65/symbol.c @@ -54,12 +54,12 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName) /* Parse a (possibly scoped) identifer. The scope of the name must exist and - * is returned as function result, while the last part (the identifier) which - * may be either a symbol or a scope depending on the context is returned in - * Name. FullName is a string buffer that is used to store the full name of - * the identifier including the scope. It is used internally and may be used - * by the caller for error messages or similar. - */ +** is returned as function result, while the last part (the identifier) which +** may be either a symbol or a scope depending on the context is returned in +** Name. FullName is a string buffer that is used to store the full name of +** the identifier including the scope. It is used internally and may be used +** by the caller for error messages or similar. +*/ { SymTable* Scope; @@ -89,8 +89,8 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName) SB_Append (FullName, Name); /* The scope must exist, so search for it starting with the current - * scope. - */ + ** scope. + */ Scope = SymFindAnyScope (CurrentScope, Name); if (Scope == 0) { /* Scope not found */ @@ -125,8 +125,8 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName) NextTok (); /* If a namespace token follows, we search for another scope, otherwise - * the name is a symbol and we're done. - */ + ** the name is a symbol and we're done. + */ if (CurTok.Tok != TOK_NAMESPACE) { /* Symbol */ return Scope; @@ -153,8 +153,8 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName) SymEntry* ParseScopedSymName (SymFindAction Action) /* Parse a (possibly scoped) symbol name, search for it in the symbol table - * and return the symbol table entry. - */ +** and return the symbol table entry. +*/ { StrBuf ScopeName = STATIC_STRBUF_INITIALIZER; StrBuf Ident = STATIC_STRBUF_INITIALIZER; @@ -171,12 +171,12 @@ SymEntry* ParseScopedSymName (SymFindAction Action) SB_Done (&ScopeName); /* Check if the scope is valid. Errors have already been diagnosed by - * the routine, so just exit. - */ + ** the routine, so just exit. + */ if (Scope) { /* Search for the symbol and return it. If no scope was specified, - * search also in the upper levels. - */ + ** search also in the upper levels. + */ if (NoScope && (Action & SYM_ALLOC_NEW) == 0) { Sym = SymFindAny (Scope, &Ident); } else { @@ -184,9 +184,9 @@ SymEntry* ParseScopedSymName (SymFindAction Action) } } else { /* No scope ==> no symbol. To avoid errors in the calling routine that - * may not expect NULL to be returned if Action contains SYM_ALLOC_NEW, - * create a new symbol. - */ + ** may not expect NULL to be returned if Action contains SYM_ALLOC_NEW, + ** create a new symbol. + */ if (Action & SYM_ALLOC_NEW) { Sym = NewSymEntry (&Ident, SF_NONE); } else { @@ -205,8 +205,8 @@ SymEntry* ParseScopedSymName (SymFindAction Action) SymTable* ParseScopedSymTable (void) /* Parse a (possibly scoped) symbol table (scope) name, search for it in the - * symbol space and return the symbol table struct. - */ +** symbol space and return the symbol table struct. +*/ { StrBuf ScopeName = STATIC_STRBUF_INITIALIZER; StrBuf Name = STATIC_STRBUF_INITIALIZER; @@ -223,9 +223,9 @@ SymTable* ParseScopedSymTable (void) SB_Done (&ScopeName); /* If we got no error, search for the child scope withint the enclosing one. - * Beware: If no explicit parent scope was specified, search in all upper - * levels. - */ + ** Beware: If no explicit parent scope was specified, search in all upper + ** levels. + */ if (Scope) { /* Search for the last scope */ if (NoScope) { @@ -246,8 +246,8 @@ SymTable* ParseScopedSymTable (void) SymEntry* ParseAnySymName (SymFindAction Action) /* Parse a cheap local symbol or a a (possibly scoped) symbol name, search - * for it in the symbol table and return the symbol table entry. - */ +** for it in the symbol table and return the symbol table entry. +*/ { SymEntry* Sym; @@ -262,6 +262,3 @@ SymEntry* ParseAnySymName (SymFindAction Action) /* Return the symbol found */ return Sym; } - - - diff --git a/src/ca65/symbol.h b/src/ca65/symbol.h index 30964f0c0..2bbe87ce7 100644 --- a/src/ca65/symbol.h +++ b/src/ca65/symbol.h @@ -61,33 +61,30 @@ struct StrBuf; struct SymTable* ParseScopedIdent (struct StrBuf* Name, struct StrBuf* FullName); /* Parse a (possibly scoped) identifer. The scope of the name must exist and - * is returned as function result, while the last part (the identifier) which - * may be either a symbol or a scope depending on the context is returned in - * Name. FullName is a string buffer that is used to store the full name of - * the identifier including the scope. It is used internally and may be used - * by the caller for error messages or similar. - */ +** is returned as function result, while the last part (the identifier) which +** may be either a symbol or a scope depending on the context is returned in +** Name. FullName is a string buffer that is used to store the full name of +** the identifier including the scope. It is used internally and may be used +** by the caller for error messages or similar. +*/ struct SymEntry* ParseScopedSymName (SymFindAction Action); /* Parse a (possibly scoped) symbol name, search for it in the symbol table - * and return the symbol table entry. - */ +** and return the symbol table entry. +*/ struct SymTable* ParseScopedSymTable (void); /* Parse a (possibly scoped) symbol table (scope) name, search for it in the - * symbol space and return the symbol table struct. - */ +** symbol space and return the symbol table struct. +*/ struct SymEntry* ParseAnySymName (SymFindAction Action); /* Parse a cheap local symbol or a a (possibly scoped) symbol name, search - * for it in the symbol table and return the symbol table entry. - */ +** for it in the symbol table and return the symbol table entry. +*/ /* End of symbol.h */ #endif - - - diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index 612bc09f2..f1459dca0 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -115,12 +115,12 @@ SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags) int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E) /* Search in the given tree for a name. If we find the symbol, the function - * will return 0 and put the entry pointer into E. If we did not find the - * symbol, and the tree is empty, E is set to NULL. If the tree is not empty, - * E will be set to the last entry, and the result of the function is <0 if - * the entry should be inserted on the left side, and >0 if it should get - * inserted on the right side. - */ +** will return 0 and put the entry pointer into E. If we did not find the +** symbol, and the tree is empty, E is set to NULL. If the tree is not empty, +** E will be set to the last entry, and the result of the function is <0 if +** the entry should be inserted on the left side, and >0 if it should get +** inserted on the right side. +*/ { /* Is there a tree? */ if (T == 0) { @@ -196,8 +196,8 @@ static void SymReplaceExprRefs (SymEntry* S) CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == S); /* We cannot touch the root node, since there are pointers to it. - * Replace it by a literal node. - */ + ** Replace it by a literal node. + */ E->Op = EXPR_LITERAL; E->V.IVal = Val; } @@ -234,8 +234,8 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags return; } /* Delete the current symbol expression, since it will get - * replaced - */ + ** replaced + */ FreeExpr (S->Expr); S->Expr = 0; } @@ -255,17 +255,17 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags S->Expr = Expr; /* In case of a variable symbol, walk over all expressions containing - * this symbol and replace the (sub-)expression by the literal value of - * the tree. Be sure to replace the expression node in place, since there - * may be pointers to it. - */ + ** this symbol and replace the (sub-)expression by the literal value of + ** the tree. Be sure to replace the expression node in place, since there + ** may be pointers to it. + */ if (Flags & SF_VAR) { SymReplaceExprRefs (S); } /* If the symbol is marked as global, export it. Address size is checked - * below. - */ + ** below. + */ if (S->Flags & SF_GLOBAL) { S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT; ReleaseFullLineInfo (&S->DefLines); @@ -326,15 +326,15 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags) } /* If no address size is given, use the address size of the enclosing - * segment. - */ + ** segment. + */ if (AddrSize == ADDR_SIZE_DEFAULT) { AddrSize = GetCurrentSegAddrSize (); } /* If the symbol is marked as import or global, check the address size, - * then do silently remove the global flag. - */ + ** then do silently remove the global flag. + */ if (S->Flags & SF_IMPORT) { if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) { Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S)); @@ -355,9 +355,9 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags) S->AddrSize = AddrSize; /* Mark the position of the import as the position of the definition. - * Please note: In case of multiple .global or .import statements, the line - * infos add up. - */ + ** Please note: In case of multiple .global or .import statements, the line + ** infos add up. + */ GetFullLineInfo (&S->DefLines); } @@ -379,8 +379,8 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags) } /* If the symbol was marked as global before, remove the global flag and - * proceed, but check the address size. - */ + ** proceed, but check the address size. + */ if (S->Flags & SF_GLOBAL) { if (AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); @@ -388,14 +388,14 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags) S->Flags &= ~SF_GLOBAL; /* .GLOBAL remembers line infos in case an .IMPORT follows. We have - * to remove these here. - */ + ** to remove these here. + */ ReleaseFullLineInfo (&S->DefLines); } /* If the symbol was already marked as an export, but wasn't defined - * before, the address sizes in both definitions must match. - */ + ** before, the address sizes in both definitions must match. + */ if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) { if (S->ExportSize != AddrSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); @@ -404,8 +404,8 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags) S->ExportSize = AddrSize; /* If the symbol is already defined, check symbol size against the - * exported size. - */ + ** exported size. + */ if (S->Flags & SF_DEFINED) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* No export size given, use the real size of the symbol */ @@ -429,8 +429,8 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags) void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as a global symbol, that is, as a symbol that is - * either imported or exported. - */ +** either imported or exported. +*/ { if (S->Flags & SF_VAR) { /* Variable symbols cannot be exported or imported */ @@ -439,8 +439,8 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) } /* If the symbol is already marked as import, the address size must match. - * Apart from that, ignore the global declaration. - */ + ** Apart from that, ignore the global declaration. + */ if (S->Flags & SF_IMPORT) { if (AddrSize == ADDR_SIZE_DEFAULT) { /* Use the size of the current segment */ @@ -453,8 +453,8 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) } /* If the symbol is already an export: If it is not defined, the address - * sizes must match. - */ + ** sizes must match. + */ if (S->Flags & SF_EXPORT) { if ((S->Flags & SF_DEFINED) == 0) { /* Symbol is undefined */ @@ -471,9 +471,9 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) } /* If the symbol is already marked as global, the address size must match. - * Use the ExportSize here, since it contains the actual address size - * passed to this function. - */ + ** Use the ExportSize here, since it contains the actual address size + ** passed to this function. + */ if (S->Flags & SF_GLOBAL) { if (AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); @@ -482,10 +482,10 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) } /* If we come here, the symbol was neither declared as export, import or - * global before. Check if it is already defined, in which case it will - * become an export. If it is not defined, mark it as global and remember - * the given address sizes. - */ + ** global before. Check if it is already defined, in which case it will + ** become an export. If it is not defined, mark it as global and remember + ** the given address sizes. + */ if (S->Flags & SF_DEFINED) { /* The symbol is defined, export it */ S->ExportSize = AddrSize; @@ -501,9 +501,9 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) S->Flags |= (SF_EXPORT | Flags); } else { /* Since we don't know if the symbol will get exported or imported, - * remember two different address sizes: One for an import in AddrSize, - * and the other one for an export in ExportSize. - */ + ** remember two different address sizes: One for an import in AddrSize, + ** and the other one for an export in ExportSize. + */ S->AddrSize = AddrSize; if (S->AddrSize == ADDR_SIZE_DEFAULT) { /* Use the size of the current segment */ @@ -513,8 +513,8 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) S->Flags |= (SF_GLOBAL | Flags); /* Remember the current location as location of definition in case - * an .IMPORT follows later. - */ + ** an .IMPORT follows later. + */ GetFullLineInfo (&S->DefLines); } } @@ -523,8 +523,8 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Prio) /* Mark the given symbol as a module constructor/destructor. This will also - * mark the symbol as an export. Initializers may never be zero page symbols. - */ +** mark the symbol as an export. Initializers may never be zero page symbols. +*/ { /* Check the parameters */ #if (CD_TYPE_MIN != 0) @@ -547,9 +547,9 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri } /* If the symbol was already marked as an export or global, check if - * this was done specifiying the same address size. In case of a global - * declaration, silently remove the global flag. - */ + ** this was done specifiying the same address size. In case of a global + ** declaration, silently remove the global flag. + */ if (S->Flags & (SF_EXPORT | SF_GLOBAL)) { if (S->ExportSize != AddrSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); @@ -559,8 +559,8 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri S->ExportSize = AddrSize; /* If the symbol is already defined, check symbol size against the - * exported size. - */ + ** exported size. + */ if (S->Flags & SF_DEFINED) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* Use the real size of the symbol */ @@ -571,8 +571,8 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri } /* If the symbol was already declared as a condes, check if the new - * priority value is the same as the old one. - */ + ** priority value is the same as the old one. + */ if (S->ConDesPrio[Type] != CD_PRIO_NONE) { if (S->ConDesPrio[Type] != Prio) { Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S)); @@ -593,10 +593,10 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize) /* Mark the address size of the given symbol as guessed. The address size - * passed as argument is the one NOT used, because the actual address size - * wasn't known. Example: Zero page addressing was not used because symbol - * is undefined, and absolute addressing was available. - */ +** passed as argument is the one NOT used, because the actual address size +** wasn't known. Example: Zero page addressing was not used because symbol +** is undefined, and absolute addressing was available. +*/ { /* We must have a valid address size passed */ PRECONDITION (AddrSize != ADDR_SIZE_DEFAULT); @@ -619,8 +619,8 @@ void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize) void SymExportFromGlobal (SymEntry* S) /* Called at the end of assembly. Converts a global symbol that is defined - * into an export. - */ +** into an export. +*/ { /* Remove the global flag and make the symbol an export */ S->Flags &= ~SF_GLOBAL; @@ -631,8 +631,8 @@ void SymExportFromGlobal (SymEntry* S) void SymImportFromGlobal (SymEntry* S) /* Called at the end of assembly. Converts a global symbol that is undefined - * into an import. - */ +** into an import. +*/ { /* Remove the global flag and make it an import */ S->Flags &= ~SF_GLOBAL; @@ -643,8 +643,8 @@ void SymImportFromGlobal (SymEntry* S) int SymIsConst (const SymEntry* S, long* Val) /* Return true if the given symbol has a constant value. If Val is not NULL - * and the symbol has a constant value, store it's value there. - */ +** and the symbol has a constant value, store it's value there. +*/ { /* Check for constness */ return (SymHasExpr (S) && IsConstExpr (S->Expr, Val)); @@ -654,16 +654,16 @@ int SymIsConst (const SymEntry* S, long* Val) SymTable* GetSymParentScope (SymEntry* S) /* Get the parent scope of the symbol (not the one it is defined in). Return - * NULL if the symbol is a cheap local, or defined on global level. - */ +** NULL if the symbol is a cheap local, or defined on global level. +*/ { if ((S->Flags & SF_LOCAL) != 0) { /* This is a cheap local symbol */ return 0; } else if (S->Sym.Tab == 0) { /* Symbol not in a table. This may happen if there have been errors - * before. Return NULL in this case to avoid further errors. - */ + ** before. Return NULL in this case to avoid further errors. + */ return 0; } else { /* This is a global symbol */ @@ -684,8 +684,8 @@ struct ExprNode* GetSymExpr (SymEntry* S) const struct ExprNode* SymResolve (const SymEntry* S) /* Helper function for DumpExpr. Resolves a symbol into an expression or return - * NULL. Do not call in other contexts! - */ +** NULL. Do not call in other contexts! +*/ { return SymHasExpr (S)? S->Expr : 0; } @@ -694,8 +694,8 @@ const struct ExprNode* SymResolve (const SymEntry* S) long GetSymVal (SymEntry* S) /* Return the value of a symbol assuming it's constant. FAIL will be called - * in case the symbol is undefined or not constant. - */ +** in case the symbol is undefined or not constant. +*/ { long Val; CHECK (S != 0 && SymHasExpr (S) && IsConstExpr (GetSymExpr (S), &Val)); @@ -724,10 +724,10 @@ unsigned GetSymExportId (const SymEntry* S) unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal) /* Return a set of flags used when writing symbol information into a file. - * If the SYM_CONST bit is set, ConstVal will contain the constant value - * of the symbol. The result does not include the condes count. - * See common/symdefs.h for more information. - */ +** If the SYM_CONST bit is set, ConstVal will contain the constant value +** of the symbol. The result does not include the condes count. +** See common/symdefs.h for more information. +*/ { /* Setup info flags */ unsigned Flags = 0; @@ -744,6 +744,3 @@ unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal) /* Return the result */ return Flags; } - - - diff --git a/src/ca65/symentry.h b/src/ca65/symentry.h index a9b1386e3..5ac8f9c41 100644 --- a/src/ca65/symentry.h +++ b/src/ca65/symentry.h @@ -92,11 +92,11 @@ struct SymEntry { Collection DefLines; /* Line infos for definition */ Collection RefLines; /* Line infos for references */ FilePos* GuessedUse[1]; /* File position where symbol - * address size was guessed, and the - * smallest possible addressing was NOT - * used. Currently only for zero page - * addressing - */ + ** address size was guessed, and the + ** smallest possible addressing was NOT + ** used. Currently only for zero page + ** addressing + */ struct HLLDbgSym* HLLSym; /* Symbol from high level language */ unsigned Flags; /* Symbol flags */ unsigned DebugSymId; /* Debug symbol id */ @@ -130,12 +130,12 @@ SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags); int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E); /* Search in the given tree for a name. If we find the symbol, the function - * will return 0 and put the entry pointer into E. If we did not find the - * symbol, and the tree is empty, E is set to NULL. If the tree is not empty, - * E will be set to the last entry, and the result of the function is <0 if - * the entry should be inserted on the left side, and >0 if it should get - * inserted on the right side. - */ +** will return 0 and put the entry pointer into E. If we did not find the +** symbol, and the tree is empty, E is set to NULL. If the tree is not empty, +** E will be set to the last entry, and the result of the function is <0 if +** the entry should be inserted on the left side, and >0 if it should get +** inserted on the right side. +*/ #if defined(HAVE_INLINE) INLINE void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr) @@ -174,30 +174,30 @@ void SymExport (SymEntry* Sym, unsigned char AddrSize, unsigned Flags); void SymGlobal (SymEntry* Sym, unsigned char AddrSize, unsigned Flags); /* Mark the given symbol as a global symbol, that is, as a symbol that is - * either imported or exported. - */ +** either imported or exported. +*/ void SymConDes (SymEntry* Sym, unsigned char AddrSize, unsigned Type, unsigned Prio); /* Mark the given symbol as a module constructor/destructor. This will also - * mark the symbol as an export. Initializers may never be zero page symbols. - */ +** mark the symbol as an export. Initializers may never be zero page symbols. +*/ void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize); /* Mark the address size of the given symbol as guessed. The address size - * passed as argument is the one NOT used, because the actual address size - * wasn't known. Example: Zero page addressing was not used because symbol - * is undefined, and absolute addressing was available. - */ +** passed as argument is the one NOT used, because the actual address size +** wasn't known. Example: Zero page addressing was not used because symbol +** is undefined, and absolute addressing was available. +*/ void SymExportFromGlobal (SymEntry* S); /* Called at the end of assembly. Converts a global symbol that is defined - * into an export. - */ +** into an export. +*/ void SymImportFromGlobal (SymEntry* S); /* Called at the end of assembly. Converts a global symbol that is undefined - * into an import. - */ +** into an import. +*/ #if defined(HAVE_INLINE) INLINE int SymIsDef (const SymEntry* S) @@ -254,8 +254,8 @@ INLINE int SymIsVar (const SymEntry* S) int SymIsConst (const SymEntry* Sym, long* Val); /* Return true if the given symbol has a constant value. If Val is not NULL - * and the symbol has a constant value, store it's value there. - */ +** and the symbol has a constant value, store it's value there. +*/ #if defined(HAVE_INLINE) INLINE int SymHasExpr (const SymEntry* S) @@ -303,16 +303,16 @@ INLINE int SymHasUserMark (SymEntry* S) struct SymTable* GetSymParentScope (SymEntry* S); /* Get the parent scope of the symbol (not the one it is defined in). Return - * NULL if the symbol is a cheap local, or defined on global level. - */ +** NULL if the symbol is a cheap local, or defined on global level. +*/ struct ExprNode* GetSymExpr (SymEntry* Sym); /* Get the expression for a non-const symbol */ const struct ExprNode* SymResolve (const SymEntry* Sym); /* Helper function for DumpExpr. Resolves a symbol into an expression or return - * NULL. Do not call in other contexts! - */ +** NULL. Do not call in other contexts! +*/ #if defined(HAVE_INLINE) INLINE const StrBuf* GetSymName (const SymEntry* S) @@ -327,8 +327,8 @@ INLINE const StrBuf* GetSymName (const SymEntry* S) #if defined(HAVE_INLINE) INLINE unsigned char GetSymAddrSize (const SymEntry* S) /* Return the address size of the symbol. Beware: This function will just - * return the AddrSize member, it will not look at the expression! - */ +** return the AddrSize member, it will not look at the expression! +*/ { return S->AddrSize; } @@ -338,8 +338,8 @@ INLINE unsigned char GetSymAddrSize (const SymEntry* S) long GetSymVal (SymEntry* Sym); /* Return the value of a symbol assuming it's constant. FAIL will be called - * in case the symbol is undefined or not constant. - */ +** in case the symbol is undefined or not constant. +*/ unsigned GetSymImportId (const SymEntry* Sym); /* Return the import id for the given symbol */ @@ -349,17 +349,13 @@ unsigned GetSymExportId (const SymEntry* Sym); unsigned GetSymInfoFlags (const SymEntry* Sym, long* ConstVal); /* Return a set of flags used when writing symbol information into a file. - * If the SYM_CONST bit is set, ConstVal will contain the constant value - * of the symbol. The result does not include the condes count. - * See common/symdefs.h for more information. - */ +** If the SYM_CONST bit is set, ConstVal will contain the constant value +** of the symbol. The result does not include the condes count. +** See common/symdefs.h for more information. +*/ /* End of symentry.h */ #endif - - - - diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index 2681605fa..7e21dd309 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2012, Ullrich von Bassewitz */ +/* (C) 1998-2014, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -207,8 +207,8 @@ void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type, } /* If we have a current scope, search for the given name and create a - * new one if it doesn't exist. If this is the root scope, just create it. - */ + ** new one if it doesn't exist. If this is the root scope, just create it. + */ if (CurrentScope) { /* Search for the scope, create a new one */ @@ -230,11 +230,11 @@ void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type, CurrentScope->Label = ScopeLabel; /* If this is a scope that allows to emit data into segments, add spans - * for all currently existing segments. Doing this for just a few scope - * types is not really necessary but an optimization, because it does not - * allocate memory for useless data (unhandled types here don't occupy - * space in any segment). - */ + ** for all currently existing segments. Doing this for just a few scope + ** types is not really necessary but an optimization, because it does not + ** allocate memory for useless data (unhandled types here don't occupy + ** space in any segment). + */ if (CurrentScope->Type <= SCOPE_HAS_DATA) { OpenSpanList (&CurrentScope->Spans); } @@ -246,17 +246,17 @@ void SymLeaveLevel (void) /* Leave the current lexical level */ { /* If this is a scope that allows to emit data into segments, close the - * open the spans. - */ + ** open the spans. + */ if (CurrentScope->Type <= SCOPE_HAS_DATA) { CloseSpanList (&CurrentScope->Spans); } /* If we have spans, the first one is the segment that was active, when the - * scope was opened. Set the size of the scope to the number of data bytes - * emitted into this segment. If we have an owner symbol set the size of - * this symbol, too. - */ + ** scope was opened. Set the size of the scope to the number of data bytes + ** emitted into this segment. If we have an owner symbol set the size of + ** this symbol, too. + */ if (CollCount (&CurrentScope->Spans) > 0) { const Span* S = CollAtUnchecked (&CurrentScope->Spans, 0); unsigned long Size = GetSpanSize (S); @@ -304,9 +304,9 @@ SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, SymFindAction Acti SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name) /* Find a scope in the given or any of its parent scopes. The function will - * never create a new symbol, since this can only be done in one specific - * scope. - */ +** never create a new symbol, since this can only be done in one specific +** scope. +*/ { SymTable* Scope; do { @@ -325,9 +325,9 @@ SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name) SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Action) /* Find a cheap local symbol. If Action contains SYM_ALLOC_NEW and the entry is - * not found, create a new one. Return the entry found, or the new entry - * created, or - in case Action is SYM_FIND_EXISTING - return 0. - */ +** not found, create a new one. Return the entry found, or the new entry +** created, or - in case Action is SYM_FIND_EXISTING - return 0. +*/ { SymEntry* S; @@ -375,10 +375,10 @@ SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Acti SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action) /* Find a new symbol table entry in the given table. If Action contains - * SYM_ALLOC_NEW and the entry is not found, create a new one. Return the - * entry found, or the new entry created, or - in case Action is - * SYM_FIND_EXISTING - return 0. - */ +** SYM_ALLOC_NEW and the entry is not found, create a new one. Return the +** entry found, or the new entry created, or - in case Action is +** SYM_FIND_EXISTING - return 0. +*/ { SymEntry* S; @@ -399,9 +399,9 @@ SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action) if (Action & SYM_ALLOC_NEW) { /* Otherwise create a new entry, insert and return it. If the scope is - * already closed, mark the symbol as fixed so it won't be resolved - * by a symbol in the enclosing scopes later. - */ + ** already closed, mark the symbol as fixed so it won't be resolved + ** by a symbol in the enclosing scopes later. + */ SymEntry* N = NewSymEntry (Name, SF_NONE); if (SymTabIsClosed (Scope)) { N->Flags |= SF_FIXED; @@ -427,9 +427,9 @@ SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action) SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name) /* Find a symbol in the given or any of its parent scopes. The function will - * never create a new symbol, since this can only be done in one specific - * scope. - */ +** never create a new symbol, since this can only be done in one specific +** scope. +*/ { /* Generate the name hash */ unsigned Hash = HashBuf (Name); @@ -438,9 +438,9 @@ SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name) SymEntry* Sym; do { /* Search in the current table. Ignore entries flagged with SF_UNUSED, - * because for such symbols there is a real entry in one of the parent - * scopes. - */ + ** because for such symbols there is a real entry in one of the parent + ** scopes. + */ if (SymSearchTree (Scope->Table[Hash % Scope->TableSlots], Name, &Sym) == 0) { if (Sym->Flags & SF_UNUSED) { Sym = 0; @@ -467,15 +467,15 @@ static void SymCheckUndefined (SymEntry* S) /* Handle an undefined symbol */ { /* Undefined symbol. It may be... - * - * - An undefined symbol in a nested lexical level. If the symbol is not - * fixed to this level, search for the symbol in the higher levels and - * make the entry a trampoline entry if we find one. - * - * - If the symbol is not found, it is a real undefined symbol. If the - * AutoImport flag is set, make it an import. If the AutoImport flag is - * not set, it's an error. - */ + ** + ** - An undefined symbol in a nested lexical level. If the symbol is not + ** fixed to this level, search for the symbol in the higher levels and + ** make the entry a trampoline entry if we find one. + ** + ** - If the symbol is not found, it is a real undefined symbol. If the + ** AutoImport flag is set, make it an import. If the AutoImport flag is + ** not set, it's an error. + */ SymEntry* Sym = 0; if ((S->Flags & SF_FIXED) == 0) { SymTable* Tab = GetSymParentScope (S); @@ -483,8 +483,8 @@ static void SymCheckUndefined (SymEntry* S) Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING | SYM_CHECK_ONLY); if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) { /* We've found a symbol in a higher level that is - * either defined in the source, or an import. - */ + ** either defined in the source, or an import. + */ break; } /* No matching symbol found in this level. Look further */ @@ -495,9 +495,9 @@ static void SymCheckUndefined (SymEntry* S) if (Sym) { /* We found the symbol in a higher level. Transfer the flags and - * address size from the local symbol to that in the higher level - * and check for problems. - */ + ** address size from the local symbol to that in the higher level + ** and check for problems. + */ if (S->Flags & SF_EXPORT) { if (Sym->Flags & SF_IMPORT) { /* The symbol is already marked as import */ @@ -505,17 +505,7 @@ static void SymCheckUndefined (SymEntry* S) "Symbol `%s' is already an import", GetString (Sym->Name)); } - if (Sym->Flags & SF_EXPORT) { - /* The symbol is already marked as an export. */ - if (Sym->AddrSize > S->ExportSize) { - /* We're exporting a symbol smaller than it actually is */ - LIWarning (&S->DefLines, 1, - "Symbol `%m%p' is %s but exported %s", - GetSymName (Sym), - AddrSizeToStr (Sym->AddrSize), - AddrSizeToStr (S->ExportSize)); - } - } else { + if ((Sym->Flags & SF_EXPORT) == 0) { /* Mark the symbol as an export */ Sym->Flags |= SF_EXPORT; Sym->ExportSize = S->ExportSize; @@ -525,7 +515,7 @@ static void SymCheckUndefined (SymEntry* S) } if (Sym->AddrSize > Sym->ExportSize) { /* We're exporting a symbol smaller than it actually is */ - LIWarning (&S->DefLines, 1, + LIWarning (&Sym->DefLines, 1, "Symbol `%m%p' is %s but exported %s", GetSymName (Sym), AddrSizeToStr (Sym->AddrSize), @@ -584,13 +574,13 @@ void SymCheck (void) } /* First pass: Walk through all symbols, checking for undefined's and - * changing them to trampoline symbols or make them imports. - */ + ** changing them to trampoline symbols or make them imports. + */ S = SymList; while (S) { /* If the symbol is marked as global, mark it as export, if it is - * already defined, otherwise mark it as import. - */ + ** already defined, otherwise mark it as import. + */ if (S->Flags & SF_GLOBAL) { if (S->Flags & SF_DEFINED) { SymExportFromGlobal (S); @@ -610,10 +600,10 @@ void SymCheck (void) } /* Second pass: Walk again through the symbols. Count exports and imports - * and set address sizes where this has not happened before. Ignore - * undefined's, since we handled them in the last pass, and ignore unused - * symbols, since we handled them in the last pass, too. - */ + ** and set address sizes where this has not happened before. Ignore + ** undefined's, since we handled them in the last pass, and ignore unused + ** symbols, since we handled them in the last pass, too. + */ S = SymList; while (S) { if ((S->Flags & SF_UNUSED) == 0 && @@ -649,8 +639,8 @@ void SymCheck (void) } /* If the symbol is defined but has an unknown address size, - * recalculate it. - */ + ** recalculate it. + */ if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) { ExprDesc ED; ED_Init (&ED); @@ -673,9 +663,9 @@ void SymCheck (void) } /* If the address size of the symbol was guessed, check the guess - * against the actual address size and print a warning if the two - * differ. - */ + ** against the actual address size and print a warning if the two + ** differ. + */ if (S->AddrSize != ADDR_SIZE_DEFAULT) { /* Do we have data for this address size? */ if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) { @@ -735,10 +725,10 @@ void WriteImports (void) ObjWriteVar (ImportCount); /* Walk throught list and write all valid imports to the file. An import - * is considered valid, if it is either referenced, or the forced bit is - * set. Otherwise, the import is ignored (no need to link in something - * that isn't used). - */ + ** is considered valid, if it is either referenced, or the forced bit is + ** set. Otherwise, the import is ignored (no need to link in something + ** that isn't used). + */ S = SymList; while (S) { if ((S->Flags & (SF_UNUSED | SF_IMPORT)) == SF_IMPORT && @@ -780,8 +770,8 @@ void WriteExports (void) unsigned SymFlags = GetSymInfoFlags (S, &ConstVal); /* Check if this symbol has a size. If so, remember it in the - * flags. - */ + ** flags. + */ long Size; SymEntry* SizeSym = FindSizeOfSymbol (S); if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) { @@ -865,8 +855,8 @@ void WriteDbgSyms (void) ObjWriteVar (Count); /* Walk through list and write all symbols to the file. Ignore size - * symbols. - */ + ** symbols. + */ S = SymList; while (S) { if (IsDbgSym (S)) { @@ -876,8 +866,8 @@ void WriteDbgSyms (void) unsigned SymFlags = GetSymInfoFlags (S, &ConstVal); /* Check if this symbol has a size. If so, remember it in the - * flags. - */ + ** flags. + */ long Size; SymEntry* SizeSym = FindSizeOfSymbol (S); if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) { @@ -891,8 +881,8 @@ void WriteDbgSyms (void) ObjWrite8 (S->AddrSize); /* Write the id of the parent. For normal symbols, this is a - * scope (symbol table), for cheap locals, it's a symbol. - */ + ** scope (symbol table), for cheap locals, it's a symbol. + */ if (SYM_IS_STD (SymFlags)) { ObjWriteVar (S->Sym.Tab->Id); } else { @@ -969,8 +959,8 @@ void WriteScopes (void) unsigned Flags = 0; /* Check if this scope has a size. If so, remember it in the - * flags. - */ + ** flags. + */ long Size; SymEntry* SizeSym = FindSizeOfScope (S); if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) { @@ -1031,6 +1021,3 @@ void WriteScopes (void) /* Done writing the scopes */ ObjEndScopes (); } - - - diff --git a/src/ca65/symtab.h b/src/ca65/symtab.h index e7f7384d0..7e7a9009c 100644 --- a/src/ca65/symtab.h +++ b/src/ca65/symtab.h @@ -112,28 +112,28 @@ SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, SymFindAction Acti SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name); /* Find a scope in the given or any of its parent scopes. The function will - * never create a new symbol, since this can only be done in one specific - * scope. - */ +** never create a new symbol, since this can only be done in one specific +** scope. +*/ SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Action); /* Find a cheap local symbol. If Action contains SYM_ALLOC_NEW and the entry is - * not found, create a new one. Return the entry found, or the new entry - * created, or - in case Action is SYM_FIND_EXISTING - return 0. - */ +** not found, create a new one. Return the entry found, or the new entry +** created, or - in case Action is SYM_FIND_EXISTING - return 0. +*/ SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action); /* Find a new symbol table entry in the given table. If Action contains - * SYM_ALLOC_NEW and the entry is not found, create a new one. Return the - * entry found, or the new entry created, or - in case Action is - * SYM_FIND_EXISTING - return 0. - */ +** SYM_ALLOC_NEW and the entry is not found, create a new one. Return the +** entry found, or the new entry created, or - in case Action is +** SYM_FIND_EXISTING - return 0. +*/ SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name); /* Find a symbol in the given or any of its parent scopes. The function will - * never create a new symbol, since this can only be done in one specific - * scope. - */ +** never create a new symbol, since this can only be done in one specific +** scope. +*/ #if defined(HAVE_INLINE) INLINE unsigned char GetSymTabType (const SymTable* S) @@ -178,6 +178,3 @@ void WriteScopes (void); /* End of symtab.h */ #endif - - - diff --git a/src/ca65/token.c b/src/ca65/token.c index b2d103dde..db2a63fc7 100644 --- a/src/ca65/token.c +++ b/src/ca65/token.c @@ -62,8 +62,8 @@ int TokHasIVal (token_t Tok) void CopyToken (Token* Dst, const Token* Src) /* Copy a token from Src to Dst. The current value of Dst.SVal is free'd, - * so Dst must be initialized. - */ +** so Dst must be initialized. +*/ { /* Copy the fields */ Dst->Tok = Src->Tok; @@ -72,6 +72,3 @@ void CopyToken (Token* Dst, const Token* Src) SB_Copy (&Dst->SVal, &Src->SVal); Dst->Pos = Src->Pos; } - - - diff --git a/src/ca65/token.h b/src/ca65/token.h index 5214771fd..803b12785 100644 --- a/src/ca65/token.h +++ b/src/ca65/token.h @@ -244,7 +244,6 @@ typedef enum token_t { TOK_STRING, TOK_STRLEN, TOK_STRUCT, - TOK_SUNPLUS, TOK_TAG, TOK_TCOUNT, TOK_TIME, @@ -307,14 +306,11 @@ INLINE int TokIsSep (enum token_t T) void CopyToken (Token* Dst, const Token* Src); /* Copy a token. The current value of Dst.SVal is free'd, so Dst must be - * initialized. - */ +** initialized. +*/ /* End of token.h */ #endif - - - diff --git a/src/ca65/toklist.c b/src/ca65/toklist.c index e6adf3d96..16efd24df 100644 --- a/src/ca65/toklist.c +++ b/src/ca65/toklist.c @@ -180,9 +180,9 @@ void FreeTokList (TokList* List) enum token_t GetTokListTerm (enum token_t Term) /* Determine if the following token list is enclosed in curly braces. This is - * the case if the next token is the opening brace. If so, skip it and return - * a closing brace, otherwise return Term. - */ +** the case if the next token is the opening brace. If so, skip it and return +** a closing brace, otherwise return Term. +*/ { if (CurTok.Tok == TOK_LCURLY) { NextTok (); @@ -216,16 +216,16 @@ void AddCurTok (TokList* List) static int ReplayTokList (void* List) /* Function that gets the next token from a token list and sets it. This - * function may be used together with the PushInput function from the istack - * module. - */ +** function may be used together with the PushInput function from the istack +** module. +*/ { /* Cast the generic pointer to an actual list */ TokList* L = List; /* If there are no more tokens, decrement the repeat counter. If it goes - * zero, delete the list and remove the function from the stack. - */ + ** zero, delete the list and remove the function from the stack. + */ if (L->Last == 0) { if (++L->RepCount >= L->RepMax) { /* Done with this list */ @@ -249,8 +249,8 @@ static int ReplayTokList (void* List) L->LI = StartLine (&CurTok.Pos, LI_TYPE_ASM, PushCounter); /* If a check function is defined, call it, so it may look at the token - * just set and changed it as apropriate. - */ + ** just set and changed it as apropriate. + */ if (L->Check) { L->Check (L); } @@ -266,9 +266,9 @@ static int ReplayTokList (void* List) void PushTokList (TokList* List, const char* Desc) /* Push a token list to be used as input for InputFromStack. This includes - * several initializations needed in the token list structure, so don't use - * PushInput directly. - */ +** several initializations needed in the token list structure, so don't use +** PushInput directly. +*/ { /* If the list is empty, just delete it and bail out */ if (List->Count == 0) { @@ -283,6 +283,3 @@ void PushTokList (TokList* List, const char* Desc) ++PushCounter; PushInput (ReplayTokList, List, Desc); } - - - diff --git a/src/ca65/toklist.h b/src/ca65/toklist.h index 6e7a414cc..6ee8b5f5f 100644 --- a/src/ca65/toklist.h +++ b/src/ca65/toklist.h @@ -111,25 +111,21 @@ void FreeTokList (TokList* T); token_t GetTokListTerm (token_t Term); /* Determine if the following token list is enclosed in curly braces. This is - * the case if the next token is the opening brace. If so, skip it and return - * a closing brace, otherwise return Term. - */ +** the case if the next token is the opening brace. If so, skip it and return +** a closing brace, otherwise return Term. +*/ void AddCurTok (TokList* T); /* Add the current token to the token list */ void PushTokList (TokList* List, const char* Desc); /* Push a token list to be used as input for InputFromStack. This includes - * several initializations needed in the token list structure, so don't use - * PushInput directly. - */ +** several initializations needed in the token list structure, so don't use +** PushInput directly. +*/ /* End of toklist.h */ #endif - - - - diff --git a/src/ca65/ulabel.c b/src/ca65/ulabel.c index 140dad3d9..9712f4942 100644 --- a/src/ca65/ulabel.c +++ b/src/ca65/ulabel.c @@ -75,8 +75,8 @@ static unsigned ULabDefCount = 0; /* Number of defined labels */ static ULabel* NewULabel (ExprNode* Val) /* Create a new ULabel and insert it into the collection. The created label - * structure is returned. - */ +** structure is returned. +*/ { /* Allocate memory for the ULabel structure */ ULabel* L = xmalloc (sizeof (ULabel)); @@ -98,11 +98,11 @@ static ULabel* NewULabel (ExprNode* Val) ExprNode* ULabRef (int Which) /* Get an unnamed label. If Which is negative, it is a backreference (a - * reference to an already defined label), and the function will return a - * segment relative expression. If Which is positive, it is a forward ref, - * and the function will return a expression node for an unnamed label that - * must be resolved later. - */ +** reference to an already defined label), and the function will return a +** segment relative expression. If Which is positive, it is a forward ref, +** and the function will return a expression node for an unnamed label that +** must be resolved later. +*/ { int Index; ULabel* L; @@ -139,8 +139,8 @@ ExprNode* ULabRef (int Which) ++L->Ref; /* If the label is already defined, return its value, otherwise return - * just a reference. - */ + ** just a reference. + */ if (L->Val) { return CloneExpr (L->Val); } else { @@ -155,9 +155,9 @@ void ULabDef (void) { if (ULabDefCount < CollCount (&ULabList)) { /* We did already have a forward reference to this label, so has - * already been generated, but doesn't have a value. Use the current - * PC for the label value. - */ + ** already been generated, but doesn't have a value. Use the current + ** PC for the label value. + */ ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount); CHECK (L->Val == 0); L->Val = GenCurrentPC (); @@ -185,9 +185,9 @@ int ULabCanResolve (void) ExprNode* ULabResolve (unsigned Index) /* Return a valid expression for the unnamed label with the given index. This - * is used to resolve unnamed labels when assembly is done, so it is an error - * if a label is still undefined in this phase. - */ +** is used to resolve unnamed labels when assembly is done, so it is an error +** if a label is still undefined in this phase. +*/ { /* Get the label and check that it is defined */ ULabel* L = CollAt (&ULabList, Index); @@ -201,8 +201,8 @@ ExprNode* ULabResolve (unsigned Index) void ULabDone (void) /* Run through all unnamed labels, check for anomalies and errors and do - * necessary cleanups. - */ +** necessary cleanups. +*/ { /* Check if there are undefined labels */ unsigned I = ULabDefCount; @@ -213,8 +213,8 @@ void ULabDone (void) } /* Walk over all labels and emit a warning if any unreferenced ones - * are found. Remove line infos because they're no longer needed. - */ + ** are found. Remove line infos because they're no longer needed. + */ for (I = 0; I < CollCount (&ULabList); ++I) { ULabel* L = CollAtUnchecked (&ULabList, I); if (L->Ref == 0) { @@ -223,7 +223,3 @@ void ULabDone (void) ReleaseFullLineInfo (&L->LineInfos); } } - - - - diff --git a/src/ca65/ulabel.h b/src/ca65/ulabel.h index c7c172918..67ea30862 100644 --- a/src/ca65/ulabel.h +++ b/src/ca65/ulabel.h @@ -46,11 +46,11 @@ ExprNode* ULabRef (int Which); /* Get an unnamed label. If Which is negative, it is a backreference (a - * reference to an already defined label), and the function will return a - * segment relative expression. If Which is positive, it is a forward ref, - * and the function will return a expression node for an unnamed label that - * must be resolved later. - */ +** reference to an already defined label), and the function will return a +** segment relative expression. If Which is positive, it is a forward ref, +** and the function will return a expression node for an unnamed label that +** must be resolved later. +*/ void ULabDef (void); /* Define an unnamed label at the current PC */ @@ -60,20 +60,17 @@ int ULabCanResolve (void); ExprNode* ULabResolve (unsigned Index); /* Return a valid expression for the unnamed label with the given index. This - * is used to resolve unnamed labels when assembly is done, so it is an error - * if a label is still undefined in this phase. - */ +** is used to resolve unnamed labels when assembly is done, so it is an error +** if a label is still undefined in this phase. +*/ void ULabDone (void); /* Run through all unnamed labels, check for anomalies and errors and do - * necessary cleanups. - */ +** necessary cleanups. +*/ /* End of ulabel.h */ #endif - - - diff --git a/src/cc65.vcxproj b/src/cc65.vcxproj index 888fa53b7..1c1f993fe 100644 --- a/src/cc65.vcxproj +++ b/src/cc65.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -18,10 +18,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -46,7 +48,7 @@ <ClCompile> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <WarningLevel>Level3</WarningLevel> <TreatWarningAsError>true</TreatWarningAsError> @@ -62,7 +64,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> diff --git a/src/cc65/anonname.c b/src/cc65/anonname.c index 2c33b3f17..d02253d82 100644 --- a/src/cc65/anonname.c +++ b/src/cc65/anonname.c @@ -63,8 +63,8 @@ static const char AnonTag[] = "$anon"; char* AnonName (char* Buf, const char* Spec) /* Get a name for an anonymous variable or type. The given buffer is expected - * to be IDENTSIZE characters long. A pointer to the buffer is returned. - */ +** to be IDENTSIZE characters long. A pointer to the buffer is returned. +*/ { static unsigned ACount = 0; xsprintf (Buf, IDENTSIZE, "%s-%s-%04X", AnonTag, Spec, ++ACount); @@ -78,6 +78,3 @@ int IsAnonName (const char* Name) { return (strncmp (Name, AnonTag, sizeof (AnonTag) - 1) == 0); } - - - diff --git a/src/cc65/anonname.h b/src/cc65/anonname.h index 43292505e..dfaa1bdaa 100644 --- a/src/cc65/anonname.h +++ b/src/cc65/anonname.h @@ -46,8 +46,8 @@ char* AnonName (char* Buf, const char* Spec); /* Get a name for an anonymous variable or type. The given buffer is expected - * to be IDENTSIZE characters long. A pointer to the buffer is returned. - */ +** to be IDENTSIZE characters long. A pointer to the buffer is returned. +*/ int IsAnonName (const char* Name); /* Check if the given symbol name is that of an anonymous symbol */ @@ -55,7 +55,5 @@ int IsAnonName (const char* Name); /* End of anonname.h */ + #endif - - - diff --git a/src/cc65/asmcode.c b/src/cc65/asmcode.c index ec0a8791e..ee50d6faa 100644 --- a/src/cc65/asmcode.c +++ b/src/cc65/asmcode.c @@ -86,8 +86,8 @@ void RemoveCode (const CodeMark* M) void MoveCode (const CodeMark* Start, const CodeMark* End, const CodeMark* Target) /* Move the code between Start (inclusive) and End (exclusive) to - * (before) Target. The code marks aren't updated. - */ +** (before) Target. The code marks aren't updated. +*/ { CS_MoveEntries (CS->Code, Start->Pos, End->Pos - Start->Pos, Target->Pos); } @@ -130,6 +130,3 @@ void WriteAsmOutput (void) Entry = Entry->NextSym; } } - - - diff --git a/src/cc65/asmcode.h b/src/cc65/asmcode.h index 5d70ae381..ad079d0c3 100644 --- a/src/cc65/asmcode.h +++ b/src/cc65/asmcode.h @@ -76,8 +76,8 @@ void RemoveCode (const CodeMark* M); void MoveCode (const CodeMark* Start, const CodeMark* End, const CodeMark* Target); /* Move the code between Start (inclusive) and End (exclusive) to - * (before) Target. The code marks aren't updated. - */ +** (before) Target. The code marks aren't updated. +*/ int CodeRangeIsEmpty (const CodeMark* Start, const CodeMark* End); /* Return true if the given code range is empty (no code between Start and End) */ @@ -88,8 +88,5 @@ void WriteAsmOutput (void); /* End of asmcode.h */ + #endif - - - - diff --git a/src/cc65/asmlabel.c b/src/cc65/asmlabel.c index 46330c303..09aee3b92 100644 --- a/src/cc65/asmlabel.c +++ b/src/cc65/asmlabel.c @@ -70,9 +70,9 @@ unsigned GetLocalLabel (void) const char* LocalLabelName (unsigned L) /* Make a label name from the given label number. The label name will be - * created in static storage and overwritten when calling the function - * again. - */ +** created in static storage and overwritten when calling the function +** again. +*/ { static char Buf[64]; sprintf (Buf, "L%04X", L); @@ -98,7 +98,3 @@ int IsLocalLabelName (const char* Name) /* Local label name */ return 1; } - - - - diff --git a/src/cc65/asmlabel.h b/src/cc65/asmlabel.h index 44235c9d9..4a76643a5 100644 --- a/src/cc65/asmlabel.h +++ b/src/cc65/asmlabel.h @@ -49,9 +49,9 @@ unsigned GetLocalLabel (void); const char* LocalLabelName (unsigned L); /* Make a label name from the given label number. The label name will be - * created in static storage and overwritten when calling the function - * again. - */ +** created in static storage and overwritten when calling the function +** again. +*/ int IsLocalLabelName (const char* Name); /* Return true if Name is the name of a local label */ @@ -59,7 +59,5 @@ int IsLocalLabelName (const char* Name); /* End of asmlabel.h */ + #endif - - - diff --git a/src/cc65/asmstmt.c b/src/cc65/asmstmt.c index ce2660e54..59c1332ff 100644 --- a/src/cc65/asmstmt.c +++ b/src/cc65/asmstmt.c @@ -69,8 +69,8 @@ static void AsmRangeError (unsigned Arg) static void AsmErrorSkip (void) /* Called in case of an error, skips tokens until the closing paren or a - * semicolon is reached. - */ +** semicolon is reached. +*/ { static const token_t TokenList[] = { TOK_RPAREN, TOK_SEMI }; SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0])); @@ -80,8 +80,8 @@ static void AsmErrorSkip (void) static SymEntry* AsmGetSym (unsigned Arg, unsigned Type) /* Find the symbol with the name currently in NextTok. The symbol must be of - * the given type. On errors, NULL is returned. - */ +** the given type. On errors, NULL is returned. +*/ { SymEntry* Sym; @@ -257,9 +257,9 @@ static void ParseLVarArg (StrBuf* T, unsigned Arg) } /* The symbol may be a parameter to a variadic function. In this case, we - * don't have a fixed stack offset, so check it and bail out with an error - * if this is the case. - */ + ** don't have a fixed stack offset, so check it and bail out with an error + ** if this is the case. + */ if ((Sym->Flags & SC_PARAM) == SC_PARAM && F_IsVariadic (CurrentFunc)) { Error ("Argument %u has no fixed stack offset", Arg); AsmErrorSkip (); @@ -352,16 +352,16 @@ static void ParseAsm (void) NextToken (); /* Parse the statement. It may contain several lines and one or more - * of the following place holders: - * %b - Numerical 8 bit value - * %w - Numerical 16 bit value - * %l - Numerical 32 bit value - * %v - Assembler name of a (global) variable - * %o - Stack offset of a (local) variable - * %g - Assembler name of a C label - * %s - Any argument converted to a string (almost) - * %% - The % sign - */ + ** of the following place holders: + ** %b - Numerical 8 bit value + ** %w - Numerical 16 bit value + ** %l - Numerical 32 bit value + ** %v - Assembler name of a (global) variable + ** %o - Stack offset of a (local) variable + ** %g - Assembler name of a C label + ** %s - Any argument converted to a string (almost) + ** %% - The % sign + */ Arg = 0; while ((C = SB_Get (&S)) != '\0') { @@ -415,9 +415,9 @@ Done: void AsmStatement (void) /* This function parses ASM statements. The syntax of the ASM directive - * looks like the one defined for C++ (C has no ASM directive), that is, - * a string literal in parenthesis. - */ +** looks like the one defined for C++ (C has no ASM directive), that is, +** a string literal in parenthesis. +*/ { /* Skip the ASM */ NextToken (); @@ -434,8 +434,8 @@ void AsmStatement (void) Error ("String literal expected"); /* Try some smart error recovery: Skip tokens until we reach the - * enclosing paren, or a semicolon. - */ + ** enclosing paren, or a semicolon. + */ AsmErrorSkip (); } else { @@ -447,6 +447,3 @@ void AsmStatement (void) /* Closing paren needed */ ConsumeRParen (); } - - - diff --git a/src/cc65/asmstmt.h b/src/cc65/asmstmt.h index e3a6a0433..2884a3893 100644 --- a/src/cc65/asmstmt.h +++ b/src/cc65/asmstmt.h @@ -46,15 +46,12 @@ void AsmStatement (void); /* This function parses ASM statements. The syntax of the ASM directive - * looks like the one defined for C++ (C has no ASM directive), that is, - * a string literal in parenthesis. - */ +** looks like the one defined for C++ (C has no ASM directive), that is, +** a string literal in parenthesis. +*/ /* End of asmstmt.h */ #endif - - - diff --git a/src/cc65/assignment.c b/src/cc65/assignment.c index 81a189f36..f0607ac58 100644 --- a/src/cc65/assignment.c +++ b/src/cc65/assignment.c @@ -75,18 +75,18 @@ void Assignment (ExprDesc* Expr) NextToken (); /* cc65 does not have full support for handling structs by value. Since - * assigning structs is one of the more useful operations from this - * family, allow it here. - */ + ** assigning structs is one of the more useful operations from this + ** family, allow it here. + */ if (IsClassStruct (ltype)) { /* Get the size of the left hand side. */ unsigned Size = SizeOf (ltype); /* If the size is that of a basic type (char, int, long), we will copy - * the struct using the primary register, otherwise we use memcpy. In - * the former case, push the address only if really needed. - */ + ** the struct using the primary register, otherwise we use memcpy. In + ** the former case, push the address only if really needed. + */ int UseReg = 1; Type* stype; switch (Size) { @@ -143,10 +143,10 @@ void Assignment (ExprDesc* Expr) } else { /* We have an rvalue. This can only happen if a function returns - * a struct, since there is no other way to generate an expression - * that as a struct as an rvalue result. We allow only 1, 2, and 4 - * byte sized structs and do direct assignment. - */ + ** a struct, since there is no other way to generate an expression + ** that has a struct as an rvalue result. We allow only 1, 2, and 4 + ** byte sized structs, and do direct assignment. + */ if (UseReg) { /* Do the store */ Store (Expr, stype); @@ -168,8 +168,8 @@ void Assignment (ExprDesc* Expr) unsigned Flags; /* If the bit-field fits within one byte, do the following operations - * with bytes. - */ + ** with bytes. + */ if (Expr->BitOffs / CHAR_BITS == (Expr->BitOffs + Expr->BitWidth - 1) / CHAR_BITS) { Expr->Type = type_uchar; } @@ -197,14 +197,14 @@ void Assignment (ExprDesc* Expr) MarkedExprWithCheck (hie1, &Expr2); /* Do type conversion if necessary. Beware: Do not use char type - * here! - */ + ** here! + */ TypeConversion (&Expr2, ltype); /* Special treatment if the value is constant. */ /* Beware: Expr2 may contain side effects, so there must not be - * code generated for Expr2. - */ + ** code generated for Expr2. + */ if (ED_IsConstAbsInt (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { /* Get the value and apply the mask */ @@ -214,8 +214,8 @@ void Assignment (ExprDesc* Expr) RemoveCode (&PushPos); /* If the value is equal to the mask now, all bits are one, and we - * can remove the mask operation from above. - */ + ** can remove the mask operation from above. + */ if (Val == Mask) { RemoveCode (&AndPos); } @@ -266,6 +266,3 @@ void Assignment (ExprDesc* Expr) /* Value is still in primary and not an lvalue */ ED_MakeRValExpr (Expr); } - - - diff --git a/src/cc65/assignment.h b/src/cc65/assignment.h index 6273724ca..278c5ef72 100644 --- a/src/cc65/assignment.h +++ b/src/cc65/assignment.h @@ -55,7 +55,5 @@ void Assignment (ExprDesc* lval); /* End of assignment.h */ + #endif - - - diff --git a/src/cc65/casenode.c b/src/cc65/casenode.c index 0e1b37305..f5e751f08 100644 --- a/src/cc65/casenode.c +++ b/src/cc65/casenode.c @@ -94,10 +94,10 @@ void FreeCaseNodeColl (Collection* Nodes) int SearchCaseNode (const Collection* Nodes, unsigned char Key, int* Index) /* Search for a node in the given collection. If the node has been found, - * set Index to the index of the node and return true. If the node was not - * found, set Index the the insertion position of the node and return - * false. - */ +** set Index to the index of the node and return true. If the node was not +** found, set Index the the insertion position of the node and return +** false. +*/ { /* Do a binary search */ int First = 0; @@ -134,8 +134,8 @@ int SearchCaseNode (const Collection* Nodes, unsigned char Key, int* Index) unsigned InsertCaseValue (Collection* Nodes, unsigned long Val, unsigned Depth) /* Insert a new case value into a CaseNode tree with the given depth. Return - * the code label for the value. - */ +** the code label for the value. +*/ { CaseNode* N = 0; unsigned CaseLabel = GetLocalLabel (); /* Code label */ @@ -155,8 +155,8 @@ unsigned InsertCaseValue (Collection* Nodes, unsigned long Val, unsigned Depth) CollInsert (Nodes, N, Index); /* If this is not the last round, create the collection for - * the subnodes, otherwise get a label for the code. - */ + ** the subnodes, otherwise get a label for the code. + */ if (Depth > 0) { N->Nodes = NewCollection (); } else { @@ -168,8 +168,8 @@ unsigned InsertCaseValue (Collection* Nodes, unsigned long Val, unsigned Depth) N = CollAt (Nodes, Index); /* If this is the last round and we found a node, we have a - * duplicate case label in a switch. - */ + ** duplicate case label in a switch. + */ if (Depth == 0) { Error ("Duplicate case label"); } @@ -182,6 +182,3 @@ unsigned InsertCaseValue (Collection* Nodes, unsigned long Val, unsigned Depth) /* Return the label of the node we found/created */ return CaseLabel; } - - - diff --git a/src/cc65/casenode.h b/src/cc65/casenode.h index aa1de2efa..aef546f19 100644 --- a/src/cc65/casenode.h +++ b/src/cc65/casenode.h @@ -115,20 +115,18 @@ void FreeCaseNodeColl (Collection* Nodes); int SearchCaseNode (const Collection* Nodes, unsigned char Key, int* Index); /* Search for a node in the given collection. If the node has been found, - * set Index to the index of the node and return true. If the node was not - * found, set Index the the insertion position of the node and return - * false. - */ +** set Index to the index of the node and return true. If the node was not +** found, set Index the the insertion position of the node and return +** false. +*/ unsigned InsertCaseValue (Collection* Nodes, unsigned long Val, unsigned Depth); /* Insert a new case value into a CaseNode tree with the given depth. Return - * the code label for the value. - */ +** the code label for the value. +*/ /* End of casenode.h */ + #endif - - - diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c index 21eef8fe5..729248e95 100644 --- a/src/cc65/codeent.c +++ b/src/cc65/codeent.c @@ -96,8 +96,8 @@ static char* GetArgCopy (const char* Arg) static int NumArg (const char* Arg, unsigned long* Num) /* If the given argument is numerical, convert it and return true. Otherwise - * set Num to zero and return false. - */ +** set Num to zero and return false. +*/ { char* End; unsigned long Val; @@ -113,8 +113,8 @@ static int NumArg (const char* Arg, unsigned long* Num) } /* Convert the value. strtol is not exactly what we want here, but it's - * cheap and may be replaced by something fancier later. - */ + ** cheap and may be replaced by something fancier later. + */ Val = strtoul (Arg, &End, Base); /* Check if the conversion was successful */ @@ -141,16 +141,16 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D) const ZPInfo* Info; /* If this is a subroutine call, or a jump to an external function, - * lookup the information about this function and use it. The jump itself - * does not change any registers, so we don't need to use the data from D. - */ + ** lookup the information about this function and use it. The jump itself + ** does not change any registers, so we don't need to use the data from D. + */ if ((E->Info & (OF_UBRA | OF_CALL)) != 0 && E->JumpTo == 0) { /* A subroutine call or jump to external symbol (function exit) */ GetFuncInfo (E->Arg, &E->Use, &E->Chg); } else { /* Some other instruction. Use the values from the opcode description - * plus addressing mode info. - */ + ** plus addressing mode info. + */ E->Use = D->Use | GetAMUseInfo (E->AM); E->Chg = D->Chg; @@ -218,11 +218,11 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D) const char* MakeHexArg (unsigned Num) /* Convert Num into a string in the form $XY, suitable for passing it as an - * argument to NewCodeEntry, and return a pointer to the string. - * BEWARE: The function returns a pointer to a static buffer, so the value is - * gone if you call it twice (and apart from that it's not thread and signal - * safe). - */ +** argument to NewCodeEntry, and return a pointer to the string. +** BEWARE: The function returns a pointer to a static buffer, so the value is +** gone if you call it twice (and apart from that it's not thread and signal +** safe). +*/ { static char Buf[16]; xsprintf (Buf, sizeof (Buf), "$%02X", (unsigned char) Num); @@ -288,8 +288,8 @@ void FreeCodeEntry (CodeEntry* E) void CE_ReplaceOPC (CodeEntry* E, opc_t OPC) /* Replace the opcode of the instruction. This will also replace related info, - * Size, Use and Chg, but it will NOT update any arguments or labels. - */ +** Size, Use and Chg, but it will NOT update any arguments or labels. +*/ { /* Get the opcode descriptor */ const OPCDesc* D = GetOPCDesc (OPC); @@ -325,9 +325,9 @@ void CE_AttachLabel (CodeEntry* E, CodeLabel* L) void CE_ClearJumpTo (CodeEntry* E) /* Clear the JumpTo entry and the argument (which contained the name of the - * label). Note: The function will not clear the backpointer from the label, - * so use it with care. - */ +** label). Note: The function will not clear the backpointer from the label, +** so use it with care. +*/ { /* Clear the JumpTo entry */ E->JumpTo = 0; @@ -366,8 +366,8 @@ void CE_SetArg (CodeEntry* E, const char* Arg) void CE_SetNumArg (CodeEntry* E, long Num) /* Set a new numeric argument for the given code entry that must already - * have a numeric argument. - */ +** have a numeric argument. +*/ { char Buf[16]; @@ -404,8 +404,8 @@ int CE_IsConstImm (const CodeEntry* E) int CE_IsKnownImm (const CodeEntry* E, unsigned long Num) /* Return true if the argument of E is a constant immediate value that is - * equal to Num. - */ +** equal to Num. +*/ { return (E->AM == AM65_IMM && CE_HasNumArg (E) && E->Num == Num); } @@ -414,12 +414,12 @@ int CE_IsKnownImm (const CodeEntry* E, unsigned long Num) int CE_UseLoadFlags (CodeEntry* E) /* Return true if the instruction uses any flags that are set by a load of - * a register (N and Z). - */ +** a register (N and Z). +*/ { /* Follow unconditional branches, but beware of endless loops. After this, - * E will point to the first entry that is not a branch. - */ + ** E will point to the first entry that is not a branch. + */ if (E->Info & OF_UBRA) { Collection C = AUTO_COLLECTION_INITIALIZER; @@ -491,8 +491,8 @@ void CE_FreeRegInfo (CodeEntry* E) void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) /* Generate register info for this instruction. If an old info exists, it is - * overwritten. - */ +** overwritten. +*/ { /* Pointers to the register contents */ RegContents* In; @@ -522,8 +522,8 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) case OP65_ADC: /* We don't know the value of the carry, so the result is - * always unknown. - */ + ** always unknown. + */ Out->RegA = UNKNOWN_REGVAL; break; @@ -1490,9 +1490,3 @@ void CE_Output (const CodeEntry* E) /* Terminate the line */ WriteOutput ("\n"); } - - - - - - diff --git a/src/cc65/codeent.h b/src/cc65/codeent.h index 72ce626bb..4d0289086 100644 --- a/src/cc65/codeent.h +++ b/src/cc65/codeent.h @@ -90,11 +90,11 @@ struct CodeEntry { const char* MakeHexArg (unsigned Num); /* Convert Num into a string in the form $XY, suitable for passing it as an - * argument to NewCodeEntry, and return a pointer to the string. - * BEWARE: The function returns a pointer to a static buffer, so the value is - * gone if you call it twice (and apart from that it's not thread and signal - * safe). - */ +** argument to NewCodeEntry, and return a pointer to the string. +** BEWARE: The function returns a pointer to a static buffer, so the value is +** gone if you call it twice (and apart from that it's not thread and signal +** safe). +*/ CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo, LineInfo* LI); @@ -105,8 +105,8 @@ void FreeCodeEntry (CodeEntry* E); void CE_ReplaceOPC (CodeEntry* E, opc_t OPC); /* Replace the opcode of the instruction. This will also replace related info, - * Size, Use and Chg, but it will NOT update any arguments or labels. - */ +** Size, Use and Chg, but it will NOT update any arguments or labels. +*/ int CodeEntriesAreEqual (const CodeEntry* E1, const CodeEntry* E2); /* Check if both code entries are equal */ @@ -116,9 +116,9 @@ void CE_AttachLabel (CodeEntry* E, CodeLabel* L); void CE_ClearJumpTo (CodeEntry* E); /* Clear the JumpTo entry and the argument (which contained the name of the - * label). Note: The function will not clear the backpointer from the label, - * so use it with care. - */ +** label). Note: The function will not clear the backpointer from the label, +** so use it with care. +*/ #if defined(HAVE_INLINE) INLINE int CE_HasLabel (const CodeEntry* E) @@ -198,16 +198,16 @@ void CE_SetArg (CodeEntry* E, const char* Arg); void CE_SetNumArg (CodeEntry* E, long Num); /* Set a new numeric argument for the given code entry that must already - * have a numeric argument. - */ +** have a numeric argument. +*/ int CE_IsConstImm (const CodeEntry* E); /* Return true if the argument of E is a constant immediate value */ int CE_IsKnownImm (const CodeEntry* E, unsigned long Num); /* Return true if the argument of E is a constant immediate value that is - * equal to Num. - */ +** equal to Num. +*/ #if defined(HAVE_INLINE) INLINE int CE_IsCallTo (const CodeEntry* E, const char* Name) @@ -221,16 +221,16 @@ INLINE int CE_IsCallTo (const CodeEntry* E, const char* Name) int CE_UseLoadFlags (CodeEntry* E); /* Return true if the instruction uses any flags that are set by a load of - * a register (N and Z). - */ +** a register (N and Z). +*/ void CE_FreeRegInfo (CodeEntry* E); /* Free an existing register info struct */ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs); /* Generate register info for this instruction. If an old info exists, it is - * overwritten. - */ +** overwritten. +*/ void CE_Output (const CodeEntry* E); /* Output the code entry to the output file */ @@ -238,8 +238,5 @@ void CE_Output (const CodeEntry* E); /* End of codeent.h */ + #endif - - - - diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 2d41c4a95..f6ec2f51a 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -192,8 +192,8 @@ void g_fileinfo (const char* Name, unsigned long Size, unsigned long MTime) { if (DebugInfo) { /* We have to place this into the global text segment, so it will - * appear before all .dbg line statements. - */ + ** appear before all .dbg line statements. + */ TS_AddLine (GS->Text, "\t.dbg\t\tfile, \"%s\", %lu, %lu", Name, Size, MTime); } } @@ -298,15 +298,15 @@ int push (unsigned flags) static unsigned MakeByteOffs (unsigned Flags, unsigned Offs) /* The value in Offs is an offset to an address in a/x. Make sure, an object - * of the type given in Flags can be loaded or stored into this address by - * adding part of the offset to the address in ax, so that the remaining - * offset fits into an index register. Return the remaining offset. - */ +** of the type given in Flags can be loaded or stored into this address by +** adding part of the offset to the address in ax, so that the remaining +** offset fits into an index register. Return the remaining offset. +*/ { /* If the offset is too large for a byte register, add the high byte - * of the offset to the primary. Beware: We need a special correction - * if the offset in the low byte will overflow in the operation. - */ + ** of the offset to the primary. Beware: We need a special correction + ** if the offset in the low byte will overflow in the operation. + */ unsigned O = Offs & ~0xFFU; if ((Offs & 0xFF) > 256 - sizeofarg (Flags)) { /* We need to add the low byte also */ @@ -351,8 +351,8 @@ void g_aliasdatalabel (unsigned label, unsigned baselabel, long offs) /* Define label as a local alias for baselabel+offs */ { /* We need an intermediate buffer here since LocalLabelName uses a - * static buffer which changes with each call. - */ + ** static buffer which changes with each call. + */ StrBuf L = AUTO_STRBUF_INITIALIZER; SB_AppendStr (&L, LocalLabelName (label)); SB_Terminate (&L); @@ -427,10 +427,10 @@ void g_importmainargs (void) /* Remember the argument size of a function. The variable is set by g_enter - * and used by g_leave. If the functions gets its argument size by the caller - * (variable param list or function without prototype), g_enter will set the - * value to -1. - */ +** and used by g_leave. If the function gets its argument size by the caller +** (variable param list or function without prototype), g_enter will set the +** value to -1. +*/ static int funcargs; @@ -602,9 +602,9 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes) } else if (StackOffs <= RegOffs) { /* More bytes, but the relation between the register offset in the - * register bank and the stack offset allows us to generate short - * code that uses just one index register. - */ + ** register bank and the stack offset allows us to generate short + ** code that uses just one index register. + */ unsigned Label = GetLocalLabel (); AddCodeLine ("ldy #$%02X", StackOffs); g_defcodelabel (Label); @@ -616,9 +616,9 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes) } else { - /* Ok, this is the generic code. We need to save X because the - * caller will only save A. - */ + /* OK, this is the generic code. We need to save X because the + ** caller will only save A. + */ unsigned Label = GetLocalLabel (); AddCodeLine ("stx tmp1"); AddCodeLine ("ldy #$%02X", (unsigned char) (StackOffs + Bytes - 1)); @@ -840,13 +840,13 @@ void g_getlocal (unsigned Flags, int Offs) void g_getind (unsigned Flags, unsigned Offs) /* Fetch the specified object type indirect through the primary register - * into the primary register - */ +** into the primary register +*/ { /* If the offset is greater than 255, add the part that is > 255 to - * the primary. This way we get an easy addition and use the low byte - * as the offset - */ + ** the primary. This way we get an easy addition and use the low byte + ** as the offset + */ Offs = MakeByteOffs (Flags, Offs); /* Handle the indirect fetch */ @@ -958,8 +958,8 @@ void g_leasp (int Offs) void g_leavariadic (int Offs) /* Fetch the address of a parameter in a variadic function into the primary - * register - */ +** register +*/ { unsigned ArgSizeOffs; @@ -967,8 +967,8 @@ void g_leavariadic (int Offs) Offs -= StackPtr; /* Get the offset of the parameter which is stored at sp+0 on function - * entry and check if this offset is reachable with a byte offset. - */ + ** entry and check if this offset is reachable with a byte offset. + */ CHECK (StackPtr <= 0); ArgSizeOffs = -StackPtr; CheckLocalOffs (ArgSizeOffs); @@ -1106,14 +1106,14 @@ void g_putlocal (unsigned Flags, int Offs, long Val) void g_putind (unsigned Flags, unsigned Offs) /* Store the specified object type in the primary register at the address - * on the top of the stack - */ +** on the top of the stack +*/ { /* We can handle offsets below $100 directly, larger offsets must be added - * to the address. Since a/x is in use, best code is achieved by adding - * just the high byte. Be sure to check if the low byte will overflow while - * while storing. - */ + ** to the address. Since a/x is in use, best code is achieved by adding + ** just the high byte. Be sure to check if the low byte will overflow while + ** while storing. + */ if ((Offs & 0xFF) > 256 - sizeofarg (Flags | CF_FORCECHAR)) { /* Overflow - we need to add the low byte also */ @@ -1226,26 +1226,34 @@ void g_tosint (unsigned flags) -void g_regint (unsigned Flags) -/* Make sure, the value in the primary register an int. Convert if necessary */ +static void g_regchar (unsigned Flags) +/* Make sure, the value in the primary register is in the range of char. Truncate if necessary */ { unsigned L; + AddCodeLine ("ldx #$00"); + + if ((Flags & CF_UNSIGNED) == 0) { + /* Sign extend */ + L = GetLocalLabel(); + AddCodeLine ("cmp #$80"); + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("dex"); + g_defcodelabel (L); + } +} + + + +void g_regint (unsigned Flags) +/* Make sure, the value in the primary register an int. Convert if necessary */ +{ switch (Flags & CF_TYPEMASK) { case CF_CHAR: if (Flags & CF_FORCECHAR) { /* Conversion is from char */ - if (Flags & CF_UNSIGNED) { - AddCodeLine ("ldx #$00"); - } else { - L = GetLocalLabel(); - AddCodeLine ("ldx #$00"); - AddCodeLine ("cmp #$80"); - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); - } + g_regchar (Flags); } /* FALLTHROUGH */ @@ -1263,8 +1271,6 @@ void g_regint (unsigned Flags) void g_reglong (unsigned Flags) /* Make sure, the value in the primary register a long. Convert if necessary */ { - unsigned L; - switch (Flags & CF_TYPEMASK) { case CF_CHAR: @@ -1280,12 +1286,7 @@ void g_reglong (unsigned Flags) } } else { if (IS_Get (&CodeSizeFactor) >= 366) { - L = GetLocalLabel(); - AddCodeLine ("ldx #$00"); - AddCodeLine ("cmp #$80"); - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); + g_regchar (Flags); AddCodeLine ("stx sreg"); AddCodeLine ("stx sreg+1"); } else { @@ -1321,9 +1322,9 @@ void g_reglong (unsigned Flags) unsigned g_typeadjust (unsigned lhs, unsigned rhs) /* Adjust the integer operands before doing a binary operation. lhs is a flags - * value, that corresponds to the value on TOS, rhs corresponds to the value - * in (e)ax. The return value is the the flags value for the resulting type. - */ +** value, that corresponds to the value on TOS, rhs corresponds to the value +** in (e)ax. The return value is the the flags value for the resulting type. +*/ { unsigned ltype, rtype; unsigned result; @@ -1352,11 +1353,11 @@ unsigned g_typeadjust (unsigned lhs, unsigned rhs) } /* Determine the result type for the operation: - * - The result is const if both operands are const. - * - The result is unsigned if one of the operands is unsigned. - * - The result is long if one of the operands is long. - * - Otherwise the result is int sized. - */ + ** - The result is const if both operands are const. + ** - The result is unsigned if one of the operands is unsigned. + ** - The result is long if one of the operands is long. + ** - Otherwise the result is int sized. + */ result = (lhs & CF_CONST) & (rhs & CF_CONST); result |= (lhs & CF_UNSIGNED) | (rhs & CF_UNSIGNED); if (rtype == CF_LONG || ltype == CF_LONG) { @@ -1371,38 +1372,45 @@ unsigned g_typeadjust (unsigned lhs, unsigned rhs) unsigned g_typecast (unsigned lhs, unsigned rhs) /* Cast the value in the primary register to the operand size that is flagged - * by the lhs value. Return the result value. - */ +** by the lhs value. Return the result value. +*/ { - unsigned ltype, rtype; - - /* Get the type spec from the flags */ - ltype = lhs & CF_TYPEMASK; - rtype = rhs & CF_TYPEMASK; - /* Check if a conversion is needed */ if ((rhs & CF_CONST) == 0) { - if (ltype == CF_LONG && rtype != CF_LONG) { - /* We must promote the primary register to long */ - g_reglong (rhs); - } else if (ltype == CF_INT && rtype != CF_INT) { - /* We must promote the primary register to int */ - g_regint (rhs); + switch (lhs & CF_TYPEMASK) { + + case CF_LONG: + /* We must promote the primary register to long */ + g_reglong (rhs); + break; + + case CF_INT: + /* We must promote the primary register to int */ + g_regint (rhs); + break; + + case CF_CHAR: + /* We must truncate the primary register to char */ + g_regchar (lhs); + break; + + default: + typeerror (lhs); } } /* Do not need any other action. If the left type is int, and the primary - * register is long, it will be automagically truncated. If the right hand - * side is const, it is not located in the primary register and handled by - * the expression parser code. - */ + ** register is long, it will be automagically truncated. If the right hand + ** side is const, it is not located in the primary register and handled by + ** the expression parser code. + */ /* Result is const if the right hand side was const */ lhs |= (rhs & CF_CONST); /* The resulting type is that of the left hand side (that's why you called - * this function :-) - */ + ** this function :-) + */ return lhs; } @@ -1410,10 +1418,10 @@ unsigned g_typecast (unsigned lhs, unsigned rhs) void g_scale (unsigned flags, long val) /* Scale the value in the primary register by the given value. If val is positive, - * scale up, is val is negative, scale down. This function is used to scale - * the operands or results of pointer arithmetic by the size of the type, the - * pointer points to. - */ +** scale up, is val is negative, scale down. This function is used to scale +** the operands or results of pointer arithmetic by the size of the type, the +** pointer points to. +*/ { int p2; @@ -1813,9 +1821,9 @@ void g_addeqind (unsigned flags, unsigned offs, unsigned long val) /* Emit += for the location with address in ax */ { /* If the offset is too large for a byte register, add the high byte - * of the offset to the primary. Beware: We need a special correction - * if the offset in the low byte will overflow in the operation. - */ + ** of the offset to the primary. Beware: We need a special correction + ** if the offset in the low byte will overflow in the operation. + */ offs = MakeByteOffs (flags, offs); /* Check the size and determine operation */ @@ -2009,9 +2017,9 @@ void g_subeqind (unsigned flags, unsigned offs, unsigned long val) /* Emit -= for the location with address in ax */ { /* If the offset is too large for a byte register, add the high byte - * of the offset to the primary. Beware: We need a special correction - * if the offset in the low byte will overflow in the operation. - */ + ** of the offset to the primary. Beware: We need a special correction + ** if the offset in the low byte will overflow in the operation. + */ offs = MakeByteOffs (flags, offs); /* Check the size and determine operation */ @@ -2168,8 +2176,8 @@ void g_restore (unsigned flags) void g_cmp (unsigned flags, unsigned long val) /* Immidiate compare. The primary register will not be changed, Z flag - * will be set. - */ +** will be set. +*/ { unsigned L; @@ -2204,11 +2212,11 @@ void g_cmp (unsigned flags, unsigned long val) static void oper (unsigned Flags, unsigned long Val, const char** Subs) /* Encode a binary operation. subs is a pointer to four strings: - * 0 --> Operate on ints - * 1 --> Operate on unsigneds - * 2 --> Operate on longs - * 3 --> Operate on unsigned longs - */ +** 0 --> Operate on ints +** 1 --> Operate on unsigneds +** 2 --> Operate on longs +** 3 --> Operate on unsigned longs +*/ { /* Determine the offset into the array */ if (Flags & CF_UNSIGNED) { @@ -2326,8 +2334,8 @@ void g_push (unsigned flags, unsigned long val) void g_swap (unsigned flags) /* Swap the primary register and the top of the stack. flags give the type - * of *both* values (must have same size). - */ +** of *both* values (must have same size). +*/ { switch (flags & CF_TYPEMASK) { @@ -2421,8 +2429,8 @@ void g_drop (unsigned Space) { if (Space > 255) { /* Inline the code since calling addysp repeatedly is quite some - * overhead. - */ + ** overhead. + */ AddCodeLine ("pha"); AddCodeLine ("lda #$%02X", (unsigned char) Space); AddCodeLine ("clc"); @@ -2450,8 +2458,8 @@ void g_space (int Space) g_drop (-Space); } else if (Space > 255) { /* Inline the code since calling subysp repeatedly is quite some - * overhead. - */ + ** overhead. + */ AddCodeLine ("pha"); AddCodeLine ("lda sp"); AddCodeLine ("sec"); @@ -2547,8 +2555,8 @@ void g_mul (unsigned flags, unsigned long val) } /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { @@ -2624,8 +2632,8 @@ void g_mul (unsigned flags, unsigned long val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. - */ + ** into the normal, non-optimized stuff. + */ flags &= ~CF_FORCECHAR; /* Handle chars as ints */ g_push (flags & ~CF_CONST, 0); @@ -2695,8 +2703,8 @@ void g_or (unsigned flags, unsigned long val) }; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { @@ -2744,9 +2752,9 @@ void g_or (unsigned flags, unsigned long val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + ** into the normal, non-optimized stuff. Note: The standard stuff will + ** always work with ints. + */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } @@ -2766,8 +2774,8 @@ void g_xor (unsigned flags, unsigned long val) /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { @@ -2812,9 +2820,9 @@ void g_xor (unsigned flags, unsigned long val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + ** into the normal, non-optimized stuff. Note: The standard stuff will + ** always work with ints. + */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } @@ -2833,8 +2841,8 @@ void g_and (unsigned Flags, unsigned long Val) }; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (Flags & CF_CONST) { switch (Flags & CF_TYPEMASK) { @@ -2904,9 +2912,9 @@ void g_and (unsigned Flags, unsigned long Val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + ** into the normal, non-optimized stuff. Note: The standard stuff will + ** always work with ints. + */ Flags &= ~CF_FORCECHAR; g_push (Flags & ~CF_CONST, 0); } @@ -2925,8 +2933,8 @@ void g_asr (unsigned flags, unsigned long val) }; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { @@ -3035,9 +3043,9 @@ void g_asr (unsigned flags, unsigned long val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + ** into the normal, non-optimized stuff. Note: The standard stuff will + ** always work with ints. + */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } @@ -3057,8 +3065,8 @@ void g_asl (unsigned flags, unsigned long val) /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { @@ -3134,9 +3142,9 @@ void g_asl (unsigned flags, unsigned long val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + ** into the normal, non-optimized stuff. Note: The standard stuff will + ** always work with ints. + */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } @@ -3419,10 +3427,10 @@ void g_dec (unsigned flags, unsigned long val) /* - * Following are the conditional operators. They compare the TOS against - * the primary and put a literal 1 in the primary if the condition is - * true, otherwise they clear the primary register - */ +** Following are the conditional operators. They compare the TOS against +** the primary and put a literal 1 in the primary if the condition is +** true, otherwise they clear the primary register +*/ @@ -3436,8 +3444,8 @@ void g_eq (unsigned flags, unsigned long val) unsigned L; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { @@ -3467,9 +3475,9 @@ void g_eq (unsigned flags, unsigned long val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + ** into the normal, non-optimized stuff. Note: The standard stuff will + ** always work with ints. + */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } @@ -3490,8 +3498,8 @@ void g_ne (unsigned flags, unsigned long val) unsigned L; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { @@ -3521,9 +3529,9 @@ void g_ne (unsigned flags, unsigned long val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + ** into the normal, non-optimized stuff. Note: The standard stuff will + ** always work with ints. + */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } @@ -3544,14 +3552,14 @@ void g_lt (unsigned flags, unsigned long val) unsigned Label; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { /* Because the handling of the overflow flag is too complex for - * inlining, we can handle only unsigned compares, and signed - * compares against zero here. - */ + ** inlining, we can handle only unsigned compares, and signed + ** compares against zero here. + */ if (flags & CF_UNSIGNED) { /* Give a warning in some special cases */ @@ -3683,9 +3691,9 @@ void g_lt (unsigned flags, unsigned long val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + ** into the normal, non-optimized stuff. Note: The standard stuff will + ** always work with ints. + */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } @@ -3705,8 +3713,8 @@ void g_le (unsigned flags, unsigned long val) /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { /* Look at the type */ @@ -3718,8 +3726,8 @@ void g_le (unsigned flags, unsigned long val) /* Unsigned compare */ if (val < 0xFF) { /* Use < instead of <= because the former gives - * better code on the 6502 than the latter. - */ + ** better code on the 6502 than the latter. + */ g_lt (flags, val+1); } else { /* Always true */ @@ -3730,8 +3738,8 @@ void g_le (unsigned flags, unsigned long val) /* Signed compare */ if ((long) val < 0x7F) { /* Use < instead of <= because the former gives - * better code on the 6502 than the latter. - */ + ** better code on the 6502 than the latter. + */ g_lt (flags, val+1); } else { /* Always true */ @@ -3748,8 +3756,8 @@ void g_le (unsigned flags, unsigned long val) /* Unsigned compare */ if (val < 0xFFFF) { /* Use < instead of <= because the former gives - * better code on the 6502 than the latter. - */ + ** better code on the 6502 than the latter. + */ g_lt (flags, val+1); } else { /* Always true */ @@ -3773,8 +3781,8 @@ void g_le (unsigned flags, unsigned long val) /* Unsigned compare */ if (val < 0xFFFFFFFF) { /* Use < instead of <= because the former gives - * better code on the 6502 than the latter. - */ + ** better code on the 6502 than the latter. + */ g_lt (flags, val+1); } else { /* Always true */ @@ -3798,9 +3806,9 @@ void g_le (unsigned flags, unsigned long val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + ** into the normal, non-optimized stuff. Note: The standard stuff will + ** always work with ints. + */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } @@ -3820,8 +3828,8 @@ void g_gt (unsigned flags, unsigned long val) /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { /* Look at the type */ @@ -3832,14 +3840,14 @@ void g_gt (unsigned flags, unsigned long val) if (flags & CF_UNSIGNED) { if (val == 0) { /* If we have a compare > 0, we will replace it by - * != 0 here, since both are identical but the - * latter is easier to optimize. - */ + ** != 0 here, since both are identical but the + ** latter is easier to optimize. + */ g_ne (flags, val); } else if (val < 0xFF) { /* Use >= instead of > because the former gives - * better code on the 6502 than the latter. - */ + ** better code on the 6502 than the latter. + */ g_ge (flags, val+1); } else { /* Never true */ @@ -3849,8 +3857,8 @@ void g_gt (unsigned flags, unsigned long val) } else { if ((long) val < 0x7F) { /* Use >= instead of > because the former gives - * better code on the 6502 than the latter. - */ + ** better code on the 6502 than the latter. + */ g_ge (flags, val+1); } else { /* Never true */ @@ -3867,14 +3875,14 @@ void g_gt (unsigned flags, unsigned long val) /* Unsigned compare */ if (val == 0) { /* If we have a compare > 0, we will replace it by - * != 0 here, since both are identical but the latter - * is easier to optimize. - */ + ** != 0 here, since both are identical but the latter + ** is easier to optimize. + */ g_ne (flags, val); } else if (val < 0xFFFF) { /* Use >= instead of > because the former gives better - * code on the 6502 than the latter. - */ + ** code on the 6502 than the latter. + */ g_ge (flags, val+1); } else { /* Never true */ @@ -3898,14 +3906,14 @@ void g_gt (unsigned flags, unsigned long val) /* Unsigned compare */ if (val == 0) { /* If we have a compare > 0, we will replace it by - * != 0 here, since both are identical but the latter - * is easier to optimize. - */ + ** != 0 here, since both are identical but the latter + ** is easier to optimize. + */ g_ne (flags, val); } else if (val < 0xFFFFFFFF) { /* Use >= instead of > because the former gives better - * code on the 6502 than the latter. - */ + ** code on the 6502 than the latter. + */ g_ge (flags, val+1); } else { /* Never true */ @@ -3929,9 +3937,9 @@ void g_gt (unsigned flags, unsigned long val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + ** into the normal, non-optimized stuff. Note: The standard stuff will + ** always work with ints. + */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } @@ -3953,14 +3961,14 @@ void g_ge (unsigned flags, unsigned long val) /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { /* Because the handling of the overflow flag is too complex for - * inlining, we can handle only unsigned compares, and signed - * compares against zero here. - */ + ** inlining, we can handle only unsigned compares, and signed + ** compares against zero here. + */ if (flags & CF_UNSIGNED) { /* Give a warning in some special cases */ @@ -4087,9 +4095,9 @@ void g_ge (unsigned flags, unsigned long val) } /* If we go here, we didn't emit code. Push the lhs on stack and fall - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + ** into the normal, non-optimized stuff. Note: The standard stuff will + ** always work with ints. + */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } @@ -4362,6 +4370,3 @@ void g_asmcode (struct StrBuf* B) { AddCodeLine ("%.*s", (int) SB_GetLen (B), SB_GetConstBuf (B)); } - - - diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h index a2f91518d..4ad375618 100644 --- a/src/cc65/codegen.h +++ b/src/cc65/codegen.h @@ -53,11 +53,11 @@ /* Code generator flags. - * Note: The type flags are designed so that a smaller type may override a - * larger one by or'ing it into the existing one. - * Note^2: The actual type including the sign flag is in the lower bits, so - * we can mask the information and use them as a table index. - */ +** Note: The type flags are designed so that a smaller type may override a +** larger one by or'ing it into the existing one. +** Note^2: The actual type including the sign flag is in the lower bits, so +** we can mask the information and use them as a table index. +*/ #define CF_NONE 0x0000 /* No special flags */ /* Values for the actual type */ @@ -208,21 +208,21 @@ void g_reglong (unsigned Flags); unsigned g_typeadjust (unsigned lhs, unsigned rhs); /* Adjust the integer operands before doing a binary operation. lhs is a flags - * value, that corresponds to the value on TOS, rhs corresponds to the value - * in (e)ax. The return value is the the flags value for the resulting type. - */ +** value, that corresponds to the value on TOS, rhs corresponds to the value +** in (e)ax. The return value is the the flags value for the resulting type. +*/ unsigned g_typecast (unsigned lhs, unsigned rhs); /* Cast the value in the primary register to the operand size that is flagged - * by the lhs value. Return the result value. - */ +** by the lhs value. Return the result value. +*/ void g_scale (unsigned flags, long val); /* Scale the value in the primary register by the given value. If val is positive, - * scale up, is val is negative, scale down. This function is used to scale - * the operands or results of pointer arithmetic by the size of the type, the - * pointer points to. - */ +** scale up, is val is negative, scale down. This function is used to scale +** the operands or results of pointer arithmetic by the size of the type, the +** pointer points to. +*/ @@ -274,16 +274,16 @@ void g_getlocal (unsigned Flags, int Offs); void g_getind (unsigned Flags, unsigned Offs); /* Fetch the specified object type indirect through the primary register - * into the primary register - */ +** into the primary register +*/ void g_leasp (int Offs); /* Fetch the address of the specified symbol into the primary register */ void g_leavariadic (int Offs); /* Fetch the address of a parameter in a variadic function into the primary - * register - */ +** register +*/ @@ -301,8 +301,8 @@ void g_putlocal (unsigned Flags, int Offs, long Val); void g_putind (unsigned flags, unsigned offs); /* Store the specified object type in the primary register at the address - * on the top of the stack - */ +** on the top of the stack +*/ @@ -376,8 +376,8 @@ void g_restore (unsigned flags); void g_cmp (unsigned flags, unsigned long val); /* Immidiate compare. The primary register will not be changed, Z flag - * will be set. - */ +** will be set. +*/ void g_test (unsigned flags); /* Test the value in the primary and set the condition codes */ @@ -387,8 +387,8 @@ void g_push (unsigned flags, unsigned long val); void g_swap (unsigned flags); /* Swap the primary register and the top of the stack. flags give the type - * of *both* values (must have same size). - */ +** of *both* values (must have same size). +*/ void g_call (unsigned Flags, const char* Label, unsigned ArgSize); /* Call the specified subroutine name */ @@ -486,6 +486,5 @@ void g_asmcode (struct StrBuf* B); /* End of codegen.h */ + #endif - - diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index 5f549c4a6..be80319e7 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -64,8 +64,8 @@ static const char CmpSuffixTab [][4] = { }; /* Table listing the function names and code info values for known internally - * used functions. This table should get auto-generated in the future. - */ +** used functions. This table should get auto-generated in the future. +*/ typedef struct FuncInfo FuncInfo; struct FuncInfo { const char* Name; /* Function name */ @@ -74,9 +74,9 @@ struct FuncInfo { }; /* Note for the shift functions: Shifts are done modulo 32, so all shift - * routines are marked to use only the A register. The remainder is ignored - * anyway. - */ +** routines are marked to use only the A register. The remainder is ignored +** anyway. +*/ static const FuncInfo FuncInfoTable[] = { { "addeq0sp", REG_AX, REG_AXY }, { "addeqysp", REG_AXY, REG_AXY }, @@ -376,15 +376,15 @@ static int CompareFuncInfo (const void* Key, const void* Info) void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg) /* For the given function, lookup register information and store it into - * the given variables. If the function is unknown, assume it will use and - * load all registers. - */ +** the given variables. If the function is unknown, assume it will use and +** load all registers. +*/ { /* If the function name starts with an underline, it is an external - * function. Search for it in the symbol table. If the function does - * not start with an underline, it may be a runtime support function. - * Search for it in the list of builtin functions. - */ + ** function. Search for it in the symbol table. If the function does + ** not start with an underline, it may be a runtime support function. + ** Search for it in the list of builtin functions. + */ if (Name[0] == '_') { /* Search in the symbol table, skip the leading underscore */ @@ -396,11 +396,11 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg) FuncDesc* D = E->V.F.Func; /* A function may use the A or A/X registers if it is a fastcall - * function. If it is not a fastcall function but a variadic one, - * it will use the Y register (the parameter size is passed here). - * In all other cases, no registers are used. However, we assume - * that any function will destroy all registers. - */ + ** function. If it is not a fastcall function but a variadic one, + ** it will use the Y register (the parameter size is passed here). + ** In all other cases, no registers are used. However, we assume + ** that any function will destroy all registers. + */ if (IsQualFastcall (E->Type) && D->ParamCount > 0) { /* Will use registers depending on the last param */ unsigned LastParamSize = CheckedSizeOf (D->LastParam->Type); @@ -428,9 +428,9 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg) } else if (IsDigit (Name[0]) || Name[0] == '$') { /* A call to a numeric address. Assume that anything gets used and - * destroyed. This is not a real problem, since numeric addresses - * are used mostly in inline assembly anyway. - */ + ** destroyed. This is not a real problem, since numeric addresses + ** are used mostly in inline assembly anyway. + */ *Use = REG_ALL; *Chg = REG_ALL; return; @@ -448,10 +448,10 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg) *Chg = Info->Chg; } else { /* It's an internal function we have no information for. If in - * debug mode, output an additional warning, so we have a chance - * to fix it. Otherwise assume that the internal function will - * use and change all registers. - */ + ** debug mode, output an additional warning, so we have a chance + ** to fix it. Otherwise assume that the internal function will + ** use and change all registers. + */ if (Debug) { fprintf (stderr, "No info about internal function `%s'\n", Name); } @@ -462,8 +462,8 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg) } /* Function not found - assume that the primary register is input, and all - * registers are changed - */ + ** registers are changed + */ *Use = REG_EAXY; *Chg = REG_ALL; } @@ -478,8 +478,8 @@ static int CompareZPInfo (const void* Name, const void* Info) const ZPInfo* E = (const ZPInfo*) Info; /* Do the compare. Be careful because of the length (Info may contain - * more than just the zeropage name). - */ + ** more than just the zeropage name). + */ if (E->Len == 0) { /* Do a full compare */ return strcmp (N, E->Name); @@ -498,8 +498,8 @@ static int CompareZPInfo (const void* Name, const void* Info) const ZPInfo* GetZPInfo (const char* Name) /* If the given name is a zero page symbol, return a pointer to the info - * struct for this symbol, otherwise return NULL. - */ +** struct for this symbol, otherwise return NULL. +*/ { /* Search for the zp location in the list */ return bsearch (Name, ZPInfoTable, ZPInfoCount, @@ -523,8 +523,8 @@ static unsigned GetRegInfo2 (CodeSeg* S, unsigned R; /* Check if we have already visited the current code entry. If so, - * bail out. - */ + ** bail out. + */ if (CE_HasMark (E)) { break; } @@ -542,8 +542,8 @@ static unsigned GetRegInfo2 (CodeSeg* S, } if (R != REG_NONE) { /* We are not interested in the use of any register that has been - * used before. - */ + ** used before. + */ R &= ~Unused; /* Remember the remaining registers */ Used |= R; @@ -552,8 +552,8 @@ static unsigned GetRegInfo2 (CodeSeg* S, /* Evaluate the changed registers */ if ((R = E->Chg) != REG_NONE) { /* We are not interested in the use of any register that has been - * used before. - */ + ** used before. + */ R &= ~Used; /* Remember the remaining registers */ Unused |= R; @@ -570,8 +570,8 @@ static unsigned GetRegInfo2 (CodeSeg* S, } /* If we have an unconditional branch, follow this branch if possible, - * otherwise we're done. - */ + ** otherwise we're done. + */ if ((E->Info & OF_UBRA) != 0) { /* Does this jump have a valid target? */ @@ -587,9 +587,9 @@ static unsigned GetRegInfo2 (CodeSeg* S, } /* In case of conditional branches, follow the branch if possible and - * follow the normal flow (branch not taken) afterwards. If we cannot - * follow the branch, we're done. - */ + ** follow the normal flow (branch not taken) afterwards. If we cannot + ** follow the branch, we're done. + */ } else if ((E->Info & OF_CBRA) != 0) { /* Recursively determine register usage at the branch target */ @@ -604,8 +604,8 @@ static unsigned GetRegInfo2 (CodeSeg* S, } else { /* Jump to external label. This will effectively exit the - * function, so we use the exitregs information here. - */ + ** function, so we use the exitregs information here. + */ U1 = S->ExitRegs; } @@ -677,8 +677,8 @@ static unsigned GetRegInfo1 (CodeSeg* S, unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted) /* Determine register usage information for the instructions starting at the - * given index. - */ +** given index. +*/ { CodeEntry* E; Collection Visited; /* Visited entries */ @@ -748,9 +748,9 @@ int RegEAXUsed (struct CodeSeg* S, unsigned Index) unsigned GetKnownReg (unsigned Use, const RegContents* RC) /* Return the register or zero page location from the set in Use, thats - * contents are known. If Use does not contain any register, or if the - * register in question does not have a known value, return REG_NONE. - */ +** contents are known. If Use does not contain any register, or if the +** register in question does not have a known value, return REG_NONE. +*/ { if ((Use & REG_A) != 0) { return (RC == 0 || RC->RegA >= 0)? REG_A : REG_NONE; @@ -796,9 +796,9 @@ static cmp_t FindCmpCond (const char* Code, unsigned CodeLen) cmp_t FindBoolCmpCond (const char* Name) /* Check if the given string is the name of one of the boolean transformer - * subroutine, and if so, return the condition that is evaluated by this - * routine. Return CMP_INV if the condition is not recognised. - */ +** subroutine, and if so, return the condition that is evaluated by this +** routine. Return CMP_INV if the condition is not recognised. +*/ { /* Check for the correct subroutine name */ if (strncmp (Name, "bool", 4) == 0) { @@ -814,8 +814,8 @@ cmp_t FindBoolCmpCond (const char* Name) cmp_t FindTosCmpCond (const char* Name) /* Check if this is a call to one of the TOS compare functions (tosgtax). - * Return the condition code or CMP_INV on failure. - */ +** Return the condition code or CMP_INV on failure. +*/ { unsigned Len = strlen (Name); @@ -828,6 +828,3 @@ cmp_t FindTosCmpCond (const char* Name) return CMP_INV; } } - - - diff --git a/src/cc65/codeinfo.h b/src/cc65/codeinfo.h index 68a08b5c8..be0bfbf01 100644 --- a/src/cc65/codeinfo.h +++ b/src/cc65/codeinfo.h @@ -128,19 +128,19 @@ typedef enum { void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg); /* For the given function, lookup register information and store it into - * the given variables. If the function is unknown, assume it will use and - * load all registers. - */ +** the given variables. If the function is unknown, assume it will use and +** load all registers. +*/ const ZPInfo* GetZPInfo (const char* Name); /* If the given name is a zero page symbol, return a pointer to the info - * struct for this symbol, otherwise return NULL. - */ +** struct for this symbol, otherwise return NULL. +*/ unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted); /* Determine register usage information for the instructions starting at the - * given index. - */ +** given index. +*/ int RegAUsed (struct CodeSeg* S, unsigned Index); /* Check if the value in A is used. */ @@ -159,26 +159,23 @@ int RegEAXUsed (struct CodeSeg* S, unsigned Index); unsigned GetKnownReg (unsigned Use, const struct RegContents* RC); /* Return the register or zero page location from the set in Use, thats - * contents are known. If Use does not contain any register, or if the - * register in question does not have a known value, return REG_NONE. - */ +** contents are known. If Use does not contain any register, or if the +** register in question does not have a known value, return REG_NONE. +*/ cmp_t FindBoolCmpCond (const char* Name); /* Check if the given string is the name of one of the boolean transformer - * subroutine, and if so, return the condition that is evaluated by this - * routine. Return CMP_INV if the condition is not recognised. - */ +** subroutine, and if so, return the condition that is evaluated by this +** routine. Return CMP_INV if the condition is not recognised. +*/ cmp_t FindTosCmpCond (const char* Name); /* Check if this is a call to one of the TOS compare functions (tosgtax). - * Return the condition code or CMP_INV on failure. - */ +** Return the condition code or CMP_INV on failure. +*/ /* End of codeinfo.h */ + #endif - - - - diff --git a/src/cc65/codelab.c b/src/cc65/codelab.c index 88de84dc1..f36520835 100644 --- a/src/cc65/codelab.c +++ b/src/cc65/codelab.c @@ -101,8 +101,8 @@ void CL_AddRef (CodeLabel* L, struct CodeEntry* E) void CL_MoveRefs (CodeLabel* OldLabel, CodeLabel* NewLabel) /* Move all references to OldLabel to point to NewLabel. OldLabel will have no - * more references on return. - */ +** more references on return. +*/ { /* Walk through all instructions referencing the old label */ unsigned Count = CL_GetRefCount (OldLabel); @@ -132,7 +132,3 @@ void CL_Output (const CodeLabel* L) WriteOutput ("\n"); } } - - - - diff --git a/src/cc65/codelab.h b/src/cc65/codelab.h index d38a30e82..103049b23 100644 --- a/src/cc65/codelab.h +++ b/src/cc65/codelab.h @@ -108,8 +108,8 @@ void CL_AddRef (CodeLabel* L, struct CodeEntry* E); void CL_MoveRefs (CodeLabel* OldLabel, CodeLabel* NewLabel); /* Move all references to OldLabel to point to NewLabel. OldLabel will have no - * more references on return. - */ +** more references on return. +*/ void CL_Output (const CodeLabel* L); /* Output the code label to the output file */ @@ -117,7 +117,5 @@ void CL_Output (const CodeLabel* L); /* End of codelab.h */ + #endif - - - diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index a16364be4..9eb175105 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -80,8 +80,8 @@ static unsigned OptLoad1 (CodeSeg* S) /* Search for a call to ldaxysp where X is not used later and replace it by - * a load of just the A register. - */ +** a load of just the A register. +*/ { unsigned I; unsigned Changes = 0; @@ -161,8 +161,8 @@ static unsigned OptLoad2 (CodeSeg* S) !RegXUsed (S, I+3)) { /* A/X are stored into memory somewhere and X is not used - * later - */ + ** later + */ /* lda (sp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[0]->LI); @@ -251,8 +251,8 @@ static unsigned OptLoad3 (CodeSeg* S) CodeEntry* N; /* If we had a preceeding load that is identical, remove this one. - * If it is not identical, or we didn't have one, remember it. - */ + ** If it is not identical, or we didn't have one, remember it. + */ if (Load != 0 && E->OPC == Load->OPC && E->AM == Load->AM && @@ -299,21 +299,21 @@ static unsigned OptLoad3 (CodeSeg* S) static unsigned OptDecouple (CodeSeg* S) /* Decouple operations, that is, do the following replacements: - * - * dex -> ldx #imm - * inx -> ldx #imm - * dey -> ldy #imm - * iny -> ldy #imm - * tax -> ldx #imm - * txa -> lda #imm - * tay -> ldy #imm - * tya -> lda #imm - * lda zp -> lda #imm - * ldx zp -> ldx #imm - * ldy zp -> ldy #imm - * - * Provided that the register values are known of course. - */ +** +** dex -> ldx #imm +** inx -> ldx #imm +** dey -> ldy #imm +** iny -> ldy #imm +** tax -> ldx #imm +** txa -> lda #imm +** tay -> ldy #imm +** tya -> lda #imm +** lda zp -> lda #imm +** ldx zp -> ldx #imm +** ldy zp -> ldy #imm +** +** Provided that the register values are known of course. +*/ { unsigned Changes = 0; unsigned I; @@ -529,9 +529,9 @@ static unsigned OptDecouple (CodeSeg* S) static unsigned IsDecSP (const CodeEntry* E) /* Check if this is an insn that decrements the stack pointer. If so, return - * the decrement. If not, return zero. - * The function expects E to be a subroutine call. - */ +** the decrement. If not, return zero. +** The function expects E to be a subroutine call. +*/ { if (strncmp (E->Arg, "decsp", 5) == 0) { if (E->Arg[5] >= '1' && E->Arg[5] <= '8') { @@ -549,8 +549,8 @@ static unsigned IsDecSP (const CodeEntry* E) static unsigned OptStackPtrOps (CodeSeg* S) /* Merge adjacent calls to decsp into one. NOTE: This function won't merge all - * known cases! - */ +** known cases! +*/ { unsigned Changes = 0; unsigned I; @@ -851,8 +851,8 @@ static int CmpOptStep (const void* Key, const void* Func) static OptFunc* FindOptFunc (const char* Name) /* Find an optimizer step by name in the table and return a pointer. Return - * NULL if no such step is found. - */ +** NULL if no such step is found. +*/ { /* Search for the function in the list */ OptFunc** O = bsearch (Name, OptFuncs, OPTFUNC_COUNT, sizeof (OptFuncs[0]), CmpOptStep); @@ -863,8 +863,8 @@ static OptFunc* FindOptFunc (const char* Name) static OptFunc* GetOptFunc (const char* Name) /* Find an optimizer step by name in the table and return a pointer. Print an - * error and call AbEnd if not found. - */ +** error and call AbEnd if not found. +*/ { /* Search for the function in the list */ OptFunc* F = FindOptFunc (Name); @@ -1074,8 +1074,8 @@ static unsigned RunOptFunc (CodeSeg* S, OptFunc* F, unsigned Max) unsigned Changes, C; /* Don't run the function if it is disabled or if it is prohibited by the - * code size factor - */ + ** code size factor + */ if (F->Disabled || F->CodeSizeFactor > S->CodeSizeFactor) { return 0; } @@ -1113,10 +1113,10 @@ static unsigned RunOptFunc (CodeSeg* S, OptFunc* F, unsigned Max) static unsigned RunOptGroup1 (CodeSeg* S) /* Run the first group of optimization steps. These steps translate known - * patterns emitted by the code generator into more optimal patterns. Order - * of the steps is important, because some of the steps done earlier cover - * the same patterns as later steps as subpatterns. - */ +** patterns emitted by the code generator into more optimal patterns. Order +** of the steps is important, because some of the steps done earlier cover +** the same patterns as later steps as subpatterns. +*/ { unsigned Changes = 0; @@ -1168,10 +1168,10 @@ static unsigned RunOptGroup1 (CodeSeg* S) static unsigned RunOptGroup2 (CodeSeg* S) /* Run one group of optimization steps. This step involves just decoupling - * instructions by replacing them by instructions that do not depend on - * previous instructions. This makes it easier to find instructions that - * aren't used. - */ +** instructions by replacing them by instructions that do not depend on +** previous instructions. This makes it easier to find instructions that +** aren't used. +*/ { unsigned Changes = 0; @@ -1185,9 +1185,9 @@ static unsigned RunOptGroup2 (CodeSeg* S) static unsigned RunOptGroup3 (CodeSeg* S) /* Run one group of optimization steps. These steps depend on each other, - * that means that one step may allow another step to do additional work, - * so we will repeat the steps as long as we see any changes. - */ +** that means that one step may allow another step to do additional work, +** so we will repeat the steps as long as we see any changes. +*/ { unsigned Changes, C; @@ -1254,8 +1254,8 @@ static unsigned RunOptGroup3 (CodeSeg* S) static unsigned RunOptGroup4 (CodeSeg* S) /* Run another round of pattern replacements. These are done late, since there - * may be better replacements before. - */ +** may be better replacements before. +*/ { unsigned Changes = 0; @@ -1287,9 +1287,9 @@ static unsigned RunOptGroup5 (CodeSeg* S) Changes += RunOptFunc (S, &DOpt65C02Stores, 1); if (Changes) { /* The 65C02 replacement codes do often make the use of a register - * value unnecessary, so if we have changes, run another load - * removal pass. - */ + ** value unnecessary, so if we have changes, run another load + ** removal pass. + */ Changes += RunOptFunc (S, &DOptUnusedLoads, 1); } } @@ -1302,18 +1302,18 @@ static unsigned RunOptGroup5 (CodeSeg* S) static unsigned RunOptGroup6 (CodeSeg* S) /* This one is quite special. It tries to replace "lda (sp),y" by "lda (sp,x)". - * The latter is ony cycle slower, but if we're able to remove the necessary - * load of the Y register, because X is zero anyway, we gain 1 cycle and - * shorten the code by one (transfer) or two bytes (load). So what we do is - * to replace the insns, remove unused loads, and then change back all insns - * where Y is still zero (meaning that the load has not been removed). - */ +** The latter is ony cycle slower, but if we're able to remove the necessary +** load of the Y register, because X is zero anyway, we gain 1 cycle and +** shorten the code by one (transfer) or two bytes (load). So what we do is +** to replace the insns, remove unused loads, and then change back all insns +** where Y is still zero (meaning that the load has not been removed). +*/ { unsigned Changes = 0; /* This group will only run for a standard 6502, because the 65C02 has a - * better addressing mode that covers this case. - */ + ** better addressing mode that covers this case. + */ if ((CPUIsets[CPU] & CPU_ISET_65SC02) == 0) { Changes += RunOptFunc (S, &DOptIndLoads1, 1); Changes += RunOptFunc (S, &DOptUnusedLoads, 1); @@ -1328,21 +1328,21 @@ static unsigned RunOptGroup6 (CodeSeg* S) static unsigned RunOptGroup7 (CodeSeg* S) /* The last group of optimization steps. Adjust branches, do size optimizations. - */ +*/ { unsigned Changes = 0; unsigned C; /* Optimize for size, that is replace operations by shorter ones, even - * if this does hinder further optimizations (no problem since we're - * done soon). - */ + ** if this does hinder further optimizations (no problem since we're + ** done soon). + */ C = RunOptFunc (S, &DOptSize1, 1); if (C) { Changes += C; /* Run some optimization passes again, since the size optimizations - * may have opened new oportunities. - */ + ** may have opened new oportunities. + */ Changes += RunOptFunc (S, &DOptUnusedLoads, 1); Changes += RunOptFunc (S, &DOptUnusedStores, 1); Changes += RunOptFunc (S, &DOptJumpTarget1, 5); @@ -1353,8 +1353,8 @@ static unsigned RunOptGroup7 (CodeSeg* S) if (C) { Changes += C; /* Run some optimization passes again, since the size optimizations - * may have opened new oportunities. - */ + ** may have opened new oportunities. + */ Changes += RunOptFunc (S, &DOptUnusedLoads, 1); Changes += RunOptFunc (S, &DOptJumpTarget1, 5); Changes += RunOptFunc (S, &DOptStore5, 1); @@ -1366,8 +1366,8 @@ static unsigned RunOptGroup7 (CodeSeg* S) Changes += RunOptFunc (S, &DOptBranchDist, 3); /* Replace conditional branches to RTS. If we had changes, we must run dead - * code elimination again, since the change may have introduced dead code. - */ + ** code elimination again, since the change may have introduced dead code. + */ C = RunOptFunc (S, &DOptRTSJumps2, 1); Changes += C; if (C) { @@ -1432,6 +1432,3 @@ void RunOpt (CodeSeg* S) WriteOptStats (StatFileName); } } - - - diff --git a/src/cc65/codeopt.h b/src/cc65/codeopt.h index 7ce2fa844..e0bc83731 100644 --- a/src/cc65/codeopt.h +++ b/src/cc65/codeopt.h @@ -64,7 +64,5 @@ void RunOpt (CodeSeg* S); /* End of codeopt.h */ + #endif - - - diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index c28f32651..a808a26f7 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -87,8 +87,8 @@ static void CS_PrintFunctionHeader (const CodeSeg* S) static void CS_MoveLabelsToEntry (CodeSeg* S, CodeEntry* E) /* Move all labels from the label pool to the given entry and remove them - * from the pool. - */ +** from the pool. +*/ { /* Transfer the labels if we have any */ unsigned I; @@ -203,8 +203,8 @@ static const char* SkipSpace (const char* S) static const char* ReadToken (const char* L, const char* Term, char* Buf, unsigned BufSize) /* Read the next token into Buf, return the updated line pointer. The - * token is terminated by one of the characters given in term. - */ +** token is terminated by one of the characters given in term. +*/ { /* Read/copy the token */ unsigned I = 0; @@ -214,8 +214,8 @@ static const char* ReadToken (const char* L, const char* Term, Buf[I] = *L; } else if (I == BufSize-1) { /* Cannot store this character, this is an input error (maybe - * identifier too long or similar). - */ + ** identifier too long or similar). + */ Error ("ASM code error: syntax error"); } ++I; @@ -238,11 +238,11 @@ static const char* ReadToken (const char* L, const char* Term, static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L) /* Parse an instruction nnd generate a code entry from it. If the line contains - * errors, output an error message and return NULL. - * For simplicity, we don't accept the broad range of input a "real" assembler - * does. The instruction and the argument are expected to be separated by - * white space, for example. - */ +** errors, output an error message and return NULL. +** For simplicity, we don't accept the broad range of input a "real" assembler +** does. The instruction and the argument are expected to be separated by +** white space, for example. +*/ { char Mnemo[IDENTSIZE+10]; const OPCDesc* OPC; @@ -265,8 +265,8 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L) CS_AddLabel (S, Mnemo); /* If we have reached end of line, bail out, otherwise a mnemonic - * may follow. - */ + ** may follow. + */ if (*L == '\0') { return 0; } @@ -415,10 +415,10 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L) } /* If the instruction is a branch, check for the label and generate it - * if it does not exist. This may lead to unused labels (if the label - * is actually an external one) which are removed by the CS_MergeLabels - * function later. - */ + ** if it does not exist. This may lead to unused labels (if the label + ** is actually an external one) which are removed by the CS_MergeLabels + ** function later. + */ Label = 0; if (AM == AM65_BRA) { @@ -434,8 +434,8 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L) } /* We do now have the addressing mode in AM. Allocate a new CodeEntry - * structure and initialize it. - */ + ** structure and initialize it. + */ E = NewCodeEntry (OPC->OPC, AM, Arg, Label, LI); /* Return the new code entry */ @@ -469,8 +469,8 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func) } /* If we have a function given, get the return type of the function. - * Assume ANY return type besides void will use the A and X registers. - */ + ** Assume ANY return type besides void will use the A and X registers. + */ if (S->Func && !IsTypeVoid ((RetType = GetFuncReturn (Func->Type)))) { if (SizeOf (RetType) == SizeOf (type_long)) { S->ExitRegs = REG_EAX; @@ -564,8 +564,8 @@ void CS_AddLine (CodeSeg* S, LineInfo* LI, const char* Format, ...) void CS_InsertEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index) /* Insert the code entry at the index given. Following code entries will be - * moved to slots with higher indices. - */ +** moved to slots with higher indices. +*/ { /* Insert the entry into the collection */ CollInsert (&S->Entries, E, Index); @@ -575,27 +575,27 @@ void CS_InsertEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index) void CS_DelEntry (CodeSeg* S, unsigned Index) /* Delete an entry from the code segment. This includes moving any associated - * labels, removing references to labels and even removing the referenced labels - * if the reference count drops to zero. - * Note: Labels are moved forward if possible, that is, they are moved to the - * next insn (not the preceeding one). - */ +** labels, removing references to labels and even removing the referenced labels +** if the reference count drops to zero. +** Note: Labels are moved forward if possible, that is, they are moved to the +** next insn (not the preceeding one). +*/ { /* Get the code entry for the given index */ CodeEntry* E = CS_GetEntry (S, Index); /* If the entry has a labels, we have to move this label to the next insn. - * If there is no next insn, move the label into the code segement label - * pool. The operation is further complicated by the fact that the next - * insn may already have a label. In that case change all reference to - * this label and delete the label instead of moving it. - */ + ** If there is no next insn, move the label into the code segement label + ** pool. The operation is further complicated by the fact that the next + ** insn may already have a label. In that case change all reference to + ** this label and delete the label instead of moving it. + */ unsigned Count = CE_GetLabelCount (E); if (Count > 0) { /* The instruction has labels attached. Check if there is a next - * instruction. - */ + ** instruction. + */ if (Index == CS_GetEntryCount (S)-1) { /* No next instruction, move to the codeseg label pool */ @@ -613,8 +613,8 @@ void CS_DelEntry (CodeSeg* S, unsigned Index) } /* If this insn references a label, remove the reference. And, if the - * the reference count for this label drops to zero, remove this label. - */ + ** the reference count for this label drops to zero, remove this label. + */ if (E->JumpTo) { /* Remove the reference */ CS_RemoveLabelRef (S, E); @@ -631,12 +631,12 @@ void CS_DelEntry (CodeSeg* S, unsigned Index) void CS_DelEntries (CodeSeg* S, unsigned Start, unsigned Count) /* Delete a range of code entries. This includes removing references to labels, - * labels attached to the entries and so on. - */ +** labels attached to the entries and so on. +*/ { /* Start deleting the entries from the rear, because this involves less - * memory moving. - */ + ** memory moving. + */ while (Count--) { CS_DelEntry (S, Start + Count); } @@ -646,14 +646,14 @@ void CS_DelEntries (CodeSeg* S, unsigned Start, unsigned Count) void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos) /* Move a range of entries from one position to another. Start is the index - * of the first entry to move, Count is the number of entries and NewPos is - * the index of the target entry. The entry with the index Start will later - * have the index NewPos. All entries with indices NewPos and above are - * moved to higher indices. If the code block is moved to the end of the - * current code, and if pending labels exist, these labels will get attached - * to the first instruction of the moved block (the first one after the - * current code end) - */ +** of the first entry to move, Count is the number of entries and NewPos is +** the index of the target entry. The entry with the index Start will later +** have the index NewPos. All entries with indices NewPos and above are +** moved to higher indices. If the code block is moved to the end of the +** current code, and if pending labels exist, these labels will get attached +** to the first instruction of the moved block (the first one after the +** current code end) +*/ { /* Transparently handle an empty range */ if (Count == 0) { @@ -661,8 +661,8 @@ void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos } /* If NewPos is at the end of the code segment, move any labels from the - * label pool to the first instruction of the moved range. - */ + ** label pool to the first instruction of the moved range. + */ if (NewPos == CS_GetEntryCount (S)) { CS_MoveLabelsToEntry (S, CS_GetEntry (S, Start)); } @@ -675,8 +675,8 @@ void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos struct CodeEntry* CS_GetPrevEntry (CodeSeg* S, unsigned Index) /* Get the code entry preceeding the one with the index Index. If there is no - * preceeding code entry, return NULL. - */ +** preceeding code entry, return NULL. +*/ { if (Index == 0) { /* This is the first entry */ @@ -691,8 +691,8 @@ struct CodeEntry* CS_GetPrevEntry (CodeSeg* S, unsigned Index) struct CodeEntry* CS_GetNextEntry (CodeSeg* S, unsigned Index) /* Get the code entry following the one with the index Index. If there is no - * following code entry, return NULL. - */ +** following code entry, return NULL. +*/ { if (Index >= CollCount (&S->Entries)-1) { /* This is the last entry */ @@ -708,8 +708,8 @@ struct CodeEntry* CS_GetNextEntry (CodeSeg* S, unsigned Index) int CS_GetEntries (CodeSeg* S, struct CodeEntry** List, unsigned Start, unsigned Count) /* Get Count code entries into List starting at index start. Return true if - * we got the lines, return false if not enough lines were available. - */ +** we got the lines, return false if not enough lines were available. +*/ { /* Check if enough entries are available */ if (Start + Count > CollCount (&S->Entries)) { @@ -739,9 +739,9 @@ unsigned CS_GetEntryIndex (CodeSeg* S, struct CodeEntry* E) int CS_RangeHasLabel (CodeSeg* S, unsigned Start, unsigned Count) /* Return true if any of the code entries in the given range has a label - * attached. If the code segment does not span the given range, check the - * possible span instead. - */ +** attached. If the code segment does not span the given range, check the +** possible span instead. +*/ { unsigned EntryCount = CS_GetEntryCount(S); @@ -752,8 +752,8 @@ int CS_RangeHasLabel (CodeSeg* S, unsigned Start, unsigned Count) } /* Check each entry. Since we have validated the index above, we may - * use the unchecked access function in the loop which is faster. - */ + ** use the unchecked access function in the loop which is faster. + */ while (Count--) { const CodeEntry* E = CollAtUnchecked (&S->Entries, Start++); if (CE_HasLabel (E)) { @@ -805,8 +805,8 @@ CodeLabel* CS_AddLabel (CodeSeg* S, const char* Name) CodeLabel* CS_GenLabel (CodeSeg* S, struct CodeEntry* E) /* If the code entry E does already have a label, return it. Otherwise - * create a new label, attach it to E and return it. - */ +** create a new label, attach it to E and return it. +*/ { CodeLabel* L; @@ -856,10 +856,10 @@ void CS_DelLabel (CodeSeg* S, CodeLabel* L) CollDeleteAll (&L->JumpFrom); /* Remove the reference to the owning instruction if it has one. The - * function may be called for a label without an owner when deleting - * unfinished parts of the code. This is unfortunate since it allows - * errors to slip through. - */ + ** function may be called for a label without an owner when deleting + ** unfinished parts of the code. This is unfortunate since it allows + ** errors to slip through. + */ if (L->Owner) { CollDeleteItem (&L->Owner->Labels, L); } @@ -872,16 +872,16 @@ void CS_DelLabel (CodeSeg* S, CodeLabel* L) void CS_MergeLabels (CodeSeg* S) /* Merge code labels. That means: For each instruction, remove all labels but - * one and adjust references accordingly. - */ +** one and adjust references accordingly. +*/ { unsigned I; unsigned J; /* First, remove all labels from the label symbol table that don't have an - * owner (this means that they are actually external labels but we didn't - * know that previously since they may have also been forward references). - */ + ** owner (this means that they are actually external labels but we didn't + ** know that previously since they may have also been forward references). + */ for (I = 0; I < CS_LABEL_HASH_SIZE; ++I) { /* Get the first label in this hash chain */ @@ -898,9 +898,9 @@ void CS_MergeLabels (CodeSeg* S) /* Get the entry referencing this label */ CodeEntry* E = CL_GetRef (X, J); /* And remove the reference. Do NOT call CE_ClearJumpTo - * here, because this will also clear the label name, - * which is not what we want. - */ + ** here, because this will also clear the label name, + ** which is not what we want. + */ E->JumpTo = 0; } @@ -937,10 +937,10 @@ void CS_MergeLabels (CodeSeg* S) RefLab = CE_GetLabel (E, 0); /* Walk through the remaining labels and change references to these - * labels to a reference to the one and only label. Delete the labels - * that are no longer used. To increase performance, walk backwards - * through the list. - */ + ** labels to a reference to the one and only label. Delete the labels + ** that are no longer used. To increase performance, walk backwards + ** through the list. + */ for (J = LabelCount-1; J >= 1; --J) { /* Get the next label */ @@ -954,9 +954,9 @@ void CS_MergeLabels (CodeSeg* S) } /* The reference label is the only remaining label. Check if there - * are any references to this label, and delete it if this is not - * the case. - */ + ** are any references to this label, and delete it if this is not + ** the case. + */ if (CollCount (&RefLab->JumpFrom) == 0) { /* Delete the label */ CS_DelLabel (S, RefLab); @@ -968,10 +968,10 @@ void CS_MergeLabels (CodeSeg* S) void CS_MoveLabels (CodeSeg* S, struct CodeEntry* Old, struct CodeEntry* New) /* Move all labels from Old to New. The routine will move the labels itself - * if New does not have any labels, and move references if there is at least - * a label for new. If references are moved, the old label is deleted - * afterwards. - */ +** if New does not have any labels, and move references if there is at least +** a label for new. If references are moved, the old label is deleted +** afterwards. +*/ { /* Get the number of labels to move */ unsigned OldLabelCount = CE_GetLabelCount (Old); @@ -1011,10 +1011,10 @@ void CS_MoveLabels (CodeSeg* S, struct CodeEntry* Old, struct CodeEntry* New) void CS_RemoveLabelRef (CodeSeg* S, struct CodeEntry* E) /* Remove the reference between E and the label it jumps to. The reference - * will be removed on both sides and E->JumpTo will be 0 after that. If - * the reference was the only one for the label, the label will get - * deleted. - */ +** will be removed on both sides and E->JumpTo will be 0 after that. If +** the reference was the only one for the label, the label will get +** deleted. +*/ { /* Get a pointer to the label and make sure it exists */ CodeLabel* L = E->JumpTo; @@ -1036,9 +1036,9 @@ void CS_RemoveLabelRef (CodeSeg* S, struct CodeEntry* E) void CS_MoveLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L) /* Change the reference of E to L instead of the current one. If this - * was the only reference to the old label, the old label will get - * deleted. - */ +** was the only reference to the old label, the old label will get +** deleted. +*/ { /* Get the old label */ CodeLabel* OldLabel = E->JumpTo; @@ -1057,10 +1057,10 @@ void CS_MoveLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L) void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last) /* Delete all entries between first and last, both inclusive. The function - * can only handle basic blocks (First is the only entry, Last the only exit) - * and no open labels. It will call FAIL if any of these preconditions are - * violated. - */ +** can only handle basic blocks (First is the only entry, Last the only exit) +** and no open labels. It will call FAIL if any of these preconditions are +** violated. +*/ { unsigned I; CodeEntry* FirstEntry; @@ -1069,17 +1069,17 @@ void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last) CHECK (First <= Last && Last < CS_GetEntryCount (S)); /* If Last is actually the last insn, call CS_DelCodeAfter instead, which - * is more flexible in this case. - */ + ** is more flexible in this case. + */ if (Last == CS_GetEntryCount (S) - 1) { CS_DelCodeAfter (S, First); return; } /* Get the first entry and check if it has any labels. If it has, move - * them to the insn following Last. If Last is the last insn of the code - * segment, make them ownerless and move them to the label pool. - */ + ** them to the insn following Last. If Last is the last insn of the code + ** segment, make them ownerless and move them to the label pool. + */ FirstEntry = CS_GetEntry (S, First); if (CE_HasLabel (FirstEntry)) { /* Get the entry following last */ @@ -1094,8 +1094,8 @@ void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last) } /* First pass: Delete all references to labels. If the reference count - * for a label drops to zero, delete it. - */ + ** for a label drops to zero, delete it. + */ for (I = Last; I >= First; --I) { /* Get the next entry */ @@ -1114,9 +1114,9 @@ void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last) } /* Second pass: Delete the instructions. If a label attached to an - * instruction still has references, it must be references from outside - * the deleted area, which is an error. - */ + ** instruction still has references, it must be references from outside + ** the deleted area, which is an error. + */ for (I = Last; I >= First; --I) { /* Get the next entry */ @@ -1142,8 +1142,8 @@ void CS_DelCodeAfter (CodeSeg* S, unsigned Last) unsigned Count = CS_GetEntryCount (S); /* First pass: Delete all references to labels. If the reference count - * for a label drops to zero, delete it. - */ + ** for a label drops to zero, delete it. + */ unsigned C = Count; while (Last < C--) { @@ -1153,8 +1153,8 @@ void CS_DelCodeAfter (CodeSeg* S, unsigned Last) /* Check if this entry has a label reference */ if (E->JumpTo) { /* If the label is a label in the label pool and this is the last - * reference to the label, remove the label from the pool. - */ + ** reference to the label, remove the label from the pool. + */ CodeLabel* L = E->JumpTo; int Index = CollIndex (&S->Labels, L); if (Index >= 0 && CollCount (&L->JumpFrom) == 1) { @@ -1169,10 +1169,10 @@ void CS_DelCodeAfter (CodeSeg* S, unsigned Last) } /* Second pass: Delete the instructions. If a label attached to an - * instruction still has references, it must be references from outside - * the deleted area. Don't delete the label in this case, just make it - * ownerless and move it to the label pool. - */ + ** instruction still has references, it must be references from outside + ** the deleted area. Don't delete the label in this case, just make it + ** ownerless and move it to the label pool. + */ C = Count; while (Last < C--) { @@ -1207,10 +1207,10 @@ void CS_ResetMarks (CodeSeg* S, unsigned First, unsigned Last) int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last) /* Check if the given code segment range is a basic block. That is, check if - * First is the only entrance and Last is the only exit. This means that no - * jump/branch inside the block may jump to an insn below First or after(!) - * Last, and that no insn may jump into this block from the outside. - */ +** First is the only entrance and Last is the only exit. This means that no +** jump/branch inside the block may jump to an insn below First or after(!) +** Last, and that no insn may jump into this block from the outside. +*/ { unsigned I; @@ -1221,8 +1221,8 @@ int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last) CS_ResetMarks (S, First, Last); /* Second pass: Walk over the range checking all labels. Note: There may be - * label on the first insn which is ok. - */ + ** label on the first insn which is ok. + */ I = First + 1; while (I <= Last) { @@ -1230,8 +1230,8 @@ int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last) CodeEntry* E = CS_GetEntry (S, I); /* Check if this entry has one or more labels, if so, check which - * entries jump to this label. - */ + ** entries jump to this label. + */ unsigned LabelCount = CE_GetLabelCount (E); unsigned LabelIndex; for (LabelIndex = 0; LabelIndex < LabelCount; ++LabelIndex) { @@ -1240,8 +1240,8 @@ int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last) CodeLabel* L = CE_GetLabel (E, LabelIndex); /* Walk over all entries that jump to this label. Check for each - * of the entries if it is out of the range. - */ + ** of the entries if it is out of the range. + */ unsigned RefCount = CL_GetRefCount (L); unsigned RefIndex; for (RefIndex = 0; RefIndex < RefCount; ++RefIndex) { @@ -1250,10 +1250,10 @@ int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last) CodeEntry* Ref = CL_GetRef (L, RefIndex); /* Walk over out complete range and check if we find the - * refering entry. This is cheaper than using CS_GetEntryIndex, - * because CS_GetEntryIndex will search the complete code - * segment and not just our range. - */ + ** refering entry. This is cheaper than using CS_GetEntryIndex, + ** because CS_GetEntryIndex will search the complete code + ** segment and not just our range. + */ unsigned J; for (J = First; J <= Last; ++J) { if (Ref == CS_GetEntry (S, J)) { @@ -1262,17 +1262,17 @@ int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last) } if (J > Last) { /* We did not find the entry. This means that the jump to - * out code segment entry E came from outside the range, - * which in turn means that the given range is not a basic - * block. - */ + ** out code segment entry E came from outside the range, + ** which in turn means that the given range is not a basic + ** block. + */ CS_ResetMarks (S, First, Last); return 0; } /* If we come here, we found the entry. Mark it, so we know - * that the branch to the label is in range. - */ + ** that the branch to the label is in range. + */ CE_SetMark (Ref); } } @@ -1282,9 +1282,9 @@ int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last) } /* Third pass: Walk again over the range and check all branches. If we - * find a branch that is not marked, its target is not inside the range - * (since we checked all the labels in the range before). - */ + ** find a branch that is not marked, its target is not inside the range + ** (since we checked all the labels in the range before). + */ I = First; while (I <= Last) { @@ -1295,8 +1295,8 @@ int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last) if (E->Info & (OF_UBRA | OF_CBRA)) { if (!CE_HasMark (E)) { /* No mark means not a basic block. Before bailing out, be sure - * to remove the marks from the remaining entries. - */ + ** to remove the marks from the remaining entries. + */ CS_ResetMarks (S, I+1, Last); return 0; } @@ -1317,18 +1317,18 @@ int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last) void CS_OutputPrologue (const CodeSeg* S) /* If the given code segment is a code segment for a function, output the - * assembler prologue into the file. That is: Output a comment header, switch - * to the correct segment and enter the local function scope. If the code - * segment is global, do nothing. - */ +** assembler prologue into the file. That is: Output a comment header, switch +** to the correct segment and enter the local function scope. If the code +** segment is global, do nothing. +*/ { /* Get the function associated with the code segment */ SymEntry* Func = S->Func; /* If the code segment is associated with a function, print a function - * header and enter a local scope. Be sure to switch to the correct - * segment before outputing the function label. - */ + ** header and enter a local scope. Be sure to switch to the correct + ** segment before outputing the function label. + */ if (Func) { /* Get the function descriptor */ CS_PrintFunctionHeader (S); @@ -1347,8 +1347,8 @@ void CS_OutputPrologue (const CodeSeg* S) void CS_OutputEpilogue (const CodeSeg* S) /* If the given code segment is a code segment for a function, output the - * assembler epilogue into the file. That is: Close the local function scope. - */ +** assembler epilogue into the file. That is: Close the local function scope. +*/ { if (S->Func) { WriteOutput ("\n.endproc\n\n"); @@ -1383,16 +1383,16 @@ void CS_Output (CodeSeg* S) /* Get the next entry */ const CodeEntry* E = CollConstAt (&S->Entries, I); /* Check if the line info has changed. If so, output the source line - * if the option is enabled and output debug line info if the debug - * option is enabled. - */ + ** if the option is enabled and output debug line info if the debug + ** option is enabled. + */ if (E->LI != LI) { /* Line info has changed, remember the new line info */ LI = E->LI; /* Add the source line as a comment. Beware: When line continuation - * was used, the line may contain newlines. - */ + ** was used, the line may contain newlines. + */ if (AddSource) { const char* L = LI->Line; WriteOutput (";\n; "); @@ -1466,8 +1466,8 @@ void CS_GenRegInfo (CodeSeg* S) CurrentRegs = &Regs; /* Walk over all insns and note just the changes from one insn to the - * next one. - */ + ** next one. + */ WasJump = 0; for (I = 0; I < CS_GetEntryCount (S); ++I) { @@ -1481,13 +1481,13 @@ void CS_GenRegInfo (CodeSeg* S) if (LabelCount > 0) { /* Loop over all entry points that jump here. If these entry - * points already have register info, check if all values are - * known and identical. If all values are identical, and the - * preceeding instruction was not an unconditional branch, check - * if the register value on exit of the preceeding instruction - * is also identical. If all these values are identical, the - * value of a register is known, otherwise it is unknown. - */ + ** points already have register info, check if all values are + ** known and identical. If all values are identical, and the + ** preceeding instruction was not an unconditional branch, check + ** if the register value on exit of the preceeding instruction + ** is also identical. If all these values are identical, the + ** value of a register is known, otherwise it is unknown. + */ CodeLabel* Label = CE_GetLabel (E, 0); unsigned Entry; if (WasJump) { @@ -1509,11 +1509,11 @@ void CS_GenRegInfo (CodeSeg* S) CodeEntry* J = CL_GetRef (Label, Entry); if (J->RI == 0) { /* No register info for this entry. This means that the - * instruction that jumps here is at higher addresses and - * the jump is a backward jump. We need a second run to - * get the register info right in this case. Until then, - * assume unknown register contents. - */ + ** instruction that jumps here is at higher addresses and + ** the jump is a backward jump. We need a second run to + ** get the register info right in this case. Until then, + ** assume unknown register contents. + */ Done = 0; RC_Invalidate (&Regs); break; @@ -1554,9 +1554,9 @@ void CS_GenRegInfo (CodeSeg* S) CurrentRegs = &E->RI->Out; /* If this insn is a branch on zero flag, we may have more info on - * register contents for one of both flow directions, but only if - * there is a previous instruction. - */ + ** register contents for one of both flow directions, but only if + ** there is a previous instruction. + */ if ((E->Info & OF_ZBRA) != 0 && (P = CS_GetPrevEntry (S, I)) != 0) { /* Get the branch condition */ @@ -1584,8 +1584,8 @@ void CS_GenRegInfo (CodeSeg* S) case OP65_CMP: /* If this is an immidiate compare, the A register has - * the value of the compare later. - */ + ** the value of the compare later. + */ if (CE_IsConstImm (P)) { if (BC == BC_EQ) { E->RI->Out2.RegA = (unsigned char)P->Num; @@ -1597,8 +1597,8 @@ void CS_GenRegInfo (CodeSeg* S) case OP65_CPX: /* If this is an immidiate compare, the X register has - * the value of the compare later. - */ + ** the value of the compare later. + */ if (CE_IsConstImm (P)) { if (BC == BC_EQ) { E->RI->Out2.RegX = (unsigned char)P->Num; @@ -1610,8 +1610,8 @@ void CS_GenRegInfo (CodeSeg* S) case OP65_CPY: /* If this is an immidiate compare, the Y register has - * the value of the compare later. - */ + ** the value of the compare later. + */ if (CE_IsConstImm (P)) { if (BC == BC_EQ) { E->RI->Out2.RegY = (unsigned char)P->Num; @@ -1648,9 +1648,9 @@ void CS_GenRegInfo (CodeSeg* S) case OP65_TAX: case OP65_TXA: /* If the branch is a beq, both A and X are zero at the - * branch target, otherwise they are zero at the next - * insn. - */ + ** branch target, otherwise they are zero at the next + ** insn. + */ if (BC == BC_EQ) { E->RI->Out2.RegA = E->RI->Out2.RegX = 0; } else { @@ -1661,9 +1661,9 @@ void CS_GenRegInfo (CodeSeg* S) case OP65_TAY: case OP65_TYA: /* If the branch is a beq, both A and Y are zero at the - * branch target, otherwise they are zero at the next - * insn. - */ + ** branch target, otherwise they are zero at the next + ** insn. + */ if (BC == BC_EQ) { E->RI->Out2.RegA = E->RI->Out2.RegY = 0; } else { @@ -1680,6 +1680,3 @@ void CS_GenRegInfo (CodeSeg* S) } while (!Done); } - - - diff --git a/src/cc65/codeseg.h b/src/cc65/codeseg.h index 125ad31c0..0d7367369 100644 --- a/src/cc65/codeseg.h +++ b/src/cc65/codeseg.h @@ -118,38 +118,38 @@ INLINE unsigned CS_GetEntryCount (const CodeSeg* S) void CS_InsertEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index); /* Insert the code entry at the index given. Following code entries will be - * moved to slots with higher indices. - */ +** moved to slots with higher indices. +*/ void CS_DelEntry (CodeSeg* S, unsigned Index); /* Delete an entry from the code segment. This includes moving any associated - * labels, removing references to labels and even removing the referenced labels - * if the reference count drops to zero. - * Note: Labels are moved forward if possible, that is, they are moved to the - * next insn (not the preceeding one). - */ +** labels, removing references to labels and even removing the referenced labels +** if the reference count drops to zero. +** Note: Labels are moved forward if possible, that is, they are moved to the +** next insn (not the preceeding one). +*/ void CS_DelEntries (CodeSeg* S, unsigned Start, unsigned Count); /* Delete a range of code entries. This includes removing references to labels, - * labels attached to the entries and so on. - */ +** labels attached to the entries and so on. +*/ void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos); /* Move a range of entries from one position to another. Start is the index - * of the first entry to move, Count is the number of entries and NewPos is - * the index of the target entry. The entry with the index Start will later - * have the index NewPos. All entries with indices NewPos and above are - * moved to higher indices. If the code block is moved to the end of the - * current code, and if pending labels exist, these labels will get attached - * to the first instruction of the moved block (the first one after the - * current code end) - */ +** of the first entry to move, Count is the number of entries and NewPos is +** the index of the target entry. The entry with the index Start will later +** have the index NewPos. All entries with indices NewPos and above are +** moved to higher indices. If the code block is moved to the end of the +** current code, and if pending labels exist, these labels will get attached +** to the first instruction of the moved block (the first one after the +** current code end) +*/ #if defined(HAVE_INLINE) INLINE void CS_MoveEntry (CodeSeg* S, unsigned OldPos, unsigned NewPos) /* Move an entry from one position to another. OldPos is the current position - * of the entry, NewPos is the new position of the entry. - */ +** of the entry, NewPos is the new position of the entry. +*/ { CollMove (&S->Entries, OldPos, NewPos); } @@ -169,34 +169,34 @@ INLINE struct CodeEntry* CS_GetEntry (CodeSeg* S, unsigned Index) struct CodeEntry* CS_GetPrevEntry (CodeSeg* S, unsigned Index); /* Get the code entry preceeding the one with the index Index. If there is no - * preceeding code entry, return NULL. - */ +** preceeding code entry, return NULL. +*/ struct CodeEntry* CS_GetNextEntry (CodeSeg* S, unsigned Index); /* Get the code entry following the one with the index Index. If there is no - * following code entry, return NULL. - */ +** following code entry, return NULL. +*/ int CS_GetEntries (CodeSeg* S, struct CodeEntry** List, unsigned Start, unsigned Count); /* Get Count code entries into List starting at index start. Return true if - * we got the lines, return false if not enough lines were available. - */ +** we got the lines, return false if not enough lines were available. +*/ unsigned CS_GetEntryIndex (CodeSeg* S, struct CodeEntry* E); /* Return the index of a code entry */ int CS_RangeHasLabel (CodeSeg* S, unsigned Start, unsigned Count); /* Return true if any of the code entries in the given range has a label - * attached. If the code segment does not span the given range, check the - * possible span instead. - */ +** attached. If the code segment does not span the given range, check the +** possible span instead. +*/ #if defined(HAVE_INLINE) INLINE int CS_HavePendingLabel (const CodeSeg* S) /* Return true if there are open labels that will get attached to the next - * instruction that is added. - */ +** instruction that is added. +*/ { return (CollCount (&S->Labels) > 0); } @@ -209,43 +209,43 @@ CodeLabel* CS_AddLabel (CodeSeg* S, const char* Name); CodeLabel* CS_GenLabel (CodeSeg* S, struct CodeEntry* E); /* If the code entry E does already have a label, return it. Otherwise - * create a new label, attach it to E and return it. - */ +** create a new label, attach it to E and return it. +*/ void CS_DelLabel (CodeSeg* S, CodeLabel* L); /* Remove references from this label and delete it. */ void CS_MergeLabels (CodeSeg* S); /* Merge code labels. That means: For each instruction, remove all labels but - * one and adjust references accordingly. - */ +** one and adjust references accordingly. +*/ void CS_MoveLabels (CodeSeg* S, struct CodeEntry* Old, struct CodeEntry* New); /* Move all labels from Old to New. The routine will move the labels itself - * if New does not have any labels, and move references if there is at least - * a label for new. If references are moved, the old label is deleted - * afterwards. - */ +** if New does not have any labels, and move references if there is at least +** a label for new. If references are moved, the old label is deleted +** afterwards. +*/ void CS_RemoveLabelRef (CodeSeg* S, struct CodeEntry* E); /* Remove the reference between E and the label it jumps to. The reference - * will be removed on both sides and E->JumpTo will be 0 after that. If - * the reference was the only one for the label, the label will get - * deleted. - */ +** will be removed on both sides and E->JumpTo will be 0 after that. If +** the reference was the only one for the label, the label will get +** deleted. +*/ void CS_MoveLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L); /* Change the reference of E to L instead of the current one. If this - * was the only reference to the old label, the old label will get - * deleted. - */ +** was the only reference to the old label, the old label will get +** deleted. +*/ void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last); /* Delete all entries between first and last, both inclusive. The function - * can only handle basic blocks (First is the only entry, Last the only exit) - * and no open labels. It will call FAIL if any of these preconditions are - * violated. - */ +** can only handle basic blocks (First is the only entry, Last the only exit) +** and no open labels. It will call FAIL if any of these preconditions are +** violated. +*/ void CS_DelCodeAfter (CodeSeg* S, unsigned Last); /* Delete all entries including the given one */ @@ -268,22 +268,22 @@ INLINE void CS_ResetAllMarks (CodeSeg* S) int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last); /* Check if the given code segment range is a basic block. That is, check if - * First is the only entrance and Last is the only exit. This means that no - * jump/branch inside the block may jump to an insn below First or after(!) - * Last, and that no insn may jump into this block from the outside. - */ +** First is the only entrance and Last is the only exit. This means that no +** jump/branch inside the block may jump to an insn below First or after(!) +** Last, and that no insn may jump into this block from the outside. +*/ void CS_OutputPrologue (const CodeSeg* S); /* If the given code segment is a code segment for a function, output the - * assembler prologue into the file. That is: Output a comment header, switch - * to the correct segment and enter the local function scope. If the code - * segment is global, do nothing. - */ +** assembler prologue into the file. That is: Output a comment header, switch +** to the correct segment and enter the local function scope. If the code +** segment is global, do nothing. +*/ void CS_OutputEpilogue (const CodeSeg* S); /* If the given code segment is a code segment for a function, output the - * assembler epilogue into the file. That is: Close the local function scope. - */ +** assembler epilogue into the file. That is: Close the local function scope. +*/ void CS_Output (CodeSeg* S); /* Output the code segment data to a file */ @@ -297,7 +297,5 @@ void CS_GenRegInfo (CodeSeg* S); /* End of codeseg.h */ + #endif - - - diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 17e9471b8..9f1ab29f5 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -141,14 +141,14 @@ static void Parse (void) } /* Check if we must reserve storage for the variable. We do this, - * - * - if it is not a typedef or function, - * - if we don't had a storage class given ("int i") - * - if the storage class is explicitly specified as static, - * - or if there is an initialization. - * - * This means that "extern int i;" will not get storage allocated. - */ + ** + ** - if it is not a typedef or function, + ** - if we don't had a storage class given ("int i") + ** - if the storage class is explicitly specified as static, + ** - or if there is an initialization. + ** + ** This means that "extern int i;" will not get storage allocated. + */ if ((Decl.StorageClass & SC_FUNC) != SC_FUNC && (Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF && ((Spec.Flags & DS_DEF_STORAGE) != 0 || @@ -161,10 +161,10 @@ static void Parse (void) } /* If this is a function declarator that is not followed by a comma - * or semicolon, it must be followed by a function body. If this is - * the case, convert an empty parameter list into one accepting no - * parameters (same as void) as required by the standard. - */ + ** or semicolon, it must be followed by a function body. If this is + ** the case, convert an empty parameter list into one accepting no + ** parameters (same as void) as required by the standard. + */ if ((Decl.StorageClass & SC_FUNC) != 0 && (CurTok.Tok != TOK_COMMA) && (CurTok.Tok != TOK_SEMI)) { @@ -191,8 +191,8 @@ static void Parse (void) if (CurTok.Tok == TOK_ASSIGN) { /* We cannot initialize types of unknown size, or - * void types in non ANSI mode. - */ + ** void types in ISO modes. + */ if (Size == 0) { if (!IsTypeVoid (Decl.Type)) { if (!IsTypeArray (Decl.Type)) { @@ -206,9 +206,9 @@ static void Parse (void) } /* Switch to the data or rodata segment. For arrays, check - * the element qualifiers, since not the array but its - * elements are const. - */ + ** the element qualifiers, since not the array but its + ** elements are const. + */ if (IsQualConst (GetBaseElementType (Decl.Type))) { g_userodata (); } else { @@ -303,8 +303,8 @@ void Compile (const char* FileName) struct tm* TM; /* Since strftime is locale dependent, we need the abbreviated month names - * in english. - */ + ** in english. + */ static const char MonthNames[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" @@ -320,9 +320,9 @@ void Compile (const char* FileName) DefineNumericMacro ("__CC65_STD__", IS_Get (&Standard)); /* Optimization macros. Since no source code has been parsed for now, the - * IS_Get functions access the values in effect now, regardless of any - * changes using #pragma later. - */ + ** IS_Get functions access the values in effect now, regardless of any + ** changes using #pragma later. + */ if (IS_Get (&Optimize)) { long CodeSize = IS_Get (&CodeSizeFactor); DefineNumericMacro ("__OPT__", 1); @@ -428,6 +428,3 @@ void FinishCompile (void) /* Leave the main lexical level */ LeaveGlobalLevel (); } - - - diff --git a/src/cc65/compile.h b/src/cc65/compile.h index 74e294efe..2d15c8200 100644 --- a/src/cc65/compile.h +++ b/src/cc65/compile.h @@ -55,6 +55,3 @@ void FinishCompile (void); /* End of compile.h */ #endif - - - diff --git a/src/cc65/coptadd.c b/src/cc65/coptadd.c index fe050cef6..07bd2bf98 100644 --- a/src/cc65/coptadd.c +++ b/src/cc65/coptadd.c @@ -51,29 +51,29 @@ unsigned OptAdd1 (CodeSeg* S) /* Search for the sequence - * - * ldy #xx - * jsr ldaxysp - * jsr pushax - * ldy #yy - * jsr ldaxysp - * jsr tosaddax - * - * and replace it by: - * - * ldy #xx-1 - * lda (sp),y - * ldy #yy-3 - * clc - * adc (sp),y - * pha - * ldy #xx - * lda (sp),y - * ldy #yy-2 - * adc (sp),y - * tax - * pla - */ +** +** ldy #xx +** jsr ldaxysp +** jsr pushax +** ldy #yy +** jsr ldaxysp +** jsr tosaddax +** +** and replace it by: +** +** ldy #xx-1 +** lda (sp),y +** ldy #yy-3 +** clc +** adc (sp),y +** pha +** ldy #xx +** lda (sp),y +** ldy #yy-2 +** adc (sp),y +** tax +** pla +*/ { unsigned Changes = 0; @@ -172,28 +172,28 @@ unsigned OptAdd1 (CodeSeg* S) unsigned OptAdd2 (CodeSeg* S) /* Search for the sequence - * - * ldy #xx - * jsr ldaxysp - * ldy #yy - * jsr addeqysp - * - * and replace it by: - * - * ldy #xx-1 - * lda (sp),y - * ldy #yy - * clc - * adc (sp),y - * sta (sp),y - * ldy #xx - * lda (sp),y - * ldy #yy+1 - * adc (sp),y - * sta (sp),y - * - * provided that a/x is not used later. - */ +** +** ldy #xx +** jsr ldaxysp +** ldy #yy +** jsr addeqysp +** +** and replace it by: +** +** ldy #xx-1 +** lda (sp),y +** ldy #yy +** clc +** adc (sp),y +** sta (sp),y +** ldy #xx +** lda (sp),y +** ldy #yy+1 +** adc (sp),y +** sta (sp),y +** +** provided that a/x is not used later. +*/ { unsigned Changes = 0; @@ -288,20 +288,20 @@ unsigned OptAdd2 (CodeSeg* S) unsigned OptAdd3 (CodeSeg* S) /* Search for the sequence - * - * jsr pushax - * ldx #$00 - * lda xxx - * jsr tosaddax - * - * and replace it by - * - * clc - * adc xxx - * bcc L1 - * inx - * L1: - */ +** +** jsr pushax +** ldx #$00 +** lda xxx +** jsr tosaddax +** +** and replace it by +** +** clc +** adc xxx +** bcc L1 +** inx +** L1: +*/ { unsigned Changes = 0; @@ -364,22 +364,22 @@ unsigned OptAdd3 (CodeSeg* S) unsigned OptAdd4 (CodeSeg* S) /* Search for the sequence - * - * jsr pushax - * lda xxx - * ldx yyy - * jsr tosaddax - * - * and replace it by - * - * clc - * adc xxx - * pha - * txa - * adc yyy - * tax - * pla - */ +** +** jsr pushax +** lda xxx +** ldx yyy +** jsr tosaddax +** +** and replace it by +** +** clc +** adc xxx +** pha +** txa +** adc yyy +** tax +** pla +*/ { unsigned Changes = 0; @@ -453,8 +453,8 @@ unsigned OptAdd4 (CodeSeg* S) unsigned OptAdd5 (CodeSeg* S) /* Search for a call to incaxn and replace it by an 8 bit add if the X register - * is not used later. - */ +** is not used later. +*/ { unsigned Changes = 0; @@ -506,14 +506,14 @@ unsigned OptAdd5 (CodeSeg* S) unsigned OptAdd6 (CodeSeg* S) /* Search for the sequence - * - * adc ... - * bcc L - * inx - * L: - * - * and remove the handling of the high byte if X is not used later. - */ +** +** adc ... +** bcc L +** inx +** L: +** +** and remove the handling of the high byte if X is not used later. +*/ { unsigned Changes = 0; @@ -553,6 +553,3 @@ unsigned OptAdd6 (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptadd.h b/src/cc65/coptadd.h index f89ad016e..e4df3b304 100644 --- a/src/cc65/coptadd.h +++ b/src/cc65/coptadd.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2001-2005, Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -51,108 +51,105 @@ unsigned OptAdd1 (CodeSeg* S); /* Search for the sequence - * - * jsr pushax - * ldy xxx - * ldx #$00 - * lda (sp),y - * jsr tosaddax - * - * and replace it by: - * - * ldy xxx-2 - * clc - * adc (sp),y - * bcc L - * inx - * L: - */ +** +** jsr pushax +** ldy xxx +** ldx #$00 +** lda (sp),y +** jsr tosaddax +** +** and replace it by: +** +** ldy xxx-2 +** clc +** adc (sp),y +** bcc L +** inx +** L: +*/ unsigned OptAdd2 (CodeSeg* S); /* Search for the sequence - * - * ldy #xx - * lda (sp),y - * tax - * dey - * lda (sp),y - * ldy #$yy - * jsr addeqysp - * - * and replace it by: - * - * ldy #xx-1 - * lda (sp),y - * ldy #yy - * clc - * adc (sp),y - * sta (sp),y - * ldy #xx - * lda (sp),y - * ldy #yy+1 - * adc (sp),y - * sta (sp),y - * - * provided that a/x is not used later. - */ +** +** ldy #xx +** lda (sp),y +** tax +** dey +** lda (sp),y +** ldy #$yy +** jsr addeqysp +** +** and replace it by: +** +** ldy #xx-1 +** lda (sp),y +** ldy #yy +** clc +** adc (sp),y +** sta (sp),y +** ldy #xx +** lda (sp),y +** ldy #yy+1 +** adc (sp),y +** sta (sp),y +** +** provided that a/x is not used later. +*/ unsigned OptAdd3 (CodeSeg* S); /* Search for the sequence - * - * jsr pushax - * ldx #$00 - * lda xxx - * jsr tosaddax - * - * and replace it by - * - * clc - * adc xxx - * bcc L1 - * inx - * L1: - */ +** +** jsr pushax +** ldx #$00 +** lda xxx +** jsr tosaddax +** +** and replace it by +** +** clc +** adc xxx +** bcc L1 +** inx +** L1: +*/ unsigned OptAdd4 (CodeSeg* S); /* Search for the sequence - * - * jsr pushax - * lda xxx - * ldx yyy - * jsr tosaddax - * - * and replace it by - * - * clc - * adc xxx - * pha - * txa - * adc yyy - * tax - * pla - */ +** +** jsr pushax +** lda xxx +** ldx yyy +** jsr tosaddax +** +** and replace it by +** +** clc +** adc xxx +** pha +** txa +** adc yyy +** tax +** pla +*/ unsigned OptAdd5 (CodeSeg* S); /* Search for a call to incaxn and replace it by an 8 bit add if the X register - * is not used later. - */ +** is not used later. +*/ unsigned OptAdd6 (CodeSeg* S); /* Search for the sequence - * - * adc ... - * bcc L - * inx - * L: - * - * and remove the handling of the high byte if X is not used later. - */ +** +** adc ... +** bcc L +** inx +** L: +** +** and remove the handling of the high byte if X is not used later. +*/ /* End of coptadd.h */ #endif - - - diff --git a/src/cc65/coptc02.c b/src/cc65/coptc02.c index 969f9fd6e..71da5effa 100644 --- a/src/cc65/coptc02.c +++ b/src/cc65/coptc02.c @@ -75,9 +75,9 @@ unsigned Opt65C02Ind (CodeSeg* S) CodeEntry* E = CS_GetEntry (S, I); /* Check for addressing mode indirect indexed Y where Y is zero. - * Note: All opcodes that are available as (zp),y are also available - * as (zp), so we can ignore the actual opcode here. - */ + ** Note: All opcodes that are available as (zp),y are also available + ** as (zp), so we can ignore the actual opcode here. + */ if (E->AM == AM65_ZP_INDY && E->RI->In.RegY == 0) { /* Replace it by indirect addressing mode */ @@ -187,8 +187,8 @@ unsigned Opt65C02Stores (CodeSeg* S) CodeEntry* E = CS_GetEntry (S, I); /* Check for a store with a register value of zero and an addressing - * mode available with STZ. - */ + ** mode available with STZ. + */ if (((E->OPC == OP65_STA && E->RI->In.RegA == 0) || (E->OPC == OP65_STX && E->RI->In.RegX == 0) || (E->OPC == OP65_STY && E->RI->In.RegY == 0)) && @@ -214,6 +214,3 @@ unsigned Opt65C02Stores (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptc02.h b/src/cc65/coptc02.h index 7d010568b..205669376 100644 --- a/src/cc65/coptc02.h +++ b/src/cc65/coptc02.h @@ -61,7 +61,5 @@ unsigned Opt65C02Stores (CodeSeg* S); /* End of coptc02.h */ + #endif - - - diff --git a/src/cc65/coptcmp.c b/src/cc65/coptcmp.c index e1b80a71c..9e9c20502 100644 --- a/src/cc65/coptcmp.c +++ b/src/cc65/coptcmp.c @@ -66,11 +66,11 @@ static const unsigned char CmpInvertTab [] = { static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond) /* Helper function for the replacement of routines that return a boolean - * followed by a conditional jump. Instead of the boolean value, the condition - * codes are evaluated directly. - * I is the index of the conditional branch, the sequence is already checked - * to be correct. - */ +** followed by a conditional jump. Instead of the boolean value, the condition +** codes are evaluated directly. +** I is the index of the conditional branch, the sequence is already checked +** to be correct. +*/ { CodeEntry* N; CodeLabel* L; @@ -91,10 +91,10 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond) case CMP_GT: /* Replace by - * beq @L - * jpl Target - * @L: ... - */ + ** beq @L + ** jpl Target + ** @L: ... + */ if ((N = CS_GetNextEntry (S, I)) == 0) { /* No such entry */ Internal ("Invalid program flow"); @@ -115,9 +115,9 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond) case CMP_LE: /* Replace by - * jmi Target - * jeq Target - */ + ** jmi Target + ** jeq Target + */ CE_ReplaceOPC (E, OP65_JMI); L = E->JumpTo; N = NewCodeEntry (OP65_JEQ, AM65_BRA, L->Name, L, E->LI); @@ -126,10 +126,10 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond) case CMP_UGT: /* Replace by - * beq @L - * jcs Target - * @L: ... - */ + ** beq @L + ** jcs Target + ** @L: ... + */ if ((N = CS_GetNextEntry (S, I)) == 0) { /* No such entry */ Internal ("Invalid program flow"); @@ -150,9 +150,9 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond) case CMP_ULE: /* Replace by - * jcc Target - * jeq Target - */ + ** jcc Target + ** jeq Target + */ CE_ReplaceOPC (E, OP65_JCC); L = E->JumpTo; N = NewCodeEntry (OP65_JEQ, AM65_BRA, L->Name, L, E->LI); @@ -169,10 +169,10 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond) static int IsImmCmp16 (CodeEntry** L) -/* Check if the instructions at L are an immidiate compare of a/x: - * - * - */ +/* Check if the instructions at L are an immediate compare of a/x: +** +** +*/ { return (L[0]->OPC == OP65_CPX && L[0]->AM == AM65_IMM && @@ -213,8 +213,8 @@ static int GetCmpRegVal (const CodeEntry* E) unsigned OptBoolTrans (CodeSeg* S) /* Try to remove the call to boolean transformer routines where the call is - * not really needed. - */ +** not really needed. +*/ { unsigned Changes = 0; @@ -235,11 +235,11 @@ unsigned OptBoolTrans (CodeSeg* S) (N->Info & OF_ZBRA) != 0) { /* Make the boolean transformer unnecessary by changing the - * the conditional jump to evaluate the condition flags that - * are set after the compare directly. Note: jeq jumps if - * the condition is not met, jne jumps if the condition is met. - * Invert the code if we jump on condition not met. - */ + ** the conditional jump to evaluate the condition flags that + ** are set after the compare directly. Note: jeq jumps if + ** the condition is not met, jne jumps if the condition is met. + ** Invert the code if we jump on condition not met. + */ if (GetBranchCond (N->OPC) == BC_EQ) { /* Jumps if condition false, invert condition */ Cond = CmpInvertTab [Cond]; @@ -275,15 +275,15 @@ unsigned OptBoolTrans (CodeSeg* S) unsigned OptCmp1 (CodeSeg* S) /* Search for the sequence - * - * ldx xx - * stx tmp1 - * ora tmp1 - * - * and replace it by - * - * ora xx - */ +** +** ldx xx +** stx tmp1 +** ora tmp1 +** +** and replace it by +** +** ora xx +*/ { unsigned Changes = 0; @@ -332,16 +332,16 @@ unsigned OptCmp1 (CodeSeg* S) unsigned OptCmp2 (CodeSeg* S) /* Search for the sequence - * - * stx xx - * stx tmp1 - * ora tmp1 - * - * and replace it by - * - * stx xx - * ora xx - */ +** +** stx xx +** stx tmp1 +** ora tmp1 +** +** and replace it by +** +** stx xx +** ora xx +*/ { unsigned Changes = 0; @@ -387,17 +387,17 @@ unsigned OptCmp2 (CodeSeg* S) unsigned OptCmp3 (CodeSeg* S) /* Search for - * - * lda/and/ora/eor ... - * cmp #$00 - * jeq/jne - * or - * lda/and/ora/eor ... - * cmp #$00 - * jsr boolxx - * - * and remove the cmp. - */ +** +** lda/and/ora/eor ... +** cmp #$00 +** jeq/jne +** or +** lda/and/ora/eor ... +** cmp #$00 +** jsr boolxx +** +** and remove the cmp. +*/ { unsigned Changes = 0; @@ -432,9 +432,9 @@ unsigned OptCmp3 (CodeSeg* S) int Delete = 0; /* Check for the call to boolxx. We only remove the compare if - * the carry flag is not evaluated later, because the load will - * not set the carry flag. - */ + ** the carry flag is not evaluated later, because the load will + ** not set the carry flag. + */ if (L[2]->OPC == OP65_JSR) { switch (FindBoolCmpCond (L[2]->Arg)) { @@ -459,10 +459,10 @@ unsigned OptCmp3 (CodeSeg* S) } else if ((L[2]->Info & OF_FBRA) != 0) { /* The following insn branches on the condition of the load, - * so the compare instruction might be removed. For safety, - * do some more checks if the carry isn't used later, since - * the compare does set the carry, but the load does not. - */ + ** so the compare instruction might be removed. For safety, + ** do some more checks if the carry isn't used later, since + ** the compare does set the carry, but the load does not. + */ CodeEntry* E; CodeEntry* N; if ((E = CS_GetNextEntry (S, I+2)) != 0 && @@ -476,9 +476,9 @@ unsigned OptCmp3 (CodeSeg* S) FindBoolCmpCond (N->Arg) == CMP_INV)) { /* The following insn branches on the condition of a load, - * and there's no use of the carry flag in sight, so the - * compare instruction can be removed. - */ + ** and there's no use of the carry flag in sight, so the + ** compare instruction can be removed. + */ Delete = 1; } } @@ -503,24 +503,24 @@ unsigned OptCmp3 (CodeSeg* S) unsigned OptCmp4 (CodeSeg* S) /* Search for - * - * lda x - * ldx y - * cpx #a - * bne L1 - * cmp #b - * L1: jne/jeq L2 - * - * If a is zero, we may remove the compare. If a and b are both zero, we may - * replace it by the sequence - * - * lda x - * ora x+1 - * jne/jeq ... - * - * L1 may be either the label at the branch instruction, or the target label - * of this instruction. - */ +** +** lda x +** ldx y +** cpx #a +** bne L1 +** cmp #b +** L1: jne/jeq L2 +** +** If a is zero, we may remove the compare. If a and b are both zero, we may +** replace it by the sequence +** +** lda x +** ora x+1 +** jne/jeq ... +** +** L1 may be either the label at the branch instruction, or the target label +** of this instruction. +*/ { unsigned Changes = 0; @@ -547,9 +547,9 @@ unsigned OptCmp4 (CodeSeg* S) CS_DelEntries (S, I+2, 3); } else { /* Move the lda instruction after the first branch. This will - * improve speed, since the load is delayed after the first - * test. - */ + ** improve speed, since the load is delayed after the first + ** test. + */ CS_MoveEntry (S, I, I+4); /* We will replace the ldx/cpx by lda/cmp */ @@ -557,8 +557,8 @@ unsigned OptCmp4 (CodeSeg* S) CE_ReplaceOPC (L[1], OP65_CMP); /* Beware: If the first LDA instruction had a label, we have - * to move this label to the top of the sequence again. - */ + ** to move this label to the top of the sequence again. + */ if (CE_HasLabel (E)) { CS_MoveLabels (S, E, L[0]); } @@ -581,14 +581,14 @@ unsigned OptCmp4 (CodeSeg* S) unsigned OptCmp5 (CodeSeg* S) /* Optimize compares of local variables: - * - * ldy #o - * jsr ldaxysp - * cpx #a - * bne L1 - * cmp #b - * jne/jeq L2 - */ +** +** ldy #o +** jsr ldaxysp +** cpx #a +** bne L1 +** cmp #b +** jne/jeq L2 +*/ { unsigned Changes = 0; @@ -615,12 +615,12 @@ unsigned OptCmp5 (CodeSeg* S) char Buf[20]; /* The value is zero, we may use the simple code version: - * ldy #o-1 - * lda (sp),y - * ldy #o - * ora (sp),y - * jne/jeq ... - */ + ** ldy #o-1 + ** lda (sp),y + ** ldy #o + ** ora (sp),y + ** jne/jeq ... + */ sprintf (Buf, "$%02X", (int)(L[0]->Num-1)); X = NewCodeEntry (OP65_LDY, AM65_IMM, Buf, 0, L[0]->LI); CS_InsertEntry (S, X, I+1); @@ -643,17 +643,17 @@ unsigned OptCmp5 (CodeSeg* S) char Buf[20]; /* Change the code to just use the A register. Move the load - * of the low byte after the first branch if possible: - * - * ldy #o - * lda (sp),y - * cmp #a - * bne L1 - * ldy #o-1 - * lda (sp),y - * cmp #b - * jne/jeq ... - */ + ** of the low byte after the first branch if possible: + ** + ** ldy #o + ** lda (sp),y + ** cmp #a + ** bne L1 + ** ldy #o-1 + ** lda (sp),y + ** cmp #b + ** jne/jeq ... + */ X = NewCodeEntry (OP65_LDY, AM65_IMM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+3); @@ -690,10 +690,10 @@ unsigned OptCmp5 (CodeSeg* S) unsigned OptCmp6 (CodeSeg* S) /* Search for calls to compare subroutines followed by a conditional branch - * and replace them by cheaper versions, since the branch means that the - * boolean value returned by these routines is not needed (we may also check - * that explicitly, but for the current code generator it is always true). - */ +** and replace them by cheaper versions, since the branch means that the +** boolean value returned by these routines is not needed (we may also check +** that explicitly, but for the current code generator it is always true). +*/ { unsigned Changes = 0; @@ -715,12 +715,12 @@ unsigned OptCmp6 (CodeSeg* S) !CE_HasLabel (N)) { /* The tos... functions will return a boolean value in a/x and - * the Z flag says if this value is zero or not. We will call - * a cheaper subroutine instead, one that does not return a - * boolean value but only valid flags. Note: jeq jumps if - * the condition is not met, jne jumps if the condition is met. - * Invert the code if we jump on condition not met. - */ + ** the Z flag says if this value is zero or not. We will call + ** a cheaper subroutine instead, one that does not return a + ** boolean value but only valid flags. Note: jeq jumps if + ** the condition is not met, jne jumps if the condition is met. + ** Invert the code if we jump on condition not met. + */ if (GetBranchCond (N->OPC) == BC_EQ) { /* Jumps if condition false, invert condition */ Cond = CmpInvertTab [Cond]; @@ -752,8 +752,8 @@ unsigned OptCmp6 (CodeSeg* S) unsigned OptCmp7 (CodeSeg* S) /* Search for a sequence ldx/txa/branch and remove the txa if A is not - * used later. - */ +** used later. +*/ { unsigned Changes = 0; @@ -796,8 +796,8 @@ unsigned OptCmp7 (CodeSeg* S) unsigned OptCmp8 (CodeSeg* S) /* Check for register compares where the contents of the register and therefore - * the result of the compare is known. - */ +** the result of the compare is known. +*/ { unsigned Changes = 0; unsigned I; @@ -817,8 +817,8 @@ unsigned OptCmp8 (CodeSeg* S) CE_IsConstImm (E)) { /* We are able to evaluate the compare at compile time. Check if - * one or more branches are ahead. - */ + ** one or more branches are ahead. + */ unsigned JumpsChanged = 0; CodeEntry* N; while ((N = CS_GetNextEntry (S, I)) != 0 && /* Followed by something.. */ @@ -855,10 +855,10 @@ unsigned OptCmp8 (CodeSeg* S) case BC_VC: case BC_VS: /* Not set by the compare operation, bail out (Note: - * Just skipping anything here is rather stupid, but - * the sequence is never generated by the compiler, - * so it's quite safe to skip). - */ + ** Just skipping anything here is rather stupid, but + ** the sequence is never generated by the compiler, + ** so it's quite safe to skip). + */ goto NextEntry; default: @@ -867,9 +867,9 @@ unsigned OptCmp8 (CodeSeg* S) } /* If the condition is false, we may remove the jump. Otherwise - * the branch will always be taken, so we may replace it by a - * jump (and bail out). - */ + ** the branch will always be taken, so we may replace it by a + ** jump (and bail out). + */ if (!Cond) { CS_DelEntry (S, I+1); } else { @@ -906,16 +906,16 @@ NextEntry: unsigned OptCmp9 (CodeSeg* S) /* Search for the sequence - * - * sbc xx - * bvs/bvc L - * eor #$80 - * L: asl a - * bcc/bcs somewhere - * - * If A is not used later (which should be the case), we can branch on the N - * flag instead of the carry flag and remove the asl. - */ +** +** sbc xx +** bvs/bvc L +** eor #$80 +** L: asl a +** bcc/bcs somewhere +** +** If A is not used later (which should be the case), we can branch on the N +** flag instead of the carry flag and remove the asl. +*/ { unsigned Changes = 0; unsigned I; @@ -971,6 +971,3 @@ unsigned OptCmp9 (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptcmp.h b/src/cc65/coptcmp.h index d54b8f5c6..0cdcf2d3d 100644 --- a/src/cc65/coptcmp.h +++ b/src/cc65/coptcmp.h @@ -51,8 +51,8 @@ unsigned OptBoolTrans (CodeSeg* S); /* Try to remove the call to boolean transformer routines where the call is - * not really needed. - */ +** not really needed. +*/ @@ -64,113 +64,110 @@ unsigned OptBoolTrans (CodeSeg* S); unsigned OptCmp1 (CodeSeg* S); /* Search for the sequence - * - * ldx xx - * stx tmp1 - * ora tmp1 - * - * and replace it by - * - * ora xx - */ +** +** ldx xx +** stx tmp1 +** ora tmp1 +** +** and replace it by +** +** ora xx +*/ unsigned OptCmp2 (CodeSeg* S); /* Search for the sequence - * - * stx xx - * stx tmp1 - * ora tmp1 - * - * and replace it by - * - * stx xx - * ora xx - */ +** +** stx xx +** stx tmp1 +** ora tmp1 +** +** and replace it by +** +** stx xx +** ora xx +*/ unsigned OptCmp3 (CodeSeg* S); /* Search for - * - * lda/and/ora/eor ... - * cmp #$00 - * jeq/jne - * or - * lda/and/ora/eor ... - * cmp #$00 - * jsr boolxx - * - * and remove the cmp. - */ +** +** lda/and/ora/eor ... +** cmp #$00 +** jeq/jne +** or +** lda/and/ora/eor ... +** cmp #$00 +** jsr boolxx +** +** and remove the cmp. +*/ unsigned OptCmp4 (CodeSeg* S); /* Search for - * - * lda x - * ldx y - * cpx #a - * bne L1 - * cmp #b - * jne/jeq L2 - * - * If a is zero, we may remove the compare. If a and b are both zero, we may - * replace it by the sequence - * - * lda x - * ora x+1 - * jne/jeq ... - * - * L1 may be either the label at the branch instruction, or the target label - * of this instruction. - */ +** +** lda x +** ldx y +** cpx #a +** bne L1 +** cmp #b +** jne/jeq L2 +** +** If a is zero, we may remove the compare. If a and b are both zero, we may +** replace it by the sequence +** +** lda x +** ora x+1 +** jne/jeq ... +** +** L1 may be either the label at the branch instruction, or the target label +** of this instruction. +*/ unsigned OptCmp5 (CodeSeg* S); /* Optimize compares of local variables: - * - * ldy #o - * lda (sp),y - * tax - * dey - * lda (sp),y - * cpx #a - * bne L1 - * cmp #b - * jne/jeq L2 - */ +** +** ldy #o +** lda (sp),y +** tax +** dey +** lda (sp),y +** cpx #a +** bne L1 +** cmp #b +** jne/jeq L2 +*/ unsigned OptCmp6 (CodeSeg* S); /* Search for calls to compare subroutines followed by a conditional branch - * and replace them by cheaper versions, since the branch means that the - * boolean value returned by these routines is not needed (we may also check - * that explicitly, but for the current code generator it is always true). - */ +** and replace them by cheaper versions, since the branch means that the +** boolean value returned by these routines is not needed (we may also check +** that explicitly, but for the current code generator it is always true). +*/ unsigned OptCmp7 (CodeSeg* S); /* Search for a sequence ldx/txa/branch and remove the txa if A is not - * used later. - */ +** used later. +*/ unsigned OptCmp8 (CodeSeg* S); /* Check for register compares where the contents of the register and therefore - * the result of the compare is known. - */ +** the result of the compare is known. +*/ unsigned OptCmp9 (CodeSeg* S); /* Search for the sequence - * - * sbc xx - * bvs/bvc L - * eor #$80 - * L: asl a - * bcc/bcs somewhere - * - * If A is not used later (which should be the case), we can branch on the N - * flag instead of the carry flag and remove the asl. - */ +** +** sbc xx +** bvs/bvc L +** eor #$80 +** L: asl a +** bcc/bcs somewhere +** +** If A is not used later (which should be the case), we can branch on the N +** flag instead of the carry flag and remove the asl. +*/ /* End of coptcmp.h */ #endif - - - diff --git a/src/cc65/coptind.c b/src/cc65/coptind.c index 14f64590e..ca9d5effd 100644 --- a/src/cc65/coptind.c +++ b/src/cc65/coptind.c @@ -66,15 +66,15 @@ static int MemAccess (CodeSeg* S, unsigned From, unsigned To, const CodeEntry* N /* If the argument of N is a zero page location that ends with "+1", we - * must also check for word accesses to the location without +1. - */ + ** must also check for word accesses to the location without +1. + */ if (N->AM == AM65_ZP && NLen > 2 && strcmp (N->Arg + NLen - 2, "+1") == 0) { What |= Base; } /* If the argument is zero page indirect, we must also check for accesses - * to "arg+1" - */ + ** to "arg+1" + */ if (N->AM == AM65_ZP_INDY || N->AM == AM65_ZPX_IND || N->AM == AM65_ZP_IND) { What |= Word; } @@ -86,8 +86,8 @@ static int MemAccess (CodeSeg* S, unsigned From, unsigned To, const CodeEntry* N CodeEntry* E = CS_GetEntry (S, From); /* Check if there is an argument and if this argument equals Arg in - * some variants. - */ + ** some variants. + */ if (E->Arg[0] != '\0') { unsigned ELen; @@ -126,8 +126,8 @@ static int MemAccess (CodeSeg* S, unsigned From, unsigned To, const CodeEntry* N static int GetBranchDist (CodeSeg* S, unsigned From, CodeEntry* To) /* Get the branch distance between the two entries and return it. The distance - * will be negative for backward jumps and positive for forward jumps. - */ +** will be negative for backward jumps and positive for forward jumps. +*/ { /* Get the index of the branch target */ unsigned TI = CS_GetEntryIndex (S, To); @@ -265,8 +265,8 @@ unsigned OptRTSJumps2 (CodeSeg* S) /* Get the jump target and the next entry. There's always a next - * entry, because we don't cover the last entry in the loop. - */ + ** entry, because we don't cover the last entry in the loop. + */ CodeEntry* X = 0; CodeEntry* T = E->JumpTo->Owner; CodeEntry* N = CS_GetNextEntry (S, I); @@ -275,15 +275,15 @@ unsigned OptRTSJumps2 (CodeSeg* S) if (T->OPC == OP65_RTS) { /* It's a jump to RTS. Create a conditional branch around an - * RTS insn. - */ + ** RTS insn. + */ X = NewCodeEntry (OP65_RTS, AM65_IMP, 0, 0, T->LI); } else if (T->OPC == OP65_JMP && T->JumpTo == 0) { /* It's a jump to a label outside the function. Create a - * conditional branch around a jump to the external label. - */ + ** conditional branch around a jump to the external label. + */ X = NewCodeEntry (OP65_JMP, AM65_ABS, T->Arg, T->JumpTo, T->LI); } @@ -298,8 +298,8 @@ unsigned OptRTSJumps2 (CodeSeg* S) CS_InsertEntry (S, X, I+1); /* Create a conditional branch with the inverse condition - * around the replacement insn - */ + ** around the replacement insn + */ /* Get the new branch opcode */ NewBranch = MakeShortBranch (GetInverseBranch (E->OPC)); @@ -350,8 +350,8 @@ unsigned OptDeadJumps (CodeSeg* S) CodeEntry* E = CS_GetEntry (S, I); /* Check if it's a branch, if it has a local target, and if the target - * is the next instruction. - */ + ** is the next instruction. + */ if (E->AM == AM65_BRA && E->JumpTo && E->JumpTo->Owner == CS_GetNextEntry (S, I)) { @@ -384,8 +384,8 @@ unsigned OptDeadJumps (CodeSeg* S) unsigned OptDeadCode (CodeSeg* S) /* Remove dead code (code that follows an unconditional jump or an rts/rti - * and has no label) - */ +** and has no label) +*/ { unsigned Changes = 0; @@ -400,9 +400,9 @@ unsigned OptDeadCode (CodeSeg* S) CodeEntry* E = CS_GetEntry (S, I); /* Check if it's an unconditional branch, and if the next entry has - * no labels attached, or if the label is just used so that the insn - * can jump to itself. - */ + ** no labels attached, or if the label is just used so that the insn + ** can jump to itself. + */ if ((E->Info & OF_DEAD) != 0 && /* Dead code follows */ (N = CS_GetNextEntry (S, I)) != 0 && /* Has next entry */ (!CE_HasLabel (N) || /* Don't has a label */ @@ -439,11 +439,11 @@ unsigned OptDeadCode (CodeSeg* S) unsigned OptJumpCascades (CodeSeg* S) /* Optimize jump cascades (jumps to jumps). In such a case, the jump is - * replaced by a jump to the final location. This will in some cases produce - * worse code, because some jump targets are no longer reachable by short - * branches, but this is quite rare, so there are more advantages than - * disadvantages. - */ +** replaced by a jump to the final location. This will in some cases produce +** worse code, because some jump targets are no longer reachable by short +** branches, but this is quite rare, so there are more advantages than +** disadvantages. +*/ { unsigned Changes = 0; @@ -458,17 +458,17 @@ unsigned OptJumpCascades (CodeSeg* S) CodeEntry* E = CS_GetEntry (S, I); /* Check: - * - if it's a branch, - * - if it has a jump label, - * - if this jump label is not attached to the instruction itself, - * - if the target instruction is itself a branch, - * - if either the first branch is unconditional or the target of - * the second branch is internal to the function. - * The latter condition will avoid conditional branches to targets - * outside of the function (usually incspx), which won't simplify the - * code, since conditional far branches are emulated by a short branch - * around a jump. - */ + ** - if it's a branch, + ** - if it has a jump label, + ** - if this jump label is not attached to the instruction itself, + ** - if the target instruction is itself a branch, + ** - if either the first branch is unconditional or the target of + ** the second branch is internal to the function. + ** The latter condition will avoid conditional branches to targets + ** outside of the function (usually incspx), which won't simplify the + ** code, since conditional far branches are emulated by a short branch + ** around a jump. + */ if ((E->Info & OF_BRA) != 0 && (OldLabel = E->JumpTo) != 0 && (N = OldLabel->Owner) != E && @@ -476,27 +476,27 @@ unsigned OptJumpCascades (CodeSeg* S) ((E->Info & OF_CBRA) == 0 || N->JumpTo != 0)) { - /* Check if we can use the final target label. This is the case, - * if the target branch is an absolut branch, or if it is a - * conditional branch checking the same condition as the first one. - */ + /* Check if we can use the final target label. That is the case, + ** if the target branch is an absolute branch; or, if it is a + ** conditional branch checking the same condition as the first one. + */ if ((N->Info & OF_UBRA) != 0 || ((E->Info & OF_CBRA) != 0 && GetBranchCond (E->OPC) == GetBranchCond (N->OPC))) { /* This is a jump cascade and we may jump to the final target, - * provided that the other insn does not jump to itself. If - * this is the case, we can also jump to ourselves, otherwise - * insert a jump to the new instruction and remove the old one. - */ + ** provided that the other insn does not jump to itself. If + ** this is the case, we can also jump to ourselves, otherwise + ** insert a jump to the new instruction and remove the old one. + */ CodeEntry* X; CodeLabel* LN = N->JumpTo; if (LN != 0 && LN->Owner == N) { /* We found a jump to a jump to itself. Replace our jump - * by a jump to itself. - */ + ** by a jump to itself. + */ CodeLabel* LE = CS_GenLabel (S, E); X = NewCodeEntry (E->OPC, E->AM, LE->Name, LE, E->LI); @@ -517,10 +517,10 @@ unsigned OptJumpCascades (CodeSeg* S) ++Changes; /* Check if both are conditional branches, and the condition of - * the second is the inverse of that of the first. In this case, - * the second branch will never be taken, and we may jump directly - * to the instruction behind this one. - */ + ** the second is the inverse of that of the first. In this case, + ** the second branch will never be taken, and we may jump directly + ** to the instruction behind this one. + */ } else if ((E->Info & OF_CBRA) != 0 && (N->Info & OF_CBRA) != 0) { CodeEntry* X; /* Instruction behind N */ @@ -537,8 +537,8 @@ unsigned OptJumpCascades (CodeSeg* S) } /* We may jump behind this conditional branch. Get the - * pointer to the next instruction - */ + ** pointer to the next instruction + */ if ((X = CS_GetNextEntry (S, CS_GetEntryIndex (S, N))) == 0) { /* N is the last entry, bail out */ goto NextEntry; @@ -575,9 +575,9 @@ NextEntry: unsigned OptRTS (CodeSeg* S) /* Optimize subroutine calls followed by an RTS. The subroutine call will get - * replaced by a jump. Don't bother to delete the RTS if it does not have a - * label, the dead code elimination should take care of it. - */ +** replaced by a jump. Don't bother to delete the RTS if it does not have a +** label, the dead code elimination should take care of it. +*/ { unsigned Changes = 0; @@ -623,10 +623,10 @@ unsigned OptRTS (CodeSeg* S) unsigned OptJumpTarget1 (CodeSeg* S) /* If the instruction preceeding an unconditional branch is the same as the - * instruction preceeding the jump target, the jump target may be moved - * one entry back. This is a size optimization, since the instruction before - * the branch gets removed. - */ +** instruction preceeding the jump target, the jump target may be moved +** one entry back. This is a size optimization, since the instruction before +** the branch gets removed. +*/ { unsigned Changes = 0; CodeEntry* E1; /* Entry 1 */ @@ -642,8 +642,8 @@ unsigned OptJumpTarget1 (CodeSeg* S) E2 = CS_GetNextEntry (S, I); /* Check if we have a jump or branch without a label attached, and - * a jump target, which is not attached to the jump itself - */ + ** a jump target, which is not attached to the jump itself + */ if (E2 != 0 && (E2->Info & OF_UBRA) != 0 && !CE_HasLabel (E2) && @@ -658,8 +658,8 @@ unsigned OptJumpTarget1 (CodeSeg* S) } /* The entry preceeding the branch target may not be the branch - * insn. - */ + ** insn. + */ if (T1 == E2) { goto NextEntry; } @@ -674,17 +674,17 @@ unsigned OptJumpTarget1 (CodeSeg* S) } /* Get the label for the instruction preceeding the jump target. - * This routine will create a new label if the instruction does - * not already have one. - */ + ** This routine will create a new label if the instruction does + ** not already have one. + */ TL1 = CS_GenLabel (S, T1); /* Change the jump target to point to this new label */ CS_MoveLabelRef (S, E2, TL1); /* If the instruction preceeding the jump has labels attached, - * move references to this label to the new label. - */ + ** move references to this label to the new label. + */ if (CE_HasLabel (E1)) { CS_MoveLabels (S, E1, T1); } @@ -710,8 +710,8 @@ NextEntry: unsigned OptJumpTarget2 (CodeSeg* S) /* If a bcs jumps to a sec insn or a bcc jumps to clc, skip this insn, since - * it's job is already done. - */ +** it's job is already done. +*/ { unsigned Changes = 0; @@ -748,8 +748,8 @@ unsigned OptJumpTarget2 (CodeSeg* S) } /* Get the owner insn of the jump target and check if it's the one, we - * will skip if present. - */ + ** will skip if present. + */ T = E->JumpTo->Owner; if (T->OPC != OPC) { goto NextEntry; @@ -763,9 +763,9 @@ unsigned OptJumpTarget2 (CodeSeg* S) } /* Get the label for the instruction following the jump target. - * This routine will create a new label if the instruction does - * not already have one. - */ + ** This routine will create a new label if the instruction does + ** not already have one. + */ L = CS_GenLabel (S, N); /* Change the jump target to point to this new label */ @@ -787,9 +787,9 @@ NextEntry: unsigned OptJumpTarget3 (CodeSeg* S) /* Jumps to load instructions of a register, that do already have the matching - * register contents may skip the load instruction, since it's job is already - * done. - */ +** register contents may skip the load instruction, since it's job is already +** done. +*/ { unsigned Changes = 0; unsigned I; @@ -804,8 +804,8 @@ unsigned OptJumpTarget3 (CodeSeg* S) CodeEntry* E = CS_GetEntry (S, I); /* Check if this is a load insn with a label and the next insn is not - * a conditional branch that needs the flags from the load. - */ + ** a conditional branch that needs the flags from the load. + */ if ((E->Info & OF_LOAD) != 0 && CE_IsConstImm (E) && CE_HasLabel (E) && @@ -825,9 +825,9 @@ unsigned OptJumpTarget3 (CodeSeg* S) CodeLabel* L = CE_GetLabel (E, J); /* Loop over all insn that reference this label. Since we may - * eventually remove a reference in the loop, we must loop - * from end down to start. - */ + ** eventually remove a reference in the loop, we must loop + ** from end down to start. + */ for (K = CL_GetRefCount (L) - 1; K >= 0; --K) { /* Get the entry that jumps here */ @@ -839,9 +839,9 @@ unsigned OptJumpTarget3 (CodeSeg* S) /* Check if the outgoing value is the one thats's loaded */ if (Val == (unsigned char) E->Num) { - /* Ok, skip the insn. First, generate a label for the - * next insn after E. - */ + /* OK, skip the insn. First, generate a label for the + ** next insn after E. + */ if (LN == 0) { LN = CS_GenLabel (S, N); } @@ -875,16 +875,16 @@ unsigned OptJumpTarget3 (CodeSeg* S) unsigned OptCondBranches1 (CodeSeg* S) /* Performs several optimization steps: - * - * - If an immidiate load of a register is followed by a conditional jump that - * is never taken because the load of the register sets the flags in such a - * manner, remove the conditional branch. - * - If the conditional branch is always taken because of the register load, - * replace it by a jmp. - * - If a conditional branch jumps around an unconditional branch, remove the - * conditional branch and make the jump a conditional branch with the - * inverse condition of the first one. - */ +** +** - If an immediate load of a register is followed by a conditional jump that +** is never taken because the load of the register sets the flags in such a +** manner, remove the conditional branch. +** - If the conditional branch is always taken because of the register load, +** replace it by a jmp. +** - If a conditional branch jumps around an unconditional branch, remove the +** conditional branch and make the jump a conditional branch with the +** inverse condition of the first one. +*/ { unsigned Changes = 0; @@ -940,11 +940,11 @@ unsigned OptCondBranches1 (CodeSeg* S) (N = CS_GetNextEntry (S, I)) != 0 && /* There is a following entry */ (N->Info & OF_UBRA) != 0 && /* ..which is an uncond branch, */ !CE_HasLabel (N) && /* ..has no label attached */ - L->Owner == CS_GetNextEntry (S, I+1)) {/* ..and jump target follows */ + L->Owner == CS_GetNextEntry (S, I+1)) { /* ..and jump target follows */ /* Replace the jump by a conditional branch with the inverse branch - * condition than the branch around it. - */ + ** condition than the branch around it. + */ CE_ReplaceOPC (N, GetInverseBranch (E->OPC)); /* Remove the conditional branch */ @@ -968,8 +968,8 @@ unsigned OptCondBranches1 (CodeSeg* S) unsigned OptCondBranches2 (CodeSeg* S) /* If on entry to a "rol a" instruction the accu is zero, and a beq/bne follows, - * we can remove the rol and branch on the state of the carry flag. - */ +** we can remove the rol and branch on the state of the carry flag. +*/ { unsigned Changes = 0; unsigned I; @@ -1103,8 +1103,8 @@ unsigned OptUnusedStores (CodeSeg* S) (E->Chg & REG_ZP) != 0) { /* Check for the zero page location. We know that there cannot be - * more than one zero page location involved in the store. - */ + ** more than one zero page location involved in the store. + */ unsigned R = E->Chg & REG_ZP; /* Get register usage and check if the register value is used later */ @@ -1185,9 +1185,9 @@ unsigned OptDupLoads (CodeSeg* S) case OP65_STA: /* If we store into a known zero page location, and this - * location does already contain the value to be stored, - * remove the store. - */ + ** location does already contain the value to be stored, + ** remove the store. + */ if (RegValIsKnown (In->RegA) && /* Value of A is known */ E->AM == AM65_ZP && /* Store into zp */ In->RegA == ZPRegVal (E->Chg, In)) { /* Value identical */ @@ -1198,9 +1198,9 @@ unsigned OptDupLoads (CodeSeg* S) case OP65_STX: /* If we store into a known zero page location, and this - * location does already contain the value to be stored, - * remove the store. - */ + ** location does already contain the value to be stored, + ** remove the store. + */ if (RegValIsKnown (In->RegX) && /* Value of A is known */ E->AM == AM65_ZP && /* Store into zp */ In->RegX == ZPRegVal (E->Chg, In)) { /* Value identical */ @@ -1208,11 +1208,11 @@ unsigned OptDupLoads (CodeSeg* S) Delete = 1; /* If the value in the X register is known and the same as - * that in the A register, replace the store by a STA. The - * optimizer will then remove the load instruction for X - * later. STX does support the zeropage,y addressing mode, - * so be sure to check for that. - */ + ** that in the A register, replace the store by a STA. The + ** optimizer will then remove the load instruction for X + ** later. STX does support the zeropage,y addressing mode, + ** so be sure to check for that. + */ } else if (RegValIsKnown (In->RegX) && In->RegX == In->RegA && E->AM != AM65_ABSY && @@ -1224,9 +1224,9 @@ unsigned OptDupLoads (CodeSeg* S) case OP65_STY: /* If we store into a known zero page location, and this - * location does already contain the value to be stored, - * remove the store. - */ + ** location does already contain the value to be stored, + ** remove the store. + */ if (RegValIsKnown (In->RegY) && /* Value of Y is known */ E->AM == AM65_ZP && /* Store into zp */ In->RegY == ZPRegVal (E->Chg, In)) { /* Value identical */ @@ -1234,12 +1234,12 @@ unsigned OptDupLoads (CodeSeg* S) Delete = 1; /* If the value in the Y register is known and the same as - * that in the A register, replace the store by a STA. The - * optimizer will then remove the load instruction for Y - * later. If replacement by A is not possible try a - * replacement by X, but check for invalid addressing modes - * in this case. - */ + ** that in the A register, replace the store by a STA. The + ** optimizer will then remove the load instruction for Y + ** later. If replacement by A is not possible try a + ** replacement by X, but check for invalid addressing modes + ** in this case. + */ } else if (RegValIsKnown (In->RegY)) { if (In->RegY == In->RegA) { CE_ReplaceOPC (E, OP65_STA); @@ -1253,9 +1253,9 @@ unsigned OptDupLoads (CodeSeg* S) case OP65_STZ: /* If we store into a known zero page location, and this - * location does already contain the value to be stored, - * remove the store. - */ + ** location does already contain the value to be stored, + ** remove the store. + */ if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && E->AM == AM65_ZP) { if (ZPRegVal (E->Chg, In) == 0) { Delete = 1; @@ -1348,8 +1348,8 @@ unsigned OptStoreLoad (CodeSeg* S) CodeEntry* E = CS_GetEntry (S, I); /* Check if it is a store instruction followed by a load from the - * same address which is itself not followed by a conditional branch. - */ + ** same address which is itself not followed by a conditional branch. + */ if ((E->Info & OF_STORE) != 0 && (N = CS_GetNextEntry (S, I)) != 0 && !CE_HasLabel (N) && @@ -1409,9 +1409,9 @@ unsigned OptTransfers1 (CodeSeg* S) (E->OPC == OP65_TYA && N->OPC == OP65_TAY && !RegAUsed (S, I+2))) { /* If the next insn is a conditional branch, check if the insn - * preceeding the first xfr will set the flags right, otherwise we - * may not remove the sequence. - */ + ** preceeding the first xfr will set the flags right, otherwise we + ** may not remove the sequence. + */ if ((X = CS_GetNextEntry (S, I+1)) == 0) { goto NextEntry; } @@ -1450,8 +1450,8 @@ NextEntry: unsigned OptTransfers2 (CodeSeg* S) /* Replace loads followed by a register transfer by a load with the second - * register if possible. - */ +** register if possible. +*/ { unsigned Changes = 0; @@ -1465,8 +1465,8 @@ unsigned OptTransfers2 (CodeSeg* S) CodeEntry* E = CS_GetEntry (S, I); /* Check if we have a load followed by a transfer where the loaded - * register is not used later. - */ + ** register is not used later. + */ if ((E->Info & OF_LOAD) != 0 && (N = CS_GetNextEntry (S, I)) != 0 && !CE_HasLabel (N) && @@ -1499,8 +1499,8 @@ unsigned OptTransfers2 (CodeSeg* S) X = NewCodeEntry (OP65_LDA, E->AM, E->Arg, 0, N->LI); } else if (E->OPC == OP65_LDX && N->OPC == OP65_TXA) { /* LDX/TXA. LDA doesn't support zp,y, so we must map it to - * abs,y instead. - */ + ** abs,y instead. + */ am_t AM = (E->AM == AM65_ZPY)? AM65_ABSY : E->AM; X = NewCodeEntry (OP65_LDA, AM, E->Arg, 0, N->LI); } @@ -1526,8 +1526,8 @@ unsigned OptTransfers2 (CodeSeg* S) unsigned OptTransfers3 (CodeSeg* S) /* Replace a register transfer followed by a store of the second register by a - * store of the first register if this is possible. - */ +** store of the first register if this is possible. +*/ { unsigned Changes = 0; unsigned UsedRegs = REG_NONE; /* Track used registers */ @@ -1544,8 +1544,8 @@ unsigned OptTransfers3 (CodeSeg* S) } State = Initialize; /* Walk over the entries. Look for a xfer instruction that is followed by - * a store later, where the value of the register is not used later. - */ + ** a store later, where the value of the register is not used later. + */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { @@ -1570,8 +1570,8 @@ unsigned OptTransfers3 (CodeSeg* S) case FoundXfer: /* If we find a conditional jump, abort the sequence, since - * handling them makes things really complicated. - */ + ** handling them makes things really complicated. + */ if (E->Info & OF_CBRA) { /* Switch back to searching */ @@ -1582,8 +1582,8 @@ unsigned OptTransfers3 (CodeSeg* S) } else if ((E->Use & XferEntry->Chg) != 0) { /* It it's a store instruction, and the block is a basic - * block, proceed. Otherwise restart - */ + ** block, proceed. Otherwise restart + */ if ((E->Info & OF_STORE) != 0 && CS_IsBasicBlock (S, Xfer, I)) { Store = I; @@ -1598,9 +1598,9 @@ unsigned OptTransfers3 (CodeSeg* S) } else if (E->Chg & XferEntry->Chg) { /* We *may* add code here to remove the transfer, but I'm - * currently not sure about the consequences, so I won't - * do that and bail out instead. - */ + ** currently not sure about the consequences, so I won't + ** do that and bail out instead. + */ I = Xfer; State = Initialize; @@ -1619,9 +1619,9 @@ unsigned OptTransfers3 (CodeSeg* S) case FoundStore: /* We are at the instruction behind the store. If the register - * isn't used later, and we have an address mode match, we can - * replace the transfer by a store and remove the store here. - */ + ** isn't used later, and we have an address mode match, we can + ** replace the transfer by a store and remove the store here. + */ if ((GetRegInfo (S, I, XferEntry->Chg) & XferEntry->Chg) == 0 && (StoreEntry->AM == AM65_ABS || StoreEntry->AM == AM65_ZP) && @@ -1710,8 +1710,8 @@ unsigned OptTransfers3 (CodeSeg* S) unsigned OptTransfers4 (CodeSeg* S) /* Replace a load of a register followed by a transfer insn of the same register - * by a load of the second register if possible. - */ +** by a load of the second register if possible. +*/ { unsigned Changes = 0; unsigned Load = 0; /* Index of load insn */ @@ -1726,8 +1726,8 @@ unsigned OptTransfers4 (CodeSeg* S) } State = Search; /* Walk over the entries. Look for a load instruction that is followed by - * a load later. - */ + ** a load later. + */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { @@ -1747,8 +1747,8 @@ unsigned OptTransfers4 (CodeSeg* S) case FoundLoad: /* If we find a conditional jump, abort the sequence, since - * handling them makes things really complicated. - */ + ** handling them makes things really complicated. + */ if (E->Info & OF_CBRA) { /* Switch back to searching */ @@ -1759,8 +1759,8 @@ unsigned OptTransfers4 (CodeSeg* S) } else if ((E->Use & LoadEntry->Chg) != 0) { /* It it's a xfer instruction, and the block is a basic - * block, proceed. Otherwise restart - */ + ** block, proceed. Otherwise restart + */ if ((E->Info & OF_XFR) != 0 && CS_IsBasicBlock (S, Load, I)) { Xfer = I; @@ -1775,9 +1775,9 @@ unsigned OptTransfers4 (CodeSeg* S) } else if (E->Chg & LoadEntry->Chg) { /* We *may* add code here to remove the load, but I'm - * currently not sure about the consequences, so I won't - * do that and bail out instead. - */ + ** currently not sure about the consequences, so I won't + ** do that and bail out instead. + */ I = Load; State = Search; } @@ -1785,9 +1785,9 @@ unsigned OptTransfers4 (CodeSeg* S) case FoundXfer: /* We are at the instruction behind the xfer. If the register - * isn't used later, and we have an address mode match, we can - * replace the transfer by a load and remove the initial load. - */ + ** isn't used later, and we have an address mode match, we can + ** replace the transfer by a load and remove the initial load. + */ if ((GetRegInfo (S, I, LoadEntry->Chg) & LoadEntry->Chg) == 0 && (LoadEntry->AM == AM65_ABS || LoadEntry->AM == AM65_ZP || @@ -1880,14 +1880,14 @@ unsigned OptPushPop (CodeSeg* S) } State = Searching; /* Walk over the entries. Look for a push instruction that is followed by - * a pop later, where the pop is not followed by an conditional branch, - * and where the value of the A register is not used later on. - * Look out for the following problems: - * - * - There may be another PHA/PLA inside the sequence: Restart it. - * - If the PLA has a label, all jumps to this label must be inside - * the sequence, otherwise we cannot remove the PHA/PLA. - */ + ** a pop later, where the pop is not followed by an conditional branch, + ** and where the value of the A register is not used later on. + ** Look out for the following problems: + ** + ** - There may be another PHA/PLA inside the sequence: Restart it. + ** - If the PLA has a label, all jumps to this label must be inside + ** the sequence, otherwise we cannot remove the PHA/PLA. + */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { @@ -1916,8 +1916,8 @@ unsigned OptPushPop (CodeSeg* S) /* Found a matching pop */ Pop = I; /* Check that the block between Push and Pop is a basic - * block (one entry, one exit). Otherwise ignore it. - */ + ** block (one entry, one exit). Otherwise ignore it. + */ if (CS_IsBasicBlock (S, Push, Pop)) { State = FoundPop; } else { @@ -1931,16 +1931,16 @@ unsigned OptPushPop (CodeSeg* S) case FoundPop: /* We're at the instruction after the PLA. - * Check for the following conditions: - * - If this instruction is a store of A that doesn't use - * another register, if the instruction does not have a - * label, and A is not used later, we may replace the PHA - * by the store and remove pla if several other conditions - * are met. - * - If this instruction is not a conditional branch, and A - * is either unused later, or not changed by the code - * between push and pop, we may remove PHA and PLA. - */ + ** Check for the following conditions: + ** - If this instruction is a store of A that doesn't use + ** another register, if the instruction does not have a + ** label, and A is not used later, we may replace the PHA + ** by the store and remove pla if several other conditions + ** are met. + ** - If this instruction is not a conditional branch, and A + ** is either unused later, or not changed by the code + ** between push and pop, we may remove PHA and PLA. + */ if (E->OPC == OP65_STA && (E->AM == AM65_ABS || E->AM == AM65_ZP) && !CE_HasLabel (E) && @@ -1995,8 +1995,8 @@ unsigned OptPushPop (CodeSeg* S) unsigned OptPrecalc (CodeSeg* S) /* Replace immediate operations with the accu where the current contents are - * known by a load of the final value. - */ +** known by a load of the final value. +*/ { unsigned Changes = 0; unsigned I; @@ -2052,11 +2052,11 @@ unsigned OptPrecalc (CodeSeg* S) case OP65_ADC: case OP65_SBC: /* If this is an operation with an immediate operand of zero, - * and the register is zero, the operation won't give us any - * results we don't already have (including the flags), so - * remove it. Something like this is generated as a result of - * a compare where parts of the values are known to be zero. - */ + ** and the register is zero, the operation won't give us any + ** results we don't already have (including the flags), so + ** remove it. Something like this is generated as a result of + ** a compare where parts of the values are known to be zero. + */ if (In->RegA == 0 && CE_IsKnownImm (E, 0x00)) { /* 0-0 or 0+0 -> remove */ CS_DelEntry (S, I); @@ -2198,15 +2198,15 @@ unsigned OptBranchDist (CodeSeg* S) unsigned OptIndLoads1 (CodeSeg* S) /* Change - * - * lda (zp),y - * - * into - * - * lda (zp,x) - * - * provided that x and y are both zero. - */ +** +** lda (zp),y +** +** into +** +** lda (zp,x) +** +** provided that x and y are both zero. +*/ { unsigned Changes = 0; unsigned I; @@ -2246,15 +2246,15 @@ unsigned OptIndLoads1 (CodeSeg* S) unsigned OptIndLoads2 (CodeSeg* S) /* Change - * - * lda (zp,x) - * - * into - * - * lda (zp),y - * - * provided that x and y are both zero. - */ +** +** lda (zp,x) +** +** into +** +** lda (zp),y +** +** provided that x and y are both zero. +*/ { unsigned Changes = 0; unsigned I; @@ -2289,6 +2289,3 @@ unsigned OptIndLoads2 (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptind.h b/src/cc65/coptind.h index 83a3f964c..90e27d547 100644 --- a/src/cc65/coptind.h +++ b/src/cc65/coptind.h @@ -60,51 +60,51 @@ unsigned OptDeadJumps (CodeSeg* S); unsigned OptDeadCode (CodeSeg* S); /* Remove dead code (code that follows an unconditional jump or an rts/rti - * and has no label) - */ +** and has no label) +*/ unsigned OptJumpCascades (CodeSeg* S); /* Optimize jump cascades (jumps to jumps). In such a case, the jump is - * replaced by a jump to the final location. This will in some cases produce - * worse code, because some jump targets are no longer reachable by short - * branches, but this is quite rare, so there are more advantages than - * disadvantages. - */ +** replaced by a jump to the final location. This will in some cases produce +** worse code, because some jump targets are no longer reachable by short +** branches, but this is quite rare, so there are more advantages than +** disadvantages. +*/ unsigned OptRTS (CodeSeg* S); /* Optimize subroutine calls followed by an RTS. The subroutine call will get - * replaced by a jump. Don't bother to delete the RTS if it does not have a - * label, the dead code elimination should take care of it. - */ +** replaced by a jump. Don't bother to delete the RTS if it does not have a +** label, the dead code elimination should take care of it. +*/ unsigned OptJumpTarget1 (CodeSeg* S); /* If the instruction preceeding an unconditional branch is the same as the - * instruction preceeding the jump target, the jump target may be moved - * one entry back. This is a size optimization, since the instruction before - * the branch gets removed. - */ +** instruction preceeding the jump target, the jump target may be moved +** one entry back. This is a size optimization, since the instruction before +** the branch gets removed. +*/ unsigned OptJumpTarget2 (CodeSeg* S); /* If a bcs jumps to a sec insn or a bcc jumps to clc, skip this insn, since - * it's job is already done. - */ +** it's job is already done. +*/ unsigned OptJumpTarget3 (CodeSeg* S); /* Jumps to load instructions of a register, that do already have the matching - * register contents may skip the load instruction, since it's job is already - * done. - */ +** register contents may skip the load instruction, since it's job is already +** done. +*/ unsigned OptCondBranches1 (CodeSeg* S); /* If an immidiate load of a register is followed by a conditional jump that - * is never taken because the load of the register sets the flags in such a - * manner, remove the conditional branch. - */ +** is never taken because the load of the register sets the flags in such a +** manner, remove the conditional branch. +*/ unsigned OptCondBranches2 (CodeSeg* S); /* If on entry to a "rol a" instruction the accu is zero, and a beq/bne follows, - * we can remove the rol and branch on the state of the carry. - */ +** we can remove the rol and branch on the state of the carry. +*/ unsigned OptUnusedLoads (CodeSeg* S); /* Remove loads of registers where the value loaded is not used later. */ @@ -123,58 +123,56 @@ unsigned OptTransfers1 (CodeSeg* S); unsigned OptTransfers2 (CodeSeg* S); /* Replace loads followed by a register transfer by a load with the second - * register if possible. - */ +** register if possible. +*/ unsigned OptTransfers3 (CodeSeg* S); /* Replace a register transfer followed by a store of the second register by a - * store of the first register if this is possible. - */ +** store of the first register if this is possible. +*/ unsigned OptTransfers4 (CodeSeg* S); /* Replace a load of a register followed by a transfer insn of the same register - * by a load of the second register if possible. - */ +** by a load of the second register if possible. +*/ unsigned OptPushPop (CodeSeg* S); /* Remove a PHA/PLA sequence were A is not used later */ unsigned OptPrecalc (CodeSeg* S); /* Replace immediate operations with the accu where the current contents are - * known by a load of the final value. - */ +** known by a load of the final value. +*/ unsigned OptBranchDist (CodeSeg* S); /* Change branches for the distance needed. */ unsigned OptIndLoads1 (CodeSeg* S); /* Change - * - * lda (zp),y - * - * into - * - * lda (zp,x) - * - * provided that x and y are both zero. - */ +** +** lda (zp),y +** +** into +** +** lda (zp,x) +** +** provided that x and y are both zero. +*/ unsigned OptIndLoads2 (CodeSeg* S); /* Change - * - * lda (zp,x) - * - * into - * - * lda (zp),y - * - * provided that x and y are both zero. - */ +** +** lda (zp,x) +** +** into +** +** lda (zp),y +** +** provided that x and y are both zero. +*/ /* End of coptind.h */ + #endif - - - diff --git a/src/cc65/coptneg.c b/src/cc65/coptneg.c index 2bc0e6b2f..03b39eb42 100644 --- a/src/cc65/coptneg.c +++ b/src/cc65/coptneg.c @@ -48,13 +48,13 @@ unsigned OptBNegA1 (CodeSeg* S) /* Check for - * - * ldx #$00 - * lda .. - * jsr bnega - * - * Remove the ldx if the lda does not use it. - */ +** +** ldx #$00 +** lda .. +** jsr bnega +** +** Remove the ldx if the lda does not use it. +*/ { unsigned Changes = 0; @@ -100,13 +100,13 @@ unsigned OptBNegA1 (CodeSeg* S) unsigned OptBNegA2 (CodeSeg* S) /* Check for - * - * lda .. - * jsr bnega - * jeq/jne .. - * - * Adjust the conditional branch and remove the call to the subroutine. - */ +** +** lda .. +** jsr bnega +** jeq/jne .. +** +** Adjust the conditional branch and remove the call to the subroutine. +*/ { unsigned Changes = 0; @@ -167,9 +167,9 @@ unsigned OptBNegA2 (CodeSeg* S) unsigned OptBNegAX1 (CodeSeg* S) /* On a call to bnegax, if X is zero, the result depends only on the value in - * A, so change the call to a call to bnega. This will get further optimized - * later if possible. - */ +** A, so change the call to a call to bnega. This will get further optimized +** later if possible. +*/ { unsigned Changes = 0; unsigned I; @@ -205,20 +205,20 @@ unsigned OptBNegAX1 (CodeSeg* S) unsigned OptBNegAX2 (CodeSeg* S) /* Search for the sequence: - * - * ldy #xx - * jsr ldaxysp - * jsr bnegax - * jne/jeq ... - * - * and replace it by - * - * ldy #xx - * lda (sp),y - * dey - * ora (sp),y - * jeq/jne ... - */ +** +** ldy #xx +** jsr ldaxysp +** jsr bnegax +** jne/jeq ... +** +** and replace it by +** +** ldy #xx +** lda (sp),y +** dey +** ora (sp),y +** jeq/jne ... +*/ { unsigned Changes = 0; @@ -278,18 +278,18 @@ unsigned OptBNegAX2 (CodeSeg* S) unsigned OptBNegAX3 (CodeSeg* S) /* Search for the sequence: - * - * lda xx - * ldx yy - * jsr bnegax - * jne/jeq ... - * - * and replace it by - * - * lda xx - * ora xx+1 - * jeq/jne ... - */ +** +** lda xx +** ldx yy +** jsr bnegax +** jne/jeq ... +** +** and replace it by +** +** lda xx +** ora xx+1 +** jeq/jne ... +*/ { unsigned Changes = 0; @@ -339,17 +339,17 @@ unsigned OptBNegAX3 (CodeSeg* S) unsigned OptBNegAX4 (CodeSeg* S) /* Search for the sequence: - * - * jsr xxx - * jsr bnega(x) - * jeq/jne ... - * - * and replace it by: - * - * jsr xxx - * <boolean test> - * jne/jeq ... - */ +** +** jsr xxx +** jsr bnega(x) +** jeq/jne ... +** +** and replace it by: +** +** jsr xxx +** <boolean test> +** jne/jeq ... +*/ { unsigned Changes = 0; @@ -419,13 +419,13 @@ unsigned OptBNegAX4 (CodeSeg* S) unsigned OptNegAX1 (CodeSeg* S) /* Search for a call to negax and replace it by - * - * eor #$FF - * clc - * adc #$01 - * - * if X isn't used later. - */ +** +** eor #$FF +** clc +** adc #$01 +** +** if X isn't used later. +*/ { unsigned Changes = 0; unsigned I; @@ -475,17 +475,17 @@ unsigned OptNegAX1 (CodeSeg* S) unsigned OptNegAX2 (CodeSeg* S) /* Search for a call to negax and replace it by - * - * ldx #$FF - * eor #$FF - * clc - * adc #$01 - * bne L1 - * inx - * L1: - * - * if X is known and zero on entry. - */ +** +** ldx #$FF +** eor #$FF +** clc +** adc #$01 +** bne L1 +** inx +** L1: +** +** if X is known and zero on entry. +*/ { unsigned Changes = 0; unsigned I; @@ -565,11 +565,11 @@ unsigned OptNegAX2 (CodeSeg* S) unsigned OptComplAX1 (CodeSeg* S) /* Search for a call to complax and replace it by - * - * eor #$FF - * - * if X isn't used later. - */ +** +** eor #$FF +** +** if X isn't used later. +*/ { unsigned Changes = 0; unsigned I; @@ -605,6 +605,3 @@ unsigned OptComplAX1 (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptneg.h b/src/cc65/coptneg.h index 580faaa67..f549fc553 100644 --- a/src/cc65/coptneg.h +++ b/src/cc65/coptneg.h @@ -51,23 +51,23 @@ unsigned OptBNegA1 (CodeSeg* S); /* Check for - * - * ldx #$00 - * lda .. - * jsr bnega - * - * Remove the ldx if the lda does not use it. - */ +** +** ldx #$00 +** lda .. +** jsr bnega +** +** Remove the ldx if the lda does not use it. +*/ unsigned OptBNegA2 (CodeSeg* S); /* Check for - * - * lda .. - * jsr bnega - * jeq/jne .. - * - * Adjust the conditional branch and remove the call to the subroutine. - */ +** +** lda .. +** jsr bnega +** jeq/jne .. +** +** Adjust the conditional branch and remove the call to the subroutine. +*/ @@ -79,56 +79,56 @@ unsigned OptBNegA2 (CodeSeg* S); unsigned OptBNegAX1 (CodeSeg* S); /* On a call to bnegax, if X is zero, the result depends only on the value in - * A, so change the call to a call to bnega. This will get further optimized - * later if possible. - */ +** A, so change the call to a call to bnega. This will get further optimized +** later if possible. +*/ unsigned OptBNegAX2 (CodeSeg* S); /* Search for the sequence: - * - * lda (xx),y - * tax - * dey - * lda (xx),y - * jsr bnegax - * jne/jeq ... - * - * and replace it by - * - * lda (xx),y - * dey - * ora (xx),y - * jeq/jne ... - */ +** +** lda (xx),y +** tax +** dey +** lda (xx),y +** jsr bnegax +** jne/jeq ... +** +** and replace it by +** +** lda (xx),y +** dey +** ora (xx),y +** jeq/jne ... +*/ unsigned OptBNegAX3 (CodeSeg* S); /* Search for the sequence: - * - * lda xx - * ldx yy - * jsr bnegax - * jne/jeq ... - * - * and replace it by - * - * lda xx - * ora xx+1 - * jeq/jne ... - */ +** +** lda xx +** ldx yy +** jsr bnegax +** jne/jeq ... +** +** and replace it by +** +** lda xx +** ora xx+1 +** jeq/jne ... +*/ unsigned OptBNegAX4 (CodeSeg* S); /* Search for the sequence: - * - * jsr xxx - * jsr bnega(x) - * jeq/jne ... - * - * and replace it by: - * - * jsr xxx - * <boolean test> - * jne/jeq ... - */ +** +** jsr xxx +** jsr bnega(x) +** jeq/jne ... +** +** and replace it by: +** +** jsr xxx +** <boolean test> +** jne/jeq ... +*/ @@ -140,27 +140,27 @@ unsigned OptBNegAX4 (CodeSeg* S); unsigned OptNegAX1 (CodeSeg* S); /* Search for a call to negax and replace it by - * - * eor #$FF - * clc - * adc #$01 - * - * if X isn't used later. - */ +** +** eor #$FF +** clc +** adc #$01 +** +** if X isn't used later. +*/ unsigned OptNegAX2 (CodeSeg* S); /* Search for a call to negax and replace it by - * - * ldx #$FF - * eor #$FF - * clc - * adc #$01 - * bne L1 - * inx - * L1: - * - * if X is known and zero on entry. - */ +** +** ldx #$FF +** eor #$FF +** clc +** adc #$01 +** bne L1 +** inx +** L1: +** +** if X is known and zero on entry. +*/ @@ -172,17 +172,14 @@ unsigned OptNegAX2 (CodeSeg* S); unsigned OptComplAX1 (CodeSeg* S); /* Search for a call to complax and replace it by - * - * eor #$FF - * - * if X isn't used later. - */ +** +** eor #$FF +** +** if X isn't used later. +*/ /* End of coptneg.h */ #endif - - - diff --git a/src/cc65/coptptrload.c b/src/cc65/coptptrload.c index 43f3cc49c..ee783c93f 100644 --- a/src/cc65/coptptrload.c +++ b/src/cc65/coptptrload.c @@ -53,28 +53,28 @@ unsigned OptPtrLoad1 (CodeSeg* S) /* Search for the sequence: - * - * clc - * adc xxx - * tay - * txa - * adc yyy - * tax - * tya - * ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * sta ptr1 - * txa - * clc - * adc yyy - * sta ptr1+1 - * ldy xxx - * ldx #$00 - * lda (ptr1),y - */ +** +** clc +** adc xxx +** tay +** txa +** adc yyy +** tax +** tya +** ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** sta ptr1 +** txa +** clc +** adc yyy +** sta ptr1+1 +** ldy xxx +** ldx #$00 +** lda (ptr1),y +*/ { unsigned Changes = 0; @@ -115,9 +115,9 @@ unsigned OptPtrLoad1 (CodeSeg* S) CS_InsertEntry (S, X, IP++); /* If the instruction before the clc is a ldx, replace the - * txa by an lda with the same location of the ldx. Otherwise - * transfer the value in X to A. - */ + ** txa by an lda with the same location of the ldx. Otherwise + ** transfer the value in X to A. + */ if ((P = CS_GetPrevEntry (S, I)) != 0 && P->OPC == OP65_LDX && !CE_HasLabel (P)) { @@ -172,29 +172,29 @@ unsigned OptPtrLoad1 (CodeSeg* S) unsigned OptPtrLoad2 (CodeSeg* S) /* Search for the sequence: - * - * adc xxx - * pha - * txa - * iny - * adc yyy - * tax - * pla - * ldy - * jsr ldauidx - * - * and replace it by: - * - * adc xxx - * sta ptr1 - * txa - * iny - * adc yyy - * sta ptr1+1 - * ldy - * ldx #$00 - * lda (ptr1),y - */ +** +** adc xxx +** pha +** txa +** iny +** adc yyy +** tax +** pla +** ldy +** jsr ldauidx +** +** and replace it by: +** +** adc xxx +** sta ptr1 +** txa +** iny +** adc yyy +** sta ptr1+1 +** ldy +** ldx #$00 +** lda (ptr1),y +*/ { unsigned Changes = 0; @@ -260,22 +260,22 @@ unsigned OptPtrLoad2 (CodeSeg* S) unsigned OptPtrLoad3 (CodeSeg* S) /* Search for the sequence: - * - * lda #<(label+0) - * ldx #>(label+0) - * clc - * adc xxx - * bcc L - * inx - * L: ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * ldy xxx - * ldx #$00 - * lda label,y - */ +** +** lda #<(label+0) +** ldx #>(label+0) +** clc +** adc xxx +** bcc L +** inx +** L: ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** ldy xxx +** ldx #$00 +** lda label,y +*/ { unsigned Changes = 0; @@ -319,8 +319,8 @@ unsigned OptPtrLoad3 (CodeSeg* S) char* Label; /* We will create all the new stuff behind the current one so - * we keep the line references. - */ + ** we keep the line references. + */ X = NewCodeEntry (OP65_LDY, L[3]->AM, L[3]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+8); @@ -354,25 +354,25 @@ unsigned OptPtrLoad3 (CodeSeg* S) unsigned OptPtrLoad4 (CodeSeg* S) /* Search for the sequence: - * - * lda #<(label+0) - * ldx #>(label+0) - * ldy #$xx - * clc - * adc (sp),y - * bcc L - * inx - * L: ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * ldy #$xx - * lda (sp),y - * tay - * ldx #$00 - * lda label,y - */ +** +** lda #<(label+0) +** ldx #>(label+0) +** ldy #$xx +** clc +** adc (sp),y +** bcc L +** inx +** L: ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** ldy #$xx +** lda (sp),y +** tay +** ldx #$00 +** lda label,y +*/ { unsigned Changes = 0; @@ -463,22 +463,22 @@ unsigned OptPtrLoad4 (CodeSeg* S) unsigned OptPtrLoad5 (CodeSeg* S) /* Search for the sequence: - * - * jsr pushax - * ldx #$00 - * lda yyy - * jsr tosaddax - * ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * sta ptr1 - * stx ptr1+1 - * ldy yyy - * ldx #$00 - * lda (ptr1),y - */ +** +** jsr pushax +** ldx #$00 +** lda yyy +** jsr tosaddax +** ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** sta ptr1 +** stx ptr1+1 +** ldy yyy +** ldx #$00 +** lda (ptr1),y +*/ { unsigned Changes = 0; @@ -549,25 +549,25 @@ unsigned OptPtrLoad5 (CodeSeg* S) unsigned OptPtrLoad6 (CodeSeg* S) /* Search for the sequence: - * - * jsr pushax - * ldy #xxx - * ldx #$00 - * lda (sp),y - * jsr tosaddax - * ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * sta ptr1 - * stx ptr1+1 - * ldy #xxx-2 - * lda (sp),y - * tay - * ldx #$00 - * lda (ptr1),y - */ +** +** jsr pushax +** ldy #xxx +** ldx #$00 +** lda (sp),y +** jsr tosaddax +** ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** sta ptr1 +** stx ptr1+1 +** ldy #xxx-2 +** lda (sp),y +** tay +** ldx #$00 +** lda (ptr1),y +*/ { unsigned Changes = 0; @@ -650,35 +650,35 @@ unsigned OptPtrLoad6 (CodeSeg* S) unsigned OptPtrLoad7 (CodeSeg* S) /* Search for the sequence: - * - * jsr aslax1/shlax1 - * clc - * adc xxx - * tay - * txa - * adc yyy - * tax - * tya - * ldy zzz - * jsr ldaxidx - * - * and replace it by: - * - * stx tmp1 - * asl a - * rol tmp1 - * clc - * adc xxx - * sta ptr1 - * lda tmp1 - * adc yyy - * sta ptr1+1 - * ldy zzz - * lda (ptr1),y - * tax - * dey - * lda (ptr1),y - */ +** +** jsr aslax1/shlax1 +** clc +** adc xxx +** tay +** txa +** adc yyy +** tax +** tya +** ldy zzz +** jsr ldaxidx +** +** and replace it by: +** +** stx tmp1 +** asl a +** rol tmp1 +** clc +** adc xxx +** sta ptr1 +** lda tmp1 +** adc yyy +** sta ptr1+1 +** ldy zzz +** lda (ptr1),y +** tax +** dey +** lda (ptr1),y +*/ { unsigned Changes = 0; unsigned I; @@ -715,15 +715,15 @@ unsigned OptPtrLoad7 (CodeSeg* S) /* If X is zero on entry to aslax1, we can generate: - * - * asl a - * bcc L1 - * inx - * L1: clc - * - * instead of the code above. "lda tmp1" needs to be changed - * to "txa" in this case. - */ + ** + ** asl a + ** bcc L1 + ** inx + ** L1: clc + ** + ** instead of the code above. "lda tmp1" needs to be changed + ** to "txa" in this case. + */ int ShortCode = (L[0]->RI->In.RegX == 0); if (ShortCode) { @@ -838,22 +838,22 @@ unsigned OptPtrLoad7 (CodeSeg* S) unsigned OptPtrLoad11 (CodeSeg* S) /* Search for the sequence: - * - * clc - * adc xxx - * bcc L - * inx - * L: ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * ldy xxx - * sta ptr1 - * stx ptr1+1 - * ldx #$00 - * lda (ptr1),y - */ +** +** clc +** adc xxx +** bcc L +** inx +** L: ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** ldy xxx +** sta ptr1 +** stx ptr1+1 +** ldx #$00 +** lda (ptr1),y +*/ { unsigned Changes = 0; @@ -884,8 +884,8 @@ unsigned OptPtrLoad11 (CodeSeg* S) CodeEntry* X; /* We will create all the new stuff behind the current one so - * we keep the line references. - */ + ** we keep the line references. + */ X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+6); @@ -925,35 +925,35 @@ unsigned OptPtrLoad11 (CodeSeg* S) unsigned OptPtrLoad12 (CodeSeg* S) /* Search for the sequence: - * - * lda regbank+n - * ldx regbank+n+1 - * sta regsave - * stx regsave+1 - * clc - * adc #$01 - * bcc L0005 - * inx - * L: sta regbank+n - * stx regbank+n+1 - * lda regsave - * ldx regsave+1 - * ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * ldy #$00 - * ldx #$00 - * lda (regbank+n),y - * inc regbank+n - * bne L1 - * inc regbank+n+1 - * L1: tay <- only if flags are used - * - * This function must execute before OptPtrLoad7! - * - */ +** +** lda regbank+n +** ldx regbank+n+1 +** sta regsave +** stx regsave+1 +** clc +** adc #$01 +** bcc L0005 +** inx +** L: sta regbank+n +** stx regbank+n+1 +** lda regsave +** ldx regsave+1 +** ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** ldy #$00 +** ldx #$00 +** lda (regbank+n),y +** inc regbank+n +** bne L1 +** inc regbank+n+1 +** L1: tay <- only if flags are used +** +** This function must execute before OptPtrLoad7! +** +*/ { unsigned Changes = 0; @@ -1012,17 +1012,17 @@ unsigned OptPtrLoad12 (CodeSeg* S) CodeLabel* Label; /* Check if the instruction following the sequence uses the flags - * set by the load. If so, insert a test of the value in the - * accumulator. - */ + ** set by the load. If so, insert a test of the value in the + ** accumulator. + */ if (CE_UseLoadFlags (L[14])) { X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[13]->LI); CS_InsertEntry (S, X, I+14); } /* Attach a label to L[14]. This may be either the just inserted - * instruction, or the one following the sequence. - */ + ** instruction, or the one following the sequence. + */ Label = CS_GenLabel (S, L[14]); /* ldy #$xx */ @@ -1070,18 +1070,18 @@ unsigned OptPtrLoad12 (CodeSeg* S) unsigned OptPtrLoad13 (CodeSeg* S) /* Search for the sequence: - * - * lda zp - * ldx zp+1 - * ldy xx - * jsr ldauidx - * - * and replace it by: - * - * ldy xx - * ldx #$00 - * lda (zp),y - */ +** +** lda zp +** ldx zp+1 +** ldy xx +** jsr ldauidx +** +** and replace it by: +** +** ldy xx +** ldx #$00 +** lda (zp),y +*/ { unsigned Changes = 0; @@ -1138,23 +1138,22 @@ unsigned OptPtrLoad13 (CodeSeg* S) unsigned OptPtrLoad14 (CodeSeg* S) /* Search for the sequence: - * - * lda zp - * ldx zp+1 - * (anything that doesn't change a/x) - * ldy xx - * jsr ldauidx - * - * and replace it by: - * - * lda zp - * ldx zp+1 - * (anything that doesn't change a/x) - * ldy xx - * ldx #$00 - * lda (zp),y - * - */ +** +** lda zp +** ldx zp+1 +** (anything that doesn't change a/x) +** ldy xx +** jsr ldauidx +** +** and replace it by: +** +** lda zp +** ldx zp+1 +** (anything that doesn't change a/x) +** ldy xx +** ldx #$00 +** lda (zp),y +*/ { unsigned Changes = 0; unsigned I; @@ -1212,24 +1211,24 @@ unsigned OptPtrLoad14 (CodeSeg* S) unsigned OptPtrLoad15 (CodeSeg* S) /* Search for the sequence: - * - * lda zp - * ldx zp+1 - * jsr pushax <- optional - * ldy xx - * jsr ldaxidx - * - * and replace it by: - * - * lda zp <- only if - * ldx zp+1 <- call to - * jsr pushax <- pushax present - * ldy xx - * lda (zp),y - * tax - * dey - * lda (zp),y - */ +** +** lda zp +** ldx zp+1 +** jsr pushax <- optional +** ldy xx +** jsr ldaxidx +** +** and replace it by: +** +** lda zp <- only if +** ldx zp+1 <- call to +** jsr pushax <- pushax present +** ldy xx +** lda (zp),y +** tax +** dey +** lda (zp),y +*/ { unsigned Changes = 0; @@ -1300,20 +1299,20 @@ unsigned OptPtrLoad15 (CodeSeg* S) unsigned OptPtrLoad16 (CodeSeg* S) /* Search for the sequence - * - * ldy ... - * jsr ldauidx - * - * and replace it by: - * - * stx ptr1+1 - * sta ptr1 - * ldy ... - * ldx #$00 - * lda (ptr1),y - * - * This step must be executed *after* OptPtrLoad1! - */ +** +** ldy ... +** jsr ldauidx +** +** and replace it by: +** +** stx ptr1+1 +** sta ptr1 +** ldy ... +** ldx #$00 +** lda (ptr1),y +** +** This step must be executed *after* OptPtrLoad1! +*/ { unsigned Changes = 0; @@ -1375,25 +1374,25 @@ unsigned OptPtrLoad16 (CodeSeg* S) unsigned OptPtrLoad17 (CodeSeg* S) /* Search for the sequence - * - * ldy ... - * jsr ldaxidx - * - * and replace it by: - * - * sta ptr1 - * stx ptr1+1 - * ldy ... - * lda (ptr1),y - * tax - * dey - * lda (ptr1),y - * - * This step must be executed *after* OptPtrLoad9! While code size increases - * by more than 200%, inlining will greatly improve visibility for the - * optimizer, so often part of the code gets improved later. So we will mark - * the step with less than 200% so it gets executed when -Oi is in effect. - */ +** +** ldy ... +** jsr ldaxidx +** +** and replace it by: +** +** sta ptr1 +** stx ptr1+1 +** ldy ... +** lda (ptr1),y +** tax +** dey +** lda (ptr1),y +** +** This step must be executed *after* OptPtrLoad9! While code size increases +** by more than 200%, inlining will greatly improve visibility for the +** optimizer, so often part of the code gets improved later. So we will mark +** the step with less than 200% so it gets executed when -Oi is in effect. +*/ { unsigned Changes = 0; @@ -1458,6 +1457,3 @@ unsigned OptPtrLoad17 (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptptrload.h b/src/cc65/coptptrload.h index 3b8a83c7b..fd93bf5c2 100644 --- a/src/cc65/coptptrload.h +++ b/src/cc65/coptptrload.h @@ -51,315 +51,313 @@ unsigned OptPtrLoad1 (CodeSeg* S); /* Search for the sequence: - * - * clc - * adc xxx - * tay - * txa - * adc yyy - * tax - * tya - * ldy - * jsr ldauidx - * - * and replace it by: - * - * clc - * adc xxx - * sta ptr1 - * txa - * adc yyy - * sta ptr1+1 - * ldy - * ldx #$00 - * lda (ptr1),y - */ +** +** clc +** adc xxx +** tay +** txa +** adc yyy +** tax +** tya +** ldy +** jsr ldauidx +** +** and replace it by: +** +** clc +** adc xxx +** sta ptr1 +** txa +** adc yyy +** sta ptr1+1 +** ldy +** ldx #$00 +** lda (ptr1),y +*/ unsigned OptPtrLoad2 (CodeSeg* S); /* Search for the sequence: - * - * adc xxx - * pha - * txa - * iny - * adc yyy - * tax - * pla - * ldy - * jsr ldauidx - * - * and replace it by: - * - * adc xxx - * sta ptr1 - * txa - * iny - * adc yyy - * sta ptr1+1 - * ldy - * ldx #$00 - * lda (ptr1),y - */ +** +** adc xxx +** pha +** txa +** iny +** adc yyy +** tax +** pla +** ldy +** jsr ldauidx +** +** and replace it by: +** +** adc xxx +** sta ptr1 +** txa +** iny +** adc yyy +** sta ptr1+1 +** ldy +** ldx #$00 +** lda (ptr1),y +*/ unsigned OptPtrLoad3 (CodeSeg* S); /* Search for the sequence: - * - * lda #<(label+0) - * ldx #>(label+0) - * clc - * adc xxx - * bcc L - * inx - * L: ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * ldy xxx - * ldx #$00 - * lda label,y - */ +** +** lda #<(label+0) +** ldx #>(label+0) +** clc +** adc xxx +** bcc L +** inx +** L: ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** ldy xxx +** ldx #$00 +** lda label,y +*/ unsigned OptPtrLoad4 (CodeSeg* S); /* Search for the sequence: - * - * lda #<(label+0) - * ldx #>(label+0) - * ldy #$xx - * clc - * adc (sp),y - * bcc L - * inx - * L: ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * ldy #$xx - * lda (sp),y - * tay - * ldx #$00 - * lda label,y - */ +** +** lda #<(label+0) +** ldx #>(label+0) +** ldy #$xx +** clc +** adc (sp),y +** bcc L +** inx +** L: ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** ldy #$xx +** lda (sp),y +** tay +** ldx #$00 +** lda label,y +*/ unsigned OptPtrLoad5 (CodeSeg* S); /* Search for the sequence: - * - * jsr pushax - * ldx #$00 - * lda yyy - * jsr tosaddax - * ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * sta ptr1 - * stx ptr1+1 - * ldy yyy - * lda (ptr1),y - */ +** +** jsr pushax +** ldx #$00 +** lda yyy +** jsr tosaddax +** ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** sta ptr1 +** stx ptr1+1 +** ldy yyy +** lda (ptr1),y +*/ unsigned OptPtrLoad6 (CodeSeg* S); /* Search for the sequence: - * - * jsr pushax - * ldy xxx - * ldx #$00 - * lda (sp),y - * jsr tosaddax - * ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * sta ptr1 - * stx ptr1+1 - * ldy xxx - * lda (sp),y - * tay - * lda (ptr1),y - */ +** +** jsr pushax +** ldy xxx +** ldx #$00 +** lda (sp),y +** jsr tosaddax +** ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** sta ptr1 +** stx ptr1+1 +** ldy xxx +** lda (sp),y +** tay +** lda (ptr1),y +*/ unsigned OptPtrLoad7 (CodeSeg* S); /* Search for the sequence: - * - * jsr aslax1/shlax1 - * clc - * adc xxx - * tay - * txa - * adc yyy - * tax - * tya - * ldy zzz - * jsr ldaxidx - * - * and replace it by: - * - * stx tmp1 - * asl a - * rol tmp1 - * clc - * adc xxx - * sta ptr1 - * lda tmp1 - * adc yyy - * sta ptr1+1 - * ldy zzz - * lda (ptr1),y - * tax - * dey - * lda (ptr1),y - */ +** +** jsr aslax1/shlax1 +** clc +** adc xxx +** tay +** txa +** adc yyy +** tax +** tya +** ldy zzz +** jsr ldaxidx +** +** and replace it by: +** +** stx tmp1 +** asl a +** rol tmp1 +** clc +** adc xxx +** sta ptr1 +** lda tmp1 +** adc yyy +** sta ptr1+1 +** ldy zzz +** lda (ptr1),y +** tax +** dey +** lda (ptr1),y +*/ unsigned OptPtrLoad11 (CodeSeg* S); /* Search for the sequence: - * - * clc - * adc xxx - * bcc L - * inx - * L: ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * ldy xxx - * sta ptr1 - * stx ptr1+1 - * ldx #$00 - * lda (ptr1),y - */ +** +** clc +** adc xxx +** bcc L +** inx +** L: ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** ldy xxx +** sta ptr1 +** stx ptr1+1 +** ldx #$00 +** lda (ptr1),y +*/ unsigned OptPtrLoad12 (CodeSeg* S); /* Search for the sequence: - * - * lda regbank+n - * ldx regbank+n+1 - * sta regsave - * stx regsave+1 - * clc - * adc #$01 - * bcc L0005 - * inx - * L: sta regbank+n - * stx regbank+n+1 - * lda regsave - * ldx regsave+1 - * ldy #$00 - * jsr ldauidx - * - * and replace it by: - * - * ldy #$00 - * ldx #$00 - * lda (regbank+n),y - * inc regbank+n - * bne L1 - * inc regbank+n+1 - * L1: tay <- only if flags are used - * - * This function must execute before OptPtrLoad7! - * - */ +** +** lda regbank+n +** ldx regbank+n+1 +** sta regsave +** stx regsave+1 +** clc +** adc #$01 +** bcc L0005 +** inx +** L: sta regbank+n +** stx regbank+n+1 +** lda regsave +** ldx regsave+1 +** ldy #$00 +** jsr ldauidx +** +** and replace it by: +** +** ldy #$00 +** ldx #$00 +** lda (regbank+n),y +** inc regbank+n +** bne L1 +** inc regbank+n+1 +** L1: tay <- only if flags are used +** +** This function must execute before OptPtrLoad7! +** +*/ unsigned OptPtrLoad13 (CodeSeg* S); /* Search for the sequence: - * - * lda zp - * ldx zp+1 - * ldy xx - * jsr ldauidx - * - * and replace it by: - * - * ldy xx - * ldx #$00 - * lda (zp),y - */ +** +** lda zp +** ldx zp+1 +** ldy xx +** jsr ldauidx +** +** and replace it by: +** +** ldy xx +** ldx #$00 +** lda (zp),y +*/ unsigned OptPtrLoad14 (CodeSeg* S); /* Search for the sequence: - * - * lda zp - * ldx zp+1 - * (anything that doesn't change a/x) - * ldy xx - * jsr ldauidx - * - * and replace it by: - * - * lda zp - * ldx zp+1 - * (anything that doesn't change a/x) - * ldy xx - * ldx #$00 - * lda (zp),y - * - * Must execute before OptPtrLoad10! - */ +** +** lda zp +** ldx zp+1 +** (anything that doesn't change a/x) +** ldy xx +** jsr ldauidx +** +** and replace it by: +** +** lda zp +** ldx zp+1 +** (anything that doesn't change a/x) +** ldy xx +** ldx #$00 +** lda (zp),y +** +** Must execute before OptPtrLoad10! +*/ unsigned OptPtrLoad15 (CodeSeg* S); /* Search for the sequence: - * - * lda zp - * ldx zp+1 - * ldy xx - * jsr ldaxidx - * - * and replace it by: - * - * ldy xx - * lda (zp),y - * tax - * dey - * lda (zp),y - */ +** +** lda zp +** ldx zp+1 +** ldy xx +** jsr ldaxidx +** +** and replace it by: +** +** ldy xx +** lda (zp),y +** tax +** dey +** lda (zp),y +*/ unsigned OptPtrLoad16 (CodeSeg* S); /* Search for the sequence - * - * ldy ... - * jsr ldauidx - * - * and replace it by: - * - * ldy ... - * stx ptr1+1 - * sta ptr1 - * ldx #$00 - * lda (ptr1),y - * - * This step must be executed *after* OptPtrLoad1! - */ +** +** ldy ... +** jsr ldauidx +** +** and replace it by: +** +** ldy ... +** stx ptr1+1 +** sta ptr1 +** ldx #$00 +** lda (ptr1),y +** +** This step must be executed *after* OptPtrLoad1! +*/ unsigned OptPtrLoad17 (CodeSeg* S); /* Search for the sequence - * - * ldy ... - * jsr ldaxidx - * - * and replace it by: - * - * ldy ... - * sta ptr1 - * stx ptr1+1 - * lda (ptr1),y - * tax - * dey - * lda (ptr1),y - * - * This step must be executed *after* OptPtrLoad9! While code size increases - * by more than 200%, inlining will greatly improve visibility for the - * optimizer, so often part of the code gets improved later. So we will mark - * the step with less than 200% so it gets executed when -Oi is in effect. - */ +** +** ldy ... +** jsr ldaxidx +** +** and replace it by: +** +** ldy ... +** sta ptr1 +** stx ptr1+1 +** lda (ptr1),y +** tax +** dey +** lda (ptr1),y +** +** This step must be executed *after* OptPtrLoad9! While code size increases +** by more than 200%, inlining will greatly improve visibility for the +** optimizer, so often part of the code gets improved later. So we will mark +** the step with less than 200% so it gets executed when -Oi is in effect. +*/ /* End of coptptrload.h */ + #endif - - - diff --git a/src/cc65/coptptrstore.c b/src/cc65/coptptrstore.c index 646cec07f..11832910f 100644 --- a/src/cc65/coptptrstore.c +++ b/src/cc65/coptptrstore.c @@ -97,9 +97,9 @@ static unsigned OptPtrStore1Sub (CodeSeg* S, unsigned I, CodeEntry** const L) static const char* LoadAXZP (CodeSeg* S, unsigned I) /* If the two instructions preceeding S/I are a load of A/X from a two byte - * zero byte location, return the name of the zero page location. Otherwise - * return NULL. - */ +** zero byte location, return the name of the zero page location. Otherwise +** return NULL. +*/ { CodeEntry* L[2]; unsigned Len; @@ -131,11 +131,11 @@ static const char* LoadAXZP (CodeSeg* S, unsigned I) static const char* LoadAXImm (CodeSeg* S, unsigned I) /* If the instructions preceeding S/I are a load of A/X of a constant value - * or a word sized address label, return the address of the location as a - * string. - * Beware: In case of a numeric value, the result is returned in static - * storage which is overwritten with each call. - */ +** or a word sized address label, return the address of the location as a +** string. +** Beware: In case of a numeric value, the result is returned in static +** storage which is overwritten with each call. +*/ { static StrBuf Buf = STATIC_STRBUF_INITIALIZER; CodeEntry* L[2]; @@ -162,9 +162,9 @@ static const char* LoadAXImm (CodeSeg* S, unsigned I) } /* Search back for the two instructions loading A and X. Abort - * the search if the registers are changed in any other way or - * if a label is reached while we don't have both loads. - */ + ** the search if the registers are changed in any other way or + ** if a label is reached while we don't have both loads. + */ ALoad = 0; XLoad = 0; while (I-- > 0) { @@ -223,49 +223,49 @@ static const char* LoadAXImm (CodeSeg* S, unsigned I) unsigned OptPtrStore1 (CodeSeg* S) /* Search for the sequence: - * - * clc - * adc xxx - * bcc L - * inx - * L: jsr pushax - * ldx #$00 - * lda yyy - * ldy #$00 - * jsr staspidx - * - * and replace it by: - * - * sta ptr1 - * stx ptr1+1 - * ldy xxx - * ldx #$00 - * lda yyy - * sta (ptr1),y - * - * or by - * - * ldy xxx - * ldx #$00 - * lda yyy - * sta (zp),y - * - * or by - * - * ldy xxx - * ldx #$00 - * lda yyy - * sta label,y - * - * or by - * - * ldy xxx - * ldx #$00 - * lda yyy - * sta $xxxx,y - * - * depending on the code preceeding the sequence above. - */ +** +** clc +** adc xxx +** bcc L +** inx +** L: jsr pushax +** ldx #$00 +** lda yyy +** ldy #$00 +** jsr staspidx +** +** and replace it by: +** +** sta ptr1 +** stx ptr1+1 +** ldy xxx +** ldx #$00 +** lda yyy +** sta (ptr1),y +** +** or by +** +** ldy xxx +** ldx #$00 +** lda yyy +** sta (zp),y +** +** or by +** +** ldy xxx +** ldx #$00 +** lda yyy +** sta label,y +** +** or by +** +** ldy xxx +** ldx #$00 +** lda yyy +** sta $xxxx,y +** +** depending on the code preceeding the sequence above. +*/ { unsigned Changes = 0; unsigned I; @@ -309,22 +309,22 @@ unsigned OptPtrStore1 (CodeSeg* S) unsigned IP = I + 9; if ((Loc = LoadAXZP (S, I)) != 0) { /* If the sequence is preceeded by a load of a ZP value, - * we can use this ZP value as a pointer using ZP - * indirect Y addressing. - */ + ** we can use this ZP value as a pointer using ZP + ** indirect Y addressing. + */ AM = AM65_ZP_INDY; } else if ((Loc = LoadAXImm (S, I)) != 0) { /* If the sequence is preceeded by a load of an immediate - * value, we can use this absolute value as an address - * using absolute indexed Y addressing. - */ + ** value, we can use this absolute value as an address + ** using absolute indexed Y addressing. + */ AM = AM65_ABSY; } /* If we don't have a store location, we use ptr1 with zp - * indirect Y addressing. We must store the value in A/X into - * ptr1 in this case. - */ + ** indirect Y addressing. We must store the value in A/X into + ** ptr1 in this case. + */ if (Loc == 0) { /* Must use ptr1 */ @@ -340,10 +340,10 @@ unsigned OptPtrStore1 (CodeSeg* S) } /* If the index is loaded from (zp),y, we cannot do that directly. - * Note: In this case, the Y register will contain the correct - * value after removing the old code, so we don't need to load - * it here. - */ + ** Note: In this case, the Y register will contain the correct + ** value after removing the old code, so we don't need to load + ** it here. + */ if (L[1]->AM == AM65_ZP_INDY) { X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); @@ -388,54 +388,54 @@ unsigned OptPtrStore1 (CodeSeg* S) unsigned OptPtrStore2 (CodeSeg* S) /* Search for the sequence: - * - * clc - * adc xxx - * bcc L - * inx - * L: jsr pushax - * ldy yyy - * ldx #$00 - * lda (sp),y - * ldy #$00 - * jsr staspidx - * - * and replace it by: - * - * sta ptr1 - * stx ptr1+1 - * ldy yyy-2 - * ldx #$00 - * lda (sp),y - * ldy xxx - * sta (ptr1),y - * - * or by - * - * ldy yyy-2 - * ldx #$00 - * lda (sp),y - * ldy xxx - * sta (zp),y - * - * or by - * - * ldy yyy-2 - * ldx #$00 - * lda (sp),y - * ldy xxx - * sta label,y - * - * or by - * - * ldy yyy-2 - * ldx #$00 - * lda (sp),y - * ldy xxx - * sta $xxxx,y - * - * depending on the code preceeding the sequence above. - */ +** +** clc +** adc xxx +** bcc L +** inx +** L: jsr pushax +** ldy yyy +** ldx #$00 +** lda (sp),y +** ldy #$00 +** jsr staspidx +** +** and replace it by: +** +** sta ptr1 +** stx ptr1+1 +** ldy yyy-2 +** ldx #$00 +** lda (sp),y +** ldy xxx +** sta (ptr1),y +** +** or by +** +** ldy yyy-2 +** ldx #$00 +** lda (sp),y +** ldy xxx +** sta (zp),y +** +** or by +** +** ldy yyy-2 +** ldx #$00 +** lda (sp),y +** ldy xxx +** sta label,y +** +** or by +** +** ldy yyy-2 +** ldx #$00 +** lda (sp),y +** ldy xxx +** sta $xxxx,y +** +** depending on the code preceeding the sequence above. +*/ { unsigned Changes = 0; unsigned I; @@ -486,22 +486,22 @@ unsigned OptPtrStore2 (CodeSeg* S) unsigned IP = I + 10; if ((Loc = LoadAXZP (S, I)) != 0) { /* If the sequence is preceeded by a load of a ZP value, - * we can use this ZP value as a pointer using ZP - * indirect Y addressing. - */ + ** we can use this ZP value as a pointer using ZP + ** indirect Y addressing. + */ AM = AM65_ZP_INDY; } else if ((Loc = LoadAXImm (S, I)) != 0) { /* If the sequence is preceeded by a load of an immediate - * value, we can use this absolute value as an address - * using absolute indexed Y addressing. - */ + ** value, we can use this absolute value as an address + ** using absolute indexed Y addressing. + */ AM = AM65_ABSY; } /* If we don't have a store location, we use ptr1 with zp - * indirect Y addressing. We must store the value in A/X into - * ptr1 in this case. - */ + ** indirect Y addressing. We must store the value in A/X into + ** ptr1 in this case. + */ if (Loc == 0) { /* Must use ptr1 */ @@ -517,20 +517,20 @@ unsigned OptPtrStore2 (CodeSeg* S) } /* Generate four different replacements depending on the addressing - * mode of the store and from where the index is loaded: - * - * 1. If the index is not loaded ZP indirect Y, we can use Y for - * the store index. - * - * 2. If the index is loaded ZP indirect Y and we store absolute - * indexed, we need Y to load the index and will therefore - * use X as index for the store. The disadvantage is that we - * need to reload X later. - * - * 3. If the index is loaded ZP indirect Y and we store ZP indirect - * Y, we must use Y for load and store and must therefore save - * the A register when loading Y the second time. - */ + ** mode of the store and from where the index is loaded: + ** + ** 1. If the index is not loaded ZP indirect Y, we can use Y for + ** the store index. + ** + ** 2. If the index is loaded ZP indirect Y and we store absolute + ** indexed, we need Y to load the index and will therefore + ** use X as index for the store. The disadvantage is that we + ** need to reload X later. + ** + ** 3. If the index is loaded ZP indirect Y and we store ZP indirect + ** Y, we must use Y for load and store and must therefore save + ** the A register when loading Y the second time. + */ if (L[1]->AM != AM65_ZP_INDY) { /* Case 1 */ @@ -630,29 +630,28 @@ unsigned OptPtrStore2 (CodeSeg* S) unsigned OptPtrStore3 (CodeSeg* S) /* Search for the sequence: - * - * jsr pushax - * ldy xxx - * jsr ldauidx - * subop - * ldy yyy - * jsr staspidx - * - * and replace it by: - * - * sta ptr1 - * stx ptr1+1 - * ldy xxx - * ldx #$00 - * lda (ptr1),y - * subop - * ldy yyy - * sta (ptr1),y - * - * In case a/x is loaded from the register bank before the pushax, we can even - * use the register bank instead of ptr1. - * - */ +** +** jsr pushax +** ldy xxx +** jsr ldauidx +** subop +** ldy yyy +** jsr staspidx +** +** and replace it by: +** +** sta ptr1 +** stx ptr1+1 +** ldy xxx +** ldx #$00 +** lda (ptr1),y +** subop +** ldy yyy +** sta (ptr1),y +** +** In case a/x is loaded from the register bank before the pushax, we can even +** use the register bank instead of ptr1. +*/ { unsigned Changes = 0; @@ -689,10 +688,10 @@ unsigned OptPtrStore3 (CodeSeg* S) /* Get the preceeding two instructions and check them. We check - * for: - * lda regbank+n - * ldx regbank+n+1 - */ + ** for: + ** lda regbank+n + ** ldx regbank+n+1 + */ if (I > 1) { CodeEntry* P[2]; P[0] = CS_GetEntry (S, I-2); @@ -740,8 +739,8 @@ unsigned OptPtrStore3 (CodeSeg* S) } /* Delete more old code. Do it here to keep a label attached to - * entry I in place. - */ + ** entry I in place. + */ CS_DelEntry (S, I); /* jsr pushax */ /* Remember, we had changes */ @@ -757,6 +756,3 @@ unsigned OptPtrStore3 (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptptrstore.h b/src/cc65/coptptrstore.h index c6798ea30..3f8fc91f9 100644 --- a/src/cc65/coptptrstore.h +++ b/src/cc65/coptptrstore.h @@ -51,132 +51,128 @@ unsigned OptPtrStore1 (CodeSeg* S); /* Search for the sequence: - * - * clc - * adc xxx - * bcc L - * inx - * L: jsr pushax - * ldx #$00 - * lda yyy - * ldy #$00 - * jsr staspidx - * - * and replace it by: - * - * sta ptr1 - * stx ptr1+1 - * ldy xxx - * ldx #$00 - * lda yyy - * sta (ptr1),y - * - * or by - * - * ldy xxx - * ldx #$00 - * lda yyy - * sta (zp),y - * - * or by - * - * ldy xxx - * ldx #$00 - * lda yyy - * sta label,y - * - * or by - * - * ldy xxx - * ldx #$00 - * lda yyy - * sta $xxxx,y - * - * depending on the two instructions preceeding the sequence above. - */ +** +** clc +** adc xxx +** bcc L +** inx +** L: jsr pushax +** ldx #$00 +** lda yyy +** ldy #$00 +** jsr staspidx +** +** and replace it by: +** +** sta ptr1 +** stx ptr1+1 +** ldy xxx +** ldx #$00 +** lda yyy +** sta (ptr1),y +** +** or by +** +** ldy xxx +** ldx #$00 +** lda yyy +** sta (zp),y +** +** or by +** +** ldy xxx +** ldx #$00 +** lda yyy +** sta label,y +** +** or by +** +** ldy xxx +** ldx #$00 +** lda yyy +** sta $xxxx,y +** +** depending on the two instructions preceeding the sequence above. +*/ unsigned OptPtrStore2 (CodeSeg* S); /* Search for the sequence: - * - * clc - * adc xxx - * bcc L - * inx - * L: jsr pushax - * ldy yyy - * ldx #$00 - * lda (sp),y - * ldy #$00 - * jsr staspidx - * - * and replace it by: - * - * sta ptr1 - * stx ptr1+1 - * ldy yyy-2 - * ldx #$00 - * lda (sp),y - * ldy xxx - * sta (ptr1),y - * - * or by - * - * ldy yyy-2 - * ldx #$00 - * lda (sp),y - * ldy xxx - * sta (zp),y - * - * or by - * - * ldy yyy-2 - * ldx #$00 - * lda (sp),y - * ldy xxx - * sta label,y - * - * or by - * - * ldy yyy-2 - * ldx #$00 - * lda (sp),y - * ldy xxx - * sta $xxxx,y - * - * depending on the code preceeding the sequence above. - */ +** +** clc +** adc xxx +** bcc L +** inx +** L: jsr pushax +** ldy yyy +** ldx #$00 +** lda (sp),y +** ldy #$00 +** jsr staspidx +** +** and replace it by: +** +** sta ptr1 +** stx ptr1+1 +** ldy yyy-2 +** ldx #$00 +** lda (sp),y +** ldy xxx +** sta (ptr1),y +** +** or by +** +** ldy yyy-2 +** ldx #$00 +** lda (sp),y +** ldy xxx +** sta (zp),y +** +** or by +** +** ldy yyy-2 +** ldx #$00 +** lda (sp),y +** ldy xxx +** sta label,y +** +** or by +** +** ldy yyy-2 +** ldx #$00 +** lda (sp),y +** ldy xxx +** sta $xxxx,y +** +** depending on the code preceeding the sequence above. +*/ unsigned OptPtrStore3 (CodeSeg* S); /* Search for the sequence: - * - * jsr pushax - * ldy xxx - * jsr ldauidx - * subop - * ldy yyy - * jsr staspidx - * - * and replace it by: - * - * sta ptr1 - * stx ptr1+1 - * ldy xxx - * ldx #$00 - * lda (ptr1),y - * subop - * ldy yyy - * sta (ptr1),y - * - * In case a/x is loaded from the register bank before the pushax, we can even - * use the register bank instead of ptr1. - * - */ +** +** jsr pushax +** ldy xxx +** jsr ldauidx +** subop +** ldy yyy +** jsr staspidx +** +** and replace it by: +** +** sta ptr1 +** stx ptr1+1 +** ldy xxx +** ldx #$00 +** lda (ptr1),y +** subop +** ldy yyy +** sta (ptr1),y +** +** In case a/x is loaded from the register bank before the pushax, we can even +** use the register bank instead of ptr1. +*/ /* End of coptptrstore.h */ + #endif - - - - diff --git a/src/cc65/coptpush.c b/src/cc65/coptpush.c index a1ed700f6..5c3daffca 100644 --- a/src/cc65/coptpush.c +++ b/src/cc65/coptpush.c @@ -48,17 +48,17 @@ unsigned OptPush1 (CodeSeg* S) /* Given a sequence - * - * jsr ldaxysp - * jsr pushax - * - * If a/x are not used later, and Y is known, replace that by - * - * ldy #xx+2 - * jsr pushwysp - * - * saving 3 bytes and several cycles. - */ +** +** jsr ldaxysp +** jsr pushax +** +** If a/x are not used later, and Y is known, replace that by +** +** ldy #xx+2 +** jsr pushwysp +** +** saving 3 bytes and several cycles. +*/ { unsigned I; unsigned Changes = 0; @@ -115,15 +115,14 @@ unsigned OptPush1 (CodeSeg* S) unsigned OptPush2 (CodeSeg* S) /* A sequence - * - * jsr ldaxidx - * jsr pushax - * - * may get replaced by - * - * jsr pushwidx - * - */ +** +** jsr ldaxidx +** jsr pushax +** +** may get replaced by +** +** jsr pushwidx +*/ { unsigned I; unsigned Changes = 0; @@ -166,6 +165,3 @@ unsigned OptPush2 (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptpush.h b/src/cc65/coptpush.h index 0cd01dde8..0d637e824 100644 --- a/src/cc65/coptpush.h +++ b/src/cc65/coptpush.h @@ -51,36 +51,32 @@ unsigned OptPush1 (CodeSeg* S); /* Given a sequence - * - * ldy #xx - * jsr ldaxysp - * jsr pushax - * - * If a/x are not used later, replace that by - * - * ldy #xx+2 - * jsr pushwysp - * - * saving 3 bytes and several cycles. - */ +** +** ldy #xx +** jsr ldaxysp +** jsr pushax +** +** If a/x are not used later, replace that by +** +** ldy #xx+2 +** jsr pushwysp +** +** saving 3 bytes and several cycles. +*/ unsigned OptPush2 (CodeSeg* S); /* A sequence - * - * jsr ldaxidx - * jsr pushax - * - * may get replaced by - * - * jsr pushwidx - * - */ +** +** jsr ldaxidx +** jsr pushax +** +** may get replaced by +** +** jsr pushwidx +*/ /* End of coptpush.h */ #endif - - - diff --git a/src/cc65/coptshift.c b/src/cc65/coptshift.c index 933c3dfa3..a4b993073 100644 --- a/src/cc65/coptshift.c +++ b/src/cc65/coptshift.c @@ -190,15 +190,14 @@ static unsigned GetShift (const char* Name) unsigned OptShift1 (CodeSeg* S) /* A call to the shlaxN routine may get replaced by one or more asl insns - * if the value of X is not used later. If X is used later, but it is zero - * on entry and it's a shift by one, it may get replaced by: - * - * asl a - * bcc L1 - * inx - * L1: - * - */ +** if the value of X is not used later. If X is used later, but it is zero +** on entry and it's a shift by one, it may get replaced by: +** +** asl a +** bcc L1 +** inx +** L1: +*/ { unsigned Changes = 0; unsigned I; @@ -233,12 +232,12 @@ unsigned OptShift1 (CodeSeg* S) } /* Change into - * - * L1: asl a - * dey - * bpl L1 - * ror a - */ + ** + ** L1: asl a + ** dey + ** bpl L1 + ** ror a + */ /* asl a */ X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI); @@ -310,12 +309,11 @@ NextEntry: unsigned OptShift2(CodeSeg* S) /* A call to the asrax1 routines may get replaced by something simpler, if - * X is not used later: - * - * cmp #$80 - * ror a - * - */ +** X is not used later: +** +** cmp #$80 +** ror a +*/ { unsigned Changes = 0; unsigned I; @@ -372,21 +370,21 @@ unsigned OptShift2(CodeSeg* S) unsigned OptShift3 (CodeSeg* S) /* The sequence - * - * bcc L - * inx - * L: jsr shrax1 - * - * may get replaced by - * - * ror a - * - * if X is zero on entry. For shift counts > 1, more - * - * shr a - * - * must be added. - */ +** +** bcc L +** inx +** L: jsr shrax1 +** +** may get replaced by +** +** ror a +** +** if X is zero on entry. For shift counts > 1, more +** +** shr a +** +** must be added. +*/ { unsigned Changes = 0; unsigned I; @@ -444,8 +442,8 @@ unsigned OptShift3 (CodeSeg* S) unsigned OptShift4 (CodeSeg* S) /* Calls to the asraxN or shraxN routines may get replaced by one or more lsr - * insns if the value of X is zero. - */ +** insns if the value of X is zero. +*/ { unsigned Changes = 0; unsigned I; @@ -480,17 +478,17 @@ unsigned OptShift4 (CodeSeg* S) } /* Generate: - * - * L1: lsr a - * dey - * bpl L1 - * rol a - * - * A negative shift count or one that is greater or equal than - * the bit width of the left operand (which is promoted to - * integer before the operation) causes undefined behaviour, so - * above transformation is safe. - */ + ** + ** L1: lsr a + ** dey + ** bpl L1 + ** rol a + ** + ** A negative shift count or one that is greater or equal than + ** the bit width of the left operand (which is promoted to + ** integer before the operation) causes undefined behaviour, so + ** above transformation is safe. + */ /* lsr a */ X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, E->LI); @@ -540,24 +538,24 @@ NextEntry: unsigned OptShift5 (CodeSeg* S) /* Search for the sequence - * - * lda xxx - * ldx yyy - * jsr aslax1/asrax1/shlax1/shrax1 - * sta aaa - * stx bbb - * - * and replace it by - * - * lda xxx - * asl a - * sta aaa - * lda yyy - * rol a - * sta bbb - * - * or similar, provided that a/x is not used later - */ +** +** lda xxx +** ldx yyy +** jsr aslax1/asrax1/shlax1/shrax1 +** sta aaa +** stx bbb +** +** and replace it by +** +** lda xxx +** asl a +** sta aaa +** lda yyy +** rol a +** sta bbb +** +** or similar, provided that a/x is not used later +*/ { unsigned Changes = 0; @@ -684,19 +682,19 @@ unsigned OptShift6 (CodeSeg* S) (Count = SHIFT_COUNT (Shift)) > 0) { /* Code is: - * - * stx tmp1 - * asl a - * rol tmp1 - * (repeat ShiftCount-1 times) - * ldx tmp1 - * - * which makes 4 + 3 * ShiftCount bytes, compared to the original - * 3 bytes for the subroutine call. However, in most cases, the - * final load of the X register gets merged with some other insn - * and replaces a txa, so for a shift count of 1, we get a factor - * of 200, which matches nicely the CodeSizeFactor enabled with -Oi - */ + ** + ** stx tmp1 + ** asl a + ** rol tmp1 + ** (repeat ShiftCount-1 times) + ** ldx tmp1 + ** + ** which makes 4 + 3 * ShiftCount bytes, compared to the original + ** 3 bytes for the subroutine call. However, in most cases, the + ** final load of the X register gets merged with some other insn + ** and replaces a txa, so for a shift count of 1, we get a factor + ** of 200, which matches nicely the CodeSizeFactor enabled with -Oi + */ if (Count > 1 || S->CodeSizeFactor > 200) { unsigned Size = 4 + 3 * Count; if ((Size * 100 / 3) > S->CodeSizeFactor) { @@ -742,6 +740,3 @@ NextEntry: /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptshift.h b/src/cc65/coptshift.h index ce63e0e1b..0410652a1 100644 --- a/src/cc65/coptshift.h +++ b/src/cc65/coptshift.h @@ -51,68 +51,66 @@ unsigned OptShift1 (CodeSeg* S); /* A call to the shlaxN routine may get replaced by one or more asl insns - * if the value of X is not used later. If X is used later, but it is zero - * on entry and it's a shift by one, it may get replaced by: - * - * asl a - * bcc L1 - * inx - * L1: - * - */ +** if the value of X is not used later. If X is used later, but it is zero +** on entry and it's a shift by one, it may get replaced by: +** +** asl a +** bcc L1 +** inx +** L1: +*/ unsigned OptShift2(CodeSeg* S); /* A call to the asrax1 routines may get replaced by something simpler, if - * X is not used later: - * - * cmp #$80 - * ror a - * - */ +** X is not used later: +** +** cmp #$80 +** ror a +*/ unsigned OptShift3 (CodeSeg* S); /* The sequence - * - * bcc L - * inx - * L: jsr shrax1 - * - * may get replaced by - * - * ror a - * - * if X is zero on entry and unused later. For shift counts > 1, more - * - * shr a - * - * must be added. - */ +** +** bcc L +** inx +** L: jsr shrax1 +** +** may get replaced by +** +** ror a +** +** if X is zero on entry and unused later. For shift counts > 1, more +** +** shr a +** +** must be added. +*/ unsigned OptShift4 (CodeSeg* S); /* Calls to the asraxN or shraxN routines may get replaced by one or more lsr - * insns if the value of X is zero. - */ +** insns if the value of X is zero. +*/ unsigned OptShift5 (CodeSeg* S); /* Search for the sequence - * - * lda xxx - * ldx yyy - * jsr aslax1/asrax1/shlax1/shrax1 - * sta aaa - * stx bbb - * - * and replace it by - * - * lda xxx - * asl a - * sta aaa - * lda yyy - * rol a - * sta bbb - * - * or similar, provided that a/x is not used later - */ +** +** lda xxx +** ldx yyy +** jsr aslax1/asrax1/shlax1/shrax1 +** sta aaa +** stx bbb +** +** and replace it by +** +** lda xxx +** asl a +** sta aaa +** lda yyy +** rol a +** sta bbb +** +** or similar, provided that a/x is not used later +*/ unsigned OptShift6 (CodeSeg* S); /* Inline the shift subroutines. */ @@ -120,7 +118,5 @@ unsigned OptShift6 (CodeSeg* S); /* End of coptshift.h */ + #endif - - - diff --git a/src/cc65/coptsize.c b/src/cc65/coptsize.c index 0848bab0e..5c23e637c 100644 --- a/src/cc65/coptsize.c +++ b/src/cc65/coptsize.c @@ -65,12 +65,12 @@ struct CallDesc { }; /* Note: The table is sorted. If there is more than one entry with the same - * name, entries are sorted best match first, so when searching linear for - * a match, the first one can be used because it is also the best one (or - * at least none of the following ones are better). - * Note^2: Ptr1 and Tmp1 aren't evaluated, because runtime routines don't - * expect parameters here. - */ +** name, entries are sorted best match first, so when searching linear for +** a match, the first one can be used because it is also the best one (or +** at least none of the following ones are better). +** Note^2: Ptr1 and Tmp1 aren't evaluated, because runtime routines don't +** expect parameters here. +*/ static const CallDesc CallTable [] = { /* Name A register X register Y register flags replacement */ { @@ -818,8 +818,8 @@ static const CallDesc CallTable [] = { static const CallDesc* FindCall (const char* Name) /* Find the function with the given name. Return a pointer to the table entry - * or NULL if the function was not found. - */ +** or NULL if the function was not found. +*/ { /* Do a binary search */ int First = 0; @@ -839,8 +839,8 @@ static const CallDesc* FindCall (const char* Name) Last = Current - 1; if (Result == 0) { /* Found. Repeat the procedure until the first of all entries - * with the same name is found. - */ + ** with the same name is found. + */ Found = 1; } } @@ -854,8 +854,8 @@ static const CallDesc* FindCall (const char* Name) static int RegMatch (short Expected, short Actual) /* Check for a register match. If Expected has a value, it must be identical - * to Actual. - */ +** to Actual. +*/ { return RegValIsUnknown (Expected) || (Expected == Actual); } @@ -870,9 +870,9 @@ static int RegMatch (short Expected, short Actual) unsigned OptSize1 (CodeSeg* S) /* Do size optimization by calling special subroutines that preload registers. - * This routine does not work standalone, it needs a following register load - * removal pass. - */ +** This routine does not work standalone, it needs a following register load +** removal pass. +*/ { CodeEntry* E; unsigned Changes = 0; @@ -897,14 +897,14 @@ unsigned OptSize1 (CodeSeg* S) const RegContents* In = &E->RI->In; /* FindCall finds the first entry that matches our function name. - * The names are listed in "best match" order, so search for the - * first one, that fulfills our conditions. - */ + ** The names are listed in "best match" order, so search for the + ** first one, that fulfills our conditions. + */ while (1) { /* Check the registers and allow slower code only if - * optimizing for size. - */ + ** optimizing for size. + */ if ((OptForSize || (D->Flags & F_SLOWER) == 0) && RegMatch (D->Regs.RegA, In->RegA) && RegMatch (D->Regs.RegX, In->RegX) && @@ -947,9 +947,9 @@ unsigned OptSize1 (CodeSeg* S) unsigned OptSize2 (CodeSeg* S) /* Do size optimization by using shorter code sequences, even if this - * introduces relations between instructions. This step must be one of the - * last steps, because it makes further work much more difficult. - */ +** introduces relations between instructions. This step must be one of the +** last steps, because it makes further work much more difficult. +*/ { unsigned Changes = 0; unsigned I; @@ -1034,6 +1034,3 @@ unsigned OptSize2 (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptsize.h b/src/cc65/coptsize.h index f1dc07e46..7df866824 100644 --- a/src/cc65/coptsize.h +++ b/src/cc65/coptsize.h @@ -51,20 +51,18 @@ unsigned OptSize1 (CodeSeg* S); /* Do size optimization by calling special subroutines that preload registers. - * This routine does not work standalone, it needs a following register load - * removal pass. - */ +** This routine does not work standalone, it needs a following register load +** removal pass. +*/ unsigned OptSize2 (CodeSeg* S); /* Do size optimization by using shorter code sequences, even if this - * introduces relations between instructions. This step must be one of the - * last steps, because it makes further work much more difficult. - */ +** introduces relations between instructions. This step must be one of the +** last steps, because it makes further work much more difficult. +*/ /* End of coptsize.h */ + #endif - - - diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index dfa14d3f8..427d0bd13 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -192,8 +192,8 @@ static void ClearLoadInfo (LoadInfo* LI) static void AdjustLoadRegInfo (LoadRegInfo* RI, int Index, int Change) /* Adjust a load register info struct after deleting or inserting an entry - * with a given index - */ +** with a given index +*/ { CHECK (abs (Change) == 1); if (Change < 0) { @@ -276,9 +276,9 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I) CHECK (RI != 0); /* If we had a load or xfer op before, this is a duplicate load which - * can cause problems if it encountered between the pushax and the op, - * so remember it. - */ + ** can cause problems if it encountered between the pushax and the op, + ** so remember it. + */ if (RI->LoadIndex >= 0 || RI->XferIndex >= 0) { RI->Flags |= LI_DUP_LOAD; } @@ -296,11 +296,11 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I) RegValIsKnown (E->RI->In.RegY) && strcmp (E->Arg, "sp") == 0) { /* A load from the stack with known offset is also ok, but in this - * case we must reload the index register later. Please note that - * a load indirect via other zero page locations is not ok, since - * these locations may change between the push and the actual - * operation. - */ + ** case we must reload the index register later. Please note that + ** a load indirect via other zero page locations is not ok, since + ** these locations may change between the push and the actual + ** operation. + */ RI->Offs = (unsigned char) E->RI->In.RegY; RI->Flags |= (LI_DIRECT | LI_RELOAD_Y); } @@ -322,9 +322,9 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I) } /* If we had a load or xfer op before, this is a duplicate load which - * can cause problems if it encountered between the pushax and the op, - * so remember it. - */ + ** can cause problems if it encountered between the pushax and the op, + ** so remember it. + */ if (Tgt->LoadIndex >= 0 || Tgt->XferIndex >= 0) { Tgt->Flags |= LI_DUP_LOAD; } @@ -339,9 +339,9 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I) } else if (CE_IsCallTo (E, "ldaxysp") && RegValIsKnown (E->RI->In.RegY)) { /* If we had a load or xfer op before, this is a duplicate load which - * can cause problems if it encountered between the pushax and the op, - * so remember it for both registers involved. - */ + ** can cause problems if it encountered between the pushax and the op, + ** so remember it for both registers involved. + */ if (LI->A.LoadIndex >= 0 || LI->A.XferIndex >= 0) { LI->A.Flags |= LI_DUP_LOAD; } @@ -378,8 +378,8 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I) static void InsertEntry (StackOpData* D, CodeEntry* E, int Index) /* Insert a new entry. Depending on Index, D->PushIndex and D->OpIndex will - * be adjusted by this function. - */ +** be adjusted by this function. +*/ { /* Insert the entry into the code segment */ CS_InsertEntry (D->Code, E, Index); @@ -401,8 +401,8 @@ static void InsertEntry (StackOpData* D, CodeEntry* E, int Index) static void DelEntry (StackOpData* D, int Index) /* Delete an entry. Depending on Index, D->PushIndex and D->OpIndex will be - * adjusted by this function, and PushEntry/OpEntry may get invalidated. - */ +** adjusted by this function, and PushEntry/OpEntry may get invalidated. +*/ { /* Delete the entry from the code segment */ CS_DelEntry (D->Code, Index); @@ -428,8 +428,8 @@ static void DelEntry (StackOpData* D, int Index) static void AdjustStackOffset (StackOpData* D, unsigned Offs) /* Adjust the offset for all stack accesses in the range PushIndex to OpIndex. - * OpIndex is adjusted according to the insertions. - */ +** OpIndex is adjusted according to the insertions. +*/ { /* Walk over all entries */ int I = D->PushIndex + 1; @@ -457,8 +457,8 @@ static void AdjustStackOffset (StackOpData* D, unsigned Offs) if (NeedCorrection) { /* Get the code entry before this one. If it's a LDY, adjust the - * value. - */ + ** value. + */ CodeEntry* P = CS_GetPrevEntry (D->Code, I); if (P && P->OPC == OP65_LDY && CE_IsConstImm (P)) { @@ -490,8 +490,8 @@ static void AdjustStackOffset (StackOpData* D, unsigned Offs) } /* If we have rhs load insns that load from stack, we'll have to adjust - * the offsets for these also. - */ + ** the offsets for these also. + */ if (D->Rhs.A.Flags & LI_RELOAD_Y) { D->Rhs.A.Offs -= Offs; } @@ -522,14 +522,14 @@ static void AddStoreX (StackOpData* D) static void ReplacePushByStore (StackOpData* D) /* Replace the call to the push subroutine by a store into the zero page - * location (actually, the push is not replaced, because we need it for - * later, but the name is still ok since the push will get removed at the - * end of each routine). - */ +** location (actually, the push is not replaced, because we need it for +** later, but the name is still ok since the push will get removed at the +** end of each routine). +*/ { /* Store the value into the zeropage instead of pushing it. Check high - * byte first so that the store is later in A/X order. - */ + ** byte first so that the store is later in A/X order. + */ if ((D->Lhs.X.Flags & LI_DIRECT) == 0) { AddStoreX (D); } @@ -542,16 +542,16 @@ static void ReplacePushByStore (StackOpData* D) static void AddOpLow (StackOpData* D, opc_t OPC, LoadInfo* LI) /* Add an op for the low byte of an operator. This function honours the - * OP_DIRECT and OP_RELOAD_Y flags and generates the necessary instructions. - * All code is inserted at the current insertion point. - */ +** OP_DIRECT and OP_RELOAD_Y flags and generates the necessary instructions. +** All code is inserted at the current insertion point. +*/ { CodeEntry* X; if ((LI->A.Flags & LI_DIRECT) != 0) { /* Op with a variable location. If the location is on the stack, we - * need to reload the Y register. - */ + ** need to reload the Y register. + */ if ((LI->A.Flags & LI_RELOAD_Y) == 0) { /* opc ... */ @@ -588,9 +588,9 @@ static void AddOpLow (StackOpData* D, opc_t OPC, LoadInfo* LI) static void AddOpHigh (StackOpData* D, opc_t OPC, LoadInfo* LI, int KeepResult) /* Add an op for the high byte of an operator. Special cases (constant values - * or similar) have to be checked separately, the function covers only the - * generic case. Code is inserted at the insertion point. - */ +** or similar) have to be checked separately, the function covers only the +** generic case. Code is inserted at the insertion point. +*/ { CodeEntry* X; @@ -651,8 +651,8 @@ static void RemoveRegLoads (StackOpData* D, LoadInfo* LI) /* Remove register load insns */ { /* Both registers may be loaded with one insn, but DelEntry will in this - * case clear the other one. - */ + ** case clear the other one. + */ if ((LI->A.Flags & (LI_REMOVE | LI_DONT_REMOVE)) == LI_REMOVE) { if (LI->A.LoadIndex >= 0) { DelEntry (D, LI->A.LoadIndex); @@ -689,9 +689,9 @@ static void RemoveRemainders (StackOpData* D) static int IsRegVar (StackOpData* D) /* If the value pushed is that of a zeropage variable, replace ZPLo and ZPHi - * in the given StackOpData struct by the variable and return true. Otherwise - * leave D untouched and return false. - */ +** in the given StackOpData struct by the variable and return true. Otherwise +** leave D untouched and return false. +*/ { CodeEntry* LoadA = D->Lhs.A.LoadEntry; CodeEntry* LoadX = D->Lhs.X.LoadEntry; @@ -735,16 +735,16 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer CodeLabel* L; /* Create a call to the boolean transformer function and a label for this - * insn. This is needed for all variants. Other insns are inserted *before* - * the call. - */ + ** insn. This is needed for all variants. Other insns are inserted *before* + ** the call. + */ X = NewCodeEntry (OP65_JSR, AM65_ABS, BoolTransformer, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex + 1); L = CS_GenLabel (D->Code, X); /* If the lhs is direct (but not stack relative), encode compares with lhs - * effectively reverting the order (which doesn't matter for ==). - */ + ** effectively reverting the order (which doesn't matter for ==). + */ if ((D->Lhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT && (D->Lhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) { @@ -766,8 +766,12 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer InsertEntry (D, X, D->IP++); /* Lhs load entries can be removed */ - D->Lhs.X.Flags |= LI_REMOVE; - D->Lhs.A.Flags |= LI_REMOVE; + if (LoadX->AM != AM65_IMM) { + D->Lhs.X.Flags |= LI_REMOVE; + } + if (LoadA->AM != AM65_IMM) { + D->Lhs.A.Flags |= LI_REMOVE; + } } else if ((D->Rhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT && (D->Rhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) { @@ -790,8 +794,12 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer InsertEntry (D, X, D->IP++); /* Rhs load entries can be removed */ - D->Rhs.X.Flags |= LI_REMOVE; - D->Rhs.A.Flags |= LI_REMOVE; + if (LoadX->AM != AM65_IMM) { + D->Rhs.X.Flags |= LI_REMOVE; + } + if (LoadA->AM != AM65_IMM) { + D->Rhs.A.Flags |= LI_REMOVE; + } } else if ((D->Rhs.A.Flags & LI_DIRECT) != 0 && (D->Rhs.X.Flags & LI_DIRECT) != 0) { @@ -848,8 +856,8 @@ static unsigned Opt_tosshift (StackOpData* D, const char* Name) ReplacePushByStore (D); /* If the lhs is direct (but not stack relative), we can just reload the - * data later. - */ + ** data later. + */ if ((D->Lhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT && (D->Lhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) { @@ -882,8 +890,8 @@ static unsigned Opt_tosshift (StackOpData* D, const char* Name) AddStoreA (D); /* Be sure to setup IP after adding the stores, otherwise it will get - * messed up. - */ + ** messed up. + */ D->IP = D->OpIndex+1; /* tay */ @@ -928,8 +936,8 @@ static unsigned Opt___bzero (StackOpData* D) } /* If the return value of __bzero is used, we have to add code to reload - * a/x from the pointer variable. - */ + ** a/x from the pointer variable. + */ if (RegAXUsed (D->Code, D->OpIndex+1)) { X = NewCodeEntry (OP65_LDA, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+1); @@ -938,8 +946,8 @@ static unsigned Opt___bzero (StackOpData* D) } /* X is always zero, A contains the size of the data area to zero. - * Note: A may be zero, in which case the operation is null op. - */ + ** Note: A may be zero, in which case the operation is null op. + */ if (D->OpEntry->RI->In.RegA != 0) { /* lda #$00 */ @@ -1074,8 +1082,8 @@ static unsigned Opt_staxspidx (StackOpData* D) InsertEntry (D, X, D->OpIndex+4); /* If we remove staxspidx, we must restore the Y register to what the - * function would return. - */ + ** function would return. + */ X = NewCodeEntry (OP65_LDY, AM65_IMM, "$00", 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+5); @@ -1098,16 +1106,16 @@ static unsigned Opt_tosaddax (StackOpData* D) CHECK (D->NextEntry != 0); /* Check if the X register is known and zero when the add is done, and - * if the add is followed by - * - * ldy #$00 - * jsr ldauidx ; or ldaidx - * - * If this is true, the addition does actually add an offset to a pointer - * before it is dereferenced. Since both subroutines take an offset in Y, - * we can pass the offset (instead of #$00) and remove the addition - * alltogether. - */ + ** if the add is followed by + ** + ** ldy #$00 + ** jsr ldauidx ; or ldaidx + ** + ** If this is true, the addition does actually add an offset to a pointer + ** before it is dereferenced. Since both subroutines take an offset in Y, + ** we can pass the offset (instead of #$00) and remove the addition + ** alltogether. + */ if (D->OpEntry->RI->In.RegX == 0 && D->NextEntry->OPC == OP65_LDY && CE_IsKnownImm (D->NextEntry, 0) && @@ -1123,17 +1131,17 @@ static unsigned Opt_tosaddax (StackOpData* D) AddStoreA (D); /* Replace the ldy by a tay. Be sure to create the new entry before - * deleting the ldy, since we will reference the line info from this - * insn. - */ + ** deleting the ldy, since we will reference the line info from this + ** insn. + */ X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, D->NextEntry->LI); DelEntry (D, D->OpIndex + 1); InsertEntry (D, X, D->OpIndex + 1); /* Replace the call to ldaidx/ldauidx. Since X is already zero, and - * the ptr is in the zero page location, we just need to load from - * the pointer, and fix X in case of ldaidx. - */ + ** the ptr is in the zero page location, we just need to load from + ** the pointer, and fix X in case of ldaidx. + */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, D->ZPLo, 0, N->LI); DelEntry (D, D->OpIndex + 2); InsertEntry (D, X, D->OpIndex + 2); @@ -1194,8 +1202,8 @@ static unsigned Opt_tosaddax (StackOpData* D) X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, D->OpEntry->LI); } else { /* Value of first op high byte is unknown. Load from ZP or - * original storage. - */ + ** original storage. + */ if (D->Lhs.X.Flags & LI_DIRECT) { CodeEntry* LoadX = D->Lhs.X.LoadEntry; X = NewCodeEntry (OP65_LDX, LoadX->AM, LoadX->Arg, 0, D->OpEntry->LI); @@ -1690,8 +1698,8 @@ static int CmpFunc (const void* Key, const void* Func) static const OptFuncDesc* FindFunc (const char* Name) /* Find the function with the given name. Return a pointer to the table entry - * or NULL if the function was not found. - */ +** or NULL if the function was not found. +*/ { return bsearch (Name, FuncTable, FUNC_COUNT, sizeof(OptFuncDesc), CmpFunc); } @@ -1708,8 +1716,8 @@ static int CmpHarmless (const void* Key, const void* Entry) static int HarmlessCall (const char* Name) /* Check if this is a call to a harmless subroutine that will not interrupt - * the pushax/op sequence when encountered. - */ +** the pushax/op sequence when encountered. +*/ { static const char* Tab[] = { "aslax1", @@ -1784,9 +1792,9 @@ static void ResetStackOpData (StackOpData* Data) static int PreCondOk (StackOpData* D) /* Check if the preconditions for a call to the optimizer subfunction are - * satisfied. As a side effect, this function will also choose the zero page - * register to use. - */ +** satisfied. As a side effect, this function will also choose the zero page +** register to use. +*/ { /* Check the flags */ unsigned UnusedRegs = D->OptFunc->UnusedRegs; @@ -1882,20 +1890,20 @@ unsigned OptStackOps (CodeSeg* S) Data.Code = S; /* Look for a call to pushax followed by a call to some other function - * that takes it's first argument on the stack, and the second argument - * in the primary register. - * It depends on the code between the two if we can handle/transform the - * sequence, so check this code for the following list of things: - * - * - the range must be a basic block (one entry, one exit) - * - there may not be accesses to local variables with unknown - * offsets (because we have to adjust these offsets). - * - no subroutine calls - * - no jump labels - * - * Since we need a zero page register later, do also check the - * intermediate code for zero page use. - */ + ** that takes it's first argument on the stack, and the second argument + ** in the primary register. + ** It depends on the code between the two if we can handle/transform the + ** sequence, so check this code for the following list of things: + ** + ** - the range must be a basic block (one entry, one exit) + ** - there may not be accesses to local variables with unknown + ** offsets (because we have to adjust these offsets). + ** - no subroutine calls + ** - no jump labels + ** + ** Since we need a zero page register later, do also check the + ** intermediate code for zero page use. + */ I = 0; while (I < (int)CS_GetEntryCount (S)) { @@ -1913,8 +1921,8 @@ unsigned OptStackOps (CodeSeg* S) case Search: /* While searching, track register load insns, so we can tell - * what is in a register once pushax is encountered. - */ + ** what is in a register once pushax is encountered. + */ if (CE_HasLabel (E)) { /* Currently we don't track across branches */ ClearLoadInfo (&Data.Lhs); @@ -1930,9 +1938,9 @@ unsigned OptStackOps (CodeSeg* S) case FoundPush: /* We' found a pushax before. Search for a stack op that may - * follow and in the meantime, track zeropage usage and check - * for code that will disable us from translating the sequence. - */ + ** follow and in the meantime, track zeropage usage and check + ** for code that will disable us from translating the sequence. + */ if (CE_HasLabel (E)) { /* Currently we don't track across branches */ ClearLoadInfo (&Data.Rhs); @@ -1940,8 +1948,8 @@ unsigned OptStackOps (CodeSeg* S) if (E->OPC == OP65_JSR) { /* Subroutine call: Check if this is one of the functions, - * we're going to replace. - */ + ** we're going to replace. + */ Data.OptFunc = FindFunc (E->Arg); if (Data.OptFunc) { /* Remember the op index and go on */ @@ -1951,9 +1959,9 @@ unsigned OptStackOps (CodeSeg* S) break; } else if (!HarmlessCall (E->Arg)) { /* A call to an unkown subroutine: We need to start - * over after the last pushax. Note: This will also - * happen if we encounter a call to pushax! - */ + ** over after the last pushax. Note: This will also + ** happen if we encounter a call to pushax! + */ I = Data.PushIndex; State = Initialize; break; @@ -1966,8 +1974,8 @@ unsigned OptStackOps (CodeSeg* S) } else if (E->Info & OF_STORE && (E->Chg & REG_ZP) == 0) { /* Too dangerous - there may be a change of a variable - * within the sequence. - */ + ** within the sequence. + */ I = Data.PushIndex; State = Initialize; break; @@ -1978,13 +1986,13 @@ unsigned OptStackOps (CodeSeg* S) E->RI->In.RegY < 2)) { /* If we are using the stack, and we don't have "indirect Y" - * addressing mode, or the value of Y is unknown, or less - * than two, we cannot cope with this piece of code. Having - * an unknown value of Y means that we cannot correct the - * stack offset, while having an offset less than two means - * that the code works with the value on stack which is to - * be removed. - */ + ** addressing mode, or the value of Y is unknown, or less + ** than two, we cannot cope with this piece of code. Having + ** an unknown value of Y means that we cannot correct the + ** stack offset, while having an offset less than two means + ** that the code works with the value on stack which is to + ** be removed. + */ I = Data.PushIndex; State = Initialize; break; @@ -1995,9 +2003,9 @@ unsigned OptStackOps (CodeSeg* S) TrackLoads (&Data.Rhs, E, I); } /* If the registers from the push (A/X) are used before they're - * changed, we cannot change the sequence, because this would - * with a high probability change the register contents. - */ + ** changed, we cannot change the sequence, because this would + ** with a high probability change the register contents. + */ UsedRegs |= E->Use; if ((UsedRegs & ~ChangedRegs) & REG_AX) { I = Data.PushIndex; @@ -2016,9 +2024,9 @@ unsigned OptStackOps (CodeSeg* S) FinalizeLoadInfo (&Data.Rhs, S); /* If the Lhs loads do load from zeropage, we have to include - * them into UsedRegs registers used. The Rhs loads have already - * been tracked. - */ + ** them into UsedRegs registers used. The Rhs loads have already + ** been tracked. + */ if (Data.Lhs.A.LoadEntry && Data.Lhs.A.LoadEntry->AM == AM65_ZP) { Data.UsedRegs |= Data.Lhs.A.LoadEntry->Use; } @@ -2027,10 +2035,10 @@ unsigned OptStackOps (CodeSeg* S) } /* Check the preconditions. If they aren't ok, reset the insn - * pointer to the pushax and start over. We will loose part of - * load tracking but at least a/x has probably lost between - * pushax and here and will be tracked again when restarting. - */ + ** pointer to the pushax and start over. We will loose part of + ** load tracking but at least a/x has probably lost between + ** pushax and here and will be tracked again when restarting. + */ if (!PreCondOk (&Data)) { I = Data.PushIndex; State = Initialize; @@ -2050,16 +2058,16 @@ unsigned OptStackOps (CodeSeg* S) AdjustStackOffset (&Data, 2); /* Regenerate register info, since AdjustStackOffset changed - * the code - */ + ** the code + */ CS_GenRegInfo (S); /* Call the optimizer function */ Changes += Data.OptFunc->Func (&Data); /* Since the function may have added or deleted entries, - * correct the index. - */ + ** correct the index. + */ I += CS_GetEntryCount (S) - OldEntryCount; /* Regenerate register info */ @@ -2079,6 +2087,3 @@ unsigned OptStackOps (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptstop.h b/src/cc65/coptstop.h index 8abc25ece..4edf284c2 100644 --- a/src/cc65/coptstop.h +++ b/src/cc65/coptstop.h @@ -55,7 +55,5 @@ unsigned OptStackOps (CodeSeg* S); /* End of coptstop.h */ + #endif - - - diff --git a/src/cc65/coptstore.c b/src/cc65/coptstore.c index ea304e15d..56343c95b 100644 --- a/src/cc65/coptstore.c +++ b/src/cc65/coptstore.c @@ -56,14 +56,14 @@ static void InsertStore (CodeSeg* S, unsigned* IP, LineInfo* LI) unsigned OptStore1 (CodeSeg* S) /* Search for the sequence - * - * ldy #n - * jsr staxysp - * ldy #n+1 - * jsr ldaxysp - * - * and remove the useless load. - */ +** +** ldy #n +** jsr staxysp +** ldy #n+1 +** jsr ldaxysp +** +** and remove the useless load. +*/ { unsigned Changes = 0; @@ -108,9 +108,9 @@ unsigned OptStore1 (CodeSeg* S) unsigned OptStore2 (CodeSeg* S) /* Search for a call to staxysp. If the ax register is not used later, and - * the value is constant, just use the A register and store directly into the - * stack. - */ +** the value is constant, just use the A register and store directly into the +** stack. +*/ { unsigned I; unsigned Changes = 0; @@ -142,8 +142,8 @@ unsigned OptStore2 (CodeSeg* S) unsigned IP = I + 1; /* Insertion point */ /* Replace the store. We will not remove the loads, since this is - * too complex and will be done by other optimizer steps. - */ + ** too complex and will be done by other optimizer steps. + */ N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (A), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); @@ -178,9 +178,9 @@ unsigned OptStore2 (CodeSeg* S) unsigned OptStore3 (CodeSeg* S) /* Search for a call to steaxysp. If the eax register is not used later, and - * the value is constant, just use the A register and store directly into the - * stack. - */ +** the value is constant, just use the A register and store directly into the +** stack. +*/ { unsigned I; unsigned Changes = 0; @@ -217,8 +217,8 @@ unsigned OptStore3 (CodeSeg* S) unsigned IP = I + 1; /* Insertion point */ /* Replace the store. We will not remove the loads, since this is - * too complex and will be done by other optimizer steps. - */ + ** too complex and will be done by other optimizer steps. + */ N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (A), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); @@ -317,15 +317,15 @@ unsigned OptStore3 (CodeSeg* S) unsigned OptStore4 (CodeSeg* S) /* Search for the sequence - * - * sta xx - * stx yy - * lda xx - * ldx yy - * - * and remove the useless load, provided that the next insn doesn't use flags - * from the load. - */ +** +** sta xx +** stx yy +** lda xx +** ldx yy +** +** and remove the useless load, provided that the next insn doesn't use flags +** from the load. +*/ { unsigned Changes = 0; @@ -374,22 +374,22 @@ unsigned OptStore4 (CodeSeg* S) unsigned OptStore5 (CodeSeg* S) /* Search for the sequence - * - * lda foo - * ldx bar - * sta something - * stx something-else - * - * and replace it by - * - * lda foo - * sta something - * lda bar - * sta something-else - * - * if X is not used later. This replacement doesn't save any cycles or bytes, - * but it keeps the value of X, which may be reused later. - */ +** +** lda foo +** ldx bar +** sta something +** stx something-else +** +** and replace it by +** +** lda foo +** sta something +** lda bar +** sta something-else +** +** if X is not used later. This replacement doesn't save any cycles or bytes, +** but it keeps the value of X, which may be reused later. +*/ { unsigned Changes = 0; @@ -435,6 +435,3 @@ unsigned OptStore5 (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptstore.h b/src/cc65/coptstore.h index 0785566e0..fc93b40ea 100644 --- a/src/cc65/coptstore.h +++ b/src/cc65/coptstore.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2002-2006, Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -51,64 +51,61 @@ unsigned OptStore1 (CodeSeg* S); /* Search for the sequence - * - * ldy #n - * jsr staxysp - * ldy #n+1 - * jsr ldaxysp - * - * and remove the useless load, provided that the next insn doesn't use flags - * from the load. - */ +** +** ldy #n +** jsr staxysp +** ldy #n+1 +** jsr ldaxysp +** +** and remove the useless load, provided that the next insn doesn't use flags +** from the load. +*/ unsigned OptStore2 (CodeSeg* S); /* Search for a call to staxysp. If the ax register is not used later, and - * the value is constant, just use the A register and store directly into the - * stack. - */ +** the value is constant, just use the A register and store directly into the +** stack. +*/ unsigned OptStore3 (CodeSeg* S); /* Search for a call to steaxysp. If the eax register is not used later, and - * the value is constant, just use the A register and store directly into the - * stack. - */ +** the value is constant, just use the A register and store directly into the +** stack. +*/ unsigned OptStore4 (CodeSeg* S); /* Search for the sequence - * - * sta xx - * stx yy - * lda xx - * ldx yy - * - * and remove the useless load, provided that the next insn doesn't use flags - * from the load. - */ +** +** sta xx +** stx yy +** lda xx +** ldx yy +** +** and remove the useless load, provided that the next insn doesn't use flags +** from the load. +*/ unsigned OptStore5 (CodeSeg* S); /* Search for the sequence - * - * lda foo - * ldx bar - * sta something - * stx something-else - * - * and replace it by - * - * lda foo - * sta something - * lda bar - * sta something-else - * - * if X is not used later. This replacement doesn't save any cycles or bytes, - * but it keeps the value of X, which may be reused later. - */ +** +** lda foo +** ldx bar +** sta something +** stx something-else +** +** and replace it by +** +** lda foo +** sta something +** lda bar +** sta something-else +** +** if X is not used later. This replacement doesn't save any cycles or bytes, +** but it keeps the value of X, which may be reused later. +*/ /* End of coptstore.h */ #endif - - - diff --git a/src/cc65/coptsub.c b/src/cc65/coptsub.c index fdb167684..3d75c1f72 100644 --- a/src/cc65/coptsub.c +++ b/src/cc65/coptsub.c @@ -51,14 +51,14 @@ unsigned OptSub1 (CodeSeg* S) /* Search for the sequence - * - * sbc ... - * bcs L - * dex - * L: - * - * and remove the handling of the high byte if X is not used later. - */ +** +** sbc ... +** bcs L +** dex +** L: +** +** and remove the handling of the high byte if X is not used later. +*/ { unsigned Changes = 0; @@ -103,21 +103,21 @@ unsigned OptSub1 (CodeSeg* S) unsigned OptSub2 (CodeSeg* S) /* Search for the sequence - * - * lda xx - * sec - * sta tmp1 - * lda yy - * sbc tmp1 - * sta yy - * - * and replace it by - * - * sec - * lda yy - * sbc xx - * sta yy - */ +** +** lda xx +** sec +** sta tmp1 +** lda yy +** sbc tmp1 +** sta yy +** +** and replace it by +** +** sec +** lda yy +** sbc xx +** sta yy +*/ { unsigned Changes = 0; @@ -150,14 +150,14 @@ unsigned OptSub2 (CodeSeg* S) CS_DelEntry (S, I+3); /* Move the lda to the position of the subtraction and change the - * op to SBC. - */ + ** op to SBC. + */ CS_MoveEntry (S, I, I+3); CE_ReplaceOPC (E, OP65_SBC); /* If the sequence head had a label, move this label back to the - * head. - */ + ** head. + */ if (CE_HasLabel (E)) { CS_MoveLabels (S, E, L[0]); } @@ -180,8 +180,8 @@ unsigned OptSub2 (CodeSeg* S) unsigned OptSub3 (CodeSeg* S) /* Search for a call to decaxn and replace it by an 8 bit sub if the X register - * is not used later. - */ +** is not used later. +*/ { unsigned Changes = 0; @@ -228,6 +228,3 @@ unsigned OptSub3 (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/coptsub.h b/src/cc65/coptsub.h index c8249bdb2..5929612e6 100644 --- a/src/cc65/coptsub.h +++ b/src/cc65/coptsub.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2001-2006, Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -51,43 +51,40 @@ unsigned OptSub1 (CodeSeg* S); /* Search for the sequence - * - * sbc ... - * bcs L - * dex - * L: - * - * and remove the handling of the high byte if X is not used later. - */ +** +** sbc ... +** bcs L +** dex +** L: +** +** and remove the handling of the high byte if X is not used later. +*/ unsigned OptSub2 (CodeSeg* S); /* Search for the sequence - * - * lda xx - * sec - * sta tmp1 - * lda yy - * sbc tmp1 - * sta yy - * - * and replace it by - * - * sec - * lda yy - * sbc xx - * sta yy - */ +** +** lda xx +** sec +** sta tmp1 +** lda yy +** sbc tmp1 +** sta yy +** +** and replace it by +** +** sec +** lda yy +** sbc xx +** sta yy +*/ unsigned OptSub3 (CodeSeg* S); /* Search for a call to decaxn and replace it by an 8 bit sub if the X register - * is not used later. - */ +** is not used later. +*/ /* End of coptsub.h */ #endif - - - diff --git a/src/cc65/copttest.c b/src/cc65/copttest.c index 91ebdc7ad..5628a42c3 100644 --- a/src/cc65/copttest.c +++ b/src/cc65/copttest.c @@ -48,24 +48,23 @@ unsigned OptTest1 (CodeSeg* S) /* Given a sequence - * - * stx xxx - * ora xxx - * beq/bne ... - * - * If X is zero, the sequence may be changed to - * - * cmp #$00 - * beq/bne ... - * - * which may be optimized further by another step. - * - * If A is zero, the sequence may be changed to - * - * txa - * beq/bne ... - * - */ +** +** stx xxx +** ora xxx +** beq/bne ... +** +** If X is zero, the sequence may be changed to +** +** cmp #$00 +** beq/bne ... +** +** which may be optimized further by another step. +** +** If A is zero, the sequence may be changed to +** +** txa +** beq/bne ... +*/ { unsigned Changes = 0; unsigned I; @@ -131,9 +130,9 @@ unsigned OptTest1 (CodeSeg* S) unsigned OptTest2 (CodeSeg* S) /* Search for an inc/dec operation followed by a load and a conditional - * branch based on the flags from the load. Remove the load if the insn - * isn't used later. - */ +** branch based on the flags from the load. Remove the load if the insn +** isn't used later. +*/ { unsigned Changes = 0; @@ -169,6 +168,3 @@ unsigned OptTest2 (CodeSeg* S) /* Return the number of changes made */ return Changes; } - - - diff --git a/src/cc65/copttest.h b/src/cc65/copttest.h index f6af1da32..6f5810859 100644 --- a/src/cc65/copttest.h +++ b/src/cc65/copttest.h @@ -51,36 +51,32 @@ unsigned OptTest1 (CodeSeg* S); /* Given a sequence - * - * stx xxx - * ora xxx - * beq/bne ... - * - * If X is zero, the sequence may be changed to - * - * cmp #$00 - * beq/bne ... - * - * which may be optimized further by another step. - * - * If A is zero, the sequence may be changed to - * - * txa - * beq/bne ... - * - */ +** +** stx xxx +** ora xxx +** beq/bne ... +** +** If X is zero, the sequence may be changed to +** +** cmp #$00 +** beq/bne ... +** +** which may be optimized further by another step. +** +** If A is zero, the sequence may be changed to +** +** txa +** beq/bne ... +*/ unsigned OptTest2 (CodeSeg* S); /* Search for an inc/dec operation followed by a load and a conditional - * branch based on the flags from the load. Remove the load if the insn - * isn't used later. - */ +** branch based on the flags from the load. Remove the load if the insn +** isn't used later. +*/ /* End of copttest.h */ #endif - - - diff --git a/src/cc65/dataseg.c b/src/cc65/dataseg.c index c19791e9e..40ec6f793 100644 --- a/src/cc65/dataseg.c +++ b/src/cc65/dataseg.c @@ -130,7 +130,3 @@ void DS_Output (const DataSeg* S) /* Add an additional newline after the segment output */ WriteOutput ("\n"); } - - - - diff --git a/src/cc65/dataseg.h b/src/cc65/dataseg.h index c822120a8..dd99d4727 100644 --- a/src/cc65/dataseg.h +++ b/src/cc65/dataseg.h @@ -88,7 +88,5 @@ void DS_Output (const DataSeg* S); /* End of dataseg.h */ + #endif - - - diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 88ec9ead6..053810b50 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -118,8 +118,8 @@ Type* TypeDup (const Type* T) Type* TypeAlloc (unsigned Len) /* Allocate memory for a type string of length Len. Len *must* include the - * trailing T_END. - */ +** trailing T_END. +*/ { return xmalloc (Len * sizeof (Type)); } @@ -200,8 +200,8 @@ Type* GetImplicitFuncType (void) Type* PointerTo (const Type* T) /* Return a type string that is "pointer to T". The type string is allocated - * on the heap and may be freed after use. - */ +** on the heap and may be freed after use. +*/ { /* Get the size of the type string including the terminator */ unsigned Size = TypeLen (T) + 1; @@ -221,8 +221,8 @@ Type* PointerTo (const Type* T) static TypeCode PrintTypeComp (FILE* F, TypeCode C, TypeCode Mask, const char* Name) /* Check for a specific component of the type. If it is there, print the - * name and remove it. Return the type with the component removed. - */ +** name and remove it. Return the type with the component removed. +*/ { if ((C & Mask) == Mask) { fprintf (F, "%s ", Name); @@ -459,9 +459,9 @@ unsigned PSizeOf (const Type* T) unsigned CheckedSizeOf (const Type* T) /* Return the size of a data type. If the size is zero, emit an error and - * return some valid size instead (so the rest of the compiler doesn't have - * to work with invalid sizes). - */ +** return some valid size instead (so the rest of the compiler doesn't have +** to work with invalid sizes). +*/ { unsigned Size = SizeOf (T); if (Size == 0) { @@ -475,9 +475,9 @@ unsigned CheckedSizeOf (const Type* T) unsigned CheckedPSizeOf (const Type* T) /* Return the size of a data type that is pointed to by a pointer. If the - * size is zero, emit an error and return some valid size instead (so the - * rest of the compiler doesn't have to work with invalid sizes). - */ +** size is zero, emit an error and return some valid size instead (so the +** rest of the compiler doesn't have to work with invalid sizes). +*/ { unsigned Size = PSizeOf (T); if (Size == 0) { @@ -540,8 +540,8 @@ unsigned TypeOf (const Type* T) Type* Indirect (Type* T) /* Do one indirection for the given type, that is, return the type where the - * given type points to. - */ +** given type points to. +*/ { /* We are expecting a pointer expression */ CHECK (IsClassPtr (T)); @@ -563,8 +563,8 @@ Type* ArrayToPtr (Type* T) int IsVariadicFunc (const Type* T) /* Return true if this is a function type or pointer to function type with - * variable parameter list - */ +** variable parameter list +*/ { FuncDesc* F = GetFuncDesc (T); return (F->Flags & FD_VARIADIC) != 0; @@ -625,8 +625,8 @@ Type* GetFuncReturn (Type* T) long GetElementCount (const Type* T) /* Get the element count of the array specified in T (which must be of - * array type). - */ +** array type). +*/ { CHECK (IsTypeArray (T)); return T->A.L; @@ -636,8 +636,8 @@ long GetElementCount (const Type* T) void SetElementCount (Type* T, long Count) /* Set the element count of the array specified in T (which must be of - * array type). - */ +** array type). +*/ { CHECK (IsTypeArray (T)); T->A.L = Count; @@ -656,9 +656,9 @@ Type* GetElementType (Type* T) Type* GetBaseElementType (Type* T) /* Return the base element type of a given type. If T is not an array, this - * will return. Otherwise it will return the base element type, which means - * the element type that is not an array. - */ +** will return. Otherwise it will return the base element type, which means +** the element type that is not an array. +*/ { while (IsTypeArray (T)) { ++T; @@ -694,15 +694,15 @@ void SetSymEntry (Type* T, SymEntry* S) Type* IntPromotion (Type* T) /* Apply the integer promotions to T and return the result. The returned type - * string may be T if there is no need to change it. - */ +** string may be T if there is no need to change it. +*/ { /* We must have an int to apply int promotions */ PRECONDITION (IsClassInt (T)); /* An integer can represent all values from either signed or unsigned char, - * so convert chars to int and leave all other types alone. - */ + ** so convert chars to int and leave all other types alone. + */ if (IsTypeChar (T)) { return type_int; } else { @@ -714,9 +714,9 @@ Type* IntPromotion (Type* T) Type* PtrConversion (Type* T) /* If the type is a function, convert it to pointer to function. If the - * expression is an array, convert it to pointer to first element. Otherwise - * return T. - */ +** expression is an array, convert it to pointer to first element. Otherwise +** return T. +*/ { if (IsTypeFunc (T)) { return PointerTo (T); @@ -746,6 +746,3 @@ TypeCode AddrSizeQualifier (unsigned AddrSize) } } - - - diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index b49694da3..598d0a228 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -220,8 +220,8 @@ Type* TypeDup (const Type* T); Type* TypeAlloc (unsigned Len); /* Allocate memory for a type string of length Len. Len *must* include the - * trailing T_END. - */ +** trailing T_END. +*/ void TypeFree (Type* T); /* Free a type string */ @@ -240,8 +240,8 @@ Type* GetImplicitFuncType (void); Type* PointerTo (const Type* T); /* Return a type string that is "pointer to T". The type string is allocated - * on the heap and may be freed after use. - */ +** on the heap and may be freed after use. +*/ void PrintType (FILE* F, const Type* T); /* Output translation of type array. */ @@ -283,22 +283,22 @@ unsigned PSizeOf (const Type* T); unsigned CheckedSizeOf (const Type* T); /* Return the size of a data type. If the size is zero, emit an error and - * return some valid size instead (so the rest of the compiler doesn't have - * to work with invalid sizes). - */ +** return some valid size instead (so the rest of the compiler doesn't have +** to work with invalid sizes). +*/ unsigned CheckedPSizeOf (const Type* T); /* Return the size of a data type that is pointed to by a pointer. If the - * size is zero, emit an error and return some valid size instead (so the - * rest of the compiler doesn't have to work with invalid sizes). - */ +** size is zero, emit an error and return some valid size instead (so the +** rest of the compiler doesn't have to work with invalid sizes). +*/ unsigned TypeOf (const Type* T); /* Get the code generator base type of the object */ Type* Indirect (Type* T); /* Do one indirection for the given type, that is, return the type where the - * given type points to. - */ +** given type points to. +*/ Type* ArrayToPtr (Type* T); /* Convert an array to a pointer to it's first element */ @@ -605,8 +605,8 @@ INLINE int IsQualCDecl (const Type* T) int IsVariadicFunc (const Type* T) attribute ((const)); /* Return true if this is a function type or pointer to function type with - * variable parameter list - */ +** variable parameter list +*/ #if defined(HAVE_INLINE) INLINE TypeCode GetSizeModifier (const Type* T) @@ -629,22 +629,22 @@ Type* GetFuncReturn (Type* T) attribute ((const)); long GetElementCount (const Type* T); /* Get the element count of the array specified in T (which must be of - * array type). - */ +** array type). +*/ void SetElementCount (Type* T, long Count); /* Set the element count of the array specified in T (which must be of - * array type). - */ +** array type). +*/ Type* GetElementType (Type* T); /* Return the element type of the given array type. */ Type* GetBaseElementType (Type* T); /* Return the base element type of a given type. If T is not an array, this - * will return. Otherwise it will return the base element type, which means - * the element type that is not an array. - */ +** will return. Otherwise it will return the base element type, which means +** the element type that is not an array. +*/ struct SymEntry* GetSymEntry (const Type* T) attribute ((const)); /* Return a SymEntry pointer from a type */ @@ -654,14 +654,14 @@ void SetSymEntry (Type* T, struct SymEntry* S); Type* IntPromotion (Type* T); /* Apply the integer promotions to T and return the result. The returned type - * string may be T if there is no need to change it. - */ +** string may be T if there is no need to change it. +*/ Type* PtrConversion (Type* T); /* If the type is a function, convert it to pointer to function. If the - * expression is an array, convert it to pointer to first element. Otherwise - * return T. - */ +** expression is an array, convert it to pointer to first element. Otherwise +** return T. +*/ TypeCode AddrSizeQualifier (unsigned AddrSize); /* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */ @@ -691,6 +691,3 @@ INLINE TypeCode DataAddrSizeQualifier (void) /* End of datatype.h */ #endif - - - diff --git a/src/cc65/declare.c b/src/cc65/declare.c index c4debd8aa..693c2116e 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -108,8 +108,8 @@ static void DuplicateQualifier (const char* Name) static TypeCode OptionalQualifiers (TypeCode Allowed) /* Read type qualifiers if we have any. Allowed specifies the allowed - * qualifiers. - */ +** qualifiers. +*/ { /* We start without any qualifiers */ TypeCode Q = T_QUAL_NONE; @@ -286,9 +286,9 @@ static void NeedTypeSpace (Declaration* D, unsigned Count) { if (D->Index + Count >= MAXTYPELEN) { /* We must call Fatal() here, since calling Error() will try to - * continue, and the declaration type is not correctly terminated - * in case we come here. - */ + ** continue, and the declaration type is not correctly terminated + ** in case we come here. + */ Fatal ("Too many type specifiers"); } } @@ -311,9 +311,9 @@ static void FixQualifiers (Type* DataType) TypeCode Q; /* Using typedefs, it is possible to generate declarations that have - * type qualifiers attached to an array, not the element type. Go and - * fix these here. - */ + ** type qualifiers attached to an array, not the element type. Go and + ** fix these here. + */ T = DataType; Q = T_QUAL_NONE; while (T->C != T_END) { @@ -341,8 +341,8 @@ static void FixQualifiers (Type* DataType) /* Pointer to function which is not fastcall? */ if (IsTypeFunc (T+1) && !IsQualFastcall (T+1)) { /* Move the fastcall qualifier from the pointer to - * the function. - */ + ** the function. + */ T[0].C &= ~T_QUAL_FASTCALL; T[1].C |= T_QUAL_FASTCALL; } else { @@ -356,8 +356,8 @@ static void FixQualifiers (Type* DataType) /* No address size qualifiers specified */ if (IsTypeFunc (T+1)) { /* Pointer to function. Use the qualifier from the function - * or the default if the function don't has one. - */ + ** or the default if the function don't has one. + */ Q = (T[1].C & T_QUAL_ADDRSIZE); if (Q == T_QUAL_NONE) { Q = CodeAddrSizeQualifier (); @@ -368,8 +368,8 @@ static void FixQualifiers (Type* DataType) T[0].C |= Q; } else { /* We have address size qualifiers. If followed by a function, - * apply these also to the function. - */ + ** apply these also to the function. + */ if (IsTypeFunc (T+1)) { TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE); if (FQ == T_QUAL_NONE) { @@ -490,8 +490,8 @@ static void ParseEnumDecl (void) static int ParseFieldWidth (Declaration* Decl) /* Parse an optional field width. Returns -1 if no field width is speficied, - * otherwise the width of the field. - */ +** otherwise the width of the field. +*/ { ExprDesc Expr; @@ -531,8 +531,8 @@ static SymEntry* StructOrUnionForwardDecl (const char* Name, unsigned Type) /* Handle a struct or union forward decl */ { /* Try to find a struct/union with the given name. If there is none, - * insert a forward declaration into the current lexical level. - */ + ** insert a forward declaration into the current lexical level. + */ SymEntry* Entry = FindTagSym (Name); if (Entry == 0) { Entry = AddStructSym (Name, Type, 0, 0); @@ -547,8 +547,8 @@ static SymEntry* StructOrUnionForwardDecl (const char* Name, unsigned Type) static unsigned CopyAnonStructFields (const Declaration* Decl, int Offs) /* Copy fields from an anon union/struct into the current lexical level. The - * function returns the size of the embedded struct/union. - */ +** function returns the size of the embedded struct/union. +*/ { /* Get the pointer to the symbol table entry of the anon struct */ SymEntry* Entry = GetSymEntry (Decl->Type); @@ -557,8 +557,8 @@ static unsigned CopyAnonStructFields (const Declaration* Decl, int Offs) unsigned Size = Entry->V.S.Size; /* Get the symbol table containing the fields. If it is empty, there has - * been an error before, so bail out. - */ + ** been an error before, so bail out. + */ SymTable* Tab = Entry->V.S.SymTab; if (Tab == 0) { /* Incomplete definition - has been flagged before */ @@ -566,19 +566,19 @@ static unsigned CopyAnonStructFields (const Declaration* Decl, int Offs) } /* Get a pointer to the list of symbols. Then walk the list adding copies - * of the embedded struct to the current level. - */ + ** of the embedded struct to the current level. + */ Entry = Tab->SymHead; while (Entry) { /* Enter a copy of this symbol adjusting the offset. We will just - * reuse the type string here. - */ + ** reuse the type string here. + */ AddLocalSym (Entry->Name, Entry->Type, SC_STRUCTFIELD, Offs + Entry->V.Offs); /* Currently, there can not be any attributes, but if there will be - * some in the future, we want to know this. - */ + ** some in the future, we want to know this. + */ CHECK (Entry->Attr == 0); /* Next entry */ @@ -643,12 +643,12 @@ static SymEntry* ParseUnionDecl (const char* Name) /* Check for fields without a name */ if (Decl.Ident[0] == '\0') { /* In cc65 mode, we allow anonymous structs/unions within - * a struct. - */ + ** a struct. + */ if (IS_Get (&Standard) >= STD_CC65 && IsClassStruct (Decl.Type)) { /* This is an anonymous struct or union. Copy the fields - * into the current level. - */ + ** into the current level. + */ CopyAnonStructFields (&Decl, 0); } else { @@ -735,8 +735,8 @@ static SymEntry* ParseStructDecl (const char* Name) ident Ident; /* If we had a flexible array member before, no other fields can - * follow. - */ + ** follow. + */ if (FlexibleMember) { Error ("Flexible array member must be last field"); FlexibleMember = 0; /* Avoid further errors */ @@ -749,10 +749,10 @@ static SymEntry* ParseStructDecl (const char* Name) FieldWidth = ParseFieldWidth (&Decl); /* If this is not a bit field, or the bit field is too large for - * the remainder of the current member, or we have a bit field - * with width zero, align the struct to the next member by adding - * a member with an anonymous name. - */ + ** the remainder of the current member, or we have a bit field + ** with width zero, align the struct to the next member by adding + ** a member with an anonymous name. + */ if (BitOffs > 0) { if (FieldWidth <= 0 || (BitOffs + FieldWidth) > (int) INT_BITS) { @@ -760,8 +760,8 @@ static SymEntry* ParseStructDecl (const char* Name) AnonName (Ident, "bit-field"); /* Add an anonymous bit-field that aligns to the next - * storage unit. - */ + ** storage unit. + */ AddBitField (Ident, StructSize, BitOffs, INT_BITS - BitOffs); /* No bits left */ @@ -771,15 +771,15 @@ static SymEntry* ParseStructDecl (const char* Name) } /* Apart from the above, a bit field with width 0 is not processed - * further. - */ + ** further. + */ if (FieldWidth == 0) { goto NextMember; } /* Check if this field is a flexible array member, and - * calculate the size of the field. - */ + ** calculate the size of the field. + */ if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) { /* Array with unspecified size */ if (StructSize == 0) { @@ -794,13 +794,13 @@ static SymEntry* ParseStructDecl (const char* Name) if (Decl.Ident[0] == '\0') { if (FieldWidth < 0) { /* In cc65 mode, we allow anonymous structs/unions within - * a struct. - */ + ** a struct. + */ if (IS_Get (&Standard) >= STD_CC65 && IsClassStruct (Decl.Type)) { /* This is an anonymous struct or union. Copy the - * fields into the current level. - */ + ** fields into the current level. + */ StructSize += CopyAnonStructFields (&Decl, StructSize); } else { @@ -817,9 +817,9 @@ static SymEntry* ParseStructDecl (const char* Name) /* Add a field entry to the table */ if (FieldWidth > 0) { /* Add full byte from the bit offset to the variable offset. - * This simplifies handling he bit-field as a char type - * in expressions. - */ + ** This simplifies handling he bit-field as a char type + ** in expressions. + */ unsigned Offs = StructSize + (BitOffs / CHAR_BITS); AddBitField (Decl.Ident, Offs, BitOffs % CHAR_BITS, FieldWidth); BitOffs += FieldWidth; @@ -1103,8 +1103,8 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers) static Type* ParamTypeCvt (Type* T) /* If T is an array, convert it to a pointer else do nothing. Return the - * resulting type. - */ +** resulting type. +*/ { if (IsTypeArray (T)) { T->C = T_PTR; @@ -1152,8 +1152,8 @@ static void ParseOldStyleParamList (FuncDesc* F) } /* Skip right paren. We must explicitly check for one here, since some of - * the breaks above bail out without checking. - */ + ** the breaks above bail out without checking. + */ ConsumeRParen (); /* An optional list of type specifications follows */ @@ -1165,8 +1165,8 @@ static void ParseOldStyleParamList (FuncDesc* F) ParseDeclSpec (&Spec, SC_AUTO, T_INT); /* We accept only auto and register as storage class specifiers, but - * we ignore all this, since we use auto anyway. - */ + ** we ignore all this, since we use auto anyway. + */ if ((Spec.StorageClass & SC_AUTO) == 0 && (Spec.StorageClass & SC_REGISTER) == 0) { Error ("Illegal storage class"); @@ -1185,8 +1185,8 @@ static void ParseOldStyleParamList (FuncDesc* F) SymEntry* Sym = FindLocalSym (Decl.Ident); if (Sym) { /* Check if we already changed the type for this - * parameter - */ + ** parameter + */ if (Sym->Flags & SC_DEFTYPE) { /* Found it, change the default type to the one given */ ChangeSymType (Sym, ParamTypeCvt (Decl.Type)); @@ -1247,14 +1247,14 @@ static void ParseAnsiParamList (FuncDesc* F) } /* Allow parameters without a name, but remember if we had some to - * eventually print an error message later. - */ + ** eventually print an error message later. + */ ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT); if (Decl.Ident[0] == '\0') { /* Unnamed symbol. Generate a name that is not user accessible, - * then handle the symbol normal. - */ + ** then handle the symbol normal. + */ AnonName (Decl.Ident, "param"); F->Flags |= FD_UNNAMED_PARAMS; @@ -1290,8 +1290,8 @@ static void ParseAnsiParamList (FuncDesc* F) } /* Skip right paren. We must explicitly check for one here, since some of - * the breaks above bail out without checking. - */ + ** the breaks above bail out without checking. + */ ConsumeRParen (); } @@ -1320,8 +1320,8 @@ static FuncDesc* ParseFuncDecl (void) } else if (CurTok.Tok == TOK_IDENT && (NextTok.Tok == TOK_COMMA || NextTok.Tok == TOK_RPAREN)) { /* If the identifier is a typedef, we have a new style parameter list, - * if it's some other identifier, it's an old style parameter list. - */ + ** if it's some other identifier, it's an old style parameter list. + */ Sym = FindSym (CurTok.Ident); if (Sym == 0 || !SymIsTypeDef (Sym)) { /* Old style (K&R) function. */ @@ -1341,15 +1341,15 @@ static FuncDesc* ParseFuncDecl (void) } /* Remember the last function parameter. We need it later for several - * purposes, for example when passing stuff to fastcall functions. Since - * more symbols are added to the table, it is easier if we remember it - * now, since it is currently the last entry in the symbol table. - */ + ** purposes, for example when passing stuff to fastcall functions. Since + ** more symbols are added to the table, it is easier if we remember it + ** now, since it is currently the last entry in the symbol table. + */ F->LastParam = GetSymTab()->SymTail; /* Assign offsets. If the function has a variable parameter list, - * there's one additional byte (the arg size). - */ + ** there's one additional byte (the arg size). + */ Offs = (F->Flags & FD_VARIADIC)? 1 : 0; Sym = F->LastParam; while (Sym) { @@ -1377,11 +1377,11 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) /* Recursively process declarators. Build a type array in reverse order. */ { /* Read optional function or pointer qualifiers. These modify the - * identifier or token to the right. For convenience, we allow the fastcall - * qualifier also for pointers here. If it is a pointer-to-function, the - * qualifier will later be transfered to the function itself. If it's a - * pointer to something else, it will be flagged as an error. - */ + ** identifier or token to the right. For convenience, we allow the fastcall + ** qualifier also for pointers here. If it is a pointer-to-function, the + ** qualifier will later be transfered to the function itself. If it's a + ** pointer to something else, it will be flagged as an error. + */ TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_FASTCALL); /* Pointer to something */ @@ -1407,15 +1407,15 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) ConsumeRParen (); } else { /* Things depend on Mode now: - * - Mode == DM_NEED_IDENT means: - * we *must* have a type and a variable identifer. - * - Mode == DM_NO_IDENT means: - * we must have a type but no variable identifer - * (if there is one, it's not read). - * - Mode == DM_ACCEPT_IDENT means: - * we *may* have an identifier. If there is an identifier, - * it is read, but it is no error, if there is none. - */ + ** - Mode == DM_NEED_IDENT means: + ** we *must* have a type and a variable identifer. + ** - Mode == DM_NO_IDENT means: + ** we must have a type but no variable identifer + ** (if there is one, it's not read). + ** - Mode == DM_ACCEPT_IDENT means: + ** we *may* have an identifier. If there is an identifier, + ** it is read, but it is no error, if there is none. + */ if (Mode == DM_NO_IDENT) { D->Ident[0] = '\0'; } else if (CurTok.Tok == TOK_IDENT) { @@ -1597,8 +1597,8 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode) if ((Spec->Flags & DS_DEF_TYPE) != 0 && RetType[0].C == T_INT && RetType[1].C == T_END) { /* Function has an implicit int return. Output a warning if we don't - * have the C89 standard enabled explicitly. - */ + ** have the C89 standard enabled explicitly. + */ if (IS_Get (&Standard) >= STD_C99) { Warning ("Implicit `int' return type is an obsolete feature"); } @@ -1608,13 +1608,13 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode) } /* For anthing that is not a function or typedef, check for an implicit - * int declaration. - */ + ** int declaration. + */ if ((D->StorageClass & SC_FUNC) != SC_FUNC && (D->StorageClass & SC_TYPEMASK) != SC_TYPEDEF) { /* If the standard was not set explicitly to C89, print a warning - * for variables with implicit int type. - */ + ** for variables with implicit int type. + */ if ((Spec->Flags & DS_DEF_TYPE) != 0 && IS_Get (&Standard) >= STD_C99) { Warning ("Implicit `int' is an obsolete feature"); } @@ -1658,9 +1658,9 @@ void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType) void CheckEmptyDecl (const DeclSpec* D) /* Called after an empty type declaration (that is, a type declaration without - * a variable). Checks if the declaration does really make sense and issues a - * warning if not. - */ +** a variable). Checks if the declaration does really make sense and issues a +** warning if not. +*/ { if ((D->Flags & DS_EXTRA_TYPE) == 0) { Warning ("Useless declaration"); @@ -1671,8 +1671,8 @@ void CheckEmptyDecl (const DeclSpec* D) static void SkipInitializer (unsigned BracesExpected) /* Skip the remainder of an initializer in case of errors. Try to be somewhat - * smart so we don't have too many following errors. - */ +** smart so we don't have too many following errors. +*/ { while (CurTok.Tok != TOK_CEOF && CurTok.Tok != TOK_SEMI && BracesExpected > 0) { switch (CurTok.Tok) { @@ -1688,9 +1688,9 @@ static void SkipInitializer (unsigned BracesExpected) static unsigned OpeningCurlyBraces (unsigned BracesNeeded) /* Accept any number of opening curly braces around an initialization, skip - * them and return the number. If the number of curly braces is less than - * BracesNeeded, issue a warning. - */ +** them and return the number. If the number of curly braces is less than +** BracesNeeded, issue a warning. +*/ { unsigned BraceCount = 0; while (CurTok.Tok == TOK_LCURLY) { @@ -1707,9 +1707,9 @@ static unsigned OpeningCurlyBraces (unsigned BracesNeeded) static void ClosingCurlyBraces (unsigned BracesExpected) /* Accept and skip the given number of closing curly braces together with - * an optional comma. Output an error messages, if the input does not contain - * the expected number of braces. - */ +** an optional comma. Output an error messages, if the input does not contain +** the expected number of braces. +*/ { while (BracesExpected) { if (CurTok.Tok == TOK_RCURLY) { @@ -1750,8 +1750,8 @@ static void DefineData (ExprDesc* Expr) case E_LOC_REGISTER: /* Register variable. Taking the address is usually not - * allowed. - */ + ** allowed. + */ if (IS_Get (&AllowRegVarAddr) == 0) { Error ("Cannot take the address of a register variable"); } @@ -1791,15 +1791,15 @@ static void OutputBitFieldData (StructInitData* SI) static void ParseScalarInitInternal (Type* T, ExprDesc* ED) /* Parse initializaton for scalar data types. This function will not output the - * data but return it in ED. - */ +** data but return it in ED. +*/ { /* Optional opening brace */ unsigned BraceCount = OpeningCurlyBraces (0); /* We warn if an initializer for a scalar contains braces, because this is - * quite unusual and often a sign for some problem in the input. - */ + ** quite unusual and often a sign for some problem in the input. + */ if (BraceCount > 0) { Warning ("Braces around scalar initializer"); } @@ -1874,8 +1874,8 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers) int NeedParen; /* If we initializer is enclosed in brackets, remember this fact and - * skip the opening bracket. - */ + ** skip the opening bracket. + */ NeedParen = (CurTok.Tok == TOK_LCURLY); if (NeedParen) { NextToken (); @@ -1885,8 +1885,8 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers) TranslateLiteral (CurTok.SVal); /* If the array is one too small for the string literal, omit the - * trailing zero. - */ + ** trailing zero. + */ Count = GetLiteralSize (CurTok.SVal); if (ElementCount != UNSPECIFIED && ElementCount != FLEXIBLE && @@ -1902,8 +1902,8 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers) NextToken (); /* If the initializer was enclosed in curly braces, we need a closing - * one. - */ + ** one. + */ if (NeedParen) { ConsumeRCurly (); } @@ -1917,9 +1917,9 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers) Count = 0; while (CurTok.Tok != TOK_RCURLY) { /* Flexible array members may not be initialized within - * an array (because the size of each element may differ - * otherwise). - */ + ** an array (because the size of each element may differ + ** otherwise). + */ ParseInitInternal (ElementType, 0); ++Count; if (CurTok.Tok != TOK_COMMA) @@ -1937,8 +1937,8 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers) ElementCount = Count; } else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) { /* In non ANSI mode, allow initialization of flexible array - * members. - */ + ** members. + */ ElementCount = Count; } else if (Count < ElementCount) { g_zerobytes ((ElementCount - Count) * ElementSize); @@ -1968,8 +1968,8 @@ static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) SI.Size = Entry->V.S.Size; /* Check if this struct definition has a field table. If it doesn't, it - * is an incomplete definition. - */ + ** is an incomplete definition. + */ Tab = Entry->V.S.SymTab; if (Tab == 0) { Error ("Cannot initialize variables with incomplete type"); @@ -1996,8 +1996,8 @@ static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) } /* Parse initialization of one field. Bit-fields need a special - * handling. - */ + ** handling. + */ if (SymIsBitField (Entry)) { ExprDesc ED; @@ -2012,8 +2012,8 @@ static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) SI.Offs * CHAR_BITS + SI.ValBits); /* This may be an anonymous bit-field, in which case it doesn't - * have an initializer. - */ + ** have an initializer. + */ if (IsAnonName (Entry->Name)) { /* Account for the data and output it if we have a full word */ SI.ValBits += Entry->V.B.BitWidth; @@ -2024,8 +2024,8 @@ static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) goto NextMember; } else { /* Read the data, check for a constant integer, do a range - * check. - */ + ** check. + */ ParseScalarInitInternal (type_uint, &ED); if (!ED_IsConstAbsInt (&ED)) { Error ("Constant initializer expected"); @@ -2052,13 +2052,13 @@ static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) } else { /* Standard member. We should never have stuff from a - * bit-field left - */ + ** bit-field left + */ CHECK (SI.ValBits == 0); /* Flexible array members may only be initialized if they are - * the last field (or part of the last struct field). - */ + ** the last field (or part of the last struct field). + */ SI.Offs += ParseInitInternal (Entry->Type, AllowFlexibleMembers && Entry->NextSym == 0); } @@ -2094,9 +2094,9 @@ NextMember: } /* Return the actual number of bytes initialized. This number may be - * larger than sizeof (Struct) if flexible array members are present and - * were initialized (possible in non ANSI mode). - */ + ** larger than sizeof (Struct) if flexible array members are present and + ** were initialized (possible in non ANSI mode). + */ return SI.Offs; } @@ -2104,8 +2104,8 @@ NextMember: static unsigned ParseVoidInit (void) /* Parse an initialization of a void variable (special cc65 extension). - * Return the number of bytes initialized. - */ +** Return the number of bytes initialized. +*/ { ExprDesc Expr; unsigned Size; @@ -2222,13 +2222,13 @@ unsigned ParseInit (Type* T) /* Parse initialization of variables. Return the number of data bytes. */ { /* Parse the initialization. Flexible array members can only be initialized - * in cc65 mode. - */ + ** in cc65 mode. + */ unsigned Size = ParseInitInternal (T, IS_Get (&Standard) == STD_CC65); /* The initialization may not generate code on global level, because code - * outside function scope will never get executed. - */ + ** outside function scope will never get executed. + */ if (HaveGlobalCode ()) { Error ("Non constant initializers"); RemoveGlobalCode (); @@ -2237,6 +2237,3 @@ unsigned ParseInit (Type* T) /* Return the size needed for the initialization */ return Size; } - - - diff --git a/src/cc65/declare.h b/src/cc65/declare.h index 3a21a59d9..117ac14a6 100644 --- a/src/cc65/declare.h +++ b/src/cc65/declare.h @@ -104,20 +104,17 @@ void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType); void CheckEmptyDecl (const DeclSpec* D); /* Called after an empty type declaration (that is, a type declaration without - * a variable). Checks if the declaration does really make sense and issues a - * warning if not. - */ +** a variable). Checks if the declaration does really make sense and issues a +** warning if not. +*/ unsigned ParseInit (Type* T); /* Parse initialization of variables. Return the number of initialized data - * bytes. - */ +** bytes. +*/ /* End of declare.h */ #endif - - - diff --git a/src/cc65/declattr.c b/src/cc65/declattr.c index ac45db221..bdaea20d6 100644 --- a/src/cc65/declattr.c +++ b/src/cc65/declattr.c @@ -104,8 +104,8 @@ static DeclAttr* NewDeclAttr (DeclAttrType AttrType) static const AttrDesc* FindAttribute (const char* Attr) /* Search the attribute and return the corresponding attribute descriptor. - * Return NULL if the attribute name is not known. - */ +** Return NULL if the attribute name is not known. +*/ { unsigned A; @@ -235,8 +235,8 @@ void ParseAttribute (Declaration* D) } /* If a comma follows, there's a next attribute. Otherwise this is the - * end of the attribute list. - */ + ** end of the attribute list. + */ if (CurTok.Tok != TOK_COMMA) { break; } @@ -247,6 +247,3 @@ void ParseAttribute (Declaration* D) ConsumeRParen (); ConsumeRParen (); } - - - diff --git a/src/cc65/declattr.h b/src/cc65/declattr.h index e3826c77f..63669cee7 100644 --- a/src/cc65/declattr.h +++ b/src/cc65/declattr.h @@ -75,6 +75,3 @@ void ParseAttribute (struct Declaration* D); /* End of declattr.h */ #endif - - - diff --git a/src/cc65/error.c b/src/cc65/error.c index e15cd22ba..5218d195c 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -283,8 +283,8 @@ void PPWarning (const char* Format, ...) IntStack* FindWarning (const char* Name) /* Search for a warning in the WarnMap table and return a pointer to the - * intstack that holds its state. Return NULL if there is no such warning. - */ +** intstack that holds its state. Return NULL if there is no such warning. +*/ { unsigned I; @@ -321,6 +321,3 @@ void ErrorReport (void) { Print (stdout, 1, "%u errors, %u warnings\n", ErrorCount, WarningCount); } - - - diff --git a/src/cc65/error.h b/src/cc65/error.h index 5811e1b45..9aec10c77 100644 --- a/src/cc65/error.h +++ b/src/cc65/error.h @@ -105,8 +105,8 @@ void PPWarning (const char* Format, ...) attribute ((format (printf, 1, 2))); IntStack* FindWarning (const char* Name); /* Search for a warning in the WarnMap table and return a pointer to the - * intstack that holds its state. Return NULL if there is no such warning. - */ +** intstack that holds its state. Return NULL if there is no such warning. +*/ void ListWarnings (FILE* F); /* Print a list of warning types/names to the given file */ @@ -117,9 +117,5 @@ void ErrorReport (void); /* End of error.h */ + #endif - - - - - diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 2125eb430..03374a521 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -1,7 +1,7 @@ /* expr.c - * - * Ullrich von Bassewitz, 21.06.1998 - */ +** +** Ullrich von Bassewitz, 21.06.1998 +*/ @@ -107,7 +107,7 @@ void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Call the expression function */ (*Func) (Expr); - /* Do some checks if code generation is still constistent */ + /* Do some checks to see if code generation is still consistent */ if (StackPtr != OldSP) { if (Debug) { Error ("Code generation messed up: " @@ -125,8 +125,8 @@ void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr) void MarkedExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Call an expression function with checks and record start and end of the - * generated code. - */ +** generated code. +*/ { CodeMark Start, End; GetCodePos (&Start); @@ -141,10 +141,10 @@ static Type* promoteint (Type* lhst, Type* rhst) /* In an expression with two ints, return the type of the result */ { /* Rules for integer types: - * - If one of the values is a long, the result is long. - * - If one of the values is unsigned, the result is also unsigned. - * - Otherwise the result is an int. - */ + ** - If one of the values is a long, the result is long. + ** - If one of the values is unsigned, the result is also unsigned. + ** - Otherwise the result is an int. + */ if (IsTypeLong (lhst) || IsTypeLong (rhst)) { if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) { return type_ulong; @@ -164,13 +164,13 @@ static Type* promoteint (Type* lhst, Type* rhst) static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush) /* Adjust the two values for a binary operation. lhs is expected on stack or - * to be constant, rhs is expected to be in the primary register or constant. - * The function will put the type of the result into lhs and return the - * code generator flags for the operation. - * If NoPush is given, it is assumed that the operation does not expect the lhs - * to be on stack, and that lhs is in a register instead. - * Beware: The function does only accept int types. - */ +** to be constant, rhs is expected to be in the primary register or constant. +** The function will put the type of the result into lhs and return the +** code generator flags for the operation. +** If NoPush is given, it is assumed that the operation does not expect the lhs +** to be on stack, and that lhs is in a register instead. +** Beware: The function does only accept int types. +*/ { unsigned ltype, rtype; unsigned flags; @@ -219,18 +219,18 @@ static const GenDesc* FindGen (token_t Tok, const GenDesc* Table) static int TypeSpecAhead (void) /* Return true if some sort of type is waiting (helper for cast and sizeof() - * in hie10). - */ +** in hie10). +*/ { SymEntry* Entry; /* There's a type waiting if: - * - * We have an opening paren, and - * a. the next token is a type, or - * b. the next token is a type qualifier, or - * c. the next token is a typedef'd type - */ + ** + ** We have an opening paren, and + ** a. the next token is a type, or + ** b. the next token is a type qualifier, or + ** c. the next token is a typedef'd type + */ return CurTok.Tok == TOK_LPAREN && ( TokIsType (&NextTok) || TokIsTypeQual (&NextTok) || @@ -243,10 +243,10 @@ static int TypeSpecAhead (void) void PushAddr (const ExprDesc* Expr) /* If the expression contains an address that was somehow evaluated, - * push this address on the stack. This is a helper function for all - * sorts of implicit or explicit assignment functions where the lvalue - * must be saved if it's not constant, before evaluating the rhs. - */ +** push this address on the stack. This is a helper function for all +** sorts of implicit or explicit assignment functions where the lvalue +** must be saved if it's not constant, before evaluating the rhs. +*/ { /* Get the address on stack if needed */ if (ED_IsLocExpr (Expr)) { @@ -259,8 +259,8 @@ void PushAddr (const ExprDesc* Expr) static void WarnConstCompareResult (void) /* If the result of a comparison is constant, this is suspicious when not in - * preprocessor mode. - */ +** preprocessor mode. +*/ { if (!Preprocessing && IS_Get (&WarnConstComparison) != 0) { Warning ("Result of comparison is constant"); @@ -277,11 +277,11 @@ static void WarnConstCompareResult (void) static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall) /* Parse a function parameter list and pass the parameters to the called - * function. Depending on several criteria this may be done by just pushing - * each parameter separately, or creating the parameter frame once and then - * storing into this frame. - * The function returns the size of the parameters pushed. - */ +** function. Depending on several criteria this may be done by just pushing +** each parameter separately, or creating the parameter frame once and then +** storing into this frame. +** The function returns the size of the parameters pushed. +*/ { ExprDesc Expr; @@ -295,18 +295,18 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall) int Ellipsis = 0; /* Function is variadic */ /* As an optimization, we may allocate the complete parameter frame at - * once instead of pushing each parameter as it comes. We may do that, - * if... - * - * - optimizations that increase code size are enabled (allocating the - * stack frame at once gives usually larger code). - * - we have more than one parameter to push (don't count the last param - * for __fastcall__ functions). - * - * The FrameSize variable will contain a value > 0 if storing into a frame - * (instead of pushing) is enabled. - * - */ + ** once instead of pushing each parameter as it comes. We may do that, + ** if... + ** + ** - optimizations that increase code size are enabled (allocating the + ** stack frame at once gives usually larger code). + ** - we have more than one parameter to push (don't count the last param + ** for __fastcall__ functions). + ** + ** The FrameSize variable will contain a value > 0 if storing into a frame + ** (instead of pushing) is enabled. + ** + */ if (IS_Get (&CodeSizeFactor) >= 200) { /* Calculate the number and size of the parameters */ @@ -341,13 +341,13 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall) /* Fetch the pointer to the next argument, check for too many args */ if (ParamCount <= Func->ParamCount) { /* Beware: If there are parameters with identical names, they - * cannot go into the same symbol table, which means that in this - * case of errorneous input, the number of nodes in the symbol - * table and ParamCount are NOT equal. We have to handle this case - * below to avoid segmentation violations. Since we know that this - * problem can only occur if there is more than one parameter, - * we will just use the last one. - */ + ** cannot go into the same symbol table, which means that in this + ** case of errorneous input, the number of nodes in the symbol + ** table and ParamCount are NOT equal. We have to handle this case + ** below to avoid segmentation violations. Since we know that this + ** problem can only occur if there is more than one parameter, + ** we will just use the last one. + */ if (ParamCount == 1) { /* First argument */ Param = Func->SymTab->SymHead; @@ -363,8 +363,8 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall) Error ("Too many arguments in function call"); } /* Assume an ellipsis even in case of errors to avoid an error - * message for each other argument. - */ + ** message for each other argument. + */ Ellipsis = 1; } @@ -372,8 +372,8 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall) hie1 (&Expr); /* If we don't have an argument spec, accept anything, otherwise - * convert the actual argument to the type needed. - */ + ** convert the actual argument to the type needed. + */ Flags = CF_NONE; if (!Ellipsis) { @@ -386,8 +386,8 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall) } else { /* No prototype available. Convert array to "pointer to first - * element", and function to "pointer to function". - */ + ** element", and function to "pointer to function". + */ Expr.Type = PtrConversion (Expr.Type); } @@ -403,11 +403,11 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall) unsigned ArgSize = sizeofarg (Flags); if (FrameSize > 0) { /* We have the space already allocated, store in the frame. - * Because of invalid type conversions (that have produced an - * error before), we can end up here with a non aligned stack - * frame. Since no output will be generated anyway, handle - * these cases gracefully instead of doing a CHECK. - */ + ** Because of invalid type conversions (that have produced an + ** error before), we can end up here with a non-aligned stack + ** frame. Since no output will be generated anyway, handle + ** these cases gracefully instead of doing a CHECK. + */ if (FrameSize >= ArgSize) { FrameSize -= ArgSize; } else { @@ -438,13 +438,13 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall) } /* The function returns the size of all parameters pushed onto the stack. - * However, if there are parameters missing (which is an error and was - * flagged by the compiler) AND a stack frame was preallocated above, - * we would loose track of the stackpointer and generate an internal error - * later. So we correct the value by the parameters that should have been - * pushed to avoid an internal compiler error. Since an error was - * generated before, no code will be output anyway. - */ + ** However, if there are parameters missing (which is an error and was + ** flagged by the compiler) AND a stack frame was preallocated above, + ** we would loose track of the stackpointer and generate an internal error + ** later. So we correct the value by the parameters that should have been + ** pushed to avoid an internal compiler error. Since an error was + ** generated before, no code will be output anyway. + */ return ParamSize + FrameSize; } @@ -458,7 +458,7 @@ static void FunctionCall (ExprDesc* Expr) unsigned ParamSize; /* Number of parameter bytes */ CodeMark Mark; int PtrOffs = 0; /* Offset of function pointer on stack */ - int IsFastcall = 0; /* True if it's a fast call function */ + int IsFastcall = 0; /* True if it's a fast-call function */ int PtrOnStack = 0; /* True if a pointer copy is on stack */ /* Skip the left paren */ @@ -475,19 +475,19 @@ static void FunctionCall (ExprDesc* Expr) IsFastcall = IsQualFastcall (Expr->Type + 1) && (Func->ParamCount > 0); /* Things may be difficult, depending on where the function pointer - * resides. If the function pointer is an expression of some sort - * (not a local or global variable), we have to evaluate this - * expression now and save the result for later. Since calls to - * function pointers may be nested, we must save it onto the stack. - * For fastcall functions we do also need to place a copy of the - * pointer on stack, since we cannot use a/x. - */ + ** resides. If the function pointer is an expression of some sort + ** (not a local or global variable), we have to evaluate this + ** expression now and save the result for later. Since calls to + ** function pointers may be nested, we must save it onto the stack. + ** For fastcall functions we do also need to place a copy of the + ** pointer on stack, since we cannot use a/x. + */ PtrOnStack = IsFastcall || !ED_IsConst (Expr); if (PtrOnStack) { /* Not a global or local variable, or a fastcall function. Load - * the pointer into the primary and mark it as an expression. - */ + ** the pointer into the primary and mark it as an expression. + */ LoadExpr (CF_NONE, Expr); ED_MakeRValExpr (Expr); @@ -530,16 +530,16 @@ static void FunctionCall (ExprDesc* Expr) if (IsFuncPtr) { /* If the function is not a fastcall function, load the pointer to - * the function into the primary. - */ + ** the function into the primary. + */ if (!IsFastcall) { /* Not a fastcall function - we may use the primary */ if (PtrOnStack) { /* If we have no parameters, the pointer is still in the - * primary. Remove the code to push it and correct the - * stack pointer. - */ + ** primary. Remove the code to push it and correct the + ** stack pointer. + */ if (ParamSize == 0) { RemoveCode (&Mark); PtrOnStack = 0; @@ -558,10 +558,10 @@ static void FunctionCall (ExprDesc* Expr) } else { /* Fastcall function. We cannot use the primary for the function - * pointer and must therefore use an offset to the stack location. - * Since fastcall functions may never be variadic, we can use the - * index register for this purpose. - */ + ** pointer and must therefore use an offset to the stack location. + ** Since fastcall functions may never be variadic, we can use the + ** index register for this purpose. + */ g_callind (CF_LOCAL, ParamSize, PtrOffs); } @@ -615,8 +615,8 @@ static void Primary (ExprDesc* E) } /* Process parenthesized subexpression by calling the whole parser - * recursively. - */ + ** recursively. + */ if (CurTok.Tok == TOK_LPAREN) { NextToken (); hie0 (E); @@ -625,8 +625,8 @@ static void Primary (ExprDesc* E) } /* If we run into an identifier in preprocessing mode, we assume that this - * is an undefined macro and replace it by a constant value of zero. - */ + ** is an undefined macro and replace it by a constant value of zero. + */ if (Preprocessing && CurTok.Tok == TOK_IDENT) { NextToken (); ED_MakeConstAbsInt (E, 0); @@ -634,8 +634,8 @@ static void Primary (ExprDesc* E) } /* All others may only be used if the expression evaluation is not called - * recursively by the preprocessor. - */ + ** recursively by the preprocessor. + */ if (Preprocessing) { /* Illegal expression in PP mode */ Error ("Preprocessor expression expected"); @@ -683,9 +683,9 @@ static void Primary (ExprDesc* E) E->Name = (unsigned long) Sym->Name; } else if ((Sym->Flags & SC_AUTO) == SC_AUTO) { /* Local variable. If this is a parameter for a variadic - * function, we have to add some address calculations, and the - * address is not const. - */ + ** function, we have to add some address calculations, and the + ** address is not const. + */ if ((Sym->Flags & SC_PARAM) == SC_PARAM && F_IsVariadic (CurrentFunc)) { /* Variadic parameter */ g_leavariadic (Sym->V.Offs - F_GetParamSize (CurrentFunc)); @@ -715,11 +715,11 @@ static void Primary (ExprDesc* E) } /* We've made all variables lvalues above. However, this is - * not always correct: An array is actually the address of its - * first element, which is a rvalue, and a function is a - * rvalue, too, because we cannot store anything in a function. - * So fix the flags depending on the type. - */ + ** not always correct: An array is actually the address of its + ** first element, which is a rvalue, and a function is a + ** rvalue, too, because we cannot store anything in a function. + ** So fix the flags depending on the type. + */ if (IsTypeArray (E->Type) || IsTypeFunc (E->Type)) { ED_MakeRVal (E); } @@ -734,11 +734,11 @@ static void Primary (ExprDesc* E) /* IDENT is either an auto-declared function or an undefined variable. */ if (CurTok.Tok == TOK_LPAREN) { /* C99 doesn't allow calls to undefined functions, so - * generate an error and otherwise a warning. Declare a - * function returning int. For that purpose, prepare a - * function signature for a function having an empty param - * list and returning int. - */ + ** generate an error and otherwise a warning. Declare a + ** function returning int. For that purpose, prepare a + ** function signature for a function having an empty param + ** list and returning int. + */ if (IS_Get (&Standard) >= STD_C99) { Error ("Call to undefined function `%s'", Ident); } else { @@ -800,8 +800,8 @@ static void Primary (ExprDesc* E) default: /* Illegal primary. Be sure to skip the token to avoid endless - * error loops. - */ + ** error loops. + */ Error ("Expression expected"); NextToken (); ED_MakeConstAbsInt (E, 1); @@ -830,9 +830,9 @@ static void ArrayRef (ExprDesc* Expr) tptr1 = Expr->Type; /* We can apply a special treatment for arrays that have a const base - * address. This is true for most arrays and will produce a lot better - * code. Check if this is a const base address. - */ + ** address. This is true for most arrays and will produce a lot better + ** code. Check if this is a const base address. + */ ConstBaseAddr = ED_IsRVal (Expr) && (ED_IsLocConst (Expr) || ED_IsLocStack (Expr)); @@ -843,9 +843,9 @@ static void ArrayRef (ExprDesc* Expr) LoadExpr (CF_NONE, Expr); /* Get the array pointer on stack. Do not push more than 16 - * bit, even if this value is greater, since we cannot handle - * other than 16bit stuff when doing indexing. - */ + ** bit, even if this value is greater, since we cannot handle + ** other than 16bit stuff when doing indexing. + */ GetCodePos (&Mark2); g_push (CF_PTR, 0); } @@ -854,12 +854,12 @@ static void ArrayRef (ExprDesc* Expr) MarkedExprWithCheck (hie0, &Subscript); /* Check the types of array and subscript. We can either have a - * pointer/array to the left, in which case the subscript must be of an - * integer type, or we have an integer to the left, in which case the - * subscript must be a pointer/array. - * Since we do the necessary checking here, we can rely later on the - * correct types. - */ + ** pointer/array to the left, in which case the subscript must be of an + ** integer type, or we have an integer to the left, in which case the + ** subscript must be a pointer/array. + ** Since we do the necessary checking here, we can rely later on the + ** correct types. + */ Qualifiers = T_QUAL_NONE; if (IsClassPtr (Expr->Type)) { if (!IsClassInt (Subscript.Type)) { @@ -875,8 +875,8 @@ static void ArrayRef (ExprDesc* Expr) if (!IsClassPtr (Subscript.Type)) { Error ("Subscripted value is neither array nor pointer"); /* To avoid compiler errors, make the subscript a char[] at - * address 0. - */ + ** address 0. + */ ED_MakeConstAbs (&Subscript, 0, GetCharArrayType (1)); } else if (IsTypeArray (Subscript.Type)) { Qualifiers = GetQualifier (Subscript.Type); @@ -885,16 +885,16 @@ static void ArrayRef (ExprDesc* Expr) } else { Error ("Cannot subscript"); /* To avoid compiler errors, fake both the array and the subscript, so - * we can just proceed. - */ + ** we can just proceed. + */ ED_MakeConstAbs (Expr, 0, GetCharArrayType (1)); ED_MakeConstAbsInt (&Subscript, 0); ElementType = Indirect (Expr->Type); } /* The element type has the combined qualifiers from itself and the array, - * it is a member of (if any). - */ + ** it is a member of (if any). + */ if (GetQualifier (ElementType) != (GetQualifier (ElementType) | Qualifiers)) { ElementType = TypeDup (ElementType); ElementType->C |= Qualifiers; @@ -910,9 +910,9 @@ static void ArrayRef (ExprDesc* Expr) if (ED_IsConstAbs (&Subscript) && ED_CodeRangeIsEmpty (&Subscript)) { /* The array subscript is a numeric constant. If we had pushed the - * array base address onto the stack before, we can remove this value, - * since we can generate expression+offset. - */ + ** array base address onto the stack before, we can remove this value, + ** since we can generate expression+offset. + */ if (!ConstBaseAddr) { RemoveCode (&Mark2); } else { @@ -923,17 +923,17 @@ static void ArrayRef (ExprDesc* Expr) if (IsClassPtr (Expr->Type)) { /* Lhs is pointer/array. Scale the subscript value according to - * the element size. - */ + ** the element size. + */ Subscript.IVal *= CheckedSizeOf (ElementType); /* Remove the address load code */ RemoveCode (&Mark1); /* In case of an array, we can adjust the offset of the expression - * already in Expr. If the base address was a constant, we can even - * remove the code that loaded the address into the primary. - */ + ** already in Expr. If the base address was a constant, we can even + ** remove the code that loaded the address into the primary. + */ if (IsTypeArray (Expr->Type)) { /* Adjust the offset */ @@ -942,8 +942,8 @@ static void ArrayRef (ExprDesc* Expr) } else { /* It's a pointer, so we do have to load it into the primary - * first (if it's not already there). - */ + ** first (if it's not already there). + */ if (ConstBaseAddr || ED_IsLVal (Expr)) { LoadExpr (CF_NONE, Expr); ED_MakeRValExpr (Expr); @@ -959,9 +959,9 @@ static void ArrayRef (ExprDesc* Expr) g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType)); /* Add the subscript. Since arrays are indexed by integers, - * we will ignore the true type of the subscript here and - * use always an int. #### Use offset but beware of LoadExpr! - */ + ** we will ignore the true type of the subscript here and + ** use always an int. #### Use offset but beware of LoadExpr! + */ g_inc (CF_INT | CF_CONST, Subscript.IVal); } @@ -976,19 +976,19 @@ static void ArrayRef (ExprDesc* Expr) if (IsClassPtr (Expr->Type)) { /* Indexing is based on unsigneds, so we will just use the integer - * portion of the index (which is in (e)ax, so there's no further - * action required). - */ + ** portion of the index (which is in (e)ax, so there's no further + ** action required). + */ g_scale (CF_INT, CheckedSizeOf (ElementType)); } else { /* Get the int value on top. If we come here, we're sure, both - * values are 16 bit (the first one was truncated if necessary - * and the second one is a pointer). Note: If ConstBaseAddr is - * true, we don't have a value on stack, so to "swap" both, just - * push the subscript. - */ + ** values are 16 bit (the first one was truncated if necessary + ** and the second one is a pointer). Note: If ConstBaseAddr is + ** true, we don't have a value on stack, so to "swap" both, just + ** push the subscript. + */ if (ConstBaseAddr) { g_push (CF_INT, 0); LoadExpr (CF_NONE, Expr); @@ -1003,28 +1003,28 @@ static void ArrayRef (ExprDesc* Expr) } /* The offset is now in the primary register. It we didn't have a - * constant base address for the lhs, the lhs address is already - * on stack, and we must add the offset. If the base address was - * constant, we call special functions to add the address to the - * offset value. - */ + ** constant base address for the lhs, the lhs address is already + ** on stack, and we must add the offset. If the base address was + ** constant, we call special functions to add the address to the + ** offset value. + */ if (!ConstBaseAddr) { /* The array base address is on stack and the subscript is in the - * primary. Add both. - */ + ** primary. Add both. + */ g_add (CF_INT, 0); } else { /* The subscript is in the primary, and the array base address is - * in Expr. If the subscript has itself a constant address, it is - * often a better idea to reverse again the order of the - * evaluation. This will generate better code if the subscript is - * a byte sized variable. But beware: This is only possible if the - * subscript was not scaled, that is, if this was a byte array - * or pointer. - */ + ** in Expr. If the subscript has itself a constant address, it is + ** often a better idea to reverse again the order of the + ** evaluation. This will generate better code if the subscript is + ** a byte sized variable. But beware: This is only possible if the + ** subscript was not scaled, that is, if this was a byte array + ** or pointer. + */ if ((ED_IsLocConst (&Subscript) || ED_IsLocStack (&Subscript)) && CheckedSizeOf (ElementType) == SIZEOF_CHAR) { @@ -1085,10 +1085,10 @@ static void ArrayRef (ExprDesc* Expr) Expr->Type = ElementType; /* An array element is actually a variable. So the rules for variables - * with respect to the reference type apply: If it's an array, it is - * a rvalue, otherwise it's an lvalue. (A function would also be a rvalue, - * but an array cannot contain functions). - */ + ** with respect to the reference type apply: If it's an array, it is + ** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue, + ** but an array cannot contain functions). + */ if (IsTypeArray (Expr->Type)) { ED_MakeRVal (Expr); } else { @@ -1130,8 +1130,8 @@ static void StructRef (ExprDesc* Expr) } /* If we have a struct pointer that is an lvalue and not already in the - * primary, load it now. - */ + ** primary, load it now. + */ if (ED_IsLVal (Expr) && IsTypePtr (Expr->Type)) { /* Load into the primary */ @@ -1155,8 +1155,8 @@ static void StructRef (ExprDesc* Expr) } /* A struct is usually an lvalue. If not, it is a struct in the primary - * register. - */ + ** register. + */ if (ED_IsRVal (Expr) && ED_IsLocExpr (Expr) && !IsTypePtr (Expr->Type)) { unsigned Flags = 0; @@ -1178,15 +1178,15 @@ static void StructRef (ExprDesc* Expr) } /* Generate a shift to get the field in the proper position in the - * primary. For bit fields, mask the value. - */ + ** primary. For bit fields, mask the value. + */ BitOffs = Field->V.Offs * CHAR_BITS; if (SymIsBitField (Field)) { BitOffs += Field->V.B.BitOffs; g_asr (Flags, BitOffs); /* Mask the value. This is unnecessary if the shift executed above - * moved only zeroes into the value. - */ + ** moved only zeroes into the value. + */ if (BitOffs + Field->V.B.BitWidth != Size * CHAR_BITS) { g_and (CF_INT | CF_UNSIGNED | CF_CONST, (0x0001U << Field->V.B.BitWidth) - 1U); @@ -1207,10 +1207,10 @@ static void StructRef (ExprDesc* Expr) Expr->Type = FinalType; /* An struct member is actually a variable. So the rules for variables - * with respect to the reference type apply: If it's an array, it is - * a rvalue, otherwise it's an lvalue. (A function would also be a rvalue, - * but a struct field cannot be a function). - */ + ** with respect to the reference type apply: If it's an array, it is + ** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue, + ** but a struct field cannot be a function). + */ if (IsTypeArray (Expr->Type)) { ED_MakeRVal (Expr); } else { @@ -1253,9 +1253,9 @@ static void hie11 (ExprDesc *Expr) /* Not a function */ Error ("Illegal function call"); /* Force the type to be a implicitly defined function, one - * returning an int and taking any number of arguments. - * Since we don't have a name, invent one. - */ + ** returning an int and taking any number of arguments. + ** Since we don't have a name, invent one. + */ ED_MakeConstAbs (Expr, 0, GetImplicitFuncType ()); Expr->Name = (long) IllegalFunc; } @@ -1292,9 +1292,9 @@ static void hie11 (ExprDesc *Expr) void Store (ExprDesc* Expr, const Type* StoreType) /* Store the primary register into the location denoted by Expr. If StoreType - * is given, use this type when storing instead of Expr->Type. If StoreType - * is NULL, use Expr->Type instead. - */ +** is given, use this type when storing instead of Expr->Type. If StoreType +** is NULL, use Expr->Type instead. +*/ { unsigned Flags; @@ -1687,17 +1687,17 @@ void hie10 (ExprDesc* Expr) ExprWithCheck (hie10, Expr); if (ED_IsLVal (Expr) || !(ED_IsLocConst (Expr) || ED_IsLocStack (Expr))) { /* Not a const, load it into the primary and make it a - * calculated value. - */ + ** calculated value. + */ LoadExpr (CF_NONE, Expr); ED_MakeRValExpr (Expr); } /* If the expression is already a pointer to function, the - * additional dereferencing operator must be ignored. A function - * itself is represented as "pointer to function", so any number - * of dereference operators is legal, since the result will - * always be converted to "pointer to function". - */ + ** additional dereferencing operator must be ignored. A function + ** itself is represented as "pointer to function", so any number + ** of dereference operators is legal, since the result will + ** always be converted to "pointer to function". + */ if (IsTypeFuncPtr (Expr->Type) || IsTypeFunc (Expr->Type)) { /* Expression not storable */ ED_MakeRVal (Expr); @@ -1716,8 +1716,8 @@ void hie10 (ExprDesc* Expr) NextToken (); ExprWithCheck (hie10, Expr); /* The & operator may be applied to any lvalue, and it may be - * applied to functions, even if they're no lvalues. - */ + ** applied to functions, even if they're no lvalues. + */ if (ED_IsRVal (Expr) && !IsTypeFunc (Expr->Type) && !IsTypeArray (Expr->Type)) { Error ("Illegal address"); } else { @@ -1745,8 +1745,8 @@ void hie10 (ExprDesc* Expr) GetCodePos (&Mark); hie10 (Expr); /* If the expression is a literal string, release it, so it - * won't be output as data if not used elsewhere. - */ + ** won't be output as data if not used elsewhere. + */ if (ED_IsLocLiteral (Expr)) { ReleaseLiteral (Expr->LVal); } @@ -1827,8 +1827,8 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */ /* Constant value */ GetCodePos (&Mark2); /* If the operator is commutative, don't push the left side, if - * it's a constant, since we will exchange both operands. - */ + ** it's a constant, since we will exchange both operands. + */ if ((Gen->Flags & GEN_COMM) == 0) { g_push (ltype | CF_CONST, Expr->IVal); } @@ -1943,10 +1943,10 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */ } else if (lconst && (Gen->Flags & GEN_COMM) && !rconst) { /* The left side is constant, the right side is not, and the - * operator allows swapping the operands. We haven't pushed the - * left side onto the stack in this case, and will reverse the - * operation because this allows for better code. - */ + ** operator allows swapping the operands. We haven't pushed the + ** left side onto the stack in this case, and will reverse the + ** operation because this allows for better code. + */ unsigned rtype = ltype | CF_CONST; ltype = TypeOf (Expr2.Type); /* Expr2 is now left */ type = CF_CONST; @@ -1969,9 +1969,9 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */ } else { /* If the right hand side is constant, and the generator function - * expects the lhs in the primary, remove the push of the primary - * now. - */ + ** expects the lhs in the primary, remove the push of the primary + ** now. + */ unsigned rtype = TypeOf (Expr2.Type); type = 0; if (rconst) { @@ -2063,8 +2063,8 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ } else if (IsClassPtr (Expr->Type)) { if (IsClassPtr (Expr2.Type)) { /* Both pointers are allowed in comparison if they point to - * the same type, or if one of them is a void pointer. - */ + ** the same type, or if one of them is a void pointer. + */ Type* left = Indirect (Expr->Type); Type* right = Indirect (Expr2.Type); if (TypeCmp (left, right) < TC_EQUAL && left->C != T_VOID && right->C != T_VOID) { @@ -2080,8 +2080,8 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ if (ED_IsConstAbs (Expr) && rconst) { /* If the result is constant, this is suspicious when not in - * preprocessor mode. - */ + ** preprocessor mode. + */ WarnConstCompareResult (); /* Both operands are constant, remove the generated code */ @@ -2127,9 +2127,9 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ int RightSigned = IsSignSigned (Expr2.Type); /* If the right hand side is constant, and the generator function - * expects the lhs in the primary, remove the push of the primary - * now. - */ + ** expects the lhs in the primary, remove the push of the primary + ** now. + */ unsigned flags = 0; if (rconst) { flags |= CF_CONST; @@ -2143,8 +2143,8 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ if (IsTypeChar (Expr->Type) && rconst) { /* Left side is unsigned char, right side is constant. - * Determine the minimum and maximum values - */ + ** Determine the minimum and maximum values + */ int LeftMin, LeftMax; if (LeftSigned) { LeftMin = -128; @@ -2154,25 +2154,25 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ LeftMax = 255; } /* An integer value is always represented as a signed in the - * ExprDesc structure. This may lead to false results below, - * if it is actually unsigned, but interpreted as signed - * because of the representation. Fortunately, in this case, - * the actual value doesn't matter, since it's always greater - * than what can be represented in a char. So correct the - * value accordingly. - */ + ** ExprDesc structure. This may lead to false results below, + ** if it is actually unsigned, but interpreted as signed + ** because of the representation. Fortunately, in this case, + ** the actual value doesn't matter, since it's always greater + ** than what can be represented in a char. So correct the + ** value accordingly. + */ if (!RightSigned && Expr2.IVal < 0) { /* Correct the value so it is an unsigned. It will then - * anyway match one of the cases below. - */ + ** anyway match one of the cases below. + */ Expr2.IVal = LeftMax + 1; } /* Comparing a char against a constant may have a constant - * result. Please note: It is not possible to remove the code - * for the compare alltogether, because it may have side - * effects. - */ + ** result. Please note: It is not possible to remove the code + ** for the compare alltogether, because it may have side + ** effects. + */ switch (Tok) { case TOK_EQ: @@ -2228,9 +2228,9 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ } /* If the result is not already constant (as evaluated in the - * switch above), we can execute the operation as a char op, - * since the right side constant is in a valid range. - */ + ** switch above), we can execute the operation as a char op, + ** since the right side constant is in a valid range. + */ flags |= (CF_CHAR | CF_FORCECHAR); if (!LeftSigned) { flags |= CF_UNSIGNED; @@ -2240,8 +2240,8 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ GetSignedness (Expr->Type) == GetSignedness (Expr2.Type)) { /* Both are chars with the same signedness. We can encode the - * operation as a char operation. - */ + ** operation as a char operation. + */ flags |= CF_CHAR; if (rconst) { flags |= CF_FORCECHAR; @@ -2255,9 +2255,9 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ } /* If the left side is an unsigned and the right is a constant, - * we may be able to change the compares to something more - * effective. - */ + ** we may be able to change the compares to something more + ** effective. + */ if (!LeftSigned && rconst) { switch (Tok) { @@ -2265,8 +2265,8 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ case TOK_LT: if (Expr2.IVal == 1) { /* An unsigned compare to one means that the value - * must be zero. - */ + ** must be zero. + */ GenFunc = g_eq; Expr2.IVal = 0; } @@ -2275,8 +2275,8 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ case TOK_LE: if (Expr2.IVal == 0) { /* An unsigned compare to zero means that the value - * must be zero. - */ + ** must be zero. + */ GenFunc = g_eq; } break; @@ -2284,8 +2284,8 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ case TOK_GE: if (Expr2.IVal == 1) { /* An unsigned compare to one means that the value - * must not be zero. - */ + ** must not be zero. + */ GenFunc = g_ne; Expr2.IVal = 0; } @@ -2294,8 +2294,8 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ case TOK_GT: if (Expr2.IVal == 0) { /* An unsigned compare to zero means that the value - * must not be zero. - */ + ** must not be zero. + */ GenFunc = g_ne; } break; @@ -2342,9 +2342,9 @@ static void hie9 (ExprDesc *Expr) static void parseadd (ExprDesc* Expr) /* Parse an expression with the binary plus operator. Expr contains the - * unprocessed left hand side of the expression and will contain the - * result of the expression on return. - */ +** unprocessed left hand side of the expression and will contain the +** result of the expression on return. +*/ { ExprDesc Expr2; unsigned flags; /* Operation flags */ @@ -2392,14 +2392,14 @@ static void parseadd (ExprDesc* Expr) } else { /* lhs is a constant and rhs is not constant. Load rhs into - * the primary. - */ + ** the primary. + */ LoadExpr (CF_NONE, &Expr2); /* Beware: The check above (for lhs) lets not only pass numeric - * constants, but also constant addresses (labels), maybe even - * with an offset. We have to check for that here. - */ + ** constants, but also constant addresses (labels), maybe even + ** with an offset. We have to check for that here. + */ /* First, get the rhs type. */ rhst = Expr2.Type; @@ -2437,9 +2437,9 @@ static void parseadd (ExprDesc* Expr) Expr->Type = Expr2.Type; /* Since we do already have rhs in the primary, if lhs is - * not a numeric constant, and the scale factor is not one - * (no scaling), we must take the long way over the stack. - */ + ** not a numeric constant, and the scale factor is not one + ** (no scaling), we must take the long way over the stack. + */ if (ED_IsLocAbs (Expr)) { /* Numeric constant, scale lhs */ Expr->IVal *= ScaleFactor; @@ -2543,14 +2543,14 @@ static void parseadd (ExprDesc* Expr) Expr->Type = Expr2.Type; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition. Note: Result is never constant. - * Problem here is that typeadjust does not know if the - * variable is an rvalue or lvalue, so if both operands - * are dereferenced constant numeric addresses, typeadjust - * thinks the operation works on constants. Removing - * CF_CONST here means handling the symptoms, however, the - * whole parser is such a mess that I fear to break anything - * when trying to apply another solution. - */ + ** Problem here is that typeadjust does not know if the + ** variable is an rvalue or lvalue, so if both operands + ** are dereferenced constant numeric addresses, typeadjust + ** thinks the operation works on constants. Removing + ** CF_CONST here means handling the symptoms, however, the + ** whole parser is such a mess that I fear to break anything + ** when trying to apply another solution. + */ flags = typeadjust (Expr, &Expr2, 0) & ~CF_CONST; } else { /* OOPS */ @@ -2576,9 +2576,9 @@ static void parseadd (ExprDesc* Expr) static void parsesub (ExprDesc* Expr) /* Parse an expression with the binary minus operator. Expr contains the - * unprocessed left hand side of the expression and will contain the - * result of the expression on return. - */ +** unprocessed left hand side of the expression and will contain the +** result of the expression on return. +*/ { ExprDesc Expr2; unsigned flags; /* Operation flags */ @@ -2647,8 +2647,8 @@ static void parsesub (ExprDesc* Expr) } else { /* Left hand side is not constant, right hand side is. - * Remove pushed value from stack. - */ + ** Remove pushed value from stack. + */ RemoveCode (&Mark2); if (IsClassPtr (lhst) && IsClassInt (rhst)) { @@ -2715,9 +2715,9 @@ static void parsesub (ExprDesc* Expr) Expr->Type = type_int; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer subtraction. If the left hand side descriptor says that - * the lhs is const, we have to remove this mark, since this is no - * longer true, lhs is on stack instead. - */ + ** the lhs is const, we have to remove this mark, since this is no + ** longer true, lhs is on stack instead. + */ if (ED_IsLocAbs (Expr)) { ED_MakeRValExpr (Expr); } @@ -2832,8 +2832,8 @@ static void hie2 (ExprDesc* Expr) static void hieAndPP (ExprDesc* Expr) /* Process "exp && exp" in preprocessor mode (that is, when the parser is - * called recursively from the preprocessor. - */ +** called recursively from the preprocessor. +*/ { ExprDesc Expr2; @@ -2855,8 +2855,8 @@ static void hieAndPP (ExprDesc* Expr) static void hieOrPP (ExprDesc *Expr) /* Process "exp || exp" in preprocessor mode (that is, when the parser is - * called recursively from the preprocessor. - */ +** called recursively from the preprocessor. +*/ { ExprDesc Expr2; @@ -2962,8 +2962,8 @@ static void hieOr (ExprDesc *Expr) LoadExpr (CF_FORCECHAR, Expr); /* For each expression jump to TrueLab if true. Beware: If we - * had && operators, the jump is already in place! - */ + ** had && operators, the jump is already in place! + */ if (!BoolOp) { g_truejump (CF_NONE, TrueLab); } @@ -3040,8 +3040,8 @@ static void hieQuest (ExprDesc* Expr) g_falsejump (CF_NONE, FalseLab); /* Parse second expression. Remember for later if it is a NULL pointer - * expression, then load it into the primary. - */ + ** expression, then load it into the primary. + */ ExprWithCheck (hie1, &Expr2); Expr2IsNULL = ED_IsNullPtr (&Expr2); if (!IsTypeVoid (Expr2.Type)) { @@ -3063,8 +3063,8 @@ static void hieQuest (ExprDesc* Expr) g_defcodelabel (FalseLab); /* Parse third expression. Remember for later if it is a NULL pointer - * expression, then load it into the primary. - */ + ** expression, then load it into the primary. + */ ExprWithCheck (hie1, &Expr3); Expr3IsNULL = ED_IsNullPtr (&Expr3); if (!IsTypeVoid (Expr3.Type)) { @@ -3075,18 +3075,18 @@ static void hieQuest (ExprDesc* Expr) } /* Check if any conversions are needed, if so, do them. - * Conversion rules for ?: expression are: - * - if both expressions are int expressions, default promotion - * rules for ints apply. - * - if both expressions are pointers of the same type, the - * result of the expression is of this type. - * - if one of the expressions is a pointer and the other is - * a zero constant, the resulting type is that of the pointer - * type. - * - if both expressions are void expressions, the result is of - * type void. - * - all other cases are flagged by an error. - */ + ** Conversion rules for ?: expression are: + ** - if both expressions are int expressions, default promotion + ** rules for ints apply. + ** - if both expressions are pointers of the same type, the + ** result of the expression is of this type. + ** - if one of the expressions is a pointer and the other is + ** a zero constant, the resulting type is that of the pointer + ** type. + ** - if both expressions are void expressions, the result is of + ** type void. + ** - all other cases are flagged by an error. + */ if (IsClassInt (Expr2.Type) && IsClassInt (Expr3.Type)) { CodeMark CvtCodeStart; @@ -3100,8 +3100,8 @@ static void hieQuest (ExprDesc* Expr) TypeConversion (&Expr3, ResultType); /* Emit conversion code for the second expression, but remember - * where it starts end ends. - */ + ** where it starts end ends. + */ GetCodePos (&CvtCodeStart); TypeConversion (&Expr2, ResultType); GetCodePos (&CvtCodeEnd); @@ -3166,8 +3166,8 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op) if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) { Error ("Invalid left operand type"); /* Continue. Wrong code will be generated, but the compiler won't - * break, so this is the best error recovery. - */ + ** break, so this is the best error recovery. + */ } /* Skip the operator token */ @@ -3194,15 +3194,15 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op) if (!IsClassInt (Expr2.Type)) { Error ("Invalid right operand for binary operator `%s'", Op); /* Continue. Wrong code will be generated, but the compiler won't - * break, so this is the best error recovery. - */ + ** break, so this is the best error recovery. + */ } /* Check for a constant expression */ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { /* The resulting value is a constant. If the generator has the NOPUSH - * flag set, don't push the lhs. - */ + ** flag set, don't push the lhs. + */ if (Gen->Flags & GEN_NOPUSH) { RemoveCode (&Mark); } @@ -3212,8 +3212,8 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op) } /* If the lhs is character sized, the operation may be later done - * with characters. - */ + ** with characters. + */ if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) { flags |= CF_FORCECHAR; } @@ -3244,8 +3244,8 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op) } /* If the lhs is character sized, the operation may be later done - * with characters. - */ + ** with characters. + */ if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) { flags |= CF_FORCECHAR; } @@ -3290,8 +3290,8 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr, const char* Op) if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) { Error ("Invalid left operand type"); /* Continue. Wrong code will be generated, but the compiler won't - * break, so this is the best error recovery. - */ + ** break, so this is the best error recovery. + */ } /* Skip the operator */ @@ -3305,14 +3305,14 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr, const char* Op) rflags = 0; /* Evaluate the rhs. We expect an integer here, since float is not - * supported - */ + ** supported + */ hie1 (&Expr2); if (!IsClassInt (Expr2.Type)) { Error ("Invalid right operand for binary operator `%s'", Op); /* Continue. Wrong code will be generated, but the compiler won't - * break, so this is the best error recovery. - */ + ** break, so this is the best error recovery. + */ } if (ED_IsConstAbs (&Expr2)) { /* The resulting value is a constant. Scale it. */ @@ -3467,10 +3467,10 @@ void hie0 (ExprDesc *Expr) int evalexpr (unsigned Flags, void (*Func) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is a - * constant, 0 is returned and the value is put in the Expr struct. If the - * result is not constant, LoadExpr is called to bring the value into the - * primary register and 1 is returned. - */ +** constant, 0 is returned and the value is put in the Expr struct. If the +** result is not constant, LoadExpr is called to bring the value into the +** primary register and 1 is returned. +*/ { /* Evaluate */ ExprWithCheck (Func, Expr); @@ -3499,10 +3499,10 @@ void Expression0 (ExprDesc* Expr) void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is not - * a constant of some sort, a diagnostic will be printed, and the value is - * replaced by a constant one to make sure there are no internal errors that - * result from this input error. - */ +** a constant of some sort, a diagnostic will be printed, and the value is +** replaced by a constant one to make sure there are no internal errors that +** result from this input error. +*/ { ExprWithCheck (Func, Expr); if (!ED_IsConst (Expr)) { @@ -3516,10 +3516,10 @@ void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is not - * something that may be evaluated in a boolean context, a diagnostic will be - * printed, and the value is replaced by a constant one to make sure there - * are no internal errors that result from this input error. - */ +** something that may be evaluated in a boolean context, a diagnostic will be +** printed, and the value is replaced by a constant one to make sure there +** are no internal errors that result from this input error. +*/ { ExprWithCheck (Func, Expr); if (!ED_IsBool (Expr)) { @@ -3533,10 +3533,10 @@ void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is not - * a constant numeric integer value, a diagnostic will be printed, and the - * value is replaced by a constant one to make sure there are no internal - * errors that result from this input error. - */ +** a constant numeric integer value, a diagnostic will be printed, and the +** value is replaced by a constant one to make sure there are no internal +** errors that result from this input error. +*/ { ExprWithCheck (Func, Expr); if (!ED_IsConstAbsInt (Expr)) { @@ -3545,6 +3545,3 @@ void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) ED_MakeConstAbsInt (Expr, 1); } } - - - diff --git a/src/cc65/expr.h b/src/cc65/expr.h index c5d193e6b..a6c183cbd 100644 --- a/src/cc65/expr.h +++ b/src/cc65/expr.h @@ -1,8 +1,8 @@ /* - * expr.h - * - * Ullrich von Bassewitz, 21.06.1998 - */ +** expr.h +** +** Ullrich von Bassewitz, 21.06.1998 +*/ @@ -28,52 +28,52 @@ void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr); void MarkedExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr); /* Call an expression function with checks and record start and end of the - * generated code. - */ +** generated code. +*/ void PushAddr (const ExprDesc* Expr); /* If the expression contains an address that was somehow evaluated, - * push this address on the stack. This is a helper function for all - * sorts of implicit or explicit assignment functions where the lvalue - * must be saved if it's not constant, before evaluating the rhs. - */ +** push this address on the stack. This is a helper function for all +** sorts of implicit or explicit assignment functions where the lvalue +** must be saved if it's not constant, before evaluating the rhs. +*/ void Store (ExprDesc* Expr, const Type* StoreType); /* Store the primary register into the location denoted by lval. If StoreType - * is given, use this type when storing instead of lval->Type. If StoreType - * is NULL, use lval->Type instead. - */ +** is given, use this type when storing instead of lval->Type. If StoreType +** is NULL, use lval->Type instead. +*/ int evalexpr (unsigned flags, void (*Func) (ExprDesc*), ExprDesc* Expr); /* Will evaluate an expression via the given function. If the result is a - * constant, 0 is returned and the value is put in the Expr struct. If the - * result is not constant, LoadExpr is called to bring the value into the - * primary register and 1 is returned. - */ +** constant, 0 is returned and the value is put in the Expr struct. If the +** result is not constant, LoadExpr is called to bring the value into the +** primary register and 1 is returned. +*/ void Expression0 (ExprDesc* Expr); /* Evaluate an expression via hie0 and put the result into the primary register */ void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr); /* Will evaluate an expression via the given function. If the result is not - * a constant of some sort, a diagnostic will be printed, and the value is - * replaced by a constant one to make sure there are no internal errors that - * result from this input error. - */ +** a constant of some sort, a diagnostic will be printed, and the value is +** replaced by a constant one to make sure there are no internal errors that +** result from this input error. +*/ void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr); /* Will evaluate an expression via the given function. If the result is not - * something that may be evaluated in a boolean context, a diagnostic will be - * printed, and the value is replaced by a constant one to make sure there - * are no internal errors that result from this input error. - */ +** something that may be evaluated in a boolean context, a diagnostic will be +** printed, and the value is replaced by a constant one to make sure there +** are no internal errors that result from this input error. +*/ void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr); /* Will evaluate an expression via the given function. If the result is not - * a constant numeric integer value, a diagnostic will be printed, and the - * value is replaced by a constant one to make sure there are no internal - * errors that result from this input error. - */ +** a constant numeric integer value, a diagnostic will be printed, and the +** value is replaced by a constant one to make sure there are no internal +** errors that result from this input error. +*/ void hie10 (ExprDesc* lval); /* Handle ++, --, !, unary - etc. */ @@ -92,7 +92,3 @@ void hie0 (ExprDesc* Expr); /* End of expr.h */ #endif - - - - diff --git a/src/cc65/exprdesc.c b/src/cc65/exprdesc.c index 978aedfc6..405c277a0 100644 --- a/src/cc65/exprdesc.c +++ b/src/cc65/exprdesc.c @@ -104,9 +104,9 @@ int ED_CodeRangeIsEmpty (const ExprDesc* Expr) const char* ED_GetLabelName (const ExprDesc* Expr, long Offs) /* Return the assembler label name of the given expression. Beware: This - * function may use a static buffer, so the name may get "lost" on the second - * call to the function. - */ +** function may use a static buffer, so the name may get "lost" on the second +** call to the function. +*/ { static StrBuf Buf = STATIC_STRBUF_INITIALIZER; @@ -157,8 +157,8 @@ const char* ED_GetLabelName (const ExprDesc* Expr, long Offs) int ED_GetStackOffs (const ExprDesc* Expr, int Offs) /* Get the stack offset of an address on the stack in Expr taking into account - * an additional offset in Offs. - */ +** an additional offset in Offs. +*/ { PRECONDITION (ED_IsLocStack (Expr)); Offs += ((int) Expr->IVal) - StackPtr; @@ -198,8 +198,8 @@ ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value) ExprDesc* ED_MakeRValExpr (ExprDesc* Expr) /* Convert Expr into a rvalue which is in the primary register without an - * offset. - */ +** offset. +*/ { Expr->Sym = 0; Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET); @@ -214,8 +214,8 @@ ExprDesc* ED_MakeRValExpr (ExprDesc* Expr) ExprDesc* ED_MakeLValExpr (ExprDesc* Expr) /* Convert Expr into a lvalue which is in the primary register without an - * offset. - */ +** offset. +*/ { Expr->Sym = 0; Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET); @@ -230,9 +230,9 @@ ExprDesc* ED_MakeLValExpr (ExprDesc* Expr) int ED_IsConst (const ExprDesc* Expr) /* Return true if the expression denotes a constant of some sort. This can be a - * numeric constant, the address of a global variable (maybe with offset) or - * similar. - */ +** numeric constant, the address of a global variable (maybe with offset) or +** similar. +*/ { return ED_IsRVal (Expr) && (Expr->Flags & E_LOC_CONST) != 0; } @@ -261,8 +261,8 @@ int ED_IsNullPtr (const ExprDesc* Expr) int ED_IsBool (const ExprDesc* Expr) /* Return true of the expression can be treated as a boolean, that is, it can - * be an operand to a compare operation. - */ +** be an operand to a compare operation. +*/ { /* Either ints, floats, or pointers can be used in a boolean context */ return IsClassInt (Expr->Type) || @@ -373,6 +373,3 @@ Type* ReplaceType (ExprDesc* Expr, const Type* NewType) Expr->Type = TypeDup (NewType); return OldType; } - - - diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index f2d5ce322..99a17313e 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -315,14 +315,14 @@ int ED_CodeRangeIsEmpty (const ExprDesc* Expr); const char* ED_GetLabelName (const ExprDesc* Expr, long Offs); /* Return the assembler label name of the given expression. Beware: This - * function may use a static buffer, so the name may get "lost" on the second - * call to the function. - */ +** function may use a static buffer, so the name may get "lost" on the second +** call to the function. +*/ int ED_GetStackOffs (const ExprDesc* Expr, int Offs); /* Get the stack offset of an address on the stack in Expr taking into account - * an additional offset in Offs. - */ +** an additional offset in Offs. +*/ ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type); /* Make Expr an absolute const with the given value and type. */ @@ -332,25 +332,25 @@ ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value); ExprDesc* ED_MakeRValExpr (ExprDesc* Expr); /* Convert Expr into a rvalue which is in the primary register without an - * offset. - */ +** offset. +*/ ExprDesc* ED_MakeLValExpr (ExprDesc* Expr); /* Convert Expr into a lvalue which is in the primary register without an - * offset. - */ +** offset. +*/ int ED_IsConst (const ExprDesc* Expr); /* Return true if the expression denotes a constant of some sort. This can be a - * numeric constant, the address of a global variable (maybe with offset) or - * similar. - */ +** numeric constant, the address of a global variable (maybe with offset) or +** similar. +*/ #if defined(HAVE_INLINE) INLINE int ED_IsConstAbs (const ExprDesc* Expr) /* Return true if the expression denotes a constant absolute value. This can be - * a numeric constant, cast to any type. - */ +** a numeric constant, cast to any type. +*/ { return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL); } @@ -367,8 +367,8 @@ int ED_IsNullPtr (const ExprDesc* Expr); int ED_IsBool (const ExprDesc* Expr); /* Return true of the expression can be treated as a boolean, that is, it can - * be an operand to a compare operation. - */ +** be an operand to a compare operation. +*/ void PrintExprDesc (FILE* F, ExprDesc* Expr); /* Print an ExprDesc */ @@ -379,7 +379,5 @@ Type* ReplaceType (ExprDesc* Expr, const Type* NewType); /* End of exprdesc.h */ + #endif - - - diff --git a/src/cc65/funcdesc.c b/src/cc65/funcdesc.c index 874dfb101..b9561a97c 100644 --- a/src/cc65/funcdesc.c +++ b/src/cc65/funcdesc.c @@ -73,6 +73,3 @@ void FreeFuncDesc (FuncDesc* F) /* Free the structure */ xfree (F); } - - - diff --git a/src/cc65/funcdesc.h b/src/cc65/funcdesc.h index 7232bca1d..b79c6a055 100644 --- a/src/cc65/funcdesc.h +++ b/src/cc65/funcdesc.h @@ -86,7 +86,5 @@ void FreeFuncDesc (FuncDesc* D); /* End of funcdesc.h */ + #endif - - - diff --git a/src/cc65/function.c b/src/cc65/function.c index ccf2adf49..d9f1eeac3 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -228,8 +228,8 @@ int F_GetTopLevelSP (const Function* F) int F_ReserveLocalSpace (Function* F, unsigned Size) /* Reserve (but don't allocate) the given local space and return the stack - * offset. - */ +** offset. +*/ { F->Reserved += Size; return StackPtr - F->Reserved; @@ -239,8 +239,8 @@ int F_ReserveLocalSpace (Function* F, unsigned Size) int F_GetStackPtr (const Function* F) /* Return the current stack pointer including reserved (but not allocated) - * space on the stack. - */ +** space on the stack. +*/ { return StackPtr - F->Reserved; } @@ -249,8 +249,8 @@ int F_GetStackPtr (const Function* F) void F_AllocLocalSpace (Function* F) /* Allocate any local space previously reserved. The function will do - * nothing if there is no reserved local space. - */ +** nothing if there is no reserved local space. +*/ { if (F->Reserved > 0) { @@ -269,9 +269,9 @@ void F_AllocLocalSpace (Function* F) int F_AllocRegVar (Function* F, const Type* Type) /* Allocate a register variable for the given variable type. If the allocation - * was successful, return the offset of the register variable in the register - * bank (zero page storage). If there is no register space left, return -1. - */ +** was successful, return the offset of the register variable in the register +** bank (zero page storage). If there is no register space left, return -1. +*/ { /* Allow register variables only on top level and if enabled */ if (IS_Get (&EnableRegVars) && GetLexicalLevel () == LEX_LEVEL_FUNCTION) { @@ -282,9 +282,9 @@ int F_AllocRegVar (Function* F, const Type* Type) /* Do we have space left? */ if (F->RegOffs >= Size) { /* Space left. We allocate the variables from high to low addresses, - * so the adressing is compatible with the saved values on stack. - * This allows shorter code when saving/restoring the variables. - */ + ** so the addressing is compatible with the saved values on stack. + ** This allows shorter code when saving/restoring the variables. + */ F->RegOffs -= Size; return F->RegOffs; } @@ -408,16 +408,16 @@ void NewFunc (SymEntry* Func) ReenterFunctionLevel (D); /* Check if the function header contains unnamed parameters. These are - * only allowed in cc65 mode. - */ + ** only allowed in cc65 mode. + */ if ((D->Flags & FD_UNNAMED_PARAMS) != 0 && (IS_Get (&Standard) != STD_CC65)) { Error ("Parameter name omitted"); } /* Declare two special functions symbols: __fixargs__ and __argsize__. - * The latter is different depending on the type of the function (variadic - * or not). - */ + ** The latter is different depending on the type of the function (variadic + ** or not). + */ AddConstSym ("__fixargs__", type_uint, SC_DEF | SC_CONST, D->ParamSize); if (D->Flags & FD_VARIADIC) { /* Variadic function. The variable must be const. */ @@ -443,28 +443,28 @@ void NewFunc (SymEntry* Func) } /* If cc65 extensions aren't enabled, don't allow a main function that - * doesn't return an int. - */ + ** doesn't return an int. + */ if (IS_Get (&Standard) != STD_CC65 && CurrentFunc->ReturnType[0].C != T_INT) { Error ("`main' must always return an int"); } /* Add a forced import of a symbol that is contained in the startup - * code. This will force the startup code to be linked in. - */ + ** code. This will force the startup code to be linked in. + */ g_importstartup (); /* If main() takes parameters, generate a forced import to a function - * that will setup these parameters. This way, programs that do not - * need the additional code will not get it. - */ + ** that will setup these parameters. This way, programs that do not + ** need the additional code will not get it. + */ if (D->ParamCount > 0 || (D->Flags & FD_VARIADIC) != 0) { g_importmainargs (); } /* Determine if this is a main function in a C99 environment that - * returns an int. - */ + ** returns an int. + */ if (IsTypeInt (F_GetReturnType (CurrentFunc)) && IS_Get (&Standard) == STD_C99) { C99MainFunc = 1; @@ -507,9 +507,9 @@ void NewFunc (SymEntry* Func) StackPtr = 0; /* Walk through the parameter list and allocate register variable space - * for parameters declared as register. Generate code to swap the contents - * of the register bank with the save area on the stack. - */ + ** for parameters declared as register. Generate code to swap the contents + ** of the register bank with the save area on the stack. + */ Param = D->SymTab->SymHead; while (Param && (Param->Flags & SC_PARAM) != 0) { @@ -543,8 +543,8 @@ void NewFunc (SymEntry* Func) DeclareLocals (); /* Remember the current stack pointer. All variables allocated elsewhere - * must be dropped when doing a return from an inner block. - */ + ** must be dropped when doing a return from an inner block. + */ CurrentFunc->TopLevelSP = StackPtr; /* Now process statements in this block */ @@ -553,18 +553,18 @@ void NewFunc (SymEntry* Func) } /* If this is not a void function, and not the main function in a C99 - * environment returning int, output a warning if we didn't see a return - * statement. - */ + ** environment returning int, output a warning if we didn't see a return + ** statement. + */ if (!F_HasVoidReturn (CurrentFunc) && !F_HasReturn (CurrentFunc) && !C99MainFunc) { Warning ("Control reaches end of non-void function"); } /* If this is the main function in a C99 environment returning an int, let - * it always return zero. Note: Actual return statements jump to the return - * label defined below. - * The code is removed by the optimizer if unused. - */ + ** it always return zero. Note: Actual return statements jump to the return + ** label defined below. + ** The code is removed by the optimizer if unused. + */ if (C99MainFunc) { g_getimmed (CF_INT | CF_CONST, 0, 0); } @@ -601,6 +601,3 @@ void NewFunc (SymEntry* Func) FreeFunction (CurrentFunc); CurrentFunc = 0; } - - - diff --git a/src/cc65/function.h b/src/cc65/function.h index b70389372..627457277 100644 --- a/src/cc65/function.h +++ b/src/cc65/function.h @@ -99,24 +99,24 @@ int F_GetTopLevelSP (const Function* F); int F_ReserveLocalSpace (Function* F, unsigned Size); /* Reserve (but don't allocate) the given local space and return the stack - * offset. - */ +** offset. +*/ int F_GetStackPtr (const Function* F); /* Return the current stack pointer including reserved (but not allocated) - * space on the stack. - */ +** space on the stack. +*/ void F_AllocLocalSpace (Function* F); /* Allocate any local space previously reserved. The function will do - * nothing if there is no reserved local space. - */ +** nothing if there is no reserved local space. +*/ int F_AllocRegVar (Function* F, const Type* Type); /* Allocate a register variable for the given variable type. If the allocation - * was successful, return the offset of the register variable in the register - * bank (zero page storage). If there is no register space left, return -1. - */ +** was successful, return the offset of the register variable in the register +** bank (zero page storage). If there is no register space left, return -1. +*/ void NewFunc (struct SymEntry* Func); /* Parse argument declarations and function body. */ @@ -124,7 +124,5 @@ void NewFunc (struct SymEntry* Func); /* End of function.h */ + #endif - - - diff --git a/src/cc65/global.c b/src/cc65/global.c index a6d752b27..e2800a65e 100644 --- a/src/cc65/global.c +++ b/src/cc65/global.c @@ -67,6 +67,3 @@ IntStack DataAlignment = INTSTACK(1); /* Alignment for data */ StrBuf DepName = STATIC_STRBUF_INITIALIZER; /* Name of dependencies file */ StrBuf FullDepName = STATIC_STRBUF_INITIALIZER; /* Name of full dependencies file */ StrBuf DepTarget = STATIC_STRBUF_INITIALIZER; /* Name of dependency target */ - - - diff --git a/src/cc65/global.h b/src/cc65/global.h index b9c15a26e..2abd78601 100644 --- a/src/cc65/global.h +++ b/src/cc65/global.h @@ -81,7 +81,3 @@ extern StrBuf DepTarget; /* Name of dependency target */ /* End of global.h */ #endif - - - - diff --git a/src/cc65/goto.c b/src/cc65/goto.c index 6f12c145b..6e282c636 100644 --- a/src/cc65/goto.c +++ b/src/cc65/goto.c @@ -86,6 +86,3 @@ void DoLabel (void) NextToken (); NextToken (); } - - - diff --git a/src/cc65/goto.h b/src/cc65/goto.h index a887b0eaa..3ca8223e2 100644 --- a/src/cc65/goto.h +++ b/src/cc65/goto.h @@ -53,7 +53,5 @@ void DoLabel (void); /* End of goto.h */ + #endif - - - diff --git a/src/cc65/hexval.c b/src/cc65/hexval.c index aaedf68ce..37e43da14 100644 --- a/src/cc65/hexval.c +++ b/src/cc65/hexval.c @@ -50,8 +50,8 @@ unsigned HexVal (int C) /* Convert a hex digit into a value. The function will emit an error for - * invalid hex digits. - */ +** invalid hex digits. +*/ { if (!IsXDigit (C)) { Error ("Invalid hexadecimal digit: `%c'", C); @@ -62,6 +62,3 @@ unsigned HexVal (int C) return toupper (C) - 'A' + 10; } } - - - diff --git a/src/cc65/hexval.h b/src/cc65/hexval.h index 770ed5ce5..0361ee0cf 100644 --- a/src/cc65/hexval.h +++ b/src/cc65/hexval.h @@ -46,15 +46,11 @@ unsigned HexVal (int C); /* Convert a hex digit into a value. The function will emit an error for - * invalid hex digits. - */ +** invalid hex digits. +*/ /* End of hexval.h */ + #endif - - - - - diff --git a/src/cc65/ident.c b/src/cc65/ident.c index fac69bd0a..7748095c7 100644 --- a/src/cc65/ident.c +++ b/src/cc65/ident.c @@ -52,6 +52,3 @@ int IsIdent (char c) { return (IsAlpha (c) || c == '_'); } - - - diff --git a/src/cc65/ident.h b/src/cc65/ident.h index d470e198b..36d5ae122 100644 --- a/src/cc65/ident.h +++ b/src/cc65/ident.h @@ -65,7 +65,5 @@ int IsIdent (char c); /* End of ident.h */ + #endif - - - diff --git a/src/cc65/incpath.c b/src/cc65/incpath.c index 7a4b31e94..ab164d5ca 100644 --- a/src/cc65/incpath.c +++ b/src/cc65/incpath.c @@ -44,8 +44,8 @@ -SearchPath* SysIncSearchPath; /* System include path */ -SearchPath* UsrIncSearchPath; /* User include path */ +SearchPaths* SysIncSearchPath; /* System include path */ +SearchPaths* UsrIncSearchPath; /* User include path */ @@ -76,13 +76,10 @@ void FinishIncludePaths (void) AddSubSearchPathFromEnv (SysIncSearchPath, "CC65_HOME", "include"); /* Add some compiled-in search paths if defined at compile time. */ -#ifdef CC65_INC +#if defined(CC65_INC) && !defined(_WIN32) AddSearchPath (SysIncSearchPath, STRINGIZE (CC65_INC)); #endif /* Add paths relative to the parent directory of the Windows binary. */ AddSubSearchPathFromWinBin (SysIncSearchPath, "include"); } - - - diff --git a/src/cc65/incpath.h b/src/cc65/incpath.h index ed8ba50cc..05824ac5e 100644 --- a/src/cc65/incpath.h +++ b/src/cc65/incpath.h @@ -49,8 +49,8 @@ -extern SearchPath* SysIncSearchPath; /* System include path */ -extern SearchPath* UsrIncSearchPath; /* User include path */ +extern SearchPaths* SysIncSearchPath; /* System include path */ +extern SearchPaths* UsrIncSearchPath; /* User include path */ @@ -69,7 +69,5 @@ void FinishIncludePaths (void); /* End of incpath.h */ + #endif - - - diff --git a/src/cc65/input.c b/src/cc65/input.c index a98c72e4f..005e0c668 100644 --- a/src/cc65/input.c +++ b/src/cc65/input.c @@ -144,8 +144,8 @@ static IFile* NewIFile (const char* Name, InputType Type) static AFile* NewAFile (IFile* IF, FILE* F) /* Create a new AFile, push it onto the stack, add the path of the file to - * the path search list, and finally return a pointer to the new AFile struct. - */ +** the path search list, and finally return a pointer to the new AFile struct. +*/ { StrBuf Path = AUTO_STRBUF_INITIALIZER; @@ -158,19 +158,19 @@ static AFile* NewAFile (IFile* IF, FILE* F) AF->Input = IF; /* Increment the usage counter of the corresponding IFile. If this - * is the first use, set the file data and output debug info if - * requested. - */ + ** is the first use, set the file data and output debug info if + ** requested. + */ if (IF->Usage++ == 0) { /* Get file size and modification time. There a race condition here, - * since we cannot use fileno() (non standard identifier in standard - * header file), and therefore not fstat. When using stat with the - * file name, there's a risk that the file was deleted and recreated - * while it was open. Since mtime and size are only used to check - * if a file has changed in the debugger, we will ignore this problem - * here. - */ + ** since we cannot use fileno() (non standard identifier in standard + ** header file), and therefore not fstat. When using stat with the + ** file name, there's a risk that the file was deleted and recreated + ** while it was open. Since mtime and size are only used to check + ** if a file has changed in the debugger, we will ignore this problem + ** here. + */ struct stat Buf; if (FileStat (IF->Name, &Buf) != 0) { /* Error */ @@ -187,9 +187,9 @@ static AFile* NewAFile (IFile* IF, FILE* F) CollAppend (&AFiles, AF); /* Get the path of this file and add it as an extra search path. - * To avoid file search overhead, we will add one path only once. - * This is checked by the PushSearchPath function. - */ + ** To avoid file search overhead, we will add one path only once. + ** This is checked by the PushSearchPath function. + */ SB_CopyBuf (&Path, IF->Name, FindName (IF->Name) - IF->Name); SB_Terminate (&Path); AF->SearchPath = PushSearchPath (UsrIncSearchPath, SB_GetConstBuf (&Path)); @@ -217,9 +217,9 @@ static void FreeAFile (AFile* AF) static IFile* FindFile (const char* Name) /* Find the file with the given name in the list of all files. Since the list - * is not large (usually less than 10), I don't care about using hashes or - * similar things and do a linear search. - */ +** is not large (usually less than 10), I don't care about using hashes or +** similar things and do a linear search. +*/ { unsigned I; for (I = 0; I < CollCount (&IFiles); ++I) { @@ -261,8 +261,8 @@ void OpenMainFile (const char* Name) Line = NewStrBuf (); /* Update the line infos, so we have a valid line info even at start of - * the main file before the first line is read. - */ + ** the main file before the first line is read. + */ UpdateLineInfo (MainFile->Input, MainFile->Line, Line); } @@ -289,8 +289,8 @@ void OpenIncludeFile (const char* Name, InputType IT) } /* Search the list of all input files for this file. If we don't find - * it, create a new IFile object. - */ + ** it, create a new IFile object. + */ IF = FindFile (N); if (IF == 0) { IF = NewIFile (N, IT); @@ -318,8 +318,8 @@ void OpenIncludeFile (const char* Name, InputType IT) static void CloseIncludeFile (void) /* Close an include file and switch to the higher level file. Set Input to - * NULL if this was the main file. - */ +** NULL if this was the main file. +*/ { AFile* Input; @@ -351,9 +351,9 @@ static void CloseIncludeFile (void) static void GetInputChar (void) /* Read the next character from the input stream and make CurC and NextC - * valid. If end of line is reached, both are set to NUL, no more lines - * are read by this function. - */ +** valid. If end of line is reached, both are set to NUL, no more lines +** are read by this function. +*/ { /* Drop all pushed fragments that don't have data left */ while (SB_GetIndex (Line) >= SB_GetLen (Line)) { @@ -389,9 +389,9 @@ static void GetInputChar (void) void NextChar (void) /* Skip the current input character and read the next one from the input - * stream. CurC and NextC are valid after the call. If end of line is - * reached, both are set to NUL, no more lines are read by this function. - */ +** stream. CurC and NextC are valid after the call. If end of line is +** reached, both are set to NUL, no more lines are read by this function. +*/ { /* Skip the last character read */ SB_Skip (Line); @@ -423,8 +423,8 @@ void ClearLine (void) StrBuf* InitLine (StrBuf* Buf) /* Initialize Line from Buf and read CurC and NextC from the new input line. - * The function returns the old input line. - */ +** The function returns the old input line. +*/ { StrBuf* OldLine = Line; Line = Buf; @@ -468,8 +468,8 @@ int NextLine (void) CloseIncludeFile (); /* If there is no file open, bail out, otherwise get the - * previous input file and start over. - */ + ** previous input file and start over. + */ if (CollCount (&AFiles) == 0) { return 0; } @@ -484,16 +484,16 @@ int NextLine (void) ++Input->Line; /* If the \n is preceeded by a \r, remove the \r, so we can read - * DOS/Windows files under *nix. - */ + ** DOS/Windows files under *nix. + */ if (SB_LookAtLast (Line) == '\r') { SB_Drop (Line, 1); } /* If we don't have a line continuation character at the end, - * we're done with this line. Otherwise replace the character - * by a newline and continue reading. - */ + ** we're done with this line. Otherwise replace the character + ** by a newline and continue reading. + */ if (SB_LookAtLast (Line) == '\\') { Line->Buf[Line->Len-1] = '\n'; } else { @@ -613,8 +613,8 @@ static void WriteDep (FILE* F, InputType Types) static void CreateDepFile (const char* Name, InputType Types) /* Create a dependency file with the given name and place dependencies for - * all files with the given types there. - */ +** all files with the given types there. +*/ { /* Open the file */ FILE* F = fopen (Name, "w"); @@ -623,8 +623,8 @@ static void CreateDepFile (const char* Name, InputType Types) } /* If a dependency target was given, use it, otherwise use the output - * file name as target, followed by a tab character. - */ + ** file name as target, followed by a tab character. + */ if (SB_IsEmpty (&DepTarget)) { WriteEscaped (F, OutputFilename); } else { @@ -661,5 +661,3 @@ void CreateDependencies (void) IT_MAIN | IT_SYSINC | IT_USRINC); } } - - diff --git a/src/cc65/input.h b/src/cc65/input.h index 4d2fd7fb1..a643800ba 100644 --- a/src/cc65/input.h +++ b/src/cc65/input.h @@ -52,12 +52,12 @@ /* An enum that describes different types of input files. The members are - * choosen so that it is possible to combine them to bitsets - */ +** choosen so that it is possible to combine them to bitsets +*/ typedef enum { - IT_MAIN = 0x01, /* Main input file */ - IT_SYSINC = 0x02, /* System include file (using <>) */ - IT_USRINC = 0x04, /* User include file (using "") */ + IT_MAIN = 0x01, /* Main input file */ + IT_SYSINC = 0x02, /* System include file (using <>) */ + IT_USRINC = 0x04, /* User include file (using "") */ } InputType; /* Forward for an IFile structure */ @@ -86,17 +86,17 @@ void OpenIncludeFile (const char* Name, InputType IT); void NextChar (void); /* Read the next character from the input stream and make CurC and NextC - * valid. If end of line is reached, both are set to NUL, no more lines - * are read by this function. - */ +** valid. If end of line is reached, both are set to NUL, no more lines +** are read by this function. +*/ void ClearLine (void); /* Clear the current input line */ StrBuf* InitLine (StrBuf* Buf); /* Initialize Line from Buf and read CurC and NextC from the new input line. - * The function returns the old input line. - */ +** The function returns the old input line. +*/ int NextLine (void); /* Get a line from the current input. Returns 0 on end of file. */ @@ -116,7 +116,5 @@ void CreateDependencies (void); /* End of input.h */ + #endif - - - diff --git a/src/cc65/lineinfo.c b/src/cc65/lineinfo.c index 342fce969..f5c2e2689 100644 --- a/src/cc65/lineinfo.c +++ b/src/cc65/lineinfo.c @@ -91,9 +91,9 @@ static LineInfo* NewLineInfo (struct IFile* F, unsigned LineNum, const StrBuf* L LI->LineNum = LineNum; /* Copy the line, replacing tabs by spaces in the given line since tabs - * will give rather arbitrary results when used in the output later, and - * if we do it here, we won't need another copy later. - */ + ** will give rather arbitrary results when used in the output later, and + ** if we do it here, we won't need another copy later. + */ T = LI->Line; while (Len--) { if (*S == '\t') { @@ -134,8 +134,8 @@ LineInfo* UseLineInfo (LineInfo* LI) void ReleaseLineInfo (LineInfo* LI) /* Release a reference to the given line info, free the structure if the - * reference count drops to zero. - */ +** reference count drops to zero. +*/ { CHECK (LI && LI->RefCount > 0); if (--LI->RefCount == 0) { @@ -148,8 +148,8 @@ void ReleaseLineInfo (LineInfo* LI) LineInfo* GetCurLineInfo (void) /* Return a pointer to the current line info. The reference count is NOT - * increased, use UseLineInfo for that purpose. - */ +** increased, use UseLineInfo for that purpose. +*/ { return CurLineInfo; } @@ -165,8 +165,8 @@ void UpdateLineInfo (struct IFile* F, unsigned LineNum, const StrBuf* Line) } /* If we have intermixed assembly switched off, use an empty line instead - * of the supplied one to save some memory. - */ + ** of the supplied one to save some memory. + */ if (!AddSource) { Line = &EmptyStrBuf; } @@ -192,6 +192,3 @@ unsigned GetInputLine (const LineInfo* LI) PRECONDITION (LI != 0); return LI->LineNum; } - - - diff --git a/src/cc65/lineinfo.h b/src/cc65/lineinfo.h index 3ecd0ce84..8dbe06846 100644 --- a/src/cc65/lineinfo.h +++ b/src/cc65/lineinfo.h @@ -61,8 +61,8 @@ struct IFile; /* The text for the actual line is allocated at the end of the structure, so - * the size of the structure varies. - */ +** the size of the structure varies. +*/ typedef struct LineInfo LineInfo; struct LineInfo { unsigned RefCount; /* Reference counter */ @@ -84,13 +84,13 @@ LineInfo* UseLineInfo (LineInfo* LI); void ReleaseLineInfo (LineInfo* LI); /* Release a reference to the given line info, free the structure if the - * reference count drops to zero. - */ +** reference count drops to zero. +*/ LineInfo* GetCurLineInfo (void); /* Return a pointer to the current line info. The reference count is NOT - * increased, use UseLineInfo for that purpose. - */ +** increased, use UseLineInfo for that purpose. +*/ void UpdateLineInfo (struct IFile* F, unsigned LineNum, const StrBuf* Line); /* Update the line info - called if a new line is read */ @@ -104,8 +104,5 @@ unsigned GetInputLine (const LineInfo* LI); /* End of lineinfo.h */ + #endif - - - - diff --git a/src/cc65/litpool.c b/src/cc65/litpool.c index 013c6ad4a..c427310d9 100644 --- a/src/cc65/litpool.c +++ b/src/cc65/litpool.c @@ -78,10 +78,10 @@ static LiteralPool* GlobalPool = 0; static LiteralPool* LP = 0; /* Stack that contains the nested literal pools. Since TOS is in LiteralPool - * and functions aren't nested in C, the maximum depth is 1. I'm using a - * collection anyway, so the code is prepared for nested functions or - * whatever. - */ +** and functions aren't nested in C, the maximum depth is 1. I'm using a +** collection anyway, so the code is prepared for nested functions or +** whatever. +*/ static Collection LPStack = STATIC_COLLECTION_INITIALIZER; @@ -286,8 +286,8 @@ void PushLiteralPool (struct SymEntry* Func) LiteralPool* PopLiteralPool (void) /* Pop the last literal pool from TOS and activate it. Return the old - * literal pool. - */ +** literal pool. +*/ { /* Remember the current literal pool */ LiteralPool* Old = LP; @@ -313,8 +313,8 @@ static void MoveLiterals (Collection* Source, Collection* Target) Literal* L = CollAt (Source, I); /* If it is referenced and not output, add it to the Target pool, - * otherwise free it - */ + ** otherwise free it + */ if (L->RefCount && !L->Output) { CollAppend (Target, L); } else { @@ -327,8 +327,8 @@ static void MoveLiterals (Collection* Source, Collection* Target) void MoveLiteralPool (LiteralPool* LocalPool) /* Move all referenced literals in LocalPool to the global literal pool. This - * function will free LocalPool after moving the used string literals. - */ +** function will free LocalPool after moving the used string literals. +*/ { /* Move the literals */ MoveLiterals (&LocalPool->WritableLiterals, &GlobalPool->WritableLiterals); @@ -403,10 +403,10 @@ static void OutputReadOnlyLiterals (Collection* Literals) TranslateLiteral (L); /* Check if this literal is part of another one. Since the literals - * are sorted by size (larger ones first), it can only be part of a - * literal with a smaller index. - * Beware: Only check literals that have actually been referenced. - */ + ** are sorted by size (larger ones first), it can only be part of a + ** literal with a smaller index. + ** Beware: Only check literals that have actually been referenced. + */ C = 0; for (J = 0; J < I; ++J) { @@ -474,8 +474,8 @@ Literal* AddLiteral (const char* S) Literal* AddLiteralBuf (const void* Buf, unsigned Len) /* Add a buffer containing a literal string to the literal pool. Return the - * literal. - */ +** literal. +*/ { /* Create a new literal */ Literal* L = NewLiteral (Buf, Len); @@ -498,6 +498,3 @@ Literal* AddLiteralStr (const StrBuf* S) { return AddLiteralBuf (SB_GetConstBuf (S), SB_GetLen (S)); } - - - diff --git a/src/cc65/litpool.h b/src/cc65/litpool.h index 7a771d5eb..6efdfb089 100644 --- a/src/cc65/litpool.h +++ b/src/cc65/litpool.h @@ -105,13 +105,13 @@ void PushLiteralPool (struct SymEntry* Func); LiteralPool* PopLiteralPool (void); /* Pop the last literal pool from TOS and activate it. Return the old - * literal pool. - */ +** literal pool. +*/ void MoveLiteralPool (LiteralPool* LocalPool); /* Move all referenced literals in LocalPool to the global literal pool. This - * function will free LocalPool after moving the used string literals. - */ +** function will free LocalPool after moving the used string literals. +*/ void OutputLiteralPool (void); /* Output the literal pool */ @@ -121,8 +121,8 @@ Literal* AddLiteral (const char* S); Literal* AddLiteralBuf (const void* Buf, unsigned Len); /* Add a buffer containing a literal string to the literal pool. Return the - * literal. - */ +** literal. +*/ Literal* AddLiteralStr (const StrBuf* S); /* Add a literal string to the literal pool. Return the literal. */ @@ -130,8 +130,5 @@ Literal* AddLiteralStr (const StrBuf* S); /* End of litpool.h */ + #endif - - - - diff --git a/src/cc65/loadexpr.c b/src/cc65/loadexpr.c index d3c190b13..fa37c6bbd 100644 --- a/src/cc65/loadexpr.c +++ b/src/cc65/loadexpr.c @@ -71,8 +71,8 @@ static void LoadConstant (unsigned Flags, ExprDesc* Expr) case E_LOC_REGISTER: /* Register variable. Taking the address is usually not - * allowed. - */ + ** allowed. + */ if (IS_Get (&AllowRegVarAddr) == 0) { Error ("Cannot take the address of a register variable"); } @@ -96,10 +96,10 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr) if (ED_IsLVal (Expr)) { /* Dereferenced lvalue. If this is a bit field its type is unsigned. - * But if the field is completely contained in the lower byte, we will - * throw away the high byte anyway and may therefore load just the - * low byte. - */ + ** But if the field is completely contained in the lower byte, we will + ** throw away the high byte anyway and may therefore load just the + ** low byte. + */ if (ED_IsBitField (Expr)) { Flags |= (Expr->BitOffs + Expr->BitWidth <= CHAR_BITS)? CF_CHAR : CF_INT; Flags |= CF_UNSIGNED; @@ -155,9 +155,9 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr) } /* Handle bit fields. The actual type may have been casted or - * converted, so be sure to always use unsigned ints for the - * operations. - */ + ** converted, so be sure to always use unsigned ints for the + ** operations. + */ if (ED_IsBitField (Expr)) { unsigned F = CF_INT | CF_UNSIGNED | CF_CONST | (Flags & CF_TEST); /* Shift right by the bit offset */ @@ -177,8 +177,8 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr) if (ED_IsLocExpr (Expr)) { if (Expr->IVal != 0) { /* We have an expression in the primary plus a constant - * offset. Adjust the value in the primary accordingly. - */ + ** offset. Adjust the value in the primary accordingly. + */ Flags |= TypeOf (Expr->Type); g_inc (Flags | CF_CONST, Expr->IVal); } @@ -197,6 +197,3 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr) } } - - - diff --git a/src/cc65/loadexpr.h b/src/cc65/loadexpr.h index acd570f1f..3f13311f1 100644 --- a/src/cc65/loadexpr.h +++ b/src/cc65/loadexpr.h @@ -60,7 +60,5 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr); /* End of loadexpr.h */ + #endif - - - diff --git a/src/cc65/locals.c b/src/cc65/locals.c index bdc0df906..ffadb1bd5 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -96,8 +96,8 @@ static void AllocStorage (unsigned Label, void (*UseSeg) (), unsigned Size) static void ParseRegisterDecl (Declaration* Decl, int Reg) /* Parse the declaration of a register variable. Reg is the offset of the - * variable in the register bank. - */ +** variable in the register bank. +*/ { SymEntry* Sym; @@ -112,9 +112,9 @@ static void ParseRegisterDecl (Declaration* Decl, int Reg) g_save_regvars (Reg, Size); /* Add the symbol to the symbol table. We do that now, because for register - * variables the current stack pointer is implicitly used as location for - * the save area. - */ + ** variables the current stack pointer is implicitly used as location for + ** the save area. + */ Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg); /* Check for an optional initialization */ @@ -129,18 +129,18 @@ static void ParseRegisterDecl (Declaration* Decl, int Reg) if (IsCompound) { /* Switch to read only data and define a label for the - * initialization data. - */ + ** initialization data. + */ unsigned InitLabel = AllocLabel (g_userodata); /* Parse the initialization generating a memory image of the - * data in the RODATA segment. The function does return the size - * of the initialization data, which may be greater than the - * actual size of the type, if the type is a structure with a - * flexible array member that has been initialized. Since we must - * know the size of the data in advance for register variables, - * we cannot allow that here. - */ + ** data in the RODATA segment. The function does return the size + ** of the initialization data, which may be greater than the + ** actual size of the type, if the type is a structure with a + ** flexible array member that has been initialized. Since we must + ** know the size of the data in advance for register variables, + ** we cannot allow that here. + */ if (ParseInit (Sym->Type) != Size) { Error ("Cannot initialize flexible array members of storage class `register'"); } @@ -192,8 +192,8 @@ static void ParseAutoDecl (Declaration* Decl) if (IS_Get (&StaticLocals) == 0) { /* Add the symbol to the symbol table. The stack offset we use here - * may get corrected later. - */ + ** may get corrected later. + */ Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, F_GetStackPtr (CurrentFunc) - (int) Size); @@ -210,32 +210,32 @@ static void ParseAutoDecl (Declaration* Decl) if (IsCompound) { /* Switch to read only data and define a label for the - * initialization data. - */ + ** initialization data. + */ unsigned InitLabel = AllocLabel (g_userodata); /* Parse the initialization generating a memory image of the - * data in the RODATA segment. The function will return the - * actual size of the initialization data, which may be - * greater than the size of the variable if it is a struct - * that contains a flexible array member and we're not in - * ANSI mode. - */ + ** data in the RODATA segment. The function will return the + ** actual size of the initialization data, which may be + ** greater than the size of the variable if it is a struct + ** that contains a flexible array member and we're not in + ** ANSI mode. + */ Size = ParseInit (Sym->Type); /* Now reserve space for the variable on the stack and correct - * the offset in the symbol table entry. - */ + ** the offset in the symbol table entry. + */ Sym->V.Offs = F_ReserveLocalSpace (CurrentFunc, Size); /* Next, allocate the space on the stack. This means that the - * variable is now located at offset 0 from the current sp. - */ + ** variable is now located at offset 0 from the current sp. + */ F_AllocLocalSpace (CurrentFunc); /* Generate code to copy the initialization data into the - * variable space - */ + ** variable space + */ g_initauto (InitLabel, Size); } else { @@ -253,8 +253,8 @@ static void ParseAutoDecl (Declaration* Decl) TypeConversion (&Expr, Sym->Type); /* If the value is not const, load it into the primary. - * Otherwise pass the information to the code generator. - */ + ** Otherwise pass the information to the code generator. + */ if (ED_IsConstAbsInt (&Expr)) { Flags |= CF_CONST; } else { @@ -272,8 +272,8 @@ static void ParseAutoDecl (Declaration* Decl) } else { /* Non-initialized local variable. Just keep track of - * the space needed. - */ + ** the space needed. + */ F_ReserveLocalSpace (CurrentFunc, Size); } @@ -302,13 +302,13 @@ static void ParseAutoDecl (Declaration* Decl) if (IsCompound) { /* Switch to read only data and define a label for the - * initialization data. - */ + ** initialization data. + */ unsigned InitLabel = AllocLabel (g_userodata); /* Parse the initialization generating a memory image of the - * data in the RODATA segment. - */ + ** data in the RODATA segment. + */ Size = ParseInit (Sym->Type); /* Allocate space for the variable */ @@ -371,9 +371,9 @@ static void ParseStaticDecl (Declaration* Decl) if (CurTok.Tok == TOK_ASSIGN) { /* Initialization ahead, switch to data segment and define the label. - * For arrays, we need to check the elements of the array for - * constness, not the array itself. - */ + ** For arrays, we need to check the elements of the array for + ** constness, not the array itself. + */ if (IsQualConst (GetBaseElementType (Sym->Type))) { g_userodata (); } else { @@ -427,8 +427,8 @@ static void ParseOneDecl (const DeclSpec* Spec) } /* If we don't have a name, this was flagged as an error earlier. - * To avoid problems later, use an anonymous name here. - */ + ** To avoid problems later, use an anonymous name here. + */ if (Decl.Ident[0] == '\0') { AnonName (Decl.Ident, "param"); } @@ -443,8 +443,8 @@ static void ParseOneDecl (const DeclSpec* Spec) (Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) { /* If we have a register variable, try to allocate a register and - * convert the declaration to "auto" if this is not possible. - */ + ** convert the declaration to "auto" if this is not possible. + */ int Reg = 0; /* Initialize to avoid gcc complains */ if ((Decl.StorageClass & SC_REGISTER) != 0 && (Reg = F_AllocRegVar (CurrentFunc, Decl.Type)) < 0) { @@ -493,12 +493,12 @@ void DeclareLocals (void) while (1) { /* Check variable declarations. We need to distinguish between a - * default int type and the end of variable declarations. So we - * will do the following: If there is no explicit storage class - * specifier *and* no explicit type given, *and* no type qualifiers - * have been read, it is assumed that we have reached the end of - * declarations. - */ + ** default int type and the end of variable declarations. So we + ** will do the following: If there is no explicit storage class + ** specifier *and* no explicit type given, *and* no type qualifiers + ** have been read, it is assumed that we have reached the end of + ** declarations. + */ DeclSpec Spec; ParseDeclSpec (&Spec, SC_AUTO, T_INT); if ((Spec.Flags & DS_DEF_STORAGE) != 0 && /* No storage spec */ @@ -539,12 +539,9 @@ void DeclareLocals (void) F_AllocLocalSpace (CurrentFunc); /* In case we've allocated local variables in this block, emit a call to - * the stack checking routine if stack checks are enabled. - */ + ** the stack checking routine if stack checks are enabled. + */ if (IS_Get (&CheckStack) && InitialStack != StackPtr) { g_cstackcheck (); } } - - - diff --git a/src/cc65/locals.h b/src/cc65/locals.h index d47cb6725..53d08447c 100644 --- a/src/cc65/locals.h +++ b/src/cc65/locals.h @@ -55,14 +55,12 @@ void DeclareLocals (void); void RestoreRegVars (int HaveResult); /* Restore the register variables for the local function if there are any. - * The parameter tells us if there is a return value in ax, in that case, - * the accumulator must be saved across the restore. - */ +** The parameter tells us if there is a return value in ax, in that case, +** the accumulator must be saved across the restore. +*/ /* End of locals.h */ + #endif - - - diff --git a/src/cc65/loop.c b/src/cc65/loop.c index 4a3cdd882..c15c37a79 100644 --- a/src/cc65/loop.c +++ b/src/cc65/loop.c @@ -98,6 +98,3 @@ void DelLoop (void) LoopStack = LoopStack->Next; xfree (L); } - - - diff --git a/src/cc65/loop.h b/src/cc65/loop.h index f24a3ef9f..fa2859f61 100644 --- a/src/cc65/loop.h +++ b/src/cc65/loop.h @@ -74,6 +74,3 @@ void DelLoop (void); /* End of loop.h */ #endif - - - diff --git a/src/cc65/macrotab.c b/src/cc65/macrotab.c index acb532ac4..daf5cd7b8 100644 --- a/src/cc65/macrotab.c +++ b/src/cc65/macrotab.c @@ -66,8 +66,8 @@ static Macro* MacroTab[MACRO_TAB_SIZE]; Macro* NewMacro (const char* Name) /* Allocate a macro structure with the given name. The structure is not - * inserted into the macro table. - */ +** inserted into the macro table. +*/ { /* Get the length of the macro name */ unsigned Len = strlen(Name); @@ -93,8 +93,8 @@ Macro* NewMacro (const char* Name) void FreeMacro (Macro* M) /* Delete a macro definition. The function will NOT remove the macro from the - * table, use UndefineMacro for that. - */ +** table, use UndefineMacro for that. +*/ { unsigned I; @@ -152,9 +152,9 @@ void InsertMacro (Macro* M) int UndefineMacro (const char* Name) /* Search for the macro with the given name and remove it from the macro - * table if it exists. Return 1 if a macro was found and deleted, return - * 0 otherwise. - */ +** table if it exists. Return 1 if a macro was found and deleted, return +** 0 otherwise. +*/ { /* Get the hash value of the macro name */ unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE; @@ -217,8 +217,8 @@ Macro* FindMacro (const char* Name) int FindMacroArg (Macro* M, const char* Arg) /* Search for a formal macro argument. If found, return the index of the - * argument. If the argument was not found, return -1. - */ +** argument. If the argument was not found, return -1. +*/ { unsigned I; for (I = 0; I < CollCount (&M->FormalArgs); ++I) { @@ -238,9 +238,9 @@ void AddMacroArg (Macro* M, const char* Arg) /* Add a formal macro argument. */ { /* Check if we have a duplicate macro argument, but add it anyway. - * Beware: Don't use FindMacroArg here, since the actual argument array - * may not be initialized. - */ + ** Beware: Don't use FindMacroArg here, since the actual argument array + ** may not be initialized. + */ unsigned I; for (I = 0; I < CollCount (&M->FormalArgs); ++I) { if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) { @@ -302,6 +302,3 @@ void PrintMacroStats (FILE* F) } } } - - - diff --git a/src/cc65/macrotab.h b/src/cc65/macrotab.h index c20ab81c4..c3ff20ceb 100644 --- a/src/cc65/macrotab.h +++ b/src/cc65/macrotab.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2000-2005, Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -74,13 +74,13 @@ struct Macro { Macro* NewMacro (const char* Name); /* Allocate a macro structure with the given name. The structure is not - * inserted into the macro table. - */ +** inserted into the macro table. +*/ void FreeMacro (Macro* M); /* Delete a macro definition. The function will NOT remove the macro from the - * table, use UndefineMacro for that. - */ +** table, use UndefineMacro for that. +*/ void DefineNumericMacro (const char* Name, long Val); /* Define a macro for a numeric constant */ @@ -93,9 +93,9 @@ void InsertMacro (Macro* M); int UndefineMacro (const char* Name); /* Search for the macro with the given name and remove it from the macro - * table if it exists. Return 1 if a macro was found and deleted, return - * 0 otherwise. - */ +** table if it exists. Return 1 if a macro was found and deleted, return +** 0 otherwise. +*/ Macro* FindMacro (const char* Name); /* Find a macro with the given name. Return the macro definition or NULL */ @@ -112,8 +112,8 @@ INLINE int IsMacro (const char* Name) int FindMacroArg (Macro* M, const char* Arg); /* Search for a formal macro argument. If found, return the index of the - * argument. If the argument was not found, return -1. - */ +** argument. If the argument was not found, return -1. +*/ void AddMacroArg (Macro* M, const char* Arg); /* Add a formal macro argument. */ @@ -127,7 +127,5 @@ void PrintMacroStats (FILE* F); /* End of macrotab.h */ + #endif - - - diff --git a/src/cc65/main.c b/src/cc65/main.c index 6882d56a3..b8963258d 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -160,6 +160,10 @@ static void SetSys (const char* Sys) AbEnd ("Cannot use `module' as a target for the compiler"); break; + case TGT_ATARI5200: + DefineNumericMacro ("__ATARI5200__", 1); + break; + case TGT_ATARI: DefineNumericMacro ("__ATARI__", 1); break; @@ -306,9 +310,9 @@ static void DefineSym (const char* Def) DefineNumericMacro (Def, 1); } else { /* We have a value, P points to the '=' character. Since the argument - * is const, create a copy and replace the '=' in the copy by a zero - * terminator. - */ + ** is const, create a copy and replace the '=' in the copy by a zero + ** terminator. + */ char* Q; unsigned Len = strlen (Def)+1; char* S = (char*) xmalloc (Len); @@ -468,13 +472,13 @@ static void OptDebugOpt (const char* Opt attribute ((unused)), const char* Arg) } /* Read line by line, ignore empty lines and switch optimization - * steps on/off. - */ + ** steps on/off. + */ while (fgets (Buf, sizeof (Buf), F) != 0) { /* Remove trailing control chars. This will also remove the - * trailing newline. - */ + ** trailing newline. + */ unsigned Len = strlen (Buf); while (Len > 0 && IsControl (Buf[Len-1])) { --Len; @@ -488,8 +492,8 @@ static void OptDebugOpt (const char* Opt attribute ((unused)), const char* Arg) } /* Check the first character and enable/disable the step or - * ignore the line - */ + ** ignore the line + */ switch (*Line) { case '\0': @@ -515,8 +519,8 @@ static void OptDebugOpt (const char* Opt attribute ((unused)), const char* Arg) } /* Close the file, no error check here since we were just reading and - * this is only a debug function. - */ + ** this is only a debug function. + */ (void) fclose (F); } @@ -1016,6 +1020,3 @@ int main (int argc, char* argv[]) /* Return an apropriate exit code */ return (ErrorCount > 0)? EXIT_FAILURE : EXIT_SUCCESS; } - - - diff --git a/src/cc65/opcodes.c b/src/cc65/opcodes.c index d8a7fcb1f..a7b91ca9a 100644 --- a/src/cc65/opcodes.c +++ b/src/cc65/opcodes.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2001-2004 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -451,8 +451,8 @@ const OPCDesc OPCTable[OP65_COUNT] = { OF_SETF | OF_NOIMP /* flags */ }, /* Mark RTI as "uses all registers but doesn't change them", so the - * optimizer won't remove preceeding loads. - */ + ** optimizer won't remove preceeding loads. + */ { OP65_RTI, /* opcode */ "rti", /* mnemonic */ 1, /* size */ @@ -599,15 +599,15 @@ static int FindCmp (const void* Key, const void* Desc) const OPCDesc* FindOP65 (const char* M) /* Find the given opcode and return the opcode number. If the opcode was not - * found, return NULL. - */ +** found, return NULL. +*/ { unsigned I; unsigned Len; /* Check the length of the given string, then copy it into local - * storage, converting it to upper case. - */ + ** storage, converting it to upper case. + */ char Mnemo[sizeof (OPCTable[0].Mnemo)]; Len = strlen (M); if (Len >= sizeof (OPCTable[0].Mnemo)) { @@ -658,8 +658,8 @@ unsigned GetInsnSize (opc_t OPC, am_t AM) unsigned char GetAMUseInfo (am_t AM) /* Get usage info for the given addressing mode (addressing modes that use - * index registers return REG_r info for these registers). - */ +** index registers return REG_r info for these registers). +*/ { /* Check the addressing mode. */ switch (AM) { @@ -705,8 +705,8 @@ opc_t GetInverseBranch (opc_t OPC) opc_t MakeShortBranch (opc_t OPC) /* Return the short version of the given branch. If the branch is already - * a short branch, return the opcode unchanged. - */ +** a short branch, return the opcode unchanged. +*/ { switch (OPC) { case OP65_BCC: @@ -737,8 +737,8 @@ opc_t MakeShortBranch (opc_t OPC) opc_t MakeLongBranch (opc_t OPC) /* Return the long version of the given branch. If the branch is already - * a long branch, return the opcode unchanged. - */ +** a long branch, return the opcode unchanged. +*/ { switch (OPC) { case OP65_BCC: @@ -812,7 +812,3 @@ bc_t GetInverseCond (bc_t BC) return 0; } } - - - - diff --git a/src/cc65/opcodes.h b/src/cc65/opcodes.h index 7dc5262c8..349de32a4 100644 --- a/src/cc65/opcodes.h +++ b/src/cc65/opcodes.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2001-2004 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -203,8 +203,8 @@ extern const OPCDesc OPCTable[OP65_COUNT]; const OPCDesc* FindOP65 (const char* OPC); /* Find the given opcode and return the opcode description. If the opcode was - * not found, NULL is returned. - */ +** not found, NULL is returned. +*/ unsigned GetInsnSize (opc_t OPC, am_t AM); /* Return the size of the given instruction */ @@ -233,21 +233,21 @@ INLINE unsigned GetOPCInfo (opc_t OPC) unsigned char GetAMUseInfo (am_t AM); /* Get usage info for the given addressing mode (addressing modes that use - * index registers return REG_r info for these registers). - */ +** index registers return REG_r info for these registers). +*/ opc_t GetInverseBranch (opc_t OPC); /* Return a branch that reverse the condition of the branch given in OPC */ opc_t MakeShortBranch (opc_t OPC); /* Return the short version of the given branch. If the branch is already - * a short branch, return the opcode unchanged. - */ +** a short branch, return the opcode unchanged. +*/ opc_t MakeLongBranch (opc_t OPC); /* Return the long version of the given branch. If the branch is already - * a long branch, return the opcode unchanged. - */ +** a long branch, return the opcode unchanged. +*/ bc_t GetBranchCond (opc_t OPC); /* Get the condition for the conditional branch in OPC */ @@ -258,7 +258,5 @@ bc_t GetInverseCond (bc_t BC); /* End of opcodes.h */ + #endif - - - diff --git a/src/cc65/output.c b/src/cc65/output.c index 92a66108e..e0b06ef99 100644 --- a/src/cc65/output.c +++ b/src/cc65/output.c @@ -81,8 +81,8 @@ void SetOutputName (const char* Name) void MakeDefaultOutputName (const char* InputFilename) /* If the name of the output file is empty or NULL, the name of the output - * file is derived from the input file by adjusting the file name extension. - */ +** file is derived from the input file by adjusting the file name extension. +*/ { if (OutputFilename == 0 || *OutputFilename == '\0') { /* We don't have an output file for now */ @@ -111,8 +111,8 @@ void OpenOutputFile () void OpenDebugOutputFile (const char* Name) /* Open an output file for debugging purposes. Will call Fatal() in case of - * failures. - */ +** failures. +*/ { /* Output file must not be open and we must have a name*/ PRECONDITION (OutputFile == 0); @@ -147,8 +147,8 @@ void CloseOutputFile () int WriteOutput (const char* Format, ...) /* Write to the output file using printf like formatting. Returns the number - * of chars written. - */ +** of chars written. +*/ { va_list ap; int CharCount; @@ -164,6 +164,3 @@ int WriteOutput (const char* Format, ...) /* Return the number of chars written */ return CharCount; } - - - diff --git a/src/cc65/output.h b/src/cc65/output.h index bcabba7a9..a3d2cca8a 100644 --- a/src/cc65/output.h +++ b/src/cc65/output.h @@ -70,28 +70,26 @@ void SetOutputName (const char* Name); void MakeDefaultOutputName (const char* InputFilename); /* If the name of the output file is empty or NULL, the name of the output - * file is derived from the input file by adjusting the file name extension. - */ +** file is derived from the input file by adjusting the file name extension. +*/ void OpenOutputFile (); /* Open the output file. Will call Fatal() in case of failures. */ void OpenDebugOutputFile (const char* Name); -/* Open an output file for debugging purposes. Will call Fatal() in case of - * failures. - */ +/* Open an output file for debugging purposes. Will call Fatal() in case of +** failures. +*/ void CloseOutputFile (); /* Close the output file. Will call Fatal() in case of failures. */ int WriteOutput (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Write to the output file using printf like formatting. Returns the number - * of chars written. - */ +** of chars written. +*/ /* End of output.h */ + #endif - - - diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index 980d46a20..f42274922 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -141,8 +141,8 @@ typedef enum { static void PragmaErrorSkip (void) /* Called in case of an error, skips tokens until the closing paren or a - * semicolon is reached. - */ +** semicolon is reached. +*/ { static const token_t TokenList[] = { TOK_RPAREN, TOK_SEMI }; SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0])); @@ -160,8 +160,8 @@ static int CmpKey (const void* Key, const void* Elem) static pragma_t FindPragma (const StrBuf* Key) /* Find a pragma and return the token. Return PRAGMA_ILLEGAL if the keyword is - * not a valid pragma. - */ +** not a valid pragma. +*/ { struct Pragma* P; P = bsearch (SB_GetConstBuf (Key), Pragmas, PRAGMA_COUNT, sizeof (Pragmas[0]), CmpKey); @@ -172,8 +172,8 @@ static pragma_t FindPragma (const StrBuf* Key) static int GetComma (StrBuf* B) /* Expects and skips a comma in B. Prints an error and returns zero if no - * comma is found. Return a value <> 0 otherwise. - */ +** comma is found. Return a value <> 0 otherwise. +*/ { SB_SkipWhite (B); if (SB_Get (B) != ',') { @@ -188,8 +188,8 @@ static int GetComma (StrBuf* B) static int GetString (StrBuf* B, StrBuf* S) /* Expects and skips a string in B. Prints an error and returns zero if no - * string is found. Returns a value <> 0 otherwise. - */ +** string is found. Returns a value <> 0 otherwise. +*/ { if (!SB_GetString (B, S)) { Error ("String literal expected"); @@ -202,8 +202,8 @@ static int GetString (StrBuf* B, StrBuf* S) static int GetNumber (StrBuf* B, long* Val) /* Expects and skips a number in B. Prints an eror and returns zero if no - * number is found. Returns a value <> 0 otherwise. - */ +** number is found. Returns a value <> 0 otherwise. +*/ { if (!SB_GetNumber (B, Val)) { Error ("Constant integer expected"); @@ -216,9 +216,9 @@ static int GetNumber (StrBuf* B, long* Val) static IntStack* GetWarning (StrBuf* B) /* Get a warning name from the string buffer. Returns a pointer to the intstack - * that holds the state of the warning, and NULL in case of errors. The - * function will output error messages in case of problems. - */ +** that holds the state of the warning, and NULL in case of errors. The +** function will output error messages in case of problems. +*/ { IntStack* S = 0; StrBuf W = AUTO_STRBUF_INITIALIZER; @@ -262,8 +262,8 @@ static int HasStr (StrBuf* B, const char* E) static PushPopResult ParsePushPop (StrBuf* B) /* Check for and parse the "push" and "pop" keywords. In case of "push", a - * following comma is expected and skipped. - */ +** following comma is expected and skipped. +*/ { StrBuf Ident = AUTO_STRBUF_INITIALIZER; PushPopResult Res = PP_NONE; @@ -330,8 +330,8 @@ static void PushInt (IntStack* S, long Val) static int BoolKeyword (StrBuf* Ident) /* Check if the identifier in Ident is a keyword for a boolean value. Currently - * accepted are true/false/on/off. - */ +** accepted are true/false/on/off. +*/ { if (SB_CompareStr (Ident, "true") == 0) { return 1; @@ -676,8 +676,8 @@ static void ParsePragma (void) /* Do we know this pragma? */ if (Pragma == PRAGMA_ILLEGAL) { /* According to the ANSI standard, we're not allowed to generate errors - * for unknown pragmas, but warn about them if enabled (the default). - */ + ** for unknown pragmas, but warn about them if enabled (the default). + */ if (IS_Get (&WarnUnknownPragma)) { Warning ("Unknown pragma `%s'", SB_GetConstBuf (&Ident)); } @@ -838,8 +838,8 @@ void DoPragma (void) Error ("String literal expected"); /* Try some smart error recovery: Skip tokens until we reach the - * enclosing paren, or a semicolon. - */ + ** enclosing paren, or a semicolon. + */ PragmaErrorSkip (); } else { @@ -851,6 +851,3 @@ void DoPragma (void) /* Closing paren needed */ ConsumeRParen (); } - - - diff --git a/src/cc65/pragma.h b/src/cc65/pragma.h index d75273fa6..f12dbaa83 100644 --- a/src/cc65/pragma.h +++ b/src/cc65/pragma.h @@ -50,9 +50,5 @@ void DoPragma (void); /* End of pragma.h */ + #endif - - - - - diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 199388deb..a5ab4897e 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -100,8 +100,8 @@ struct MacroExp { static unsigned Pass1 (StrBuf* Source, StrBuf* Target); /* Preprocessor pass 1. Remove whitespace. Handle old and new style comments - * and the "defined" operator. - */ +** and the "defined" operator. +*/ static void MacroReplacement (StrBuf* Source, StrBuf* Target); /* Perform macro replacement. */ @@ -169,8 +169,8 @@ static int CmpToken (const void* Key, const void* Elem) static pptoken_t FindPPToken (const char* Ident) /* Find a preprocessor token and return it. Return PP_ILLEGAL if the identifier - * is not a valid preprocessor token. - */ +** is not a valid preprocessor token. +*/ { struct PPToken* P; P = bsearch (Ident, PPTokens, PPTOKEN_COUNT, sizeof (PPTokens[0]), CmpToken); @@ -213,8 +213,8 @@ static void DoneMacroExp (MacroExp* E) static void ME_AppendActual (MacroExp* E, StrBuf* Arg) /* Add a copy of Arg to the list of actual macro arguments. - * NOTE: This function will clear Arg! - */ +** NOTE: This function will clear Arg! +*/ { /* Create a new string buffer */ StrBuf* A = NewStrBuf (); @@ -253,8 +253,8 @@ static int ME_ArgIsVariadic (const MacroExp* E) static void Stringize (StrBuf* Source, StrBuf* Target) /* Stringize the given string: Add double quotes at start and end and preceed - * each occurance of " and \ by a backslash. - */ +** each occurance of " and \ by a backslash. +*/ { char C; @@ -262,8 +262,8 @@ static void Stringize (StrBuf* Source, StrBuf* Target) SB_AppendChar (Target, '\"'); /* Replace any characters inside the string may not be part of a string - * unescaped. - */ + ** unescaped. + */ while ((C = SB_Get (Source)) != '\0') { switch (C) { case '\"': @@ -286,8 +286,8 @@ static void OldStyleComment (void) /* Remove an old style C comment from line. */ { /* Remember the current line number, so we can output better error - * messages if the comment is not terminated in the current file. - */ + ** messages if the comment is not terminated in the current file. + */ unsigned StartingLine = GetCurrentLine(); /* Skip the start of comment chars */ @@ -321,10 +321,10 @@ static void NewStyleComment (void) /* Remove a new style C comment from line. */ { /* Beware: Because line continuation chars are handled when reading - * lines, we may only skip til the end of the source line, which - * may not be the same as the end of the input line. The end of the - * source line is denoted by a lf (\n) character. - */ + ** lines, we may only skip til the end of the source line, which + ** may not be the same as the end of the input line. The end of the + ** source line is denoted by a lf (\n) character. + */ do { NextChar (); } while (CurC != '\n' && CurC != '\0'); @@ -337,9 +337,9 @@ static void NewStyleComment (void) static int SkipWhitespace (int SkipLines) /* Skip white space in the input stream. Do also skip newlines if SkipLines - * is true. Return zero if nothing was skipped, otherwise return a - * value != zero. - */ +** is true. Return zero if nothing was skipped, otherwise return a +** value != zero. +*/ { int Skipped = 0; while (1) { @@ -401,8 +401,8 @@ static void CopyQuotedString (StrBuf* Target) static int MacName (char* Ident) /* Get a macro symbol name into Ident. If we have an error, print a - * diagnostic message and clear the line. - */ +** diagnostic message and clear the line. +*/ { if (IsSym (Ident) == 0) { PPError ("Identifier expected"); @@ -447,8 +447,8 @@ static void ReadMacroArgs (MacroExp* E) NextChar (); } else if (CurC == ',' && ME_ArgIsVariadic (E)) { /* It's a comma, but we're inside a variadic macro argument, so - * just copy it and proceed. - */ + ** just copy it and proceed. + */ SB_AppendChar (&Arg, CurC); NextChar (); } else { @@ -458,8 +458,8 @@ static void ReadMacroArgs (MacroExp* E) } /* If this is not the single empty argument for a macro with - * an empty argument list, remember it. - */ + ** an empty argument list, remember it. + */ if (CurC != ')' || SB_NotEmpty (&Arg) || E->M->ArgCount > 0) { ME_AppendActual (E, &Arg); } @@ -539,8 +539,8 @@ static void MacroArgSubst (MacroExp* E) HaveSpace = SkipWhitespace (0); /* If a ## operator follows, we have to insert the actual - * argument as is, otherwise it must be macro replaced. - */ + ** argument as is, otherwise it must be macro replaced. + */ if (CurC == '#' && NextC == '#') { /* ### Add placemarker if necessary */ @@ -549,8 +549,8 @@ static void MacroArgSubst (MacroExp* E) } else { /* Replace the formal argument by a macro replaced copy - * of the actual. - */ + ** of the actual. + */ SB_Reset (Arg); MacroReplacement (Arg, &E->Replacement); @@ -576,16 +576,16 @@ static void MacroArgSubst (MacroExp* E) SkipWhitespace (0); /* Since we need to concatenate the token sequences, remove - * any whitespace that was added to target, since it must come - * from the input. - */ + ** any whitespace that was added to target, since it must come + ** from the input. + */ while (IsSpace (SB_LookAtLast (&E->Replacement))) { SB_Drop (&E->Replacement, 1); } /* If the next token is an identifier which is a macro argument, - * replace it, otherwise do nothing. - */ + ** replace it, otherwise do nothing. + */ if (IsSym (Ident)) { /* Check if it's a macro argument */ @@ -605,9 +605,9 @@ static void MacroArgSubst (MacroExp* E) } else if (CurC == '#' && E->M->ArgCount >= 0) { /* A # operator within a macro expansion of a function like - * macro. Read the following identifier and check if it's a - * macro parameter. - */ + ** macro. Read the following identifier and check if it's a + ** macro parameter. + */ NextChar (); SkipWhitespace (0); if (!IsSym (Ident) || (ArgIdx = FindMacroArg (E->M, Ident)) < 0) { @@ -673,8 +673,8 @@ static void MacroCall (StrBuf* Target, Macro* M) MacroArgSubst (&E); /* Do macro replacement on the macro that already has the parameters - * substituted. - */ + ** substituted. + */ M->Expanding = 1; MacroReplacement (&E.Replacement, Target); M->Expanding = 0; @@ -717,8 +717,8 @@ static void ExpandMacro (StrBuf* Target, Macro* M) MacroArgSubst (&E); /* Do macro replacement on the macro that already has the parameters - * substituted. - */ + ** substituted. + */ M->Expanding = 1; MacroReplacement (&E.Replacement, Target); M->Expanding = 0; @@ -776,8 +776,8 @@ static void DefineMacro (void) } /* The next token must be either an identifier, or - if not in - * C89 mode - the ellipsis. - */ + ** C89 mode - the ellipsis. + */ if (!C89 && CurC == '.') { /* Ellipsis */ NextChar (); @@ -790,8 +790,8 @@ static void DefineMacro (void) NextChar (); /* Remember that the macro is variadic and use __VA_ARGS__ as - * the argument name. - */ + ** the argument name. + */ AddMacroArg (M, "__VA_ARGS__"); M->Variadic = 1; @@ -812,8 +812,8 @@ static void DefineMacro (void) } /* If we had an ellipsis, or the next char is not a comma, we've - * reached the end of the macro argument list. - */ + ** reached the end of the macro argument list. + */ SkipWhitespace (0); if (M->Variadic || CurC != ',') { break; @@ -837,8 +837,8 @@ static void DefineMacro (void) InsertMacro (M); /* Remove whitespace and comments from the line, store the preprocessed - * line into the macro replacement buffer. - */ + ** line into the macro replacement buffer. + */ Pass1 (Line, &M->Replacement); /* Remove whitespace from the end of the line */ @@ -850,8 +850,8 @@ static void DefineMacro (void) #endif /* If we have an existing macro, check if the redefinition is identical. - * Print a diagnostic if not. - */ + ** Print a diagnostic if not. + */ if (Existing && MacroCmp (M, Existing) != 0) { PPError ("Macro redefinition is not identical"); } @@ -867,8 +867,8 @@ static void DefineMacro (void) static unsigned Pass1 (StrBuf* Source, StrBuf* Target) /* Preprocessor pass 1. Remove whitespace. Handle old and new style comments - * and the "defined" operator. - */ +** and the "defined" operator. +*/ { unsigned IdentCount; ident Ident; @@ -984,8 +984,8 @@ static void PreprocessLine (void) /* Translate one line. */ { /* Trim whitespace and remove comments. The function returns the number of - * identifiers found. If there were any, we will have to check for macros. - */ + ** identifiers found. If there were any, we will have to check for macros. + */ SB_Clear (MLine); if (Pass1 (Line, MLine) > 0) { MLine = InitLine (MLine); @@ -1045,10 +1045,10 @@ static int DoIf (int Skip) ExprDesc Expr; /* We're about to abuse the compiler expression parser to evaluate the - * #if expression. Save the current tokens to come back here later. - * NOTE: Yes, this is a hack, but it saves a complete separate expression - * evaluation for the preprocessor. - */ + ** #if expression. Save the current tokens to come back here later. + ** NOTE: Yes, this is a hack, but it saves a complete separate expression + ** evaluation for the preprocessor. + */ Token SavedCurTok = CurTok; Token SavedNextTok = NextTok; @@ -1067,9 +1067,9 @@ static int DoIf (int Skip) PreprocessLine (); /* Add two semicolons as sentinels to the line, so the following - * expression evaluation will eat these two tokens but nothing from - * the following line. - */ + ** expression evaluation will eat these two tokens but nothing from + ** the following line. + */ SB_AppendStr (Line, ";;"); SB_Terminate (Line); @@ -1123,8 +1123,8 @@ static void DoInclude (void) SkipWhitespace (0); /* Get the next char and check for a valid file name terminator. Setup - * the include directory spec (SYS/USR) by looking at the terminator. - */ + ** the include directory spec (SYS/USR) by looking at the terminator. + */ switch (CurC) { case '\"': @@ -1164,8 +1164,8 @@ Done: SB_Done (&Filename); /* Clear the remaining line so the next input will come from the new - * file (if open) - */ + ** file (if open) + */ ClearLine (); } @@ -1173,8 +1173,8 @@ Done: static void DoPragma (void) /* Handle a #pragma line by converting the #pragma preprocessor directive into - * the _Pragma() compiler operator. - */ +** the _Pragma() compiler operator. +*/ { /* Skip blanks following the #pragma directive */ SkipWhitespace (0); @@ -1302,8 +1302,8 @@ void Preprocess (void) case PP_ENDIF: if (IfIndex >= 0) { /* Remove any clauses on top of stack that do not - * need a terminating #endif. - */ + ** need a terminating #endif. + */ while (IfIndex >= 0 && (IfStack[IfIndex] & IFCOND_NEEDTERM) == 0) { --IfIndex; } @@ -1402,4 +1402,3 @@ Done: (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } } - diff --git a/src/cc65/preproc.h b/src/cc65/preproc.h index 3b2722567..8d7b3c374 100644 --- a/src/cc65/preproc.h +++ b/src/cc65/preproc.h @@ -61,7 +61,5 @@ void Preprocess (void); /* End of preproc.h */ + #endif - - - diff --git a/src/cc65/reginfo.c b/src/cc65/reginfo.c index 65c073420..383c6ec24 100644 --- a/src/cc65/reginfo.c +++ b/src/cc65/reginfo.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2001-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -104,9 +104,9 @@ void RC_Dump (FILE* F, const RegContents* RC) RegInfo* NewRegInfo (const RegContents* RC) /* Allocate a new register info, initialize and return it. If RC is not - * a NULL pointer, it is used to initialize both, the input and output - * registers. If the pointer is NULL, all registers are set to unknown. - */ +** a NULL pointer, it is used to initialize both, the input and output +** registers. If the pointer is NULL, all registers are set to unknown. +*/ { /* Allocate memory */ RegInfo* RI = xmalloc (sizeof (RegInfo)); @@ -145,6 +145,3 @@ void DumpRegInfo (const char* Desc, const RegInfo* RI) fprintf (stdout, "Out: "); RC_Dump (stdout, &RI->Out); } - - - diff --git a/src/cc65/reginfo.h b/src/cc65/reginfo.h index 31281675c..7354c301f 100644 --- a/src/cc65/reginfo.h +++ b/src/cc65/reginfo.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2001-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -114,9 +114,9 @@ INLINE int RegValIsUnknown (short Val) RegInfo* NewRegInfo (const RegContents* RC); /* Allocate a new register info, initialize and return it. If RC is not - * a NULL pointer, it is used to initialize both, the input and output - * registers. If the pointer is NULL, all registers are set to unknown. - */ +** a NULL pointer, it is used to initialize both, the input and output +** registers. If the pointer is NULL, all registers are set to unknown. +*/ void FreeRegInfo (RegInfo* RI); /* Free a RegInfo struct */ @@ -127,8 +127,5 @@ void DumpRegInfo (const char* Desc, const RegInfo* RI); /* End of reginfo.h */ + #endif - - - - diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index 9d6553ae0..16d43e2ea 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -166,8 +166,8 @@ static int CmpKey (const void* Key, const void* Elem) static token_t FindKey (const char* Key) /* Find a keyword and return the token. Return IDENT if the token is not a - * keyword. - */ +** keyword. +*/ { struct Keyword* K; K = bsearch (Key, Keywords, KEY_COUNT, sizeof (Keywords [0]), CmpKey); @@ -182,8 +182,8 @@ static token_t FindKey (const char* Key) static int SkipWhite (void) /* Skip white space in the input stream, reading and preprocessing new lines - * if necessary. Return 0 if end of file is reached, return 1 otherwise. - */ +** if necessary. Return 0 if end of file is reached, return 1 otherwise. +*/ { while (1) { while (CurC == '\0') { @@ -214,9 +214,9 @@ int TokIsFuncSpec (const Token* T) void SymName (char* S) /* Read a symbol from the input stream. The first character must have been - * checked before calling this function. The buffer is expected to be at - * least of size MAX_IDENTLEN+1. - */ +** checked before calling this function. The buffer is expected to be at +** least of size MAX_IDENTLEN+1. +*/ { unsigned Len = 0; do { @@ -354,8 +354,8 @@ static int ParseChar (void) Error ("Illegal character constant"); C = ' '; /* Try to do error recovery, otherwise the compiler will spit - * out thousands of errors in this place and abort. - */ + ** out thousands of errors in this place and abort. + */ if (CurC != '\'' && CurC != '\0') { while (NextC != '\'' && NextC != '\"' && NextC != '\0') { NextChar (); @@ -417,9 +417,9 @@ static void StringConst (void) NextTok.Tok = TOK_SCONST; /* Concatenate strings. If at least one of the concenated strings is a wide - * character literal, the whole string is a wide char literal, otherwise - * it's a normal string literal. - */ + ** character literal, the whole string is a wide char literal, otherwise + ** it's a normal string literal. + */ while (1) { /* Check if this is a normal or a wide char string */ @@ -477,8 +477,8 @@ static void NumericConst (void) unsigned long IVal; /* Value */ /* Check for a leading hex or octal prefix and determine the possible - * integer types. - */ + ** integer types. + */ if (CurC == '0') { /* Gobble 0 and examine next char */ NextChar (); @@ -494,10 +494,10 @@ static void NumericConst (void) } /* Because floating point numbers don't have octal prefixes (a number - * with a leading zero is decimal), we first have to read the number - * before converting it, so we can determine if it's a float or an - * integer. - */ + ** with a leading zero is decimal), we first have to read the number + ** before converting it, so we can determine if it's a float or an + ** integer. + */ while (IsXDigit (CurC) && HexVal (CurC) < Base) { SB_AppendChar (&S, CurC); NextChar (); @@ -505,23 +505,23 @@ static void NumericConst (void) SB_Terminate (&S); /* The following character tells us if we have an integer or floating - * point constant. Note: Hexadecimal floating point constants aren't - * supported in C89. - */ + ** point constant. Note: Hexadecimal floating point constants aren't + ** supported in C89. + */ IsFloat = (CurC == '.' || (Base == 10 && toupper (CurC) == 'E') || (Base == 16 && toupper (CurC) == 'P' && IS_Get (&Standard) >= STD_C99)); /* If we don't have a floating point type, an octal prefix results in an - * octal base. - */ + ** octal base. + */ if (!IsFloat && Prefix == 8) { Base = 8; } /* Since we do now know the correct base, convert the remembered input - * into a number. - */ + ** into a number. + */ SB_Reset (&S); IVal = 0; while ((C = SB_Get (&S)) != '\0') { @@ -577,9 +577,9 @@ static void NumericConst (void) /* Out of range for int */ Types &= ~IT_INT; /* If the value is in the range 0x8000..0xFFFF, unsigned int is not - * allowed, and we don't have a type specifying suffix, emit a - * warning, because the constant is of type long. - */ + ** allowed, and we don't have a type specifying suffix, emit a + ** warning, because the constant is of type long. + */ if (IVal <= 0xFFFF && (Types & IT_UINT) == 0 && !HaveSuffix) { Warning ("Constant is long"); } @@ -653,11 +653,11 @@ static void NumericConst (void) } /* Read exponent digits. Since we support only 32 bit floats - * with a maximum exponent of +-/127, we read the exponent - * part as integer with up to 3 digits and drop the remainder. - * This avoids an overflow of Exp. The exponent is always - * decimal, even for hex float consts. - */ + ** with a maximum exponent of +-/127, we read the exponent + ** part as integer with up to 3 digits and drop the remainder. + ** This avoids an overflow of Exp. The exponent is always + ** decimal, even for hex float consts. + */ Digits = 0; Exp = 0; while (IsDigit (CurC)) { @@ -668,8 +668,8 @@ static void NumericConst (void) } /* Check for errors: We must have exponent digits, and not more - * than three. - */ + ** than three. + */ if (Digits == 0) { Error ("Floating constant exponent has no digits"); } else if (Digits > 3) { @@ -705,10 +705,10 @@ void NextToken (void) ident token; /* We have to skip white space here before shifting tokens, since the - * tokens and the current line info is invalid at startup and will get - * initialized by reading the first time from the file. Remember if - * we were at end of input and handle that later. - */ + ** tokens and the current line info is invalid at startup and will get + ** initialized by reading the first time from the file. Remember if + ** we were at end of input and handle that later. + */ int GotEOF = (SkipWhite() == 0); /* Current token is the lookahead token */ @@ -718,9 +718,9 @@ void NextToken (void) CurTok = NextTok; /* When reading the first time from the file, the line info in NextTok, - * which was copied to CurTok is invalid. Since the information from - * the token is used for error messages, we must make it valid. - */ + ** which was copied to CurTok is invalid. Since the information from + ** the token is used for error messages, we must make it valid. + */ if (CurTok.LI == 0) { CurTok.LI = UseLineInfo (GetCurLineInfo ()); } @@ -1015,8 +1015,8 @@ void NextToken (void) void SkipTokens (const token_t* TokenList, unsigned TokenCount) /* Skip tokens until we reach TOK_CEOF or a token in the given token list. - * This routine is used for error recovery. - */ +** This routine is used for error recovery. +*/ { while (CurTok.Tok != TOK_CEOF) { @@ -1039,8 +1039,8 @@ void SkipTokens (const token_t* TokenList, unsigned TokenCount) int Consume (token_t Token, const char* ErrorMsg) /* Eat token if it is the next in the input stream, otherwise print an error - * message. Returns true if the token was found and false otherwise. - */ +** message. Returns true if the token was found and false otherwise. +*/ { if (CurTok.Tok == Token) { NextToken (); @@ -1142,6 +1142,3 @@ int ConsumeRCurly (void) { return Consume (TOK_RCURLY, "`}' expected"); } - - - diff --git a/src/cc65/scanner.h b/src/cc65/scanner.h index 77f2028b9..1242d78fd 100644 --- a/src/cc65/scanner.h +++ b/src/cc65/scanner.h @@ -254,9 +254,9 @@ int TokIsFuncSpec (const Token* T); void SymName (char* S); /* Read a symbol from the input stream. The first character must have been - * checked before calling this function. The buffer is expected to be at - * least of size MAX_IDENTLEN+1. - */ +** checked before calling this function. The buffer is expected to be at +** least of size MAX_IDENTLEN+1. +*/ int IsSym (char* S); /* If a symbol follows, read it and return 1, otherwise return 0 */ @@ -266,13 +266,13 @@ void NextToken (void); void SkipTokens (const token_t* TokenList, unsigned TokenCount); /* Skip tokens until we reach TOK_CEOF or a token in the given token list. - * This routine is used for error recovery. - */ +** This routine is used for error recovery. +*/ int Consume (token_t Token, const char* ErrorMsg); /* Eat token if it is the next in the input stream, otherwise print an error - * message. Returns true if the token was found and false otherwise. - */ +** message. Returns true if the token was found and false otherwise. +*/ int ConsumeColon (void); /* Check for a colon and skip it. */ @@ -304,10 +304,5 @@ int ConsumeRCurly (void); /* End of scanner.h */ + #endif - - - - - - diff --git a/src/cc65/scanstrbuf.c b/src/cc65/scanstrbuf.c index abddf06db..91abc8cb3 100644 --- a/src/cc65/scanstrbuf.c +++ b/src/cc65/scanstrbuf.c @@ -164,12 +164,12 @@ void SB_SkipWhite (StrBuf* B) int SB_GetSym (StrBuf* B, StrBuf* Ident, const char* SpecialChars) /* Get a symbol from the string buffer. If SpecialChars is not NULL, it - * points to a string that contains characters allowed within the string in - * addition to letters, digits and the underline. Note: The identifier must - * still begin with a letter. - * Returns 1 if a symbol was found and 0 otherwise but doesn't output any - * errors. - */ +** points to a string that contains characters allowed within the string in +** addition to letters, digits and the underline. Note: The identifier must +** still begin with a letter. +** Returns 1 if a symbol was found and 0 otherwise but doesn't output any +** errors. +*/ { /* Handle a NULL argument for SpecialChars transparently */ if (SpecialChars == 0) { @@ -198,9 +198,9 @@ int SB_GetSym (StrBuf* B, StrBuf* Ident, const char* SpecialChars) int SB_GetString (StrBuf* B, StrBuf* S) /* Get a string from the string buffer. Returns 1 if a string was found and 0 - * otherwise. Errors are only output in case of invalid strings (missing end - * of string). - */ +** otherwise. Errors are only output in case of invalid strings (missing end +** of string). +*/ { char C; @@ -250,10 +250,10 @@ int SB_GetString (StrBuf* B, StrBuf* S) int SB_GetNumber (StrBuf* B, long* Val) /* Get a number from the string buffer. Accepted formats are decimal, octal, - * hex and character constants. Numeric constants may be preceeded by a - * minus or plus sign. The function returns 1 if a number was found and - * zero otherwise. Errors are only output for invalid numbers. - */ +** hex and character constants. Numeric constants may be preceeded by a +** minus or plus sign. The function returns 1 if a number was found and +** zero otherwise. Errors are only output for invalid numbers. +*/ { int Sign; char C; @@ -281,8 +281,8 @@ int SB_GetNumber (StrBuf* B, long* Val) } /* Check for a sign. A sign must be followed by a digit, otherwise it's - * not a number - */ + ** not a number + */ Sign = 1; switch (SB_Peek (B)) { case '-': @@ -346,6 +346,3 @@ int SB_GetNumber (StrBuf* B, long* Val) *Val *= Sign; return 1; } - - - diff --git a/src/cc65/scanstrbuf.h b/src/cc65/scanstrbuf.h index a84bbd276..4fba5980e 100644 --- a/src/cc65/scanstrbuf.h +++ b/src/cc65/scanstrbuf.h @@ -54,32 +54,28 @@ void SB_SkipWhite (StrBuf* B); int SB_GetSym (StrBuf* B, StrBuf* Ident, const char* SpecialChars); /* Get a symbol from the string buffer. If SpecialChars is not NULL, it - * points to a string that contains characters allowed within the string in - * addition to letters, digits and the underline. Note: The identifier must - * still begin with a letter. - * Returns 1 if a symbol was found and 0 otherwise but doesn't output any - * errors. - */ +** points to a string that contains characters allowed within the string in +** addition to letters, digits and the underline. Note: The identifier must +** still begin with a letter. +** Returns 1 if a symbol was found and 0 otherwise but doesn't output any +** errors. +*/ int SB_GetString (StrBuf* B, StrBuf* S); /* Get a string from the string buffer. Returns 1 if a string was found and 0 - * otherwise. Errors are only output in case of invalid strings (missing end - * of string). - */ +** otherwise. Errors are only output in case of invalid strings (missing end +** of string). +*/ int SB_GetNumber (StrBuf* B, long* Val); /* Get a number from the string buffer. Accepted formats are decimal, octal, - * hex and character constants. Numeric constants may be preceeded by a - * minus or plus sign. The function returns 1 if a number was found and - * zero otherwise. Errors are only output for invalid numbers. - */ +** hex and character constants. Numeric constants may be preceeded by a +** minus or plus sign. The function returns 1 if a number was found and +** zero otherwise. Errors are only output for invalid numbers. +*/ /* End of scanstrbuf.h */ + #endif - - - - - diff --git a/src/cc65/segments.c b/src/cc65/segments.c index cdbd05e39..5e493e8f5 100644 --- a/src/cc65/segments.c +++ b/src/cc65/segments.c @@ -71,10 +71,10 @@ Segments* GS = 0; static StrStack SegmentNames[SEG_COUNT]; /* We're using a collection for the stack instead of a linked list. Since - * functions may not be nested (at least in the current implementation), the - * maximum stack depth is 2, so there is not really a need for a better - * implementation. - */ +** functions may not be nested (at least in the current implementation), the +** maximum stack depth is 2, so there is not really a need for a better +** implementation. +*/ static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER; @@ -300,6 +300,3 @@ void OutputSegments (const Segments* S) /* Output the code segment epiloque */ CS_OutputEpilogue (S->Code); } - - - diff --git a/src/cc65/segments.h b/src/cc65/segments.h index cf6c72fba..f55be688b 100644 --- a/src/cc65/segments.h +++ b/src/cc65/segments.h @@ -156,7 +156,5 @@ void OutputSegments (const Segments* S); /* End of segments.h */ + #endif - - - diff --git a/src/cc65/shiftexpr.c b/src/cc65/shiftexpr.c index 44a42f304..c61514f43 100644 --- a/src/cc65/shiftexpr.c +++ b/src/cc65/shiftexpr.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2004-2006 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -136,9 +136,9 @@ void ShiftExpr (struct ExprDesc* Expr) RemoveCode (&Mark2); /* If the shift count is greater or equal than the bit count of - * the operand, the behaviour is undefined according to the - * standard. - */ + ** the operand, the behaviour is undefined according to the + ** standard. + */ if (Expr2.IVal < 0 || Expr2.IVal >= (long) ExprBits) { Warning ("Shift count too large for operand type"); @@ -174,11 +174,11 @@ void ShiftExpr (struct ExprDesc* Expr) } /* If we're shifting an integer or unsigned to the right, the - * lhs has a const address, and the shift count is larger than 8, - * we can load just the high byte as a char with the correct - * signedness, and reduce the shift count by 8. If the remaining - * shift count is zero, we're done. - */ + ** lhs has a const address, and the shift count is larger than 8, + ** we can load just the high byte as a char with the correct + ** signedness, and reduce the shift count by 8. If the remaining + ** shift count is zero, we're done. + */ if (Tok == TOK_SHR && IsTypeInt (Expr->Type) && ED_IsLVal (Expr) && @@ -192,8 +192,8 @@ void ShiftExpr (struct ExprDesc* Expr) Expr2.IVal -= 8; /* Replace the type of the expression temporarily by the - * corresponding char type. - */ + ** corresponding char type. + */ OldType = Expr->Type; if (IsSignUnsigned (Expr->Type)) { Expr->Type = type_uchar; @@ -235,6 +235,3 @@ Next: Expr->Type = ResultType; } } - - - diff --git a/src/cc65/shiftexpr.h b/src/cc65/shiftexpr.h index b4c50d44b..2a000fd58 100644 --- a/src/cc65/shiftexpr.h +++ b/src/cc65/shiftexpr.h @@ -34,7 +34,7 @@ #ifndef SHIFTEXPR_H -#define SHIFTEXPT_H +#define SHIFTEXPR_H @@ -68,7 +68,3 @@ void ShiftExpr (struct ExprDesc* Expr); /* End of shiftexpr.h */ #endif - - - - diff --git a/src/cc65/stackptr.c b/src/cc65/stackptr.c index 26669fa57..1f10e8500 100644 --- a/src/cc65/stackptr.c +++ b/src/cc65/stackptr.c @@ -68,7 +68,3 @@ void SP_Pop (const Type* T) { StackPtr += SizeOf (T); } - - - - diff --git a/src/cc65/stackptr.h b/src/cc65/stackptr.h index 4232c0a46..4f90f8dcc 100644 --- a/src/cc65/stackptr.h +++ b/src/cc65/stackptr.h @@ -71,6 +71,3 @@ void SP_Pop (const Type* T); /* End of stackptr.h */ #endif - - - diff --git a/src/cc65/standard.c b/src/cc65/standard.c index e6a842d2c..36897a059 100644 --- a/src/cc65/standard.c +++ b/src/cc65/standard.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -64,8 +64,8 @@ static const char* StdNames[STD_COUNT] = { standard_t FindStandard (const char* Name) /* Find a standard by name. Returns one of the constants defined above. - * STD_UNKNOWN is returned if Name doesn't match a standard. - */ +** STD_UNKNOWN is returned if Name doesn't match a standard. +*/ { unsigned I; @@ -79,6 +79,3 @@ standard_t FindStandard (const char* Name) /* Not found */ return STD_UNKNOWN; } - - - diff --git a/src/cc65/standard.h b/src/cc65/standard.h index bebc154ee..b0bc8481f 100644 --- a/src/cc65/standard.h +++ b/src/cc65/standard.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -74,15 +74,11 @@ extern IntStack Standard; /* Language standard */ standard_t FindStandard (const char* Name); /* Find a standard by name. Returns one of the constants defined above. - * STD_UNKNOWN is returned if Name doesn't match a standard. - */ +** STD_UNKNOWN is returned if Name doesn't match a standard. +*/ /* End of standard.h */ #endif - - - - diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c index 1c3c89483..182cad1ef 100644 --- a/src/cc65/stdfunc.c +++ b/src/cc65/stdfunc.c @@ -78,8 +78,8 @@ static void StdFunc_strlen (FuncDesc*, ExprDesc*); /* Table with all known functions and their handlers. Must be sorted - * alphabetically! - */ +** alphabetically! +*/ static struct StdFuncDesc { const char* Name; void (*Handler) (FuncDesc*, ExprDesc*); @@ -122,8 +122,8 @@ static int CmpFunc (const void* Key, const void* Elem) static long ArrayElementCount (const ArgDesc* Arg) /* Check if the type of the given argument is an array. If so, and if the - * element count is known, return it. In all other cases, return UNSPECIFIED. - */ +** element count is known, return it. In all other cases, return UNSPECIFIED. +*/ { long Count; @@ -143,8 +143,8 @@ static long ArrayElementCount (const ArgDesc* Arg) static void ParseArg (ArgDesc* Arg, Type* Type) /* Parse one argument but do not push it onto the stack. Make all fields in - * Arg valid. - */ +** Arg valid. +*/ { /* We have a prototype, so chars may be pushed as chars */ Arg->Flags = CF_FORCECHAR; @@ -165,8 +165,8 @@ static void ParseArg (ArgDesc* Arg, Type* Type) GetCodePos (&Arg->Load); /* If the value is a constant, set the flag, otherwise load it into the - * primary register. - */ + ** primary register. + */ if (ED_IsConstAbsInt (&Arg->Expr) && ED_CodeRangeIsEmpty (&Arg->Expr)) { /* Remember that we have a constant value */ Arg->Flags |= CF_CONST; @@ -219,10 +219,10 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ConsumeComma (); /* Argument #3. Since memcpy is a fastcall function, we must load the - * arg into the primary if it is not already there. This parameter is - * also ignored for the calculation of the parameter size, since it is - * not passed via the stack. - */ + ** arg into the primary if it is not already there. This parameter is + ** also ignored for the calculation of the parameter size, since it is + ** not passed via the stack. + */ ParseArg (&Arg3, Arg3Type); if (Arg3.Flags & CF_CONST) { LoadExpr (CF_NONE, &Arg3.Expr); @@ -237,8 +237,8 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) Warning ("Call to memcpy has no effect"); /* Remove all of the generated code but the load of the first - * argument, which is what memcpy returns. - */ + ** argument, which is what memcpy returns. + */ RemoveCode (&Arg1.Push); /* Set the function result to the first argument */ @@ -249,10 +249,10 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } /* We've generated the complete code for the function now and know the - * types of all parameters. Check for situations where better code can - * be generated. If such a situation is detected, throw away the - * generated, and emit better code. - */ + ** types of all parameters. Check for situations where better code can + ** be generated. If such a situation is detected, throw away the + ** generated, and emit better code. + */ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && @@ -309,8 +309,8 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } /* memcpy returns the address, so the result is actually identical - * to the first argument. - */ + ** to the first argument. + */ *Expr = Arg1.Expr; } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && @@ -319,12 +319,12 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) { /* It is possible to just use one index register even if the stack - * offset is not zero, by adjusting the offset to the constant - * address accordingly. But we cannot do this if the data in - * question is in the register space or at an absolute address less - * than 256. Register space is zero page, which means that the - * address calculation could overflow in the linker. - */ + ** offset is not zero, by adjusting the offset to the constant + ** address accordingly. But we cannot do this if the data in + ** question is in the register space or at an absolute address less + ** than 256. Register space is zero page, which means that the + ** address calculation could overflow in the linker. + */ int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) && !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256); @@ -383,8 +383,8 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } /* memcpy returns the address, so the result is actually identical - * to the first argument. - */ + ** to the first argument. + */ *Expr = Arg1.Expr; } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && @@ -393,12 +393,12 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) { /* It is possible to just use one index register even if the stack - * offset is not zero, by adjusting the offset to the constant - * address accordingly. But we cannot do this if the data in - * question is in the register space or at an absolute address less - * than 256. Register space is zero page, which means that the - * address calculation could overflow in the linker. - */ + ** offset is not zero, by adjusting the offset to the constant + ** address accordingly. But we cannot do this if the data in + ** question is in the register space or at an absolute address less + ** than 256. Register space is zero page, which means that the + ** address calculation could overflow in the linker. + */ int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) && !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256); @@ -457,8 +457,8 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } /* memcpy returns the address, so the result is actually identical - * to the first argument. - */ + ** to the first argument. + */ *Expr = Arg1.Expr; } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && @@ -540,8 +540,8 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ConsumeComma (); /* Argument #2. This argument is special in that we will call another - * function if it is a constant zero. - */ + ** function if it is a constant zero. + */ ParseArg (&Arg2, Arg2Type); if ((Arg2.Flags & CF_CONST) != 0 && Arg2.Expr.IVal == 0) { /* Don't call memset, call bzero instead */ @@ -555,10 +555,10 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ConsumeComma (); /* Argument #3. Since memset is a fastcall function, we must load the - * arg into the primary if it is not already there. This parameter is - * also ignored for the calculation of the parameter size, since it is - * not passed via the stack. - */ + ** arg into the primary if it is not already there. This parameter is + ** also ignored for the calculation of the parameter size, since it is + ** not passed via the stack. + */ ParseArg (&Arg3, Arg3Type); if (Arg3.Flags & CF_CONST) { LoadExpr (CF_NONE, &Arg3.Expr); @@ -573,8 +573,8 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) Warning ("Call to memset has no effect"); /* Remove all of the generated code but the load of the first - * argument, which is what memset returns. - */ + ** argument, which is what memset returns. + */ RemoveCode (&Arg1.Push); /* Set the function result to the first argument */ @@ -585,14 +585,14 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } /* We've generated the complete code for the function now and know the - * types of all parameters. Check for situations where better code can - * be generated. If such a situation is detected, throw away the - * generated, and emit better code. - * Note: Lots of improvements would be possible here, but I will - * concentrate on the most common case: memset with arguments 2 and 3 - * being constant numerical values. Some checks have shown that this - * covers nearly 90% of all memset calls. - */ + ** types of all parameters. Check for situations where better code can + ** be generated. If such a situation is detected, throw away the + ** generated, and emit better code. + ** Note: Lots of improvements would be possible here, but I will + ** concentrate on the most common case: memset with arguments 2 and 3 + ** being constant numerical values. Some checks have shown that this + ** covers nearly 90% of all memset calls. + */ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && ED_IsConstAbsInt (&Arg2.Expr) && ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) || @@ -637,8 +637,8 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } /* memset returns the address, so the result is actually identical - * to the first argument. - */ + ** to the first argument. + */ *Expr = Arg1.Expr; } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && @@ -665,8 +665,8 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) AddCodeLine ("bne %s", LocalLabelName (Label)); /* memset returns the address, so the result is actually identical - * to the first argument. - */ + ** to the first argument. + */ *Expr = Arg1.Expr; } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && @@ -674,8 +674,8 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) (Arg2.Expr.IVal != 0 || IS_Get (&CodeSizeFactor) > 200)) { /* Remove all of the generated code but the load of the first - * argument. - */ + ** argument. + */ RemoveCode (&Arg1.Push); /* We need a label */ @@ -702,8 +702,8 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } /* Load the function result pointer into a/x (x is still valid). This - * code will get removed by the optimizer if it is not used later. - */ + ** code will get removed by the optimizer if it is not used later. + */ AddCodeLine ("lda ptr1"); /* The function result is an rvalue in the primary register */ @@ -759,10 +759,10 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ParseArg (&Arg2, Arg2Type); /* Since strcmp is a fastcall function, we must load the - * arg into the primary if it is not already there. This parameter is - * also ignored for the calculation of the parameter size, since it is - * not passed via the stack. - */ + ** arg into the primary if it is not already there. This parameter is + ** also ignored for the calculation of the parameter size, since it is + ** not passed via the stack. + */ if (Arg2.Flags & CF_CONST) { LoadExpr (CF_NONE, &Arg2.Expr); } @@ -771,8 +771,8 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr) g_call (CF_FIXARGC, Func_strcmp, ParamSize); /* Get the element counts of the arguments. Then get the larger of the - * two into ECount1. This removes FLEXIBLE and UNSPECIFIED automatically - */ + ** two into ECount1. This removes FLEXIBLE and UNSPECIFIED automatically + */ ECount1 = ArrayElementCount (&Arg1); ECount2 = ArrayElementCount (&Arg2); if (ECount2 > ECount1) { @@ -780,24 +780,24 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } /* If the second argument is the empty string literal, we can generate - * more efficient code. - */ + ** more efficient code. + */ if (ED_IsLocLiteral (&Arg2.Expr) && IS_Get (&WritableStrings) == 0 && GetLiteralSize (Arg2.Expr.LVal) == 1 && GetLiteralStr (Arg2.Expr.LVal)[0] == '\0') { /* Drop the generated code so we have the first argument in the - * primary - */ + ** primary + */ RemoveCode (&Arg1.Push); /* We don't need the literal any longer */ ReleaseLiteral (Arg2.Expr.LVal); /* We do now have Arg1 in the primary. Load the first character from - * this string and cast to int. This is the function result. - */ + ** this string and cast to int. This is the function result. + */ IsArray = IsTypeArray (Arg1.Type) && ED_IsRVal (&Arg1.Expr); if (IsArray && ED_IsLocStack (&Arg1.Expr) && (Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) { @@ -817,8 +817,8 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr) AddCodeLine ("lda %s", ED_GetLabelName (&Arg1.Expr, 0)); } else { /* Drop part of the generated code so we have the first argument - * in the primary - */ + ** in the primary + */ RemoveCode (&Arg1.Push); /* Fetch the first char */ @@ -957,10 +957,10 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ConsumeComma (); /* Argument #2. Since strcpy is a fastcall function, we must load the - * arg into the primary if it is not already there. This parameter is - * also ignored for the calculation of the parameter size, since it is - * not passed via the stack. - */ + ** arg into the primary if it is not already there. This parameter is + ** also ignored for the calculation of the parameter size, since it is + ** not passed via the stack. + */ ParseArg (&Arg2, Arg2Type); if (Arg2.Flags & CF_CONST) { LoadExpr (CF_NONE, &Arg2.Expr); @@ -973,10 +973,10 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ECount = ArrayElementCount (&Arg1); /* We've generated the complete code for the function now and know the - * types of all parameters. Check for situations where better code can - * be generated. If such a situation is detected, throw away the - * generated, and emit better code. - */ + ** types of all parameters. Check for situations where better code can + ** be generated. If such a situation is detected, throw away the + ** generated, and emit better code. + */ if (((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) || @@ -1019,12 +1019,12 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) { /* It is possible to just use one index register even if the stack - * offset is not zero, by adjusting the offset to the constant - * address accordingly. But we cannot do this if the data in - * question is in the register space or at an absolute address less - * than 256. Register space is zero page, which means that the - * address calculation could overflow in the linker. - */ + ** offset is not zero, by adjusting the offset to the constant + ** address accordingly. But we cannot do this if the data in + ** question is in the register space or at an absolute address less + ** than 256. Register space is zero page, which means that the + ** address calculation could overflow in the linker. + */ int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) && !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256); @@ -1062,12 +1062,12 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) StackPtr >= -255) { /* It is possible to just use one index register even if the stack - * offset is not zero, by adjusting the offset to the constant - * address accordingly. But we cannot do this if the data in - * question is in the register space or at an absolute address less - * than 256. Register space is zero page, which means that the - * address calculation could overflow in the linker. - */ + ** offset is not zero, by adjusting the offset to the constant + ** address accordingly. But we cannot do this if the data in + ** question is in the register space or at an absolute address less + ** than 256. Register space is zero page, which means that the + ** address calculation could overflow in the linker. + */ int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) && !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256); @@ -1140,8 +1140,8 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr) hie1 (&Arg); /* Check if the argument is an array. If so, remember the element count. - * Otherwise set the element count to undefined. - */ + ** Otherwise set the element count to undefined. + */ IsArray = IsTypeArray (Arg.Type); if (IsArray) { ECount = GetElementCount (Arg.Type); @@ -1156,19 +1156,19 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } /* Check if the elements of an array can be addressed by a byte sized - * index. This is true if the size of the array is known and less than - * 256. - */ + ** index. This is true if the size of the array is known and less than + ** 256. + */ IsByteIndex = (ECount != UNSPECIFIED && ECount < 256); /* Do type conversion */ TypeConversion (&Arg, ArgType); /* If the expression is a literal, and if string literals are read - * only, we can calculate the length of the string and remove it - * from the literal pool. Otherwise we have to calculate the length - * at runtime. - */ + ** only, we can calculate the length of the string and remove it + ** from the literal pool. Otherwise we have to calculate the length + ** at runtime. + */ if (ED_IsLocLiteral (&Arg) && IS_Get (&WritableStrings) == 0) { /* Constant string literal */ @@ -1178,9 +1178,9 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ReleaseLiteral (Arg.LVal); /* We will inline strlen for arrays with constant addresses, if either the - * inlining was forced on the command line, or the array is smaller than - * 256, so the inlining is considered safe. - */ + ** inlining was forced on the command line, or the array is smaller than + ** 256, so the inlining is considered safe. + */ } else if (ED_IsLocConst (&Arg) && IsArray && (IS_Get (&InlineStdFuncs) || IsByteIndex)) { @@ -1199,8 +1199,8 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr) Expr->Type = type_size_t; /* We will inline strlen for arrays on the stack, if the array is - * completely within the reach of a byte sized index register. - */ + ** completely within the reach of a byte sized index register. + */ } else if (ED_IsLocStack (&Arg) && IsArray && IsByteIndex && (Arg.IVal - StackPtr) + ECount < 256) { @@ -1224,9 +1224,9 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr) Expr->Type = type_size_t; /* strlen for a string that is pointed to by a register variable will only - * get inlined if requested on the command line, since we cannot know how - * big the buffer actually is, so inlining is not always safe. - */ + ** get inlined if requested on the command line, since we cannot know how + ** big the buffer actually is, so inlining is not always safe. + */ } else if (ED_IsLocRegister (&Arg) && ED_IsLVal (&Arg) && IsPtr && IS_Get (&InlineStdFuncs)) { @@ -1245,9 +1245,9 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr) Expr->Type = type_size_t; /* Last check: We will inline a generic strlen routine if inlining was - * requested on the command line, and the code size factor is more than - * 400 (code is 13 bytes vs. 3 for a jsr call). - */ + ** requested on the command line, and the code size factor is more than + ** 400 (code is 13 bytes vs. 3 for a jsr call). + */ } else if (IS_Get (&CodeSizeFactor) > 400 && IS_Get (&InlineStdFuncs)) { /* Load the expression into the primary */ @@ -1297,8 +1297,8 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr) int FindStdFunc (const char* Name) /* Determine if the given function is a known standard function that may be - * called in a special way. If so, return the index, otherwise return -1. - */ +** called in a special way. If so, return the index, otherwise return -1. +*/ { /* Look into the table for known names */ struct StdFuncDesc* D = @@ -1326,6 +1326,3 @@ void HandleStdFunc (int Index, FuncDesc* F, ExprDesc* lval) /* Call the handler function */ D->Handler (F, lval); } - - - diff --git a/src/cc65/stdfunc.h b/src/cc65/stdfunc.h index 9716d2b3e..7fc3abd3e 100644 --- a/src/cc65/stdfunc.h +++ b/src/cc65/stdfunc.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -52,8 +52,8 @@ int FindStdFunc (const char* Name); /* Determine if the given function is a known standard function that may be - * called in a special way. If so, return the index, otherwise return -1. - */ +** called in a special way. If so, return the index, otherwise return -1. +*/ void HandleStdFunc (int Index, struct FuncDesc* F, ExprDesc* lval); /* Generate code for a known standard function. */ @@ -63,6 +63,3 @@ void HandleStdFunc (int Index, struct FuncDesc* F, ExprDesc* lval); /* End of stdfunc.h */ #endif - - - diff --git a/src/cc65/stdnames.c b/src/cc65/stdnames.c index aa58e3be4..687b53894 100644 --- a/src/cc65/stdnames.c +++ b/src/cc65/stdnames.c @@ -50,6 +50,3 @@ const char Func_memset[] = "memset"; /* Asm name of "memset" */ const char Func_strcmp[] = "strcmp"; /* Asm name of "strcmp" */ const char Func_strcpy[] = "strcpy"; /* Asm name of "strcpy" */ const char Func_strlen[] = "strlen"; /* Asm name of "strlen" */ - - - diff --git a/src/cc65/stdnames.h b/src/cc65/stdnames.h index d60de04a2..dcb323924 100644 --- a/src/cc65/stdnames.h +++ b/src/cc65/stdnames.h @@ -56,6 +56,3 @@ extern const char Func_strlen[]; /* Asm name of "strlen" */ /* End of stdnames.h */ #endif - - - diff --git a/src/cc65/stmt.c b/src/cc65/stmt.c index 34a314863..84b516dc3 100644 --- a/src/cc65/stmt.c +++ b/src/cc65/stmt.c @@ -73,9 +73,9 @@ static int CheckLabelWithoutStatement (void) /* Called from Statement() after a label definition. Will check for a - * following closing curly brace. This means that a label is not followed - * by a statement which is required by the standard. Output an error if so. - */ +** following closing curly brace. This means that a label is not followed +** by a statement which is required by the standard. Output an error if so. +*/ { if (CurTok.Tok == TOK_RCURLY) { Error ("Label at end of compound statement"); @@ -89,9 +89,9 @@ static int CheckLabelWithoutStatement (void) static void CheckTok (token_t Tok, const char* Msg, int* PendingToken) /* Helper function for Statement. Will check for Tok and print Msg if not - * found. If PendingToken is NULL, it will the skip the token, otherwise - * it will store one to PendingToken. - */ +** found. If PendingToken is NULL, it will the skip the token, otherwise +** it will store one to PendingToken. +*/ { if (CurTok.Tok != Tok) { Error ("%s", Msg); @@ -106,12 +106,12 @@ static void CheckTok (token_t Tok, const char* Msg, int* PendingToken) static void CheckSemi (int* PendingToken) /* Helper function for Statement. Will check for a semicolon and print an - * error message if not found (plus some error recovery). If PendingToken is - * NULL, it will the skip the token, otherwise it will store one to - * PendingToken. - * This function is a special version of CheckTok with the addition of the - * error recovery. - */ +** error message if not found (plus some error recovery). If PendingToken is +** NULL, it will the skip the token, otherwise it will store one to +** PendingToken. +** This function is a special version of CheckTok with the addition of the +** error recovery. +*/ { int HaveToken = (CurTok.Tok == TOK_SEMI); if (!HaveToken) { @@ -171,8 +171,8 @@ static int IfStatement (void) g_defcodelabel (Label1); /* Since there's no else clause, we're not sure, if the a break - * statement is really executed. - */ + ** statement is really executed. + */ return 0; } else { @@ -185,8 +185,8 @@ static int IfStatement (void) NextToken (); /* If the if expression was always true, the code in the else branch - * is never executed. Output a warning if this is the case. - */ + ** is never executed. Output a warning if this is the case. + */ if (TestResult == TESTEXPR_TRUE) { Warning ("Unreachable code"); } @@ -261,13 +261,13 @@ static void WhileStatement (void) NextToken (); /* Add the loop to the loop stack. In case of a while loop, the condition - * label is used for continue statements. - */ + ** label is used for continue statements. + */ AddLoop (BreakLabel, CondLabel); /* We will move the code that evaluates the while condition to the end of - * the loop, so generate a jump here. - */ + ** the loop, so generate a jump here. + */ g_jump (CondLabel); /* Remember the current position */ @@ -296,8 +296,8 @@ static void WhileStatement (void) g_defcodelabel (BreakLabel); /* Eat remaining tokens that were delayed because of line info - * correctness - */ + ** correctness + */ SkipPending (PendingToken); /* Remove the loop from the loop stack */ @@ -318,9 +318,9 @@ static void ReturnStatement (void) hie0 (&Expr); /* If we return something in a void function, print an error and - * ignore the value. Otherwise convert the value to the type of the - * return. - */ + ** ignore the value. Otherwise convert the value to the type of the + ** return. + */ if (F_HasVoidReturn (CurrentFunc)) { Error ("Returning a value in function with return type void"); } else { @@ -429,8 +429,8 @@ static void ForStatement (void) NextToken (); /* Add the loop to the loop stack. A continue jumps to the start of the - * the increment condition. - */ + ** the increment condition. + */ AddLoop (BreakLabel, IncLabel); /* Skip the opening paren */ @@ -480,9 +480,9 @@ static void ForStatement (void) Statement (&PendingToken); /* If we had an increment expression, move the code to the bottom of - * the loop. In this case we don't need to jump there at the end of - * the loop body. - */ + ** the loop. In this case we don't need to jump there at the end of + ** the loop body. + */ if (HaveIncExpr) { CodeMark Here; GetCodePos (&Here); @@ -506,8 +506,8 @@ static void ForStatement (void) static int CompoundStatement (void) /* Compound statement. Allow any number of statements inside braces. The - * function returns true if the last statement was a break or return. - */ +** function returns true if the last statement was a break or return. +*/ { int GotBreak; @@ -549,13 +549,13 @@ static int CompoundStatement (void) int Statement (int* PendingToken) /* Statement parser. Returns 1 if the statement does a return/break, returns - * 0 otherwise. If the PendingToken pointer is not NULL, the function will - * not skip the terminating token of the statement (closing brace or - * semicolon), but store true if there is a pending token, and false if there - * is none. The token is always checked, so there is no need for the caller to - * check this token, it must be skipped, however. If the argument pointer is - * NULL, the function will skip the token. - */ +** 0 otherwise. If the PendingToken pointer is not NULL, the function will +** not skip the terminating token of the statement (closing brace or +** semicolon), but store true if there is a pending token, and false if there +** is none. The token is always checked, so there is no need for the caller to +** check this token, it must be skipped, however. If the argument pointer is +** NULL, the function will skip the token. +*/ { ExprDesc Expr; int GotBreak; @@ -567,8 +567,8 @@ int Statement (int* PendingToken) } /* Check for a label. A label is always part of a statement, it does not - * replace one. - */ + ** replace one. + */ while (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) { /* Handle the label */ DoLabel (); @@ -649,14 +649,14 @@ int Statement (int* PendingToken) /* Actual statement */ ExprWithCheck (hie0, &Expr); /* Load the result only if it is an lvalue and the type is - * marked as volatile. Otherwise the load is useless. - */ + ** marked as volatile. Otherwise the load is useless. + */ if (ED_IsLVal (&Expr) && IsQualVolatile (Expr.Type)) { LoadExpr (CF_NONE, &Expr); } /* If the statement didn't generate code, and is not of type - * void, emit a warning. - */ + ** void, emit a warning. + */ GetCodePos (&End); if (CodeRangeIsEmpty (&Start, &End) && !IsTypeVoid (Expr.Type) && @@ -667,7 +667,3 @@ int Statement (int* PendingToken) } return 0; } - - - - diff --git a/src/cc65/stmt.h b/src/cc65/stmt.h index 4a9a72e42..04ef728a3 100644 --- a/src/cc65/stmt.h +++ b/src/cc65/stmt.h @@ -46,19 +46,16 @@ int Statement (int* PendingToken); /* Statement parser. Returns 1 if the statement does a return/break, returns - * 0 otherwise. If the PendingToken pointer is not NULL, the function will - * not skip the terminating token of the statement (closing brace or - * semicolon), but store true if there is a pending token, and false if there - * is none. The token is always checked, so there is no need for the caller to - * check this token, it must be skipped, however. If the argument pointer is - * NULL, the function will skip the token. - */ +** 0 otherwise. If the PendingToken pointer is not NULL, the function will +** not skip the terminating token of the statement (closing brace or +** semicolon), but store true if there is a pending token, and false if there +** is none. The token is always checked, so there is no need for the caller to +** check this token, it must be skipped, however. If the argument pointer is +** NULL, the function will skip the token. +*/ /* End of stmt.h */ #endif - - - diff --git a/src/cc65/swstmt.c b/src/cc65/swstmt.c index 7e48b58d2..0aefc051c 100644 --- a/src/cc65/swstmt.c +++ b/src/cc65/swstmt.c @@ -102,8 +102,8 @@ void SwitchStatement (void) NextToken (); /* Read the switch expression and load it into the primary. It must have - * integer type. - */ + ** integer type. + */ ConsumeLParen (); Expression0 (&SwitchExpr); if (!IsClassInt (SwitchExpr.Type)) { @@ -114,20 +114,20 @@ void SwitchStatement (void) ConsumeRParen (); /* Add a jump to the switch code. This jump is usually unnecessary, - * because the switch code will moved up just behind the switch - * expression. However, in rare cases, there's a label at the end of - * the switch expression. This label will not get moved, so the code - * jumps around the switch code, and after moving the switch code, - * things look really weird. If we add a jump here, we will never have - * a label attached to the current code position, and the jump itself - * will get removed by the optimizer if it is unnecessary. - */ + ** because the switch code will moved up just behind the switch + ** expression. However, in rare cases, there's a label at the end of + ** the switch expression. This label will not get moved, so the code + ** jumps around the switch code, and after moving the switch code, + ** things look really weird. If we add a jump here, we will never have + ** a label attached to the current code position, and the jump itself + ** will get removed by the optimizer if it is unnecessary. + */ SwitchCodeLabel = GetLocalLabel (); g_jump (SwitchCodeLabel); /* Remember the current code position. We will move the switch code - * to this position later. - */ + ** to this position later. + */ GetCodePos (&CaseCodeStart); /* Setup the control structure, save the old and activate the new one */ @@ -150,8 +150,8 @@ void SwitchStatement (void) } /* Parse the following statement, which will actually be a compound - * statement because of the curly brace at the current input position - */ + ** statement because of the curly brace at the current input position + */ HaveBreak = Statement (&RCurlyBrace); /* Check if we had any labels */ @@ -160,12 +160,12 @@ void SwitchStatement (void) } /* If the last statement did not have a break, we may have an open - * label (maybe from an if or similar). Emitting code and then moving - * this code to the top will also move the label to the top which is - * wrong. So if the last statement did not have a break (which would - * carry the label), add a jump to the exit. If it is useless, the - * optimizer will remove it later. - */ + ** label (maybe from an if or similar). Emitting code and then moving + ** this code to the top will also move the label to the top which is + ** wrong. So if the last statement did not have a break (which would + ** carry the label), add a jump to the exit. If it is useless, the + ** optimizer will remove it later. + */ if (!HaveBreak) { g_jump (ExitLabel); } @@ -200,8 +200,8 @@ void SwitchStatement (void) FreeCaseNodeColl (SwitchData.Nodes); /* If the case statement was (correctly) terminated by a closing curly - * brace, skip it now. - */ + ** brace, skip it now. + */ if (RCurlyBrace) { NextToken (); } @@ -315,6 +315,3 @@ void DefaultLabel (void) /* Skip the colon */ ConsumeColon (); } - - - diff --git a/src/cc65/swstmt.h b/src/cc65/swstmt.h index 1523217f1..b4facf2cd 100644 --- a/src/cc65/swstmt.h +++ b/src/cc65/swstmt.h @@ -56,7 +56,5 @@ void DefaultLabel (void); /* End of swstmt.h */ + #endif - - - diff --git a/src/cc65/symentry.c b/src/cc65/symentry.c index 41e14e673..aa5949f97 100644 --- a/src/cc65/symentry.c +++ b/src/cc65/symentry.c @@ -158,8 +158,8 @@ int SymIsOutputFunc (const SymEntry* Sym) /* Return true if this is a function that must be output */ { /* Symbol must be a function which is defined and either extern or - * static and referenced. - */ + ** static and referenced. + */ return IsTypeFunc (Sym->Type) && SymIsDef (Sym) && (Sym->Flags & (SC_REF | SC_EXTERN)); @@ -262,6 +262,3 @@ int HasAnonName (const SymEntry* Entry) { return IsAnonName (Entry->Name); } - - - diff --git a/src/cc65/symentry.h b/src/cc65/symentry.h index 14d786995..4fa84255b 100644 --- a/src/cc65/symentry.h +++ b/src/cc65/symentry.h @@ -123,8 +123,8 @@ struct SymEntry { unsigned Label; /* Register bank offset and offset of the saved copy on stack for - * register variables. - */ + ** register variables. + */ struct { int RegOffs; int SaveOffs; @@ -272,7 +272,5 @@ int HasAnonName (const SymEntry* Entry); /* End of symentry.h */ + #endif - - - diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 4a44c770d..1f63e9430 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -159,8 +159,8 @@ static void CheckSymTable (SymTable* Tab) if (!SymIsTypeDef (Entry)) { /* Check if the symbol is one with storage, and it if it was - * defined but not used. - */ + ** defined but not used. + */ if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) { if (SymIsDef (Entry) && !SymIsRef (Entry) && !SymHasAttr (Entry, atUnused)) { @@ -268,7 +268,9 @@ void EnterFunctionLevel (void) TagTab = S; /* Create and assign a new label table */ - LabelTab = NewSymTable (SYMTAB_SIZE_LABEL); + S = NewSymTable (SYMTAB_SIZE_LABEL); + S->PrevTab = LabelTab; + LabelTab = S; } @@ -286,6 +288,7 @@ void RememberFunctionLevel (struct FuncDesc* F) /* Don't delete the tables */ SymTab = SymTab->PrevTab; TagTab = TagTab->PrevTab; + LabelTab = LabelTab->PrevTab; } @@ -375,9 +378,9 @@ void EnterStructLevel (void) SymTable* S; /* Get a new symbol table and make it current. Note: Structs and enums - * nested in struct scope are NOT local to the struct but visible in the - * outside scope. So we will NOT create a new struct or enum table. - */ + ** nested in struct scope are NOT local to the struct but visible in the + ** outside scope. So we will NOT create a new struct or enum table. + */ S = NewSymTable (SYMTAB_SIZE_BLOCK); S->PrevTab = SymTab; SymTab = S; @@ -497,8 +500,8 @@ SymEntry* FindStructField (const Type* T, const char* Name) CHECK (Struct != 0); /* Now search in the struct symbol table. Beware: The table may not - * exist. - */ + ** exist. + */ if (Struct->V.S.SymTab) { Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name)); } @@ -762,9 +765,9 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) EType = Entry->Type; /* If we are handling arrays, the old entry or the new entry may be an - * incomplete declaration. Accept this, and if the exsting entry is - * incomplete, complete it. - */ + ** incomplete declaration. Accept this, and if the exsting entry is + ** incomplete, complete it. + */ if (IsTypeArray (T) && IsTypeArray (EType)) { /* Get the array sizes */ @@ -792,17 +795,17 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) } /* In case of a function, use the new type descriptor, since it - * contains pointers to the new symbol tables that are needed if - * an actual function definition follows. Be sure not to use the - * new descriptor if it contains a function declaration with an - * empty parameter list. - */ + ** contains pointers to the new symbol tables that are needed if + ** an actual function definition follows. Be sure not to use the + ** new descriptor if it contains a function declaration with an + ** empty parameter list. + */ if (IsFunc) { /* Get the function descriptor from the new type */ FuncDesc* F = GetFuncDesc (T); /* Use this new function descriptor if it doesn't contain - * an empty parameter list. - */ + ** an empty parameter list. + */ if ((F->Flags & FD_EMPTY) == 0) { Entry->V.F.Func = F; SetFuncDesc (EType, F); @@ -822,8 +825,8 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) Entry->Type = TypeDup (T); /* If this is a function, set the function descriptor and clear - * additional fields. - */ + ** additional fields. + */ if (IsFunc) { Entry->V.F.Func = GetFuncDesc (Entry->Type); Entry->V.F.Seg = 0; @@ -956,8 +959,8 @@ void EmitDebugInfo (void) /* Output info for locals if enabled */ if (DebugInfo) { /* For cosmetic reasons in the output file, we will insert two tabs - * on global level and just one on local level. - */ + ** on global level and just one on local level. + */ if (LexicalLevel == LEX_LEVEL_GLOBAL) { Head = "\t.dbg\t\tsym"; } else { @@ -984,6 +987,3 @@ void EmitDebugInfo (void) } } } - - - diff --git a/src/cc65/symtab.h b/src/cc65/symtab.h index 154dce55a..39782d6ab 100644 --- a/src/cc65/symtab.h +++ b/src/cc65/symtab.h @@ -196,6 +196,3 @@ void EmitDebugInfo (void); /* End of symtab.h */ #endif - - - diff --git a/src/cc65/testexpr.c b/src/cc65/testexpr.c index f95c94dd8..5bb7bf7e4 100644 --- a/src/cc65/testexpr.c +++ b/src/cc65/testexpr.c @@ -51,9 +51,9 @@ unsigned Test (unsigned Label, int Invert) /* Evaluate a boolean test expression and jump depending on the result of - * the test and on Invert. The function returns one of the TESTEXPR_xx codes - * defined above. If the jump is always true, a warning is output. - */ +** the test and on Invert. The function returns one of the TESTEXPR_xx codes +** defined above. If the jump is always true, a warning is output. +*/ { ExprDesc Expr; unsigned Result; @@ -104,10 +104,10 @@ unsigned Test (unsigned Label, int Invert) unsigned TestInParens (unsigned Label, int Invert) /* Evaluate a boolean test expression in parenthesis and jump depending on - * the result of the test * and on Invert. The function returns one of the - * TESTEXPR_xx codes defined above. If the jump is always true, a warning is - * output. - */ +** the result of the test * and on Invert. The function returns one of the +** TESTEXPR_xx codes defined above. If the jump is always true, a warning is +** output. +*/ { unsigned Result; @@ -123,7 +123,3 @@ unsigned TestInParens (unsigned Label, int Invert) /* Return the result of the expression */ return Result; } - - - - diff --git a/src/cc65/testexpr.h b/src/cc65/testexpr.h index bfc033185..478280a28 100644 --- a/src/cc65/testexpr.h +++ b/src/cc65/testexpr.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -58,22 +58,19 @@ unsigned Test (unsigned Label, int Invert); /* Evaluate a boolean test expression and jump depending on the result of - * the test and on Invert. The function returns one of the TESTEXPR_xx codes - * defined above. If the jump is always true, a warning is output. - */ +** the test and on Invert. The function returns one of the TESTEXPR_xx codes +** defined above. If the jump is always true, a warning is output. +*/ unsigned TestInParens (unsigned Label, int Invert); /* Evaluate a boolean test expression in parenthesis and jump depending on - * the result of the test * and on Invert. The function returns one of the - * TESTEXPR_xx codes defined above. If the jump is always true, a warning is - * output. - */ +** the result of the test * and on Invert. The function returns one of the +** TESTEXPR_xx codes defined above. If the jump is always true, a warning is +** output. +*/ /* End of testexpr.h */ + #endif - - - - diff --git a/src/cc65/textseg.c b/src/cc65/textseg.c index 2275261e0..e59bf2e06 100644 --- a/src/cc65/textseg.c +++ b/src/cc65/textseg.c @@ -34,8 +34,8 @@ /* Note: This is NOT some sort of code segment, it is used to store lines of - * output that are textual (not real code) instead. - */ +** output that are textual (not real code) instead. +*/ @@ -116,6 +116,3 @@ void TS_Output (const TextSeg* S) /* Add an additional newline after the segment output */ WriteOutput ("\n"); } - - - diff --git a/src/cc65/textseg.h b/src/cc65/textseg.h index 1c3aba53b..83ef0bccf 100644 --- a/src/cc65/textseg.h +++ b/src/cc65/textseg.h @@ -34,8 +34,8 @@ /* Note: This is NOT some sort of code segment, it is used to store lines of - * output that are textual (not real code) instead. - */ +** output that are textual (not real code) instead. +*/ @@ -90,7 +90,5 @@ void TS_Output (const TextSeg* S); /* End of textseg.h */ + #endif - - - diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 139b3b3ff..67941026b 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -61,9 +61,9 @@ static void SetResult (typecmp_t* Result, typecmp_t Val) static int ParamsHaveDefaultPromotions (const FuncDesc* F) /* Check if any of the parameters of function F has a default promotion. In - * this case, the function is not compatible with an empty parameter name list - * declaration. - */ +** this case, the function is not compatible with an empty parameter name list +** declaration. +*/ { /* Get the symbol table */ const SymTable* Tab = F->SymTab; @@ -75,8 +75,8 @@ static int ParamsHaveDefaultPromotions (const FuncDesc* F) while (Sym && (Sym->Flags & SC_PARAM)) { /* If this is an integer type, check if the promoted type is equal - * to the original type. If not, we have a default promotion. - */ + ** to the original type. If not, we have a default promotion. + */ if (IsClassInt (Sym->Type)) { if (IntPromotion (Sym->Type) != Sym->Type) { return 1; @@ -95,8 +95,8 @@ static int ParamsHaveDefaultPromotions (const FuncDesc* F) static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2) /* Compare two function symbol tables regarding function parameters. Return 1 - * if they are equal and 0 otherwise. - */ +** if they are equal and 0 otherwise. +*/ { /* Get the symbol tables */ const SymTable* Tab1 = F1->SymTab; @@ -114,8 +114,8 @@ static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2) Type* Type2 = Sym2->Type; /* If either of both functions is old style, apply the default - * promotions to the parameter type. - */ + ** promotions to the parameter type. + */ if (F1->Flags & FD_OLDSTYLE) { if (IsClassInt (Type1)) { Type1 = IntPromotion (Type1); @@ -139,8 +139,8 @@ static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2) } /* Check both pointers against NULL or a non parameter to compare the - * field count - */ + ** field count + */ return (Sym1 == 0 || (Sym1->Flags & SC_PARAM) == 0) && (Sym2 == 0 || (Sym2->Flags & SC_PARAM) == 0); } @@ -222,8 +222,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) RightQual = GetQualifier (rhs); /* If the left type is a pointer and the right is an array, both - * are compatible. - */ + ** are compatible. + */ if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) { RightType = T_TYPE_PTR; } @@ -235,8 +235,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) } /* On indirection level zero, a qualifier or sign difference is - * accepted. The types are no longer equal, but compatible. - */ + ** accepted. The types are no longer equal, but compatible. + */ if (LeftSign != RightSign) { if (ElementCount == 0) { SetResult (Result, TC_SIGN_DIFF); @@ -247,12 +247,12 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) } if (LeftQual != RightQual) { /* On the first indirection level, different qualifiers mean - * that the types are still compatible. On the second level, - * this is a (maybe minor) error, so we create a special - * return code, since a qualifier is dropped from a pointer. - * Starting from the next level, the types are incompatible - * if the qualifiers differ. - */ + ** that the types are still compatible. On the second level, + ** this is a (maybe minor) error, so we create a special + ** return code, since a qualifier is dropped from a pointer. + ** Starting from the next level, the types are incompatible + ** if the qualifiers differ. + */ /* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */ switch (Indirections) { @@ -262,8 +262,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) case 1: /* A non const value on the right is compatible to a - * const one to the left, same for volatile. - */ + ** const one to the left, same for volatile. + */ if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) || (LeftQual & T_QUAL_VOLATILE) < (RightQual & T_QUAL_VOLATILE)) { SetResult (Result, TC_QUAL_DIFF); @@ -291,13 +291,13 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) F2 = GetFuncDesc (rhs); /* If one of both functions has an empty parameter list (which - * does also mean, it is not a function definition, because the - * flag is reset in this case), it is considered equal to any - * other definition, provided that the other has no default - * promotions in the parameter list. If none of both parameter - * lists is empty, we have to check the parameter lists and - * other attributes. - */ + ** does also mean, it is not a function definition, because the + ** flag is reset in this case), it is considered equal to any + ** other definition, provided that the other has no default + ** promotions in the parameter list. If none of both parameter + ** lists is empty, we have to check the parameter lists and + ** other attributes. + */ if (F1->Flags & FD_EMPTY) { if ((F2->Flags & FD_EMPTY) == 0) { if (ParamsHaveDefaultPromotions (F2)) { @@ -348,9 +348,9 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) case T_TYPE_STRUCT: case T_TYPE_UNION: /* Compare the fields recursively. To do that, we fetch the - * pointer to the struct definition from the type, and compare - * the fields. - */ + ** pointer to the struct definition from the type, and compare + ** the fields. + */ Sym1 = GetSymEntry (lhs); Sym2 = GetSymEntry (rhs); @@ -368,9 +368,9 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) Tab2 = Sym2->V.S.SymTab; /* One or both structs may be forward definitions. In this case, - * the symbol tables are both non existant. Assume that the - * structs are equal in this case. - */ + ** the symbol tables are both non existant. Assume that the + ** structs are equal in this case. + */ if (Tab1 != 0 && Tab2 != 0) { if (EqualSymTables (Tab1, Tab2) == 0) { @@ -420,7 +420,3 @@ typecmp_t TypeCmp (const Type* lhs, const Type* rhs) /* Return the result */ return Result; } - - - - diff --git a/src/cc65/typecmp.h b/src/cc65/typecmp.h index 652585738..5f95e42a1 100644 --- a/src/cc65/typecmp.h +++ b/src/cc65/typecmp.h @@ -75,7 +75,3 @@ typecmp_t TypeCmp (const Type* lhs, const Type* rhs); /* End of typecmp.h */ #endif - - - - diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index 6d50aa5c6..e4edd6a2e 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -67,8 +67,8 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType) OldType = Expr->Type; /* If we're converting to void, we're done. Note: This does also cover a - * conversion void -> void. - */ + ** conversion void -> void. + */ if (IsTypeVoid (NewType)) { ED_MakeRVal (Expr); /* Never an lvalue */ goto ExitPoint; @@ -81,22 +81,22 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType) } /* Get the sizes of the types. Since we've excluded void types, checking - * for known sizes makes sense here. - */ + ** for known sizes makes sense here. + */ OldSize = CheckedSizeOf (OldType); NewSize = CheckedSizeOf (NewType); /* lvalue? */ if (ED_IsLVal (Expr)) { - /* We have an lvalue. If the new size is smaller than the new one, - * we don't need to do anything. The compiler will generate code - * to load only the portion of the value that is actually needed. - * This works only on a little endian architecture, but that's - * what we support. - * If both sizes are equal, do also leave the value alone. - * If the new size is larger, we must convert the value. - */ + /* We have an lvalue. If the new size is smaller than the old one, + ** we don't need to do anything. The compiler will generate code + ** to load only the portion of the value that is actually needed. + ** This works only on a little endian architecture, but that's + ** what we support. + ** If both sizes are equal, do also leave the value alone. + ** If the new size is larger, we must convert the value. + */ if (NewSize > OldSize) { /* Load the value into the primary */ LoadExpr (CF_NONE, Expr); @@ -111,17 +111,17 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType) } else if (ED_IsLocAbs (Expr)) { /* A cast of a constant numeric value to another type. Be sure - * to handle sign extension correctly. - */ + ** to handle sign extension correctly. + */ /* Get the current and new size of the value */ unsigned OldBits = OldSize * 8; unsigned NewBits = NewSize * 8; /* Check if the new datatype will have a smaller range. If it - * has a larger range, things are ok, since the value is - * internally already represented by a long. - */ + ** has a larger range, things are OK, since the value is + ** internally already represented by a long. + */ if (NewBits <= OldBits) { /* Cut the value to the new size */ @@ -139,9 +139,9 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType) } else { /* The value is not a constant. If the sizes of the types are - * not equal, add conversion code. Be sure to convert chars - * correctly. - */ + ** not equal, add conversion code. Be sure to convert chars + ** correctly. + */ if (OldSize != NewSize) { /* Load the value into the primary */ @@ -164,9 +164,9 @@ ExitPoint: void TypeConversion (ExprDesc* Expr, Type* NewType) /* Do an automatic conversion of the given expression to the new type. Output - * warnings or errors where this automatic conversion is suspicious or - * impossible. - */ +** warnings or errors where this automatic conversion is suspicious or +** impossible. +*/ { #if 0 /* Debugging */ @@ -181,8 +181,8 @@ void TypeConversion (ExprDesc* Expr, Type* NewType) /* First, do some type checking */ if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) { /* If one of the sides are of type void, output a more apropriate - * error message. - */ + ** error message. + */ Error ("Illegal type"); } @@ -228,10 +228,10 @@ void TypeConversion (ExprDesc* Expr, Type* NewType) } /* Pointer to pointer assignment is valid, if: - * - both point to the same types, or - * - the rhs pointer is a void pointer, or - * - the lhs pointer is a void pointer. - */ + ** - both point to the same types, or + ** - the rhs pointer is a void pointer, or + ** - the lhs pointer is a void pointer. + */ if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) { /* Compare the types */ switch (TypeCmp (NewType, Expr->Type)) { @@ -295,8 +295,3 @@ void TypeCast (ExprDesc* Expr) /* Convert the value. */ DoConversion (Expr, NewType); } - - - - - diff --git a/src/cc65/typeconv.h b/src/cc65/typeconv.h index 2407862e1..8321aded4 100644 --- a/src/cc65/typeconv.h +++ b/src/cc65/typeconv.h @@ -51,9 +51,9 @@ void TypeConversion (ExprDesc* Expr, Type* NewType); /* Do an automatic conversion of the given expression to the new type. Output - * warnings or errors where this automatic conversion is suspicious or - * impossible. - */ +** warnings or errors where this automatic conversion is suspicious or +** impossible. +*/ void TypeCast (ExprDesc* Expr); /* Handle an explicit cast. */ @@ -61,7 +61,5 @@ void TypeCast (ExprDesc* Expr); /* End of typeconv.h */ + #endif - - - diff --git a/src/cc65/util.c b/src/cc65/util.c index db26dd7d2..ccc7ccb71 100644 --- a/src/cc65/util.c +++ b/src/cc65/util.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -45,8 +45,8 @@ int PowerOf2 (unsigned long Val) /* Return the exponent if val is a power of two. Return -1 if val is not a - * power of two. - */ +** power of two. +*/ { int I; unsigned long Mask = 0x0001; @@ -59,6 +59,3 @@ int PowerOf2 (unsigned long Val) } return -1; } - - - diff --git a/src/cc65/util.h b/src/cc65/util.h index 9fc717339..2aa8a2f2a 100644 --- a/src/cc65/util.h +++ b/src/cc65/util.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -46,14 +46,11 @@ int PowerOf2 (unsigned long Val); /* Return the exponent if val is a power of two. Return -1 if val is not a - * power of two. - */ +** power of two. +*/ /* End of util.h */ #endif - - - diff --git a/src/chrcvt/main.c b/src/chrcvt/main.c index bec905142..7b1c3219e 100644 --- a/src/chrcvt/main.c +++ b/src/chrcvt/main.c @@ -52,111 +52,111 @@ /* - * The following is a corrected doc from the BGI font editor toolkit: - * - * BGI Stroke File Format - * - * The structure of Borland .CHR (stroke) files is as follows: - * - * ; offset 0h is a Borland header: - * ; - * HeaderSize equ 080h - * DataSize equ (size of font file) - * descr equ "Triplex font" - * fname equ "TRIP" - * MajorVersion equ 1 - * MinorVersion equ 0 - * - * db 'PK',8,8 - * db 'BGI ',descr,' V' - * db MajorVersion+'0' - * db (MinorVersion / 10)+'0',(MinorVersion mod 10)+'0' - * db ' - 19 October 1987',0DH,0AH - * db 'Copyright (c) 1987 Borland International', 0dh,0ah - * db 0,1ah ; null & ctrl-Z = end - * - * dw HeaderSize ; size of header - * db fname ; font name - * dw DataSize ; font file size - * db MajorVersion,MinorVersion ; version #'s - * db 1,0 ; minimal version #'s - * - * db (HeaderSize - $) DUP (0) ; pad out to header size - * - * At offset 80h starts data for the file: - * - * ; 80h '+' flags stroke file type - * ; 81h-82h number chars in font file (n) - * ; 83h undefined - * ; 84h ASCII value of first char in file - * ; 85h-86h offset to stroke definitions (8+3n) - * ; 87h scan flag (normally 0) - * ; 88h distance from origin to top of capital - * ; 89h distance from origin to baseline - * ; 8Ah distance from origin to bottom descender - * ; 8Bh-8Fh undefined - * ; 90h offsets to individual character definitions - * ; 90h+2n width table (one word per character) - * ; 90h+3n start of character definitions - * ; - * The individual character definitions consist of a variable number of words - * describing the operations required to render a character. Each word - * consists of an (x,y) coordinate pair and a two-bit opcode, encoded as shown - * here: - * - * Byte 1 7 6 5 4 3 2 1 0 bit # - * op1 <seven bit signed X coord> - * - * Byte 2 7 6 5 4 3 2 1 0 bit # - * op2 <seven bit signed Y coord> - * - * - * Opcodes - * - * op1=0 op2=0 End of character definition. - * op1=1 op2=0 Move the pointer to (x,y) - * op1=1 op2=1 Draw from current pointer to (x,y) - */ +** The following is a corrected doc from the BGI font editor toolkit: +** +** BGI Stroke File Format +** +** The structure of Borland .CHR (stroke) files is as follows: +** +** ; offset 0h is a Borland header: +** ; +** HeaderSize equ 080h +** DataSize equ (size of font file) +** descr equ "Triplex font" +** fname equ "TRIP" +** MajorVersion equ 1 +** MinorVersion equ 0 +** +** db 'PK',8,8 +** db 'BGI ',descr,' V' +** db MajorVersion+'0' +** db (MinorVersion / 10)+'0',(MinorVersion mod 10)+'0' +** db ' - 19 October 1987',0DH,0AH +** db 'Copyright (c) 1987 Borland International', 0dh,0ah +** db 0,1ah ; null & ctrl-Z = end +** +** dw HeaderSize ; size of header +** db fname ; font name +** dw DataSize ; font file size +** db MajorVersion,MinorVersion ; version #'s +** db 1,0 ; minimal version #'s +** +** db (HeaderSize - $) DUP (0) ; pad out to header size +** +** At offset 80h starts data for the file: +** +** ; 80h '+' flags stroke file type +** ; 81h-82h number chars in font file (n) +** ; 83h undefined +** ; 84h ASCII value of first char in file +** ; 85h-86h offset to stroke definitions (8+3n) +** ; 87h scan flag (normally 0) +** ; 88h distance from origin to top of capital +** ; 89h distance from origin to baseline +** ; 8Ah distance from origin to bottom descender +** ; 8Bh-8Fh undefined +** ; 90h offsets to individual character definitions +** ; 90h+2n width table (one word per character) +** ; 90h+3n start of character definitions +** ; +** The individual character definitions consist of a variable number of words +** describing the operations required to render a character. Each word +** consists of an (x,y) coordinate pair and a two-bit opcode, encoded as shown +** here: +** +** Byte 1 7 6 5 4 3 2 1 0 bit # +** op1 <seven bit signed X coord> +** +** Byte 2 7 6 5 4 3 2 1 0 bit # +** op2 <seven bit signed Y coord> +** +** +** Opcodes +** +** op1=0 op2=0 End of character definition. +** op1=1 op2=0 Move the pointer to (x,y) +** op1=1 op2=1 Draw from current pointer to (x,y) +*/ /* The target file format is designed to be read by a cc65 compiled program - * more easily. It should not be necessary to load the whole file into a - * buffer to parse it, or seek within the file. Also using less memory if - * possible would be fine. Therefore we use the following structure: - * - * Header portion: - * .byte $54, $43, $48, $00 ; "TCH" version - * .word <size of data portion> - * Data portion: - * .byte <top> ; Baseline to top - * .byte <bottom> ; Baseline to bottom - * .byte <height> ; Maximum char height - * .byte <width>, ... ; $5F width bytes - * .word <char definition offset>, ... ; $5F char def offsets - * Character definitions: - * .word <converted opcode>, ... - * .byte $80 - * - * The baseline of the character is assume to be at position zero. top and - * bottom are both positive values. The former extends in positive, the other - * in negative direction of the baseline. height contains the sum of top and - * bottom and is stored here just for easier handling. - * - * The opcodes get converted for easier handling: END is marked by bit 7 - * set in the first byte. The second byte of this opcode is not needed. - * Bit 7 of the second byte marks a MOVE (bit 7 = 0) or DRAW (bit 7 = 1). - * - * The number of characters is fixed to $20..$7E (space to tilde), so character - * widths and offsets can be stored in fixed size preallocated tables. The - * space for the character definitions is allocated on the heap, it's size - * is stored in the header. - * - * Above structure allows a program to read the header portion of the file, - * validate it, then read the remainder of the file into memory in one chunk. - * The character definition offsets will then be converted into pointers by - * adding the character definition base pointer to each. - */ +** more easily. It should not be necessary to load the whole file into a +** buffer to parse it, or seek within the file. Also using less memory if +** possible would be fine. Therefore we use the following structure: +** +** Header portion: +** .byte $54, $43, $48, $00 ; "TCH" version +** .word <size of data portion> +** Data portion: +** .byte <top> ; Baseline to top +** .byte <bottom> ; Baseline to bottom +** .byte <height> ; Maximum char height +** .byte <width>, ... ; $5F width bytes +** .word <char definition offset>, ... ; $5F char def offsets +** Character definitions: +** .word <converted opcode>, ... +** .byte $80 +** +** The baseline of the character is assume to be at position zero. top and +** bottom are both positive values. The former extends in positive, the other +** in negative direction of the baseline. height contains the sum of top and +** bottom and is stored here just for easier handling. +** +** The opcodes get converted for easier handling: END is marked by bit 7 +** set in the first byte. The second byte of this opcode is not needed. +** Bit 7 of the second byte marks a MOVE (bit 7 = 0) or DRAW (bit 7 = 1). +** +** The number of characters is fixed to $20..$7E (space to tilde), so character +** widths and offsets can be stored in fixed size preallocated tables. The +** space for the character definitions is allocated on the heap, it's size +** is stored in the header. +** +** Above structure allows a program to read the header portion of the file, +** validate it, then read the remainder of the file into memory in one chunk. +** The character definition offsets will then be converted into pointers by +** adding the character definition base pointer to each. +*/ @@ -227,8 +227,8 @@ static void OptVersion (const char* Opt attribute ((unused)), static void ConvertChar (StrBuf* Data, const unsigned char* Buf, int Remaining) /* Convert data for one character. Original data is in Buf, converted data - * will be placed in Data. - */ +** will be placed in Data. +*/ { /* Convert all drawing vectors for this character */ while (1) { @@ -289,11 +289,12 @@ static void ConvertFile (const char* Input, const char* Output) /* The header of a BGI vector font file */ static const unsigned char ChrHeader[] = { /* According to the Borland docs, the following should work, but it - * doesn't. Seems like there are fonts that work, but don't have the - * "BGI" string in the header. So we use just the PK\b\b mark as - * a header. - * - * 0x50, 0x4B, 0x08, 0x08, 0x42, 0x47, 0x49, 0x20 */ + ** doesn't. Seems like there are fonts that work, but don't have the + ** "BGI" string in the header. So we use just the PK\b\b mark as + ** a header. + ** + ** 0x50, 0x4B, 0x08, 0x08, 0x42, 0x47, 0x49, 0x20 + */ 0x50, 0x4B, 0x08, 0x08 }; @@ -380,8 +381,8 @@ static void ConvertFile (const char* Input, const char* Output) Print (stderr, 1, "%.*s\n", (int) (MsgEnd - Buf - 4), Buf+4); /* Get pointers to the width table, the offset table and the vector data - * table. The first two corrected for 0x20 as first entry. - */ + ** table. The first two corrected for 0x20 as first entry. + */ OffsetBuf = Buf + 0x90 + ((0x20 - FirstChar) * 2); WidthBuf = Buf + 0x90 + (CharCount * 2) + (0x20 - FirstChar); VectorBuf = Buf + 0x90 + (CharCount * 3); @@ -425,8 +426,8 @@ static void ConvertFile (const char* Input, const char* Output) } /* If the output file is NULL, use the name of the input file with ".tch" - * appended. - */ + ** appended. + */ if (Output == 0) { Output = MakeFilename (Input, ".tch"); } diff --git a/src/cl65.vcxproj b/src/cl65.vcxproj index ee348830d..64c1126b1 100644 --- a/src/cl65.vcxproj +++ b/src/cl65.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -18,10 +18,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -47,7 +49,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> @@ -62,7 +64,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> @@ -80,7 +82,6 @@ <ItemGroup> <ClInclude Include="cl65\error.h" /> <ClInclude Include="cl65\global.h" /> - <ClInclude Include="cl65\spawn.h" /> </ItemGroup> <ItemGroup> <None Include="cl65\spawn-amiga.inc" /> diff --git a/src/cl65/error.c b/src/cl65/error.c index c68b7fe64..ee2adcfcc 100644 --- a/src/cl65/error.c +++ b/src/cl65/error.c @@ -91,5 +91,3 @@ void Internal (const char* Format, ...) exit (EXIT_FAILURE); } - - diff --git a/src/cl65/error.h b/src/cl65/error.h index 38999faec..b1ff30660 100644 --- a/src/cl65/error.h +++ b/src/cl65/error.h @@ -58,6 +58,3 @@ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)) /* End of error.h */ #endif - - - diff --git a/src/cl65/global.c b/src/cl65/global.c index 318020415..f522224ac 100644 --- a/src/cl65/global.c +++ b/src/cl65/global.c @@ -44,6 +44,3 @@ unsigned char Debug = 0; /* Debug mode enabled? */ - - - diff --git a/src/cl65/global.h b/src/cl65/global.h index fd85dc2d5..2d2d96921 100644 --- a/src/cl65/global.h +++ b/src/cl65/global.h @@ -51,6 +51,3 @@ extern unsigned char Debug; /* Debug mode enabled? */ /* End of global.h */ #endif - - - diff --git a/src/cl65/main.c b/src/cl65/main.c index e704d985c..a0a6ed02b 100644 --- a/src/cl65/main.c +++ b/src/cl65/main.c @@ -34,15 +34,27 @@ /* Check out if we have a spawn() function on the system, or if we must use - * our own. - */ -#if defined(__WATCOMC__) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__DJGPP__) -# define HAVE_SPAWN 1 +** our own. +*/ +#if defined(_WIN32) +# define HAVE_SPAWN 1 #else -# define NEED_SPAWN 1 +# define NEED_SPAWN 1 #endif -#if defined(_MSC_VER) -# pragma warning(disable : 4996) + +/* GCC strictly follows http://c-faq.com/ansi/constmismatch.html and issues an +** 'incompatible pointer type' warning - that can't be suppressed via #pragma. +** The spawnvp() prototype of MinGW (http://www.mingw.org/) differs from the +** one of MinGW-w64 (http://mingw-w64.sourceforge.net/) regarding constness. +** So there's no alternative to actually distinguish these environments :-( +*/ +#define SPAWN_ARGV_CONST_CAST +#if defined(__MINGW32__) +# include <_mingw.h> +# if !defined(__MINGW64_VERSION_MAJOR) +# undef SPAWN_ARGV_CONST_CAST +# define SPAWN_ARGV_CONST_CAST (const char* const *) +# endif #endif @@ -51,7 +63,7 @@ #include <string.h> #include <ctype.h> #include <errno.h> -#ifdef HAVE_SPAWN +#if defined(HAVE_SPAWN) # include <process.h> #endif @@ -110,8 +122,8 @@ static const char* OutputName = 0; static const char* LinkerConfig = 0; /* The name of the first input file. This will be used to construct the - * executable file name if no explicit name is given. - */ +** executable file name if no explicit name is given. +*/ static const char* FirstInput = 0; /* The names of the files for dependency generation */ @@ -214,8 +226,8 @@ static void CmdAddArgList (CmdDesc* Cmd, const char* ArgList) ++Cmd->ArgCount; /* If the argument was terminated by a comma, skip it, otherwise - * we're done. - */ + ** we're done. + */ if (*P == ',') { /* Start over at next char */ Arg = ++P; @@ -258,10 +270,10 @@ static void CmdAddFile (CmdDesc* Cmd, const char* File) } /* If the file name is not NULL (which is legal and is used to terminate - * the file list), check if the file name does already exist in the file - * list and print a warning if so. Regardless of the search result, add - * the file. - */ + ** the file list), check if the file name does already exist in the file + ** list and print a warning if so. Regardless of the search result, add + ** the file. + */ if (File) { unsigned I; for (I = 0; I < Cmd->FileCount; ++I) { @@ -375,7 +387,7 @@ static void ExecProgram (CmdDesc* Cmd) } /* Call the program */ - Status = spawnvp (P_WAIT, Cmd->Name, Cmd->Args); + Status = spawnvp (P_WAIT, Cmd->Name, SPAWN_ARGV_CONST_CAST Cmd->Args); /* Check the result code */ if (Status < 0) { @@ -395,9 +407,9 @@ static void Link (void) unsigned I; /* Since linking is always the final step, if we have an output file name - * given, set it here. If we don't have an explicit output name given, - * try to build one from the name of the first input file. - */ + ** given, set it here. If we don't have an explicit output name given, + ** try to build one from the name of the first input file. + */ if (OutputName) { CmdSetOutput (&LD65, OutputName); @@ -412,8 +424,8 @@ static void Link (void) } /* If we have a linker config file given, add it to the command line. - * Otherwise pass the target to the linker if we have one. - */ + ** Otherwise pass the target to the linker if we have one. + */ if (LinkerConfig) { if (Module) { Error ("Cannot use -C and --module together"); @@ -449,9 +461,9 @@ static void Link (void) static void AssembleFile (const char* File, unsigned ArgCount) /* Common routine to assemble a file. Will be called by Assemble() and - * AssembleIntermediate(). Adds options common for both routines and - * assembles the file. Will remove excess arguments after assembly. - */ +** AssembleIntermediate(). Adds options common for both routines and +** assembles the file. Will remove excess arguments after assembly. +*/ { /* Set the target system */ CmdSetTarget (&CA65, Target); @@ -459,9 +471,9 @@ static void AssembleFile (const char* File, unsigned ArgCount) /* Check if this is the last processing step */ if (DoLink) { /* We're linking later. Add the output file of the assembly - * the the file list of the linker. The name of the output - * file is that of the input file with ".s" replaced by ".o". - */ + ** the the file list of the linker. The name of the output + ** file is that of the input file with ".s" replaced by ".o". + */ char* ObjName = MakeFilename (File, ".o"); CmdAddFile (&LD65, ObjName); xfree (ObjName); @@ -489,13 +501,13 @@ static void AssembleFile (const char* File, unsigned ArgCount) static void AssembleIntermediate (const char* SourceFile) /* Assemble an intermediate file which was generated by a previous processing - * step with SourceFile as input. The -dep options won't be added and - * the intermediate assembler file is removed after assembly. - */ +** step with SourceFile as input. The -dep options won't be added and +** the intermediate assembler file is removed after assembly. +*/ { /* Generate the name of the assembler output file from the source file - * name. It's the same name with the extension replaced by ".s" - */ + ** name. It's the same name with the extension replaced by ".s" + */ char* AsmName = MakeFilename (SourceFile, ".s"); /* Assemble the intermediate assembler file */ @@ -520,9 +532,9 @@ static void Assemble (const char* File) unsigned ArgCount = CA65.ArgCount; /* We aren't assembling an intermediate file, but one requested by the - * user. So add a few options here if they were given on the command - * line. - */ + ** user. So add a few options here if they were given on the command + ** line. + */ if (DepName && *DepName) { CmdAddArg2 (&CA65, "--create-dep", DepName); } @@ -548,10 +560,10 @@ static void Compile (const char* File) /* Check if this is the final step */ if (DoAssemble) { /* We will assemble this file later. If a dependency file is to be - * generated, set the dependency target to be the final object file, - * not the intermediate assembler file. But beware: There may be an - * output name specified for the assembler. - */ + ** generated, set the dependency target to be the final object file, + ** not the intermediate assembler file. But beware: There may be an + ** output name specified for the assembler. + */ if (DepName || FullDepName) { /* Was an output name for the assembler specified? */ if (!DoLink && OutputName) { @@ -566,8 +578,8 @@ static void Compile (const char* File) } } else { /* If we won't assemble, this is the final step. In this case, set - * the output name if it was given. - */ + ** the output name if it was given. + */ if (OutputName) { CmdSetOutput (&CC65, OutputName); } @@ -586,8 +598,8 @@ static void Compile (const char* File) CmdDelArgs (&CC65, ArgCount); /* If this is not the final step, assemble the generated file, then - * remove it - */ + ** remove it + */ if (DoAssemble) { /* Assemble the intermediate file and remove it */ AssembleIntermediate (File); @@ -603,8 +615,8 @@ static void CompileRes (const char* File) unsigned ArgCount = GRC.ArgCount; /* Resource files need an geos-apple or geos-cbm target but this - * is checked within grc65. - */ + ** is checked within grc65. + */ CmdSetTarget (&GRC, Target); /* Add the file as argument for the resource compiler */ @@ -620,8 +632,8 @@ static void CompileRes (const char* File) CmdDelArgs (&GRC, ArgCount); /* If this is not the final step, assemble the generated file, then - * remove it - */ + ** remove it + */ if (DoAssemble) { /* Assemble the intermediate file and remove it */ AssembleIntermediate (File); @@ -637,8 +649,8 @@ static void ConvertO65 (const char* File) unsigned ArgCount = CO65.ArgCount; /* If we won't assemble, this is the final step. In this case, set the - * output name. - */ + ** output name. + */ if (!DoAssemble && OutputName) { CmdSetOutput (&CO65, OutputName); } @@ -656,8 +668,8 @@ static void ConvertO65 (const char* File) CmdDelArgs (&CO65, ArgCount); /* If this is not the final step, assemble the generated file, then - * remove it - */ + ** remove it + */ if (DoAssemble) { /* Assemble the intermediate file and remove it */ AssembleIntermediate (File); @@ -1526,6 +1538,3 @@ int main (int argc, char* argv []) /* Return an apropriate exit code */ return EXIT_SUCCESS; } - - - diff --git a/src/cl65/spawn-amiga.inc b/src/cl65/spawn-amiga.inc index 4a0278cfa..5d1b60ea3 100644 --- a/src/cl65/spawn-amiga.inc +++ b/src/cl65/spawn-amiga.inc @@ -82,6 +82,3 @@ int spawnvp (int Mode attribute ((unused)), /* Return the result */ return Status; } - - - diff --git a/src/cl65/spawn-unix.inc b/src/cl65/spawn-unix.inc index a0334b8db..fc5125c34 100644 --- a/src/cl65/spawn-unix.inc +++ b/src/cl65/spawn-unix.inc @@ -103,6 +103,3 @@ int spawnvp (int Mode attribute ((unused)), const char* File, char* const argv [ */ return WEXITSTATUS (Status); } - - - diff --git a/src/cl65/spawn.h b/src/cl65/spawn.h deleted file mode 100644 index 6e75f555d..000000000 --- a/src/cl65/spawn.h +++ /dev/null @@ -1,75 +0,0 @@ -/*****************************************************************************/ -/* */ -/* spawn.h */ -/* */ -/* Execute other external programs */ -/* */ -/* */ -/* */ -/* (C) 1999 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ -/* */ -/* */ -/* This software is provided 'as-is', without any expressed or implied */ -/* warranty. In no event will the authors be held liable for any damages */ -/* arising from the use of this software. */ -/* */ -/* Permission is granted to anyone to use this software for any purpose, */ -/* including commercial applications, and to alter it and redistribute it */ -/* freely, subject to the following restrictions: */ -/* */ -/* 1. The origin of this software must not be misrepresented; you must not */ -/* claim that you wrote the original software. If you use this software */ -/* in a product, an acknowledgment in the product documentation would be */ -/* appreciated but is not required. */ -/* 2. Altered source versions must be plainly marked as such, and must not */ -/* be misrepresented as being the original software. */ -/* 3. This notice may not be removed or altered from any source */ -/* distribution. */ -/* */ -/*****************************************************************************/ - - - -#ifndef SPAWN_H -#define SPAWN_H - - - -/*****************************************************************************/ -/* Data */ -/*****************************************************************************/ - - - -/* Mode argument for spawn. This value is ignored by the function and only - * provided for DOS/Windows compatibility. - */ -#ifndef P_WAIT -#define P_WAIT 0 -#endif - - - -/*****************************************************************************/ -/* Code */ -/*****************************************************************************/ - - - -int spawnvp (int Mode, const char* File, char* const argv []); -/* Execute the given program searching and wait til it terminates. The Mode - * argument is ignored (compatibility only). The result of the function is - * the return code of the program. The function will terminate the program - * on errors. - */ - - - -/* End of spawn.h */ -#endif - - - diff --git a/src/co65.vcxproj b/src/co65.vcxproj index 7560cb866..c66c8aac8 100644 --- a/src/co65.vcxproj +++ b/src/co65.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -18,10 +18,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -47,7 +49,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> @@ -62,7 +64,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> diff --git a/src/co65/convert.c b/src/co65/convert.c index 6ae051091..af036ebf7 100644 --- a/src/co65/convert.c +++ b/src/co65/convert.c @@ -114,9 +114,9 @@ static const char* LabelPlusOffs (const char* Label, long Offs) static const char* RelocExpr (const O65Data* D, unsigned char SegID, unsigned long Val, const O65Reloc* R) /* Generate the segment relative relocation expression. R is only used if the - * expression contains am import, and may be NULL if this is an error (which - * is then flagged). - */ +** expression contains am import, and may be NULL if this is an error (which +** is then flagged). +*/ { const O65Import* Import; @@ -346,10 +346,10 @@ static void ConvertZeropageSeg (FILE* F, const O65Data* D) if (Model == O65_MODEL_CC65_MODULE) { /* o65 files of type cc65-module are linked together with a definition - * file for the zero page, but the zero page is not allocated in the - * module itself, but the locations are mapped to the zp locations of - * the main file. - */ + ** file for the zero page, but the zero page is not allocated in the + ** module itself, but the locations are mapped to the zp locations of + ** the main file. + */ fprintf (F, ".import\t__ZP_START__\t\t; Linker generated symbol\n"); fprintf (F, "%s = __ZP_START__\n", ZeropageLabel); } else { @@ -372,8 +372,8 @@ void Convert (const O65Data* D) char* Author = 0; /* For now, we do only accept o65 files generated by the ld65 linker which - * have a specific format. - */ + ** have a specific format. + */ if (!Debug && D->Header.mode != O65_MODE_CC65) { Error ("Cannot convert o65 files of this type"); } @@ -382,9 +382,9 @@ void Convert (const O65Data* D) PrintO65Stats (D); /* Walk through the options and print them if verbose mode is enabled. - * Check for a os=cc65 option and bail out if we didn't find one (for - * now - later we switch to special handling). - */ + ** Check for a os=cc65 option and bail out if we didn't find one (for + ** now - later we switch to special handling). + */ for (I = 0; I < CollCount (&D->Options); ++I) { /* Get the next option */ @@ -502,6 +502,3 @@ void Convert (const O65Data* D) fprintf (F, ".end\n"); fclose (F); } - - - diff --git a/src/co65/convert.h b/src/co65/convert.h index f000f55c4..22ef25424 100644 --- a/src/co65/convert.h +++ b/src/co65/convert.h @@ -63,6 +63,3 @@ void Convert (const struct O65Data* D); /* End of convert.h */ #endif - - - diff --git a/src/co65/error.c b/src/co65/error.c index 5ee75661b..1c1625207 100644 --- a/src/co65/error.c +++ b/src/co65/error.c @@ -89,6 +89,3 @@ void Internal (const char* Format, ...) va_end (ap); exit (EXIT_FAILURE); } - - - diff --git a/src/co65/error.h b/src/co65/error.h index 1b3060a84..4fb9d370d 100644 --- a/src/co65/error.h +++ b/src/co65/error.h @@ -63,6 +63,3 @@ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)) /* End of error.h */ #endif - - - diff --git a/src/co65/fileio.c b/src/co65/fileio.c index 4846add3f..9241797c6 100644 --- a/src/co65/fileio.c +++ b/src/co65/fileio.c @@ -103,6 +103,3 @@ void* ReadData (FILE* F, void* Data, unsigned Size) } return Data; } - - - diff --git a/src/co65/fileio.h b/src/co65/fileio.h index ccae88020..c5e9a003c 100644 --- a/src/co65/fileio.h +++ b/src/co65/fileio.h @@ -71,6 +71,3 @@ void* ReadData (FILE* F, void* Data, unsigned Size); /* End of fileio.h */ #endif - - - diff --git a/src/co65/global.c b/src/co65/global.c index 38748cc0e..bc9b0099b 100644 --- a/src/co65/global.c +++ b/src/co65/global.c @@ -69,6 +69,3 @@ const char* ZeropageLabel = 0; /* Label for the zeropage segmen /* Flags */ unsigned char DebugInfo = 0; /* Enable debug info */ unsigned char NoOutput = 0; /* Suppress the actual conversion */ - - - diff --git a/src/co65/global.h b/src/co65/global.h index 247b9de45..29c17ca29 100644 --- a/src/co65/global.h +++ b/src/co65/global.h @@ -72,6 +72,3 @@ extern unsigned char NoOutput; /* Suppress the actual conversion */ /* End of global.h */ #endif - - - diff --git a/src/co65/main.c b/src/co65/main.c index 79aca87fa..5e0ee2ed7 100644 --- a/src/co65/main.c +++ b/src/co65/main.c @@ -412,6 +412,3 @@ int main (int argc, char* argv []) /* Return an apropriate exit code */ return EXIT_SUCCESS; } - - - diff --git a/src/co65/model.c b/src/co65/model.c index 365eed49d..87a6966b7 100644 --- a/src/co65/model.c +++ b/src/co65/model.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -80,8 +80,8 @@ const char* GetModelName (O65Model M) O65Model FindModel (const char* ModelName) /* Map a model name to its identifier. Return O65_MODEL_INVALID if the name - * could not be found. Case is ignored when comparing names. - */ +** could not be found. Case is ignored when comparing names. +*/ { O65Model M; for (M = O65_MODEL_NONE; M < O65_MODEL_COUNT; ++M) { @@ -91,6 +91,3 @@ O65Model FindModel (const char* ModelName) } return O65_MODEL_INVALID; } - - - diff --git a/src/co65/model.h b/src/co65/model.h index 1f44b89b4..e727d0647 100644 --- a/src/co65/model.h +++ b/src/co65/model.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -73,14 +73,11 @@ const char* GetModelName (O65Model M); O65Model FindModel (const char* ModelName); /* Map a model name to its identifier. Return O65_MODEL_INVALID if the name - * could not be found. Case is ignored when comparing names. - */ +** could not be found. Case is ignored when comparing names. +*/ /* End of model.h */ #endif - - - diff --git a/src/co65/o65.c b/src/co65/o65.c index 187e4fc38..3496995a8 100644 --- a/src/co65/o65.c +++ b/src/co65/o65.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2002-2004 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -83,8 +83,8 @@ static O65Data* NewO65Data (void) static unsigned long ReadO65Size (FILE* F, const O65Header* H) /* Read a size variable (16 or 32 bit, depending on the mode word in the - * header) from the o65 file. - */ +** header) from the o65 file. +*/ { unsigned long Size = 0; /* Initialize to avoid warnings */ switch (H->mode & O65_SIZE_MASK) { @@ -99,8 +99,8 @@ static unsigned long ReadO65Size (FILE* F, const O65Header* H) static void ReadO65Header (FILE* F, O65Header* H) /* Read an o65 header from the given file. The function will call Error if - * something is wrong. - */ +** something is wrong. +*/ { static const char Magic[3] = { O65_MAGIC_0, O65_MAGIC_1, O65_MAGIC_2 /* "o65" */ @@ -145,9 +145,9 @@ static void ReadO65Header (FILE* F, O65Header* H) static O65Option* ReadO65Option (FILE* F) /* Read the next O65 option from the given file. The option is stored into a - * dynamically allocated O65Option struct which is returned. On end of options, - * NULL is returned. On error, Error is called which terminates the program. - */ +** dynamically allocated O65Option struct which is returned. On end of options, +** NULL is returned. On error, Error is called which terminates the program. +*/ { O65Option* O; @@ -304,8 +304,8 @@ static O65Export* ReadO65Export (FILE* F, const O65Header* H) static O65Data* ReadO65Data (FILE* F) /* Read a complete o65 file into dynamically allocated memory and return the - * created O65Data struct. - */ +** created O65Data struct. +*/ { unsigned long Count; O65Option* O; @@ -353,8 +353,8 @@ static O65Data* ReadO65Data (FILE* F) O65Data* ReadO65File (const char* Name) /* Read a complete o65 file into dynamically allocated memory and return the - * created O65Data struct. - */ +** created O65Data struct. +*/ { O65Data* D; @@ -391,9 +391,9 @@ const char* GetO65OSName (unsigned char OS) const char* GetO65OptionText (const O65Option* O) /* Return the data of the given option as a readable text. The function returns - * a pointer to a static buffer that is reused on the next call, so if in doubt, - * make a copy (and no, the function is not thread safe). - */ +** a pointer to a static buffer that is reused on the next call, so if in doubt, +** make a copy (and no, the function is not thread safe). +*/ { static char Buf[256]; unsigned I, J; @@ -434,6 +434,3 @@ const char* GetO65OptionText (const O65Option* O) Buf[I] = '\0'; return Buf; } - - - diff --git a/src/co65/o65.h b/src/co65/o65.h index 6fb8433c5..dd0ea61b7 100644 --- a/src/co65/o65.h +++ b/src/co65/o65.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2002-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -34,12 +34,12 @@ /* This files exports structures and constants to handle the o65 relocatable - * file format as defined by Andre Fachat. See the original document under - * - * http://www.6502.org/users/andre/o65/fileformat.html - * - * for more information. - */ +** file format as defined by Andre Fachat. See the original document under +** +** http://www.6502.org/users/andre/o65/fileformat.html +** +** for more information. +*/ @@ -215,23 +215,20 @@ struct O65Data { O65Data* ReadO65File (const char* Name); /* Read a complete o65 file into dynamically allocated memory and return the - * created O65Data struct. - */ +** created O65Data struct. +*/ const char* GetO65OSName (unsigned char OS); /* Return the name of the operating system given by OS */ const char* GetO65OptionText (const O65Option* O); /* Return the data of the given option as a readable text. The function returns - * a pointer to a static buffer that is reused on the next call, so if in doubt, - * make a copy (and no, the function is not thread safe). - */ +** a pointer to a static buffer that is reused on the next call, so if in doubt, +** make a copy (and no, the function is not thread safe). +*/ /* End of o65.h */ + #endif - - - - diff --git a/src/common.vcxproj b/src/common.vcxproj index a386d0c06..053d23981 100644 --- a/src/common.vcxproj +++ b/src/common.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -113,11 +113,13 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -143,7 +145,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_LIB;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_LIB;_DEBUG</PreprocessorDefinitions> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> @@ -161,7 +163,7 @@ <PrecompiledHeader> </PrecompiledHeader> <FunctionLevelLinking>true</FunctionLevelLinking> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_LIB;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_LIB;NDEBUG</PreprocessorDefinitions> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> diff --git a/src/common/abend.c b/src/common/abend.c index 0213bdde7..278ab1a00 100644 --- a/src/common/abend.c +++ b/src/common/abend.c @@ -50,8 +50,8 @@ void AbEnd (const char* Format, ...) /* Print a message preceeded by the program name and terminate the program - * with an error exit code. - */ +** with an error exit code. +*/ { va_list ap; @@ -69,6 +69,3 @@ void AbEnd (const char* Format, ...) /* Terminate the program */ exit (EXIT_FAILURE); } - - - diff --git a/src/common/abend.h b/src/common/abend.h index f32a3381d..a23285782 100644 --- a/src/common/abend.h +++ b/src/common/abend.h @@ -50,14 +50,11 @@ void AbEnd (const char* Format, ...) attribute ((format (printf, 1, 2), noreturn)); /* Print a message preceeded by the program name and terminate the program - * with an error exit code. - */ +** with an error exit code. +*/ /* End of abend.h */ #endif - - - diff --git a/src/common/addrsize.c b/src/common/addrsize.c index ad54618e6..d4eff22bb 100644 --- a/src/common/addrsize.c +++ b/src/common/addrsize.c @@ -62,8 +62,8 @@ const char* AddrSizeToStr (unsigned char AddrSize) unsigned char AddrSizeFromStr (const char* Str) /* Return the address size for a given string. Returns ADDR_SIZE_INVALID if - * the string cannot be mapped to an address size. - */ +** the string cannot be mapped to an address size. +*/ { static const struct { const char* Name; @@ -92,6 +92,3 @@ unsigned char AddrSizeFromStr (const char* Str) /* Not found */ return ADDR_SIZE_INVALID; } - - - diff --git a/src/common/addrsize.h b/src/common/addrsize.h index d2c871e3f..e2e0fa9bb 100644 --- a/src/common/addrsize.h +++ b/src/common/addrsize.h @@ -64,14 +64,11 @@ const char* AddrSizeToStr (unsigned char AddrSize); unsigned char AddrSizeFromStr (const char* Str); /* Return the address size for a given string. Returns ADDR_SIZE_INVALID if - * the string cannot be mapped to an address size. - */ +** the string cannot be mapped to an address size. +*/ /* End of addrsize.h */ #endif - - - diff --git a/src/common/alignment.c b/src/common/alignment.c index 9dad01d3e..c61658a25 100644 --- a/src/common/alignment.c +++ b/src/common/alignment.c @@ -46,9 +46,9 @@ /* To factorize an alignment, we will use the following prime table. It lists - * all primes up to 256, which means we're able to factorize alignments up to - * 0x10000. This is checked in the code. - */ +** all primes up to 256, which means we're able to factorize alignments up to +** 0x10000. This is checked in the code. +*/ static const unsigned char Primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, @@ -138,8 +138,8 @@ static void Factorize (unsigned long Value, FactorizedNumber* F) unsigned long LeastCommonMultiple (unsigned long Left, unsigned long Right) /* Calculate the least common multiple of two numbers and return - * the result. - */ +** the result. +*/ { unsigned I; FactorizedNumber L, R; @@ -150,11 +150,11 @@ unsigned long LeastCommonMultiple (unsigned long Left, unsigned long Right) Factorize (Right, &R); /* Generate the result from the factors. - * Some thoughts on range problems: Since the largest numbers we can - * factorize are 2^16 (0x10000), the only numbers that could produce an - * overflow when using 32 bits are exactly these. But the LCM for 2^16 - * and 2^16 is 2^16 so this will never happen and we're safe. - */ + ** Some thoughts on range problems: Since the largest numbers we can + ** factorize are 2^16 (0x10000), the only numbers that could produce an + ** overflow when using 32 bits are exactly these. But the LCM for 2^16 + ** and 2^16 is 2^16 so this will never happen and we're safe. + */ Res = L.Remainder * R.Remainder; for (I = 0; I < PRIME_COUNT; ++I) { unsigned P = (L.Powers[I] > R.Powers[I])? L.Powers[I] : R.Powers[I]; @@ -182,6 +182,3 @@ unsigned long AlignCount (unsigned long Addr, unsigned long Alignment) { return AlignAddr (Addr, Alignment) - Addr; } - - - diff --git a/src/common/alignment.h b/src/common/alignment.h index 6e8ffa373..b77cd4113 100644 --- a/src/common/alignment.h +++ b/src/common/alignment.h @@ -50,13 +50,13 @@ /* Maximum possible alignment. Beware: To increase the possible alignment it - * is not enough to bump this value. Check the code inside. - */ +** is not enough to bump this value. Check the code inside. +*/ #define MAX_ALIGNMENT 0x10000UL /* The following value marks what is considered a "large alignment" and worth - * a warning if not suppressed. - */ +** a warning if not suppressed. +*/ #define LARGE_ALIGNMENT 0x101UL @@ -69,8 +69,8 @@ unsigned long LeastCommonMultiple (unsigned long Left, unsigned long Right); /* Calculate the least common multiple of two numbers and return - * the result. - */ +** the result. +*/ unsigned long AlignAddr (unsigned long Addr, unsigned long Alignment); /* Align an address to the given alignment */ @@ -83,6 +83,3 @@ unsigned long AlignCount (unsigned long Addr, unsigned long Alignment); /* End of alignment.h */ #endif - - - diff --git a/src/common/assertion.c b/src/common/assertion.c index d854c95f1..dbce8562f 100644 --- a/src/common/assertion.c +++ b/src/common/assertion.c @@ -58,6 +58,3 @@ int AssertAtAsmTime (AssertAction A) { return (A & 0x02U) == 0; } - - - diff --git a/src/common/assertion.h b/src/common/assertion.h index 3f41161be..7cb425e8c 100644 --- a/src/common/assertion.h +++ b/src/common/assertion.h @@ -71,6 +71,3 @@ int AssertAtAsmTime (AssertAction A); /* End of assertion.h */ #endif - - - diff --git a/src/common/attrib.h b/src/common/attrib.h index ff963f9c5..07e08b2df 100644 --- a/src/common/attrib.h +++ b/src/common/attrib.h @@ -55,6 +55,3 @@ /* End of attrib.h */ #endif - - - diff --git a/src/common/bitops.c b/src/common/bitops.c index 86633604b..9eba961b7 100644 --- a/src/common/bitops.c +++ b/src/common/bitops.c @@ -123,6 +123,3 @@ void BitMerge (void* Target, const void* Source, unsigned Size) *T++ |= *S++; } } - - - diff --git a/src/common/bitops.h b/src/common/bitops.h index ade1d1e4e..71186ba51 100644 --- a/src/common/bitops.h +++ b/src/common/bitops.h @@ -71,6 +71,3 @@ void BitMerge (void* Target, const void* Source, unsigned Size); /* End of bitops.h */ #endif - - - diff --git a/src/common/cddefs.h b/src/common/cddefs.h index 7b3dc5b99..c44ec7b52 100644 --- a/src/common/cddefs.h +++ b/src/common/cddefs.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2000-2004 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -50,8 +50,8 @@ #define CD_TYPE_MAX 6 /* Maximum numeric type value */ /* ConDes priorities, zero is no valid priority and used to mark an empty - * (missing) decl for this type throughout the code. - */ +** (missing) decl for this type throughout the code. +*/ #define CD_PRIO_NONE 0 /* No priority (no decl) */ #define CD_PRIO_MIN 1 /* Lowest priority */ #define CD_PRIO_DEF 7 /* Default priority */ @@ -63,8 +63,8 @@ #define CD_TYPE_INT 2 /* Interruptor */ /* When part of an export in an object file, type and priority are encoded in - * one byte. In this case, the following macros access the fields: - */ +** one byte. In this case, the following macros access the fields: +*/ #define CD_GET_TYPE(v) (((v) >> 5) & 0x07) #define CD_GET_PRIO(v) (((v) & 0x1F) + 1) @@ -76,6 +76,3 @@ /* End of cddefs.h */ #endif - - - diff --git a/src/common/chartype.c b/src/common/chartype.c index 4b8fa9e3d..b55fcfb19 100644 --- a/src/common/chartype.c +++ b/src/common/chartype.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2000-2004 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -38,13 +38,13 @@ /* This module contains replacements for functions in ctype.h besides other - * functions. There is a problem with using ctype.h directly: - * The parameter must have a value of "unsigned char" or EOF. - * So on platforms where a char is signed, this may give problems or at - * least warnings. The wrapper functions below will have an "char" parameter - * but handle it correctly. They will NOT work for EOF, but this is not a - * problem, since EOF is always handled separately. - */ +** functions. There is a problem with using ctype.h directly: +** The parameter must have a value of "unsigned char" or EOF. +** So on platforms where a char is signed, this may give problems or at +** least warnings. The wrapper functions below will have an "char" parameter +** but handle it correctly. They will NOT work for EOF, but this is not a +** problem, since EOF is always handled separately. +*/ @@ -147,6 +147,3 @@ int IsQuote (char C) { return (C == '"' || C == '\''); } - - - diff --git a/src/common/chartype.h b/src/common/chartype.h index 6c38d98c8..5278dbc59 100644 --- a/src/common/chartype.h +++ b/src/common/chartype.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2000-2004 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -45,13 +45,13 @@ /* This module contains replacements for functions in ctype.h besides other - * functions. There is a problem with using ctype.h directly: - * The parameter must have a value of "unsigned char" or EOF. - * So on platforms where a char is signed, this may give problems or at - * least warnings. The wrapper functions below will have an "char" parameter - * but handle it correctly. They will NOT work for EOF, but this is not a - * problem, since EOF is always handled separately. - */ +** functions. There is a problem with using ctype.h directly: +** The parameter must have a value of "unsigned char" or EOF. +** So on platforms where a char is signed, this may give problems or at +** least warnings. The wrapper functions below will have an "char" parameter +** but handle it correctly. They will NOT work for EOF, but this is not a +** problem, since EOF is always handled separately. +*/ @@ -112,6 +112,3 @@ int IsQuote (char C); /* End of chartype.h */ #endif - - - diff --git a/src/common/check.c b/src/common/check.c index cb4589bf9..c6c5d2d95 100644 --- a/src/common/check.c +++ b/src/common/check.c @@ -77,6 +77,3 @@ static void DefaultCheckFailed (const char* Msg, const char* Cond, /* Output a diagnostic and abort */ AbEnd ("%s%s, file `%s', line %u", Msg, Cond, File, Line); } - - - diff --git a/src/common/check.h b/src/common/check.h index 3f26be79c..738fa2626 100644 --- a/src/common/check.h +++ b/src/common/check.h @@ -73,9 +73,9 @@ extern void (*CheckFailed) (const char* Msg, const char* Cond, #define ABORT(s) CheckFailed (MsgProgramAborted, s, __FILE__, __LINE__) /* Use this one instead of FAIL if there is no internal program error but an - * error condition that is caused by the user or operating system (FAIL and - * ABORT are essentially the same but the message differs). - */ +** error condition that is caused by the user or operating system (FAIL and +** ABORT are essentially the same but the message differs). +*/ #define PRECONDITION(c) \ ((void) ((c)? 0 : (CheckFailed (MsgPrecondition, #c, __FILE__, __LINE__), 0))) @@ -86,7 +86,5 @@ extern void (*CheckFailed) (const char* Msg, const char* Cond, /* End of check.h */ + #endif - - - diff --git a/src/common/cmdline.c b/src/common/cmdline.c index 13a9da061..716df1efb 100644 --- a/src/common/cmdline.c +++ b/src/common/cmdline.c @@ -106,8 +106,8 @@ static void AddArg (CmdLine* L, char* Arg) static void ExpandFile (CmdLine* L, const char* Name) /* Add the contents of a file to the command line. Each line is a separate - * argument with leading and trailing whitespace removed. - */ +** argument with leading and trailing whitespace removed. +*/ { char Buf [256]; @@ -124,8 +124,8 @@ static void ExpandFile (CmdLine* L, const char* Name) const char* B = Buf; /* Skip trailing whitespace (this will also kill the newline that is - * appended by fgets(). - */ + ** appended by fgets(). + */ unsigned Len = strlen (Buf); while (Len > 0 && IsSpace (Buf [Len-1])) { --Len; @@ -148,8 +148,8 @@ static void ExpandFile (CmdLine* L, const char* Name) } /* Close the file, ignore errors here since we had the file open for - * reading only. - */ + ** reading only. + */ (void) fclose (F); } @@ -163,9 +163,9 @@ static void ExpandFile (CmdLine* L, const char* Name) void InitCmdLine (int* aArgCount, char** aArgVec[], const char* aProgName) /* Initialize command line parsing. aArgVec is the argument array terminated by - * a NULL pointer (as usual), ArgCount is the number of valid arguments in the - * array. Both arguments are remembered in static storage. - */ +** a NULL pointer (as usual), ArgCount is the number of valid arguments in the +** array. Both arguments are remembered in static storage. +*/ { CmdLine L; int I; @@ -187,9 +187,9 @@ void InitCmdLine (int* aArgCount, char** aArgVec[], const char* aProgName) NewCmdLine (&L); /* Walk over the parameters and add them to the CmdLine struct. Add a - * special handling for arguments preceeded by the '@' sign - these are - * actually files containing arguments. - */ + ** special handling for arguments preceeded by the '@' sign - these are + ** actually files containing arguments. + */ for (I = 0; I < *aArgCount; ++I) { /* Get the next argument */ @@ -254,8 +254,8 @@ void InvDef (const char* Def) const char* GetArg (unsigned* ArgNum, unsigned Len) /* Get an argument for a short option. The argument may be appended to the - * option itself or may be separate. Len is the length of the option string. - */ +** option itself or may be separate. Len is the length of the option string. +*/ { const char* Arg = ArgVec[*ArgNum]; if (Arg[Len] != '\0') { @@ -307,7 +307,3 @@ void LongOption (unsigned* ArgNum, const LongOpt* OptTab, unsigned OptCount) /* Invalid option */ UnknownOption (Opt); } - - - - diff --git a/src/common/cmdline.h b/src/common/cmdline.h index b3a483b6b..b18906c7a 100644 --- a/src/common/cmdline.h +++ b/src/common/cmdline.h @@ -73,9 +73,9 @@ struct LongOpt { void InitCmdLine (int* aArgCount, char** aArgVec[], const char* aProgName); /* Initialize command line parsing. aArgVec is the argument array terminated by - * a NULL pointer (as usual), ArgCount is the number of valid arguments in the - * array. Both arguments are remembered in static storage. - */ +** a NULL pointer (as usual), ArgCount is the number of valid arguments in the +** array. Both arguments are remembered in static storage. +*/ void UnknownOption (const char* Opt) attribute ((noreturn)); /* Print an error about an unknown option and die. */ @@ -91,8 +91,8 @@ void InvDef (const char* Def) attribute ((noreturn)); const char* GetArg (unsigned* ArgNum, unsigned Len); /* Get an argument for a short option. The argument may be appended to the - * option itself or may be separate. Len is the length of the option string. - */ +** option itself or may be separate. Len is the length of the option string. +*/ void LongOption (unsigned* ArgNum, const LongOpt* OptTab, unsigned OptCount); /* Handle a long command line option */ @@ -102,6 +102,3 @@ void LongOption (unsigned* ArgNum, const LongOpt* OptTab, unsigned OptCount); /* End of cmdline.h */ #endif - - - diff --git a/src/common/coll.c b/src/common/coll.c index 5112157aa..aa2aa6470 100644 --- a/src/common/coll.c +++ b/src/common/coll.c @@ -78,8 +78,8 @@ Collection* InitCollection (Collection* C) void DoneCollection (Collection* C) /* Free the data for a collection. This will not free the data contained in - * the collection. - */ +** the collection. +*/ { /* Free the pointer array */ xfree (C->Items); @@ -110,9 +110,9 @@ void FreeCollection (Collection* C) void CollGrow (Collection* C, unsigned Size) /* Grow the collection C so it is able to hold Size items without a resize - * being necessary. This can be called for performance reasons if the number - * of items to be placed in the collection is known in advance. - */ +** being necessary. This can be called for performance reasons if the number +** of items to be placed in the collection is known in advance. +*/ { void** NewItems; @@ -225,8 +225,8 @@ const void* CollConstLast (const Collection* C) #if !defined(HAVE_INLINE) void* CollPop (Collection* C) /* Remove the last segment from the stack and return it. Calls FAIL if the - * collection is empty. - */ +** collection is empty. +*/ { /* We must have at least one entry */ PRECONDITION (C->Count > 0); @@ -240,8 +240,8 @@ void* CollPop (Collection* C) int CollIndex (Collection* C, const void* Item) /* Return the index of the given item in the collection. Return -1 if the - * item was not found in the collection. - */ +** item was not found in the collection. +*/ { /* Linear search */ unsigned I; @@ -260,9 +260,9 @@ int CollIndex (Collection* C, const void* Item) void CollDelete (Collection* C, unsigned Index) /* Remove the item with the given index from the collection. This will not - * free the item itself, just the pointer. All items with higher indices - * will get moved to a lower position. - */ +** free the item itself, just the pointer. All items with higher indices +** will get moved to a lower position. +*/ { /* Check the index */ PRECONDITION (Index < C->Count); @@ -276,8 +276,8 @@ void CollDelete (Collection* C, unsigned Index) void CollDeleteItem (Collection* C, const void* Item) /* Delete the item pointer from the collection. The item must be in the - * collection, otherwise FAIL will be called. - */ +** collection, otherwise FAIL will be called. +*/ { /* Get the index of the entry */ int Index = CollIndex (C, Item); @@ -293,8 +293,8 @@ void CollDeleteItem (Collection* C, const void* Item) #if !defined(HAVE_INLINE) void CollReplace (Collection* C, void* Item, unsigned Index) /* Replace the item at the given position. The old item will not be freed, - * just the pointer will get replaced. - */ +** just the pointer will get replaced. +*/ { /* Check the index */ PRECONDITION (Index < C->Count); @@ -308,10 +308,10 @@ void CollReplace (Collection* C, void* Item, unsigned Index) void CollReplaceExpand (Collection* C, void* Item, unsigned Index) /* If Index is a valid index for the collection, replace the item at this - * position by the one passed. If the collection is too small, expand it, - * filling unused pointers with NULL, then add the new item at the given - * position. - */ +** position by the one passed. If the collection is too small, expand it, +** filling unused pointers with NULL, then add the new item at the given +** position. +*/ { if (Index < C->Count) { /* Collection is already large enough */ @@ -341,10 +341,10 @@ void CollReplaceExpand (Collection* C, void* Item, unsigned Index) void CollMove (Collection* C, unsigned OldIndex, unsigned NewIndex) /* Move an item from one position in the collection to another. OldIndex - * is the current position of the item, NewIndex is the new index after - * the function has done it's work. Existing entries with indices NewIndex - * and up are moved one position upwards. - */ +** is the current position of the item, NewIndex is the new index after +** the function has done it's work. Existing entries with indices NewIndex +** and up are moved one position upwards. +*/ { /* Get the item and remove it from the collection */ void* Item = CollAt (C, OldIndex); @@ -364,11 +364,11 @@ void CollMove (Collection* C, unsigned OldIndex, unsigned NewIndex) void CollMoveMultiple (Collection* C, unsigned Start, unsigned Count, unsigned Target) /* Move a range of items from one position to another. Start is the index - * of the first item to move, Count is the number of items and Target is - * the index of the target item. The item with the index Start will later - * have the index Target. All items with indices Target and above are moved - * to higher indices. - */ +** of the first item to move, Count is the number of items and Target is +** the index of the target item. The item with the index Start will later +** have the index Target. All items with indices Target and above are moved +** to higher indices. +*/ { void** TmpItems; unsigned Bytes; @@ -391,9 +391,9 @@ void CollMoveMultiple (Collection* C, unsigned Start, unsigned Count, unsigned T memcpy (TmpItems, C->Items + Start, Bytes); /* Check if the range has to be moved upwards or downwards. Move the - * existing items to their final location, so that the space needed - * for the items now in temporary storage is unoccupied. - */ + ** existing items to their final location, so that the space needed + ** for the items now in temporary storage is unoccupied. + */ if (Target < Start) { /* Move downwards */ @@ -473,9 +473,9 @@ static void QuickSort (Collection* C, int Lo, int Hi, void CollTransfer (Collection* Dest, const Collection* Source) /* Transfer all items from Source to Dest. Anything already in Dest is left - * untouched. The items in Source are not changed and are therefore in both - * Collections on return. - */ +** untouched. The items in Source are not changed and are therefore in both +** Collections on return. +*/ { /* Be sure there's enough room in Dest */ CollGrow (Dest, Dest->Count + Source->Count); @@ -495,15 +495,12 @@ void CollSort (Collection* C, int (*Compare) (void*, const void*, const void*), void* Data) /* Sort the collection using the given compare function. The data pointer is - * passed as *first* element to the compare function, it's not used by the - * sort function itself. The other two pointer passed to the Compare function - * are pointers to objects. - */ +** passed as *first* element to the compare function, it's not used by the +** sort function itself. The other two pointer passed to the Compare function +** are pointers to objects. +*/ { if (C->Count > 1) { QuickSort (C, 0, C->Count-1, Compare, Data); } } - - - diff --git a/src/common/coll.h b/src/common/coll.h index eacfac248..5114862c4 100644 --- a/src/common/coll.h +++ b/src/common/coll.h @@ -81,8 +81,8 @@ Collection* InitCollection (Collection* C); void DoneCollection (Collection* C); /* Free the data for a collection. This will not free the data contained in - * the collection. - */ +** the collection. +*/ Collection* NewCollection (void); /* Create and return a new collection */ @@ -92,9 +92,9 @@ void FreeCollection (Collection* C); void CollGrow (Collection* C, unsigned Size); /* Grow the collection C so it is able to hold Size items without a resize - * being necessary. This can be called for performance reasons if the number - * of items to be placed in the collection is known in advance. - */ +** being necessary. This can be called for performance reasons if the number +** of items to be placed in the collection is known in advance. +*/ #if defined(HAVE_INLINE) INLINE unsigned CollCount (const Collection* C) @@ -195,8 +195,8 @@ const void* CollConstLast (const Collection* C); #if defined(HAVE_INLINE) INLINE void* CollPop (Collection* C) /* Remove the last segment from the stack and return it. Calls FAIL if the - * collection is empty. - */ +** collection is empty. +*/ { /* We must have at least one entry */ PRECONDITION (C->Count > 0); @@ -207,31 +207,31 @@ INLINE void* CollPop (Collection* C) #else void* CollPop (Collection* C); /* Remove the last segment from the stack and return it. Calls FAIL if the - * collection is empty. - */ +** collection is empty. +*/ #endif int CollIndex (Collection* C, const void* Item); /* Return the index of the given item in the collection. Return -1 if the - * item was not found in the collection. - */ +** item was not found in the collection. +*/ void CollDelete (Collection* C, unsigned Index); /* Remove the item with the given index from the collection. This will not - * free the item itself, just the pointer. All items with higher indices - * will get moved to a lower position. - */ +** free the item itself, just the pointer. All items with higher indices +** will get moved to a lower position. +*/ void CollDeleteItem (Collection* C, const void* Item); /* Delete the item pointer from the collection. The item must be in the - * collection, otherwise FAIL will be called. - */ +** collection, otherwise FAIL will be called. +*/ #if defined(HAVE_INLINE) INLINE void CollDeleteAll (Collection* C) /* Delete all items from the given collection. This will not free the items - * itself, it will only remove the pointers. - */ +** itself, it will only remove the pointers. +*/ { /* This one is easy... */ C->Count = 0; @@ -243,8 +243,8 @@ INLINE void CollDeleteAll (Collection* C) #if defined(HAVE_INLINE) INLINE void CollReplace (Collection* C, void* Item, unsigned Index) /* Replace the item at the given position. The old item will not be freed, - * just the pointer will get replaced. - */ +** just the pointer will get replaced. +*/ { /* Check the index */ PRECONDITION (Index < C->Count); @@ -255,53 +255,49 @@ INLINE void CollReplace (Collection* C, void* Item, unsigned Index) #else void CollReplace (Collection* C, void* Item, unsigned Index); /* Replace the item at the given position. The old item will not be freed, - * just the pointer will get replaced. - */ +** just the pointer will get replaced. +*/ #endif void CollReplaceExpand (Collection* C, void* Item, unsigned Index); /* If Index is a valid index for the collection, replace the item at this - * position by the one passed. If the collection is too small, expand it, - * filling unused pointers with NULL, then add the new item at the given - * position. - */ +** position by the one passed. If the collection is too small, expand it, +** filling unused pointers with NULL, then add the new item at the given +** position. +*/ void CollMove (Collection* C, unsigned OldIndex, unsigned NewIndex); /* Move an item from one position in the collection to another. OldIndex - * is the current position of the item, NewIndex is the new index after - * the function has done it's work. Existing entries with indices NewIndex - * and up are moved one position upwards. - */ +** is the current position of the item, NewIndex is the new index after +** the function has done it's work. Existing entries with indices NewIndex +** and up are moved one position upwards. +*/ void CollMoveMultiple (Collection* C, unsigned Start, unsigned Count, unsigned Target); /* Move a range of items from one position to another. Start is the index - * of the first item to move, Count is the number of items and Target is - * the index of the target item. The item with the index Start will later - * have the index Target. All items with indices Target and above are moved - * to higher indices. - */ +** of the first item to move, Count is the number of items and Target is +** the index of the target item. The item with the index Start will later +** have the index Target. All items with indices Target and above are moved +** to higher indices. +*/ void CollTransfer (Collection* Dest, const Collection* Source); /* Transfer all items from Source to Dest. Anything already in Dest is left - * untouched. The items in Source are not changed and are therefore in both - * Collections on return. - */ +** untouched. The items in Source are not changed and are therefore in both +** Collections on return. +*/ void CollSort (Collection* C, int (*Compare) (void*, const void*, const void*), void* Data); /* Sort the collection using the given compare function. The data pointer is - * passed as *first* element to the compare function, it's not used by the - * sort function itself. The other two pointer passed to the Compare function - * are pointers to objects. - */ +** passed as *first* element to the compare function, it's not used by the +** sort function itself. The other two pointer passed to the Compare function +** are pointers to objects. +*/ /* End of coll.h */ #endif - - - - diff --git a/src/common/cpu.c b/src/common/cpu.c index 59353a6a1..142d55258 100644 --- a/src/common/cpu.c +++ b/src/common/cpu.c @@ -58,7 +58,6 @@ const char* CPUNames[CPU_COUNT] = { "65SC02", "65C02", "65816", - "sunplus", "sweet16", "huc6280", "m740", @@ -72,7 +71,6 @@ const unsigned CPUIsets[CPU_COUNT] = { CPU_ISET_6502 | CPU_ISET_65SC02, CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02, CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02 | CPU_ISET_65816, - CPU_ISET_SUNPLUS, CPU_ISET_SWEET16, CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02 | CPU_ISET_HUC6280, CPU_ISET_6502 | CPU_ISET_M740, @@ -121,8 +119,8 @@ int ValidAddrSizeForCPU (unsigned char AddrSize) cpu_t FindCPU (const char* Name) /* Find a CPU by name and return the target id. CPU_UNKNOWN is returned if - * the given name is no valid target. - */ +** the given name is no valid target. +*/ { unsigned I; @@ -136,6 +134,3 @@ cpu_t FindCPU (const char* Name) /* Not found */ return CPU_UNKNOWN; } - - - diff --git a/src/common/cpu.h b/src/common/cpu.h index 424053cf9..5bdbdef8c 100644 --- a/src/common/cpu.h +++ b/src/common/cpu.h @@ -53,7 +53,6 @@ typedef enum { CPU_65SC02, CPU_65C02, CPU_65816, - CPU_SUNPLUS, /* Not in the freeware version - sorry */ CPU_SWEET16, CPU_HUC6280, /* Used in PC engine */ CPU_M740, /* Mitsubishi 740 series MCUs */ @@ -68,7 +67,6 @@ enum { CPU_ISET_65SC02 = 1 << CPU_65SC02, CPU_ISET_65C02 = 1 << CPU_65C02, CPU_ISET_65816 = 1 << CPU_65816, - CPU_ISET_SUNPLUS = 1 << CPU_SUNPLUS, CPU_ISET_SWEET16 = 1 << CPU_SWEET16, CPU_ISET_HUC6280 = 1 << CPU_HUC6280, CPU_ISET_M740 = 1 << CPU_M740, @@ -96,14 +94,11 @@ int ValidAddrSizeForCPU (unsigned char AddrSize); cpu_t FindCPU (const char* Name); /* Find a CPU by name and return the target id. CPU_UNKNOWN is returned if - * the given name is no valid target. - */ +** the given name is no valid target. +*/ /* End of cpu.h */ #endif - - - diff --git a/src/common/debugflag.c b/src/common/debugflag.c index d660018b5..7d2e80009 100644 --- a/src/common/debugflag.c +++ b/src/common/debugflag.c @@ -45,6 +45,3 @@ unsigned char Debug = 0; /* Debug mode */ - - - diff --git a/src/common/debugflag.h b/src/common/debugflag.h index f62e60e82..d325a9eb9 100644 --- a/src/common/debugflag.h +++ b/src/common/debugflag.h @@ -49,7 +49,5 @@ extern unsigned char Debug; /* Debug mode */ /* End of debugflag.h */ + #endif - - - diff --git a/src/common/exprdefs.c b/src/common/exprdefs.c index 69eda4c4d..d9a5adf6b 100644 --- a/src/common/exprdefs.c +++ b/src/common/exprdefs.c @@ -232,6 +232,3 @@ void DumpExpr (const ExprNode* Expr, const ExprNode* (*ResolveSym) (const struct InternalDumpExpr (Expr, ResolveSym); printf ("\n"); } - - - diff --git a/src/common/exprdefs.h b/src/common/exprdefs.h index 933677fa3..5465c4f25 100644 --- a/src/common/exprdefs.h +++ b/src/common/exprdefs.h @@ -145,6 +145,3 @@ void DumpExpr (const ExprNode* Expr, const ExprNode* (*ResolveSym) (const struct /* End of exprdefs.h */ #endif - - - diff --git a/src/common/fileid.c b/src/common/fileid.c index fe26aff79..fd6d95d54 100644 --- a/src/common/fileid.c +++ b/src/common/fileid.c @@ -58,10 +58,10 @@ int CompareFileId (const void* Key, const void* Id) const FileId* GetFileId (const char* Name, const FileId* Table, unsigned Count) /* Determine the id of the given file by looking at file extension of the name. - * The table passed to the function must be sorted alphabetically. If the - * extension is found, a pointer to the matching table entry is returned. If - * no matching table entry was found, the function returns NULL. - */ +** The table passed to the function must be sorted alphabetically. If the +** extension is found, a pointer to the matching table entry is returned. If +** no matching table entry was found, the function returns NULL. +*/ { /* Determine the file type by the extension */ const char* Ext = FindExt (Name); @@ -74,6 +74,3 @@ const FileId* GetFileId (const char* Name, const FileId* Table, unsigned Count) /* Search for a table entry and return it */ return bsearch (Ext+1, Table, Count, sizeof (FileId), CompareFileId); } - - - diff --git a/src/common/fileid.h b/src/common/fileid.h index 751c4ca17..df71cf2bb 100644 --- a/src/common/fileid.h +++ b/src/common/fileid.h @@ -45,8 +45,8 @@ /* An entry for a table that maps extensions to some sort of identifier. Such - * a table - sorted alphabetically - is passed to GetFileId. - */ +** a table - sorted alphabetically - is passed to GetFileId. +*/ typedef struct FileId FileId; struct FileId { const char Ext[4]; @@ -66,15 +66,13 @@ int CompareFileId (const void* Key, const void* Id); const FileId* GetFileId (const char* Name, const FileId* Table, unsigned Count); /* Determine the id of the given file by looking at file extension of the name. - * The table passed to the function must be sorted alphabetically. If the - * extension is found, a pointer to the matching table entry is returned. If - * no matching table entry was found, the function returns NULL. - */ +** The table passed to the function must be sorted alphabetically. If the +** extension is found, a pointer to the matching table entry is returned. If +** no matching table entry was found, the function returns NULL. +*/ /* End of fileid.h */ + #endif - - - diff --git a/src/common/filepos.c b/src/common/filepos.c index bf6888495..51488ffe5 100644 --- a/src/common/filepos.c +++ b/src/common/filepos.c @@ -56,9 +56,9 @@ void InitFilePos (FilePos* P) int CompareFilePos (const FilePos* P1, const FilePos* P2) /* Compare two file positions. Return zero if both are equal, return a value - * > 0 if P1 is greater and P2, and a value < 0 if P1 is less than P2. The - * compare rates file index over line over column. - */ +** > 0 if P1 is greater and P2, and a value < 0 if P1 is less than P2. The +** compare rates file index over line over column. +*/ { if (P1->Name > P2->Name) { return 1; @@ -76,6 +76,3 @@ int CompareFilePos (const FilePos* P1, const FilePos* P2) return 0; } } - - - diff --git a/src/common/filepos.h b/src/common/filepos.h index 21ef2e7b0..d6368ad6f 100644 --- a/src/common/filepos.h +++ b/src/common/filepos.h @@ -68,15 +68,12 @@ void InitFilePos (FilePos* P); int CompareFilePos (const FilePos* P1, const FilePos* P2); /* Compare two file positions. Return zero if both are equal, return a value - * > 0 if P1 is greater and P2, and a value < 0 if P1 is less than P2. The - * compare rates file index over line over column. - */ +** > 0 if P1 is greater and P2, and a value < 0 if P1 is less than P2. The +** compare rates file index over line over column. +*/ /* End of filepos.h */ #endif - - - diff --git a/src/common/filestat.c b/src/common/filestat.c index 0f5f5cd11..b72fa7a74 100644 --- a/src/common/filestat.c +++ b/src/common/filestat.c @@ -2,7 +2,7 @@ /* */ /* filestat.c */ /* */ -/* Replacement for buggy Microsoft code */ +/* Replacement for Windows code */ /* */ /* */ /* */ @@ -34,22 +34,21 @@ /* This module works around bugs in the time conversion code supplied by - * Microsoft. See here for a description of the problem: - * http://www.codeproject.com/KB/datetime/dstbugs.aspx - * Please let me note that I find it absolutely unacceptable to just declare - * buggy behaviour like this "works as designed" as Microsoft does. The - * problems did even make it into .NET, where the DateTime builtin data type - * has exactly the same problems as described in the article above. - */ +** Microsoft. See here for a description of the problem: +** http://www.codeproject.com/KB/datetime/dstbugs.aspx +** Please let me note that I find it absolutely unacceptable to just declare +** buggy behaviour like this "works as designed" as Microsoft does. The +** problems did even make it into .NET, where the DateTime builtin data type +** has exactly the same problems as described in the article above. +*/ #include <sys/types.h> #include <sys/stat.h> -#if defined(__WATCOMC__) && defined(__NT__) -#define BUGGY_OS 1 -#include <errno.h> -#include <windows.h> +#if defined(_WIN32) +# include <errno.h> +# include <windows.h> #endif /* common */ @@ -63,21 +62,21 @@ -#if defined(BUGGY_OS) +#if defined(_WIN32) static time_t FileTimeToUnixTime (const FILETIME* T) /* Calculate a unix time_t value from a FILETIME. FILETIME contains a 64 bit - * value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals. - * time_t is in seconds since 1970-01-01 00:00:00. - */ +** value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals. +** time_t is in seconds since 1970-01-01 00:00:00. +*/ { /* Offset between 1600-01-01 and the Epoch in seconds. Watcom C has no - * way to express a number > 32 bit (known to me) but is able to do - * calculations with 64 bit integers, so we need to do it this way. - */ - static const ULARGE_INTEGER Offs = { 0xB6109100UL, 0x00000020UL }; + ** way to express a number > 32 bit (known to me) but is able to do + ** calculations with 64 bit integers, so we need to do it this way. + */ + static const ULARGE_INTEGER Offs = { { 0xB6109100UL, 0x00000020UL } }; ULARGE_INTEGER V; V.LowPart = T->dwLowDateTime; V.HighPart = T->dwHighDateTime; @@ -100,10 +99,10 @@ int FileStat (const char* Path, struct stat* Buf) } /* Open the file using backup semantics, so we won't change atime. Then - * retrieve the correct times in UTC and replace the ones in Buf. Return - * EACCES in case of errors to avoid the hassle of translating windows - * error codes to standard ones. - */ + ** retrieve the correct times in UTC and replace the ones in Buf. Return + ** EACCES in case of errors to avoid the hassle of translating windows + ** error codes to standard ones. + */ H = CreateFile (Path, GENERIC_READ, FILE_SHARE_READ, diff --git a/src/common/filestat.h b/src/common/filestat.h index 50b7685ef..42900881a 100644 --- a/src/common/filestat.h +++ b/src/common/filestat.h @@ -2,7 +2,7 @@ /* */ /* filestat.h */ /* */ -/* Replacement for buggy Microsoft code */ +/* Replacement for Windows code */ /* */ /* */ /* */ @@ -34,13 +34,13 @@ /* This module works around bugs in the time conversion code supplied by - * Microsoft. See here for a description of the problem: - * http://www.codeproject.com/KB/datetime/dstbugs.aspx - * Please let me note that I find it absolutely unacceptable to just declare - * buggy behaviour like this "works as designed" as Microsoft does. The - * problems did even make it into .NET, where the DateTime builtin data type - * has exactly the same problems as described in the article above. - */ +** Microsoft. See here for a description of the problem: +** http://www.codeproject.com/KB/datetime/dstbugs.aspx +** Please let me note that I find it absolutely unacceptable to just declare +** buggy behaviour like this "works as designed" as Microsoft does. The +** problems did even make it into .NET, where the DateTime builtin data type +** has exactly the same problems as described in the article above. +*/ @@ -68,6 +68,3 @@ int FileStat (const char* Path, struct stat* Buf); /* End of filestat.h */ #endif - - - diff --git a/src/common/filetime.c b/src/common/filetime.c index 025380759..8bdf44f3f 100644 --- a/src/common/filetime.c +++ b/src/common/filetime.c @@ -2,7 +2,7 @@ /* */ /* filetime.c */ /* */ -/* Replacement for buggy Microsoft code */ +/* Replacement for Windows code */ /* */ /* */ /* */ @@ -34,27 +34,21 @@ /* This module works around bugs in the time conversion code supplied by - * Microsoft. The problem described here: - * http://www.codeproject.com/KB/datetime/dstbugs.aspx - * is also true when setting file times via utime(), so we need a - * replacement - */ +** Microsoft. The problem described here: +** http://www.codeproject.com/KB/datetime/dstbugs.aspx +** is also true when setting file times via utime(), so we need a +** replacement +*/ -#if defined(__WATCOMC__) && defined(__NT__) -#define BUGGY_OS 1 -#include <errno.h> -#include <windows.h> +#if defined(_WIN32) +# include <errno.h> +# include <windows.h> #else -#if defined(__WATCOMC__) || defined(_MSC_VER) || defined(__MINGW32__) -/* The Windows compilers have the file in the wrong directory */ -# include <sys/utime.h> -#else -# include <sys/types.h> /* FreeBSD needs this */ +# include <sys/types.h> /* FreeBSD needs this */ # include <utime.h> #endif -#endif /* common */ @@ -68,21 +62,21 @@ -#if defined(BUGGY_OS) +#if defined(_WIN32) static FILETIME* UnixTimeToFileTime (time_t T, FILETIME* FT) /* Calculate a FILETIME value from a time_t. FILETIME contains a 64 bit - * value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals. - * time_t is in seconds since 1970-01-01 00:00:00. - */ +** value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals. +** time_t is in seconds since 1970-01-01 00:00:00. +*/ { /* Offset between 1600-01-01 and the Epoch in seconds. Watcom C has no - * way to express a number > 32 bit (known to me) but is able to do - * calculations with 64 bit integers, so we need to do it this way. - */ - static const ULARGE_INTEGER Offs = { 0xB6109100UL, 0x00000020UL }; + ** way to express a number > 32 bit (known to me) but is able to do + ** calculations with 64 bit integers, so we need to do it this way. + */ + static const ULARGE_INTEGER Offs = { { 0xB6109100UL, 0x00000020UL } }; ULARGE_INTEGER V; V.QuadPart = ((unsigned __int64) T + Offs.QuadPart) * 10000000U; FT->dwLowDateTime = V.LowPart; @@ -94,9 +88,9 @@ static FILETIME* UnixTimeToFileTime (time_t T, FILETIME* FT) int SetFileTimes (const char* Path, time_t T) /* Set the time of last modification and the time of last access of a file to - * the given time T. This calls utime() for system where it works, and applies - * workarounds for all others (which in fact means "WINDOWS"). - */ +** the given time T. This calls utime() for system where it works, and applies +** workarounds for all others (which in fact means "WINDOWS"). +*/ { HANDLE H; FILETIME FileTime; @@ -135,9 +129,9 @@ int SetFileTimes (const char* Path, time_t T) int SetFileTimes (const char* Path, time_t T) /* Set the time of last modification and the time of last access of a file to - * the given time T. This calls utime() for system where it works, and applies - * workarounds for all others (which in fact means "WINDOWS"). - */ +** the given time T. This calls utime() for system where it works, and applies +** workarounds for all others (which in fact means "WINDOWS"). +*/ { struct utimbuf U; @@ -150,6 +144,3 @@ int SetFileTimes (const char* Path, time_t T) #endif - - - diff --git a/src/common/filetime.h b/src/common/filetime.h index 8a27712d9..f5f00cdc9 100644 --- a/src/common/filetime.h +++ b/src/common/filetime.h @@ -2,7 +2,7 @@ /* */ /* filetime.h */ /* */ -/* Replacement for buggy Microsoft code */ +/* Replacement for Windows code */ /* */ /* */ /* */ @@ -34,11 +34,11 @@ /* This module works around bugs in the time conversion code supplied by - * Microsoft. The problem described here: - * http://www.codeproject.com/KB/datetime/dstbugs.aspx - * is also true when setting file times via utime(), so we need a - * replacement - */ +** Microsoft. The problem described here: +** http://www.codeproject.com/KB/datetime/dstbugs.aspx +** is also true when setting file times via utime(), so we need a +** replacement +*/ @@ -59,15 +59,12 @@ int SetFileTimes (const char* Path, time_t T); /* Set the time of last modification and the time of last access of a file to - * the given time T. This calls utime() for system where it works, and applies - * workarounds for all others (which in fact means "WINDOWS"). - */ +** the given time T. This calls utime() for system where it works, and applies +** workarounds for all others (which in fact means "WINDOWS"). +*/ /* End of filestat.h */ #endif - - - diff --git a/src/common/filetype.c b/src/common/filetype.c index 3e5779eb8..a5bac640d 100644 --- a/src/common/filetype.c +++ b/src/common/filetype.c @@ -95,8 +95,8 @@ static const FileId TypeTable[] = { FILETYPE GetFileType (const char* Name) /* Determine the type of the given file by looking at the name. If the file - * type could not be determined, the function returns FILETYPE_UNKOWN. - */ +** type could not be determined, the function returns FILETYPE_UNKOWN. +*/ { /* Search for a table entry */ const FileId* F = GetFileId (Name, TypeTable, FILETYPE_COUNT); @@ -104,6 +104,3 @@ FILETYPE GetFileType (const char* Name) /* Return the result */ return F? F->Id : FILETYPE_UNKNOWN; } - - - diff --git a/src/common/filetype.h b/src/common/filetype.h index c1294d5f4..f4beae73a 100644 --- a/src/common/filetype.h +++ b/src/common/filetype.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -65,13 +65,11 @@ typedef enum { FILETYPE GetFileType (const char* Name); /* Determine the type of the given file by looking at the name. If the file - * type could not be determined, the function returns FILETYPE_UNKOWN. - */ +** type could not be determined, the function returns FILETYPE_UNKOWN. +*/ /* End of filetype.h */ + #endif - - - diff --git a/src/common/fname.c b/src/common/fname.c index 5fd56338d..4e4f7c7fa 100644 --- a/src/common/fname.c +++ b/src/common/fname.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -77,8 +77,8 @@ const char* FindExt (const char* Name) const char* FindName (const char* Path) /* Return a pointer to the file name in Path. If there is no path leading to - * the file, the function returns Path as name. - */ +** the file, the function returns Path as name. +*/ { /* Get the length of the name */ int Len = strlen (Path); @@ -96,10 +96,10 @@ const char* FindName (const char* Path) char* MakeFilename (const char* Origin, const char* Ext) /* Make a new file name from Origin and Ext. If Origin has an extension, it - * is removed and Ext is appended. If Origin has no extension, Ext is simply - * appended. The result is placed in a malloc'ed buffer and returned. - * The function may be used to create "foo.o" from "foo.s". - */ +** is removed and Ext is appended. If Origin has no extension, Ext is simply +** appended. The result is placed in a malloc'ed buffer and returned. +** The function may be used to create "foo.o" from "foo.s". +*/ { char* Out; const char* P = FindExt (Origin); @@ -115,6 +115,3 @@ char* MakeFilename (const char* Origin, const char* Ext) } return Out; } - - - diff --git a/src/common/fname.h b/src/common/fname.h index c9c3848f7..1b94d270c 100644 --- a/src/common/fname.h +++ b/src/common/fname.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -49,21 +49,18 @@ const char* FindExt (const char* Name); const char* FindName (const char* Path); /* Return a pointer to the file name in Path. If there is no path leading to - * the file, the function returns Path as name. - */ +** the file, the function returns Path as name. +*/ char* MakeFilename (const char* Origin, const char* Ext); /* Make a new file name from Origin and Ext. If Origin has an extension, it - * is removed and Ext is appended. If Origin has no extension, Ext is simply - * appended. The result is placed in a malloc'ed buffer and returned. - * The function may be used to create "foo.o" from "foo.s". - */ +** is removed and Ext is appended. If Origin has no extension, Ext is simply +** appended. The result is placed in a malloc'ed buffer and returned. +** The function may be used to create "foo.o" from "foo.s". +*/ /* End of fname.h */ #endif - - - diff --git a/src/common/fp.c b/src/common/fp.c index cfec86e42..0c4d2790c 100644 --- a/src/common/fp.c +++ b/src/common/fp.c @@ -34,13 +34,13 @@ /* The compiler must use the same floating point arithmetic as the target - * platform, otherwise expressions will yield a different result when - * evaluated in the compiler or on the target platform. Since writing a target - * and source library is almost double the work, we will at least add the - * hooks here, and define functions for a plug in library that may be added - * at a later time. Currently we use the builtin data types of the compiler - * that translates cc65. - */ +** platform, otherwise expressions will yield a different result when +** evaluated in the compiler or on the target platform. Since writing a target +** and source library is almost double the work, we will at least add the +** hooks here, and define functions for a plug in library that may be added +** at a later time. Currently we use the builtin data types of the compiler +** that translates cc65. +*/ @@ -236,6 +236,3 @@ Double FP_D_Div (Double Left, Double Right) D.V = Left.V / Right.V; return D; } - - - diff --git a/src/common/fp.h b/src/common/fp.h index 8544c453f..978359b8b 100644 --- a/src/common/fp.h +++ b/src/common/fp.h @@ -34,16 +34,15 @@ /* The compiler must use the same floating point arithmetic as the target - * platform, otherwise expressions will yield a different result when - * evaluated in the compiler or on the target platform. Since writing a target - * and source library is almost double the work, we will at least add the - * hooks here, and define functions for a plug in library that may be added - * at a later time. Currently we use the builtin data types of the compiler - * that translates cc65. - * - * BEWARE: This code will currently only work on little endian systems! - * - */ +** platform, otherwise expressions will yield a different result when +** evaluated in the compiler or on the target platform. Since writing a target +** and source library is almost double the work, we will at least add the +** hooks here, and define functions for a plug in library that may be added +** at a later time. Currently we use the builtin data types of the compiler +** that translates cc65. +** +** BEWARE: This code will currently only work on little endian systems! +*/ @@ -140,8 +139,3 @@ Double FP_D_Div (Double Left, Double Right); /* End of fp.h */ #endif - - - - - diff --git a/src/common/fragdefs.h b/src/common/fragdefs.h index c0a37ffcd..c3e589cb2 100644 --- a/src/common/fragdefs.h +++ b/src/common/fragdefs.h @@ -70,6 +70,3 @@ /* End of fragdefs.h */ #endif - - - diff --git a/src/common/gentype.c b/src/common/gentype.c index aa1471aa4..1600a7c2f 100644 --- a/src/common/gentype.c +++ b/src/common/gentype.c @@ -48,8 +48,8 @@ void GT_AddArray (StrBuf* Type, unsigned ArraySize) /* Add an array with the given size to the type string in Type. This will - * NOT add the element type! - */ +** NOT add the element type! +*/ { unsigned SizeBytes; @@ -75,10 +75,10 @@ void GT_AddArray (StrBuf* Type, unsigned ArraySize) unsigned GT_GetElementCount (StrBuf* Type) /* Retrieve the element count of an array stored in Type at the current index - * position. Note: Index must point to the array token itself, since the size - * of the element count is encoded there. The index position will get moved - * past the array. - */ +** position. Note: Index must point to the array token itself, since the size +** of the element count is encoded there. The index position will get moved +** past the array. +*/ { /* Get the number of bytes for the element count */ unsigned SizeBytes = GT_GET_SIZE (SB_Get (Type)); @@ -99,15 +99,15 @@ unsigned GT_GetElementCount (StrBuf* Type) const char* GT_AsString (const StrBuf* Type, StrBuf* String) /* Convert the type into a readable representation. The target string buffer - * will be zero terminated and a pointer to the contents are returned. - */ +** will be zero terminated and a pointer to the contents are returned. +*/ { static const char HexTab[16] = "0123456789ABCDEF"; unsigned I; /* Convert Type into readable hex. String will have twice then length - * plus a terminator. - */ + ** plus a terminator. + */ SB_Realloc (String, 2 * SB_GetLen (Type) + 1); SB_Clear (String); @@ -123,6 +123,3 @@ const char* GT_AsString (const StrBuf* Type, StrBuf* String) /* Return the contents of String */ return SB_GetConstBuf (String); } - - - diff --git a/src/common/gentype.h b/src/common/gentype.h index 1a2440f46..b3f13f176 100644 --- a/src/common/gentype.h +++ b/src/common/gentype.h @@ -34,21 +34,21 @@ /* This module implements a specification for a "generic data type". It is - * called generic, because it doesn't mimic a high level language. Instead it - * tries to desrcibe the type as representation on the machine. - * The reasoning behing this type is to allow a debugger to represent the - * data to the user, independent of the actual source. - * C data types may be mapped to generic ones, but attributes like const or - * volatile are (of course) lost. - * - * The data type is stored in a char array and can be terminate by a zero - * (see definition of GT_END below). The later is not really necessary but - * allows handling of types using the usual string functions. This is in fact - * one of the advantages of the choosen implementation: - * String buffers may be used to dynamically build types. Types may be stored - * as strings in the string pool of an object file. And a string pool may be - * used to remove duplicates and reference types using unique ids. - */ +** called generic, because it doesn't mimic a high level language. Instead it +** tries to desrcibe the type as representation on the machine. +** The reasoning behing this type is to allow a debugger to represent the +** data to the user, independent of the actual source. +** C data types may be mapped to generic ones, but attributes like const or +** volatile are (of course) lost. +** +** The data type is stored in a char array; and, can be terminated by a zero +** (see definition of GT_END below). The latter is not really necessary; but, +** allows handling of types using the usual string functions. This is in fact +** one of the advantages of the chosen implementation: +** String buffers may be used to dynamically build types. Types may be stored +** as strings in the string pool of an object file. And a string pool may be +** used to remove duplicates and reference types using unique ids. +*/ @@ -132,27 +132,23 @@ void GT_AddArray (StrBuf* Type, unsigned ArraySize); /* Add an array with the given size to the type string in Type. This will - * NOT add the element type! - */ +** NOT add the element type! +*/ unsigned GT_GetElementCount (StrBuf* Type); /* Retrieve the element count of an array stored in Type at the current index - * position. Note: Index must point to the array token itself, since the size - * of the element count is encoded there. The index position will get moved - * past the array. - */ +** position. Note: Index must point to the array token itself, since the size +** of the element count is encoded there. The index position will get moved +** past the array. +*/ const char* GT_AsString (const StrBuf* Type, StrBuf* String); /* Convert the type into a readable representation. The target string buffer - * will be zero terminated and a pointer to the contents are returned. - */ +** will be zero terminated and a pointer to the contents are returned. +*/ /* End of gentype.h */ #endif - - - - diff --git a/src/common/hashfunc.c b/src/common/hashfunc.c index 6774c88fc..3ef268778 100644 --- a/src/common/hashfunc.c +++ b/src/common/hashfunc.c @@ -46,10 +46,10 @@ unsigned HashInt (unsigned V) /* Return a hash value for the given integer. The function uses Robert - * Jenkins' 32 bit integer hash function taken from - * http://www.concentric.net/~ttwang/tech/inthash.htm - * For 16 bit integers, the function may be suboptimal. - */ +** Jenkins' 32 bit integer hash function taken from +** http://www.concentric.net/~ttwang/tech/inthash.htm +** For 16 bit integers, the function may be suboptimal. +*/ { V = (V + 0x7ed55d16) + (V << 12); V = (V ^ 0xc761c23c) ^ (V >> 19); @@ -89,6 +89,3 @@ unsigned HashBuf (const StrBuf* S) } return H; } - - - diff --git a/src/common/hashfunc.h b/src/common/hashfunc.h index 4d8b5ac7b..2645474cf 100644 --- a/src/common/hashfunc.h +++ b/src/common/hashfunc.h @@ -64,6 +64,3 @@ unsigned HashBuf (const StrBuf* S) attribute ((const)); /* End of hashfunc.h */ #endif - - - diff --git a/src/common/hashtab.c b/src/common/hashtab.c index 376e26a28..4330ad61c 100644 --- a/src/common/hashtab.c +++ b/src/common/hashtab.c @@ -63,8 +63,8 @@ HashTable* InitHashTable (HashTable* T, unsigned Slots, const HashFunctions* Fun void DoneHashTable (HashTable* T) /* Destroy the contents of a hash table. Note: This will not free the entries - * in the table! - */ +** in the table! +*/ { /* Just free the array with the table pointers */ xfree (T->Table); @@ -103,8 +103,8 @@ static void HT_Alloc (HashTable* T) HashNode* HT_FindHash (const HashTable* T, const void* Key, unsigned Hash) /* Find the node with the given key. Differs from HT_Find in that the hash - * for the key is precalculated and passed to the function. - */ +** for the key is precalculated and passed to the function. +*/ { HashNode* N; @@ -118,8 +118,8 @@ HashNode* HT_FindHash (const HashTable* T, const void* Key, unsigned Hash) while (N) { /* First compare the full hash, to avoid calling the compare function - * if it is not really necessary. - */ + ** if it is not really necessary. + */ if (N->Hash == Hash && T->Func->Compare (Key, T->Func->GetKey (N)) == 0) { /* Found */ @@ -188,8 +188,8 @@ void HT_Remove (HashTable* T, void* Entry) HashNode** Q = &T->Table[Slot]; while (1) { /* If the pointer is NULL, the node is not in the table which we will - * consider a serious error. - */ + ** consider a serious error. + */ CHECK (*Q != 0); if (*Q == N) { /* Found - remove it */ @@ -206,12 +206,12 @@ void HT_Remove (HashTable* T, void* Entry) void HT_Walk (HashTable* T, int (*F) (void* Entry, void* Data), void* Data) /* Walk over all nodes of a hash table, optionally deleting entries from the - * table. For each node, the user supplied function F is called, passing a - * pointer to the entry, and the data pointer passed to HT_Walk by the caller. - * If F returns true, the node is deleted from the hash table otherwise it's - * left in place. While deleting the node, the node is not accessed, so it is - * safe for F to free the memory associcated with the entry. - */ +** table. For each node, the user supplied function F is called, passing a +** pointer to the entry, and the data pointer passed to HT_Walk by the caller. +** If F returns true, the node is deleted from the hash table otherwise it's +** left in place. While deleting the node, the node is not accessed, so it is +** safe for F to free the memory associcated with the entry. +*/ { unsigned I; @@ -231,8 +231,8 @@ void HT_Walk (HashTable* T, int (*F) (void* Entry, void* Data), void* Data) /* Fetch the next node in chain now, because F() may delete it */ HashNode* Next = (*Cur)->Next; /* Call the user function. N is also the pointer to the entry. If - * the function returns true, the entry is to be deleted. - */ + ** the function returns true, the entry is to be deleted. + */ if (F (*Cur, Data)) { /* Delete the node from the chain */ *Cur = Next; @@ -244,6 +244,3 @@ void HT_Walk (HashTable* T, int (*F) (void* Entry, void* Data), void* Data) } } } - - - diff --git a/src/common/hashtab.h b/src/common/hashtab.h index a8397db40..f110fa1a0 100644 --- a/src/common/hashtab.h +++ b/src/common/hashtab.h @@ -51,10 +51,10 @@ /* Hash table node. NOTE: This structure must be the first member of a struct - * that is hashed by the module. Having it first allows to omit a pointer to - * the entry itself, because the C standard guarantees that a pointer to a - * struct can be converted to its first member. - */ +** that is hashed by the module. Having it first allows to omit a pointer to +** the entry itself, because the C standard guarantees that a pointer to a +** struct can be converted to its first member. +*/ typedef struct HashNode HashNode; struct HashNode { HashNode* Next; /* Next entry in hash list */ @@ -75,9 +75,9 @@ struct HashFunctions { int (*Compare) (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if - * Key1 is smaller than Key2, zero if both are equal, and a value greater - * than zero if Key1 is greater then Key2. - */ + ** Key1 is smaller than Key2, zero if both are equal, and a value greater + ** than zero if Key1 is greater then Key2. + */ }; /* Hash table */ @@ -122,8 +122,8 @@ HashTable* InitHashTable (HashTable* T, unsigned Slots, const HashFunctions* Fun void DoneHashTable (HashTable* T); /* Destroy the contents of a hash table. Note: This will not free the entries - * in the table! - */ +** in the table! +*/ #if defined(HAVE_INLINE) INLINE HashTable* NewHashTable (unsigned Slots, const HashFunctions* Func) @@ -151,8 +151,8 @@ INLINE unsigned HT_GetCount (const HashTable* T) HashNode* HT_FindHash (const HashTable* T, const void* Key, unsigned Hash); /* Find the node with the given key. Differs from HT_Find in that the hash - * for the key is precalculated and passed to the function. - */ +** for the key is precalculated and passed to the function. +*/ void* HT_Find (const HashTable* T, const void* Key); /* Find the entry with the given key and return it */ @@ -165,18 +165,15 @@ void HT_Remove (HashTable* T, void* Entry); void HT_Walk (HashTable* T, int (*F) (void* Entry, void* Data), void* Data); /* Walk over all nodes of a hash table, optionally deleting entries from the - * table. For each node, the user supplied function F is called, passing a - * pointer to the entry, and the data pointer passed to HT_Walk by the caller. - * If F returns true, the node is deleted from the hash table otherwise it's - * left in place. While deleting the node, the node is not accessed, so it is - * safe for F to free the memory associcated with the entry. - */ +** table. For each node, the user supplied function F is called, passing a +** pointer to the entry, and the data pointer passed to HT_Walk by the caller. +** If F returns true, the node is deleted from the hash table otherwise it's +** left in place. While deleting the node, the node is not accessed, so it is +** safe for F to free the memory associcated with the entry. +*/ /* End of hashtab.h */ #endif - - - diff --git a/src/common/hlldbgsym.h b/src/common/hlldbgsym.h index c1e6487ce..0edb7e2ce 100644 --- a/src/common/hlldbgsym.h +++ b/src/common/hlldbgsym.h @@ -34,10 +34,10 @@ /* This module contains definitions for high level language symbols passed - * down from the C compiler. They're collected in the assembler and written to - * the object file in binary form, then again read by the linker and finally - * placed in the debug info file. - */ +** down from the C compiler. They're collected in the assembler and written to +** the object file in binary form, then again read by the linker and finally +** placed in the debug info file. +*/ @@ -77,6 +77,3 @@ /* End of hlldbgsyms.h */ #endif - - - diff --git a/src/common/inline.h b/src/common/inline.h index 3857511a1..b90b3d1f4 100644 --- a/src/common/inline.h +++ b/src/common/inline.h @@ -54,6 +54,3 @@ /* End of inline.h */ #endif - - - diff --git a/src/common/intstack.c b/src/common/intstack.c index f5518e337..3f99e8854 100644 --- a/src/common/intstack.c +++ b/src/common/intstack.c @@ -87,6 +87,3 @@ long IS_Pop (IntStack* S) PRECONDITION (S->Count > 0); return S->Stack[--S->Count]; } - - - diff --git a/src/common/intstack.h b/src/common/intstack.h index f3fbf081b..313a846c1 100644 --- a/src/common/intstack.h +++ b/src/common/intstack.h @@ -116,7 +116,5 @@ long IS_Pop (IntStack* S); /* End of intstack.h */ + #endif - - - diff --git a/src/common/inttypes.h b/src/common/inttypes.h index 3c87eb7be..0d9cb75fc 100644 --- a/src/common/inttypes.h +++ b/src/common/inttypes.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -39,17 +39,17 @@ /* If we have stdint.h, include it, otherwise try some quesswork on types. - * gcc and msvc don't define __STDC_VERSION__ without special flags, so check - * for them explicitly. Undefined symbols are replaced by zero, so a check for - * defined(__GNUC__) or defined(_MSC_VER) is not necessary. - */ +** gcc and msvc don't define __STDC_VERSION__ without special flags, so check +** for them explicitly. Undefined symbols are replaced by zero, so a check for +** defined(__GNUC__) or defined(_MSC_VER) is not necessary. +*/ #if (__STDC_VERSION__ >= 199901) || (__GNUC__ >= 3) || (_MSC_VER >= 1600) #include <stdint.h> #else /* Assume long is the largest type available, and assume that pointers can be - * safely converted into this type and back. - */ +** safely converted into this type and back. +*/ typedef long intptr_t; typedef unsigned long uintptr_t; typedef long intmax_t; @@ -62,7 +62,5 @@ typedef unsigned long uintmax_t; /* End of inttypes.h */ + #endif - - - diff --git a/src/common/libdefs.h b/src/common/libdefs.h index 19b3a8290..d91084c26 100644 --- a/src/common/libdefs.h +++ b/src/common/libdefs.h @@ -67,6 +67,3 @@ struct LibHeader { /* End of libdefs.h */ #endif - - - diff --git a/src/common/lidefs.h b/src/common/lidefs.h index 3c996f710..29d47b57a 100644 --- a/src/common/lidefs.h +++ b/src/common/lidefs.h @@ -62,6 +62,3 @@ /* End of lidefs.h */ #endif - - - diff --git a/src/common/matchpat.c b/src/common/matchpat.c index 9ea17cdb4..ac24c39ab 100644 --- a/src/common/matchpat.c +++ b/src/common/matchpat.c @@ -94,8 +94,8 @@ typedef unsigned char CharSet[32]; /* 256 bits */ static int RealChar (const unsigned char* Pattern) /* Return the next character from Pattern. If the next character is the - * escape character, skip it and return the following. - */ +** escape character, skip it and return the following. +*/ { if (*Pattern == ESCAPE_CHAR) { Pattern++; @@ -146,9 +146,9 @@ static int RecursiveMatch (const unsigned char* Source, const unsigned char* Pat } else { /* Check a single char. Build a set of all possible characters in - * CS, then check if the current char of Source is contained in - * there. - */ + ** CS, then check if the current char of Source is contained in + ** there. + */ CS_CLEAR (CS); /* Clear the character set */ if (*Pattern == '?') { @@ -224,11 +224,11 @@ static int RecursiveMatch (const unsigned char* Source, const unsigned char* Pat int MatchPattern (const char* Source, const char* Pattern) /* Match the string in Source against Pattern. Pattern may contain the - * wildcards '*', '?', '[abcd]' '[ab-d]', '[!abcd]', '[!ab-d]'. The - * function returns a value of zero if Source does not match Pattern, - * otherwise a non zero value is returned. If Pattern contains an invalid - * wildcard pattern (e.g. 'A[x'), the function returns zero. - */ +** wildcards '*', '?', '[abcd]' '[ab-d]', '[!abcd]', '[!ab-d]'. The +** function returns a value of zero if Source does not match Pattern, +** otherwise a non zero value is returned. If Pattern contains an invalid +** wildcard pattern (e.g. 'A[x'), the function returns zero. +*/ { /* Handle the trivial cases */ if (Pattern == 0 || *Pattern == '\0') { @@ -238,6 +238,3 @@ int MatchPattern (const char* Source, const char* Pattern) /* Do the real thing */ return RecursiveMatch ((const unsigned char*) Source, (const unsigned char*) Pattern); } - - - diff --git a/src/common/matchpat.h b/src/common/matchpat.h index ddf431ff9..eb1c80dd4 100644 --- a/src/common/matchpat.h +++ b/src/common/matchpat.h @@ -50,17 +50,14 @@ int MatchPattern (const char* Source, const char* Pattern); /* Match the string in Source against Pattern. Pattern may contain the - * wildcards '*', '?', '[abcd]' '[ab-d]', '[!abcd]', '[!ab-d]'. The - * function returns a value of zero if Source does not match Pattern, - * otherwise a non zero value is returned. If Pattern contains an invalid - * wildcard pattern (e.g. 'A[x'), the function returns zero. - */ +** wildcards '*', '?', '[abcd]' '[ab-d]', '[!abcd]', '[!ab-d]'. The +** function returns a value of zero if Source does not match Pattern, +** otherwise a non zero value is returned. If Pattern contains an invalid +** wildcard pattern (e.g. 'A[x'), the function returns zero. +*/ /* End of matchpat.h */ #endif - - - diff --git a/src/common/mmodel.c b/src/common/mmodel.c index 7ed0f9b3f..05f2a4b27 100644 --- a/src/common/mmodel.c +++ b/src/common/mmodel.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -90,8 +90,8 @@ mmodel_t FindMemoryModel (const char* Name) void SetMemoryModel (mmodel_t Model) /* Set the memory model updating the MemoryModel variables and the address - * sizes for the segments. - */ +** sizes for the segments. +*/ { /* Remember the memory model */ MemoryModel = Model; @@ -124,5 +124,3 @@ void SetMemoryModel (mmodel_t Model) /* Zeropage is always zeropage */ ZpAddrSize = ADDR_SIZE_ZP; } - - diff --git a/src/common/mmodel.h b/src/common/mmodel.h index 043e93037..350da4423 100644 --- a/src/common/mmodel.h +++ b/src/common/mmodel.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -74,14 +74,11 @@ mmodel_t FindMemoryModel (const char* Name); void SetMemoryModel (mmodel_t Model); /* Set the memory model updating the MemoryModel variables and the address - * sizes for the segments. - */ +** sizes for the segments. +*/ /* End of mmodel.h */ #endif - - - diff --git a/src/common/objdefs.h b/src/common/objdefs.h index 608a4dc62..537ed2d57 100644 --- a/src/common/objdefs.h +++ b/src/common/objdefs.h @@ -92,6 +92,3 @@ struct ObjHeader { /* End of objdefs.h */ #endif - - - diff --git a/src/common/optdefs.h b/src/common/optdefs.h index 55264ca88..fae517667 100644 --- a/src/common/optdefs.h +++ b/src/common/optdefs.h @@ -72,6 +72,3 @@ struct Option { /* End of optdefs.h */ #endif - - - diff --git a/src/common/print.c b/src/common/print.c index 53b2aa210..70f43bc35 100644 --- a/src/common/print.c +++ b/src/common/print.c @@ -72,6 +72,3 @@ void Print (FILE* F, unsigned V, const char* Format, ...) vfprintf (F, Format, ap); va_end (ap); } - - - diff --git a/src/common/print.h b/src/common/print.h index 92b654910..d570d3ec6 100644 --- a/src/common/print.h +++ b/src/common/print.h @@ -70,7 +70,3 @@ void Print (FILE* F, unsigned V, const char* Format, ...) /* End of print.h */ #endif - - - - diff --git a/src/common/scopedefs.h b/src/common/scopedefs.h index 08a7f5ec8..31e493f2b 100644 --- a/src/common/scopedefs.h +++ b/src/common/scopedefs.h @@ -76,6 +76,3 @@ enum { /* End of scopedefs.h */ #endif - - - diff --git a/src/common/searchpath.c b/src/common/searchpath.c index 16945f36d..78443f34c 100644 --- a/src/common/searchpath.c +++ b/src/common/searchpath.c @@ -35,10 +35,12 @@ #include <stdlib.h> #include <string.h> +#if defined(_WIN32) +# include <windows.h> +#endif #if defined(_MSC_VER) /* Microsoft compiler */ # include <io.h> -# pragma warning(disable : 4996) #else /* Anyone else */ # include <unistd.h> @@ -83,7 +85,7 @@ static char* CleanupPath (const char* Path) -static void Add (SearchPath* P, const char* New) +static void Add (SearchPaths* P, const char* New) /* Cleanup a new search path and add it to the list */ { /* Add a clean copy of the path to the collection */ @@ -92,7 +94,7 @@ static void Add (SearchPath* P, const char* New) -SearchPath* NewSearchPath (void) +SearchPaths* NewSearchPath (void) /* Create a new, empty search path list */ { return NewCollection (); @@ -100,7 +102,7 @@ SearchPath* NewSearchPath (void) -void AddSearchPath (SearchPath* P, const char* NewPath) +void AddSearchPath (SearchPaths* P, const char* NewPath) /* Add a new search path to the end of an existing list */ { /* Allow a NULL path */ @@ -111,20 +113,20 @@ void AddSearchPath (SearchPath* P, const char* NewPath) -void AddSearchPathFromEnv (SearchPath* P, const char* EnvVar) +void AddSearchPathFromEnv (SearchPaths* P, const char* EnvVar) /* Add a search path from an environment variable to the end of an existing - * list. - */ +** list. +*/ { AddSearchPath (P, getenv (EnvVar)); } -void AddSubSearchPathFromEnv (SearchPath* P, const char* EnvVar, const char* SubDir) +void AddSubSearchPathFromEnv (SearchPaths* P, const char* EnvVar, const char* SubDir) /* Add a search path from an environment variable, adding a subdirectory to - * the environment variable value. - */ +** the environment variable value. +*/ { StrBuf Dir = AUTO_STRBUF_INITIALIZER; @@ -157,21 +159,20 @@ void AddSubSearchPathFromEnv (SearchPath* P, const char* EnvVar, const char* Sub -void AddSubSearchPathFromWinBin (SearchPath* P, const char* SubDir) +void AddSubSearchPathFromWinBin (SearchPaths* P, const char* SubDir) { /* Windows only: - * Add a search path from the running binary, adding a subdirectory to - * the parent directory of the directory containing the binary. - */ -#if defined(_MSC_VER) +** Add a search path from the running binary, adding a subdirectory to +** the parent directory of the directory containing the binary. +*/ +#if defined(_WIN32) char Dir[_MAX_PATH]; char* Ptr; - if (_get_pgmptr (&Ptr) != 0) { + if (GetModuleFileName (NULL, Dir, _MAX_PATH) == 0) { return; } - strcpy (Dir, Ptr); /* Remove binary name */ Ptr = strrchr (Dir, '\\'); @@ -204,11 +205,11 @@ void AddSubSearchPathFromWinBin (SearchPath* P, const char* SubDir) } -int PushSearchPath (SearchPath* P, const char* NewPath) +int PushSearchPath (SearchPaths* P, const char* NewPath) /* Add a new search path to the head of an existing search path list, provided - * that it's not already there. If the path is already at the first position, - * return zero, otherwise return a non zero value. - */ +** that it's not already there. If the path is already at the first position, +** return zero, otherwise return a non zero value. +*/ { /* Generate a clean copy of NewPath */ char* Path = CleanupPath (NewPath); @@ -227,7 +228,7 @@ int PushSearchPath (SearchPath* P, const char* NewPath) -void PopSearchPath (SearchPath* P) +void PopSearchPath (SearchPaths* P) /* Remove a search path from the head of an existing search path list */ { /* Remove the path at position 0 */ @@ -237,10 +238,10 @@ void PopSearchPath (SearchPath* P) -char* SearchFile (const SearchPath* P, const char* File) +char* SearchFile (const SearchPaths* P, const char* File) /* Search for a file in a list of directories. Return a pointer to a malloced - * area that contains the complete path, if found, return 0 otherwise. - */ +** area that contains the complete path, if found, return 0 otherwise. +*/ { char* Name = 0; StrBuf PathName = AUTO_STRBUF_INITIALIZER; @@ -271,6 +272,3 @@ char* SearchFile (const SearchPath* P, const char* File) SB_Done (&PathName); return Name; } - - - diff --git a/src/common/searchpath.h b/src/common/searchpath.h index 555a0e18e..6f5bafa7a 100644 --- a/src/common/searchpath.h +++ b/src/common/searchpath.h @@ -53,7 +53,7 @@ #define STRINGIZE(arg) _STRINGIZE(arg) /* A search path is a pointer to the list */ -typedef struct Collection SearchPath; +typedef struct Collection SearchPaths; @@ -63,46 +63,44 @@ typedef struct Collection SearchPath; -SearchPath* NewSearchPath (void); +SearchPaths* NewSearchPath (void); /* Create a new, empty search path list */ -void AddSearchPath (SearchPath* P, const char* NewPath); +void AddSearchPath (SearchPaths* P, const char* NewPath); /* Add a new search path to the end of an existing list */ -void AddSearchPathFromEnv (SearchPath* P, const char* EnvVar); +void AddSearchPathFromEnv (SearchPaths* P, const char* EnvVar); /* Add a search path from an environment variable to the end of an existing - * list. - */ +** list. +*/ -void AddSubSearchPathFromEnv (SearchPath* P, const char* EnvVar, const char* SubDir); +void AddSubSearchPathFromEnv (SearchPaths* P, const char* EnvVar, const char* SubDir); /* Add a search path from an environment variable, adding a subdirectory to - * the environment variable value. - */ +** the environment variable value. +*/ -void AddSubSearchPathFromWinBin (SearchPath* P, const char* SubDir); +void AddSubSearchPathFromWinBin (SearchPaths* P, const char* SubDir); /* Windows only: - * Add a search path from the running binary, adding a subdirectory to - * the parent directory of the directory containing the binary. - */ +** Add a search path from the running binary, adding a subdirectory to +** the parent directory of the directory containing the binary. +*/ -int PushSearchPath (SearchPath* P, const char* NewPath); +int PushSearchPath (SearchPaths* P, const char* NewPath); /* Add a new search path to the head of an existing search path list, provided - * that it's not already there. If the path is already at the first position, - * return zero, otherwise return a non zero value. - */ +** that it's not already there. If the path is already at the first position, +** return zero, otherwise return a non zero value. +*/ -void PopSearchPath (SearchPath* P); +void PopSearchPath (SearchPaths* P); /* Remove a search path from the head of an existing search path list */ -char* SearchFile (const SearchPath* P, const char* File); +char* SearchFile (const SearchPaths* P, const char* File); /* Search for a file in a list of directories. Return a pointer to a malloced - * area that contains the complete path, if found, return 0 otherwise. - */ +** area that contains the complete path, if found, return 0 otherwise. +*/ /* End of searchpath.h */ + #endif - - - diff --git a/src/common/segdefs.h b/src/common/segdefs.h index e8f6883f6..10a366582 100644 --- a/src/common/segdefs.h +++ b/src/common/segdefs.h @@ -52,6 +52,3 @@ /* End of segdefs.h */ #endif - - - diff --git a/src/common/segnames.c b/src/common/segnames.c index 2bed984ed..bb9aac351 100644 --- a/src/common/segnames.c +++ b/src/common/segnames.c @@ -65,6 +65,3 @@ int ValidSegName (const char* Name) /* Name is ok */ return 1; } - - - diff --git a/src/common/segnames.h b/src/common/segnames.h index 071cb387b..0d57d6ac3 100644 --- a/src/common/segnames.h +++ b/src/common/segnames.h @@ -68,6 +68,3 @@ int ValidSegName (const char* Name); /* End of segnames.h */ #endif - - - diff --git a/src/common/shift.c b/src/common/shift.c index 156dbd22c..16b9d0c5d 100644 --- a/src/common/shift.c +++ b/src/common/shift.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -34,16 +34,16 @@ /* According to the C standard, shifting a data type by the number of bits it - * has causes undefined behaviour. So - * - * unsigned long l = 1; - * unsigned u =32; - * l <<= u; - * - * maybe illegal. The functions in this module behave safely in this respect, - * and they use proper casting to distinguish signed from unsigned shifts. - * They are not a general purpose replacement for the shift operator! - */ +** has causes undefined behaviour. So +** +** unsigned long l = 1; +** unsigned u =32; +** l <<= u; +** +** may be illegal. The functions in this module behave safely in that respect, +** and they use proper casting to distinguish signed from unsigned shifts. +** They are not a general purpose replacement for the shift operator! +*/ @@ -125,6 +125,3 @@ unsigned long shr_l (unsigned long l, unsigned count) } return l; } - - - diff --git a/src/common/shift.h b/src/common/shift.h index 4bf96e335..9a35e52c5 100644 --- a/src/common/shift.h +++ b/src/common/shift.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -34,16 +34,16 @@ /* According to the C standard, shifting a data type by the number of bits it - * has causes undefined behaviour. So - * - * unsigned long l = 1; - * unsigned u =32; - * l <<= u; - * - * maybe illegal. The functions in this module behave safely in this respect, - * and they use proper casting to distinguish signed from unsigned shifts. - * They are not a general purpose replacement for the shift operator! - */ +** has causes undefined behaviour. So +** +** unsigned long l = 1; +** unsigned u =32; +** l <<= u; +** +** may be illegal. The functions in this module behave safely in that respect, +** and they use proper casting to distinguish signed from unsigned shifts. +** They are not a general purpose replacement for the shift operator! +*/ @@ -79,6 +79,3 @@ unsigned long shr_l (unsigned long l, unsigned count); /* End of shift.h */ #endif - - - diff --git a/src/common/strbuf.c b/src/common/strbuf.c index 029fe5ad4..79419f1c4 100644 --- a/src/common/strbuf.c +++ b/src/common/strbuf.c @@ -75,8 +75,8 @@ StrBuf* SB_Init (StrBuf* B) StrBuf* SB_InitFromString (StrBuf* B, const char* S) /* Initialize a string buffer from a literal string. Beware: The buffer won't - * store a copy but a pointer to the actual string. - */ +** store a copy but a pointer to the actual string. +*/ { B->Allocated = 0; B->Len = strlen (S); @@ -126,8 +126,8 @@ void FreeStrBuf (StrBuf* B) void SB_Realloc (StrBuf* B, unsigned NewSize) /* Reallocate the string buffer space, make sure at least NewSize bytes are - * available. - */ +** available. +*/ { /* Get the current size, use a minimum of 8 bytes */ unsigned NewAllocated = B->Allocated; @@ -141,9 +141,9 @@ void SB_Realloc (StrBuf* B, unsigned NewSize) } /* Reallocate the buffer. Beware: The allocated size may be zero while the - * length is not. This means that we have a buffer that wasn't allocated - * on the heap. - */ + ** length is not. This means that we have a buffer that wasn't allocated + ** on the heap. + */ if (B->Allocated) { /* Just reallocate the block */ B->Buf = xrealloc (B->Buf, NewAllocated); @@ -160,9 +160,9 @@ void SB_Realloc (StrBuf* B, unsigned NewSize) static void SB_CheapRealloc (StrBuf* B, unsigned NewSize) /* Reallocate the string buffer space, make sure at least NewSize bytes are - * available. This function won't copy the old buffer contents over to the new - * buffer and may be used if the old contents are overwritten later. - */ +** available. This function won't copy the old buffer contents over to the new +** buffer and may be used if the old contents are overwritten later. +*/ { /* Get the current size, use a minimum of 8 bytes */ unsigned NewAllocated = B->Allocated; @@ -214,8 +214,8 @@ void SB_Drop (StrBuf* B, unsigned Count) void SB_Terminate (StrBuf* B) /* Zero terminate the given string buffer. NOTE: The terminating zero is not - * accounted for in B->Len, if you want that, you have to use AppendChar! - */ +** accounted for in B->Len, if you want that, you have to use AppendChar! +*/ { unsigned NewLen = B->Len + 1; if (NewLen > B->Allocated) { @@ -310,8 +310,8 @@ void SB_Append (StrBuf* Target, const StrBuf* Source) #if !defined(HAVE_INLINE) void SB_Cut (StrBuf* B, unsigned Len) /* Cut the contents of B at the given length. If the current length of the - * buffer is smaller than Len, nothing will happen. - */ +** buffer is smaller than Len, nothing will happen. +*/ { if (Len < B->Len) { B->Len = Len; @@ -323,10 +323,10 @@ void SB_Cut (StrBuf* B, unsigned Len) void SB_Slice (StrBuf* Target, const StrBuf* Source, unsigned Start, unsigned Len) /* Copy a slice from Source into Target. The current contents of Target are - * destroyed. If Start is greater than the length of Source, or if Len - * characters aren't available, the result will be a buffer with less than Len - * bytes. - */ +** destroyed. If Start is greater than the length of Source, or if Len +** characters aren't available, the result will be a buffer with less than Len +** bytes. +*/ { /* Calculate the length of the resulting buffer */ if (Start >= Source->Len) { @@ -352,8 +352,8 @@ void SB_Slice (StrBuf* Target, const StrBuf* Source, unsigned Start, unsigned Le void SB_Move (StrBuf* Target, StrBuf* Source) /* Move the complete contents of Source to target. This will delete the old - * contents of Target, and Source will be empty after the call. - */ +** contents of Target, and Source will be empty after the call. +*/ { /* Free the target string */ if (Target->Allocated) { @@ -448,18 +448,18 @@ int SB_CompareStr (const StrBuf* S1, const char* S2) void SB_VPrintf (StrBuf* S, const char* Format, va_list ap) /* printf function with S as target. The function is safe, which means that - * the current contents of S are discarded, and are allocated again with - * a matching size for the output. The function will call FAIL when problems - * are detected (anything that let xsnprintf return -1). - */ +** the current contents of S are discarded, and are allocated again with +** a matching size for the output. The function will call FAIL when problems +** are detected (anything that let xsnprintf return -1). +*/ { va_list tmp; int SizeNeeded; /* Since we must determine the space needed anyway, we will try with - * the currently allocated memory. If the call succeeds, we've saved - * an allocation. If not, we have to reallocate and try again. - */ + ** the currently allocated memory. If the call succeeds, we've saved + ** an allocation. If not, we have to reallocate and try again. + */ va_copy (tmp, ap); SizeNeeded = xvsnprintf (S->Buf, S->Allocated, Format, tmp); va_end (tmp); @@ -483,16 +483,13 @@ void SB_VPrintf (StrBuf* S, const char* Format, va_list ap) void SB_Printf (StrBuf* S, const char* Format, ...) /* vprintf function with S as target. The function is safe, which means that - * the current contents of S are discarded, and are allocated again with - * a matching size for the output. The function will call FAIL when problems - * are detected (anything that let xsnprintf return -1). - */ +** the current contents of S are discarded, and are allocated again with +** a matching size for the output. The function will call FAIL when problems +** are detected (anything that let xsnprintf return -1). +*/ { va_list ap; va_start (ap, Format); SB_VPrintf (S, Format, ap); va_end (ap); } - - - diff --git a/src/common/strbuf.h b/src/common/strbuf.h index 4d90637d5..e0602a6c8 100644 --- a/src/common/strbuf.h +++ b/src/common/strbuf.h @@ -95,10 +95,10 @@ StrBuf* SB_Init (StrBuf* B); StrBuf* SB_InitFromString (StrBuf* B, const char* S); /* Initialize a string buffer from a literal string. Beware: The buffer won't - * store a copy but a pointer to the actual string. A buffer initialized with - * this routine may be "forgotten" without calling SB_Done, since no memory - * has been allocated. - */ +** store a copy but a pointer to the actual string. A buffer initialized with +** this routine may be "forgotten" without calling SB_Done, since no memory +** has been allocated. +*/ void SB_Done (StrBuf* B); /* Free the data of a string buffer (but not the struct itself) */ @@ -111,8 +111,8 @@ void FreeStrBuf (StrBuf* B); void SB_Realloc (StrBuf* B, unsigned NewSize); /* Reallocate the string buffer space, make sure at least NewSize bytes are - * available. - */ +** available. +*/ #if defined(HAVE_INLINE) INLINE unsigned SB_GetLen (const StrBuf* B) @@ -229,8 +229,8 @@ INLINE void SB_Reset (StrBuf* B) #if defined(HAVE_INLINE) INLINE char SB_Get (StrBuf* B) /* Return the next character from the string incrementing Index. Returns NUL - * if the end of the string is reached. - */ +** if the end of the string is reached. +*/ { return (B->Index < B->Len)? B->Buf[B->Index++] : '\0'; } @@ -241,8 +241,8 @@ INLINE char SB_Get (StrBuf* B) #if defined(HAVE_INLINE) INLINE char SB_Peek (const StrBuf* B) /* Look at the next character from the string without incrementing Index. - * Returns NUL if the end of the string is reached. - */ +** Returns NUL if the end of the string is reached. +*/ { return (B->Index < B->Len)? B->Buf[B->Index] : '\0'; } @@ -253,8 +253,8 @@ INLINE char SB_Peek (const StrBuf* B) #if defined(HAVE_INLINE) INLINE char SB_LookAt (const StrBuf* B, unsigned Index) /* Look at a specific character from the string. Returns NUL if the given - * index is greater than the size of the string. - */ +** index is greater than the size of the string. +*/ { return (Index < B->Len)? B->Buf[Index] : '\0'; } @@ -265,8 +265,8 @@ INLINE char SB_LookAt (const StrBuf* B, unsigned Index) #if defined(HAVE_INLINE) INLINE char SB_LookAtLast (const StrBuf* B) /* Look at the last character from the string. Returns NUL if the string buffer - * is empty. - */ +** is empty. +*/ { return (B->Len > 0)? B->Buf[B->Len-1] : '\0'; } @@ -304,8 +304,8 @@ void SB_Drop (StrBuf* B, unsigned Count); void SB_Terminate (StrBuf* B); /* Zero terminate the given string buffer. NOTE: The terminating zero is not - * accounted for in B->Len, if you want that, you have to use AppendChar! - */ +** accounted for in B->Len, if you want that, you have to use AppendChar! +*/ void SB_CopyBuf (StrBuf* Target, const char* Buf, unsigned Size); /* Copy Buf to Target, discarding the old contents of Target */ @@ -364,8 +364,8 @@ void SB_Append (StrBuf* Target, const StrBuf* Source); #if defined(HAVE_INLINE) INLINE void SB_Cut (StrBuf* B, unsigned Len) /* Cut the contents of B at the given length. If the current length of the - * buffer is smaller than Len, nothing will happen. - */ +** buffer is smaller than Len, nothing will happen. +*/ { if (Len < B->Len) { B->Len = Len; @@ -374,21 +374,21 @@ INLINE void SB_Cut (StrBuf* B, unsigned Len) #else void SB_Cut (StrBuf* B, unsigned Len); /* Cut the contents of B at the given length. If the current length of the - * buffer is smaller than Len, nothing will happen. - */ +** buffer is smaller than Len, nothing will happen. +*/ #endif void SB_Slice (StrBuf* Target, const StrBuf* Source, unsigned Start, unsigned Len); /* Copy a slice from Source into Target. The current contents of Target are - * destroyed. If Start is greater than the length of Source, or if Len - * characters aren't available, the result will be a buffer with less than Len - * bytes. - */ +** destroyed. If Start is greater than the length of Source, or if Len +** characters aren't available, the result will be a buffer with less than Len +** bytes. +*/ void SB_Move (StrBuf* Target, StrBuf* Source); /* Move the complete contents of Source to target. This will delete the old - * contents of Target, and Source will be empty after the call. - */ +** contents of Target, and Source will be empty after the call. +*/ void SB_ToLower (StrBuf* S); /* Convert all characters in S to lower case */ @@ -404,23 +404,20 @@ int SB_CompareStr (const StrBuf* S1, const char* S2); void SB_VPrintf (StrBuf* S, const char* Format, va_list ap) attribute ((format (printf, 2, 0))); /* printf function with S as target. The function is safe, which means that - * the current contents of S are discarded, and are allocated again with - * a matching size for the output. The function will call FAIL when problems - * are detected (anything that let xsnprintf return -1). - */ +** the current contents of S are discarded, and are allocated again with +** a matching size for the output. The function will call FAIL when problems +** are detected (anything that let xsnprintf return -1). +*/ void SB_Printf (StrBuf* S, const char* Format, ...) attribute ((format (printf, 2, 3))); /* vprintf function with S as target. The function is safe, which means that - * the current contents of S are discarded, and are allocated again with - * a matching size for the output. The function will call FAIL when problems - * are detected (anything that let xsnprintf return -1). - */ +** the current contents of S are discarded, and are allocated again with +** a matching size for the output. The function will call FAIL when problems +** are detected (anything that let xsnprintf return -1). +*/ /* End of strbuf.h */ #endif - - - diff --git a/src/common/strpool.c b/src/common/strpool.c index 963ecaf0a..244681afd 100644 --- a/src/common/strpool.c +++ b/src/common/strpool.c @@ -34,11 +34,11 @@ /* A string pool is used to store identifiers and other strings. Each string - * stored in the pool has a unique id, which may be used to access the string - * in the pool. Identical strings are stored only once in the pool and have - * identical ids. This means that instead of comparing strings, just the - * string pool ids must be compared. - */ +** stored in the pool has a unique id, which may be used to access the string +** in the pool. Identical strings are stored only once in the pool and have +** identical ids. This means that instead of comparing strings, just the +** string pool ids must be compared. +*/ @@ -68,9 +68,9 @@ static const void* HT_GetKey (const void* Entry); static int HT_Compare (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if - * Key1 is smaller than Key2, zero if both are equal, and a value greater - * than zero if Key1 is greater then Key2. - */ +** Key1 is smaller than Key2, zero if both are equal, and a value greater +** than zero if Key1 is greater then Key2. +*/ @@ -154,9 +154,9 @@ static const void* HT_GetKey (const void* Entry) static int HT_Compare (const void* Key1, const void* Key2) /* Compare two keys. The function must return a value less than zero if - * Key1 is smaller than Key2, zero if both are equal, and a value greater - * than zero if Key1 is greater then Key2. - */ +** Key1 is smaller than Key2, zero if both are equal, and a value greater +** than zero if Key1 is greater then Key2. +*/ { return SB_Compare (Key1, Key2); } @@ -228,9 +228,9 @@ const StrBuf* SP_Get (const StringPool* P, unsigned Index) unsigned SP_Add (StringPool* P, const StrBuf* S) /* Add a string buffer to the buffer and return the index. If the string does - * already exist in the pool, SP_AddBuf will just return the index of the - * existing string. - */ +** already exist in the pool, SP_AddBuf will just return the index of the +** existing string. +*/ { /* Search for a matching entry in the hash table */ StringPoolEntry* E = HT_Find (&P->Tab, S); @@ -259,14 +259,14 @@ unsigned SP_Add (StringPool* P, const StrBuf* S) unsigned SP_AddStr (StringPool* P, const char* S) /* Add a string to the buffer and return the index. If the string does already - * exist in the pool, SP_Add will just return the index of the existing string. - */ +** exist in the pool, SP_Add will just return the index of the existing string. +*/ { unsigned Id; /* First make a string buffer, then add it. This is some overhead, but the - * routine will probably go. - */ + ** routine will probably go. + */ StrBuf Buf; Id = SP_Add (P, SB_InitFromString (&Buf, S)); @@ -281,6 +281,3 @@ unsigned SP_GetCount (const StringPool* P) { return CollCount (&P->Entries); } - - - diff --git a/src/common/strpool.h b/src/common/strpool.h index 60b8b3451..8a6a8faee 100644 --- a/src/common/strpool.h +++ b/src/common/strpool.h @@ -34,11 +34,11 @@ /* A string pool is used to store identifiers and other strings. Each string - * stored in the pool has a unique id, which may be used to access the string - * in the pool. Identical strings are only stored once in the pool and have - * identical ids. This means that instead of comparing strings, just the - * string pool ids must be compared. - */ +** stored in the pool has a unique ID, which may be used to access the string +** in the pool. Identical strings are only stored once in the pool and have +** identical IDs. This means that instead of comparing strings, just the +** string pool IDs must be compared. +*/ @@ -84,14 +84,14 @@ const StrBuf* SP_Get (const StringPool* P, unsigned Index); unsigned SP_Add (StringPool* P, const StrBuf* S); /* Add a string buffer to the buffer and return the index. If the string does - * already exist in the pool, SP_AddBuf will just return the index of the - * existing string. - */ +** already exist in the pool, SP_AddBuf will just return the index of the +** existing string. +*/ unsigned SP_AddStr (StringPool* P, const char* S); /* Add a string to the buffer and return the index. If the string does already - * exist in the pool, SP_Add will just return the index of the existing string. - */ +** exist in the pool, SP_Add will just return the index of the existing string. +*/ unsigned SP_GetCount (const StringPool* P); /* Return the number of strings in the pool */ @@ -101,6 +101,3 @@ unsigned SP_GetCount (const StringPool* P); /* End of strpool.h */ #endif - - - diff --git a/src/common/strstack.c b/src/common/strstack.c index c316399b2..508af178e 100644 --- a/src/common/strstack.c +++ b/src/common/strstack.c @@ -80,6 +80,3 @@ void SS_Push (StrStack* S, const char* Val) CHECK (S->Count < sizeof (S->Stack) / sizeof (S->Stack[0])); S->Stack[S->Count++] = xstrdup (Val); } - - - diff --git a/src/common/strstack.h b/src/common/strstack.h index 6331241de..d29a47993 100644 --- a/src/common/strstack.h +++ b/src/common/strstack.h @@ -100,7 +100,5 @@ void SS_Push (StrStack* S, const char* Val); /* End of strstack.h */ + #endif - - - diff --git a/src/common/strutil.c b/src/common/strutil.c index 1cab51869..dabed34cd 100644 --- a/src/common/strutil.c +++ b/src/common/strutil.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2001-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -49,9 +49,9 @@ char* StrCopy (char* Dest, size_t DestSize, const char* Source) /* Copy Source to Dest honouring the maximum size of the target buffer. In - * constrast to strncpy, the resulting string will always be NUL terminated. - * The function returns the pointer to the destintation buffer. - */ +** constrast to strncpy, the resulting string will always be NUL terminated. +** The function returns the pointer to the destintation buffer. +*/ { size_t Len = strlen (Source); if (Len >= DestSize) { diff --git a/src/common/strutil.h b/src/common/strutil.h index 24daa222a..61dd74b64 100644 --- a/src/common/strutil.h +++ b/src/common/strutil.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2001-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -50,9 +50,9 @@ char* StrCopy (char* Dest, size_t DestSize, const char* Source); /* Copy Source to Dest honouring the maximum size of the target buffer. In - * constrast to strncpy, the resulting string will always be NUL terminated. - * The function returns the pointer to the destintation buffer. - */ +** constrast to strncpy, the resulting string will always be NUL terminated. +** The function returns the pointer to the destintation buffer. +*/ int StrCaseCmp (const char* S1, const char* S2); /* Compare two strings ignoring case */ @@ -62,6 +62,3 @@ int StrCaseCmp (const char* S1, const char* S2); /* End of strutil.h */ #endif - - - diff --git a/src/common/symdefs.h b/src/common/symdefs.h index fbe0bc168..1a487e0f3 100644 --- a/src/common/symdefs.h +++ b/src/common/symdefs.h @@ -103,6 +103,3 @@ /* End of symdefs.h */ #endif - - - diff --git a/src/common/target.c b/src/common/target.c index d8d3f9c54..b909e4d70 100644 --- a/src/common/target.c +++ b/src/common/target.c @@ -119,12 +119,13 @@ struct TargetEntry { }; /* Table that maps target names to ids. Sorted alphabetically for bsearch. - * Allows multiple entries for one target id (target name aliases). - */ +** Allows mupltiple entries for one target id (target name aliases). +*/ static const TargetEntry TargetMap[] = { { "apple2", TGT_APPLE2 }, { "apple2enh", TGT_APPLE2ENH }, { "atari", TGT_ATARI }, + { "atari5200", TGT_ATARI5200 }, { "atarixl", TGT_ATARIXL }, { "atmos", TGT_ATMOS }, { "bbc", TGT_BBC }, @@ -158,6 +159,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = { { "none", CPU_6502, BINFMT_BINARY, CTNone }, { "module", CPU_6502, BINFMT_O65, CTNone }, { "atari", CPU_6502, BINFMT_BINARY, CTAtari }, + { "atari5200", CPU_6502, BINFMT_BINARY, CTAtari }, { "atarixl", CPU_6502, BINFMT_BINARY, CTAtari }, { "vic20", CPU_6502, BINFMT_BINARY, CTPET }, { "c16", CPU_6502, BINFMT_BINARY, CTPET }, @@ -203,8 +205,8 @@ static int Compare (const void* Key, const void* Entry) target_t FindTarget (const char* Name) /* Find a target by name and return the target id. TGT_UNKNOWN is returned if - * the given name is no valid target. - */ +** the given name is no valid target. +*/ { /* Search for the name in the map */ const TargetEntry* T; @@ -234,4 +236,3 @@ const char* GetTargetName (target_t Target) /* Return the array entry */ return GetTargetProperties (Target)->Name; } - diff --git a/src/common/target.h b/src/common/target.h index 47946a309..067352deb 100644 --- a/src/common/target.h +++ b/src/common/target.h @@ -55,6 +55,7 @@ typedef enum { TGT_NONE, TGT_MODULE, TGT_ATARI, + TGT_ATARI5200, TGT_ATARIXL, TGT_VIC20, TGT_C16, @@ -107,8 +108,8 @@ extern target_t Target; target_t FindTarget (const char* Name); /* Find a target by name and return the target id. TGT_UNKNOWN is returned if - * the given name is no valid target. - */ +** the given name is no valid target. +*/ const TargetProperties* GetTargetProperties (target_t Target); /* Return the properties for a target */ @@ -119,7 +120,5 @@ const char* GetTargetName (target_t Target); /* End of target.h */ + #endif - - - diff --git a/src/common/tgttrans.c b/src/common/tgttrans.c index a1b61cbd3..95bdf8662 100644 --- a/src/common/tgttrans.c +++ b/src/common/tgttrans.c @@ -87,8 +87,8 @@ void TgtTranslateInit (void) int TgtTranslateChar (int C) /* Translate one character from the source character set into the target - * system character set. - */ +** system character set. +*/ { /* Translate */ return Tab[C & 0xFF]; @@ -98,8 +98,8 @@ int TgtTranslateChar (int C) void TgtTranslateBuf (void* Buf, unsigned Len) /* Translate a buffer of the given length from the source character set into - * the target system character set. - */ +** the target system character set. +*/ { /* Translate */ unsigned char* B = (unsigned char*)Buf; @@ -113,8 +113,8 @@ void TgtTranslateBuf (void* Buf, unsigned Len) void TgtTranslateStrBuf (StrBuf* Buf) /* Translate a string buffer from the source character set into the target - * system character set. - */ +** system character set. +*/ { TgtTranslateBuf (SB_GetBuf (Buf), SB_GetLen (Buf)); } @@ -127,8 +127,3 @@ void TgtTranslateSet (unsigned Index, unsigned char C) CHECK (Index > 0 && Index < sizeof (Tab)); Tab[Index] = C; } - - - - - diff --git a/src/common/tgttrans.h b/src/common/tgttrans.h index e4f08f71a..46981ec0f 100644 --- a/src/common/tgttrans.h +++ b/src/common/tgttrans.h @@ -54,18 +54,18 @@ void TgtTranslateInit (void); int TgtTranslateChar (int C); /* Translate one character from the source character set into the target - * system character set. - */ +** system character set. +*/ void TgtTranslateBuf (void* Buf, unsigned Len); /* Translate a buffer of the given length from the source character set into - * the target system character set. - */ +** the target system character set. +*/ void TgtTranslateStrBuf (StrBuf* Buf); /* Translate a string buffer from the source character set into the target - * system character set. - */ +** system character set. +*/ void TgtTranslateSet (unsigned Index, unsigned char C); /* Set the translation code for the given character */ @@ -75,6 +75,3 @@ void TgtTranslateSet (unsigned Index, unsigned char C); /* End of tgttrans.h */ #endif - - - diff --git a/src/common/va_copy.h b/src/common/va_copy.h index 30f275461..2f56efa1a 100644 --- a/src/common/va_copy.h +++ b/src/common/va_copy.h @@ -74,7 +74,5 @@ /* End of va_copy.h */ + #endif - - - diff --git a/src/common/version.c b/src/common/version.c index e5d52c02d..d2fcf4f40 100644 --- a/src/common/version.c +++ b/src/common/version.c @@ -33,8 +33,10 @@ -#include "version.h" +/* common */ #include "xsprintf.h" +#include "searchpath.h" +#include "version.h" @@ -46,9 +48,6 @@ #define VER_MAJOR 2U #define VER_MINOR 14U -#define VER_PATCH 0U -#define VER_RC 0U - @@ -61,11 +60,11 @@ const char* GetVersionAsString (void) /* Returns the version number as a string in a static buffer */ { - static char Buf[20]; -#if defined(VER_RC) && (VER_RC > 0U) - xsnprintf (Buf, sizeof (Buf), "%u.%u.%u-rc%u", VER_MAJOR, VER_MINOR, VER_PATCH, VER_RC); + static char Buf[60]; +#if defined(GIT_SHA) + xsnprintf (Buf, sizeof (Buf), "%u.%u - Git %s", VER_MAJOR, VER_MINOR, STRINGIZE (GIT_SHA)); #else - xsnprintf (Buf, sizeof (Buf), "%u.%u.%u", VER_MAJOR, VER_MINOR, VER_PATCH); + xsnprintf (Buf, sizeof (Buf), "%u.%u", VER_MAJOR, VER_MINOR); #endif return Buf; } @@ -75,8 +74,5 @@ const char* GetVersionAsString (void) unsigned GetVersionAsNumber (void) /* Returns the version number as a combined unsigned for use in a #define */ { - return ((VER_MAJOR * 0x100) + (VER_MINOR * 0x10) + VER_PATCH); + return ((VER_MAJOR * 0x100) + (VER_MINOR * 0x10)); } - - - diff --git a/src/common/version.h b/src/common/version.h index edf5d2c56..145c2eddd 100644 --- a/src/common/version.h +++ b/src/common/version.h @@ -55,7 +55,3 @@ unsigned GetVersionAsNumber (void); /* End of version.h */ #endif - - - - diff --git a/src/common/xmalloc.c b/src/common/xmalloc.c index 1a7b915ab..327d378fe 100644 --- a/src/common/xmalloc.c +++ b/src/common/xmalloc.c @@ -125,6 +125,3 @@ void* xdup (const void* Buf, size_t Size) { return memcpy (xmalloc (Size), Buf, Size); } - - - diff --git a/src/common/xmalloc.h b/src/common/xmalloc.h index 3979a9617..eb196b6a1 100644 --- a/src/common/xmalloc.h +++ b/src/common/xmalloc.h @@ -68,6 +68,3 @@ void* xdup (const void* Buf, size_t Size); /* End of xmalloc.h */ #endif - - - diff --git a/src/common/xsprintf.c b/src/common/xsprintf.c index c33f32b24..d50ad7a68 100644 --- a/src/common/xsprintf.c +++ b/src/common/xsprintf.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2000-2004 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -55,12 +55,12 @@ /* The following is a very basic vsnprintf like function called xvsnprintf. It - * features only the basic format specifiers (especially the floating point - * stuff is missing), but may be extended if required. Reason for supplying - * my own implementation is that vsnprintf is standard but not implemented by - * older compilers, and some that implement it, don't adhere to the standard - * (for example Microsoft with its _vsnprintf). - */ +** features only the basic format specifiers (especially the floating point +** stuff is missing), but may be extended if required. Reason for supplying +** my own implementation is that vsnprintf is standard but not implemented by +** older compilers, and some that implement it, don't adhere to the standard +** (for example Microsoft with its _vsnprintf). +*/ typedef struct { @@ -73,9 +73,9 @@ typedef struct { size_t BufFill; /* Argument string buffer and string buffer pointer. The string buffer - * must be big enough to hold a converted integer of the largest type - * including an optional sign and terminating zero. - */ + ** must be big enough to hold a converted integer of the largest type + ** including an optional sign and terminating zero. + */ char ArgBuf[256]; int ArgLen; @@ -223,9 +223,9 @@ static void FormatInt (PrintfCtrl* P, uintmax_t Val) ToStr (P, Val); /* The default precision for all integer conversions is one. This means - * that the fPrec flag is always set and does not need to be checked - * later on. - */ + ** that the fPrec flag is always set and does not need to be checked + ** later on. + */ if ((P->Flags & fPrec) == 0) { P->Flags |= fPrec; P->Prec = 1; @@ -305,9 +305,9 @@ static void FormatStr (PrintfCtrl* P, const char* Val) unsigned WidthPadding; /* Get the string length limited to the precision. Beware: We cannot use - * strlen here, because if a precision is given, the string may not be - * zero terminated. - */ + ** strlen here, because if a precision is given, the string may not be + ** zero terminated. + */ int Len; if ((P->Flags & fPrec) != 0) { const char* S = memchr (Val, '\0', P->Prec); @@ -367,8 +367,8 @@ static void StoreOffset (PrintfCtrl* P) int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap) /* A basic vsnprintf implementation. Does currently only support integer - * formats. - */ +** formats. +*/ { PrintfCtrl P; int Done; @@ -418,8 +418,8 @@ int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap) if (F == '*') { P.Width = va_arg (P.ap, int); /* A negative field width argument is taken as a - flag followed - * by a positive field width. - */ + ** by a positive field width. + */ if (P.Width < 0) { P.Flags |= fMinus; P.Width = -P.Width; @@ -445,8 +445,8 @@ int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap) if (F == '*') { P.Prec = va_arg (P.ap, int); /* A negative precision argument is taken as if the precision - * were omitted. - */ + ** were omitted. + */ if (P.Prec < 0) { P.Flags &= ~fPrec; } @@ -462,8 +462,8 @@ int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap) } } else if (F == '-') { /* A negative precision argument is taken as if the precision - * were omitted. - */ + ** were omitted. + */ F = *Format++; /* Skip the minus */ while (IsDigit (F = *Format++)) ; P.Flags &= ~fPrec; @@ -581,8 +581,8 @@ int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap) /* Handle the length by using a precision */ if ((P.Flags & fPrec) != 0) { /* Precision already specified, use length of string - * if less. - */ + ** if less. + */ if ((unsigned) P.Prec > SB_GetLen (S)) { P.Prec = SB_GetLen (S); } @@ -622,9 +622,9 @@ int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap) va_end (P.ap); /* Terminate the output string and return the number of chars that had - * been written if the buffer was large enough. - * Beware: The terminating zero is not counted for the function result! - */ + ** been written if the buffer was large enough. + ** Beware: The terminating zero is not counted for the function result! + */ AddChar (&P, '\0'); return P.BufFill - 1; } @@ -633,8 +633,8 @@ int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap) int xsnprintf (char* Buf, size_t Size, const char* Format, ...) /* A basic snprintf implementation. Does currently only support integer - * formats. - */ +** formats. +*/ { int Res; va_list ap; @@ -676,6 +676,3 @@ int xvsprintf (char* Buf, size_t BufSize, const char* Format, va_list ap) CHECK (Res >= 0 && (unsigned) (Res+1) < BufSize); return Res; } - - - diff --git a/src/common/xsprintf.h b/src/common/xsprintf.h index 07672c5c4..a37b71914 100644 --- a/src/common/xsprintf.h +++ b/src/common/xsprintf.h @@ -34,14 +34,14 @@ /* We need a way to output a StrBuf, but on the other side, we don't want to - * switch off gcc's printf format string checking. So we cheat as follows: - * %m (which is a gcc extension and doesn't take an argument) switches %p - * between outputting a pointer and a string buf. This works just one time, - * so each StrBuf needs in fact a %m%p spec. There's no way to apply a width - * and precision to such a StrBuf, but *not* using %p would bring up a warning - * about a wrong argument type each time. Maybe gcc will one day allow custom - * format specifiers and we can change this ... - */ +** switch off gcc's printf format string checking. So we cheat as follows: +** %m (which is a gcc extension and doesn't take an argument) switches %p +** between outputting a pointer and a string buf. This works just one time, +** so each StrBuf needs in fact a %m%p spec. There's no way to apply a width +** and precision to such a StrBuf, but *not* using %p would bring up a warning +** about a wrong argument type each time. Maybe gcc will one day allow custom +** format specifiers and we can change this ... +*/ @@ -66,14 +66,14 @@ int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap) attribute ((format (printf, 3, 0))); /* A basic vsnprintf implementation. Does currently only support integer - * formats. - */ +** formats. +*/ int xsnprintf (char* Buf, size_t Size, const char* Format, ...) attribute ((format (printf, 3, 4))); /* A basic snprintf implementation. Does currently only support integer - * formats. - */ +** formats. +*/ int xsprintf (char* Buf, size_t BufSize, const char* Format, ...) attribute ((format (printf, 3, 4))); @@ -88,7 +88,3 @@ int xvsprintf (char* Buf, size_t BufSize, const char* Format, va_list ap) /* End of xsprintf.h */ #endif - - - - diff --git a/src/da65.vcxproj b/src/da65.vcxproj index a71e46a65..7810844dc 100644 --- a/src/da65.vcxproj +++ b/src/da65.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -18,10 +18,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -47,7 +49,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> @@ -62,7 +64,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> diff --git a/src/da65/asminc.c b/src/da65/asminc.c index 079b751ba..06a397d52 100644 --- a/src/da65/asminc.c +++ b/src/da65/asminc.c @@ -168,8 +168,8 @@ void AsmInc (const char* Filename, char CommentStart, int IgnoreUnknown) } /* Determine the base of the number. Allow $ and % as prefixes for - * hex and binary numbers respectively. - */ + ** hex and binary numbers respectively. + */ if (*L == '$') { Base = 16; ++L; @@ -233,6 +233,3 @@ void AsmInc (const char* Filename, char CommentStart, int IgnoreUnknown) /* Close the include file ignoring errors (we were just reading). */ (void) fclose (F); } - - - diff --git a/src/da65/asminc.h b/src/da65/asminc.h index 8c375b67e..bf48710e9 100644 --- a/src/da65/asminc.h +++ b/src/da65/asminc.h @@ -50,7 +50,5 @@ void AsmInc (const char* Filename, char CommentStart, int IgnoreUnknown); /* End of asminc.h */ + #endif - - - diff --git a/src/da65/attrtab.c b/src/da65/attrtab.c index 07a47b72e..1cfb5ba45 100644 --- a/src/da65/attrtab.c +++ b/src/da65/attrtab.c @@ -178,6 +178,3 @@ attr_t GetLabelAttr (unsigned Addr) /* Return the attribute */ return (AttrTab[Addr] & atLabelMask); } - - - diff --git a/src/da65/attrtab.h b/src/da65/attrtab.h index b1caf083d..c9fb9c35f 100644 --- a/src/da65/attrtab.h +++ b/src/da65/attrtab.h @@ -114,7 +114,5 @@ attr_t GetLabelAttr (unsigned Addr); /* End of attrtab.h */ + #endif - - - diff --git a/src/da65/code.c b/src/da65/code.c index c94fa24cd..9aff732b3 100644 --- a/src/da65/code.c +++ b/src/da65/code.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -98,8 +98,8 @@ void LoadCode (void) } /* Seek to the input offset and correct size to contain the remainder of - * the file. - */ + ** the file. + */ if (fseek (F, InputOffs, SEEK_SET) != 0) { Error ("Cannot seek on file `%s': %s", InFile, strerror (errno)); } @@ -114,9 +114,9 @@ void LoadCode (void) } /* If the start address was not given, set it so that the code loads to - * 0x10000 - Size. This is a reasonable default assuming that the file - * is a ROM that contains the hardware vectors at $FFFA. - */ + ** 0x10000 - Size. This is a reasonable default assuming that the file + ** is a ROM that contains the hardware vectors at $FFFA. + */ if (StartAddr < 0) { if (Size > 0x10000) { StartAddr = 0; @@ -219,6 +219,3 @@ void ResetCode (void) { PC = CodeStart; } - - - diff --git a/src/da65/code.h b/src/da65/code.h index e4d95a03b..0d21e61e1 100644 --- a/src/da65/code.h +++ b/src/da65/code.h @@ -84,7 +84,5 @@ void ResetCode (void); /* End of code.h */ + #endif - - - diff --git a/src/da65/comments.c b/src/da65/comments.c index 4702cf9d7..64b64ca28 100644 --- a/src/da65/comments.c +++ b/src/da65/comments.c @@ -85,6 +85,3 @@ const char* GetComment (unsigned Addr) /* Return the label if any */ return CommentTab[Addr]; } - - - diff --git a/src/da65/comments.h b/src/da65/comments.h index 0e235d31d..1b8bc1771 100644 --- a/src/da65/comments.h +++ b/src/da65/comments.h @@ -57,7 +57,5 @@ const char* GetComment (unsigned Addr); /* End of comments.h */ + #endif - - - diff --git a/src/da65/data.c b/src/da65/data.c index 0e2f7f275..f4c37818f 100644 --- a/src/da65/data.c +++ b/src/da65/data.c @@ -57,9 +57,9 @@ static unsigned GetSpan (attr_t Style) unsigned RemainingBytes = GetRemainingBytes (); /* Count how many bytes are available. This number is limited by the - * number of remaining bytes, a label, a segment change, or the end of - * the given Style attribute. - */ + ** number of remaining bytes, a label, a segment change, or the end of + ** the given Style attribute. + */ unsigned Count = 1; while (Count < RemainingBytes) { attr_t Attr; @@ -91,9 +91,9 @@ static unsigned DoTable (attr_t Style, unsigned MemberSize, void (*TableFunc) (u unsigned Count = GetSpan (Style); /* If the count is less than the member size, print a row of Count data - * bytes. We assume here that there is no member with a size that is less - * than BytesPerLine. - */ + ** bytes. We assume here that there is no member with a size that is less + ** than BytesPerLine. + */ if (Count < MemberSize) { DataByteLine (Count); PC += Count; @@ -172,8 +172,8 @@ unsigned AddrTable (void) unsigned long Start = PC; /* Loop while table bytes left and we don't need to create a label at the - * current position. - */ + ** current position. + */ while (BytesLeft && GetStyleAttr (PC) == atAddrTab) { unsigned Addr; @@ -238,8 +238,8 @@ unsigned RtsTable (void) unsigned long Start = PC; /* Loop while table bytes left and we don't need to create a label at the - * current position. - */ + ** current position. + */ while (BytesLeft && GetStyleAttr (PC) == atRtsTab) { unsigned Addr; @@ -373,6 +373,3 @@ unsigned TextTable (void) /* Return the number of bytes output */ return ByteCount; } - - - diff --git a/src/da65/data.h b/src/da65/data.h index 37c0df04a..4cec14a03 100644 --- a/src/da65/data.h +++ b/src/da65/data.h @@ -68,7 +68,5 @@ unsigned TextTable (void); /* End of data.h */ + #endif - - - diff --git a/src/da65/error.c b/src/da65/error.c index e0d96c9fb..d09dadcbb 100644 --- a/src/da65/error.c +++ b/src/da65/error.c @@ -86,6 +86,3 @@ void Internal (const char* Format, ...) va_end (ap); exit (EXIT_FAILURE); } - - - diff --git a/src/da65/error.h b/src/da65/error.h index b8de97286..d0221bcc4 100644 --- a/src/da65/error.h +++ b/src/da65/error.h @@ -63,6 +63,3 @@ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)) /* End of error.h */ #endif - - - diff --git a/src/da65/global.c b/src/da65/global.c index 14f9982d0..e2b1fd144 100644 --- a/src/da65/global.c +++ b/src/da65/global.c @@ -77,6 +77,3 @@ unsigned ACol = 17; /* Argument column */ unsigned CCol = 49; /* Comment column */ unsigned TCol = 81; /* Text bytes column */ unsigned BytesPerLine = 8; /* Max. number of data bytes per line */ - - - diff --git a/src/da65/global.h b/src/da65/global.h index b48805157..14b113399 100644 --- a/src/da65/global.h +++ b/src/da65/global.h @@ -112,6 +112,3 @@ extern unsigned BytesPerLine; /* End of global.h */ #endif - - - diff --git a/src/da65/handler.c b/src/da65/handler.c index 1b26fca7e..0806301fe 100644 --- a/src/da65/handler.c +++ b/src/da65/handler.c @@ -93,8 +93,8 @@ static void OneLine (const OpcDesc* D, const char* Arg, ...) static const char* GetAbsOverride (unsigned Flags, unsigned Addr) /* If the instruction requires an abs override modifier, return the necessary - * string, otherwise return the empty string. - */ +** string, otherwise return the empty string. +*/ { if ((Flags & flAbsOverride) != 0 && Addr < 0x100) { return "a:"; @@ -137,10 +137,10 @@ static void GenerateLabel (unsigned Flags, unsigned Addr) ((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd))) { /* As a special case, handle ranges with tables or similar. Within - * such a range with a granularity > 1, do only generate dependent - * labels for all addresses but the first one. Be sure to generate - * a label for the start of the range, however. - */ + ** such a range with a granularity > 1, do only generate dependent + ** labels for all addresses but the first one. Be sure to generate + ** a label for the start of the range, however. + */ attr_t Style = GetStyleAttr (Addr); unsigned Granularity = GetGranularity (Style); @@ -153,8 +153,8 @@ static void GenerateLabel (unsigned Flags, unsigned Addr) /* Search for the start of the range or the last non dependent - * label in the range. - */ + ** label in the range. + */ unsigned Offs; attr_t LabelAttr; unsigned LabelAddr = Addr; @@ -414,10 +414,10 @@ void OH_BitBranch (const OpcDesc* D) unsigned BranchAddr = (((int) PC+3) + BranchOffs) & 0xFFFF; /* Generate labels in pass 1. The bit branch codes are special in that - * they don't really match the remainder of the 6502 instruction set (they - * are a Rockwell addon), so we must pass additional flags as direct - * value to the second GenerateLabel call. - */ + ** they don't really match the remainder of the 6502 instruction set (they + ** are a Rockwell addon), so we must pass additional flags as direct + ** value to the second GenerateLabel call. + */ GenerateLabel (D->Flags, TestAddr); GenerateLabel (flLabel, BranchAddr); @@ -662,6 +662,3 @@ void OH_JmpAbsoluteIndirect (const OpcDesc* D) } SeparatorLine (); } - - - diff --git a/src/da65/handler.h b/src/da65/handler.h index fddcfba25..77da618c1 100644 --- a/src/da65/handler.h +++ b/src/da65/handler.h @@ -103,7 +103,5 @@ void OH_JmpAbsoluteIndirect (const OpcDesc* D); /* End of handler.h */ + #endif - - - diff --git a/src/da65/infofile.c b/src/da65/infofile.c index 4b1857dc5..4ee1ffd79 100644 --- a/src/da65/infofile.c +++ b/src/da65/infofile.c @@ -837,9 +837,3 @@ void ReadInfoFile (void) InfoCloseInput (); } } - - - - - - diff --git a/src/da65/infofile.h b/src/da65/infofile.h index 0bfeb79b8..b8b3f53a8 100644 --- a/src/da65/infofile.h +++ b/src/da65/infofile.h @@ -50,7 +50,5 @@ void ReadInfoFile (void); /* End of infofile.h */ + #endif - - - diff --git a/src/da65/labels.c b/src/da65/labels.c index c837b17a6..547a79869 100644 --- a/src/da65/labels.c +++ b/src/da65/labels.c @@ -70,8 +70,8 @@ static const char* SymTab[0x10000]; static const char* MakeLabelName (unsigned Addr) /* Make the default label name from the given address and return it in a - * static buffer. - */ +** static buffer. +*/ { static char LabelBuf [32]; xsprintf (LabelBuf, sizeof (LabelBuf), "L%04X", Addr); @@ -89,8 +89,8 @@ static void AddLabel (unsigned Addr, attr_t Attr, const char* Name) /* Must not have two symbols for one address */ if (ExistingAttr != atNoLabel) { /* Allow redefinition if identical. Beware: Unnamed labels don't - * have a name (you guessed that, didn't you?). - */ + ** have a name (you guessed that, didn't you?). + */ if (ExistingAttr == Attr && ((Name == 0 && SymTab[Addr] == 0) || strcmp (SymTab[Addr], Name) == 0)) { return; @@ -133,8 +133,8 @@ void AddUnnamedLabel (unsigned Addr) void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs) /* Add a dependent label at the given address using "basename+Offs" as the new - * name. - */ +** name. +*/ { /* Allocate memory for the dependent label name */ unsigned NameLen = strlen (BaseName); @@ -159,8 +159,8 @@ void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Off static void AddLabelRange (unsigned Addr, attr_t Attr, const char* Name, unsigned Count) /* Add a label for a range. The first entry gets the label "Name" while the - * others get "Name+offs". - */ +** others get "Name+offs". +*/ { /* Define the label */ AddLabel (Addr, Attr, Name); @@ -196,8 +196,8 @@ static void AddLabelRange (unsigned Addr, attr_t Attr, void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count) /* Add an internal label for a range. The first entry gets the label "Name" - * while the others get "Name+offs". - */ +** while the others get "Name+offs". +*/ { /* Define the label range */ AddLabelRange (Addr, atIntLabel, Name, Count); @@ -207,8 +207,8 @@ void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count) void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count) /* Add an external label for a range. The first entry gets the label "Name" - * while the others get "Name+offs". - */ +** while the others get "Name+offs". +*/ { /* Define the label range */ AddLabelRange (Addr, atExtLabel, Name, Count); @@ -227,8 +227,8 @@ int HaveLabel (unsigned Addr) int MustDefLabel (unsigned Addr) /* Return true if we must define a label for this address, that is, if there - * is a label at this address, and it is an external or internal label. - */ +** is a label at this address, and it is an external or internal label. +*/ { /* Get the label attribute */ attr_t A = GetLabelAttr (Addr); @@ -246,8 +246,8 @@ const char* GetLabelName (unsigned Addr) attr_t A = GetLabelAttr (Addr); /* Special case unnamed labels, because these don't have a named stored in - * the symbol table to save space. - */ + ** the symbol table to save space. + */ if (A == atUnnamedLabel) { return ""; } else { @@ -260,9 +260,9 @@ const char* GetLabelName (unsigned Addr) const char* GetLabel (unsigned Addr, unsigned RefFrom) /* Return the label name for an address, as it is used in a label reference. - * RefFrom is the address the label is referenced from. This is needed in case - * of unnamed labels, to determine the name. - */ +** RefFrom is the address the label is referenced from. This is needed in case +** of unnamed labels, to determine the name. +*/ { static const char* FwdLabels[] = { ":+", ":++", ":+++", ":++++", ":+++++", ":++++++", ":+++++++", @@ -277,15 +277,15 @@ const char* GetLabel (unsigned Addr, unsigned RefFrom) attr_t A = GetLabelAttr (Addr); /* Special case unnamed labels, because these don't have a named stored in - * the symbol table to save space. - */ + ** the symbol table to save space. + */ if (A == atUnnamedLabel) { unsigned Count = 0; /* Search forward or backward depending in which direction the label - * is. - */ + ** is. + */ if (Addr <= RefFrom) { /* Search backwards */ unsigned I = RefFrom; @@ -333,8 +333,8 @@ const char* GetLabel (unsigned Addr, unsigned RefFrom) void ForwardLabel (unsigned Offs) /* If necessary, output a forward label, one that is within the next few - * bytes and is therefore output as "label = * + x". - */ +** bytes and is therefore output as "label = * + x". +*/ { /* Calculate the actual address */ unsigned long Addr = PC + Offs; @@ -348,8 +348,8 @@ void ForwardLabel (unsigned Offs) } /* An unnamed label cannot be output as a forward declaration, so this is - * an error. - */ + ** an error. + */ if (A == atUnnamedLabel) { Error ("Cannot define unnamed label at address $%04lX", Addr); } @@ -410,6 +410,3 @@ void DefOutOfRangeLabels (void) SeparatorLine (); } - - - diff --git a/src/da65/labels.h b/src/da65/labels.h index 34735a54c..c4b52774a 100644 --- a/src/da65/labels.h +++ b/src/da65/labels.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2006 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -59,40 +59,40 @@ void AddUnnamedLabel (unsigned Addr); void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs); /* Add a dependent label at the given address using "base name+Offs" as the new - * name. - */ +** name. +*/ void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count); /* Add an internal label for a range. The first entry gets the label "Name" - * while the others get "Name+offs". - */ +** while the others get "Name+offs". +*/ void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count); /* Add an external label for a range. The first entry gets the label "Name" - * while the others get "Name+offs". - */ +** while the others get "Name+offs". +*/ int HaveLabel (unsigned Addr); /* Check if there is a label for the given address */ int MustDefLabel (unsigned Addr); /* Return true if we must define a label for this address, that is, if there - * is a label at this address, and it is an external or internal label. - */ +** is a label at this address, and it is an external or internal label. +*/ const char* GetLabelName (unsigned Addr); /* Return the label name for an address */ const char* GetLabel (unsigned Addr, unsigned RefFrom); /* Return the label name for an address, as it is used in a label reference. - * RefFrom is the address the label is referenced from. This is needed in case - * of unnamed labels, to determine the name. - */ +** RefFrom is the address the label is referenced from. This is needed in case +** of unnamed labels, to determine the name. +*/ void ForwardLabel (unsigned Offs); /* If necessary, output a forward label, one that is within the next few - * bytes and is therefore output as "label = * + x". - */ +** bytes and is therefore output as "label = * + x". +*/ void DefOutOfRangeLabels (void); /* Output any labels that are out of the loaded code range */ @@ -100,7 +100,5 @@ void DefOutOfRangeLabels (void); /* End of labels.h */ + #endif - - - diff --git a/src/da65/main.c b/src/da65/main.c index a0af30539..a819f9771 100644 --- a/src/da65/main.c +++ b/src/da65/main.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2011, Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2011, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -108,8 +108,8 @@ static void Usage (void) static void RangeCheck (const char* Opt, unsigned long Val, unsigned long Min, unsigned long Max) /* Do a range check for the given option and abort if there's a range - * error. - */ +** error. +*/ { if (Val < Min || Val > Max) { Error ("Argument for %s outside valid range (%ld-%ld)", Opt, Min, Max); @@ -120,8 +120,8 @@ static void RangeCheck (const char* Opt, unsigned long Val, static unsigned long CvtNumber (const char* Arg, const char* Number) /* Convert a number from a string. Allow '$' and '0x' prefixes for hex - * numbers. - */ +** numbers. +*/ { unsigned long Val; int Converted; @@ -357,8 +357,8 @@ static void OneOpcode (unsigned RemainingBytes) attr_t Style = GetStyleAttr (PC); /* If we have a label at this address, output the label and an attached - * comment, provided that we aren't in a skip area. - */ + ** comment, provided that we aren't in a skip area. + */ if (Style != atSkip && MustDefLabel (PC)) { const char* Comment = GetComment (PC); if (Comment) { @@ -368,11 +368,11 @@ static void OneOpcode (unsigned RemainingBytes) } /* Check... - * - ...if we have enough bytes remaining for the code at this address. - * - ...if the current instruction is valid for the given CPU. - * - ...if there is no label somewhere between the instruction bytes. - * If any of these conditions is false, switch to data mode. - */ + ** - ...if we have enough bytes remaining for the code at this address. + ** - ...if the current instruction is valid for the given CPU. + ** - ...if there is no label somewhere between the instruction bytes. + ** If any of these conditions is false, switch to data mode. + */ if (Style == atDefault) { if (D->Size > RemainingBytes) { Style = atIllegal; @@ -402,8 +402,8 @@ static void OneOpcode (unsigned RemainingBytes) case atCode: /* Beware: If we don't have enough bytes left to disassemble the - * following insn, fall through to byte mode. - */ + ** following insn, fall through to byte mode. + */ if (D->Size <= RemainingBytes) { /* Output labels within the next insn */ unsigned I; @@ -594,9 +594,9 @@ int main (int argc, char* argv []) } /* Check the formatting options for reasonable values. Note: We will not - * really check that they make sense, just that they aren't complete - * garbage. - */ + ** really check that they make sense, just that they aren't complete + ** garbage. + */ if (MCol >= ACol) { AbEnd ("mnemonic-column value must be smaller than argument-column value"); } @@ -613,8 +613,8 @@ int main (int argc, char* argv []) } /* Get the current time and convert it to string so it can be used in - * the output page headers. - */ + ** the output page headers. + */ T = time (0); strftime (Now, sizeof (Now), "%Y-%m-%d %H:%M:%S", localtime (&T)); @@ -633,6 +633,3 @@ int main (int argc, char* argv []) /* Done */ return EXIT_SUCCESS; } - - - diff --git a/src/da65/opc6502.c b/src/da65/opc6502.c index b59db8d57..27f734d56 100644 --- a/src/da65/opc6502.c +++ b/src/da65/opc6502.c @@ -304,6 +304,3 @@ const OpcDesc OpcTable_6502[256] = { { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "", 1, flIllegal, OH_Illegal, }, /* $ff */ }; - - - diff --git a/src/da65/opc6502.h b/src/da65/opc6502.h index 26171cf61..c890e241b 100644 --- a/src/da65/opc6502.h +++ b/src/da65/opc6502.h @@ -54,7 +54,5 @@ extern const OpcDesc OpcTable_6502[256]; /* End of opc6502.h */ + #endif - - - diff --git a/src/da65/opc6502x.c b/src/da65/opc6502x.c index ee2c4e0ec..c02a145c6 100644 --- a/src/da65/opc6502x.c +++ b/src/da65/opc6502x.c @@ -46,8 +46,8 @@ /* Descriptions for all opcodes. Base table from opc6502.c with illegal - * opcodes from http://www.oxyron.de/html/opcodes02.html - */ +** opcodes from http://www.oxyron.de/html/opcodes02.html +*/ const OpcDesc OpcTable_6502X[256] = { { "brk", 1, flNone, OH_Implicit }, /* $00 */ { "ora", 2, flUseLabel, OH_DirectXIndirect }, /* $01 */ @@ -306,7 +306,3 @@ const OpcDesc OpcTable_6502X[256] = { { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "isc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $ff */ }; - - - - diff --git a/src/da65/opc65816.c b/src/da65/opc65816.c index 520aafefb..2cd2aaee8 100644 --- a/src/da65/opc65816.c +++ b/src/da65/opc65816.c @@ -304,6 +304,3 @@ const OpcDesc OpcTable_65816[256] = { { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "sbc", 4, flUseLabel, OH_AbsoluteLongX }, /* $ff */ }; - - - diff --git a/src/da65/opc65816.h b/src/da65/opc65816.h index 4b0ac21f4..12ffc4a37 100644 --- a/src/da65/opc65816.h +++ b/src/da65/opc65816.h @@ -54,7 +54,5 @@ extern const OpcDesc OpcTable_65816[256]; /* End of opc65816.h */ + #endif - - - diff --git a/src/da65/opc65c02.c b/src/da65/opc65c02.c index 5d29a36de..00520e729 100644 --- a/src/da65/opc65c02.c +++ b/src/da65/opc65c02.c @@ -304,6 +304,3 @@ const OpcDesc OpcTable_65C02[256] = { { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "bbs7", 3, flUseLabel, OH_BitBranch }, /* $ff */ }; - - - diff --git a/src/da65/opc65c02.h b/src/da65/opc65c02.h index 2addf5861..38138aa51 100644 --- a/src/da65/opc65c02.h +++ b/src/da65/opc65c02.h @@ -54,7 +54,5 @@ extern const OpcDesc OpcTable_65C02[256]; /* End of opc65c02.h */ + #endif - - - diff --git a/src/da65/opc65sc02.c b/src/da65/opc65sc02.c index 236a9ee34..90549d00f 100644 --- a/src/da65/opc65sc02.c +++ b/src/da65/opc65sc02.c @@ -304,6 +304,3 @@ const OpcDesc OpcTable_65SC02[256] = { { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "", 1, flIllegal, OH_Illegal, }, /* $ff */ }; - - - diff --git a/src/da65/opc65sc02.h b/src/da65/opc65sc02.h index e9cd30a21..391f425ea 100644 --- a/src/da65/opc65sc02.h +++ b/src/da65/opc65sc02.h @@ -54,7 +54,5 @@ extern const OpcDesc OpcTable_65SC02[256]; /* End of opc65sc02.h */ + #endif - - - diff --git a/src/da65/opcdesc.h b/src/da65/opcdesc.h index 093e71c9d..7913131cd 100644 --- a/src/da65/opcdesc.h +++ b/src/da65/opcdesc.h @@ -73,7 +73,5 @@ struct OpcDesc { /* End of opcdesc.h */ + #endif - - - diff --git a/src/da65/opchuc6280.h b/src/da65/opchuc6280.h index 26f5390a8..d0518dcc4 100644 --- a/src/da65/opchuc6280.h +++ b/src/da65/opchuc6280.h @@ -54,7 +54,5 @@ extern const OpcDesc OpcTable_HuC6280[256]; /* End of opchuc6280.h */ + #endif - - - diff --git a/src/da65/opcm740.c b/src/da65/opcm740.c index 2a2040515..67a36b48c 100644 --- a/src/da65/opcm740.c +++ b/src/da65/opcm740.c @@ -305,6 +305,3 @@ const OpcDesc OpcTable_M740[256] = { { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "clb", 2, flUseLabel, OH_ZeroPageBit }, /* $ff */ }; - - - diff --git a/src/da65/opcm740.h b/src/da65/opcm740.h index edfa20c8d..07c49578b 100644 --- a/src/da65/opcm740.h +++ b/src/da65/opcm740.h @@ -55,7 +55,5 @@ extern const OpcDesc OpcTable_M740[256]; /* End of opcm740.h */ + #endif - - - diff --git a/src/da65/opctable.c b/src/da65/opctable.c index e44294b1e..c85805faf 100644 --- a/src/da65/opctable.c +++ b/src/da65/opctable.c @@ -76,7 +76,3 @@ void SetOpcTable (cpu_t CPU) default: Error ("Unsupported CPU"); } } - - - - diff --git a/src/da65/opctable.h b/src/da65/opctable.h index 2835fba01..d5c81b216 100644 --- a/src/da65/opctable.h +++ b/src/da65/opctable.h @@ -69,7 +69,5 @@ void SetOpcTable (cpu_t CPU); /* End of opctable.h */ + #endif - - - diff --git a/src/da65/output.c b/src/da65/output.c index 3bfebc428..9098d7d37 100644 --- a/src/da65/output.c +++ b/src/da65/output.c @@ -168,8 +168,8 @@ void DefLabel (const char* Name) { Output ("%s:", Name); /* If the label is longer than the configured maximum, or if it runs into - * the opcode column, start a new line. - */ + ** the opcode column, start a new line. + */ if (Col > LBreak+2 || Col > MCol) { LineFeed (); } @@ -179,8 +179,8 @@ void DefLabel (const char* Name) void DefForward (const char* Name, const char* Comment, unsigned Offs) /* Define a label as "* + x", where x is the offset relative to the - * current PC. - */ +** current PC. +*/ { if (Pass == PassCount) { /* Flush existing output if necessary */ @@ -383,6 +383,3 @@ void OutputSettings (void) LineFeed (); LineFeed (); } - - - diff --git a/src/da65/output.h b/src/da65/output.h index 16e2ee3be..ad5f8d34e 100644 --- a/src/da65/output.h +++ b/src/da65/output.h @@ -69,8 +69,8 @@ void DefLabel (const char* Name); void DefForward (const char* Name, const char* Comment, unsigned Offs); /* Define a label as "* + x", where x is the offset relative to the - * current PC. - */ +** current PC. +*/ void DefConst (const char* Name, const char* Comment, unsigned Addr); /* Define an address constant */ @@ -111,8 +111,5 @@ void OutputSettings (void); /* End of output.h */ + #endif - - - - diff --git a/src/da65/scanner.c b/src/da65/scanner.c index dab5ffe98..8dc8d393a 100644 --- a/src/da65/scanner.c +++ b/src/da65/scanner.c @@ -533,7 +533,3 @@ void InfoCloseInput (void) InputFile = 0; } } - - - - diff --git a/src/da65/scanner.h b/src/da65/scanner.h index 46b9d29fc..f7f090fad 100644 --- a/src/da65/scanner.h +++ b/src/da65/scanner.h @@ -214,7 +214,5 @@ void InfoCloseInput (void); /* End of scanner.h */ + #endif - - - diff --git a/src/da65/segment.c b/src/da65/segment.c index 479f8f973..cad2096ff 100644 --- a/src/da65/segment.c +++ b/src/da65/segment.c @@ -66,8 +66,8 @@ struct Segment { }; /* Tables containing the segments. A segment is inserted using it's hash - * value. Collision is done by single linked lists. - */ +** value. Collision is done by single linked lists. +*/ static Segment* StartTab[HASH_SIZE]; /* Table containing segment starts */ static Segment* EndTab[HASH_SIZE]; /* Table containing segment ends */ @@ -107,6 +107,3 @@ void AddAbsSegment (unsigned Start, unsigned End, const char* Name) /* Mark the addresses within the segment */ MarkRange (Start, End, atSegment); } - - - diff --git a/src/da65/segment.h b/src/da65/segment.h index b2dc26488..14700ba99 100644 --- a/src/da65/segment.h +++ b/src/da65/segment.h @@ -52,6 +52,3 @@ void AddAbsSegment (unsigned Start, unsigned End, const char* Name); /* End of segment.h */ #endif - - - diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index 05951f6c6..e0d8894f9 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -71,11 +71,11 @@ struct StrBuf { #define STRBUF_INITIALIZER { 0, 0, 0 } /* An array of unsigneds/pointers that grows if needed. C guarantees that a - * pointer to a union correctly converted points to each of its members. - * So what we do here is using union entries that contain an unsigned - * (used to store ids until they're resolved) and pointers to actual items - * in storage. - */ +** pointer to a union correctly converted points to each of its members. +** So what we do here is using union entries that contain an unsigned +** (used to store ids until they're resolved) and pointers to actual items +** in storage. +*/ typedef union CollEntry CollEntry; union CollEntry { void* Ptr; @@ -93,8 +93,8 @@ struct Collection { #define COLLECTION_INITIALIZER { 0, 0, 0 } /* Span info management. The following table has as many entries as there - * are addresses active in spans. Each entry lists the spans for this address. - */ +** are addresses active in spans. Each entry lists the spans for this address. +*/ typedef struct SpanInfoListEntry SpanInfoListEntry; struct SpanInfoListEntry { cc65_addr Addr; /* Unique address */ @@ -177,16 +177,16 @@ typedef enum { } Token; /* Data structure containing information from the debug info file. A pointer - * to this structure is passed as handle to callers from the outside. - */ +** to this structure is passed as handle to callers from the outside. +*/ typedef struct DbgInfo DbgInfo; struct DbgInfo { /* First we have all items in collections sorted by id. The ids are - * continous, so an access by id is almost as cheap as an array access. - * The collections are also used when the objects are deleted, so they're - * actually the ones that "own" the items. - */ + ** continous, so an access by id is almost as cheap as an array access. + ** The collections are also used when the objects are deleted, so they're + ** actually the ones that "own" the items. + */ Collection CSymInfoById; /* C symbol infos sorted by id */ Collection FileInfoById; /* File infos sorted by id */ Collection LibInfoById; /* Library infos sorted by id */ @@ -404,8 +404,8 @@ struct TypeInfo { }; /* A structure used when parsing a type string into a set of cc65_typedata - * structures. - */ +** structures. +*/ typedef struct TypeParseData TypeParseData; struct TypeParseData { TypeInfo* Info; @@ -498,8 +498,8 @@ static void SB_Done (StrBuf* B) static void SB_Realloc (StrBuf* B, unsigned NewSize) /* Reallocate the string buffer space, make sure at least NewSize bytes are - * available. - */ +** available. +*/ { /* Get the current size, use a minimum of 8 bytes */ unsigned NewAllocated = B->Allocated; @@ -513,9 +513,9 @@ static void SB_Realloc (StrBuf* B, unsigned NewSize) } /* Reallocate the buffer. Beware: The allocated size may be zero while the - * length is not. This means that we have a buffer that wasn't allocated - * on the heap. - */ + ** length is not. This means that we have a buffer that wasn't allocated + ** on the heap. + */ if (B->Allocated) { /* Just reallocate the block */ B->Buf = xrealloc (B->Buf, NewAllocated); @@ -532,9 +532,9 @@ static void SB_Realloc (StrBuf* B, unsigned NewSize) static void SB_CheapRealloc (StrBuf* B, unsigned NewSize) /* Reallocate the string buffer space, make sure at least NewSize bytes are - * available. This function won't copy the old buffer contents over to the new - * buffer and may be used if the old contents are overwritten later. - */ +** available. This function won't copy the old buffer contents over to the new +** buffer and may be used if the old contents are overwritten later. +*/ { /* Get the current size, use a minimum of 8 bytes */ unsigned NewAllocated = B->Allocated; @@ -596,8 +596,8 @@ static char SB_At (const StrBuf* B, unsigned Pos) static void SB_Terminate (StrBuf* B) /* Zero terminate the given string buffer. NOTE: The terminating zero is not - * accounted for in B->Len, if you want that, you have to use AppendChar! - */ +** accounted for in B->Len, if you want that, you have to use AppendChar! +*/ { unsigned NewLen = B->Len + 1; if (NewLen > B->Allocated) { @@ -653,8 +653,8 @@ static void SB_AppendChar (StrBuf* B, int C) static char* SB_StrDup (const StrBuf* B) /* Return the contents of B as a dynamically allocated string. The string - * will always be NUL terminated. - */ +** will always be NUL terminated. +*/ { /* Allocate memory */ char* S = xmalloc (B->Len + 1); @@ -701,15 +701,15 @@ static Collection* CollNew (void) static void CollDone (Collection* C) /* Free the data for a collection. This will not free the data contained in - * the collection. - */ +** the collection. +*/ { /* Free the pointer array */ xfree (C->Items); /* Clear the fields, so the collection may be reused (or CollDone called) - * again - */ + ** again + */ C->Count = 0; C->Size = 0; C->Items = 0; @@ -739,9 +739,9 @@ static unsigned CollCount (const Collection* C) static void CollMove (Collection* Source, Collection* Target) /* Move all data from one collection to another. This function will first free - * the data in the target collection, and - after the move - clear the data - * from the source collection. - */ +** the data in the target collection, and - after the move - clear the data +** from the source collection. +*/ { /* Free the target collection data */ xfree (Target->Items); @@ -759,9 +759,9 @@ static void CollMove (Collection* Source, Collection* Target) static void CollGrow (Collection* C, unsigned Size) /* Grow the collection C so it is able to hold Size items without a resize - * being necessary. This can be called for performance reasons if the number - * of items to be placed in the collection is known in advance. - */ +** being necessary. This can be called for performance reasons if the number +** of items to be placed in the collection is known in advance. +*/ { CollEntry* NewItems; @@ -839,10 +839,10 @@ static void CollReplace (Collection* C, void* Item, unsigned Index) static void CollReplaceExpand (Collection* C, void* Item, unsigned Index) /* If Index is a valid index for the collection, replace the item at this - * position by the one passed. If the collection is too small, expand it, - * filling unused pointers with NULL, then add the new item at the given - * position. - */ +** position by the one passed. If the collection is too small, expand it, +** filling unused pointers with NULL, then add the new item at the given +** position. +*/ { if (Index < C->Count) { /* Collection is already large enough */ @@ -1070,9 +1070,9 @@ static void DBGPRINT(const char* format, ...) {} static unsigned GetId (const void* Data) /* Return the id of one of the info structures. All structures have the Id - * field as first member, and the C standard allows converting a union pointer - * to the data type of the first member, so this is safe and portable. - */ +** field as first member, and the C standard allows converting a union pointer +** to the data type of the first member, so this is safe and portable. +*/ { if (Data) { return *(const unsigned*)Data; @@ -1156,9 +1156,9 @@ static void UnexpectedToken (InputData* D) static void UnknownKeyword (InputData* D) /* Print a warning about an unknown keyword in the file. Try to do smart - * recovery, so if later versions of the debug information add additional - * keywords, this code may be able to at least ignore them. - */ +** recovery, so if later versions of the debug information add additional +** keywords, this code may be able to at least ignore them. +*/ { /* Output a warning */ ParseError (D, CC65_WARNING, "Unknown keyword \"%s\" - skipping", @@ -1168,9 +1168,9 @@ static void UnknownKeyword (InputData* D) NextToken (D); /* If an equal sign follows, ignore anything up to the next line end - * or comma. If a comma or line end follows, we're already done. If - * we have none of both, we ignore the remainder of the line. - */ + ** or comma. If a comma or line end follows, we're already done. If + ** we have none of both, we ignore the remainder of the line. + */ if (D->Tok == TOK_EQUAL) { NextToken (D); while (D->Tok != TOK_COMMA && D->Tok != TOK_EOL && D->Tok != TOK_EOF) { @@ -1215,8 +1215,8 @@ static void FreeCSymInfo (CSymInfo* S) static cc65_csyminfo* new_cc65_csyminfo (unsigned Count) /* Allocate and return a cc65_csyminfo struct that is able to hold Count - * entries. Initialize the count field of the returned struct. - */ +** entries. Initialize the count field of the returned struct. +*/ { cc65_csyminfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); @@ -1292,8 +1292,8 @@ static void FreeFileInfo (FileInfo* F) static cc65_sourceinfo* new_cc65_sourceinfo (unsigned Count) /* Allocate and return a cc65_sourceinfo struct that is able to hold Count - * entries. Initialize the count field of the returned struct. - */ +** entries. Initialize the count field of the returned struct. +*/ { cc65_sourceinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); @@ -1318,9 +1318,9 @@ static int CompareFileInfoByName (const void* L, const void* R) /* Helper function to sort file infos in a collection by name */ { /* Sort by file name. If names are equal, sort by timestamp, - * then sort by size. Which means, identical files will go - * together. - */ + ** then sort by size. Which means, identical files will go + ** together. + */ int Res = strcmp (((const FileInfo*) L)->Name, ((const FileInfo*) R)->Name); if (Res != 0) { @@ -1373,8 +1373,8 @@ static void FreeLibInfo (LibInfo* L) static cc65_libraryinfo* new_cc65_libraryinfo (unsigned Count) /* Allocate and return a cc65_libraryinfo struct that is able to hold Count - * entries. Initialize the count field of the returned struct. - */ +** entries. Initialize the count field of the returned struct. +*/ { cc65_libraryinfo* L = xmalloc (sizeof (*L) - sizeof (L->data[0]) + Count * sizeof (L->data[0])); @@ -1423,8 +1423,8 @@ static void FreeLineInfo (LineInfo* L) static cc65_lineinfo* new_cc65_lineinfo (unsigned Count) /* Allocate and return a cc65_lineinfo struct that is able to hold Count - * entries. Initialize the count field of the returned struct. - */ +** entries. Initialize the count field of the returned struct. +*/ { cc65_lineinfo* L = xmalloc (sizeof (*L) - sizeof (L->data[0]) + Count * sizeof (L->data[0])); @@ -1497,8 +1497,8 @@ static void FreeModInfo (ModInfo* M) static cc65_moduleinfo* new_cc65_moduleinfo (unsigned Count) /* Allocate and return a cc65_moduleinfo struct that is able to hold Count - * entries. Initialize the count field of the returned struct. - */ +** entries. Initialize the count field of the returned struct. +*/ { cc65_moduleinfo* M = xmalloc (sizeof (*M) - sizeof (M->data[0]) + Count * sizeof (M->data[0])); @@ -1569,8 +1569,8 @@ static void FreeScopeInfo (ScopeInfo* S) static cc65_scopeinfo* new_cc65_scopeinfo (unsigned Count) /* Allocate and return a cc65_scopeinfo struct that is able to hold Count - * entries. Initialize the count field of the returned struct. - */ +** entries. Initialize the count field of the returned struct. +*/ { cc65_scopeinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); @@ -1656,8 +1656,8 @@ static void FreeSegInfo (SegInfo* S) static cc65_segmentinfo* new_cc65_segmentinfo (unsigned Count) /* Allocate and return a cc65_segmentinfo struct that is able to hold Count - * entries. Initialize the count field of the returned struct. - */ +** entries. Initialize the count field of the returned struct. +*/ { cc65_segmentinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); @@ -1722,8 +1722,8 @@ static void FreeSpanInfo (SpanInfo* S) static cc65_spaninfo* new_cc65_spaninfo (unsigned Count) /* Allocate and return a cc65_spaninfo struct that is able to hold Count - * entries. Initialize the count field of the returned struct. - */ +** entries. Initialize the count field of the returned struct. +*/ { cc65_spaninfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); @@ -1749,12 +1749,12 @@ static void CopySpanInfo (cc65_spandata* D, const SpanInfo* S) static int CompareSpanInfoByAddr (const void* L, const void* R) /* Helper function to sort span infos in a collection by address. Span infos - * with smaller start address are considered smaller. If start addresses are - * equal, line spans with smaller end address are considered smaller. This - * means, that when CompareSpanInfoByAddr is used for sorting, a range with - * identical start addresses will have smaller spans first, followed by - * larger spans. - */ +** with smaller start address are considered smaller. If start addresses are +** equal, line spans with smaller end address are considered smaller. This +** means, that when CompareSpanInfoByAddr is used for sorting, a range with +** identical start addresses will have smaller spans first, followed by +** larger spans. +*/ { /* Sort by start of span */ if (((const SpanInfo*) L)->Start > ((const SpanInfo*) R)->Start) { @@ -1812,8 +1812,8 @@ static void FreeSymInfo (SymInfo* S) static cc65_symbolinfo* new_cc65_symbolinfo (unsigned Count) /* Allocate and return a cc65_symbolinfo struct that is able to hold Count - * entries. Initialize the count field of the returned struct. - */ +** entries. Initialize the count field of the returned struct. +*/ { cc65_symbolinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); @@ -1834,8 +1834,8 @@ static void CopySymInfo (cc65_symboldata* D, const SymInfo* S) D->symbol_size = S->Size; /* If this is an import, it doesn't have a value or segment. Use the data - * from the matching export instead. - */ + ** from the matching export instead. + */ if (S->Exp.Info) { /* This is an import, because it has a matching export */ D->export_id = S->Exp.Info->Id; @@ -1875,8 +1875,8 @@ static int CompareSymInfoByVal (const void* L, const void* R) /* Helper function to sort symbol infos in a collection by value */ { /* Sort by symbol value. If both are equal, sort by symbol name so it - * looks nice when such a list is returned. - */ + ** looks nice when such a list is returned. + */ if (((const SymInfo*) L)->Value > ((const SymInfo*) R)->Value) { return 1; } else if (((const SymInfo*) L)->Value < ((const SymInfo*) R)->Value) { @@ -1978,8 +1978,8 @@ static void InitTypeParseData (TypeParseData* P, const StrBuf* Type, static cc65_typedata* TypeFromString (TypeParseData* P) /* Parse a type string and return a set of typedata structures. Will be called - * recursively. Will set P->Error and return NULL in case of problems. - */ +** recursively. Will set P->Error and return NULL in case of problems. +*/ { cc65_typedata* Data; unsigned char B; @@ -2084,10 +2084,10 @@ static cc65_typedata* TypeFromString (TypeParseData* P) static TypeInfo* ParseTypeString (InputData* D, StrBuf* Type) /* Check if the string T contains a valid type string. Convert it from readable - * to binary. Calculate how many cc65_typedata structures are necessary when it - * is converted. Convert the string into a set of cc65_typedata structures and - * return them. - */ +** to binary. Calculate how many cc65_typedata structures are necessary when it +** is converted. Convert the string into a set of cc65_typedata structures and +** return them. +*/ { unsigned I; unsigned Count; @@ -2122,8 +2122,8 @@ static TypeInfo* ParseTypeString (InputData* D, StrBuf* Type) Type->Len = (Length /= 2); /* Get a pointer to the type data, then count the number of cc65_typedata - * items needed. - */ + ** items needed. + */ A = SB_GetConstBuf (Type); Count = 0; I = 0; @@ -2193,8 +2193,8 @@ static void InitSpanInfoList (SpanInfoList* L) static void CreateSpanInfoList (SpanInfoList* L, Collection* SpanInfos) /* Create a SpanInfoList from a Collection with span infos. The collection - * must be sorted by ascending start addresses. - */ +** must be sorted by ascending start addresses. +*/ { unsigned I, J; SpanInfo* S; @@ -2255,10 +2255,10 @@ static void CreateSpanInfoList (SpanInfoList* L, Collection* SpanInfos) S = CollAt (SpanInfos, I); /* Determine the start index of the next range. Line infos are sorted - * by ascending start address, so the start address of the next entry - * is always larger than the previous one - we don't need to check - * that. - */ + ** by ascending start address, so the start address of the next entry + ** is always larger than the previous one - we don't need to check + ** that. + */ if (S->Start <= End) { /* Range starts within out already known linear range */ StartIndex += (unsigned) (S->Start - Start); @@ -2282,11 +2282,11 @@ static void CreateSpanInfoList (SpanInfoList* L, Collection* SpanInfos) for (I = 0, List = L->List; I < L->Count; ++I, ++List) { /* For a count of 1, we store the pointer to the lineinfo for this - * address in the Data pointer directly. For counts > 1, we allocate - * an array of pointers and reset the counter, so we can use it as - * an index later. This is dangerous programming since it disables - * all possible checks! - */ + ** address in the Data pointer directly. For counts > 1, we allocate + ** an array of pointers and reset the counter, so we can use it as + ** an index later. This is dangerous programming since it disables + ** all possible checks! + */ if (List->Count > 1) { List->Data = xmalloc (List->Count * sizeof (SpanInfo*)); List->Count = 0; @@ -2313,10 +2313,10 @@ static void CreateSpanInfoList (SpanInfoList* L, Collection* SpanInfos) S = CollAt (SpanInfos, I); /* Determine the start index of the next range. Line infos are sorted - * by ascending start address, so the start address of the next entry - * is always larger than the previous one - we don't need to check - * that. - */ + ** by ascending start address, so the start address of the next entry + ** is always larger than the previous one - we don't need to check + ** that. + */ if (S->Start <= End) { /* Range starts within out already known linear range */ StartIndex += (unsigned) (S->Start - Start); @@ -2734,8 +2734,8 @@ static int StrConstFollows (InputData* D) static int Consume (InputData* D, Token Tok, const char* Name) /* Check for a token and consume it. Return true if the token was comsumed, - * return false otherwise. - */ +** return false otherwise. +*/ { if (TokenFollows (D, Tok, Name)) { NextToken (D); @@ -2773,8 +2773,8 @@ static void ParseCSym (InputData* D) /* Parse a CSYM line */ { /* Most of the following variables are initialized with a value that is - * overwritten later. This is just to avoid compiler warnings. - */ + ** overwritten later. This is just to avoid compiler warnings. + */ unsigned Id = 0; StrBuf Name = STRBUF_INITIALIZER; int Offs = 0; @@ -3137,8 +3137,8 @@ static void ParseInfo (InputData* D) } /* Remember the token, skip it, check for equal, check for an integer - * constant. - */ + ** constant. + */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { @@ -3496,8 +3496,8 @@ static void ParseModule (InputData* D) /* Parse a MODULE line */ { /* Most of the following variables are initialized with a value that is - * overwritten later. This is just to avoid compiler warnings. - */ + ** overwritten later. This is just to avoid compiler warnings. + */ unsigned Id = CC65_INV_ID; StrBuf Name = STRBUF_INITIALIZER; unsigned FileId = CC65_INV_ID; @@ -3632,8 +3632,8 @@ static void ParseScope (InputData* D) /* Parse a SCOPE line */ { /* Most of the following variables are initialized with a value that is - * overwritten later. This is just to avoid compiler warnings. - */ + ** overwritten later. This is just to avoid compiler warnings. + */ unsigned Id = CC65_INV_ID; cc65_scope_type Type = CC65_SCOPE_MODULE; cc65_size Size = 0; @@ -4150,8 +4150,8 @@ static void ParseSym (InputData* D) /* Parse a SYM line */ { /* Most of the following variables are initialized with a value that is - * overwritten later. This is just to avoid compiler warnings. - */ + ** overwritten later. This is just to avoid compiler warnings. + */ Collection DefLineIds = COLLECTION_INITIALIZER; unsigned ExportId = CC65_INV_ID; unsigned FileId = CC65_INV_ID; @@ -4419,8 +4419,8 @@ static void ParseType (InputData* D) /* Parse a TYPE line */ { /* Most of the following variables are initialized with a value that is - * overwritten later. This is just to avoid compiler warnings. - */ + ** overwritten later. This is just to avoid compiler warnings. + */ unsigned Id = CC65_INV_ID; StrBuf Value = STRBUF_INITIALIZER; @@ -4574,8 +4574,8 @@ static void ParseVersion (InputData* D) case TOK_IDENT: /* Try to skip unknown keywords that may have been added by - * a later version. - */ + ** a later version. + */ UnknownKeyword (D); break; @@ -4618,10 +4618,10 @@ ErrorExit: static int FindCSymInfoByName (const Collection* CSymInfos, const char* Name, unsigned* Index) /* Find the C symbol info with a given file name. The function returns true if - * the name was found. In this case, Index contains the index of the first item - * that matches. If the item wasn't found, the function returns false and - * Index contains the insert position for Name. - */ +** the name was found. In this case, Index contains the index of the first item +** that matches. If the item wasn't found, the function returns false and +** Index contains the insert position for Name. +*/ { /* Do a binary search */ int Lo = 0; @@ -4644,8 +4644,8 @@ static int FindCSymInfoByName (const Collection* CSymInfos, const char* Name, } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've - * the first item that has a match. - */ + ** the first item that has a match. + */ if (Res == 0) { Found = 1; } @@ -4662,10 +4662,10 @@ static int FindCSymInfoByName (const Collection* CSymInfos, const char* Name, static int FindFileInfoByName (const Collection* FileInfos, const char* Name, unsigned* Index) /* Find the FileInfo for a given file name. The function returns true if the - * name was found. In this case, Index contains the index of the first item - * that matches. If the item wasn't found, the function returns false and - * Index contains the insert position for Name. - */ +** name was found. In this case, Index contains the index of the first item +** that matches. If the item wasn't found, the function returns false and +** Index contains the insert position for Name. +*/ { /* Do a binary search */ int Lo = 0; @@ -4688,8 +4688,8 @@ static int FindFileInfoByName (const Collection* FileInfos, const char* Name, } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've - * the first item that has a match. - */ + ** the first item that has a match. + */ if (Res == 0) { Found = 1; } @@ -4705,8 +4705,8 @@ static int FindFileInfoByName (const Collection* FileInfos, const char* Name, static SpanInfoListEntry* FindSpanInfoByAddr (const SpanInfoList* L, cc65_addr Addr) /* Find the index of a SpanInfo for a given address. Returns 0 if no such - * SpanInfo was found. - */ +** SpanInfo was found. +*/ { /* Do a binary search */ int Lo = 0; @@ -4738,8 +4738,8 @@ static SpanInfoListEntry* FindSpanInfoByAddr (const SpanInfoList* L, cc65_addr A static LineInfo* FindLineInfoByLine (const Collection* LineInfos, cc65_line Line) /* Find the LineInfo for a given line number. The function returns the line - * info or NULL if none was found. - */ +** info or NULL if none was found. +*/ { /* Do a binary search */ int Lo = 0; @@ -4771,8 +4771,8 @@ static LineInfo* FindLineInfoByLine (const Collection* LineInfos, cc65_line Line static SegInfo* FindSegInfoByName (const Collection* SegInfos, const char* Name) /* Find the SegInfo for a given segment name. The function returns the segment - * info or NULL if none was found. - */ +** info or NULL if none was found. +*/ { /* Do a binary search */ int Lo = 0; @@ -4808,10 +4808,10 @@ static SegInfo* FindSegInfoByName (const Collection* SegInfos, const char* Name) static int FindScopeInfoByName (const Collection* ScopeInfos, const char* Name, unsigned* Index) /* Find the ScopeInfo for a given scope name. The function returns true if the - * name was found. In this case, Index contains the index of the first item - * that matches. If the item wasn't found, the function returns false and - * Index contains the insert position for Name. - */ +** name was found. In this case, Index contains the index of the first item +** that matches. If the item wasn't found, the function returns false and +** Index contains the insert position for Name. +*/ { /* Do a binary search */ int Lo = 0; @@ -4834,8 +4834,8 @@ static int FindScopeInfoByName (const Collection* ScopeInfos, const char* Name, } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've - * the first item that has a match. - */ + ** the first item that has a match. + */ if (Res == 0) { Found = 1; } @@ -4852,10 +4852,10 @@ static int FindScopeInfoByName (const Collection* ScopeInfos, const char* Name, static int FindSymInfoByName (const Collection* SymInfos, const char* Name, unsigned* Index) /* Find the SymInfo for a given file name. The function returns true if the - * name was found. In this case, Index contains the index of the first item - * that matches. If the item wasn't found, the function returns false and - * Index contains the insert position for Name. - */ +** name was found. In this case, Index contains the index of the first item +** that matches. If the item wasn't found, the function returns false and +** Index contains the insert position for Name. +*/ { /* Do a binary search */ int Lo = 0; @@ -4878,8 +4878,8 @@ static int FindSymInfoByName (const Collection* SymInfos, const char* Name, } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've - * the first item that has a match. - */ + ** the first item that has a match. + */ if (Res == 0) { Found = 1; } @@ -4896,10 +4896,10 @@ static int FindSymInfoByName (const Collection* SymInfos, const char* Name, static int FindSymInfoByValue (const Collection* SymInfos, long Value, unsigned* Index) /* Find the SymInfo for a given value. The function returns true if the - * value was found. In this case, Index contains the index of the first item - * that matches. If the item wasn't found, the function returns false and - * Index contains the insert position for the given value. - */ +** value was found. In this case, Index contains the index of the first item +** that matches. If the item wasn't found, the function returns false and +** Index contains the insert position for the given value. +*/ { /* Do a binary search */ int Lo = 0; @@ -4919,8 +4919,8 @@ static int FindSymInfoByValue (const Collection* SymInfos, long Value, } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've - * the first item that has a match. - */ + ** the first item that has a match. + */ if (Value == CurItem->Value) { Found = 1; } @@ -4940,8 +4940,8 @@ static void ProcessCSymInfo (InputData* D) unsigned I; /* Walk over all c symbols. Resolve the ids and add the c symbols to the - * corresponding asm symbols. - */ + ** corresponding asm symbols. + */ for (I = 0; I < CollCount (&D->Info->CSymInfoById); ++I) { /* Get this c symbol info */ @@ -4960,8 +4960,8 @@ static void ProcessCSymInfo (InputData* D) S->Sym.Info = CollAt (&D->Info->SymInfoById, S->Sym.Id); /* For normal (=static) symbols, add a backlink to the symbol but - * check that there is not more than one. - */ + ** check that there is not more than one. + */ if (S->SC != CC65_CSYM_AUTO && S->SC != CC65_CSYM_REG) { if (S->Sym.Info->CSym) { ParseError (D, @@ -5003,12 +5003,12 @@ static void ProcessCSymInfo (InputData* D) CollAppend (S->Scope.Info->CSymInfoByName, S); /* If the scope has an owner symbol, it's a .PROC scope. If this - * symbol is identical to the one attached to the C symbol, this - * is actuallay a C function and the scope is the matching scope. - * Remember the C symbol in the scope in this case. - * Beware: Scopes haven't been postprocessed, so we don't have a - * pointer but just an id. - */ + ** symbol is identical to the one attached to the C symbol, this + ** is actuallay a C function and the scope is the matching scope. + ** Remember the C symbol in the scope in this case. + ** Beware: Scopes haven't been postprocessed, so we don't have a + ** pointer but just an id. + */ if (S->Sym.Info && S->Scope.Info->Label.Id == S->Sym.Info->Id) { /* This scope is our function scope */ S->Scope.Info->CSymFunc = S; @@ -5105,18 +5105,18 @@ static void ProcessLineInfo (InputData* D) Collection* FileInfos = &D->Info->FileInfoById; /* Walk over the line infos and replace the id numbers of file and segment - * with pointers to the actual structs. Add the line info to each file - * where it is defined. Resolve the spans and add backpointers to the - * spans. - */ + ** with pointers to the actual structs. Add the line info to each file + ** where it is defined. Resolve the spans and add backpointers to the + ** spans. + */ for (I = 0; I < CollCount (LineInfos); ++I) { /* Get LineInfo struct */ LineInfo* L = CollAt (LineInfos, I); /* Replace the file id by a pointer to the FileInfo. Add a back - * pointer - */ + ** pointer + */ if (L->File.Id >= CollCount (FileInfos)) { ParseError (D, CC65_ERROR, @@ -5157,8 +5157,8 @@ static void ProcessLineInfo (InputData* D) } /* Walk over all files and sort the line infos for each file so we can - * do a binary search later. - */ + ** do a binary search later. + */ for (I = 0; I < CollCount (FileInfos); ++I) { /* Get a pointer to this file info */ @@ -5219,8 +5219,8 @@ static void ProcessScopeInfo (InputData* D) unsigned I, J; /* Walk over all scopes. Resolve the ids and add the scopes to the list - * of scopes for a module. - */ + ** of scopes for a module. + */ for (I = 0; I < CollCount (&D->Info->ScopeInfoById); ++I) { /* Get this scope info */ @@ -5240,16 +5240,16 @@ static void ProcessScopeInfo (InputData* D) CollAppend (&S->Mod.Info->ScopeInfoByName, S); /* If this is a main scope, add a pointer to the corresponding - * module. - */ + ** module. + */ if (S->Parent.Id == CC65_INV_ID) { /* No parent means main scope */ S->Mod.Info->MainScope = S; } /* If this is the scope that implements a C function, add the - * function to the list of all functions in this module. - */ + ** function to the list of all functions in this module. + */ if (S->CSymFunc) { CollAppend (&S->Mod.Info->CSymFuncByName, S->CSymFunc); } @@ -5316,10 +5316,10 @@ static void ProcessScopeInfo (InputData* D) } /* Walk over all modules. If a module doesn't have scopes, it wasn't - * compiled with debug info which is ok. If it has debug info, it must - * also have a main scope. If there are scopes, sort them by name. Do - * also sort C functions in this module by name. - */ + ** compiled with debug info which is ok. If it has debug info, it must + ** also have a main scope. If there are scopes, sort them by name. Do + ** also sort C functions in this module by name. + */ for (I = 0; I < CollCount (&D->Info->ModInfoById); ++I) { /* Get this module */ @@ -5404,8 +5404,8 @@ static void ProcessSpanInfo (InputData* D) } /* Append this span info to the temporary collection that is later - * sorted by address. - */ + ** sorted by address. + */ CollAppend (&SpanInfoByAddr, S); } @@ -5591,11 +5591,11 @@ static void ProcessSymInfo (InputData* D) cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc) /* Parse the debug info file with the given name. On success, the function - * will return a pointer to an opaque cc65_dbginfo structure, that must be - * passed to the other functions in this module to retrieve information. - * errorfunc is called in case of warnings and errors. If the file cannot be - * read successfully, NULL is returned. - */ +** will return a pointer to an opaque cc65_dbginfo structure, that must be +** passed to the other functions in this module to retrieve information. +** errorfunc is called in case of warnings and errors. If the file cannot be +** read successfully, NULL is returned. +*/ { /* Data structure used to control scanning and parsing */ InputData D = { @@ -5727,8 +5727,8 @@ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc) case TOK_IDENT: /* Output a warning, then skip the line with the unknown - * keyword that may have been added by a later version. - */ + ** keyword that may have been added by a later version. + */ ParseError (&D, CC65_WARNING, "Unknown keyword \"%s\" - skipping", SB_GetConstBuf (&D.SVal)); @@ -5753,8 +5753,8 @@ CloseAndExit: SB_Done (&D.SVal); /* In case of errors, delete the debug info already allocated and - * return NULL - */ + ** return NULL + */ if (D.Errors > 0) { /* Free allocated stuff */ FreeDbgInfo (D.Info); @@ -5762,9 +5762,9 @@ CloseAndExit: } /* We do now have all the information from the input file. Do - * postprocessing. Beware: Some of the following postprocessing - * depends on the order of the calls. - */ + ** postprocessing. Beware: Some of the following postprocessing + ** depends on the order of the calls. + */ ProcessCSymInfo (&D); ProcessFileInfo (&D); ProcessLineInfo (&D); @@ -5831,10 +5831,10 @@ const cc65_csyminfo* cc65_get_csymlist (cc65_dbginfo Handle) const cc65_csyminfo* cc65_csym_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a c symbol with a specific id. The function - * returns NULL if the id is invalid (no such c symbol) and otherwise a - * cc65_csyminfo structure with one entry that contains the requested - * symbol information. - */ +** returns NULL if the id is invalid (no such c symbol) and otherwise a +** cc65_csyminfo structure with one entry that contains the requested +** symbol information. +*/ { const DbgInfo* Info; cc65_csyminfo* S; @@ -5864,9 +5864,9 @@ const cc65_csyminfo* cc65_csym_byid (cc65_dbginfo Handle, unsigned Id) const cc65_csyminfo* cc65_cfunc_bymodule (cc65_dbginfo Handle, unsigned ModId) /* Return the list of C functions (not symbols!) for a specific module. If - * the module id is invalid, the function will return NULL, otherwise a - * (possibly empty) c symbol list. - */ +** the module id is invalid, the function will return NULL, otherwise a +** (possibly empty) c symbol list. +*/ { const DbgInfo* Info; const ModInfo* M; @@ -5904,8 +5904,8 @@ const cc65_csyminfo* cc65_cfunc_bymodule (cc65_dbginfo Handle, unsigned ModId) const cc65_csyminfo* cc65_cfunc_byname (cc65_dbginfo Handle, const char* Name) /* Return a list of all C functions with the given name that have a - * definition. - */ +** definition. +*/ { const DbgInfo* Info; unsigned Index; @@ -5957,8 +5957,8 @@ const cc65_csyminfo* cc65_cfunc_byname (cc65_dbginfo Handle, const char* Name) const cc65_csyminfo* cc65_csym_byscope (cc65_dbginfo Handle, unsigned ScopeId) /* Return all C symbols for a scope. The function will return NULL if the - * given id is invalid. - */ +** given id is invalid. +*/ { const DbgInfo* Info; const ScopeInfo* S; @@ -6042,10 +6042,10 @@ const cc65_libraryinfo* cc65_get_librarylist (cc65_dbginfo Handle) const cc65_libraryinfo* cc65_library_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a library with a specific id. The function - * returns NULL if the id is invalid (no such library) and otherwise a - * cc65_libraryinfo structure with one entry that contains the requested - * library information. - */ +** returns NULL if the id is invalid (no such library) and otherwise a +** cc65_libraryinfo structure with one entry that contains the requested +** library information. +*/ { const DbgInfo* Info; cc65_libraryinfo* D; @@ -6093,10 +6093,10 @@ void cc65_free_libraryinfo (cc65_dbginfo Handle, const cc65_libraryinfo* Info) const cc65_lineinfo* cc65_line_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a line with a specific id. The function - * returns NULL if the id is invalid (no such line) and otherwise a - * cc65_lineinfo structure with one entry that contains the requested - * module information. - */ +** returns NULL if the id is invalid (no such line) and otherwise a +** cc65_lineinfo structure with one entry that contains the requested +** module information. +*/ { const DbgInfo* Info; cc65_lineinfo* D; @@ -6127,8 +6127,8 @@ const cc65_lineinfo* cc65_line_byid (cc65_dbginfo Handle, unsigned Id) const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo Handle, unsigned FileId, cc65_line Line) /* Return line information for a source file/line number combination. The - * function returns NULL if no line information was found. - */ +** function returns NULL if no line information was found. +*/ { const DbgInfo* Info; const FileInfo* F; @@ -6171,8 +6171,8 @@ const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo Handle, unsigned FileId, const cc65_lineinfo* cc65_line_bysource (cc65_dbginfo Handle, unsigned FileId) /* Return line information for a source file. The function returns NULL if the - * file id is invalid. - */ +** file id is invalid. +*/ { const DbgInfo* Info; const FileInfo* F; @@ -6210,8 +6210,8 @@ const cc65_lineinfo* cc65_line_bysource (cc65_dbginfo Handle, unsigned FileId) const cc65_lineinfo* cc65_line_bysymdef (cc65_dbginfo Handle, unsigned SymId) /* Return line information for the definition of a symbol. The function - * returns NULL if the symbol id is invalid, otherwise a list of line infos. - */ +** returns NULL if the symbol id is invalid, otherwise a list of line infos. +*/ { const DbgInfo* Info; const SymInfo* S; @@ -6249,8 +6249,8 @@ const cc65_lineinfo* cc65_line_bysymdef (cc65_dbginfo Handle, unsigned SymId) const cc65_lineinfo* cc65_line_bysymref (cc65_dbginfo Handle, unsigned SymId) /* Return line information for all references of a symbol. The function - * returns NULL if the symbol id is invalid, otherwise a list of line infos. - */ +** returns NULL if the symbol id is invalid, otherwise a list of line infos. +*/ { const DbgInfo* Info; const SymInfo* S; @@ -6288,8 +6288,8 @@ const cc65_lineinfo* cc65_line_bysymref (cc65_dbginfo Handle, unsigned SymId) const cc65_lineinfo* cc65_line_byspan (cc65_dbginfo Handle, unsigned SpanId) /* Return line information for a a span. The function returns NULL if the - * span id is invalid, otherwise a list of line infos. - */ +** span id is invalid, otherwise a list of line infos. +*/ { const DbgInfo* Info; const SpanInfo* S; @@ -6314,8 +6314,8 @@ const cc65_lineinfo* cc65_line_byspan (cc65_dbginfo Handle, unsigned SpanId) D = new_cc65_lineinfo (CollCount (S->LineInfoList)); /* Fill in the data. Since S->LineInfoList may be NULL, we will use the - * count field of the returned data struct instead. - */ + ** count field of the returned data struct instead. + */ for (I = 0; I < D->count; ++I) { /* Copy the data */ CopyLineInfo (D->data + I, CollAt (S->LineInfoList, I)); @@ -6375,10 +6375,10 @@ const cc65_moduleinfo* cc65_get_modulelist (cc65_dbginfo Handle) const cc65_moduleinfo* cc65_module_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a module with a specific id. The function - * returns NULL if the id is invalid (no such module) and otherwise a - * cc65_moduleinfo structure with one entry that contains the requested - * module information. - */ +** returns NULL if the id is invalid (no such module) and otherwise a +** cc65_moduleinfo structure with one entry that contains the requested +** module information. +*/ { const DbgInfo* Info; cc65_moduleinfo* D; @@ -6454,10 +6454,10 @@ const cc65_spaninfo* cc65_get_spanlist (cc65_dbginfo Handle) const cc65_spaninfo* cc65_span_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a span with a specific id. The function - * returns NULL if the id is invalid (no such span) and otherwise a - * cc65_spaninfo structure with one entry that contains the requested - * span information. - */ +** returns NULL if the id is invalid (no such span) and otherwise a +** cc65_spaninfo structure with one entry that contains the requested +** span information. +*/ { const DbgInfo* Info; cc65_spaninfo* D; @@ -6487,8 +6487,8 @@ const cc65_spaninfo* cc65_span_byid (cc65_dbginfo Handle, unsigned Id) const cc65_spaninfo* cc65_span_byaddr (cc65_dbginfo Handle, unsigned long Addr) /* Return span information for the given address. The function returns NULL - * if no spans were found for this address. - */ +** if no spans were found for this address. +*/ { const DbgInfo* Info; SpanInfoListEntry* E; @@ -6528,8 +6528,8 @@ const cc65_spaninfo* cc65_span_byaddr (cc65_dbginfo Handle, unsigned long Addr) const cc65_spaninfo* cc65_span_byline (cc65_dbginfo Handle, unsigned LineId) /* Return span information for the given source line. The function returns NULL - * if the line id is invalid, otherwise the spans for this line (possibly zero). - */ +** if the line id is invalid, otherwise the spans for this line (possibly zero). +*/ { const DbgInfo* Info; const LineInfo* L; @@ -6567,8 +6567,8 @@ const cc65_spaninfo* cc65_span_byline (cc65_dbginfo Handle, unsigned LineId) const cc65_spaninfo* cc65_span_byscope (cc65_dbginfo Handle, unsigned ScopeId) /* Return span information for the given scope. The function returns NULL if - * the scope id is invalid, otherwise the spans for this scope (possibly zero). - */ +** the scope id is invalid, otherwise the spans for this scope (possibly zero). +*/ { const DbgInfo* Info; const ScopeInfo* S; @@ -6652,10 +6652,10 @@ const cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo Handle) const cc65_sourceinfo* cc65_source_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a source file with a specific id. The function - * returns NULL if the id is invalid (no such source file) and otherwise a - * cc65_sourceinfo structure with one entry that contains the requested - * source file information. - */ +** returns NULL if the id is invalid (no such source file) and otherwise a +** cc65_sourceinfo structure with one entry that contains the requested +** source file information. +*/ { const DbgInfo* Info; cc65_sourceinfo* D; @@ -6686,9 +6686,9 @@ const cc65_sourceinfo* cc65_source_byid (cc65_dbginfo Handle, unsigned Id) const cc65_sourceinfo* cc65_source_bymodule (cc65_dbginfo Handle, unsigned Id) /* Return information about the source files used to build a module. The - * function returns NULL if the module id is invalid (no such module) and - * otherwise a cc65_sourceinfo structure with one entry per source file. - */ +** function returns NULL if the module id is invalid (no such module) and +** otherwise a cc65_sourceinfo structure with one entry per source file. +*/ { const DbgInfo* Info; const ModInfo* M; @@ -6771,8 +6771,8 @@ const cc65_scopeinfo* cc65_get_scopelist (cc65_dbginfo Handle) const cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo Handle, unsigned Id) /* Return the scope with a given id. The function returns NULL if no scope - * with this id was found. - */ +** with this id was found. +*/ { const DbgInfo* Info; cc65_scopeinfo* D; @@ -6802,8 +6802,8 @@ const cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo Handle, unsigned Id) const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo Handle, unsigned ModId) /* Return the list of scopes for one module. The function returns NULL if no - * scope with the given id was found. - */ +** scope with the given id was found. +*/ { const DbgInfo* Info; const ModInfo* M; @@ -6840,8 +6840,8 @@ const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo Handle, unsigned ModId) const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo Handle, const char* Name) /* Return the list of scopes with a given name. Returns NULL if no scope with - * the given name was found, otherwise a non empty scope list. - */ +** the given name was found, otherwise a non empty scope list. +*/ { const DbgInfo* Info; unsigned Index; @@ -6894,8 +6894,8 @@ const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo Handle, const char* Name) const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo Handle, unsigned SpanId) /* Return scope information for a a span. The function returns NULL if the - * span id is invalid, otherwise a list of line scopes. - */ +** span id is invalid, otherwise a list of line scopes. +*/ { const DbgInfo* Info; const SpanInfo* S; @@ -6920,8 +6920,8 @@ const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo Handle, unsigned SpanId) D = new_cc65_scopeinfo (CollCount (S->ScopeInfoList)); /* Fill in the data. Since D->ScopeInfoList may be NULL, we will use the - * count field of the returned data struct instead. - */ + ** count field of the returned data struct instead. + */ for (I = 0; I < D->count; ++I) { /* Copy the data */ CopyScopeInfo (D->data + I, CollAt (S->ScopeInfoList, I)); @@ -6935,9 +6935,9 @@ const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo Handle, unsigned SpanId) const cc65_scopeinfo* cc65_childscopes_byid (cc65_dbginfo Handle, unsigned Id) /* Return the direct child scopes of a scope with a given id. The function - * returns NULL if no scope with this id was found, otherwise a list of the - * direct childs. - */ +** returns NULL if no scope with this id was found, otherwise a list of the +** direct childs. +*/ { const DbgInfo* Info; cc65_scopeinfo* D; @@ -7020,9 +7020,9 @@ const cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle) const cc65_segmentinfo* cc65_segment_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a segment with a specific id. The function returns - * NULL if the id is invalid (no such segment) and otherwise a segmentinfo - * structure with one entry that contains the requested segment information. - */ +** NULL if the id is invalid (no such segment) and otherwise a segmentinfo +** structure with one entry that contains the requested segment information. +*/ { const DbgInfo* Info; cc65_segmentinfo* D; @@ -7053,10 +7053,10 @@ const cc65_segmentinfo* cc65_segment_byid (cc65_dbginfo Handle, unsigned Id) const cc65_segmentinfo* cc65_segment_byname (cc65_dbginfo Handle, const char* Name) /* Return information about a segment with a specific name. The function - * returns NULL if no segment with this name exists and otherwise a - * cc65_segmentinfo structure with one entry that contains the requested - * information. - */ +** returns NULL if no segment with this name exists and otherwise a +** cc65_segmentinfo structure with one entry that contains the requested +** information. +*/ { const DbgInfo* Info; const SegInfo* S; @@ -7106,8 +7106,8 @@ void cc65_free_segmentinfo (cc65_dbginfo Handle, const cc65_segmentinfo* Info) const cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo Handle, unsigned Id) /* Return the symbol with a given id. The function returns NULL if no symbol - * with this id was found. - */ +** with this id was found. +*/ { const DbgInfo* Info; cc65_symbolinfo* D; @@ -7137,8 +7137,8 @@ const cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo Handle, unsigned Id) const cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name) /* Return a list of symbols with a given name. The function returns NULL if - * no symbol with this name was found. - */ +** no symbol with this name was found. +*/ { const DbgInfo* Info; cc65_symbolinfo* D; @@ -7159,8 +7159,8 @@ const cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name } /* Index contains the position. Count how many symbols with this name - * we have. Skip the first one, since we have at least one. - */ + ** we have. Skip the first one, since we have at least one. + */ Count = 1; while ((unsigned) Index + Count < CollCount (&Info->SymInfoByName)) { const SymInfo* S = CollAt (&Info->SymInfoByName, (unsigned) Index + Count); @@ -7187,10 +7187,10 @@ const cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name const cc65_symbolinfo* cc65_symbol_byscope (cc65_dbginfo Handle, unsigned ScopeId) /* Return a list of symbols in the given scope. This includes cheap local - * symbols, but not symbols in subscopes. The function returns NULL if the - * scope id is invalid (no such scope) and otherwise a - possibly empty - - * symbol list. - */ +** symbols, but not symbols in subscopes. The function returns NULL if the +** scope id is invalid (no such scope) and otherwise a - possibly empty - +** symbol list. +*/ { const DbgInfo* Info; cc65_symbolinfo* D; @@ -7230,9 +7230,9 @@ const cc65_symbolinfo* cc65_symbol_byscope (cc65_dbginfo Handle, unsigned ScopeI const cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo Handle, cc65_addr Start, cc65_addr End) /* Return a list of labels in the given range. End is inclusive. The function - * return NULL if no symbols within the given range are found. Non label - * symbols are ignored and not returned. - */ +** return NULL if no symbols within the given range are found. Non label +** symbols are ignored and not returned. +*/ { const DbgInfo* Info; Collection SymInfoList = COLLECTION_INITIALIZER; @@ -7247,21 +7247,21 @@ const cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo Handle, cc65_addr Start Info = Handle; /* Search for the symbol. Because we're searching for a range, we cannot - * make use of the function result. - */ + ** make use of the function result. + */ FindSymInfoByValue (&Info->SymInfoByVal, Start, &Index); /* Start from the given index, check all symbols until the end address is - * reached. Place all symbols into SymInfoList for later. - */ + ** reached. Place all symbols into SymInfoList for later. + */ for (I = Index; I < CollCount (&Info->SymInfoByVal); ++I) { /* Get the item */ SymInfo* Item = CollAt (&Info->SymInfoByVal, I); /* The collection is sorted by address, so if we get a value larger - * than the end address, we're done. - */ + ** than the end address, we're done. + */ if (Item->Value > (long) End) { break; } @@ -7276,8 +7276,8 @@ const cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo Handle, cc65_addr Start } /* If we don't have any labels within the range, bail out. No memory has - * been allocated for SymInfoList. - */ + ** been allocated for SymInfoList. + */ if (CollCount (&SymInfoList) == 0) { return 0; } @@ -7320,8 +7320,8 @@ void cc65_free_symbolinfo (cc65_dbginfo Handle, const cc65_symbolinfo* Info) const cc65_typedata* cc65_type_byid (cc65_dbginfo Handle, unsigned Id) /* Return the data for the type with the given id. The function returns NULL - * if no type with this id was found. - */ +** if no type with this id was found. +*/ { const DbgInfo* Info; const TypeInfo* T; diff --git a/src/dbginfo/dbginfo.h b/src/dbginfo/dbginfo.h index 7cb7271b2..7317e575f 100644 --- a/src/dbginfo/dbginfo.h +++ b/src/dbginfo/dbginfo.h @@ -52,8 +52,8 @@ extern "C" { /* Data types used for addresses, sizes and line numbers. Change to "unsigned - * long" if you ever want to run the code on a 16-bit machine. - */ +** long" if you ever want to run the code on a 16-bit machine. +*/ typedef unsigned cc65_line; /* Used to store line numbers */ typedef unsigned cc65_addr; /* Used to store (65xx) addresses */ typedef unsigned cc65_size; /* Used to store (65xx) sizes */ @@ -89,19 +89,19 @@ struct cc65_parseerror { typedef void (*cc65_errorfunc) (const cc65_parseerror*); /* Pointer to an opaque data structure containing information from the debug - * info file. Actually a handle to the data in the file. - */ +** info file. Actually a handle to the data in the file. +*/ typedef const void* cc65_dbginfo; cc65_dbginfo cc65_read_dbginfo (const char* filename, cc65_errorfunc errorfunc); /* Parse the debug info file with the given name. On success, the function - * will return a pointer to an opaque cc65_dbginfo structure, that must be - * passed to the other functions in this module to retrieve information. - * errorfunc is called in case of warnings and errors. If the file cannot be - * read successfully, NULL is returned. - */ +** will return a pointer to an opaque cc65_dbginfo structure, that must be +** passed to the other functions in this module to retrieve information. +** errorfunc is called in case of warnings and errors. If the file cannot be +** read successfully, NULL is returned. +*/ void cc65_free_dbginfo (cc65_dbginfo Handle); /* Free debug information read from a file */ @@ -154,26 +154,26 @@ const cc65_csyminfo* cc65_get_csymlist (cc65_dbginfo handle); const cc65_csyminfo* cc65_csym_byid (cc65_dbginfo handle, unsigned id); /* Return information about a c symbol with a specific id. The function - * returns NULL if the id is invalid (no such c symbol) and otherwise a - * cc65_csyminfo structure with one entry that contains the requested - * symbol information. - */ +** returns NULL if the id is invalid (no such c symbol) and otherwise a +** cc65_csyminfo structure with one entry that contains the requested +** symbol information. +*/ const cc65_csyminfo* cc65_cfunc_bymodule (cc65_dbginfo handle, unsigned module_id); /* Return the list of C functions (not symbols!) for a specific module. If - * the module id is invalid, the function will return NULL, otherwise a - * (possibly empty) c symbol list. - */ +** the module id is invalid, the function will return NULL, otherwise a +** (possibly empty) c symbol list. +*/ const cc65_csyminfo* cc65_cfunc_byname (cc65_dbginfo handle, const char* name); /* Return a list of all C functions with the given name that have a - * definition. - */ +** definition. +*/ const cc65_csyminfo* cc65_csym_byscope (cc65_dbginfo handle, unsigned scope_id); /* Return all C symbols for a scope. The function will return NULL if the - * given id is invalid. - */ +** given id is invalid. +*/ void cc65_free_csyminfo (cc65_dbginfo handle, const cc65_csyminfo* info); /* Free a c symbol info record */ @@ -206,10 +206,10 @@ const cc65_libraryinfo* cc65_get_librarylist (cc65_dbginfo handle); const cc65_libraryinfo* cc65_library_byid (cc65_dbginfo handle, unsigned id); /* Return information about a library with a specific id. The function - * returns NULL if the id is invalid (no such library) and otherwise a - * cc65_libraryinfo structure with one entry that contains the requested - * library information. - */ +** returns NULL if the id is invalid (no such library) and otherwise a +** cc65_libraryinfo structure with one entry that contains the requested +** library information. +*/ void cc65_free_libraryinfo (cc65_dbginfo handle, const cc65_libraryinfo* info); /* Free a library info record */ @@ -249,37 +249,37 @@ struct cc65_lineinfo { const cc65_lineinfo* cc65_line_byid (cc65_dbginfo handle, unsigned id); /* Return information about a line with a specific id. The function - * returns NULL if the id is invalid (no such line) and otherwise a - * cc65_lineinfo structure with one entry that contains the requested - * module information. - */ +** returns NULL if the id is invalid (no such line) and otherwise a +** cc65_lineinfo structure with one entry that contains the requested +** module information. +*/ const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo handle, unsigned source_id, cc65_line line); /* Return line information for a source file/line number combination. The - * function returns NULL if no line information was found. - */ +** function returns NULL if no line information was found. +*/ const cc65_lineinfo* cc65_line_bysource (cc65_dbginfo Handle, unsigned source_id); /* Return line information for a source file. The function returns NULL if the - * file id is invalid. - */ +** file id is invalid. +*/ const cc65_lineinfo* cc65_line_bysymdef (cc65_dbginfo handle, unsigned symbol_id); /* Return line information for the definition of a symbol. The function - * returns NULL if the symbol id is invalid, otherwise a list of line infos. - */ +** returns NULL if the symbol id is invalid, otherwise a list of line infos. +*/ const cc65_lineinfo* cc65_line_bysymref (cc65_dbginfo handle, unsigned symbol_id); /* Return line information for all references of a symbol. The function - * returns NULL if the symbol id is invalid, otherwise a list of line infos. - */ +** returns NULL if the symbol id is invalid, otherwise a list of line infos. +*/ const cc65_lineinfo* cc65_line_byspan (cc65_dbginfo handle, unsigned span_id); /* Return line information for a a span. The function returns NULL if the - * span id is invalid, otherwise a list of line infos. - */ +** span id is invalid, otherwise a list of line infos. +*/ void cc65_free_lineinfo (cc65_dbginfo handle, const cc65_lineinfo* info); /* Free line info returned by one of the other functions */ @@ -293,10 +293,10 @@ void cc65_free_lineinfo (cc65_dbginfo handle, const cc65_lineinfo* info); /* Module information - * Notes: - * - scope_id contains CC65_INV_ID if the module was compiled without - * debug information. - */ +** Notes: +** - scope_id contains CC65_INV_ID if the module was compiled without +** debug information. +*/ typedef struct cc65_moduledata cc65_moduledata; struct cc65_moduledata { unsigned module_id; /* The internal module id */ @@ -319,10 +319,10 @@ const cc65_moduleinfo* cc65_get_modulelist (cc65_dbginfo handle); const cc65_moduleinfo* cc65_module_byid (cc65_dbginfo handle, unsigned id); /* Return information about a module with a specific id. The function - * returns NULL if the id is invalid (no such module) and otherwise a - * cc65_moduleinfo structure with one entry that contains the requested - * module information. - */ +** returns NULL if the id is invalid (no such module) and otherwise a +** cc65_moduleinfo structure with one entry that contains the requested +** module information. +*/ void cc65_free_moduleinfo (cc65_dbginfo handle, const cc65_moduleinfo* info); /* Free a module info record */ @@ -360,26 +360,26 @@ const cc65_spaninfo* cc65_get_spanlist (cc65_dbginfo handle); const cc65_spaninfo* cc65_span_byid (cc65_dbginfo handle, unsigned id); /* Return information about a span with a specific id. The function - * returns NULL if the id is invalid (no such span) and otherwise a - * cc65_spaninfo structure with one entry that contains the requested - * span information. - */ +** returns NULL if the id is invalid (no such span) and otherwise a +** cc65_spaninfo structure with one entry that contains the requested +** span information. +*/ const cc65_spaninfo* cc65_span_byaddr (cc65_dbginfo handle, unsigned long addr); /* Return span information for the given address. The function returns NULL - * if no spans were found for this address. - */ +** if no spans were found for this address. +*/ const cc65_spaninfo* cc65_span_byline (cc65_dbginfo handle, unsigned line_id); /* Return span information for the given source line. The function returns NULL - * if the line id is invalid, otherwise the spans for this line (possibly zero). - */ +** if the line id is invalid, otherwise the spans for this line (possibly zero). +*/ const cc65_spaninfo* cc65_span_byscope (cc65_dbginfo handle, unsigned scope_id); /* Return span information for the given scope. The function returns NULL if - * the scope id is invalid, otherwise the spans for this scope (possibly zero). - */ +** the scope id is invalid, otherwise the spans for this scope (possibly zero). +*/ void cc65_free_spaninfo (cc65_dbginfo handle, const cc65_spaninfo* info); /* Free a span info record */ @@ -414,17 +414,17 @@ const cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo handle); const cc65_sourceinfo* cc65_source_byid (cc65_dbginfo handle, unsigned id); /* Return information about a source file with a specific id. The function - * returns NULL if the id is invalid (no such source file) and otherwise a - * cc65_sourceinfo structure with one entry that contains the requested - * source file information. - */ +** returns NULL if the id is invalid (no such source file) and otherwise a +** cc65_sourceinfo structure with one entry that contains the requested +** source file information. +*/ const cc65_sourceinfo* cc65_source_bymodule (cc65_dbginfo handle, unsigned module_id); /* Return information about the source files used to build a module. The - * function returns NULL if the module id is invalid (no such module) and - * otherwise a cc65_sourceinfo structure with one entry per source file. - */ +** function returns NULL if the module id is invalid (no such module) and +** otherwise a cc65_sourceinfo structure with one entry per source file. +*/ void cc65_free_sourceinfo (cc65_dbginfo handle, const cc65_sourceinfo* info); /* Free a source info record */ @@ -470,29 +470,29 @@ const cc65_scopeinfo* cc65_get_scopelist (cc65_dbginfo handle); const cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo handle, unsigned id); /* Return the scope with a given id. The function returns NULL if no scope - * with this id was found. - */ +** with this id was found. +*/ const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo handle, unsigned module_id); /* Return the list of scopes for one module. The function returns NULL if no - * scope with the given id was found. - */ +** scope with the given id was found. +*/ const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo handle, const char* name); /* Return the list of scopes with a given name. Returns NULL if no scope with - * the given name was found, otherwise a non empty scope list. - */ +** the given name was found, otherwise a non empty scope list. +*/ const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo handle, unsigned span_id); /* Return scope information for a a span. The function returns NULL if the - * span id is invalid, otherwise a list of line scopes. - */ +** span id is invalid, otherwise a list of line scopes. +*/ const cc65_scopeinfo* cc65_childscopes_byid (cc65_dbginfo handle, unsigned id); /* Return the direct child scopes of a scope with a given id. The function - * returns NULL if no scope with this id was found, otherwise a list of the - * direct childs. - */ +** returns NULL if no scope with this id was found, otherwise a list of the +** direct childs. +*/ void cc65_free_scopeinfo (cc65_dbginfo Handle, const cc65_scopeinfo* Info); /* Free a scope info record */ @@ -506,12 +506,12 @@ void cc65_free_scopeinfo (cc65_dbginfo Handle, const cc65_scopeinfo* Info); /* Segment information. - * Notes: - * - output_name may be NULL if the data wasn't written to the output file - * (example: bss segment) - * - output_offs is invalid if there is no output_name, and may not be of - * much use in case of a relocatable output file - */ +** Notes: +** - output_name may be NULL if the data wasn't written to the output file +** (example: bss segment) +** - output_offs is invalid if there is no output_name, and may not be of +** much use in case of a relocatable output file +*/ typedef struct cc65_segmentdata cc65_segmentdata; struct cc65_segmentdata { unsigned segment_id; /* The internal segment id */ @@ -535,17 +535,17 @@ const cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo handle); const cc65_segmentinfo* cc65_segment_byid (cc65_dbginfo handle, unsigned id); /* Return information about a segment with a specific id. The function returns - * NULL if the id is invalid (no such segment) and otherwise a cc65_segmentinfo - * structure with one entry that contains the requested segment information. - */ +** NULL if the id is invalid (no such segment) and otherwise a cc65_segmentinfo +** structure with one entry that contains the requested segment information. +*/ const cc65_segmentinfo* cc65_segment_byname (cc65_dbginfo handle, const char* name); /* Return information about a segment with a specific name. The function - * returns NULL if no segment with this name exists and otherwise a - * cc65_segmentinfo structure with one entry that contains the requested - * information. - */ +** returns NULL if no segment with this name exists and otherwise a +** cc65_segmentinfo structure with one entry that contains the requested +** information. +*/ void cc65_free_segmentinfo (cc65_dbginfo handle, const cc65_segmentinfo* info); /* Free a segment info record */ @@ -566,18 +566,18 @@ typedef enum { } cc65_symbol_type; /* Notes: - * - If the symbol is segment relative, the segment id gives segment - * information, otherwise it contains CC65_INV_ID. - * - If the type is CC65_SYM_IMPORT, export_id may contain the id of the - * export. This is not the case if the module contaiing the export doesn't - * have debug information. - * - For an import, the fields symbol_value and segment_id are taken from - * the export, if it is available, since imports have no value or segments - * by itself. - * - For an import symbol_size doesn't have a meaning. - * - For normal symbols (not cheap locals) parent_id contains CC65_INV_ID, - * for cheap locals it contains the symbol id of the parent symbol. - */ +** - If the symbol is segment relative, the segment id gives segment +** information, otherwise it contains CC65_INV_ID. +** - If the type is CC65_SYM_IMPORT, export_id may contain the id of the +** export. This is not the case if the module contaiing the export doesn't +** have debug information. +** - For an import, the fields symbol_value and segment_id are taken from +** the export, if it is available, since imports have no value or segments +** by itself. +** - For an import symbol_size doesn't have a meaning. +** - For normal symbols (not cheap locals) parent_id contains CC65_INV_ID, +** for cheap locals it contains the symbol id of the parent symbol. +*/ typedef struct cc65_symboldata cc65_symboldata; struct cc65_symboldata { unsigned symbol_id; /* Id of symbol */ @@ -601,28 +601,28 @@ struct cc65_symbolinfo { const cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo handle, unsigned id); /* Return the symbol with a given id. The function returns NULL if no symbol - * with this id was found. - */ +** with this id was found. +*/ const cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo handle, const char* name); /* Return a list of symbols with a given name. The function returns NULL if - * no symbol with this name was found. - */ +** no symbol with this name was found. +*/ const cc65_symbolinfo* cc65_symbol_byscope (cc65_dbginfo handle, unsigned scope_id); /* Return a list of symbols in the given scope. This includes cheap local - * symbols, but not symbols in subscopes. The function returns NULL if the - * scope id is invalid (no such scope) and otherwise a - possibly empty - - * symbol list. - */ +** symbols, but not symbols in subscopes. The function returns NULL if the +** scope id is invalid (no such scope) and otherwise a - possibly empty - +** symbol list. +*/ const cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo handle, cc65_addr start, cc65_addr end); /* Return a list of labels in the given range. end is inclusive. The function - * return NULL if no symbols within the given range are found. Non label - * symbols are ignored and not returned. - */ +** return NULL if no symbols within the given range are found. Non label +** symbols are ignored and not returned. +*/ void cc65_free_symbolinfo (cc65_dbginfo handle, const cc65_symbolinfo* info); /* Free a symbol info record */ @@ -654,12 +654,12 @@ typedef enum { /* A type is a linked list of typedata structures. In case of arrays, the - * structure will contain an element count and the element type. In case of - * pointers, the structure will contain the type of the data, the pointer - * points to (currently, there are only VOID pointers). - * The next pointer points to the next entry in the list. It is NULL if the - * end of the list is reached. - */ +** structure will contain an element count and the element type. In case of +** pointers, the structure will contain the type of the data, the pointer +** points to (currently, there are only VOID pointers). +** The next pointer points to the next entry in the list. It is NULL if the +** end of the list is reached. +*/ typedef struct cc65_typedata cc65_typedata; struct cc65_typedata { cc65_typedata* next; /* Pointer to next entry */ @@ -687,8 +687,8 @@ struct cc65_typedata { const cc65_typedata* cc65_type_byid (cc65_dbginfo handle, unsigned id); /* Return the data for the type with the given id. The function returns NULL - * if no type with this id was found. - */ +** if no type with this id was found. +*/ void cc65_free_typedata (cc65_dbginfo Handle, const cc65_typedata* data); /* Free a symbol info record */ diff --git a/src/dbginfo/dbgsh.c b/src/dbginfo/dbgsh.c index 4c2e3d79a..41200e86a 100644 --- a/src/dbginfo/dbgsh.c +++ b/src/dbginfo/dbgsh.c @@ -368,9 +368,9 @@ static const CmdEntry* FindCmd (const char* Cmd, const CmdEntry* Tab, unsigned C static void ExecCmd (Collection* Args, const CmdEntry* Tab, unsigned Count) /* Search for the command in slot 0 of the given collection. If found, check - * the argument count, then execute it. If there are problems, output a - * diagnostic. - */ +** the argument count, then execute it. If there are problems, output a +** diagnostic. +*/ { /* Search for the command, check number of args, then execute it */ const char* Cmd = CollAt (Args, 0); @@ -381,11 +381,11 @@ static void ExecCmd (Collection* Args, const CmdEntry* Tab, unsigned Count) } /* Check the number of arguments. Zero means that the function will check - * itself. A negative count means that the function needs at least - * abs(count) arguments. A positive count means that the function needs - * exactly this number of arguments. - * Note: The number includes the command itself. - */ + ** itself. A negative count means that the function needs at least + ** abs(count) arguments. A positive count means that the function needs + ** exactly this number of arguments. + ** Note: The number includes the command itself. + */ if (E->ArgCount > 0 && (int)CollCount (Args) != E->ArgCount) { /* Argument number mismatch */ switch (E->ArgCount) { @@ -479,10 +479,10 @@ static unsigned FindIdType (const char* TypeName) static int GetId (const char* S, unsigned* Id, unsigned* IdType) /* Parse a string for an id. If a valid id is found, it is placed in Id and - * the function returns true. If an optional type is found, it is placed in - * IdType, otherwise IdType is left unchanged. If no id is found, the - * function returns false. - */ +** the function returns true. If an optional type is found, it is placed in +** IdType, otherwise IdType is left unchanged. If no id is found, the +** function returns false. +*/ { char TypeBuf[20]; char C; @@ -924,8 +924,8 @@ static void UnloadFile (void) static int FileIsLoaded (void) /* Return true if the file is open and has loaded without errors: If not, - * print an error message and return false. - */ +** print an error message and return false. +*/ { /* File open? */ if (Info == 0) { @@ -1810,8 +1810,8 @@ static void CmdUnload (Collection* Args attribute ((unused))) static int Parse (char* CmdLine, Collection* Args) /* Parse the command line and store the arguments in Args. Return true if ok, - * false on error. - */ +** false on error. +*/ { char* End; diff --git a/src/grc65.vcxproj b/src/grc65.vcxproj index 29a8ca4b5..211ad7cce 100644 --- a/src/grc65.vcxproj +++ b/src/grc65.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -18,10 +18,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -47,7 +49,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> @@ -62,7 +64,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> diff --git a/src/ld65.vcxproj b/src/ld65.vcxproj index b837e1873..acb9b4240 100644 --- a/src/ld65.vcxproj +++ b/src/ld65.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -18,10 +18,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -47,7 +49,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> @@ -62,7 +64,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> diff --git a/src/ld65/asserts.c b/src/ld65/asserts.c index f84bdf3f4..276b13595 100644 --- a/src/ld65/asserts.c +++ b/src/ld65/asserts.c @@ -157,6 +157,3 @@ void CheckAssertions (void) } } } - - - diff --git a/src/ld65/asserts.h b/src/ld65/asserts.h index 94125294d..bce41aa15 100644 --- a/src/ld65/asserts.h +++ b/src/ld65/asserts.h @@ -76,6 +76,3 @@ void CheckAssertions (void); /* End of asserts.h */ #endif - - - diff --git a/src/ld65/bin.c b/src/ld65/bin.c index e86411241..ada4f1e3c 100644 --- a/src/ld65/bin.c +++ b/src/ld65/bin.c @@ -106,8 +106,8 @@ static unsigned BinWriteExpr (ExprNode* E, int Signed, unsigned Size, unsigned long Offs attribute ((unused)), void* Data) /* Called from SegWrite for an expression. Evaluate the expression, check the - * range and write the expression value to the file. - */ +** range and write the expression value to the file. +*/ { /* There's a predefined function to handle constant expressions */ return SegWriteConstExpr (((BinDesc*)Data)->F, E, Signed, Size); @@ -170,23 +170,23 @@ static void BinWriteMem (BinDesc* D, MemoryArea* M) PrintNumVal ("FileOffs", (unsigned long) ftell (D->F)); /* Check if the alignment for the segment from the linker config is - * a multiple for that of the segment. - */ + ** a multiple for that of the segment. + */ if ((S->RunAlignment % S->Seg->Alignment) != 0) { /* Segment requires another alignment than configured - * in the linker. - */ + ** in the linker. + */ Warning ("Segment `%s' is not aligned properly. Resulting " "executable may not be functional.", GetString (S->Name)); } /* If this is the run memory area, we must apply run alignment. If - * this is not the run memory area but the load memory area (which - * means that both are different), we must apply load alignment. - * Beware: DoWrite may be true even if this is the run memory area, - * because it may be also the load memory area. - */ + ** this is not the run memory area but the load memory area (which + ** means that both are different), we must apply load alignment. + ** Beware: DoWrite may be true even if this is the run memory area, + ** because it may be also the load memory area. + */ if (S->Run == M) { /* Handle ALIGN and OFFSET/START */ @@ -227,8 +227,8 @@ static void BinWriteMem (BinDesc* D, MemoryArea* M) } /* Now write the segment to disk if it is not a BSS type segment and - * if the memory area is the load area. - */ + ** if the memory area is the load area. + */ if (DoWrite) { unsigned long P = ftell (D->F); SegWrite (D->Filename, D->F, S->Seg, BinWriteExpr, D); @@ -263,9 +263,9 @@ static int BinUnresolved (unsigned Name attribute ((unused)), void* D) /* Called if an unresolved symbol is encountered */ { /* Unresolved symbols are an error in binary format. Bump the counter - * and return zero telling the caller that the symbol is indeed - * unresolved. - */ + ** and return zero telling the caller that the symbol is indeed + ** unresolved. + */ ((BinDesc*) D)->Undef++; return 0; } @@ -281,8 +281,8 @@ void BinWriteTarget (BinDesc* D, struct File* F) D->Filename = GetString (F->Name); /* Check for unresolved symbols. The function BinUnresolved is called - * if we get an unresolved symbol. - */ + ** if we get an unresolved symbol. + */ D->Undef = 0; /* Reset the counter */ CheckUnresolvedImports (BinUnresolved, D); if (D->Undef > 0) { @@ -316,8 +316,3 @@ void BinWriteTarget (BinDesc* D, struct File* F) D->F = 0; D->Filename = 0; } - - - - - diff --git a/src/ld65/bin.h b/src/ld65/bin.h index 9cb5e7dd9..f53aec9c4 100644 --- a/src/ld65/bin.h +++ b/src/ld65/bin.h @@ -73,6 +73,3 @@ void BinWriteTarget (BinDesc* D, File* F); /* End of bin.h */ #endif - - - diff --git a/src/ld65/binfmt.c b/src/ld65/binfmt.c index 39a7ae3e2..a510f94b7 100644 --- a/src/ld65/binfmt.c +++ b/src/ld65/binfmt.c @@ -88,6 +88,3 @@ int RelocatableBinFmt (unsigned Format) /* Return the flag */ return Reloc; } - - - diff --git a/src/ld65/binfmt.h b/src/ld65/binfmt.h index 5c4bf5778..831e46d12 100644 --- a/src/ld65/binfmt.h +++ b/src/ld65/binfmt.h @@ -63,6 +63,3 @@ int RelocatableBinFmt (unsigned Format); /* End of binfmt.h */ #endif - - - diff --git a/src/ld65/cfgexpr.c b/src/ld65/cfgexpr.c index 65ff3dd67..a6c912491 100644 --- a/src/ld65/cfgexpr.c +++ b/src/ld65/cfgexpr.c @@ -230,8 +230,8 @@ long CfgConstExpr (void) long CfgCheckedConstExpr (long Min, long Max) /* Read an expression, make sure it's an int and in range, then return its - * value. - */ +** value. +*/ { /* Get the value */ long Val = CfgConstExpr (); @@ -244,6 +244,3 @@ long CfgCheckedConstExpr (long Min, long Max) /* Return the value */ return Val; } - - - diff --git a/src/ld65/cfgexpr.h b/src/ld65/cfgexpr.h index 8a6e18c67..4ec00c052 100644 --- a/src/ld65/cfgexpr.h +++ b/src/ld65/cfgexpr.h @@ -57,13 +57,11 @@ long CfgConstExpr (void); long CfgCheckedConstExpr (long Min, long Max); /* Read an expression, make sure it's an int and in range, then return its - * value. - */ +** value. +*/ /* End of cfgexpr.h */ + #endif - - - diff --git a/src/ld65/condes.c b/src/ld65/condes.c index dc8383767..d8c378211 100644 --- a/src/ld65/condes.c +++ b/src/ld65/condes.c @@ -137,9 +137,9 @@ static int ConDesCompare (void* Data, const void* E1, const void* E2) int Cmp; /* Data is actually a pointer to a ConDesDesc from the table, E1 and - * E2 are exports from the collection. Get the condes type and cast - * the void pointers to object pointers. - */ + ** E2 are exports from the collection. Get the condes type and cast + ** the void pointers to object pointers. + */ ConDesDesc* CD = ((ConDesDesc*) Data); int Type = CD - ConDes; const Export* Exp1 = (const Export*) E1; @@ -178,16 +178,16 @@ static void ConDesCreateOne (ConDesDesc* CD) unsigned I; /* Check if this table has a segment and table label defined. If not, - * creation was not requested in the config file - ignore it. - */ + ** creation was not requested in the config file - ignore it. + */ if (CD->SegName == INVALID_STRING_ID || CD->Label == INVALID_STRING_ID) { return; } /* Check if there is an import for the table label. If not, there is no - * reference to the table and we would just waste memory creating the - * table. - */ + ** reference to the table and we would just waste memory creating the + ** table. + */ if (!IsUnresolved (CD->Label)) { return; } @@ -202,10 +202,10 @@ static void ConDesCreateOne (ConDesDesc* CD) Sec = NewSection (Seg, 1, ADDR_SIZE_ABS); /* Walk over the exports and create a fragment for each one. We will use - * the exported expression without copying it, since it's cheap and there - * is currently no place where it gets changed (hope this will not hunt - * me later...). - */ + ** the exported expression without copying it, since it's cheap and there + ** is currently no place where it gets changed (hope this will not hunt + ** me later...). + */ Count = CollCount (&CD->ExpList); for (I = 0; I < Count; ++I) { @@ -220,13 +220,13 @@ static void ConDesCreateOne (ConDesDesc* CD) } /* Define the table start as an export, offset into section is zero - * (the section only contains the table). - */ + ** (the section only contains the table). + */ CreateSectionExport (CD->Label, Sec, 0); /* If we have a CountSym name given AND if it is referenced, define it - * with the number of elements in the table. - */ + ** with the number of elements in the table. + */ if (CD->CountSym) { CreateConstExport (CD->CountSym, Count); } @@ -273,8 +273,8 @@ void ConDesSetSegName (unsigned Type, unsigned SegName) const ConDesImport* ConDesGetImport (unsigned Type) /* Get the forced import for the given ConDes type. Returns NULL if there is - * no forced import for this type. - */ +** no forced import for this type. +*/ { const ConDesImport* Import; @@ -389,6 +389,3 @@ void ConDesDump (void) printf ("CONDES(%u): %u symbols\n", Type, CollCount (ExpList)); } } - - - diff --git a/src/ld65/condes.h b/src/ld65/condes.h index 3cec6bda9..6df8361ac 100644 --- a/src/ld65/condes.h +++ b/src/ld65/condes.h @@ -89,8 +89,8 @@ void ConDesSetSegName (unsigned Type, unsigned SegName); const ConDesImport* ConDesGetImport (unsigned Type); /* Get the forced import for the given ConDes type. Returns NULL if there is - * no forced import for this type. - */ +** no forced import for this type. +*/ void ConDesSetImport (unsigned Type, const ConDesImport* Import); /* Set the forced import for the given ConDes type */ @@ -121,6 +121,3 @@ void ConDesDump (void); /* End of condes.h */ #endif - - - diff --git a/src/ld65/config.c b/src/ld65/config.c index a5d6ff39b..46e9a48fb 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -131,9 +131,9 @@ typedef enum { } CfgSymType; /* Symbol structure. It is used for o65 imports and exports, but also for - * symbols from the SYMBOLS sections (symbols defined in the config file or - * forced imports). - */ +** symbols from the SYMBOLS sections (symbols defined in the config file or +** forced imports). +*/ typedef struct CfgSymbol CfgSymbol; struct CfgSymbol { CfgSymType Type; /* Type of symbol */ @@ -268,9 +268,9 @@ static void MemoryInsert (MemoryArea* M, SegDesc* S) static CfgSymbol* NewCfgSymbol (CfgSymType Type, unsigned Name) /* Create a new CfgSymbol structure with the given type and name. The - * current config file position is recorded in the returned struct. The - * created struct is inserted into the CfgSymbols collection and returned. - */ +** current config file position is recorded in the returned struct. The +** created struct is inserted into the CfgSymbols collection and returned. +*/ { /* Allocate memory */ CfgSymbol* Sym = xmalloc (sizeof (CfgSymbol)); @@ -385,8 +385,8 @@ static void FreeSegDesc (SegDesc* S) static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name) /* Check if the item is already defined. Print an error if so. If not, set - * the marker that we have a definition now. - */ +** the marker that we have a definition now. +*/ { if (*Flags & Mask) { CfgError (&CfgErrorPos, "%s is already defined", Name); @@ -522,8 +522,8 @@ static void ParseMemory (void) AttrCheck (M->Attr, MA_SIZE, "SIZE"); /* If we don't have a file name for output given, use the default - * file name. - */ + ** file name. + */ if ((M->Attr & MA_FILE) == 0) { FileInsert (GetFile (GetStringId (OutputName)), M); OutputNameUsed = 1; @@ -781,8 +781,8 @@ static void ParseSegments (void) } /* An attribute of ALIGN_LOAD doesn't make sense if there are no - * separate run and load memory areas. - */ + ** separate run and load memory areas. + */ if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) { CfgWarning (&CfgErrorPos, "ALIGN_LOAD attribute specified, but no separate " @@ -792,8 +792,8 @@ static void ParseSegments (void) } /* If the segment is marked as BSS style, it may not have separate - * load and run memory areas, because it's is never written to disk. - */ + ** load and run memory areas, because it's is never written to disk. + */ if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) { CfgWarning (&CfgErrorPos, "Segment with type `bss' has both LOAD and RUN " @@ -930,8 +930,8 @@ static void ParseO65 (void) /* Cannot use this attribute twice */ FlagAttr (&AttrFlags, atOS, "OS"); /* Get the operating system. It may be specified as name or - * as a number in the range 1..255. - */ + ** as a number in the range 1..255. + */ if (CfgTok == CFGTOK_INTCON) { CfgRangeCheck (O65OS_MIN, O65OS_MAX); OS = (unsigned) CfgIVal; @@ -1266,8 +1266,8 @@ static void ParseStartAddress (void) AttrCheck (AttrFlags, atDefault, "DEFAULT"); /* If no start address was given on the command line, use the one given - * here - */ + ** here + */ if (!HaveStartAddr) { StartAddr = DefStartAddr; } @@ -1559,8 +1559,8 @@ void CfgRead (void) O65FmtDesc = NewO65Desc (); /* If we have a config name given, open the file, otherwise we will read - * from a buffer. - */ + ** from a buffer. + */ CfgOpenInput (); /* Parse the file */ @@ -1591,14 +1591,14 @@ static void ProcessSegments (void) SegDesc* S = CollAtUnchecked (&SegDescList, I); /* Search for the actual segment in the input files. The function may - * return NULL (no such segment), this is checked later. - */ + ** return NULL (no such segment), this is checked later. + */ S->Seg = SegFind (S->Name); /* If the segment is marked as BSS style, and if the segment exists - * in any of the object file, check that there's no initialized data - * in the segment. - */ + ** in any of the object file, check that there's no initialized data + ** in the segment. + */ if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) { CfgWarning (GetSourcePos (S->LI), "Segment `%s' with type `bss' contains initialized data", @@ -1606,10 +1606,10 @@ static void ProcessSegments (void) } /* If this segment does exist in any of the object files, insert the - * segment into the load/run memory areas. Otherwise print a warning - * and discard it, because the segment pointer in the descriptor is - * invalid. - */ + ** segment into the load/run memory areas. Otherwise print a warning + ** and discard it, because the segment pointer in the descriptor is + ** invalid. + */ if (S->Seg != 0) { /* Insert the segment into the memory area list */ @@ -1669,9 +1669,9 @@ static void ProcessSymbols (void) } /* Check if we have this symbol defined already. The entry - * routine will check this also, but we get a more verbose - * error message when checking it here. - */ + ** routine will check this also, but we get a more verbose + ** error message when checking it here. + */ if (O65GetExport (O65FmtDesc, Sym->Name) != 0) { CfgError ( GetSourcePos (Sym->LI), @@ -1695,9 +1695,9 @@ static void ProcessSymbols (void) } /* Check if we have this symbol defined already. The entry - * routine will check this also, but we get a more verbose - * error message when checking it here. - */ + ** routine will check this also, but we get a more verbose + ** error message when checking it here. + */ if (O65GetImport (O65FmtDesc, Sym->Name) != 0) { CfgError ( GetSourcePos (Sym->LI), @@ -1770,28 +1770,28 @@ static void CreateLoadDefines (SegDesc* S, unsigned long SegAddr) unsigned CfgProcess (void) /* Process the config file after reading in object files and libraries. This - * includes postprocessing of the config file data but also assigning segments - * and defining segment/memory area related symbols. The function will return - * the number of memory area overflows (so zero means anything went ok). - * In case of overflows, a short mapfile can be generated later, to ease the - * task of rearranging segments for the user. - */ +** includes postprocessing of the config file data but also assigning segments +** and defining segment/memory area related symbols. The function will return +** the number of memory area overflows (so zero means anything went ok). +** In case of overflows, a short mapfile can be generated later, to ease the +** task of rearranging segments for the user. +*/ { unsigned Overflows = 0; unsigned I; /* Postprocess symbols. We must do that first, since weak symbols are - * defined here, which may be needed later. - */ + ** defined here, which may be needed later. + */ ProcessSymbols (); /* Postprocess segments */ ProcessSegments (); /* Walk through each of the memory sections. Add up the sizes and check - * for an overflow of the section. Assign the start addresses of the - * segments while doing this. - */ + ** for an overflow of the section. Assign the start addresses of the + ** segments while doing this. + */ for (I = 0; I < CollCount (&MemoryAreas); ++I) { unsigned J; @@ -1807,8 +1807,8 @@ unsigned CfgProcess (void) M->Relocatable = RelocatableBinFmt (M->F->Format); /* Resolve the start address expression, remember the start address - * and mark the memory area as placed. - */ + ** and mark the memory area as placed. + */ if (!IsConstExpr (M->StartExpr)) { CfgError (GetSourcePos (M->LI), "Start address of memory area `%s' is not constant", @@ -1818,9 +1818,9 @@ unsigned CfgProcess (void) M->Flags |= MF_PLACED; /* If requested, define the symbol for the start of the memory area. - * Doing it here means that the expression for the size of the area - * may reference this symbol. - */ + ** Doing it here means that the expression for the size of the area + ** may reference this symbol. + */ if (M->Flags & MF_DEFINE) { Export* E; StrBuf Buf = STATIC_STRBUF_INITIALIZER; @@ -1851,21 +1851,21 @@ unsigned CfgProcess (void) unsigned long StartAddr = Addr; /* Some actions depend on wether this is the load or run memory - * area. - */ + ** area. + */ if (S->Run == M) { /* This is the run (and maybe load) memory area. Handle - * alignment and explict start address and offset. - */ + ** alignment and explict start address and offset. + */ if (S->Flags & SF_ALIGN) { /* Align the address */ unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment); /* If the first segment placed in the memory area needs - * fill bytes for the alignment, emit a warning, since - * this is somewhat suspicious. - */ + ** fill bytes for the alignment, emit a warning, since + ** this is somewhat suspicious. + */ if (M->FillLevel == 0 && NewAddr > Addr) { CfgWarning (GetSourcePos (S->LI), "First segment in memory area `%s' does " @@ -1901,22 +1901,22 @@ unsigned CfgProcess (void) } /* Set the start address of this segment, set the readonly flag - * in the segment and and remember if the segment is in a - * relocatable file or not. - */ + ** in the segment and and remember if the segment is in a + ** relocatable file or not. + */ S->Seg->PC = Addr; S->Seg->ReadOnly = (S->Flags & SF_RO) != 0; /* Remember the run memory for this segment, which is also a - * flag that the segment has been placed. - */ + ** flag that the segment has been placed. + */ S->Seg->MemArea = M; } else if (S->Load == M) { /* This is the load memory area, *and* run and load are - * different (because of the "else" above). Handle alignment. - */ + ** different (because of the "else" above). Handle alignment. + */ if (S->Flags & SF_ALIGN_LOAD) { /* Align the address */ Addr = AlignAddr (Addr, S->LoadAlignment); @@ -1925,15 +1925,15 @@ unsigned CfgProcess (void) } /* If this is the load memory area and the segment doesn't have a - * fill value defined, use the one from the memory area. - */ + ** fill value defined, use the one from the memory area. + */ if (S->Load == M && (S->Flags & SF_FILLVAL) == 0) { S->Seg->FillVal = M->FillVal; } /* Increment the fill level of the memory area and check for an - * overflow. - */ + ** overflow. + */ M->FillLevel = Addr + S->Seg->Size - M->Start; if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) { ++Overflows; @@ -1945,8 +1945,8 @@ unsigned CfgProcess (void) } /* If requested, define symbols for the start and size of the - * segment. - */ + ** segment. + */ if (S->Flags & SF_DEFINE) { if (S->Run == M && (S->Flags & SF_RUN_DEF) == 0) { CreateRunDefines (S, Addr); @@ -1960,8 +1960,8 @@ unsigned CfgProcess (void) Addr += S->Seg->Size; /* If this segment will go out to the file, or its place - * in the file will be filled, then increase the file size. - */ + ** in the file will be filled, then increase the file size. + */ if (S->Load == M && ((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0)) { M->F->Size += Addr - StartAddr; @@ -1970,8 +1970,8 @@ unsigned CfgProcess (void) } /* If requested, define symbols for start, size and offset of the - * memory area - */ + ** memory area + */ if (M->Flags & MF_DEFINE) { Export* E; StrBuf Buf = STATIC_STRBUF_INITIALIZER; @@ -1987,8 +1987,8 @@ unsigned CfgProcess (void) CollAppend (&E->DefLines, M->LI); /* Define the file offset of the memory area. This isn't of much - * use for relocatable output files. - */ + ** use for relocatable output files. + */ if (!M->Relocatable) { SB_Printf (&Buf, "__%s_FILEOFFS__", GetString (M->Name)); E = CreateConstExport (GetStrBufId (&Buf), M->FileOffs); @@ -2000,8 +2000,8 @@ unsigned CfgProcess (void) } /* If we didn't have an overflow and are requested to fill the memory - * area, acount for that in the file size. - */ + ** area, acount for that in the file size. + */ if ((M->Flags & MF_OVERFLOW) == 0 && (M->Flags & MF_FILL) != 0) { M->F->Size += (M->Size - M->FillLevel); } @@ -2054,8 +2054,8 @@ void CfgWriteTarget (void) } else { /* No output file. Walk through the list and mark all segments - * loading into these memory areas in this file as dumped. - */ + ** loading into these memory areas in this file as dumped. + */ unsigned J; for (J = 0; J < CollCount (&F->MemoryAreas); ++J) { @@ -2080,6 +2080,3 @@ void CfgWriteTarget (void) } } } - - - diff --git a/src/ld65/config.h b/src/ld65/config.h index 76104d2d8..6a36af6cc 100644 --- a/src/ld65/config.h +++ b/src/ld65/config.h @@ -110,12 +110,12 @@ void CfgRead (void); unsigned CfgProcess (void); /* Process the config file after reading in object files and libraries. This - * includes postprocessing of the config file data but also assigning segments - * and defining segment/memory area related symbols. The function will return - * the number of memory area overflows (so zero means anything went ok). - * In case of overflows, a short mapfile can be generated later, to ease the - * task of rearranging segments for the user. - */ +** includes postprocessing of the config file data but also assigning segments +** and defining segment/memory area related symbols. The function will return +** the number of memory area overflows (so zero means anything went ok). +** In case of overflows, a short mapfile can be generated later, to ease the +** task of rearranging segments for the user. +*/ void CfgWriteTarget (void); /* Write the target file(s) */ @@ -125,8 +125,3 @@ void CfgWriteTarget (void); /* End of config.h */ #endif - - - - - diff --git a/src/ld65/dbgfile.c b/src/ld65/dbgfile.c index aec560212..386706f66 100644 --- a/src/ld65/dbgfile.c +++ b/src/ld65/dbgfile.c @@ -60,10 +60,10 @@ static void AssignIds (void) /* Assign the base ids for debug info output. Within each module, many of the - * items are addressed by ids which are actually the indices of the items in - * the collections. To make them unique, we must assign a unique base to each - * range. - */ +** items are addressed by ids which are actually the indices of the items in +** the collections. To make them unique, we must assign a unique base to each +** range. +*/ { /* Walk over all modules */ unsigned I; @@ -114,8 +114,8 @@ void CreateDbgFile (void) fprintf (F, "version\tmajor=2,minor=0\n"); /* Output a line with the item numbers so the debug info module is able - * to preallocate the required memory. - */ + ** to preallocate the required memory. + */ fprintf ( F, "info\tcsym=%u,file=%u,lib=%u,line=%u,mod=%u,scope=%u,seg=%u,span=%u,sym=%u,type=%u\n", @@ -169,6 +169,3 @@ void CreateDbgFile (void) Error ("Error closing debug file `%s': %s", DbgFileName, strerror (errno)); } } - - - diff --git a/src/ld65/dbgfile.h b/src/ld65/dbgfile.h index a5020101e..b8e1a534f 100644 --- a/src/ld65/dbgfile.h +++ b/src/ld65/dbgfile.h @@ -52,6 +52,3 @@ void CreateDbgFile (void); /* End of dbgfile.h */ #endif - - - diff --git a/src/ld65/dbgsyms.c b/src/ld65/dbgsyms.c index 808f04c44..955f0f76d 100644 --- a/src/ld65/dbgsyms.c +++ b/src/ld65/dbgsyms.c @@ -91,8 +91,8 @@ struct HLLDbgSym { }; /* We will collect all debug symbols in the following array and remove - * duplicates before outputing them into a label file. - */ +** duplicates before outputing them into a label file. +*/ static DbgSym* DbgSymPool[256]; @@ -141,8 +141,8 @@ static HLLDbgSym* NewHLLDbgSym (void) static DbgSym* GetDbgSym (DbgSym* D, long Val) /* Check if we find the same debug symbol in the table. If we find it, return - * a pointer to the other occurrence, if we didn't find it, return NULL. - */ +** a pointer to the other occurrence, if we didn't find it, return NULL. +*/ { /* Create the hash. We hash over the symbol value */ unsigned Hash = ((Val >> 24) & 0xFF) ^ @@ -219,8 +219,8 @@ DbgSym* ReadDbgSym (FILE* F, ObjData* O, unsigned Id) } /* If its an exports, there's also the export id, but we don't remember - * it but use it to let the export point back to us. - */ + ** it but use it to let the export point back to us. + */ if (SYM_IS_EXPORT (D->Type)) { /* Get the export from the export id, then set the our id */ GetObjExport (O, ReadVar (F))->DbgSymId = Id; @@ -377,8 +377,8 @@ void PrintDbgSyms (FILE* F) } /* For cheap local symbols, add the owner symbol, for others, - * add the owner scope. - */ + ** add the owner scope. + */ if (SYM_IS_STD (S->Type)) { fprintf (F, ",scope=%u", O->ScopeBaseId + S->OwnerId); } else { @@ -390,9 +390,9 @@ void PrintDbgSyms (FILE* F) PrintLineInfo (F, &S->RefLines, ",ref=%u"); /* If this is an import, output the id of the matching export. - * If this is not an import, output its value and - if we have - * it - the segment. - */ + ** If this is not an import, output its value and - if we have + ** it - the segment. + */ if (SYM_IS_IMPORT (S->Type)) { /* Get the import */ @@ -405,9 +405,9 @@ void PrintDbgSyms (FILE* F) fputs (",type=imp", F); /* If this is not a linker generated symbol, and the module - * that contains the export has debug info, output the debug - * symbol id for the export - */ + ** that contains the export has debug info, output the debug + ** symbol id for the export + */ if (Exp->Obj && OBJ_HAS_DBGINFO (Exp->Obj->Header.Flags)) { fprintf (F, ",exp=%u", Exp->Obj->SymBaseId + Exp->DbgSymId); } @@ -423,8 +423,8 @@ void PrintDbgSyms (FILE* F) fprintf (F, ",val=0x%lX", Val); /* Check for a segmented expression and add the segment id to - * the debug info if we have one. - */ + ** the debug info if we have one. + */ GetSegExprVal (S->Expr, &D); if (!D.TooComplex && D.Seg != 0) { fprintf (F, ",seg=%u", D.Seg->Id); @@ -526,9 +526,9 @@ void PrintDbgSymLabels (FILE* F) Val = GetDbgSymVal (D); /* Lookup this symbol in the table. If it is found in the table, it was - * already written to the file, so don't emit it twice. If it is not in - * the table, insert and output it. - */ + ** already written to the file, so don't emit it twice. If it is not in + ** the table, insert and output it. + */ if (GetDbgSym (D, Val) == 0) { /* Emit the VICE label line */ @@ -540,7 +540,3 @@ void PrintDbgSymLabels (FILE* F) } } } - - - - diff --git a/src/ld65/dbgsyms.h b/src/ld65/dbgsyms.h index 3d58579f6..f631dcb52 100644 --- a/src/ld65/dbgsyms.h +++ b/src/ld65/dbgsyms.h @@ -96,6 +96,3 @@ void PrintDbgSymLabels (FILE* F); /* End of dbgsyms.h */ #endif - - - diff --git a/src/ld65/error.c b/src/ld65/error.c index bfd7e0671..20dfd4537 100644 --- a/src/ld65/error.c +++ b/src/ld65/error.c @@ -107,6 +107,3 @@ void Internal (const char* Format, ...) exit (EXIT_FAILURE); } - - - diff --git a/src/ld65/error.h b/src/ld65/error.h index e144bb4fd..b49d8919c 100644 --- a/src/ld65/error.h +++ b/src/ld65/error.h @@ -63,6 +63,3 @@ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)) /* End of error.h */ #endif - - - diff --git a/src/ld65/exports.c b/src/ld65/exports.c index c5533d318..e7ef3d413 100644 --- a/src/ld65/exports.c +++ b/src/ld65/exports.c @@ -123,9 +123,9 @@ static Import* NewImport (unsigned char AddrSize, ObjData* Obj) void FreeImport (Import* I) /* Free an import. NOTE: This won't remove the import from the exports table, - * so it may only be called for unused imports (imports from modules that - * aren't referenced). - */ +** so it may only be called for unused imports (imports from modules that +** aren't referenced). +*/ { /* Safety */ PRECONDITION ((I->Flags & IMP_INLIST) == 0); @@ -161,9 +161,9 @@ Import* ReadImport (FILE* F, ObjData* Obj) /* Check the address size */ if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) { /* Beware: This function may be called in cases where the object file - * is not read completely into memory. In this case, the file list is - * invalid. Be sure not to access it in this case. - */ + ** is not read completely into memory. In this case, the file list is + ** invalid. Be sure not to access it in this case. + */ if (ObjHasFiles (I->Obj)) { const LineInfo* LI = GetImportPos (I); Error ("Invalid import size in for `%s', imported from %s(%u): 0x%02X", @@ -197,8 +197,8 @@ Import* GenImport (unsigned Name, unsigned char AddrSize) /* Check the address size */ if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) { /* We have no object file information and no line info for a new - * import - */ + ** import + */ Error ("Invalid import size 0x%02X for symbol `%s'", I->AddrSize, GetString (I->Name)); @@ -246,8 +246,8 @@ Import* InsertImport (Import* I) } /* Ok, E now points to a valid exports entry for the given import. Insert - * the import into the imports list and update the counters. - */ + ** the import into the imports list and update the counters. + */ I->Exp = E; I->Next = E->ImpList; E->ImpList = I; @@ -321,9 +321,9 @@ static Export* NewExport (unsigned Type, unsigned char AddrSize, void FreeExport (Export* E) /* Free an export. NOTE: This won't remove the export from the exports table, - * so it may only be called for unused exports (exports from modules that - * aren't referenced). - */ +** so it may only be called for unused exports (exports from modules that +** aren't referenced). +*/ { /* Safety */ PRECONDITION ((E->Flags & EXP_INLIST) == 0); @@ -367,9 +367,9 @@ Export* ReadExport (FILE* F, ObjData* O) ReadData (F, ConDes, ConDesCount); /* Re-order the data. In the file, each decl is encoded into a byte - * which contains the type and the priority. In memory, we will use - * an array of types which contain the priority. - */ + ** which contains the type and the priority. In memory, we will use + ** an array of types which contain the priority. + */ for (I = 0; I < ConDesCount; ++I) { E->ConDes[CD_GET_TYPE (ConDes[I])] = CD_GET_PRIO (ConDes[I]); } @@ -395,8 +395,8 @@ Export* ReadExport (FILE* F, ObjData* O) ReadLineInfoList (F, O, &E->RefLines); /* If this symbol is exported as a condes, and the condes type declares a - * forced import, add this import to the object module. - */ + ** forced import, add this import to the object module. + */ for (I = 0; I < CD_TYPE_COUNT; ++I) { const ConDesImport* CDI; @@ -410,10 +410,10 @@ Export* ReadExport (FILE* F, ObjData* O) CollAppend (&O->Imports, Imp); /* Add line info for the export that is actually the condes that - * forces the import. Then, add line info for the config. file. - * The export's info is added first because the import pretends - * that it came from the object module instead of the config. file. - */ + ** forces the import. Then, add line info for the config. file. + ** The export's info is added first because the import pretends + ** that it came from the object module instead of the config. file. + */ for (J = 0; J < CollCount (&E->DefLines); ++J) { CollAppend (&Imp->RefLines, DupLineInfo (CollAt (&E->DefLines, J))); } @@ -461,8 +461,8 @@ void InsertExport (Export* E) if (L->Expr == 0) { /* This *is* an unresolved external. Use the actual export - * in E instead of the dummy one in L. - */ + ** in E instead of the dummy one in L. + */ E->Next = L->Next; E->ImpCount = L->ImpCount; E->ImpList = L->ImpList; @@ -474,8 +474,8 @@ void InsertExport (Export* E) ImpOpen -= E->ImpCount; /* Decrease open imports now */ xfree (L); /* We must run through the import list and change the - * export pointer now. - */ + ** export pointer now. + */ Imp = E->ImpList; while (Imp) { Imp->Exp = E; @@ -606,8 +606,8 @@ Export* CreateSectionExport (unsigned Name, Section* Sec, unsigned long Offs) Export* FindExport (unsigned Name) /* Check for an identifier in the list. Return 0 if not found, otherwise - * return a pointer to the export. - */ +** return a pointer to the export. +*/ { /* Get a pointer to the list with the symbols hash value */ Export* L = HashTab[Name & HASHTAB_MASK]; @@ -685,9 +685,9 @@ static void CheckSymType (const Export* E) const LineInfo* ImportLI = GetImportPos (I); /* Generate strings that describe the location of the im- and - * exports. This depends on the place from where they come: - * Object file or linker config. - */ + ** exports. This depends on the place from where they come: + ** Object file or linker config. + */ if (E->Obj) { /* The export comes from an object file */ SB_Printf (&ExportLoc, "%s, %s(%u)", @@ -707,15 +707,15 @@ static void CheckSymType (const Export* E) GetSourceLine (ImportLI)); } else if (ImportLI) { /* The import is linker generated and we have line - * information - */ + ** information + */ SB_Printf (&ImportLoc, "%s(%u)", GetSourceName (ImportLI), GetSourceLine (ImportLI)); } else { /* The import is linker generated and we don't have line - * information - */ + ** information + */ SB_Printf (&ImportLoc, "%s", GetObjFileName (I->Obj)); } @@ -758,8 +758,8 @@ static void CheckSymTypes (void) static void PrintUnresolved (ExpCheckFunc F, void* Data) /* Print a list of unresolved symbols. On unresolved symbols, F is - * called (see the comments on ExpCheckFunc in the data section). - */ +** called (see the comments on ExpCheckFunc in the data section). +*/ { unsigned I; @@ -827,8 +827,8 @@ static void CreateExportPool (void) void CheckExports (void) /* Setup the list of all exports and check for export/import symbol type - * mismatches. - */ +** mismatches. +*/ { /* Create an export pool */ CreateExportPool (); @@ -841,8 +841,8 @@ void CheckExports (void) void CheckUnresolvedImports (ExpCheckFunc F, void* Data) /* Check if there are any unresolved imports. On unresolved imports, F is - * called (see the comments on ExpCheckFunc in the data section). - */ +** called (see the comments on ExpCheckFunc in the data section). +*/ { /* Check for unresolved externals */ if (ImpOpen != 0) { @@ -870,8 +870,8 @@ static char GetAddrSizeCode (unsigned char AddrSize) -void PrintExportMap (FILE* F) -/* Print an export map to the given file */ +void PrintExportMapByName (FILE* F) +/* Print an export map, sorted by symbol name, to the given file */ { unsigned I; unsigned Count; @@ -902,6 +902,61 @@ void PrintExportMap (FILE* F) +static int CmpExpValue (const void* I1, const void* I2) +/* Compare function for qsort */ +{ + long V1 = GetExportVal (ExpPool [*(unsigned *)I1]); + long V2 = GetExportVal (ExpPool [*(unsigned *)I2]); + + return V1 < V2 ? -1 : V1 == V2 ? 0 : 1; +} + + + +void PrintExportMapByValue (FILE* F) +/* Print an export map, sorted by symbol value, to the given file */ +{ + unsigned I; + unsigned Count; + unsigned *ExpValXlat; + + /* Create a translation table where the symbols are sorted by value. */ + ExpValXlat = xmalloc (ExpCount * sizeof (unsigned)); + for (I = 0; I < ExpCount; ++I) { + /* Initialize table with current sort order. */ + ExpValXlat [I] = I; + } + + /* Sort them by value */ + qsort (ExpValXlat, ExpCount, sizeof (unsigned), CmpExpValue); + + /* Print all exports */ + Count = 0; + for (I = 0; I < ExpCount; ++I) { + const Export* E = ExpPool [ExpValXlat [I]]; + + /* Print unreferenced symbols only if explictly requested */ + if (VerboseMap || E->ImpCount > 0 || SYM_IS_CONDES (E->Type)) { + fprintf (F, + "%-25s %06lX %c%c%c%c ", + GetString (E->Name), + GetExportVal (E), + E->ImpCount? 'R' : ' ', + SYM_IS_LABEL (E->Type)? 'L' : 'E', + GetAddrSizeCode ((unsigned char) E->AddrSize), + SYM_IS_CONDES (E->Type)? 'I' : ' '); + if (++Count == 2) { + Count = 0; + fprintf (F, "\n"); + } + } + } + fprintf (F, "\n"); + xfree (ExpValXlat); +} + + + void PrintImportMap (FILE* F) /* Print an import map to the given file */ { @@ -915,8 +970,8 @@ void PrintImportMap (FILE* F) const Export* Exp = ExpPool [I]; /* Print the symbol only if there are imports, or if a verbose map - * file is requested. - */ + ** file is requested. + */ if (VerboseMap || Exp->ImpCount > 0) { /* Print the export */ @@ -930,9 +985,9 @@ void PrintImportMap (FILE* F) while (Imp) { /* Print the import. Beware: The import might be linker - * generated, in which case there is no object file and - * sometimes no line information. - */ + ** generated, in which case there is no object file and + ** sometimes no line information. + */ const LineInfo* LI = GetImportPos (Imp); if (LI) { fprintf (F, @@ -1003,7 +1058,3 @@ void CircularRefError (const Export* E) GetSourceName (LI), GetSourceLine (LI)); } - - - - diff --git a/src/ld65/exports.h b/src/ld65/exports.h index 0d5337785..d69e6d7ad 100644 --- a/src/ld65/exports.h +++ b/src/ld65/exports.h @@ -96,11 +96,11 @@ struct Export { /* Prototype of a function that is called if an undefined symbol is found. It - * may check if the symbol is an external symbol (for binary formats that - * support externals) and will return zero if the symbol could not be - * resolved, or a value != zero if the symbol could be resolved. The - * CheckExports routine will print out the missing symbol in the first case. - */ +** may check if the symbol is an external symbol (for binary formats that +** support externals) and will return zero if the symbol could not be +** resolved, or a value != zero if the symbol could be resolved. The +** CheckExports routine will print out the missing symbol in the first case. +*/ typedef int (*ExpCheckFunc) (unsigned Name, void* Data); @@ -113,9 +113,9 @@ typedef int (*ExpCheckFunc) (unsigned Name, void* Data); void FreeImport (Import* I); /* Free an import. NOTE: This won't remove the import from the exports table, - * so it may only be called for unused imports (imports from modules that - * aren't referenced). - */ +** so it may only be called for unused imports (imports from modules that +** aren't referenced). +*/ Import* ReadImport (FILE* F, ObjData* Obj); /* Read an import from a file and insert it into the table */ @@ -131,9 +131,9 @@ const LineInfo* GetImportPos (const Import* I); void FreeExport (Export* E); /* Free an export. NOTE: This won't remove the export from the exports table, - * so it may only be called for unused exports (exports from modules that - * aren't referenced). - */ +** so it may only be called for unused exports (exports from modules that +** aren't referenced). +*/ Export* ReadExport (FILE* F, ObjData* Obj); /* Read an export from a file */ @@ -161,8 +161,8 @@ Export* CreateSectionExport (unsigned Name, Section* S, unsigned long Offs); Export* FindExport (unsigned Name); /* Check for an identifier in the list. Return 0 if not found, otherwise - * return a pointer to the export. - */ +** return a pointer to the export. +*/ int IsUnresolved (unsigned Name); /* Check if this symbol is an unresolved export */ @@ -178,16 +178,19 @@ long GetExportVal (const Export* E); void CheckExports (void); /* Setup the list of all exports and check for export/import symbol type - * mismatches. - */ +** mismatches. +*/ void CheckUnresolvedImports (ExpCheckFunc F, void* Data); /* Check if there are any unresolved imports. On unresolved imports, F is - * called (see the comments on ExpCheckFunc in the data section). - */ +** called (see the comments on ExpCheckFunc in the data section). +*/ -void PrintExportMap (FILE* F); -/* Print an export map to the given file */ +void PrintExportMapByName (FILE* F); +/* Print an export map to the given file (sorted by symbol name) */ + +void PrintExportMapByValue (FILE* F); +/* Print an export map to the given file (sorted by export value) */ void PrintImportMap (FILE* F); /* Print an import map to the given file */ @@ -212,7 +215,3 @@ void CircularRefError (const Export* E); /* End of exports.h */ #endif - - - - diff --git a/src/ld65/expr.c b/src/ld65/expr.c index c5cfe9abd..efdff899e 100644 --- a/src/ld65/expr.c +++ b/src/ld65/expr.c @@ -93,8 +93,8 @@ void FreeExpr (ExprNode* Root) int IsConstExpr (ExprNode* Root) /* Return true if the given expression is a constant expression, that is, one - * with no references to external symbols. - */ +** with no references to external symbols. +*/ { int Const; Export* E; @@ -111,9 +111,9 @@ int IsConstExpr (ExprNode* Root) /* Get the referenced export */ E = GetExprExport (Root); /* If this export has a mark set, we've already encountered it. - * This means that the export is used to define it's own value, - * which in turn means, that we have a circular reference. - */ + ** This means that the export is used to define it's own value, + ** which in turn means, that we have a circular reference. + */ if (ExportHasMark (E)) { CircularRefError (E); Const = 0; @@ -126,8 +126,8 @@ int IsConstExpr (ExprNode* Root) case EXPR_SECTION: /* A section expression is const if the segment it is in is - * not relocatable and already placed. - */ + ** not relocatable and already placed. + */ S = GetExprSection (Root); M = S->Seg->MemArea; return M != 0 && (M->Flags & MF_PLACED) != 0 && !M->Relocatable; @@ -160,9 +160,9 @@ int IsConstExpr (ExprNode* Root) GetSegExprVal (Root->Left, &D); /* The expression is const if the expression contains exactly - * one segment that is assigned to a memory area which has a - * bank attribute that is constant. - */ + ** one segment that is assigned to a memory area which has a + ** bank attribute that is constant. + */ return (D.TooComplex == 0 && D.Seg != 0 && D.Seg->MemArea != 0 && @@ -224,9 +224,9 @@ Import* GetExprImport (ExprNode* Expr) PRECONDITION (Expr->Op == EXPR_SYMBOL); /* If we have an object file, get the import from it, otherwise - * (internally generated expressions), get the import from the - * import pointer. - */ + ** (internally generated expressions), get the import from the + ** import pointer. + */ if (Expr->Obj) { /* Return the Import */ return GetObjImport (Expr->Obj, Expr->V.ImpNum); @@ -256,9 +256,9 @@ Section* GetExprSection (ExprNode* Expr) PRECONDITION (Expr->Op == EXPR_SECTION); /* If we have an object file, get the section from it, otherwise - * (internally generated expressions), get the section from the - * section pointer. - */ + ** (internally generated expressions), get the section from the + ** section pointer. + */ if (Expr->Obj) { /* Return the export */ return CollAt (&Expr->Obj->Sections, Expr->V.SecNum); @@ -288,9 +288,9 @@ long GetExprVal (ExprNode* Expr) /* Get the referenced export */ E = GetExprExport (Expr); /* If this export has a mark set, we've already encountered it. - * This means that the export is used to define it's own value, - * which in turn means, that we have a circular reference. - */ + ** This means that the export is used to define it's own value, + ** which in turn means, that we have a circular reference. + */ if (ExportHasMark (E)) { CircularRefError (E); Val = 0; @@ -453,10 +453,10 @@ long GetExprVal (ExprNode* Expr) static void GetSegExprValInternal (ExprNode* Expr, SegExprDesc* D, int Sign) /* Check if the given expression consists of a segment reference and only - * constant values, additions and subtractions. If anything else is found, - * set D->TooComplex to true. - * Internal, recursive routine. - */ +** constant values, additions and subtractions. If anything else is found, +** set D->TooComplex to true. +** Internal, recursive routine. +*/ { Export* E; @@ -470,9 +470,9 @@ static void GetSegExprValInternal (ExprNode* Expr, SegExprDesc* D, int Sign) /* Get the referenced export */ E = GetExprExport (Expr); /* If this export has a mark set, we've already encountered it. - * This means that the export is used to define it's own value, - * which in turn means, that we have a circular reference. - */ + ** This means that the export is used to define it's own value, + ** which in turn means, that we have a circular reference. + */ if (ExportHasMark (E)) { CircularRefError (E); } else { @@ -530,9 +530,9 @@ static void GetSegExprValInternal (ExprNode* Expr, SegExprDesc* D, int Sign) void GetSegExprVal (ExprNode* Expr, SegExprDesc* D) /* Check if the given expression consists of a segment reference and only - * constant values, additions and subtractions. If anything else is found, - * set D->TooComplex to true. The function will initialize D. - */ +** constant values, additions and subtractions. If anything else is found, +** set D->TooComplex to true. The function will initialize D. +*/ { /* Initialize the given structure */ D->Val = 0; @@ -714,6 +714,3 @@ int EqualExpr (ExprNode* E1, ExprNode* E2) } } - - - diff --git a/src/ld65/expr.h b/src/ld65/expr.h index bc3e8b216..8b5879a27 100644 --- a/src/ld65/expr.h +++ b/src/ld65/expr.h @@ -78,8 +78,8 @@ void FreeExpr (ExprNode* Root); int IsConstExpr (ExprNode* Root); /* Return true if the given expression is a constant expression, that is, one - * with no references to external symbols. - */ +** with no references to external symbols. +*/ Import* GetExprImport (ExprNode* Expr); /* Get the import data structure for a symbol expression node */ @@ -95,9 +95,9 @@ long GetExprVal (ExprNode* Expr); void GetSegExprVal (ExprNode* Expr, SegExprDesc* D); /* Check if the given expression consists of a segment reference and only - * constant values, additions and subtractions. If anything else is found, - * set D->TooComplex to true. The function will initialize D. - */ +** constant values, additions and subtractions. If anything else is found, +** set D->TooComplex to true. The function will initialize D. +*/ ExprNode* LiteralExpr (long Val, ObjData* O); /* Return an expression tree that encodes the given literal value */ @@ -122,6 +122,3 @@ int EqualExpr (ExprNode* E1, ExprNode* E2); /* End of expr.h */ #endif - - - diff --git a/src/ld65/extsyms.c b/src/ld65/extsyms.c index b19c23100..b250125a7 100644 --- a/src/ld65/extsyms.c +++ b/src/ld65/extsyms.c @@ -124,8 +124,8 @@ ExtSym* NewExtSym (ExtSymTab* Tab, unsigned Name) static void FreeExtSym (ExtSym* E) /* Free an external symbol structure. Will not unlink the entry, so internal - * use only. - */ +** use only. +*/ { xfree (E); } @@ -172,8 +172,8 @@ void FreeExtSymTab (ExtSymTab* Tab) ExtSym* GetExtSym (const ExtSymTab* Tab, unsigned Name) /* Return the entry for the external symbol with the given name. Return NULL - * if there is no such symbol. - */ +** if there is no such symbol. +*/ { /* Hash the name */ unsigned Hash = (Name & HASHTAB_MASK); @@ -204,8 +204,8 @@ unsigned ExtSymCount (const ExtSymTab* Tab) const ExtSym* ExtSymList (const ExtSymTab* Tab) /* Return the start of the symbol list sorted by symbol number. Call - * ExtSymNext for the next symbol. - */ +** ExtSymNext for the next symbol. +*/ { return Tab->Root; } @@ -233,7 +233,3 @@ const ExtSym* ExtSymNext (const ExtSym* E) { return E->List; } - - - - diff --git a/src/ld65/extsyms.h b/src/ld65/extsyms.h index c3c82b2e2..45f094177 100644 --- a/src/ld65/extsyms.h +++ b/src/ld65/extsyms.h @@ -69,16 +69,16 @@ void FreeExtSymTab (ExtSymTab* Tab); ExtSym* GetExtSym (const ExtSymTab* Tab, unsigned Name); /* Return the entry for the external symbol with the given name. Return NULL - * if there is no such symbol. - */ +** if there is no such symbol. +*/ unsigned ExtSymCount (const ExtSymTab* Tab); /* Return the number of symbols in the table */ const ExtSym* ExtSymList (const ExtSymTab* Tab); /* Return the start of the symbol list sorted by symbol number. Call - * ExtSymNext for the next symbol. - */ +** ExtSymNext for the next symbol. +*/ unsigned ExtSymNum (const ExtSym* E); /* Return the number of an external symbol */ @@ -94,7 +94,3 @@ const ExtSym* ExtSymNext (const ExtSym* E); /* End of extsyms.h */ #endif - - - - diff --git a/src/ld65/fileinfo.c b/src/ld65/fileinfo.c index cc0238166..5964e1ea6 100644 --- a/src/ld65/fileinfo.c +++ b/src/ld65/fileinfo.c @@ -64,10 +64,10 @@ static Collection FileInfos = STATIC_COLLECTION_INITIALIZER; static int FindFileInfo (unsigned Name, unsigned* Index) /* Find the FileInfo for a given file name. The function returns true if the - * name was found. In this case, Index contains the index of the first item - * that matches. If the item wasn't found, the function returns false and - * Index contains the insert position for FileName. - */ +** name was found. In this case, Index contains the index of the first item +** that matches. If the item wasn't found, the function returns false and +** Index contains the insert position for FileName. +*/ { /* Do a binary search */ int Lo = 0; @@ -87,8 +87,8 @@ static int FindFileInfo (unsigned Name, unsigned* Index) } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've - * the first item that has a match. - */ + ** the first item that has a match. + */ if (CurItem->Name == Name) { Found = 1; } @@ -148,10 +148,10 @@ FileInfo* ReadFileInfo (FILE* F, ObjData* O) if (FindFileInfo (Name, &Index)) { /* We have at least one such entry. Try all of them and, if size and - * modification time matches, return the first match. When the loop - * is terminated without finding an entry, Index points one behind - * the last entry with the name, which is the perfect insert position. - */ + ** modification time matches, return the first match. When the loop + ** is terminated without finding an entry, Index points one behind + ** the last entry with the name, which is the perfect insert position. + */ FI = CollAt (&FileInfos, Index); while (1) { @@ -183,8 +183,8 @@ FileInfo* ReadFileInfo (FILE* F, ObjData* O) CollAppend (&FI->Modules, O); /* Insert the file info in our global list. Index points to the insert - * position. - */ + ** position. + */ CollInsert (&FileInfos, FI, Index); /* Return the new struct */ @@ -261,6 +261,3 @@ void PrintDbgFileInfo (FILE* F) fputc ('\n', F); } } - - - diff --git a/src/ld65/fileinfo.h b/src/ld65/fileinfo.h index 038e2404c..978ef4ce2 100644 --- a/src/ld65/fileinfo.h +++ b/src/ld65/fileinfo.h @@ -87,7 +87,5 @@ void PrintDbgFileInfo (FILE* F); /* End of fileinfo.h */ + #endif - - - diff --git a/src/ld65/fileio.c b/src/ld65/fileio.c index 9edb911ab..f6a2719a6 100644 --- a/src/ld65/fileio.c +++ b/src/ld65/fileio.c @@ -147,10 +147,10 @@ void WriteVar (FILE* F, unsigned long V) /* Write a variable sized value to the file in special encoding */ { /* We will write the value to the file in 7 bit chunks. If the 8th bit - * is clear, we're done, if it is set, another chunk follows. This will - * allow us to encode smaller values with less bytes, at the expense of - * needing 5 bytes if a 32 bit value is written to file. - */ + ** is clear, we're done, if it is set, another chunk follows. This will + ** allow us to encode smaller values with less bytes, at the expense of + ** needing 5 bytes if a 32 bit value is written to file. + */ do { unsigned char C = (V & 0x7F); V >>= 7; @@ -258,8 +258,8 @@ unsigned long ReadVar (FILE* F) /* Read a variable size value from the file */ { /* The value was written to the file in 7 bit chunks LSB first. If there - * are more bytes, bit 8 is set, otherwise it is clear. - */ + ** are more bytes, bit 8 is set, otherwise it is clear. + */ unsigned char C; unsigned long V = 0; unsigned Shift = 0; @@ -280,8 +280,8 @@ unsigned long ReadVar (FILE* F) unsigned ReadStr (FILE* F) /* Read a string from the file, place it into the global string pool, and - * return its string id. - */ +** return its string id. +*/ { unsigned Id; StrBuf Buf = STATIC_STRBUF_INITIALIZER; @@ -332,7 +332,3 @@ void* ReadData (FILE* F, void* Data, unsigned Size) } return Data; } - - - - diff --git a/src/ld65/fileio.h b/src/ld65/fileio.h index f78f4a11b..72e4a6fcb 100644 --- a/src/ld65/fileio.h +++ b/src/ld65/fileio.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -104,8 +104,8 @@ unsigned long ReadVar (FILE* F); unsigned ReadStr (FILE* F); /* Read a string from the file, place it into the global string pool, and - * return its string id. - */ +** return its string id. +*/ FilePos* ReadFilePos (FILE* F, FilePos* Pos); /* Read a file position from the file */ @@ -118,6 +118,3 @@ void* ReadData (FILE* F, void* Data, unsigned Size); /* End of fileio.h */ #endif - - - diff --git a/src/ld65/filepath.c b/src/ld65/filepath.c index 42357bb47..17cd451de 100644 --- a/src/ld65/filepath.c +++ b/src/ld65/filepath.c @@ -44,13 +44,13 @@ -SearchPath* LibSearchPath; /* Library path */ -SearchPath* ObjSearchPath; /* Object file path */ -SearchPath* CfgSearchPath; /* Config file path */ +SearchPaths* LibSearchPath; /* Library path */ +SearchPaths* ObjSearchPath; /* Object file path */ +SearchPaths* CfgSearchPath; /* Config file path */ -SearchPath* LibDefaultPath; /* Default Library path */ -SearchPath* ObjDefaultPath; /* Default Object file path */ -SearchPath* CfgDefaultPath; /* Default Config file path */ +SearchPaths* LibDefaultPath; /* Default Library path */ +SearchPaths* ObjDefaultPath; /* Default Object file path */ +SearchPaths* CfgDefaultPath; /* Default Config file path */ @@ -88,13 +88,13 @@ void InitSearchPaths (void) AddSubSearchPathFromEnv (CfgDefaultPath, "CC65_HOME", "cfg"); /* Add some compiled-in search paths if defined at compile time. */ -#if defined(LD65_LIB) +#if defined(LD65_LIB) && !defined(_WIN32) AddSearchPath (LibDefaultPath, STRINGIZE (LD65_LIB)); #endif -#if defined(LD65_OBJ) +#if defined(LD65_OBJ) && !defined(_WIN32) AddSearchPath (ObjDefaultPath, STRINGIZE (LD65_OBJ)); #endif -#if defined(LD65_CFG) +#if defined(LD65_CFG) && !defined(_WIN32) AddSearchPath (CfgDefaultPath, STRINGIZE (LD65_CFG)); #endif @@ -103,6 +103,3 @@ void InitSearchPaths (void) AddSubSearchPathFromWinBin (ObjDefaultPath, "lib"); AddSubSearchPathFromWinBin (CfgDefaultPath, "cfg"); } - - - diff --git a/src/ld65/filepath.h b/src/ld65/filepath.h index 97e77068b..a2fcd4bb3 100644 --- a/src/ld65/filepath.h +++ b/src/ld65/filepath.h @@ -49,13 +49,13 @@ -extern SearchPath* LibSearchPath; /* Library path */ -extern SearchPath* ObjSearchPath; /* Object file path */ -extern SearchPath* CfgSearchPath; /* Config file path */ +extern SearchPaths* LibSearchPath; /* Library path */ +extern SearchPaths* ObjSearchPath; /* Object file path */ +extern SearchPaths* CfgSearchPath; /* Config file path */ -extern SearchPath* LibDefaultPath; /* Default Library path */ -extern SearchPath* ObjDefaultPath; /* Default Object file path */ -extern SearchPath* CfgDefaultPath; /* Default Config file path */ +extern SearchPaths* LibDefaultPath; /* Default Library path */ +extern SearchPaths* ObjDefaultPath; /* Default Object file path */ +extern SearchPaths* CfgDefaultPath; /* Default Config file path */ @@ -71,7 +71,5 @@ void InitSearchPaths (void); /* End of filepath.h */ + #endif - - - diff --git a/src/ld65/fragment.c b/src/ld65/fragment.c index 70ca3d037..5efac371c 100644 --- a/src/ld65/fragment.c +++ b/src/ld65/fragment.c @@ -57,8 +57,8 @@ Fragment* NewFragment (unsigned char Type, unsigned Size, Section* S) Fragment* F; /* Calculate the size of the memory block. LitBuf is only needed if the - * fragment contains literal data. - */ + ** fragment contains literal data. + */ unsigned FragSize = sizeof (Fragment) - 1; if (Type == FRAG_LITERAL) { FragSize += Size; @@ -94,6 +94,3 @@ Fragment* NewFragment (unsigned char Type, unsigned Size, Section* S) /* Return the new fragment */ return F; } - - - diff --git a/src/ld65/fragment.h b/src/ld65/fragment.h index 98f90f568..7d6dd9201 100644 --- a/src/ld65/fragment.h +++ b/src/ld65/fragment.h @@ -112,7 +112,3 @@ INLINE unsigned GetFragmentSourceLine (const Fragment* F) /* End of fragment.h */ #endif - - - - diff --git a/src/ld65/global.c b/src/ld65/global.c index 985a5914f..dc0c8d521 100644 --- a/src/ld65/global.c +++ b/src/ld65/global.c @@ -56,6 +56,3 @@ unsigned char VerboseMap = 0; /* Verbose map file */ const char* MapFileName = 0; /* Name of the map file */ const char* LabelFileName = 0; /* Name of the label file */ const char* DbgFileName = 0; /* Name of the debug file */ - - - diff --git a/src/ld65/global.h b/src/ld65/global.h index 957d34041..4b873f027 100644 --- a/src/ld65/global.h +++ b/src/ld65/global.h @@ -62,6 +62,3 @@ extern const char* DbgFileName; /* Name of the debug file */ /* End of global.h */ #endif - - - diff --git a/src/ld65/library.c b/src/ld65/library.c index c81ee6f91..0dadcfa67 100644 --- a/src/ld65/library.c +++ b/src/ld65/library.c @@ -232,8 +232,8 @@ static ObjData* ReadIndexEntry (Library* L) static void ReadBasicData (Library* L, ObjData* O) /* Read basic data for an object file that is necessary to resolve external - * references. - */ +** references. +*/ { /* Seek to the start of the object file and read the header */ LibSeek (L, O->Start); @@ -275,8 +275,8 @@ static void LibReadIndex (Library* L) } /* Walk over the index and read basic data for all object files in the - * library. - */ + ** library. + */ for (I = 0; I < CollCount (&L->Modules); ++I) { ReadBasicData (L, CollAtUnchecked (&L->Modules, I)); } @@ -292,8 +292,8 @@ static void LibReadIndex (Library* L) static void LibCheckExports (ObjData* O) /* Check if the exports from this file can satisfy any import requests. If so, - * insert the imports and exports from this file and mark the file as added. - */ +** insert the imports and exports from this file and mark the file as added. +*/ { unsigned I; @@ -336,8 +336,8 @@ static void LibResolve (void) unsigned Additions; /* Walk repeatedly over all open libraries until there's nothing more - * to add. - */ + ** to add. + */ do { Additions = 0; @@ -349,9 +349,9 @@ static void LibResolve (void) Library* L = CollAt (&OpenLibs, I); /* Walk through all modules in this library and check for each - * module if there are unresolved externals in existing modules - * that may be resolved by adding the module. - */ + ** module if there are unresolved externals in existing modules + ** that may be resolved by adding the module. + */ for (J = 0; J < CollCount (&L->Modules); ++J) { /* Get the next module */ @@ -371,17 +371,17 @@ static void LibResolve (void) } while (Additions > 0); /* We do know now which modules must be added, so we can load the data - * for these modues into memory. Since we're walking over all modules - * anyway, we will also remove data for unneeded modules. - */ + ** for these modues into memory. Since we're walking over all modules + ** anyway, we will also remove data for unneeded modules. + */ for (I = 0; I < CollCount (&OpenLibs); ++I) { /* Get the next library */ Library* L = CollAt (&OpenLibs, I); /* Walk over all modules in this library and add the files list and - * sections for all referenced modules. - */ + ** sections for all referenced modules. + */ J = 0; while (J < CollCount (&L->Modules)) { @@ -398,22 +398,22 @@ static void LibResolve (void) ObjReadAssertions (L->F, O->Start + O->Header.AssertOffs, O); /* Seek to the start of the segment list and read the segments. - * This must be late, since the data here may reference other - * stuff. - */ + ** This must be late, since the data here may reference other + ** stuff. + */ ObjReadSections (L->F, O->Start + O->Header.SegOffs, O); /* Read the scope table from the object file. Scopes reference - * segments, so we must read them after the sections. - */ + ** segments, so we must read them after the sections. + */ ObjReadScopes (L->F, O->Start + O->Header.ScopeOffs, O); /* Read the spans */ ObjReadSpans (L->F, O->Start + O->Header.SpanOffs, O); /* All references to strings are now resolved, so we can delete - * the module string pool. - */ + ** the module string pool. + */ FreeObjStrings (O); /* Insert the object into the list of all used object files */ @@ -432,8 +432,8 @@ static void LibResolve (void) } /* If we have referenced modules in this library, assign it an id - * (which is the index in the library collection) and keep it. - */ + ** (which is the index in the library collection) and keep it. + */ if (CollCount (&L->Modules) > 0) { CloseLibrary (L); L->Id = CollCount (&LibraryList); @@ -453,16 +453,16 @@ static void LibResolve (void) void LibAdd (FILE* F, const char* Name) /* Add files from the library to the list if there are references that could - * be satisfied. - */ +** be satisfied. +*/ { /* Add the library to the list of open libraries */ LibOpen (F, Name); /* If there is no library group open, just resolve all open symbols and - * close the library. Otherwise we will do nothing because resolving will - * be done when the group is closed. - */ + ** close the library. Otherwise we will do nothing because resolving will + ** be done when the group is closed. + */ if (!Grouping) { LibResolve (); } @@ -472,9 +472,9 @@ void LibAdd (FILE* F, const char* Name) void LibStartGroup (void) /* Start a library group. Objects within a library group may reference each - * other, and libraries are searched repeatedly until all references are - * satisfied. - */ +** other, and libraries are searched repeatedly until all references are +** satisfied. +*/ { /* We cannot already have a group open */ if (Grouping) { @@ -489,9 +489,9 @@ void LibStartGroup (void) void LibEndGroup (void) /* End a library group and resolve all open references. Objects within a - * library group may reference each other, and libraries are searched - * repeatedly until all references are satisfied. - */ +** library group may reference each other, and libraries are searched +** repeatedly until all references are satisfied. +*/ { /* We must have a library group open */ if (!Grouping) { @@ -553,7 +553,3 @@ void PrintDbgLibraries (FILE* F) fprintf (F, "lib\tid=%u,name=\"%s\"\n", L->Id, GetString (L->Name)); } } - - - - diff --git a/src/ld65/library.h b/src/ld65/library.h index 19648630c..abf75675a 100644 --- a/src/ld65/library.h +++ b/src/ld65/library.h @@ -57,20 +57,20 @@ struct Library; void LibAdd (FILE* F, const char* Name); /* Add files from the library to the list if there are references that could - * be satisfied. - */ +** be satisfied. +*/ void LibStartGroup (void); /* Start a library group. Objects within a library group may reference each - * other, and libraries are searched repeatedly until all references are - * satisfied. - */ +** other, and libraries are searched repeatedly until all references are +** satisfied. +*/ void LibEndGroup (void); /* End a library group and resolve all open references. Objects within a - * library group may reference each other, and libraries are searched - * repeatedly until all references are satisfied. - */ +** library group may reference each other, and libraries are searched +** repeatedly until all references are satisfied. +*/ void LibCheckGroup (void); /* Check if there are open library groups */ @@ -92,6 +92,3 @@ void PrintDbgLibraries (FILE* F); /* End of library.h */ #endif - - - diff --git a/src/ld65/lineinfo.c b/src/ld65/lineinfo.c index cc54055c3..25eca4fcd 100644 --- a/src/ld65/lineinfo.c +++ b/src/ld65/lineinfo.c @@ -143,8 +143,8 @@ LineInfo* ReadLineInfo (FILE* F, ObjData* O) void ReadLineInfoList (FILE* F, ObjData* O, Collection* LineInfos) /* Read a list of line infos stored as a list of indices in the object file, - * make real line infos from them and place them into the passed collection. - */ +** make real line infos from them and place them into the passed collection. +*/ { /* Read the number of line info indices that follow */ unsigned LineInfoCount = ReadVar (F); @@ -159,8 +159,8 @@ void ReadLineInfoList (FILE* F, ObjData* O, Collection* LineInfos) unsigned LineInfoIndex = ReadVar (F); /* The line info index was written by the assembler and must - * therefore be part of the line infos read from the object file. - */ + ** therefore be part of the line infos read from the object file. + */ if (LineInfoIndex >= CollCount (&O->LineInfos)) { Internal ("Invalid line info index %u in module `%s' - max is %u", LineInfoIndex, @@ -177,8 +177,8 @@ void ReadLineInfoList (FILE* F, ObjData* O, Collection* LineInfos) const LineInfo* GetAsmLineInfo (const Collection* LineInfos) /* Find a line info of type LI_TYPE_ASM and count zero in the given collection - * and return it. Return NULL if no such line info was found. - */ +** and return it. Return NULL if no such line info was found. +*/ { unsigned I; @@ -284,6 +284,3 @@ void PrintDbgLineInfo (FILE* F) } } } - - - diff --git a/src/ld65/lineinfo.h b/src/ld65/lineinfo.h index 5af9e5788..84be249bd 100644 --- a/src/ld65/lineinfo.h +++ b/src/ld65/lineinfo.h @@ -68,9 +68,9 @@ struct Segment; /* Structure holding line information. The Pos.Name field is always the - * global string id of the file name. If the line info was read from the - * object file, the File pointer is valid, otherwise it is NULL. - */ +** global string id of the file name. If the line info was read from the +** object file, the File pointer is valid, otherwise it is NULL. +*/ typedef struct LineInfo LineInfo; struct LineInfo { unsigned Id; /* Line info id */ @@ -102,13 +102,13 @@ LineInfo* DupLineInfo (const LineInfo* LI); void ReadLineInfoList (FILE* F, struct ObjData* O, Collection* LineInfos); /* Read a list of line infos stored as a list of indices in the object file, - * make real line infos from them and place them into the passed collection. - */ +** make real line infos from them and place them into the passed collection. +*/ const LineInfo* GetAsmLineInfo (const Collection* LineInfos); /* Find a line info of type LI_TYPE_ASM and count zero in the given collection - * and return it. Return NULL if no such line info was found. - */ +** and return it. Return NULL if no such line info was found. +*/ #if defined(HAVE_INLINE) INLINE const FilePos* GetSourcePos (const LineInfo* LI) @@ -186,7 +186,5 @@ void PrintDbgLineInfo (FILE* F); /* End of lineinfo.h */ + #endif - - - diff --git a/src/ld65/main.c b/src/ld65/main.c index 84af34d54..5030b1dc3 100644 --- a/src/ld65/main.c +++ b/src/ld65/main.c @@ -80,6 +80,24 @@ static unsigned ObjFiles = 0; /* Count of object files linked */ static unsigned LibFiles = 0; /* Count of library files linked */ +/* struct InputFile.Type definitions */ +#define INPUT_FILES_FILE 0 /* Entry is a file (unknown type) */ +#define INPUT_FILES_FILE_OBJ 1 /* Entry is a object file */ +#define INPUT_FILES_FILE_LIB 2 /* Entry is a library file */ +#define INPUT_FILES_SGROUP 3 /* Entry is 'StartGroup' */ +#define INPUT_FILES_EGROUP 4 /* Entry is 'EndGroup' */ + +#define MAX_INPUTFILES 256 + +/* Array of inputs (libraries and object files) */ +static struct InputFile { + const char *FileName; + unsigned Type; +} *InputFiles; +static unsigned InputFilesCount = 0; +static const char *CmdlineCfgFile = NULL, + *CmdlineTarget = NULL; + /*****************************************************************************/ @@ -134,8 +152,8 @@ static void Usage (void) static unsigned long CvtNumber (const char* Arg, const char* Number) /* Convert a number from a string. Allow '$' and '0x' prefixes for hex - * numbers. - */ +** numbers. +*/ { unsigned long Val; int Converted; @@ -209,11 +227,11 @@ static void LinkFile (const char* Name, FILETYPE Type) Magic = Read32 (F); /* Check the magic for known file types. The handling is somewhat weird - * since we may have given a file with a ".lib" extension, which was - * searched and found in a directory for library files, but we now find - * out (by looking at the magic) that it's indeed an object file. We just - * ignore the problem and hope no one will notice... - */ + ** since we may have given a file with a ".lib" extension, which was + ** searched and found in a directory for library files, but we now find + ** out (by looking at the magic) that it's indeed an object file. We just + ** ignore the problem and hope no one will notice... + */ switch (Magic) { case OBJ_MAGIC: @@ -347,8 +365,8 @@ static void OptForceImport (const char* Opt attribute ((unused)), const char* Ar if (ColPos == 0) { /* Use default address size (which for now is always absolute - * addressing) - */ + ** addressing) + */ InsertImport (GenImport (GetStringId (Arg), ADDR_SIZE_ABS)); } else { @@ -390,7 +408,10 @@ static void OptHelp (const char* Opt attribute ((unused)), static void OptLib (const char* Opt attribute ((unused)), const char* Arg) /* Link a library */ { - LinkFile (Arg, FILETYPE_LIB); + InputFiles[InputFilesCount].Type = INPUT_FILES_FILE_LIB; + InputFiles[InputFilesCount].FileName = Arg; + if (++InputFilesCount >= MAX_INPUTFILES) + Error ("Too many input files"); } @@ -406,6 +427,9 @@ static void OptLibPath (const char* Opt attribute ((unused)), const char* Arg) static void OptMapFile (const char* Opt attribute ((unused)), const char* Arg) /* Give the name of the map file */ { + if (MapFileName) { + Error ("Cannot use -m twice"); + } MapFileName = Arg; } @@ -426,7 +450,10 @@ static void OptModuleId (const char* Opt, const char* Arg) static void OptObj (const char* Opt attribute ((unused)), const char* Arg) /* Link an object file */ { - LinkFile (Arg, FILETYPE_OBJ); + InputFiles[InputFilesCount].Type = INPUT_FILES_FILE_OBJ; + InputFiles[InputFilesCount].FileName = Arg; + if (++InputFilesCount >= MAX_INPUTFILES) + Error ("Too many input files"); } @@ -439,16 +466,14 @@ static void OptObjPath (const char* Opt attribute ((unused)), const char* Arg) -static void OptOutputName (const char* Opt, const char* Arg) +static void OptOutputName (const char* Opt attribute ((unused)), const char* Arg) /* Give the name of the output file */ { - /* If the name of the output file has been used in the config before - * (by using %O) we're actually changing it later, which - in most cases - - * gives unexpected results, so emit a warning in this case. - */ - if (OutputNameUsed) { - Warning ("Option `%s' should precede options `-t' or `-C'", Opt); + static int OutputNameSeen = 0; + if (OutputNameSeen) { + Error ("Cannot use -o twice"); } + OutputNameSeen = 1; OutputName = Arg; } @@ -457,6 +482,9 @@ static void OptOutputName (const char* Opt, const char* Arg) static void OptStartAddr (const char* Opt, const char* Arg) /* Set the default start address */ { + if (HaveStartAddr) { + Error ("Cannot use -S twice"); + } StartAddr = CvtNumber (Opt, Arg); HaveStartAddr = 1; } @@ -520,16 +548,61 @@ static void OptVersion (const char* Opt attribute ((unused)), -int main (int argc, char* argv []) -/* Assembler main program */ +static void CmdlOptStartGroup (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* Remember 'start group' occurrence in input files array */ +{ + InputFiles[InputFilesCount].Type = INPUT_FILES_SGROUP; + InputFiles[InputFilesCount].FileName = Arg; /* Unused */ + if (++InputFilesCount >= MAX_INPUTFILES) + Error ("Too many input files"); +} + + + +static void CmdlOptEndGroup (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* Remember 'end group' occurrence in input files array */ +{ + InputFiles[InputFilesCount].Type = INPUT_FILES_EGROUP; + InputFiles[InputFilesCount].FileName = Arg; /* Unused */ + if (++InputFilesCount >= MAX_INPUTFILES) + Error ("Too many input files"); +} + + + +static void CmdlOptConfig (const char* Opt attribute ((unused)), const char* Arg) +/* Set 'config file' command line parameter */ +{ + if (CmdlineCfgFile || CmdlineTarget) { + Error ("Cannot use -C/-t twice"); + } + CmdlineCfgFile = Arg; +} + + + +static void CmdlOptTarget (const char* Opt attribute ((unused)), const char* Arg) +/* Set 'target' command line parameter */ +{ + if (CmdlineCfgFile || CmdlineTarget) { + Error ("Cannot use -C/-t twice"); + } + CmdlineTarget = Arg; +} + + + +static void ParseCommandLine(void) { /* Program long options */ static const LongOpt OptTab[] = { { "--cfg-path", 1, OptCfgPath }, - { "--config", 1, OptConfig }, + { "--config", 1, CmdlOptConfig }, { "--dbgfile", 1, OptDbgFile }, { "--define", 1, OptDefine }, - { "--end-group", 0, OptEndGroup }, + { "--end-group", 0, CmdlOptEndGroup }, { "--force-import", 1, OptForceImport }, { "--help", 0, OptHelp }, { "--lib", 1, OptLib }, @@ -539,27 +612,18 @@ int main (int argc, char* argv []) { "--obj", 1, OptObj }, { "--obj-path", 1, OptObjPath }, { "--start-addr", 1, OptStartAddr }, - { "--start-group", 0, OptStartGroup }, - { "--target", 1, OptTarget }, + { "--start-group", 0, CmdlOptStartGroup }, + { "--target", 1, CmdlOptTarget }, { "--version", 0, OptVersion }, }; unsigned I; - unsigned MemoryAreaOverflows; + unsigned LabelFileGiven = 0; - /* Initialize the cmdline module */ - InitCmdLine (&argc, &argv, "ld65"); + /* Allocate memory for input file array */ + InputFiles = xmalloc (MAX_INPUTFILES * sizeof (struct InputFile)); - /* Initialize the input file search paths */ - InitSearchPaths (); - - /* Initialize the string pool */ - InitStrPool (); - - /* Initialize the type pool */ - InitTypePool (); - - /* Check the parameters */ + /* Defer setting of config/target and input files until all options are parsed */ I = 1; while (I < ArgCount) { @@ -577,11 +641,11 @@ int main (int argc, char* argv []) break; case '(': - OptStartGroup (Arg, 0); + CmdlOptStartGroup (Arg, 0); break; case ')': - OptEndGroup (Arg, 0); + CmdlOptEndGroup (Arg, 0); break; case 'h': @@ -594,14 +658,11 @@ int main (int argc, char* argv []) break; case 'o': - OptOutputName (Arg, GetArg (&I, 2)); + OptOutputName (NULL, GetArg (&I, 2)); break; case 't': - if (CfgAvail ()) { - Error ("Cannot use -C/-t twice"); - } - OptTarget (Arg, GetArg (&I, 2)); + CmdlOptTarget (Arg, GetArg (&I, 2)); break; case 'u': @@ -617,7 +678,7 @@ int main (int argc, char* argv []) break; case 'C': - OptConfig (Arg, GetArg (&I, 2)); + CmdlOptConfig (Arg, GetArg (&I, 2)); break; case 'D': @@ -626,9 +687,17 @@ int main (int argc, char* argv []) case 'L': switch (Arg [2]) { - /* ## The first one is obsolete and will go */ - case 'n': LabelFileName = GetArg (&I, 3); break; - default: OptLibPath (Arg, GetArg (&I, 2)); break; + case 'n': + /* ## This one is obsolete and will go */ + if (LabelFileGiven) { + Error ("Cannot use -Ln twice"); + } + LabelFileGiven = 1; + LabelFileName = GetArg (&I, 3); + break; + default: + OptLibPath (Arg, GetArg (&I, 2)); + break; } break; @@ -648,7 +717,10 @@ int main (int argc, char* argv []) } else { /* A filename */ - LinkFile (Arg, FILETYPE_UNKNOWN); + InputFiles[InputFilesCount].Type = INPUT_FILES_FILE; + InputFiles[InputFilesCount].FileName = Arg; + if (++InputFilesCount >= MAX_INPUTFILES) + Error ("Too many input files"); } @@ -656,6 +728,61 @@ int main (int argc, char* argv []) ++I; } + if (CmdlineTarget) { + OptTarget (NULL, CmdlineTarget); + } else if (CmdlineCfgFile) { + OptConfig (NULL, CmdlineCfgFile); + } + + /* Process input files */ + for (I = 0; I < InputFilesCount; ++I) { + switch (InputFiles[I].Type) { + case INPUT_FILES_FILE: + LinkFile (InputFiles[I].FileName, FILETYPE_UNKNOWN); + break; + case INPUT_FILES_FILE_LIB: + LinkFile (InputFiles[I].FileName, FILETYPE_LIB); + break; + case INPUT_FILES_FILE_OBJ: + LinkFile (InputFiles[I].FileName, FILETYPE_OBJ); + break; + case INPUT_FILES_SGROUP: + OptStartGroup (NULL, 0); + break; + case INPUT_FILES_EGROUP: + OptEndGroup (NULL, 0); + break; + default: + abort (); + } + } + + /* Free memory used for input file array */ + xfree (InputFiles); +} + + + +int main (int argc, char* argv []) +/* Linker main program */ +{ + unsigned MemoryAreaOverflows; + + /* Initialize the cmdline module */ + InitCmdLine (&argc, &argv, "ld65"); + + /* Initialize the input file search paths */ + InitSearchPaths (); + + /* Initialize the string pool */ + InitStrPool (); + + /* Initialize the type pool */ + InitTypePool (); + + /* Parse the command line */ + ParseCommandLine (); + /* Check if we had any object files */ if (ObjFiles == 0) { Error ("No object files to link"); @@ -673,9 +800,9 @@ int main (int argc, char* argv []) ConDesCreate (); /* Process data from the config file. Assign start addresses for the - * segments, define linker symbols. The function will return the number - * of memory area overflows (zero on success). - */ + ** segments, define linker symbols. The function will return the number + ** of memory area overflows (zero on success). + */ MemoryAreaOverflows = CfgProcess (); /* Check module assertions */ @@ -685,9 +812,9 @@ int main (int argc, char* argv []) CheckExports (); /* If we had a memory area overflow before, we cannot generate the output - * file. However, we will generate a short map file if requested, since - * this will help the user to rearrange segments and fix the overflow. - */ + ** file. However, we will generate a short map file if requested, since + ** this will help the user to rearrange segments and fix the overflow. + */ if (MemoryAreaOverflows) { if (MapFileName) { CreateMapFile (SHORT_MAPFILE); @@ -722,6 +849,3 @@ int main (int argc, char* argv []) /* Return an apropriate exit code */ return EXIT_SUCCESS; } - - - diff --git a/src/ld65/mapfile.c b/src/ld65/mapfile.c index fa8d98efc..0cf9b651b 100644 --- a/src/ld65/mapfile.c +++ b/src/ld65/mapfile.c @@ -59,8 +59,8 @@ void CreateMapFile (int ShortMap) /* Create a map file. If ShortMap is true, only the segment lists are - * generated, not the import/export lists. - */ +** generated, not the import/export lists. +*/ { unsigned I; @@ -90,8 +90,8 @@ void CreateMapFile (int ShortMap) for (J = 0; J < CollCount (&O->Sections); ++J) { const Section* S = CollConstAt (&O->Sections, J); /* Don't include zero sized sections if not explicitly - * requested - */ + ** requested + */ if (VerboseMap || S->Size > 0) { fprintf (F, " %-17s Offs=%06lX Size=%06lX " @@ -111,11 +111,17 @@ void CreateMapFile (int ShortMap) /* The remainder is not written for short map files */ if (!ShortMap) { - /* Write the exports list */ + /* Write the exports list by name */ fprintf (F, "\n\n" - "Exports list:\n" - "-------------\n"); - PrintExportMap (F); + "Exports list by name:\n" + "---------------------\n"); + PrintExportMapByName (F); + + /* Write the exports list by value */ + fprintf (F, "\n\n" + "Exports list by value:\n" + "----------------------\n"); + PrintExportMapByValue (F); /* Write the imports list */ fprintf (F, "\n\n" @@ -152,6 +158,3 @@ void CreateLabelFile (void) Error ("Error closing label file `%s': %s", LabelFileName, strerror (errno)); } } - - - diff --git a/src/ld65/mapfile.h b/src/ld65/mapfile.h index c2685e7aa..4a1d4d777 100644 --- a/src/ld65/mapfile.h +++ b/src/ld65/mapfile.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2005 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -60,8 +60,8 @@ enum { void CreateMapFile (int ShortMap); /* Create a map file. If ShortMap is true, only the segment lists are - * generated, not the import/export lists. - */ +** generated, not the import/export lists. +*/ void CreateLabelFile (void); /* Create a label file */ @@ -71,6 +71,3 @@ void CreateLabelFile (void); /* End of mapfile.h */ #endif - - - diff --git a/src/ld65/memarea.c b/src/ld65/memarea.c index 5b562b34a..d143b9790 100644 --- a/src/ld65/memarea.c +++ b/src/ld65/memarea.c @@ -73,7 +73,3 @@ MemoryArea* NewMemoryArea (const FilePos* Pos, unsigned Name) /* ...and return it */ return M; } - - - - diff --git a/src/ld65/memarea.h b/src/ld65/memarea.h index 4e051871c..b6972a985 100644 --- a/src/ld65/memarea.h +++ b/src/ld65/memarea.h @@ -99,8 +99,3 @@ MemoryArea* NewMemoryArea (const FilePos* Pos, unsigned Name); /* End of memarea.h */ #endif - - - - - diff --git a/src/ld65/o65.c b/src/ld65/o65.c index 7373c23c7..aceb5158a 100644 --- a/src/ld65/o65.c +++ b/src/ld65/o65.c @@ -94,8 +94,8 @@ #define MF_ALIGN_MASK 0x0003 /* Mask to extract alignment */ /* The four o65 segment types. Note: These values are identical to the values - * needed for the segmentID in the o65 spec. - */ +** needed for the segmentID in the o65 spec. +*/ #define O65SEG_UNDEF 0x00 #define O65SEG_ABS 0x01 #define O65SEG_TEXT 0x02 @@ -222,11 +222,11 @@ static unsigned O65SegType (const SegDesc* S) /* Map our own segment types into something o65 compatible */ { /* Check the segment type. Readonly segments are assign to the o65 - * text segment, writeable segments that contain data are assigned - * to data, bss and zp segments are handled respectively. - * Beware: Zeropage segments have the SF_BSS flag set, so be sure - * to check SF_ZP first. - */ + ** text segment, writeable segments that contain data are assigned + ** to data, bss and zp segments are handled respectively. + ** Beware: Zeropage segments have the SF_BSS flag set, so be sure + ** to check SF_ZP first. + */ if (S->Flags & SF_RO) { return O65SEG_TEXT; } else if (S->Flags & SF_ZP) { @@ -242,8 +242,8 @@ static unsigned O65SegType (const SegDesc* S) static void CvtMemoryToSegment (ExprDesc* ED) /* Convert a memory area into a segment by searching the list of run segments - * in this memory area and assigning the nearest one. - */ +** in this memory area and assigning the nearest one. +*/ { /* Get the memory area from the expression */ MemoryArea* M = ED->MemRef; @@ -291,8 +291,8 @@ static void CvtMemoryToSegment (ExprDesc* ED) static const SegDesc* FindSeg (SegDesc** const List, unsigned Count, const Segment* S) /* Search for a segment in the given list of segment descriptors and return - * the descriptor for a segment if we found it, and NULL if not. - */ +** the descriptor for a segment if we found it, and NULL if not. +*/ { unsigned I; @@ -341,9 +341,9 @@ static const SegDesc* O65FindSeg (const O65Desc* D, const Segment* S) static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign) /* Extract and evaluate all constant factors in an subtree that has only - * additions and subtractions. If anything other than additions and - * subtractions are found, D->TooComplex is set to true. - */ +** additions and subtractions. If anything other than additions and +** subtractions are found, D->TooComplex is set to true. +*/ { Export* E; @@ -357,9 +357,9 @@ static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign) /* Get the referenced Export */ E = GetExprExport (Expr); /* If this export has a mark set, we've already encountered it. - * This means that the export is used to define it's own value, - * which in turn means, that we have a circular reference. - */ + ** This means that the export is used to define it's own value, + ** which in turn means, that we have a circular reference. + */ if (ExportHasMark (E)) { CircularRefError (E); } else if (E->Expr == 0) { @@ -412,8 +412,8 @@ static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign) /* Remember the memory area reference */ D->MemRef = Expr->V.Mem; /* Add the start address of the memory area to the constant - * value - */ + ** value + */ D->Val += (Sign * D->MemRef->Start); } break; @@ -593,9 +593,9 @@ static void O65WriteHeader (O65Desc* D) static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, unsigned long Offs, void* Data) /* Called from SegWrite for an expression. Evaluate the expression, check the - * range and write the expression value to the file, update the relocation - * table. - */ +** range and write the expression value to the file, update the relocation +** table. +*/ { long Diff; unsigned RefCount; @@ -614,9 +614,9 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, } /* We have a relocatable expression that needs a relocation table entry. - * Calculate the number of bytes between this entry and the last one, and - * setup all necessary intermediate bytes in the relocation table. - */ + ** Calculate the number of bytes between this entry and the last one, and + ** setup all necessary intermediate bytes in the relocation table. + */ Offs += D->SegSize; /* Calulate full offset */ Diff = ((long) Offs) - D->LastOffs; while (Diff > 0xFE) { @@ -649,9 +649,9 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, } /* If we have a memory area reference, we need to convert it into a - * segment reference. If we cannot do that, we cannot handle the - * expression. - */ + ** segment reference. If we cannot do that, we cannot handle the + ** expression. + */ if (ED.MemRef) { CvtMemoryToSegment (&ED); if (ED.SegRef == 0) { @@ -682,8 +682,8 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, WriteVal (D->F, BinVal, Size); /* Determine the actual type of relocation entry needed from the - * information gathered about the expression. - */ + ** information gathered about the expression. + */ if (E->Op == EXPR_BYTE0) { RelocType = O65RELOC_LOW; } else if (E->Op == EXPR_BYTE1) { @@ -730,8 +730,8 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, Seg = O65FindSeg (D, ED.SegRef); if (Seg == 0) { /* For some reason, we didn't find this segment in the list of - * segments written to the o65 file. - */ + ** segments written to the o65 file. + */ return SEG_EXPR_INVALID; } RelocType |= O65SegType (Seg); @@ -844,8 +844,8 @@ static void O65WriteDataSeg (O65Desc* D) static void O65WriteBssSeg (O65Desc* D) /* "Write" the bss segments to the o65 output file. This will only update - * the relevant header fields. - */ +** the relevant header fields. +*/ { /* Initialize variables */ D->CurReloc = 0; @@ -861,8 +861,8 @@ static void O65WriteBssSeg (O65Desc* D) static void O65WriteZPSeg (O65Desc* D) /* "Write" the zeropage segments to the o65 output file. This will only update - * the relevant header fields. - */ +** the relevant header fields. +*/ { /* Initialize variables */ D->CurReloc = 0; @@ -935,9 +935,9 @@ static void O65WriteExports (O65Desc* D) const char* Name = GetString (NameIdx); /* Get the export for this symbol. We've checked before that this - * export does really exist, so if it is unresolved, or if we don't - * find it, there is an error in the linker code. - */ + ** export does really exist, so if it is unresolved, or if we don't + ** find it, there is an error in the linker code. + */ Export* E = FindExport (NameIdx); if (E == 0 || IsUnresolvedExport (E)) { Internal ("Unresolved export `%s' found in O65WriteExports", Name); @@ -950,8 +950,8 @@ static void O65WriteExports (O65Desc* D) O65ParseExpr (Expr, InitExprDesc (&ED, D), 1); /* We cannot handle expressions with imported symbols, or expressions - * with more than one segment reference here - */ + ** with more than one segment reference here + */ if (ED.ExtRef != 0 || (ED.SegRef != 0 && ED.SecRef != 0)) { ED.TooComplex = 1; } @@ -975,8 +975,8 @@ static void O65WriteExports (O65Desc* D) Seg = O65FindSeg (D, ED.SegRef); if (Seg == 0) { /* For some reason, we didn't find this segment in the list of - * segments written to the o65 file. - */ + ** segments written to the o65 file. + */ Error ("Segment for symbol `%s' is undefined", Name); } SegmentID = O65SegType (Seg); @@ -1203,8 +1203,8 @@ void O65SetExport (O65Desc* D, unsigned Ident) /* Set an exported identifier */ { /* Get the export for this symbol and check if it does exist and is - * a resolved symbol. - */ + ** a resolved symbol. + */ Export* E = FindExport (Ident); if (E == 0 || IsUnresolvedExport (E)) { Error ("Unresolved export: `%s'", GetString (Ident)); @@ -1320,18 +1320,26 @@ static void O65SetupHeader (O65Desc* D) SegDesc* FirstSeg = D->ZPSeg [0]; D->Header.ZPBase = FirstSeg->Seg->PC; } +} - /* If we have byte wise relocation and an alignment of 1, we can set - * the "simple addressing" bit in the header. - */ + + +static void O65UpdateHeader (O65Desc* D) +/* Update mode word, currently only the "simple" bit */ +{ + /* If we have byte wise relocation and an alignment of 1, and text + ** and data are adjacent, we can set the "simple addressing" bit + ** in the header. + */ if ((D->Header.Mode & MF_RELOC_MASK) == MF_RELOC_BYTE && - (D->Header.Mode & MF_ALIGN_MASK) == MF_ALIGN_1) { + (D->Header.Mode & MF_ALIGN_MASK) == MF_ALIGN_1 && + D->Header.TextBase + D->Header.TextSize == D->Header.DataBase && + D->Header.DataBase + D->Header.DataSize == D->Header.BssBase) { D->Header.Mode = (D->Header.Mode & ~MF_ADDR_MASK) | MF_ADDR_SIMPLE; } } - void O65WriteTarget (O65Desc* D, File* F) /* Write an o65 output file */ { @@ -1344,8 +1352,8 @@ void O65WriteTarget (O65Desc* D, File* F) D->Filename = GetString (F->Name); /* Check for unresolved symbols. The function O65Unresolved is called - * if we get an unresolved symbol. - */ + ** if we get an unresolved symbol. + */ D->Undef = 0; /* Reset the counter */ CheckUnresolvedImports (O65Unresolved, D); if (D->Undef > 0) { @@ -1369,8 +1377,8 @@ void O65WriteTarget (O65Desc* D, File* F) Print (stdout, 1, "Opened `%s'...\n", D->Filename); /* Define some more options: A timestamp, the linker version and the - * filename - */ + ** filename + */ T = time (0); strcpy (OptBuf, ctime (&T)); OptLen = strlen (OptBuf); @@ -1411,6 +1419,9 @@ void O65WriteTarget (O65Desc* D, File* F) /* Write the list of exports */ O65WriteExports (D); + /* Update header flags */ + O65UpdateHeader (D); + /* Seek back to the start and write the updated header */ fseek (D->F, 0, SEEK_SET); O65WriteHeader (D); @@ -1424,7 +1435,3 @@ void O65WriteTarget (O65Desc* D, File* F) D->F = 0; D->Filename = 0; } - - - - diff --git a/src/ld65/o65.h b/src/ld65/o65.h index 7de0832a8..2112537ff 100644 --- a/src/ld65/o65.h +++ b/src/ld65/o65.h @@ -124,6 +124,3 @@ void O65WriteTarget (O65Desc* D, File* F); /* End of o65.h */ #endif - - - diff --git a/src/ld65/objdata.c b/src/ld65/objdata.c index 1bdef6bd7..7e83f9107 100644 --- a/src/ld65/objdata.c +++ b/src/ld65/objdata.c @@ -104,9 +104,9 @@ ObjData* NewObjData (void) void FreeObjData (ObjData* O) /* Free an ObjData object. NOTE: This function works only for unused object - * data, that is, ObjData objects that aren't used because they aren't - * referenced. - */ +** data, that is, ObjData objects that aren't used because they aren't +** referenced. +*/ { unsigned I; @@ -145,8 +145,8 @@ void FreeObjData (ObjData* O) void FreeObjStrings (ObjData* O) /* Free the module string data. Used once the object file is loaded completely - * when all strings are converted to global strings. - */ +** when all strings are converted to global strings. +*/ { xfree (O->Strings); O->Strings = 0; @@ -164,8 +164,8 @@ void InsertObjData (ObjData* O) void InsertObjGlobals (ObjData* O) /* Insert imports and exports from the object file into the global import and - * export lists. - */ +** export lists. +*/ { unsigned I; @@ -194,8 +194,8 @@ unsigned MakeGlobalStringId (const ObjData* O, unsigned Index) const char* GetObjFileName (const ObjData* O) /* Get the name of the object file. Return "[linker generated]" if the object - * file is NULL. - */ +** file is NULL. +*/ { return O? GetString (O->Name) : "[linker generated]"; } @@ -309,7 +309,3 @@ void PrintDbgModules (FILE* F) } } - - - - diff --git a/src/ld65/objdata.h b/src/ld65/objdata.h index 4c477eee0..554fe0c6b 100644 --- a/src/ld65/objdata.h +++ b/src/ld65/objdata.h @@ -111,30 +111,30 @@ ObjData* NewObjData (void); void FreeObjData (ObjData* O); /* Free an ObjData object. NOTE: This function works only for unused object - * data, that is, ObjData objects that aren't used because they aren't - * referenced. - */ +** data, that is, ObjData objects that aren't used because they aren't +** referenced. +*/ void FreeObjStrings (ObjData* O); /* Free the module string data. Used once the object file is loaded completely - * when all strings are converted to global strings. - */ +** when all strings are converted to global strings. +*/ void InsertObjData (ObjData* O); /* Insert the ObjData object into the collection of used ObjData objects. */ void InsertObjGlobals (ObjData* O); /* Insert imports and exports from the object file into the global import and - * export lists. - */ +** export lists. +*/ unsigned MakeGlobalStringId (const ObjData* O, unsigned Index); /* Convert a local string id into a global one and return it. */ const char* GetObjFileName (const ObjData* O); /* Get the name of the object file. Return "[linker generated]" if the object - * file is NULL. - */ +** file is NULL. +*/ #if defined(HAVE_INLINE) INLINE int ObjHasFiles (const ObjData* O) @@ -175,8 +175,3 @@ void PrintDbgModules (FILE* F); /* End of objdata.h */ #endif - - - - - diff --git a/src/ld65/objfile.c b/src/ld65/objfile.c index 7b8dc4419..870ca5221 100644 --- a/src/ld65/objfile.c +++ b/src/ld65/objfile.c @@ -342,14 +342,14 @@ void ObjAdd (FILE* Obj, const char* Name) ObjReadAssertions (Obj, O->Header.AssertOffs, O); /* Read the segment list from the object file. This must be late, since - * the expressions stored in the code may reference segments or imported - * symbols. - */ + ** the expressions stored in the code may reference segments or imported + ** symbols. + */ ObjReadSections (Obj, O->Header.SegOffs, O); /* Read the scope table from the object file. Scopes reference segments, so - * we must read them after the sections. - */ + ** we must read them after the sections. + */ ObjReadScopes (Obj, O->Header.ScopeOffs, O); /* Read the spans from the object file */ @@ -368,11 +368,7 @@ void ObjAdd (FILE* Obj, const char* Name) InsertObjData (O); /* All references to strings are now resolved, so we can delete the module - * string pool. - */ + ** string pool. + */ FreeObjStrings (O); } - - - - diff --git a/src/ld65/objfile.h b/src/ld65/objfile.h index e982f90b5..4683638c7 100644 --- a/src/ld65/objfile.h +++ b/src/ld65/objfile.h @@ -92,6 +92,3 @@ void ObjAdd (FILE* F, const char* Name); /* End of objfile.h */ #endif - - - diff --git a/src/ld65/scanner.c b/src/ld65/scanner.c index b6d45354a..0f6ea58de 100644 --- a/src/ld65/scanner.c +++ b/src/ld65/scanner.c @@ -580,6 +580,3 @@ void CfgCloseInput (void) InputFile = 0; } } - - - diff --git a/src/ld65/scanner.h b/src/ld65/scanner.h index 9e27b6720..006ccfceb 100644 --- a/src/ld65/scanner.h +++ b/src/ld65/scanner.h @@ -166,12 +166,12 @@ extern StrBuf CfgSVal; extern unsigned long CfgIVal; /* Error location. PLEASE NOTE: I'm abusing the FilePos structure to some - * degree. It is used mostly to hold a file position, where the Name member - * is an index into the source file table of an object file. As used in config - * file processing, the Name member is a string pool index instead. This is - * distinguished by the object file pointer being NULL or not in the structs - * where this is relevant. - */ +** degree. It is used mostly to hold a file position, where the Name member +** is an index into the source file table of an object file. As used in config +** file processing, the Name member is a string pool index instead. This is +** distinguished by the object file pointer being NULL or not in the structs +** where this is relevant. +*/ extern FilePos CfgErrorPos; @@ -239,7 +239,5 @@ void CfgCloseInput (void); /* End of scanner.h */ + #endif - - - diff --git a/src/ld65/scopes.c b/src/ld65/scopes.c index b3acc0d7d..edf0d0da2 100644 --- a/src/ld65/scopes.c +++ b/src/ld65/scopes.c @@ -171,6 +171,3 @@ void PrintDbgScopes (FILE* F) } } } - - - diff --git a/src/ld65/scopes.h b/src/ld65/scopes.h index 142dc16bb..67d70148b 100644 --- a/src/ld65/scopes.h +++ b/src/ld65/scopes.h @@ -92,6 +92,3 @@ void PrintDbgScopes (FILE* F); /* End of scopes.h */ #endif - - - diff --git a/src/ld65/segments.c b/src/ld65/segments.c index e42a40d22..9c3972ac5 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -124,16 +124,16 @@ static Segment* NewSegment (unsigned Name, unsigned char AddrSize) Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName) /* Search for a segment and return an existing one. If the segment does not - * exist, create a new one and return that. ObjName is only used for the error - * message and may be NULL if the segment is linker generated. - */ +** exist, create a new one and return that. ObjName is only used for the error +** message and may be NULL if the segment is linker generated. +*/ { /* Try to locate the segment in the table */ Segment* S = SegFind (Name); /* If we don't have that segment already, allocate it using the type of - * the first section. - */ + ** the first section. + */ if (S == 0) { /* Create a new segment */ S = NewSegment (Name, AddrSize); @@ -308,8 +308,8 @@ Segment* SegFind (unsigned Name) int IsBSSType (Segment* S) /* Check if the given segment is a BSS style segment, that is, it does not - * contain non-zero data. - */ +** contain non-zero data. +*/ { /* Loop over all sections */ unsigned I; @@ -405,8 +405,8 @@ void SegDump (void) unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size) /* Write a supposedly constant expression to the target file. Do a range - * check and return one of the SEG_EXPR_xxx codes. - */ +** check and return one of the SEG_EXPR_xxx codes. +*/ { static const unsigned long U_Hi[4] = { 0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL @@ -449,8 +449,8 @@ unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size) void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) /* Write the data from the given segment to a file. For expressions, F is - * called (see description of SegWriteFunc above). - */ +** called (see description of SegWriteFunc above). +*/ { unsigned I; int Sign; @@ -472,9 +472,9 @@ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* Print (stdout, 2, " Section from \"%s\"\n", GetObjFileName (Sec->Obj)); /* If we have fill bytes, write them now. Beware: If this is the - * first section, the fill value is not considered part of the segment - * and therefore taken from the memory area. - */ + ** first section, the fill value is not considered part of the segment + ** and therefore taken from the memory area. + */ FillVal = (I == 0)? S->MemArea->FillVal : S->FillVal; Print (stdout, 2, " Filling 0x%lx bytes with 0x%02x\n", Sec->Fill, FillVal); @@ -646,8 +646,8 @@ void PrintDbgSegments (FILE* F) void CheckSegments (void) /* Walk through the segment list and check if there are segments that were - * not written to the output file. Output an error if this is the case. - */ +** not written to the output file. Output an error if this is the case. +*/ { unsigned I; for (I = 0; I < CollCount (&SegmentList); ++I) { @@ -662,6 +662,3 @@ void CheckSegments (void) } } } - - - diff --git a/src/ld65/segments.h b/src/ld65/segments.h index 67006bcc1..dc1e61d7d 100644 --- a/src/ld65/segments.h +++ b/src/ld65/segments.h @@ -95,8 +95,8 @@ struct Section { /* Prototype for a function that is used to write expressions to the target - * file (used in SegWrite). It returns one of the following values: - */ +** file (used in SegWrite). It returns one of the following values: +*/ #define SEG_EXPR_OK 0U /* Ok */ #define SEG_EXPR_RANGE_ERROR 1U /* Range error */ #define SEG_EXPR_TOO_COMPLEX 2U /* Expression too complex */ @@ -118,9 +118,9 @@ typedef unsigned (*SegWriteFunc) (ExprNode* E, /* The expression to write Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName); /* Search for a segment and return an existing one. If the segment does not - * exist, create a new one and return that. ObjName is only used for the error - * message and may be NULL if the segment is linker generated. - */ +** exist, create a new one and return that. ObjName is only used for the error +** message and may be NULL if the segment is linker generated. +*/ Section* NewSection (Segment* Seg, unsigned long Alignment, unsigned char AddrSize); /* Create a new section for the given segment */ @@ -133,21 +133,21 @@ Segment* SegFind (unsigned Name); int IsBSSType (Segment* S); /* Check if the given segment is a BSS style segment, that is, it does not - * contain non-zero data. - */ +** contain non-zero data. +*/ void SegDump (void); /* Dump the segments and it's contents */ unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size); /* Write a supposedly constant expression to the target file. Do a range - * check and return one of the SEG_EXPR_xxx codes. - */ +** check and return one of the SEG_EXPR_xxx codes. +*/ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* Data); /* Write the data from the given segment to a file. For expressions, F is - * called (see description of SegWriteFunc above). - */ +** called (see description of SegWriteFunc above). +*/ unsigned SegmentCount (void); /* Return the total number of segments */ @@ -160,15 +160,11 @@ void PrintDbgSegments (FILE* F); void CheckSegments (void); /* Walk through the segment list and check if there are segments that were - * not written to the output file. Output an error if this is the case. - */ +** not written to the output file. Output an error if this is the case. +*/ /* End of segments.h */ #endif - - - - diff --git a/src/ld65/span.c b/src/ld65/span.c index 1b3f35e06..498ab762a 100644 --- a/src/ld65/span.c +++ b/src/ld65/span.c @@ -111,9 +111,9 @@ Span* ReadSpan (FILE* F, ObjData* O, unsigned Id) unsigned* ReadSpanList (FILE* F) /* Read a list of span ids from a file. The list is returned as an array of - * unsigneds, the first being the number of spans (never zero) followed by - * the span ids. If the number of spans is zero, NULL is returned. - */ +** unsigneds, the first being the number of spans (never zero) followed by +** the span ids. If the number of spans is zero, NULL is returned. +*/ { unsigned* Spans; @@ -187,9 +187,9 @@ unsigned SpanCount (void) void PrintDbgSpanList (FILE* F, const ObjData* O, const unsigned* List) /* Output a string ",span=x[+y...]" for the given list. If the list is empty - * or NULL, output nothing. This is a helper function for other modules to - * print a list of spans read by ReadSpanList to the debug info file. - */ +** or NULL, output nothing. This is a helper function for other modules to +** print a list of spans read by ReadSpanList to the debug info file. +*/ { if (List && *List) { unsigned I; @@ -245,6 +245,3 @@ void PrintDbgSpans (FILE* F) /* Free the string buffer */ SB_Done (&SpanType); } - - - diff --git a/src/ld65/span.h b/src/ld65/span.h index 6e549189b..67ac84e43 100644 --- a/src/ld65/span.h +++ b/src/ld65/span.h @@ -78,9 +78,9 @@ Span* ReadSpan (FILE* F, struct ObjData* O, unsigned Id); unsigned* ReadSpanList (FILE* F); /* Read a list of span ids from a file. The list is returned as an array of - * unsigneds, the first being the number of spans (never zero) followed by - * the span ids. If the number of spans is zero, NULL is returned. - */ +** unsigneds, the first being the number of spans (never zero) followed by +** the span ids. If the number of spans is zero, NULL is returned. +*/ unsigned* DupSpanList (const unsigned* S); /* Duplicate a span list */ @@ -93,9 +93,9 @@ unsigned SpanCount (void); void PrintDbgSpanList (FILE* F, const struct ObjData* O, const unsigned* List); /* Output a string ",span=x[+y...]" for the given list. If the list is empty - * or NULL, output nothing. This is a helper function for other modules to - * print a list of spans read by ReadSpanList to the debug info file. - */ +** or NULL, output nothing. This is a helper function for other modules to +** print a list of spans read by ReadSpanList to the debug info file. +*/ void PrintDbgSpans (FILE* F); /* Output the spans to a debug info file */ @@ -103,7 +103,5 @@ void PrintDbgSpans (FILE* F); /* End of span.h */ + #endif - - - diff --git a/src/ld65/spool.c b/src/ld65/spool.c index b3173eb17..2b4f1ad45 100644 --- a/src/ld65/spool.c +++ b/src/ld65/spool.c @@ -61,11 +61,7 @@ void InitStrPool (void) StrPool = NewStringPool (1103); /* We insert a first string here, which will have id zero. This means - * that we can treat index zero later as invalid. - */ + ** that we can treat index zero later as invalid. + */ SP_AddStr (StrPool, "<invalid message #0>"); } - - - - diff --git a/src/ld65/spool.h b/src/ld65/spool.h index bd5a7a627..e376c5fe1 100644 --- a/src/ld65/spool.h +++ b/src/ld65/spool.h @@ -111,7 +111,3 @@ void InitStrPool (void); /* End of spool.h */ #endif - - - - diff --git a/src/ld65/tpool.c b/src/ld65/tpool.c index f943fa704..e6006e4e1 100644 --- a/src/ld65/tpool.c +++ b/src/ld65/tpool.c @@ -88,6 +88,3 @@ void InitTypePool (void) /* Allocate a type pool */ TypePool = NewStringPool (137); } - - - diff --git a/src/ld65/tpool.h b/src/ld65/tpool.h index d2a8510d9..c05408711 100644 --- a/src/ld65/tpool.h +++ b/src/ld65/tpool.h @@ -106,7 +106,3 @@ void InitTypePool (void); /* End of tpool.h */ #endif - - - - diff --git a/src/od65.vcxproj b/src/od65.vcxproj index abb2e7c8a..c788ac961 100644 --- a/src/od65.vcxproj +++ b/src/od65.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -18,10 +18,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -47,7 +49,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> @@ -62,7 +64,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> diff --git a/src/od65/dump.c b/src/od65/dump.c index ffca41907..2f538fe1d 100644 --- a/src/od65/dump.c +++ b/src/od65/dump.c @@ -64,8 +64,8 @@ static void DestroyStrPool (Collection* C) /* Free all strings in the given pool plus the item pointers. Note: The - * collection may not be reused later. - */ +** collection may not be reused later. +*/ { unsigned I; for (I = 0; I < CollCount (C); ++I) { @@ -78,9 +78,9 @@ static void DestroyStrPool (Collection* C) static const char* GetString (const Collection* C, unsigned Index) /* Get a string from a collection. In fact, this function calls CollConstAt, - * but will print a somewhat more readable error message if the index is out - * of bounds. - */ +** but will print a somewhat more readable error message if the index is out +** of bounds. +*/ { if (Index >= CollCount (C)) { Error ("Invalid string index (%u) - file corrupt!", Index); @@ -401,8 +401,8 @@ void DumpObjOptions (FILE* F, unsigned long Offset) default: /* Unknown argument type. This means that we cannot determine - * the option length, so we cannot proceed. - */ + ** the option length, so we cannot proceed. + */ Error ("Unknown option type: 0x%02X", Type); break; } @@ -951,7 +951,3 @@ void DumpObjSegSize (FILE* F, unsigned long Offset) /* Destroy the string pool */ DestroyStrPool (&StrPool); } - - - - diff --git a/src/od65/dump.h b/src/od65/dump.h index eafb86a3c..5371b7bdb 100644 --- a/src/od65/dump.h +++ b/src/od65/dump.h @@ -83,7 +83,3 @@ void DumpObjSegSize (FILE* F, unsigned long Offset); /* End of dump.h */ #endif - - - - diff --git a/src/od65/error.c b/src/od65/error.c index 2b5827571..364f52266 100644 --- a/src/od65/error.c +++ b/src/od65/error.c @@ -85,6 +85,3 @@ void Internal (const char* Format, ...) va_end (ap); exit (EXIT_FAILURE); } - - - diff --git a/src/od65/error.h b/src/od65/error.h index 16eabdb0e..8e1469a34 100644 --- a/src/od65/error.h +++ b/src/od65/error.h @@ -63,6 +63,3 @@ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)) /* End of error.h */ #endif - - - diff --git a/src/od65/fileio.c b/src/od65/fileio.c index 9ddab17af..a8d31c730 100644 --- a/src/od65/fileio.c +++ b/src/od65/fileio.c @@ -137,8 +137,8 @@ unsigned long ReadVar (FILE* F) /* Read a variable size value from the file */ { /* The value was written to the file in 7 bit chunks LSB first. If there - * are more bytes, bit 8 is set, otherwise it is clear. - */ + ** are more bytes, bit 8 is set, otherwise it is clear. + */ unsigned char C; unsigned long V = 0; unsigned Shift = 0; @@ -246,6 +246,3 @@ void ReadStrPool (FILE* F, Collection* C) CollAppend (C, ReadStr (F)); } } - - - diff --git a/src/od65/fileio.h b/src/od65/fileio.h index cf05a7dad..068c4d9a3 100644 --- a/src/od65/fileio.h +++ b/src/od65/fileio.h @@ -97,6 +97,3 @@ void ReadStrPool (FILE* F, Collection* C); /* End of fileio.h */ #endif - - - diff --git a/src/od65/global.c b/src/od65/global.c index eb6555154..bb56ceecf 100644 --- a/src/od65/global.c +++ b/src/od65/global.c @@ -44,6 +44,3 @@ unsigned What = 0; /* What should get dumped? */ - - - diff --git a/src/od65/global.h b/src/od65/global.h index 624fe2a84..22054d3f6 100644 --- a/src/od65/global.h +++ b/src/od65/global.h @@ -65,6 +65,3 @@ extern unsigned What; /* What should get dumped? */ /* End of global.h */ #endif - - - diff --git a/src/od65/main.c b/src/od65/main.c index aa0e6f86d..802290ffd 100644 --- a/src/od65/main.c +++ b/src/od65/main.c @@ -361,6 +361,3 @@ int main (int argc, char* argv []) /* Success */ return EXIT_SUCCESS; } - - - diff --git a/src/sim65.vcxproj b/src/sim65.vcxproj index 7a65f9384..f87b4db6b 100644 --- a/src/sim65.vcxproj +++ b/src/sim65.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -18,10 +18,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -48,7 +50,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> @@ -63,7 +65,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> diff --git a/src/sim65/6502.c b/src/sim65/6502.c index 2a43e40dc..312eb2fe1 100644 --- a/src/sim65/6502.c +++ b/src/sim65/6502.c @@ -85,8 +85,8 @@ static unsigned HaveIRQRequest; #define GET_SF() ((Regs.SR & SF) != 0) /* Set the flags. The parameter is a boolean flag that says if the flag should be - * set or reset. - */ +** set or reset. +*/ #define SET_CF(f) do { if (f) { Regs.SR |= CF; } else { Regs.SR &= ~CF; } } while (0) #define SET_ZF(f) do { if (f) { Regs.SR |= ZF; } else { Regs.SR &= ~ZF; } } while (0) #define SET_IF(f) do { if (f) { Regs.SR |= IF; } else { Regs.SR &= ~IF; } } while (0) @@ -96,8 +96,8 @@ static unsigned HaveIRQRequest; #define SET_SF(f) do { if (f) { Regs.SR |= SF; } else { Regs.SR &= ~SF; } } while (0) /* Special test and set macros. The meaning of the parameter depends on the - * actual flag that should be set or reset. - */ +** actual flag that should be set or reset. +*/ #define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0) #define TEST_SF(v) SET_SF (((v) & 0x80) != 0) #define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0) diff --git a/src/sim65/6502.h b/src/sim65/6502.h index 6a640fae1..2cf2d4f1e 100644 --- a/src/sim65/6502.h +++ b/src/sim65/6502.h @@ -93,8 +93,8 @@ void NMIRequest (void); unsigned ExecuteInsn (void); /* Execute one CPU instruction. Return the number of clock cycles for the - * executed instruction. - */ +** executed instruction. +*/ unsigned long GetCycles (void); /* Return the total number of clock cycles executed */ diff --git a/src/sim65/error.c b/src/sim65/error.c index 378403e55..3114951af 100644 --- a/src/sim65/error.c +++ b/src/sim65/error.c @@ -85,6 +85,3 @@ void Internal (const char* Format, ...) va_end (ap); exit (EXIT_FAILURE); } - - - diff --git a/src/sim65/error.h b/src/sim65/error.h index 507294b90..7bee4954c 100644 --- a/src/sim65/error.h +++ b/src/sim65/error.h @@ -63,6 +63,3 @@ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)) /* End of error.h */ #endif - - - diff --git a/src/sim65/memory.c b/src/sim65/memory.c index 42f4f7be7..305b26a73 100644 --- a/src/sim65/memory.c +++ b/src/sim65/memory.c @@ -83,9 +83,9 @@ unsigned MemReadWord (unsigned Addr) unsigned MemReadZPWord (unsigned char Addr) /* Read a word from the zero page. This function differs from ReadMemW in that - * the read will always be in the zero page, even in case of an address - * overflow. - */ +** the read will always be in the zero page, even in case of an address +** overflow. +*/ { unsigned W = MemReadByte (Addr++); return (W | (MemReadByte (Addr) << 8)); diff --git a/src/sim65/memory.h b/src/sim65/memory.h index 5e234c561..5de3a2bb8 100644 --- a/src/sim65/memory.h +++ b/src/sim65/memory.h @@ -55,9 +55,9 @@ unsigned MemReadWord (unsigned Addr); unsigned MemReadZPWord (unsigned char Addr); /* Read a word from the zero page. This function differs from ReadMemW in that - * the read will always be in the zero page, even in case of an address - * overflow. - */ +** the read will always be in the zero page, even in case of an address +** overflow. +*/ void MemInit (void); /* Initialize the memory subsystem */ @@ -67,7 +67,3 @@ void MemInit (void); /* End of memory.h */ #endif - - - - diff --git a/src/sim65/paravirt.c b/src/sim65/paravirt.c index 29b8ea930..0deb59a5f 100644 --- a/src/sim65/paravirt.c +++ b/src/sim65/paravirt.c @@ -36,15 +36,17 @@ #include <string.h> #include <stdlib.h> #include <fcntl.h> +#if defined(_WIN32) +# define O_INITIAL O_BINARY +#else +# define O_INITIAL 0 +#endif #if defined(_MSC_VER) /* Microsoft compiler */ # include <io.h> -# pragma warning(disable : 4996) -# define O_INITIAL O_BINARY #else /* Anyone else */ # include <unistd.h> -# define O_INITIAL 0 #endif /* common */ diff --git a/src/sp65.vcxproj b/src/sp65.vcxproj index 1651ab007..8db98346c 100644 --- a/src/sp65.vcxproj +++ b/src/sp65.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -18,10 +18,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -47,7 +49,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> @@ -62,7 +64,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> diff --git a/src/sp65/asm.c b/src/sp65/asm.c index c397d33d6..8f520cb9e 100644 --- a/src/sp65/asm.c +++ b/src/sp65/asm.c @@ -238,6 +238,3 @@ void WriteAsmFile (const StrBuf* Data, const Collection* A, const Bitmap* B) Error ("Error closing output file `%s': %s", Name, strerror (errno)); } } - - - diff --git a/src/sp65/asm.h b/src/sp65/asm.h index 06d16802e..18c55e8b5 100644 --- a/src/sp65/asm.h +++ b/src/sp65/asm.h @@ -61,6 +61,3 @@ void WriteAsmFile (const StrBuf* Data, const Collection* A, const Bitmap* B); /* End of asm.h */ #endif - - - diff --git a/src/sp65/attr.c b/src/sp65/attr.c index 8f0ddeaed..db026af48 100644 --- a/src/sp65/attr.c +++ b/src/sp65/attr.c @@ -96,10 +96,10 @@ void DumpAttrColl (const Collection* C) int FindAttr (const Collection* C, const char* Name, unsigned* Index) /* Search for an attribute with the given name in the collection. If it is - * found, the function returns true and Index contains the index of the - * entry. If Name isn't found, the function returns false and Index - * will contain the insert position. - */ +** found, the function returns true and Index contains the index of the +** entry. If Name isn't found, the function returns false and Index +** will contain the insert position. +*/ { /* Do a binary search */ int Lo = 0; @@ -136,8 +136,8 @@ int FindAttr (const Collection* C, const char* Name, unsigned* Index) const Attr* GetAttr (const Collection* C, const char* Name) /* Search for an attribute with the given name and return it. The function - * returns NULL if the attribute wasn't found. - */ +** returns NULL if the attribute wasn't found. +*/ { /* Search for the attribute and return it */ unsigned Index; @@ -153,9 +153,9 @@ const Attr* GetAttr (const Collection* C, const char* Name) const Attr* NeedAttr (const Collection* C, const char* Name, const char* Op) /* Search for an attribute with the given name and return it. If the attribute - * is not found, the function terminates with an error using Op as additional - * context in the error message. - */ +** is not found, the function terminates with an error using Op as additional +** context in the error message. +*/ { /* Search for the attribute and return it */ unsigned Index; @@ -169,8 +169,8 @@ const Attr* NeedAttr (const Collection* C, const char* Name, const char* Op) const char* GetAttrVal (const Collection* C, const char* Name) /* Search for an attribute with the given name and return its value. The - * function returns NULL if the attribute wasn't found. - */ +** function returns NULL if the attribute wasn't found. +*/ { const Attr* A = GetAttr (C, Name); return (A == 0)? 0 : A->Value; @@ -180,9 +180,9 @@ const char* GetAttrVal (const Collection* C, const char* Name) const char* NeedAttrVal (const Collection* C, const char* Name, const char* Op) /* Search for an attribute with the given name and return its value. If the - * attribute wasn't not found, the function terminates with an error using - * Op as additional context in the error message. - */ +** attribute wasn't not found, the function terminates with an error using +** Op as additional context in the error message. +*/ { const Attr* A = NeedAttr (C, Name, Op); return (A == 0)? 0 : A->Value; @@ -197,8 +197,8 @@ void AddAttr (Collection* C, const char* Name, const char* Value) Attr* A = NewAttr (Name, Value); /* Search for the attribute. If it is there, we have a duplicate, otherwise - * we have the insert position. - */ + ** we have the insert position. + */ unsigned Index; if (FindAttr (C, Name, &Index)) { Error ("Duplicate command line attribute `%s'", Name); @@ -212,9 +212,9 @@ void AddAttr (Collection* C, const char* Name, const char* Value) void SplitAddAttr (Collection* C, const char* Combined, const char* Name) /* Split a combined name/value pair and add it as an attribute to C. Some - * attributes may not need a name. If the name is missing, use Name. If - * Name is NULL, terminate with an error. - */ +** attributes may not need a name. If the name is missing, use Name. If +** Name is NULL, terminate with an error. +*/ { /* Name and value are separated by an equal sign */ const char* Pos = strchr (Combined, '='); @@ -242,10 +242,10 @@ void SplitAddAttr (Collection* C, const char* Combined, const char* Name) Collection* ParseAttrList (const char* List, const char** NameList, unsigned NameCount) /* Parse a list containing name/value pairs into a sorted collection. Some - * attributes may not need a name, so NameList contains these names. If there - * were no errors, the function returns a alphabetically sorted collection - * containing Attr entries. - */ +** attributes may not need a name, so NameList contains these names. If there +** were no errors, the function returns a alphabetically sorted collection +** containing Attr entries. +*/ { const char* Name; @@ -304,6 +304,3 @@ void FreeAttrList (Collection* C) /* Free the collection itself */ FreeCollection (C); } - - - diff --git a/src/sp65/attr.h b/src/sp65/attr.h index 9a4f834fb..2b7ce68b9 100644 --- a/src/sp65/attr.h +++ b/src/sp65/attr.h @@ -75,48 +75,48 @@ void DumpAttrColl (const Collection* C); int FindAttr (const Collection* C, const char* Name, unsigned* Index); /* Search for an attribute with the given name in the collection. If it is - * found, the function returns true and Index contains the index of the - * entry. If Name isn't found, the function returns false and Index - * will contain the insert position. - */ +** found, the function returns true and Index contains the index of the +** entry. If Name isn't found, the function returns false and Index +** will contain the insert position. +*/ const Attr* GetAttr (const Collection* C, const char* Name); /* Search for an attribute with the given name and return it. The function - * returns NULL if the attribute wasn't found. - */ +** returns NULL if the attribute wasn't found. +*/ const Attr* NeedAttr (const Collection* C, const char* Name, const char* Op); /* Search for an attribute with the given name and return it. If the attribute - * is not found, the function terminates with an error using Op as additional - * context in the error message. - */ +** is not found, the function terminates with an error using Op as additional +** context in the error message. +*/ const char* GetAttrVal (const Collection* C, const char* Name); /* Search for an attribute with the given name and return its value. The - * function returns NULL if the attribute wasn't found. - */ +** function returns NULL if the attribute wasn't found. +*/ const char* NeedAttrVal (const Collection* C, const char* Name, const char* Op); /* Search for an attribute with the given name and return its value. If the - * attribute wasn't not found, the function terminates with an error using - * Op as additional context in the error message. - */ +** attribute wasn't not found, the function terminates with an error using +** Op as additional context in the error message. +*/ void AddAttr (Collection* C, const char* Name, const char* Value); /* Add an attribute to an alphabetically sorted attribute collection */ void SplitAddAttr (Collection* C, const char* Combined, const char* Name); /* Split a combined name/value pair and add it as an attribute to C. Some - * attributes may not need a name. If the name is missing, use Name. If - * Name is NULL, terminate with an error. - */ +** attributes may not need a name. If the name is missing, use Name. If +** Name is NULL, terminate with an error. +*/ Collection* ParseAttrList (const char* List, const char** NameList, unsigned NameCount); /* Parse a list containing name/value pairs into a sorted collection. Some - * attributes may not need a name, so NameList contains these names. If there - * were no errors, the function returns a alphabetically sorted collection - * containing Attr entries. - */ +** attributes may not need a name, so NameList contains these names. If there +** were no errors, the function returns a alphabetically sorted collection +** containing Attr entries. +*/ void FreeAttrList (Collection* C); /* Free a list of attributes */ @@ -126,6 +126,3 @@ void FreeAttrList (Collection* C); /* End of attr.h */ #endif - - - diff --git a/src/sp65/bin.c b/src/sp65/bin.c index fddb8320f..fdf7ddee0 100644 --- a/src/sp65/bin.c +++ b/src/sp65/bin.c @@ -69,10 +69,10 @@ void WriteBinFile (const StrBuf* Data, const Collection* A, } /* Write to the file. We will use fwrite here instead of the fileio - * module, since it's just one call, so the latter doesn't have any - * advantages, and we can output a more readable error message in case of - * problems. - */ + ** module, since it's just one call, so the latter doesn't have any + ** advantages, and we can output a more readable error message in case of + ** problems. + */ Size = SB_GetLen (Data); if (fwrite (SB_GetConstBuf (Data), 1, Size, F) != Size) { Error ("Error writing to output file `%s': %s", Name, strerror (errno)); @@ -83,6 +83,3 @@ void WriteBinFile (const StrBuf* Data, const Collection* A, Error ("Error closing output file `%s': %s", Name, strerror (errno)); } } - - - diff --git a/src/sp65/bin.h b/src/sp65/bin.h index 476ae9a16..4a32a0a98 100644 --- a/src/sp65/bin.h +++ b/src/sp65/bin.h @@ -61,6 +61,3 @@ void WriteBinFile (const StrBuf* Data, const Collection* A, const Bitmap* B); /* End of bin.h */ #endif - - - diff --git a/src/sp65/bitmap.c b/src/sp65/bitmap.c index b6270d246..4536fb819 100644 --- a/src/sp65/bitmap.c +++ b/src/sp65/bitmap.c @@ -104,9 +104,9 @@ int ValidBitmapSize (unsigned Width, unsigned Height) Bitmap* SliceBitmap (const Bitmap* O, unsigned OrigX, unsigned OrigY, unsigned Width, unsigned Height) /* Create a slice of the given bitmap. The slice starts at position X/Y of - * the original and has the given width and height. Location 0/0 is at the - * upper left corner. - */ +** the original and has the given width and height. Location 0/0 is at the +** upper left corner. +*/ { Bitmap* B; unsigned Y; @@ -140,15 +140,15 @@ Bitmap* SliceBitmap (const Bitmap* O, unsigned OrigX, unsigned OrigY, Color GetPixelColor (const Bitmap* B, unsigned X, unsigned Y) /* Get the color for a given pixel. For indexed bitmaps, the palette entry - * is returned. - */ +** is returned. +*/ { /* Get the pixel at the given coordinates */ Pixel P = GetPixel (B, X, Y); /* If the bitmap has a palette, return the color from the palette. For - * simplicity, we will only check the palette, not the type. - */ + ** simplicity, we will only check the palette, not the type. + */ if (B->Pal) { if (P.Index >= B->Pal->Count) { /* Palette index is invalid */ @@ -166,8 +166,8 @@ Color GetPixelColor (const Bitmap* B, unsigned X, unsigned Y) Pixel GetPixel (const Bitmap* B, unsigned X, unsigned Y) /* Return a pixel from the bitmap. The returned value may either be a color - * or a palette index, depending on the type of the bitmap. - */ +** or a palette index, depending on the type of the bitmap. +*/ { /* Check the coordinates */ PRECONDITION (X < B->Width && Y < B->Height); @@ -175,6 +175,3 @@ Pixel GetPixel (const Bitmap* B, unsigned X, unsigned Y) /* Return the pixel */ return B->Data[Y * B->Width + X]; } - - - diff --git a/src/sp65/bitmap.h b/src/sp65/bitmap.h index f5423f67f..bf5e60559 100644 --- a/src/sp65/bitmap.h +++ b/src/sp65/bitmap.h @@ -65,10 +65,10 @@ typedef struct Bitmap Bitmap; struct Bitmap { /* Name of the bitmap. This is used for error messages and should be - * something that allows the user to identify which bitmap the message - * refers to. For bitmaps loaded from a file, using the file name is - * a good idea. - */ + ** something that allows the user to identify which bitmap the message + ** refers to. For bitmaps loaded from a file, using the file name is + ** a good idea. + */ StrBuf Name; /* Size of the bitmap */ @@ -103,19 +103,19 @@ Bitmap* SliceBitmap (const Bitmap* Original, unsigned X, unsigned Y, unsigned Width, unsigned Height); /* Create a slice of the given bitmap. The slice starts at position X/Y of - * the original and has the given width and height. Location 0/0 is at the - * upper left corner. - */ +** the original and has the given width and height. Location 0/0 is at the +** upper left corner. +*/ Color GetPixelColor (const Bitmap* B, unsigned X, unsigned Y); /* Get the color for a given pixel. For indexed bitmaps, the palette entry - * is returned. - */ +** is returned. +*/ Pixel GetPixel (const Bitmap* B, unsigned X, unsigned Y); /* Return a pixel from the bitmap. The returned value may either be a color - * or a palette index, depending on the type of the bitmap. - */ +** or a palette index, depending on the type of the bitmap. +*/ #if defined(HAVE_INLINE) INLINE int BitmapIsIndexed (const Bitmap* B) @@ -170,8 +170,8 @@ INLINE const StrBuf* GetBitmapName (const Bitmap* B) #if defined(HAVE_INLINE) INLINE unsigned GetBitmapColors (const Bitmap* B) /* Get the number of colors in an image. The function will return the number - * of palette entries for indexed bitmaps and 2^24 for non indexed bitmaps. - */ +** of palette entries for indexed bitmaps and 2^24 for non indexed bitmaps. +*/ { return B->Pal? B->Pal->Count : (1U << 24); } @@ -184,6 +184,3 @@ INLINE unsigned GetBitmapColors (const Bitmap* B) /* End of bitmap.h */ #endif - - - diff --git a/src/sp65/c.c b/src/sp65/c.c index 537333b67..d4d6ee00b 100644 --- a/src/sp65/c.c +++ b/src/sp65/c.c @@ -157,9 +157,9 @@ void WriteCFile (const StrBuf* Data, const Collection* A, const Bitmap* B) /* Write a readable header */ fprintf (F, "/*\n" - " * This file was generated by %s %s from\n" - " * %.*s (%ux%u, %u colors%s)\n" - " */\n" + "** This file was generated by %s %s from\n" + "** %.*s (%ux%u, %u colors%s)\n" + "*/\n" "\n", ProgName, GetVersionAsString (), @@ -169,8 +169,8 @@ void WriteCFile (const StrBuf* Data, const Collection* A, const Bitmap* B) BitmapIsIndexed (B)? ", indexed" : ""); /* If an identifier was given, output #defines for width, height, the - * number of colors and declare a variable for the data. - */ + ** number of colors and declare a variable for the data. + */ if (Ident) { fprintf (F, "#define %s_COLORS %u\n" @@ -223,6 +223,3 @@ void WriteCFile (const StrBuf* Data, const Collection* A, const Bitmap* B) Error ("Error closing output file `%s': %s", Name, strerror (errno)); } } - - - diff --git a/src/sp65/c.h b/src/sp65/c.h index 8cf763144..113d0dee1 100644 --- a/src/sp65/c.h +++ b/src/sp65/c.h @@ -61,6 +61,3 @@ void WriteCFile (const StrBuf* Data, const Collection* A, const Bitmap* B); /* End of c.h */ #endif - - - diff --git a/src/sp65/color.c b/src/sp65/color.c index e1abd79be..0180865c6 100644 --- a/src/sp65/color.c +++ b/src/sp65/color.c @@ -64,6 +64,3 @@ Color RGBA (unsigned char R, unsigned char G, unsigned char B, unsigned char A) } #endif - - - diff --git a/src/sp65/color.h b/src/sp65/color.h index 3646837f5..31688bff4 100644 --- a/src/sp65/color.h +++ b/src/sp65/color.h @@ -94,6 +94,3 @@ Color RGBA (unsigned char R, unsigned char G, unsigned char B, unsigned char A); /* End of color.h */ #endif - - - diff --git a/src/sp65/convert.c b/src/sp65/convert.c index f5022246c..45b40f1ef 100644 --- a/src/sp65/convert.c +++ b/src/sp65/convert.c @@ -89,10 +89,10 @@ static int Compare (const void* Key, const void* MapEntry) StrBuf* ConvertTo (const Bitmap* B, const Collection* A) /* Convert the bitmap B into some sort of other binary format. The output is - * stored in a string buffer (which is actually a dynamic char array) and - * returned. The actual output format is taken from the "format" attribute - * in the attribute collection A. - */ +** stored in a string buffer (which is actually a dynamic char array) and +** returned. The actual output format is taken from the "format" attribute +** in the attribute collection A. +*/ { const ConverterMapEntry* E; @@ -123,4 +123,3 @@ void ListConversionTargets (FILE* F) fprintf (F, " %s\n", ConverterMap[I].Format); } } - diff --git a/src/sp65/convert.h b/src/sp65/convert.h index b0bc51ba8..3ebb23dc2 100644 --- a/src/sp65/convert.h +++ b/src/sp65/convert.h @@ -57,10 +57,10 @@ StrBuf* ConvertTo (const Bitmap* B, const Collection* A); /* Convert the bitmap B into some sort of other binary format. The output is - * stored in a string buffer (which is actually a dynamic char array) and - * returned. The actual output format is taken from the "format" attribute - * in the attribute collection A. - */ +** stored in a string buffer (which is actually a dynamic char array) and +** returned. The actual output format is taken from the "format" attribute +** in the attribute collection A. +*/ void ListConversionTargets (FILE* F); /* Output a list of conversion targets */ @@ -70,6 +70,3 @@ void ListConversionTargets (FILE* F); /* End of convert.h */ #endif - - - diff --git a/src/sp65/error.c b/src/sp65/error.c index 70bc5bdb3..7a29cb551 100644 --- a/src/sp65/error.c +++ b/src/sp65/error.c @@ -85,6 +85,3 @@ void Internal (const char* Format, ...) va_end (ap); exit (EXIT_FAILURE); } - - - diff --git a/src/sp65/error.h b/src/sp65/error.h index 7643cefa9..41ee83b1b 100644 --- a/src/sp65/error.h +++ b/src/sp65/error.h @@ -63,6 +63,3 @@ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)) /* End of error.h */ #endif - - - diff --git a/src/sp65/fileio.c b/src/sp65/fileio.c index a43b7eb26..074a7b534 100644 --- a/src/sp65/fileio.c +++ b/src/sp65/fileio.c @@ -123,6 +123,3 @@ void* ReadData (FILE* F, void* Data, unsigned Size) } return Data; } - - - diff --git a/src/sp65/fileio.h b/src/sp65/fileio.h index de2cdd2ce..c17647d33 100644 --- a/src/sp65/fileio.h +++ b/src/sp65/fileio.h @@ -72,6 +72,3 @@ void* ReadData (FILE* F, void* Data, unsigned Size); /* End of fileio.h */ #endif - - - diff --git a/src/sp65/geosbitmap.c b/src/sp65/geosbitmap.c index f5770f720..201d0aca1 100644 --- a/src/sp65/geosbitmap.c +++ b/src/sp65/geosbitmap.c @@ -76,15 +76,15 @@ struct RLE { static void StoreByte (struct RLE* RLE) /* Store a unique byte or a run of repeated bytes. If count is zero, the - * function will flush the internal buffers, so that all data is in RLE->D. - */ +** function will flush the internal buffers, so that all data is in RLE->D. +*/ { if (RLE->Count == 1 || RLE->Count == 2) { /* A run of two identical bytes is treated as two unique bytes, since - * this will usually merge with the following run. - */ + ** this will usually merge with the following run. + */ SB_AppendChar (&RLE->UniqueData, RLE->LastVal); if (RLE->Count == 2) { SB_AppendChar (&RLE->UniqueData, RLE->LastVal); @@ -96,8 +96,8 @@ static void StoreByte (struct RLE* RLE) } else { /* Run of repeated bytes. First flush the temp buffer for unique - * bytes. - */ + ** bytes. + */ const char* Buf = SB_GetConstBuf (&RLE->UniqueData); unsigned Count = SB_GetLen (&RLE->UniqueData); while (Count) { @@ -142,9 +142,9 @@ static void StoreByte (struct RLE* RLE) StrBuf* GenGeosBitmap (const Bitmap* B, const Collection* A attribute ((unused))) /* Generate binary output in GEOS compacted bitmap format for the bitmap B. - * The output is stored in a string buffer (which is actually a dynamic char - * array) and returned. - */ +** The output is stored in a string buffer (which is actually a dynamic char +** array) and returned. +*/ { unsigned LineWidth; unsigned char* Buf; @@ -192,8 +192,8 @@ StrBuf* GenGeosBitmap (const Bitmap* B, const Collection* A attribute ((unused)) SB_Realloc (D, 64); /* Compact the image. We're currently using only REPEAT and UNIQUE opcodes. - * BIGCOUNT is rather difficult to apply. - */ + ** BIGCOUNT is rather difficult to apply. + */ RLE.Buf = Buf; RLE.Remaining = LineWidth * GetBitmapHeight (B) - 1; RLE.LastVal = *RLE.Buf++; @@ -229,6 +229,3 @@ StrBuf* GenGeosBitmap (const Bitmap* B, const Collection* A attribute ((unused)) /* Return the converted bitmap */ return D; } - - - diff --git a/src/sp65/geosbitmap.h b/src/sp65/geosbitmap.h index 87fccf666..759030224 100644 --- a/src/sp65/geosbitmap.h +++ b/src/sp65/geosbitmap.h @@ -55,9 +55,9 @@ StrBuf* GenGeosBitmap (const Bitmap* B, const Collection* A); /* Generate binary output in GEOS compacted bitmap format for the bitmap B. - * The output is stored in a string buffer (which is actually a dynamic char - * array) and returned. - */ +** The output is stored in a string buffer (which is actually a dynamic char +** array) and returned. +*/ diff --git a/src/sp65/geosicon.c b/src/sp65/geosicon.c index 52a8945ee..bc4072b0e 100644 --- a/src/sp65/geosicon.c +++ b/src/sp65/geosicon.c @@ -64,9 +64,9 @@ StrBuf* GenGeosIcon (const Bitmap* B, const Collection* A attribute ((unused))) /* Generate binary output in GEOS icon format for the bitmap B. The output - * is stored in a string buffer (which is actually a dynamic char array) and - * returned. - */ +** is stored in a string buffer (which is actually a dynamic char array) and +** returned. +*/ { StrBuf* D; unsigned X, Y; @@ -108,6 +108,3 @@ StrBuf* GenGeosIcon (const Bitmap* B, const Collection* A attribute ((unused))) /* Return the converted bitmap */ return D; } - - - diff --git a/src/sp65/geosicon.h b/src/sp65/geosicon.h index 3a54b70cc..545aab1ac 100644 --- a/src/sp65/geosicon.h +++ b/src/sp65/geosicon.h @@ -55,15 +55,12 @@ StrBuf* GenGeosIcon (const Bitmap* B, const Collection* A); /* Generate binary output in GEOS icon format for the bitmap B. The output - * is stored in a string buffer (which is actually a dynamic char array) and - * returned. - */ +** is stored in a string buffer (which is actually a dynamic char array) and +** returned. +*/ /* End of geosicon.h */ #endif - - - diff --git a/src/sp65/input.c b/src/sp65/input.c index 85807752f..381adf6b9 100644 --- a/src/sp65/input.c +++ b/src/sp65/input.c @@ -87,9 +87,9 @@ static const FileId FormatTable[] = { Bitmap* ReadInputFile (const Collection* A) /* Read a bitmap from a file and return it. Format, file name etc. must be - * given as attributes in A. If no format is given, the function tries to - * autodetect it by using the extension of the file name. - */ +** given as attributes in A. If no format is given, the function tries to +** autodetect it by using the extension of the file name. +*/ { const FileId* F; @@ -119,6 +119,3 @@ Bitmap* ReadInputFile (const Collection* A) /* Call the format specific read */ return InputFormatTable[F->Id].Read (A); } - - - diff --git a/src/sp65/input.h b/src/sp65/input.h index cfbc6f63c..60581cfe8 100644 --- a/src/sp65/input.h +++ b/src/sp65/input.h @@ -54,15 +54,12 @@ Bitmap* ReadInputFile (const Collection* A); /* Read a bitmap from a file and return it. Format, file name etc. must be - * given as attributes in A. If no format is given, the function tries to - * autodetect it by using the extension of the file name. - */ +** given as attributes in A. If no format is given, the function tries to +** autodetect it by using the extension of the file name. +*/ /* End of input.h */ #endif - - - diff --git a/src/sp65/koala.c b/src/sp65/koala.c index d66969348..e2122c781 100644 --- a/src/sp65/koala.c +++ b/src/sp65/koala.c @@ -62,9 +62,9 @@ StrBuf* GenKoala (const Bitmap* B, const Collection* A attribute ((unused))) /* Generate binary output in koala format for the bitmap B. The output is - * stored in a string buffer (which is actually a dynamic char array) and - * returned. - */ +** stored in a string buffer (which is actually a dynamic char array) and +** returned. +*/ { StrBuf* D; unsigned char Screen[160][200]; @@ -101,6 +101,3 @@ StrBuf* GenKoala (const Bitmap* B, const Collection* A attribute ((unused))) /* Return the converted bitmap */ return D; } - - - diff --git a/src/sp65/koala.h b/src/sp65/koala.h index 57ea86ad5..5114bee65 100644 --- a/src/sp65/koala.h +++ b/src/sp65/koala.h @@ -55,15 +55,12 @@ StrBuf* GenKoala (const Bitmap* B, const Collection* A); /* Generate binary output in koala format for the bitmap B. The output is - * stored in a string buffer (which is actually a dynamic char array) and - * returned. - */ +** stored in a string buffer (which is actually a dynamic char array) and +** returned. +*/ /* End of koala.h */ #endif - - - diff --git a/src/sp65/lynxsprite.c b/src/sp65/lynxsprite.c index 99d7a1bc1..e4afc7773 100644 --- a/src/sp65/lynxsprite.c +++ b/src/sp65/lynxsprite.c @@ -235,22 +235,22 @@ static void WriteOutBuffer(StrBuf *D) static void encodeSprite(StrBuf *D, enum Mode M, char ColorBits, char ColorMask, char LineBuffer[512], int len, int LastOpaquePixel) { /* - * The data starts with a byte count. It tells the number of bytes on this - * line + 1. - * Special case is a count of 1. It will change to next quadrant. - * Other special case is 0. It will end the sprite. - * - * Ordinary data packet. These are bits in a stream. - * 1=literal 0=packed - * 4 bit count (+1) - * for literal you put "count" values - * for packed you repeat the value "count" times - * Never use packed mode for one pixel - * If the last bit on a line is 1 you need to add a byte of zeroes - * A sequence 00000 ends a scan line - * - * All data is high nybble first - */ +** The data starts with a byte count. It tells the number of bytes on this +** line + 1. +** Special case is a count of 1. It will change to next quadrant. +** Other special case is 0. It will end the sprite. +** +** Ordinary data packet. These are bits in a stream. +** 1=literal 0=packed +** 4 bit count (+1) +** for literal you put "count" values +** for packed you repeat the value "count" times +** Never use packed mode for one pixel +** If the last bit on a line is 1 you need to add a byte of zeroes +** A sequence 00000 ends a scan line +** +** All data is high nybble first +*/ unsigned char V = 0; signed i; signed count; @@ -369,17 +369,17 @@ static void encodeSprite(StrBuf *D, enum Mode M, char ColorBits, char ColorMask, StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A) /* Generate binary output in Lynx sprite format for the bitmap B. The output - * is stored in a string buffer (which is actually a dynamic char array) and - * returned. - * - * The Lynx will draw 4 quadrants: - * - Down right - * - Up right - * - Up left - * - Down left - * - * The sprite will end with a byte 0. - */ +** is stored in a string buffer (which is actually a dynamic char array) and +** returned. +** +** The Lynx will draw 4 quadrants: +** - Down right +** - Up right +** - Up left +** - Down left +** +** The sprite will end with a byte 0. +*/ { enum Mode M; StrBuf* D; @@ -552,6 +552,3 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A) /* Return the converted bitmap */ return D; } - - - diff --git a/src/sp65/lynxsprite.h b/src/sp65/lynxsprite.h index c5611e036..4f9a9f07d 100644 --- a/src/sp65/lynxsprite.h +++ b/src/sp65/lynxsprite.h @@ -55,15 +55,12 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A); /* Generate binary output in packed Lynx sprite format for the bitmap B. The output - * is stored in a string buffer (which is actually a dynamic char array) and - * returned. - */ +** is stored in a string buffer (which is actually a dynamic char array) and +** returned. +*/ /* End of lynxsprite.h */ #endif - - - diff --git a/src/sp65/main.c b/src/sp65/main.c index 92cd71114..ef2188c82 100644 --- a/src/sp65/main.c +++ b/src/sp65/main.c @@ -107,8 +107,8 @@ static void Usage (void) static void SetWorkBitmap (Bitmap* N) /* Delete an old working bitmap and set a new one. The new one may be NULL - * to clear it. - */ +** to clear it. +*/ { /* If we have a distinct work bitmap, delete it */ if (C != 0 && C != B) { @@ -123,8 +123,8 @@ static void SetWorkBitmap (Bitmap* N) static void SetOutputData (StrBuf* N) /* Delete the old output data and replace it by the given one. The new one - * may be NULL to clear it. - */ +** may be NULL to clear it. +*/ { /* Delete the old output data */ if (D != 0) { @@ -405,6 +405,3 @@ int main (int argc, char* argv []) /* Success */ return EXIT_SUCCESS; } - - - diff --git a/src/sp65/output.c b/src/sp65/output.c index ac6f3db92..3ffa38dcc 100644 --- a/src/sp65/output.c +++ b/src/sp65/output.c @@ -106,11 +106,11 @@ static const FileId FormatTable[] = { void WriteOutputFile (const StrBuf* Data, const Collection* A, const Bitmap* B) /* Write the contents of Data to a file. Format, file name etc. must be given - * as attributes in A. If no format is given, the function tries to autodetect - * it by using the extension of the file name. The bitmap passed to the - * function is the bitmap used as source of the conversion. It may be used to - * determine the bitmap properties for documentation purposes. - */ +** as attributes in A. If no format is given, the function tries to autodetect +** it by using the extension of the file name. The bitmap passed to the +** function is the bitmap used as source of the conversion. It may be used to +** determine the bitmap properties for documentation purposes. +*/ { const FileId* F; @@ -140,6 +140,3 @@ void WriteOutputFile (const StrBuf* Data, const Collection* A, const Bitmap* B) /* Call the format specific write */ OutputFormatTable[F->Id].Write (Data, A, B); } - - - diff --git a/src/sp65/output.h b/src/sp65/output.h index 6d3b4c16b..ff9a59b8a 100644 --- a/src/sp65/output.h +++ b/src/sp65/output.h @@ -54,17 +54,14 @@ void WriteOutputFile (const StrBuf* Data, const Collection* A, const Bitmap* B); /* Write the contents of Data to a file. Format, file name etc. must be given - * as attributes in A. If no format is given, the function tries to autodetect - * it by using the extension of the file name. The bitmap passed to the - * function is the bitmap used as source of the conversion. It may be used to - * determine the bitmap properties for documentation purposes. - */ +** as attributes in A. If no format is given, the function tries to autodetect +** it by using the extension of the file name. The bitmap passed to the +** function is the bitmap used as source of the conversion. It may be used to +** determine the bitmap properties for documentation purposes. +*/ /* End of output.h */ #endif - - - diff --git a/src/sp65/palette.c b/src/sp65/palette.c index b407b365c..333843af0 100644 --- a/src/sp65/palette.c +++ b/src/sp65/palette.c @@ -138,6 +138,3 @@ void DumpPalette (FILE* F, const Palette* P) (((unsigned long) C->R) << 0)); } } - - - diff --git a/src/sp65/palette.h b/src/sp65/palette.h index d7180e0f0..61eb6519d 100644 --- a/src/sp65/palette.h +++ b/src/sp65/palette.h @@ -85,6 +85,3 @@ void DumpPalette (FILE* F, const Palette* P); /* End of palette.h */ #endif - - - diff --git a/src/sp65/pcx.c b/src/sp65/pcx.c index 51767c931..273ad8cf0 100644 --- a/src/sp65/pcx.c +++ b/src/sp65/pcx.c @@ -153,10 +153,10 @@ static PCXHeader* ReadPCXHeader (FILE* F, const char* Name) P->Compressed, Name); } /* We support: - * - one plane with either 1 or 8 bits per pixel - * - three planes with 8 bits per pixel - * - four planes with 8 bits per pixel (does this exist?) - */ + ** - one plane with either 1 or 8 bits per pixel + ** - three planes with 8 bits per pixel + ** - four planes with 8 bits per pixel (does this exist?) + */ if (!((P->BPP == 1 && P->Planes == 1) || (P->BPP == 8 && (P->Planes == 1 || P->Planes == 3 || P->Planes == 4)))) { /* We could support others, but currently we don't */ @@ -326,8 +326,8 @@ Bitmap* ReadPCXFile (const Collection* A) } /* One plane means we have a palette which is either part of the header - * or follows. - */ + ** or follows. + */ if (P->PalInfo == 0) { /* Create the monochrome palette */ @@ -440,6 +440,3 @@ Bitmap* ReadPCXFile (const Collection* A) /* Return the bitmap */ return B; } - - - diff --git a/src/sp65/pcx.h b/src/sp65/pcx.h index c288a2514..038a947ba 100644 --- a/src/sp65/pcx.h +++ b/src/sp65/pcx.h @@ -60,6 +60,3 @@ Bitmap* ReadPCXFile (const Collection* A); /* End of pcx.h */ #endif - - - diff --git a/src/sp65/pixel.h b/src/sp65/pixel.h index f313ff302..3684b5530 100644 --- a/src/sp65/pixel.h +++ b/src/sp65/pixel.h @@ -67,6 +67,3 @@ union Pixel { /* End of pixel.h */ #endif - - - diff --git a/src/sp65/raw.c b/src/sp65/raw.c index 871200652..6844fe2c3 100644 --- a/src/sp65/raw.c +++ b/src/sp65/raw.c @@ -52,8 +52,8 @@ StrBuf* GenRaw (const Bitmap* B, const Collection* A attribute ((unused))) /* Generate binary output in raw format. The output is stored in a string - * buffer (which is actually a dynamic char array) and returned. - */ +** buffer (which is actually a dynamic char array) and returned. +*/ { StrBuf* D; unsigned X, Y; @@ -84,6 +84,3 @@ StrBuf* GenRaw (const Bitmap* B, const Collection* A attribute ((unused))) /* Return the converted bitmap */ return D; } - - - diff --git a/src/sp65/raw.h b/src/sp65/raw.h index d4c44f7ea..5e83cea47 100644 --- a/src/sp65/raw.h +++ b/src/sp65/raw.h @@ -55,13 +55,11 @@ StrBuf* GenRaw (const Bitmap* B, const Collection* A); /* Generate binary output in raw format. The output is stored in a string - * buffer (which is actually a dynamic char array) and returned. - */ +** buffer (which is actually a dynamic char array) and returned. +*/ /* End of raw.h */ + #endif - - - diff --git a/src/sp65/vic2sprite.c b/src/sp65/vic2sprite.c index d32a9cc66..3e99ec7b2 100644 --- a/src/sp65/vic2sprite.c +++ b/src/sp65/vic2sprite.c @@ -92,9 +92,9 @@ static enum Mode GetMode (const Collection* A) StrBuf* GenVic2Sprite (const Bitmap* B, const Collection* A) /* Generate binary output in VICII sprite format for the bitmap B. The output - * is stored in a string buffer (which is actually a dynamic char array) and - * returned. - */ +** is stored in a string buffer (which is actually a dynamic char array) and +** returned. +*/ { enum Mode M; StrBuf* D; @@ -177,6 +177,3 @@ StrBuf* GenVic2Sprite (const Bitmap* B, const Collection* A) /* Return the converted bitmap */ return D; } - - - diff --git a/src/sp65/vic2sprite.h b/src/sp65/vic2sprite.h index 8b1407e64..b6c839c7c 100644 --- a/src/sp65/vic2sprite.h +++ b/src/sp65/vic2sprite.h @@ -55,15 +55,12 @@ StrBuf* GenVic2Sprite (const Bitmap* B, const Collection* A); /* Generate binary output in VICII sprite format for the bitmap B. The output - * is stored in a string buffer (which is actually a dynamic char array) and - * returned. - */ +** is stored in a string buffer (which is actually a dynamic char array) and +** returned. +*/ /* End of vic2sprite.h */ #endif - - - diff --git a/test/err/cc65091001.c b/test/err/cc65091001.c new file mode 100644 index 000000000..265df0aac --- /dev/null +++ b/test/err/cc65091001.c @@ -0,0 +1,29 @@ +/* + !!DESCRIPTION!! invalid binary operation on pointer, should not compile + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! +*/ + +/* > Gets stuck in an endless loop with -O. */ + +#include <assert.h> +#include <string.h> +typedef unsigned char U8; +char var = 0xf0; +char fn(char bar) +{ + char* ptr = (char*)0xf; + var |= ptr; /* should throw an error here */ + while (var > bar) + var <<= 1; + return 0; +} +int main() { + fn(0x7f); + assert(0); + + printf("it works :)\n"); + + return 0; +} \ No newline at end of file diff --git a/test/err/front.c b/test/err/front.c new file mode 100644 index 000000000..dde8d47ec --- /dev/null +++ b/test/err/front.c @@ -0,0 +1,133 @@ +/* + !!DESCRIPTION!! this code is not supposed to compile + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +main() { + return 0; +} + +nested(a,b) { + if ((a<4 && b == 'r') + || (a == 1 && (b == 'h' || b == 'i')) + || (a == 2 && (b == 'o' || b == 'y')) + ) a=b; +} + +/* type name scope */ + +void s(struct D *d) {} /* this struct D differs from the one below */ +typedef struct D D; +struct D {int x, y;} Dy={0}; +D Dz={1}; +Dfunc(){ + D a; a.y=1; + s(&Dy); /* error */ +} + +/* qualifiers */ + +const a; int b; +const int a, *x; int b, *y; +volatile unsigned z; + +f() { + x = y; + z = z + z; /* should be 2 references to z's r-value */ +} +f1() { + x = &a; + x = &b; + y = &a; /* error */ + y = &b; +} +f2(int **a, int **b) { + f(&x, &y); + **a = 0; + return **b; +} +g(const int *p) { + g(&a); + g(&b); + return *p; +} +h(int *p) { + f(&a); + f(&b); + return *p; +} +h1(const int x, int y) { + h1(a,b); + h1(b,a); + return x + y; +} +h2() { + char *b; const void *p; + p = b; + b = p; /* error (incompatible pointer type) */ +} + +/* static naming */ + +extern int yy; set1() { { static yy=1; yy=2;} yy=4;} +static int yy; set2() { yy=5; {static yy=2; yy=3; }} +static void goo() {} +sss() { int goo; { static int goo();} goo=1;} + +/* +rrr(p) float *p; { extern int xr; + { static float xr; + { extern int *xr; } p=&xr; }} +*/ + +/* local extern */ + +static int ss1; +int ss3; +extern int ss5; +setstatic() { extern int ss1,ss2,ss3,ss4; ss1 = ss2; ss3 = ss4; ss5 = 0;} +static int ss2; +int ss4; +static int ss5; + +/* function prototypes */ + +int fx1(void); +int fx1(); + +/* +int gx1(double x); +*/ +/* int gx1(x) double x; { gx1(&x); } */ /* error */ + +int hx1(); +/* +int hx1(double x,...); */ /* error */ + +/* +int ff1(double x, int *y); +int ff1(x,y) float x; int y[]; {x=y[0];} +*/ + +int gg1(int a); +int gg1(a,b){a=b;} + +int hh1(const int x); +hh1(a) {return a;} + +extern int strcmp(const char*, const char*); +extern void qsort(void*, int, int, int (*)(const void*, const void*)); +extern int cmp(char**a, char**b) { return strcmp(*a,*b); } +sort() { + int n; char *a[100]; + qsort(a, n, sizeof(char*), (int (*)(const void*, const void*))cmp); + qsort(a, n, sizeof(char*), cmp); /* error (incompatible pointer type) */ +} + +/* nasty calls */ + +onearg(){ + int a,b,c,d; + f( ( (a? (b = 1): (c = 2)), (d ? 3 : 4) ) ); /* 1 argument */ +} diff --git a/test/ref/8q.c b/test/ref/8q.c new file mode 100644 index 000000000..afbe41c64 --- /dev/null +++ b/test/ref/8q.c @@ -0,0 +1,47 @@ +/* + !!DESCRIPTION!! solves the "8 queens" chess problem + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +int up[15], down[15], rows[8], x[8]; +void queens(int c); +void print(void); + +int main(void) +{ + int i; + for (i = 0; i < 15; i++) + up[i] = down[i] = 1; + for (i = 0; i < 8; i++) + rows[i] = 1; + queens(0); + return 0; +} + +void queens(int c) +{ + int r; + + for (r = 0; r < 8; r++) + if (rows[r] && up[r-c+7] && down[r+c]) { + rows[r] = up[r-c+7] = down[r+c] = 0; + x[c] = r; + if (c == 7) + print(); + else + queens(c + 1); + rows[r] = up[r-c+7] = down[r+c] = 1; + } +} + +void print(void) +{ + int k; + + for (k = 0; k < 8; k++) { + printf("%c", x[k]+'1'); + if(k<7) printf(" "); + } + printf("\n"); +} diff --git a/test/ref/array.c b/test/ref/array.c new file mode 100644 index 000000000..9d170aaa9 --- /dev/null +++ b/test/ref/array.c @@ -0,0 +1,62 @@ +/* + !!DESCRIPTION!! basic array properties + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +#include <stdio.h> + +#ifndef NO_NEW_PROTOTYPES_FOR_OLD_FUNC_DECL +int f(void); +int g(int x[][4],int *y[]); +#endif + +int x[3][4], *y[3]; + +main() { + int z[3][4]; + int i, j, *p; + + for (i = 0; i < 3; i++) { + for (j = 0; j < 4; j++) + x[i][j] = 1000*i + j; + y[i] = x[i]; + } + f(); + for (i = 0; i < 3; i++) { + y[i] = p = &z[i][0]; + for (j = 0; j < 4; j++) + p[j] = x[i][j]; + } + g(z, y); + + return 0; +} + +f() { + int i, j; + + for (i = 0; i < 3; i++) + for (j = 0; j < 4; j++) + printf(" %d", x[i][j]); + printf("\n"); + for (i = 0; i < 3; i++) + for (j = 0; j < 4; j++) + printf(" %d", y[i][j]); + printf("\n"); +} + +g(x, y) +int x[][4], *y[]; +{ + int i, j; + + for (i = 0; i < 3; i++) + for (j = 0; j < 4; j++) + printf(" %d", x[i][j]); + printf("\n"); + for (i = 0; i < 3; i++) + for (j = 0; j < 4; j++) + printf(" %d", y[i][j]); + printf("\n"); +} diff --git a/test/ref/cc65070303.c b/test/ref/cc65070303.c new file mode 100644 index 000000000..c0404dab8 --- /dev/null +++ b/test/ref/cc65070303.c @@ -0,0 +1,38 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! +*/ + +#include <stdio.h> + +typedef signed int TypA[3]; +typedef struct TypB { + TypA Data[2]; +} sTypB; +sTypB Bs[10]; +TypA * APtr; + +int main(int argc, char* argv[]) +{ + Bs[7].Data[1][2]=11; + APtr=&(Bs[7].Data[1]); + printf("Hallo Welt! %i = %i \n",Bs[7].Data[1][2], (*APtr)[2] ); + return 0; +} + +/* +....gives +test.c(20): Error: Incompatible pointer types +for   APtr=&(Bs[7].Data[1]); + +My experience in C is very limited, but as this works both in MSVC and +the 8 bit Z80 compiler i originally used, i guess its an bug in CC65. + +As a workaround, an typecast via  APtr=(TypA*)&(Bs[7].Data[1]); +seems to work. + +greetings, +   Andreas +*/ \ No newline at end of file diff --git a/test/ref/cc65080227.c b/test/ref/cc65080227.c new file mode 100644 index 000000000..4dd454b98 --- /dev/null +++ b/test/ref/cc65080227.c @@ -0,0 +1,37 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! +*/ + +long a; /* must be static life */ +long b; /* must be static life */ + +int main(void) +{ + a = 0x00112200; /* must be immediate pattern is (1stBYTE == 4thBYTE) */ + b = a; + /* b is 0x11112200 ! */ + + printf("b (should be 0x00112200): %08lx\n",b); + + return 0; +} + +/* +[ command line ] + cl65 -c -T -l -O test.c + +[ part of test.lst ] + 000012r 1 ; b = a; + 000012r 1 AD rr rr lda _a+2 + 000015r 1 85 rr sta sreg + 000017r 1 AE rr rr ldx _a+1 + 00001Ar 1 AD rr rr lda _a + 00001Dr 1 8D rr rr sta _b + 000020r 1 8E rr rr stx _b+1 + 000023r 1 A4 rr ldy sreg + 000025r 1 8C rr rr sty _b+2 + 000028r 1 8C rr rr sty _b+3 ; lost 4th BYTE ! +*/ \ No newline at end of file diff --git a/test/ref/cc65080328.c b/test/ref/cc65080328.c new file mode 100644 index 000000000..11ef73514 --- /dev/null +++ b/test/ref/cc65080328.c @@ -0,0 +1,24 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! +*/ + +/* +The following code produces an 'Error: Incompatible pointer types' at +the last line when compiling with snapshot-2.11.9.20080316 without +optimizations. If I remove the struct inside f() it compiles fine ?!? + +Best, Oliver +*/ + +void f(void){struct{int i;}d;} +struct{void(*p)(void);}s={f}; + +int main(void) +{ + printf("it works :)\n"); + + return 0; +} diff --git a/test/ref/cc65090111.c b/test/ref/cc65090111.c new file mode 100644 index 000000000..f515716f7 --- /dev/null +++ b/test/ref/cc65090111.c @@ -0,0 +1,49 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! +*/ + +/* +cc65 doesn't compile this, if i use the "-O"-option. +but it works with "while(!0)"; instead of "for(;;);" + +i'm using cl65 V2.12.9 win + +---- +#include <stdint.h> + +int main(void) +{ + static uint8_t x = 0; + static uint8_t y = 0; + + for (x = 0; x < 16; ++x) + { + y = y + 1; + } + for(;;); +} +*/ + +#include <stdint.h> + +int test(void) +{ + static uint8_t x = 0; + static uint8_t y = 0; + + for (x = 0; x < 16; ++x) + { + y = y + 1; + } + for(;;); +} + +int main(void) +{ + printf("it works :)\n"); + + return 0; +} diff --git a/test/ref/cc65090124.c b/test/ref/cc65090124.c new file mode 100644 index 000000000..fef22268f --- /dev/null +++ b/test/ref/cc65090124.c @@ -0,0 +1,61 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! +*/ + +/* +there is a bug in the preprocessor (i think) ... the following works +(compiles) correctly: + +unsigned long fs,fd,a; + +unsigned long _func(unsigned long x,unsigned long y) +{ + return 0; +} + +int main(void) +{ + fs=(_func((fd/a),(_func(2,0x0082c90f)))); +} + +now if i wrap _func into a macro like this: + +#define func(x,y) _func(x,y) + +int main(void) +{ + fs=(func((fd/a),(func(2,0x0082c90f)))); +} + +i get "Error: `)' expected" on that line. (this is with the snapshot, freshly +compiled 5 minutes ago) +*/ + +unsigned long fs,fd,a; + +unsigned long _func1(unsigned long x,unsigned long y) +{ + return 0; +} + +int test1(void) +{ + fs=(_func1((fd/a),(_func1(2,0x0082c90f)))); +} + +#define func(x,y) _func1(x,y) + +int test2(void) +{ + fs=(func((fd/a),(func(2,0x0082c90f)))); +} + +int main(void) +{ + printf("it works :)\n"); + + return 0; +} diff --git a/test/ref/cc65090726.c b/test/ref/cc65090726.c new file mode 100644 index 000000000..fb4773afb --- /dev/null +++ b/test/ref/cc65090726.c @@ -0,0 +1,46 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! +*/ + +struct Record { + struct Record *PtrComp; + int x; +}; + +typedef struct Record RecordType; +typedef RecordType *RecordPtr; + +void Proc3(RecordPtr *PtrParOut) +{ + /* whatever */ +} + +void Proc1(RecordPtr PtrParIn) +{ +#define NextRecord (*(PtrParIn->PtrComp)) + Proc3((RecordPtr *)NextRecord.PtrComp); + Proc3(&NextRecord.PtrComp); + Proc3(&PtrParIn->PtrComp->PtrComp); + +#ifdef CAST_STRUCT_PTR + Proc3((RecordPtr *) PtrParIn->PtrComp->PtrComp); + Proc3((RecordPtr *) (*(PtrParIn->PtrComp)).PtrComp); + Proc3((RecordPtr *) NextRecord.PtrComp); +#else + Proc3(PtrParIn->PtrComp->PtrComp); + Proc3((*(PtrParIn->PtrComp)).PtrComp); + Proc3(NextRecord.PtrComp); +#endif + +#undef NextRecord +} + +int main(void) +{ + printf("it works :)\n"); + + return 0; +} diff --git a/test/ref/cc65090910.c b/test/ref/cc65090910.c new file mode 100644 index 000000000..c8e5ce934 --- /dev/null +++ b/test/ref/cc65090910.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! optimizer bug + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Oliver Schmidt +*/ + +/* +After spending a "little" time I finally succeeded in isolating an +(maybe THE) optimizer bug causing Contiki to fail. + +From my user perspective it is very interesting that the bug shows up +with compiler option -O but does _not_ show up with -Oi. +*/ + +unsigned htons(unsigned val) +{ + return (((unsigned) (val)) << 8) | (((unsigned) (val)) >> 8); +} + +int main(void) +{ + printf("%x -> %x\n", 0x1234, htons(0x1234) & 0xffff); + + return 0; +} diff --git a/test/ref/cc65090913.c b/test/ref/cc65090913.c new file mode 100644 index 000000000..a319fec50 --- /dev/null +++ b/test/ref/cc65090913.c @@ -0,0 +1,31 @@ +/* + !!DESCRIPTION!! optimizer bug + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Oliver Schmidt +*/ + +/* +> I found the problem and fixed it. cc65 treated a label as a statement, but +> the standard says, that a label is part of a statement. In a loop without +> curly braces like +> +> while (foo < bar) +> label: ++foo; +> +> the following statement is the one that is looped over - and because cc65 +> treated just the label as a statement, it created code that looped forever. + +*/ + +int foo=0,bar=2; + +int main(void) +{ + while(foo<bar) + label: ++foo; + + printf("foo: %d bar: %d\n",foo,bar); + + return 0; +} diff --git a/test/ref/cc65091007.c b/test/ref/cc65091007.c new file mode 100644 index 000000000..1c69e02f9 --- /dev/null +++ b/test/ref/cc65091007.c @@ -0,0 +1,27 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Johan Kotlinski +*/ + +/* +This produces the compiler error "test.c(9): Error: Assignment to const" +Shouldn't be an error, should it? baz is const, bar isn't. +*/ + +typedef struct { + char foo; +} Bar; + +int main() { + Bar bar; + Bar* const baz = &bar; + + baz->foo = 1; + + printf("it works :)\n"); + + return 0; +} + diff --git a/test/ref/cc65091022.c b/test/ref/cc65091022.c new file mode 100644 index 000000000..222253992 --- /dev/null +++ b/test/ref/cc65091022.c @@ -0,0 +1,20 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Johan Kotlinski +*/ + +/* +...gives "test.c(2): Error: Variable `foo' has unknown size" using -Cl. +Is it really unknown? + +cc65 V2.13.0, SVN version: 4384 +*/ + +int main() { + char foo[] = { 0 }; + printf("it works :)\n"); + + return 0; +} diff --git a/test/ref/cc65101102.c b/test/ref/cc65101102.c new file mode 100644 index 000000000..4faa7c12b --- /dev/null +++ b/test/ref/cc65101102.c @@ -0,0 +1,56 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Marc 'BlackJack' Rintsch +*/ + +/* +Compiler is build from cc65-snapshot-2.13.9.20101031 sources. + +Expected results and also what I get from this without any optimisations +are: 48663 and 49218 + +When I turn on ``-O``: 58096 and 58096. After swapping the two variable +declaration lines in `calculate_checksum()` the results are correct +with ``-O``. + +But with ``--O --static-locals`` the results are incorrect again (31757 +and 15408). ``--static-locals`` alone works though. +*/ + +#include <stdio.h> +#include <stdint.h> + +// uint16_t __fastcall__ calculate_checksum(uint8_t *block); +uint8_t block[256]; + +uint16_t calculate_checksum(uint8_t *block) +{ + uint16_t i, result = 0xffff; + uint8_t j; + + for (i = 0; i < 256; ++i) { + result ^= block[i] << 8; + for (j = 0; j < 8; ++j) { + if (result & (1 << 15)) { + result = (result << 1) ^ 0x1021; + } else { + result <<= 1; + } + } + } + return ~result; +} + +int main(void) +{ + uint16_t i; + + printf("zeroes: %u\n", calculate_checksum(block)); + for (i = 0; i < 256; ++i) block[i] = i; + printf("0..255: %u\n", calculate_checksum(block)); + + return 0; +} + diff --git a/test/ref/cc65101209.c b/test/ref/cc65101209.c new file mode 100644 index 000000000..c14543640 --- /dev/null +++ b/test/ref/cc65101209.c @@ -0,0 +1,38 @@ +/* + !!DESCRIPTION!! mod operator bug + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! marcas +*/ + +#include <stdlib.h> +#include <stdio.h> + +int main(void) { + int tmp; + + for (tmp = 0; tmp<=12345; tmp++) + if (!(tmp%1000)) printf("%d mod 1000 is %d\n", tmp, tmp%1000); + + return 0; +} + +/* +results in (vice x64) +0 mod 1000 is 0 +232 mod 1000 is 0 +1000 mod 1000 is 0 + +Interesting: + + 1000 = $3E8 + 232 = $E8 + +So testing with 999 gives: + +0 mod 999 is 0 +231 mod 999 is 0 +999 mod 999 is 0 + +This seems to be systematic. +*/ \ No newline at end of file diff --git a/test/ref/cc65101216.c b/test/ref/cc65101216.c new file mode 100644 index 000000000..eaaf0b3e4 --- /dev/null +++ b/test/ref/cc65101216.c @@ -0,0 +1,27 @@ +/* + !!DESCRIPTION!! division bug + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Stefan Wessels +*/ + +/* +The output from the code below is: +a / b = 6 + +Shouldn't that be 0? +*/ + +#include <stdio.h> +#define b 10000 +char a; +int main() +{ + char c; + + a = 100; + c = a / b; + printf("a / b = %d", c); + + return 0; +} \ No newline at end of file diff --git a/test/ref/cc65110210.c b/test/ref/cc65110210.c new file mode 100644 index 000000000..2c7853556 --- /dev/null +++ b/test/ref/cc65110210.c @@ -0,0 +1,55 @@ +/* + !!DESCRIPTION!! linker bug + !!ORIGIN!! testsuite + !!LICENCE!! public domain +*/ + +/* +with SVN version: 4973M + +$ cl65 -v -o test.prg tests/cc65110210.c +Opened include file `/usr/local/lib/cc65/include/stdio.h' +Opened include file `/usr/local/lib/cc65/include/stddef.h' +Opened include file `/usr/local/lib/cc65/include/stdarg.h' +Opened include file `/usr/local/lib/cc65/include/limits.h' +0 errors, 0 warnings +Opened output file `tests/cc65110210.s' +Wrote output to `tests/cc65110210.s' +Closed output file `tests/cc65110210.s' +cl65: Subprocess `ld65' aborted by signal 11 + +*/ + +/* #define STANDALONE */ + +#include <stdio.h> +#include <limits.h> + +#ifdef STANDALONE + +#define NO_IMPLICIT_FUNCPTR_CONV + +#define OPENTEST() +#define CLOSETEST() + +#else + +#endif + +#ifdef NO_IMPLICIT_FUNCPTR_CONV +void (*p1func)(void); +#else +void (*p1func)(); +#endif + +void func(void) +{ + (*p1func)(); +} + +int main(void) +{ + printf("it works :)\n"); + + return (0); +} diff --git a/test/ref/cc65110211.c b/test/ref/cc65110211.c new file mode 100644 index 000000000..76b3f4a70 --- /dev/null +++ b/test/ref/cc65110211.c @@ -0,0 +1,80 @@ +/* + !!DESCRIPTION!! unreachable code related bug + !!ORIGIN!! Testsuite + !!LICENCE!! Public Domain +*/ + +/* + test2 and test3 will result in an endless loop (SVN version: 4974M) +*/ + +#define OPENTEST() +#define CLOSETEST() + +static char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +int test1(void) +{ + int res; + unsigned char *p; + + p = upper; + res = 0; + + while(*p) { + if(*p < 0) { + res = 1; + } + p++; + } + + printf("test1:ok\n"); + return res; +} + +int test2(void) +{ + int res; + unsigned char *p; + + p = upper; + res = 0; + + while(*p) { + if(*p++ < 0) { + res = 1; + } + } + + printf("test2:ok\n"); + return res; +} + +int test3(void) +{ + int res; + unsigned char *p; + + p = upper; + res = 0; + + while(*p) { + if(*++p < 0) { + res = 1; + } + } + + printf("test3:ok\n"); + return res; +} + +int main(int n,char **args) +{ + test1(); + test2(); + test3(); + + printf("it works :)\n"); + + return 0; +} diff --git a/test/ref/cf.c b/test/ref/cf.c new file mode 100644 index 000000000..951f31295 --- /dev/null +++ b/test/ref/cf.c @@ -0,0 +1,181 @@ +/* + !!DESCRIPTION!! print character frequencies + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +/* + cf - print character frequencies +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> + +#define INFILE "cf.in" + +#ifndef NO_FLOATS +float f[0x100]; +#else +signed f[0x100]; +#endif + +#ifdef NO_OLD_FUNC_DECL +int main(int argc,char **argv) +#else +main(argc, argv) +int argc; +char *argv[]; +#endif +{ + int i, c, nc; +#ifndef NO_FLOATS + float cutoff, atof(); +#else + signed cutoff; +#endif + + if (argc <= 1) +#ifndef NO_FLOATS + cutoff = 0.0; +#else + cutoff = 0; +#endif + else +#ifndef NO_FLOATS + cutoff = atof(argv[1])/100; +#else + cutoff = atoi(argv[1])/100; +#endif + for (i = 0; i < 0x100; ) + { +#ifndef NO_FLOATS + f[i++] = 0.0; +#else + f[i++] = 0; +#endif + } + + printf("input:\n\n"); + + nc = 0; + while ((c = GETCHAR()) != -1) + { +/* printf("[%02x]",c); */ + printf("%c",c); + f[c] += 1; + nc++; + } + printf("\n\ncount: %d\n\n",nc); + + /* + now try to print a report in a way so that + the order is somewhat independent from the + target character set + */ + + printf("a-z char:freq\n\n"); + + /* first round ... lowercase characters */ + for (i = 0; i < 0x100; ++i) + { + if ((f[i]) && ((f[i]/nc) >= cutoff)) + { + if ((i >= 'a') && (i <= 'z')) + { + printf("%c", i); +#ifndef NO_FLOATS + printf(":%.1f\n", 100*f[i]/nc); +#else + printf(":%d\n", 100*f[i]/nc); +#endif + f[i]=0; + } + } + } + + printf("A-Z char:freq\n\n"); + + /* second round ... uppercase characters */ + for (i = 0; i < 0x100; ++i) + { + if ((f[i]) && ((f[i]/nc) >= cutoff)) + { + if ((i >= 'A') && (i <= 'Z')) + { + printf("%c", i); +#ifndef NO_FLOATS + printf(":%.1f\n", 100*f[i]/nc); +#else + printf(":%d\n", 100*f[i]/nc); +#endif + f[i]=0; + } + } + } + + printf("0-9 char:freq\n\n"); + + /* third round ... numbers */ + for (i = 0; i < 0x100; ++i) + { + if ((f[i]) && ((f[i]/nc) >= cutoff)) + { + if ((i >= '0') && (i <= '9')) + { + printf("%c", i); +#ifndef NO_FLOATS + printf(":%.1f\n", 100*f[i]/nc); +#else + printf(":%d\n", 100*f[i]/nc); +#endif + f[i]=0; + } + } + } + + printf("isprint char:freq\n\n"); + + /* second last round ... remaining printable characters */ + for (i = 0; i < 0x100; ++i) + { + if ((f[i]) && ((f[i]/nc) >= cutoff)) + { + if(isprint(i)) + { + printf("%c", i); +#ifndef NO_FLOATS + printf(":%.1f\n", 100*f[i]/nc); +#else + printf(":%d\n", 100*f[i]/nc); +#endif + f[i]=0; + } + } + } + + printf("rest char:freq\n\n"); + + /* last round ... remaining non printable characters */ + for (i = 0; i < 0x100; ++i) + { + if ((f[i]) && ((f[i]/nc) >= cutoff)) + { + if(i=='\n') + { + printf("newline"); + } + else + { + printf("%03o", i); + } +#ifndef NO_FLOATS + printf(":%.1f\n", 100*f[i]/nc); +#else + printf(":%d\n", 100*f[i]/nc); +#endif + } + } + + return 0; +} diff --git a/test/ref/charconst.c b/test/ref/charconst.c new file mode 100644 index 000000000..1aa9f8e3f --- /dev/null +++ b/test/ref/charconst.c @@ -0,0 +1,59 @@ +/* + !!DESCRIPTION!! check if character constants are translated correctly + !!ORIGIN!! cc65 bug report + !!LICENCE!! Public Domain +*/ + +#include <limits.h> +#include <ctype.h> + +void backslash(unsigned char c) +{ + printf("%c : ",c); + + switch (c) + { + case 'b': + c = '\b'; + case 'f': + c = '\f'; + case 'n': + c = '\n'; + case 'r': + c = '\r'; + case 't': + c = '\t'; + case 'v': + #ifndef NO_BACKSLASH_V + c = '\v'; + #else + c = 0x0b; + #endif + } + + if(!isprint(c)) + { + printf("ok.\n"); + } + else + { + printf("failed.\n"); + } +} + +void testbackslash(void) +{ + backslash('b'); + backslash('f'); + backslash('n'); + backslash('r'); + backslash('t'); + backslash('v'); +} + +int main(void) +{ + testbackslash(); + + return 0; +} diff --git a/test/ref/charset.c b/test/ref/charset.c new file mode 100644 index 000000000..59b7c4c54 --- /dev/null +++ b/test/ref/charset.c @@ -0,0 +1,93 @@ +/* + !!DESCRIPTION!! basic ASCII character test + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Groepaz/Hitmen +*/ + +#include <stdio.h> + +#if 0 + +/* this kind of line-continuation for strings doesnt work properly for cc65 */ + +const unsigned char characters[]={ + /*0123456789abcdef0123456789abcdef*/ + /* iso646-us control-characters */ + " " /* 00-1f */ + /* iso646-us printable characters */ + " !\"#$%&'()*+,-./" /* 20-2f !"#$%&'()*+,-./ */ + "0123456789" /* 30-39 0123456789 */ + ":;<=>?@" /* 3a-40 :;<=>?@ */ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* 41-5a A-Z */ + "[\\]^_`" /* 5b-60 [\]^_` */ + "abcdefghijklmnopqrstuvwxyz" /* 61-7a a-z */ + "{|}~ " /* 7b-7f {|}~ */ + /* iso8859-15 extended characters */ +}; + +#endif + +const unsigned char characters[]={ + /*0123456789abcdef0123456789abcdef*/ + /* iso646-us control-characters */ + /* 00-1f */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /* iso646-us printable characters */ + /* 20-2f !"#$%&'()*+,-./ */ + ' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/', + /* 30-39 0123456789 */ + '0','1','2','3','4','5','6','7','8','9', + /* 3a-40 :;<=>?@ */ + ':',';','<','=','>','?','@', + /* 41-5a A-Z */ + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', + /* 5b-60 [\]^_` */ + '[','\\',']','^','_','`', + /* 61-7a a-z */ + 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', + /* 7b-7f {|}~ */ + '{','|','}','~',' ' + /* iso8859-15 extended characters */ +}; + +void printchars(unsigned char a,unsigned char b){ + for(b++;a!=b;a++) +/* printf("%02x ",a); */ +/* printf("%02x ",characters[a]); */ + printf("%c",characters[a]); + printf("\n"); +} + +int main(void) { + printf("characters:\n\n"); + printchars(0x61,0x7a); + printchars(0x41,0x5a); + printf("numbers:\n\n"); + printchars(0x30,0x39); + printf("other:\n\n"); + printchars(0x20,0x2f); + /*printchars(0x3a,0x40);*/ + printchars(0x3a,0x3f); + /*printchars(0x5b,0x60);*/ + /*printchars(0x7b,0x7f);*/ + printf("\n\n"); + printf("slash: '%c'\n",'/'); + printf("backslash: '%c'\n",'\\'); + printf("curly braces open: '%c'\n",'{'); + printf("curly braces close: '%c'\n",'}'); + printf("square braces open: '%c'\n",'['); + printf("square braces close: '%c'\n",']'); + printf("underscore: '%c'\n",'_'); + printf("tilde: '%c'\n",'~'); + printf("pipe: '%c'\n",'|'); + printf("apostroph: '%c'\n",'\''); + printf("single quote '%c'\n",'`'); + printf("xor '%c'\n",'^'); + printf("at '%c'\n",'@'); + + return 0; +} diff --git a/test/ref/cvt.c b/test/ref/cvt.c new file mode 100644 index 000000000..ed7b6084e --- /dev/null +++ b/test/ref/cvt.c @@ -0,0 +1,53 @@ +/* + !!DESCRIPTION!! type conversion + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +signed char c; +signed short s; +signed int i; +signed long int l; +unsigned char C; +unsigned short S; +unsigned int I; +unsigned long int L; + +#ifdef NO_FLOATS +signed long f; +signed long d; +signed long D; +#else +float f; +double d; +long double D; +#endif + +void *p; +void (*P)(void); + +void print(void) { + #ifdef NO_FLOATS + printf("%d %d %d %ld %u %u %u %lu %ld.000000 %ld.000000 %ld.000000\n",c,s,i,l,C,S,I,L,f,d,D); + #else + printf("%d %d %d %ld %u %u %u %lu %f %f %lf \n",c,s,i,l,C,S,I,L,f,d,D ); + #endif +} + +main() { + c= 1; s=c;i=c;l=c;C=c;S=c;I=c;L=c; f=c;d=c;D=c; print(); + s= 2; c=s; i=s;l=s;C=s;S=s;I=s;L=s; f=s;d=s;D=s; print(); + i= 3; c=i;s=i; l=i;C=i;S=i;I=i;L=i; f=i;d=i;D=i; print(); + l= 4; c=l;s=l;i=l; C=l;S=l;I=l;L=l; f=l;d=l;D=l; print(); + C= 5; c=C;s=C;i=C;l=C; S=C;I=C;L=C; f=C;d=C;D=C; print(); + S= 6; c=S;s=S;i=S;l=S;C=S; I=S;L=S; f=S;d=S;D=S; print(); + I= 7; c=I;s=I;i=I;l=I;C=I;S=I; L=I; f=I;d=I;D=I; print(); + L= 8; c=L;s=L;i=L;l=L;C=L;S=L;I=S; f=L;d=L;D=L; print(); + f= 9; c=f;s=f;i=f;l=f;C=f;S=f;I=f;L=f; d=f;D=f; print(); + d=10; c=d;s=d;i=d;l=d;C=d;S=d;I=d;L=d;f=d; D=d; print(); + D=11; c=D;s=D;i=D;l=D;C=D;S=D;I=D;L=D;f=D;d=D; print(); + + p=0; p=0L; p=0U; p=0UL; p=P; + P=0; P=0L; P=0U; P=0UL; P=p; + return 0; +} diff --git a/test/ref/dijkstra.c b/test/ref/dijkstra.c new file mode 100644 index 000000000..168324f68 --- /dev/null +++ b/test/ref/dijkstra.c @@ -0,0 +1,369 @@ +/* + !!DESCRIPTION!! Dijkstras Algorithm + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Groepaz/Hitmen +*/ + +#include <stdio.h> +#include <stdlib.h> + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#define DIJKSTRA_INFINITY (0xffff) + +#define DIJKSTRA_FLAG_UNVISITED (0x0) +/* +#define DIJKSTRA_FLAG_OPEN (0x1) +*/ +#define DIJKSTRA_FLAG_CLOSED (0x2) + +typedef struct _DIJKSTRA_EDGE { + struct _DIJKSTRA_NODE *NEXTNODE; + unsigned short DISTANCE; +} DIJKSTRA_EDGE; + +typedef struct _DIJKSTRA_NODE { + DIJKSTRA_EDGE *EDGES; + unsigned char TAG; + unsigned char FLAG; + unsigned short MINDIST; + struct _DIJKSTRA_NODE *PREVIOUS; +} DIJKSTRA_NODE; + +/* init with graph, startnode, working-array */ +void Dijkstra_Init(const DIJKSTRA_NODE *graph,DIJKSTRA_NODE *start,DIJKSTRA_NODE *nodes); + +/* call main algo with working-array */ +void Dijkstra_Search(DIJKSTRA_NODE *nodes); + +/* print path, call with working-array, endnode */ +void Dijkstra_Path(DIJKSTRA_NODE *nodes,DIJKSTRA_NODE *end); + +/* print table, call with working-array, current node */ +void Dijkstra_Table(DIJKSTRA_NODE *nodes,DIJKSTRA_NODE *current); + +/* internally used routines */ + +unsigned short Dijkstra_Distance(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode); +void Dijkstra_Relax(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode); +DIJKSTRA_NODE *Dijkstra_NextCheapest(DIJKSTRA_NODE *graph); +unsigned short Dijkstra_CountUnvisited(DIJKSTRA_NODE *graph); + +/* define to get printed info as the algorithm proceeds */ +#define DIJKSTRA_PRINTDEBUG + +/* the working array */ +DIJKSTRA_NODE mynodes[0x10]; + +/* test-network data (mypoints and myedges) */ + +const DIJKSTRA_EDGE myedges_A[]={ + {&mynodes[1],1}, + {NULL} +}; +const DIJKSTRA_EDGE myedges_B[]={ + {&mynodes[0],1}, + {&mynodes[2],2}, + {&mynodes[3],1}, + {NULL} +}; +const DIJKSTRA_EDGE myedges_C[]={ + {&mynodes[1],2}, + {&mynodes[5],1}, + {NULL} +}; +const DIJKSTRA_EDGE myedges_D[]={ + {&mynodes[1],1}, + {&mynodes[4],1}, + {NULL} +}; +const DIJKSTRA_EDGE myedges_E[]={ + {&mynodes[6],1}, + {NULL} +}; +const DIJKSTRA_EDGE myedges_F[]={ + {&mynodes[7],1}, + {NULL} +}; +const DIJKSTRA_EDGE myedges_G[]={ + {&mynodes[8],1}, + {&mynodes[7],4}, + {NULL} +}; +const DIJKSTRA_EDGE myedges_H[]={ + {&mynodes[9],1}, + {&mynodes[6],4}, + {NULL} +}; +const DIJKSTRA_EDGE myedges_I[]={ + {&mynodes[10],5}, + {NULL} +}; +const DIJKSTRA_EDGE myedges_J[]={ + {&mynodes[10],1}, + {NULL} +}; +const DIJKSTRA_EDGE myedges_K[]={ + {&mynodes[11],1}, + {NULL} +}; +const DIJKSTRA_EDGE myedges_L[]={ + {&mynodes[10],1}, + {NULL} +}; + +const DIJKSTRA_NODE mypoints[]={ + {(DIJKSTRA_EDGE *)&myedges_A[0],'A'}, + {(DIJKSTRA_EDGE *)&myedges_B[0],'B'}, + {(DIJKSTRA_EDGE *)&myedges_C[0],'C'}, + {(DIJKSTRA_EDGE *)&myedges_D[0],'D'}, + {(DIJKSTRA_EDGE *)&myedges_E[0],'E'}, + {(DIJKSTRA_EDGE *)&myedges_F[0],'F'}, + {(DIJKSTRA_EDGE *)&myedges_G[0],'G'}, + {(DIJKSTRA_EDGE *)&myedges_H[0],'H'}, + {(DIJKSTRA_EDGE *)&myedges_I[0],'I'}, + {(DIJKSTRA_EDGE *)&myedges_J[0],'J'}, + {(DIJKSTRA_EDGE *)&myedges_K[0],'K'}, + {(DIJKSTRA_EDGE *)&myedges_L[0],'L'}, + {NULL} +}; + +/* + * initialize working-array + */ + +void Dijkstra_Init(const DIJKSTRA_NODE *graph,DIJKSTRA_NODE *start,DIJKSTRA_NODE *nodes) { + while(graph->EDGES!=NULL) { + nodes->EDGES=graph->EDGES; + nodes->TAG=graph->TAG; + nodes->FLAG=DIJKSTRA_FLAG_UNVISITED; + nodes->MINDIST=DIJKSTRA_INFINITY; + nodes->PREVIOUS=NULL; + + graph++;nodes++; + + } +/* + start->FLAG=DIJKSTRA_FLAG_OPEN; + start->PREVIOUS=NULL; + */ + start->MINDIST=0; +} + +/* + * compute the distance between two Nodes in the Graph + */ + +unsigned short Dijkstra_Distance(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode){ +DIJKSTRA_EDGE *edge; + + edge=currnode->EDGES; + + while(edge!=NULL) { + if(edge->NEXTNODE == nextnode){ + return(edge->DISTANCE); + } + + edge++; + + } + + return(DIJKSTRA_INFINITY); +} + +/* + * 'relax' one node against another + */ + +void Dijkstra_Relax(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode){ +unsigned short newdist; + +#ifdef DIJKSTRA_PRINTDEBUG + printf("relax >%c< to >%c<\n",currnode->TAG,nextnode->TAG); +#endif + + newdist=currnode->MINDIST+Dijkstra_Distance(currnode,nextnode); + + if((nextnode->MINDIST)>(newdist)){ + nextnode->MINDIST=newdist; + nextnode->PREVIOUS=currnode; + + } +} + +/* + * find the yet unprocessed Node with the currently + * smallest estimated MINDIST + */ + +DIJKSTRA_NODE *Dijkstra_NextCheapest(DIJKSTRA_NODE *graph){ +unsigned short mindist; +DIJKSTRA_NODE *node; + + node=NULL; + mindist=DIJKSTRA_INFINITY; + + while(graph->EDGES!=NULL) { + if(graph->FLAG!=DIJKSTRA_FLAG_CLOSED){ + if(!(mindist<graph->MINDIST)){ + mindist=graph->MINDIST; + node=graph; + } + } + + graph++; + + } + +#ifdef DIJKSTRA_PRINTDEBUG + if(node!=NULL) printf("next cheapest Node: >%c<\n",node->TAG); +#endif + + return(node); +} + +/* + * count number of Nodes that are left for processing + */ + +unsigned short Dijkstra_CountUnvisited(DIJKSTRA_NODE *graph){ +unsigned short num; + + num=0; + + while(graph->EDGES!=NULL) { + if(graph->FLAG!=DIJKSTRA_FLAG_CLOSED){ + num++; + } + + graph++; + + } + + return(num); +} + +/* + * Dijkstra-Algorithmus main processing + */ + +void Dijkstra_Search(DIJKSTRA_NODE *graph){ +DIJKSTRA_NODE *currnode,*nextnode; +DIJKSTRA_EDGE *edge; + + currnode=graph; + + while(Dijkstra_CountUnvisited(graph)>0){ + edge=currnode->EDGES; + while(edge->NEXTNODE!=NULL){ + nextnode=edge->NEXTNODE; + if(nextnode->FLAG!=DIJKSTRA_FLAG_CLOSED){ +/* + nextnode->FLAG=DIJKSTRA_FLAG_OPEN; + */ + Dijkstra_Relax(currnode,nextnode); +#ifdef DIJKSTRA_PRINTDEBUG + Dijkstra_Table(graph,currnode); +#endif + } + edge++; + } + currnode=Dijkstra_NextCheapest(graph); + currnode->FLAG=DIJKSTRA_FLAG_CLOSED; + } +} + +/* + * print the Path from start Node to one other Node + */ + +void Dijkstra_Path(DIJKSTRA_NODE *graph,DIJKSTRA_NODE *end){ +DIJKSTRA_NODE *currnode,*nextnode; + + printf("Path from >%c< to >%c< : ",end->TAG,graph->TAG); + + currnode=end; + + while(currnode->PREVIOUS!=NULL){ + printf(">%c< ",currnode->TAG); + currnode=currnode->PREVIOUS; + } + + printf(">%c<\n",currnode->TAG); +} + +/* + * print working-array as a table + */ + +void Dijkstra_Table(DIJKSTRA_NODE *graph,DIJKSTRA_NODE *current){ +DIJKSTRA_NODE *g; + + printf("----------------------\n"); + + printf("Node |"); + g=graph;while(g->EDGES!=NULL) { + printf("-->%c<-|",g->TAG); + g++; + } + printf("\n"); + + printf("MinDist |"); + g=graph;while(g->EDGES!=NULL) { + printf(" %5u|",g->MINDIST); + g++; + } + printf("\n"); + + printf("Flag |"); + g=graph;while(g->EDGES!=NULL) { + switch(g->FLAG){ +/* + case DIJKSTRA_FLAG_OPEN: + printf("opened|"); + break; + */ + case DIJKSTRA_FLAG_CLOSED: + printf("closed|"); + break; + default: + if(g->MINDIST!=DIJKSTRA_INFINITY){ + printf("opened|"); + } else { + printf("------|"); + } + break; + } + g++; + } + printf("\n"); + + printf("Previous|"); + g=graph;while(g->EDGES!=NULL) { + if(g->PREVIOUS==NULL) + printf("------|"); + else + printf(" (%c) |",g->PREVIOUS->TAG); + g++; + } + printf("\n"); + + printf("----------------------\n"); +} + +int main(void) +{ + /* init with graph, startnode, working-array */ + Dijkstra_Init(&mypoints[0],&mynodes[0],&mynodes[0]); + /* call main algo with working-array */ + Dijkstra_Search(&mynodes[0]); + /* print table, call with working-array, endnode */ + Dijkstra_Table(&mynodes[0],&mynodes[11]); + /* print path, call with working-array, endnode */ + Dijkstra_Path(&mynodes[0],&mynodes[11]); + + return 0; +} diff --git a/test/ref/divmod.c b/test/ref/divmod.c new file mode 100644 index 000000000..68a0198e1 --- /dev/null +++ b/test/ref/divmod.c @@ -0,0 +1,38 @@ +/* + !!DESCRIPTION!! div/mod test + !!ORIGIN!! + !!LICENCE!! public domain +*/ + +#include <stdio.h> + +void printc(signed char a,signed char b){ +signed char x=a/b,y=a%b,z=a*b; + printf("%3d,%3d is %3d,%3d,%3d\n",a,b,x,y,z); +} +void prints(short a,short b){ +short x=a/b,y=a%b,z=a*b; + printf("%3d,%3d is %3d,%3d,%3d\n",a,b,x,y,z); +} +void printl(long a,long b){ +long x=a/b,y=a%b,z=a*b; + printf("%3ld,%3ld is %3ld,%3ld,%3ld\n",a,b,x,y,z); +} + +int main(void) { + printl( 3,-2); + printl(-3,-2); + printl(-3, 2); + printl( 3, 2); + printf("-\n"); + prints( 3,-2); + prints(-3,-2); + prints(-3, 2); + prints( 3, 2); + printf("-\n"); + printc( 3,-2); + printc(-3,-2); + printc(-3, 2); + printc( 3, 2); + return 0; +} diff --git a/test/ref/fields.c b/test/ref/fields.c new file mode 100644 index 000000000..794a81924 --- /dev/null +++ b/test/ref/fields.c @@ -0,0 +1,92 @@ +/* + !!DESCRIPTION!! bitfield test + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +#ifdef NO_BITFIELDS + +main() +{ + printf("NO_BITFIELDS\n\r"); +} + +#else + +#ifdef SIZEOF_INT_16BIT + +#ifdef REFCC +#include <stdint.h> +struct foo { + int16_t a; + char b; + int16_t x : 12, y : 4; + int16_t zz : 1, : 0, : 4, z : 3; + char c; +} x = { 1, 2, 3, 4, 5, 6 }; + +struct baz { uint16_t a:2, b:4, c:16;} y = { 7, 8, 9}; +int16_t i = 8; + +#else + +struct foo { + int a; + char b; + int x : 12, y : 4; + int zz : 1, : 0, : 4, z : 3; + char c; +} x = { 1, 2, 3, 4, 5, 6 }; + +struct baz { unsigned int a:2, b:4, c:16;} y = { 7, 8, 9}; +int i = 8; +#endif + +#else +struct foo { + int a; + char b; + int x : 12, y : 4, : 0, : 4, z : 3; + char c; +} x = { 1, 2, 3, 4, 5, 6 }; + +struct baz { unsigned int a:2, b:4, c:32;} y = { 7, 8, 9}; +int i = 16; +#endif + +#ifdef NO_IMPLICIT_FUNC_PROTOTYPES +f1(struct baz *p); +f2(struct baz *p); +#endif + +main() +{ + printf("x = %d b:%d %d %d %d c:%d\n", x.a, x.b, x.x, x.y, x.z, x.c); + printf("y = %d b:%d c:%d\n", y.a, y.b, y.c); + x.y = i; + x.z = 070; + printf("x = %d b:%d %d %d %d c:%d\n", x.a, x.b, x.x, x.y, x.z, x.c); + y.a = 2; + y.c = i; + printf("y = %d b:%d c:%d\n", y.a, y.b, y.c); +#ifdef CAST_STRUCT_PTR + f2((struct baz *)&x); +#else + f2(&x); +#endif + return 0; +} + +f1(struct baz *p) { + p->a = p->b = 0; + if (p->b) + printf("p->b != 0!\n"); + p->a = 0x3; p->b = 0xf; + printf("p->a = 0x%x, p->b = 0x%x\n", p->a, p->b); +} +f2(struct baz *p) { + p->a = (i==0); + p->b = (f1(p),0); +} + +#endif diff --git a/test/ref/hanoi.c b/test/ref/hanoi.c new file mode 100644 index 000000000..234ac41e4 --- /dev/null +++ b/test/ref/hanoi.c @@ -0,0 +1,90 @@ +/* + !!DESCRIPTION!! solves the "towers of hanoi" problem + !!ORIGIN!! BYTE UNIX Benchmarks + !!LICENCE!! Public Domain +*/ + +/******************************************************************************* + * The BYTE UNIX Benchmarks - Release 3 + * Module: hanoi.c SID: 3.3 5/15/91 19:30:20 + * + ******************************************************************************* + * Bug reports, patches, comments, suggestions should be sent to: + * + * Ben Smith, Rick Grehan or Tom Yager + * ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com + * + ******************************************************************************* + * Modification Log: + * $Header: hanoi.c,v 3.5 87/08/06 08:11:14 kenj Exp $ + * August 28, 1990 - Modified timing routines (ty) + * + ******************************************************************************/ + +#define VERBOSE +/*#define USECMDLINE*/ + +#include <stdio.h> +#include <stdlib.h> + +unsigned short iter = 0; /* number of iterations */ +char num[4]; +long cnt; + +int disk=5, /* default number of disks */ + duration=10; /* default time to run test */ + +void mov(unsigned char n,unsigned char f,unsigned char t) +{ +char o; + + if(n == 1) + { + num[f]--; + num[t]++; + } + else + { + o = (6-(f+t)); + mov(n-1,f,o); + mov(1,f,t); + mov(n-1,o,t); + } + + #ifdef VERBOSE + printf("%2d: %2d %2d %2d %2d\n", + (int)iter,(int)num[0],(int)num[1],(int)num[2],(int)num[3]); + #endif +} + +int main(int argc,char **argv) +{ + #ifdef USECMDLINE + if (argc < 2) { + printf("Usage: %s [duration] [disks]\n", argv[0]); + exit(1); + } + else + { + if(argc > 1) duration = atoi(argv[1]); + if(argc > 2) disk = atoi(argv[2]); + } + #endif + + printf("towers of hanoi\ndisks: %d\n\n",disk); + + num[1] = disk; + + #ifdef VERBOSE + printf("%2d: %2d %2d %2d %2d\n", + (int)iter,(int)num[0],(int)num[1],(int)num[2],(int)num[3]); + #endif + + while(num[3]<disk) + { + mov(disk,1,3); + ++iter; + } + + return 0; +} diff --git a/test/ref/ifexpr.c b/test/ref/ifexpr.c new file mode 100644 index 000000000..a60203917 --- /dev/null +++ b/test/ref/ifexpr.c @@ -0,0 +1,36 @@ +/* + !!DESCRIPTION!! if/then, ? operator, compares + !!ORIGIN!! cc65 devel list + !!LICENCE!! Public Domain +*/ + +#include <stdio.h> +#include <limits.h> + +void t1a(void) +{ + int a = -0x5000; + + printf(a < 0x5000 ? "ok\n" : "error\n"); +} + +void t1b(void) +{ + int a = -0x5000; + + if(a<0x5000) + { + printf("ok\n"); + } + else + { + printf("error\n"); + } +} + +int main(void) +{ + t1a();t1b(); + + return 0; +} diff --git a/test/ref/incr.c b/test/ref/incr.c new file mode 100644 index 000000000..adce0e1c0 --- /dev/null +++ b/test/ref/incr.c @@ -0,0 +1,51 @@ +/* + !!DESCRIPTION!! increment/decrement + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +#include <stdio.h> + +int main(void) +{ + printf("disassemble this program to check the generated code.\n"); + return 0; +} + +memchar() { + char x, *p; + + &x, &p; + x = *p++; + x = *++p; + x = *p--; + x = *--p; +} + +memint() { + int x, *p; + + &x, &p; + x = *p++; + x = *++p; + x = *p--; + x = *--p; +} + +regchar() { + register char x, *p; + + x = *p++; + x = *++p; + x = *p--; + x = *--p; +} + +regint() { + register int x, *p; + + x = *p++; + x = *++p; + x = *p--; + x = *--p; +} diff --git a/test/ref/init.c b/test/ref/init.c new file mode 100644 index 000000000..dc3f28a81 --- /dev/null +++ b/test/ref/init.c @@ -0,0 +1,94 @@ +/* + !!DESCRIPTION!! variable initialization + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +/* todo: add back conditional stuff here ! */ + +typedef struct { int codes[3]; char name[6]; } Word; + +#ifdef NO_IMPLICIT_FUNC_PROTOTYPES + +#ifdef NO_OLD_FUNC_DECL +f(); +void g(Word *p); +h(); +#else +f(); +g(); +h(); +#endif + +#endif + +/* +Word words[] = { + 1, 2, 3,"if", + { { 4, 5 }, { 'f', 'o', 'r' } }, + 6, 7, 8, {"else"}, + { { 9, 10, 11,}, 'w', 'h', 'i', 'l', 'e', }, + { 0 }, +}, *wordlist = words; +*/ + +Word words[] = { + {{1, 2, 3},"if"}, + { { 4, 5 }, { 'f', 'o', 'r' } }, + {{6, 7, 8}, "else"}, + { { 9, 10, 11}, {'w', 'h', 'i', 'l', 'e', }}, + {{ 0 }}, +}, *wordlist = words; + +/*int x[][5] = { 1, 2, 3, 4, 0, { 5, 6 }, { 7 } };*/ +int x[][5] = { {1, 2, 3, 4, 0 }, { 5, 6 }, { 7 } }; +int *y[] = { x[0], x[1], x[2], 0 }; + +main() +{ + int i, j; + + for (i = 0; y[i]; i++) { + for (j = 0; y[i][j]; j++) + printf(" %d", y[i][j]); + printf("\n"); + } + f(); + g(wordlist); + return 0; +} + +f() { + static char *keywords[] = {"if", "for", "else", "while", 0, }; + char **p; + + for (p = keywords; *p; p++) + printf("%s\n", *p); +} + +#ifdef NO_OLD_FUNC_DECL +void g(Word *p) +#else +g(p) +Word *p; +#endif +{ + int i; + + for ( ; p->codes[0]; p++) { + for (i = 0; i < sizeof p->codes/sizeof(p->codes[0]); i++) + printf("%d ", p->codes[i]); + printf("%s\n", p->name); + } + h(); +} + +h() +{ + int i; + + for (i = 0; i < sizeof(words)/sizeof(Word); i++) + printf("%d %d %d %s\n", words[i].codes[0], + words[i].codes[1], words[i].codes[2], + &words[i].name[0]); +} diff --git a/test/ref/limits.c b/test/ref/limits.c new file mode 100644 index 000000000..613d6bd09 --- /dev/null +++ b/test/ref/limits.c @@ -0,0 +1,56 @@ +/* + !!DESCRIPTION!! display type limits + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +#include <stdio.h> +#include <limits.h> + +#define SSHRT_MAX SHRT_MAX +#define SINT_MAX INT_MAX +#define SLONG_MAX LONG_MAX + +#define UCHAR_MIN 0 +#define USHRT_MIN 0 +#define SSHRT_MIN SHRT_MIN +#define UINT_MIN 0 +#define SINT_MIN INT_MIN +#define ULONG_MIN 0l +#define SLONG_MIN LONG_MIN + +int main(void) { + printf("CHAR_MAX: 0x%08x=%d\n", CHAR_MAX, CHAR_MAX); + printf("UCHAR_MAX: 0x%08x=%d\n", UCHAR_MAX, UCHAR_MAX); + printf("SCHAR_MAX: 0x%08x=%d\n", SCHAR_MAX, SCHAR_MAX); + + printf("SHRT_MAX: 0x%08x=%d\n", SHRT_MAX, SHRT_MAX); + printf("USHRT_MAX: 0x%08x=%d\n", USHRT_MAX, USHRT_MAX); + printf("SSHRT_MAX: 0x%08x=%d\n", SSHRT_MAX, SSHRT_MAX); + + printf("INT_MAX: 0x%08x=%d\n", INT_MAX, INT_MAX); + printf("UINT_MAX: 0x%08x=%d\n", UINT_MAX, UINT_MAX); + printf("SINT_MAX: 0x%08x=%d\n", SINT_MAX, SINT_MAX); + + printf("LONG_MAX: 0x%08lx=%ld\n", LONG_MAX, LONG_MAX); + printf("ULONG_MAX: 0x%08lx=%ld\n", ULONG_MAX, ULONG_MAX); + printf("SLONG_MAX: 0x%08lx=%ld\n", SLONG_MAX, SLONG_MAX); + + printf("CHAR_MIN: 0x%08x=%d\n", CHAR_MIN, CHAR_MIN); + printf("UCHAR_MIN: 0x%08x=%d\n", UCHAR_MIN, UCHAR_MIN); + printf("SCHAR_MIN: 0x%08x=%d\n", SCHAR_MIN, SCHAR_MIN); + + printf("SHRT_MIN: 0x%08x=%d\n", SHRT_MIN, SHRT_MIN); + printf("USHRT_MIN: 0x%08x=%d\n", USHRT_MIN, USHRT_MIN); + printf("SSHRT_MIN: 0x%08x=%d\n", SSHRT_MIN, SSHRT_MIN); + + printf("INT_MIN: 0x%08x=%d\n", INT_MIN, INT_MIN); + printf("UINT_MIN: 0x%08x=%d\n", UINT_MIN, UINT_MIN); + printf("SINT_MIN: 0x%08x=%d\n", SINT_MIN, SINT_MIN); + + printf("LONG_MIN: 0x%08lx=%ld\n", LONG_MIN, LONG_MIN); + printf("ULONG_MIN: 0x%08lx=%ld\n", ULONG_MIN, ULONG_MIN); + printf("SLONG_MIN: 0x%08lx=%ld\n", SLONG_MIN, SLONG_MIN); + + return 0; +} diff --git a/test/ref/macro.c b/test/ref/macro.c new file mode 100644 index 000000000..1650b98db --- /dev/null +++ b/test/ref/macro.c @@ -0,0 +1,30 @@ +/* + !!DESCRIPTION!! macro bug test program + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Groepaz/Hitmen +*/ + +#include <stdio.h> +#include <stdlib.h> + +unsigned long fs=7; +unsigned long fd=5; +unsigned long a=3; + +unsigned long _func(unsigned long x,unsigned long y) +{ + printf("x:%ld y:%ld\n",x,y); + return 0; +} + +#define func(x,y) _func(x,y) + +int main(void) +{ + fs= func( (fd/a) , func(2,0x0082c90f) ); + printf("fs:%ld\n",fs); + fs=_func( (fd/a) , _func(2,0x0082c90f) ); + printf("fs:%ld\n",fs); + return 0; +} diff --git a/test/ref/mandel.c b/test/ref/mandel.c new file mode 100644 index 000000000..6c21151f9 --- /dev/null +++ b/test/ref/mandel.c @@ -0,0 +1,84 @@ +/* + !!DESCRIPTION!! mandelbrot test program + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Groepaz/Hitmen +*/ + +#include <stdio.h> +#include <stdlib.h> + +static unsigned short SCREEN_X; +static unsigned char SCREEN_Y; + +#define MAXCOL 8 + +#define maxiterations 16 + +#define fpshift (12) + +#define tofp(_x) ((_x)<<fpshift) +#define fromfp(_x) ((_x)>>fpshift) +#define fpabs(_x) (abs(_x)) + +#define mulfp(_a,_b) ((((signed long)_a)*(_b))>>fpshift) +#define divfp(_a,_b) ((((signed long)_a)<<fpshift)/(_b)) + +unsigned char dither[MAXCOL]={" .*o+0%#"}; + +void mandelbrot(signed short x1,signed short y1,signed short x2,signed short y2) +{ +register signed short r,r1,i; +register unsigned char count; +register signed short xs,ys,xx,yy; +register signed short x; +register unsigned char y; + + /* calc stepwidth */ + xs=((x2-x1)/(SCREEN_X)); + ys=((y2-y1)/(SCREEN_Y)); + + yy=y1; + for(y = 0; y < (SCREEN_Y); ++y) + { + yy+=ys; xx=x1; + for(x = 0; x < (SCREEN_X); ++x) + { + xx+=xs; + /* do iterations */ + r=0;i=0; + for(count=0;(count<maxiterations)&& + (fpabs(r)<tofp(2))&& + (fpabs(i)<tofp(2)) + ;++count) + { + r1 = (mulfp(r,r)-mulfp(i,i))+xx; + /* i = (mulfp(mulfp(r,i),tofp(2)))+yy; */ + i = (((signed long)r*i)>>(fpshift-1))+yy; + r=r1; + } + if(count==maxiterations) + { + printf(" "); + } + else + { + printf("%c",dither[(count%MAXCOL)]); + } + } + printf("\n"); + } +} + +int main (void) +{ + SCREEN_X = 80; + SCREEN_Y = 40; + + /* calc mandelbrot set */ + mandelbrot(tofp(-2),tofp(-2),tofp(2),tofp(2)); + + /* Done */ + return 0; +} + diff --git a/test/ref/minimal.c b/test/ref/minimal.c new file mode 100644 index 000000000..5aa3c5f4f --- /dev/null +++ b/test/ref/minimal.c @@ -0,0 +1,14 @@ +/* + !!DESCRIPTION!! minimal Program, checks if the Compiler and testsuite framework works + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Groepaz/Hitmen +*/ + +int main(void) +{ +#if 1 + printf("it works :)\n"); +#endif + return 0; +} diff --git a/test/ref/otccex.c b/test/ref/otccex.c new file mode 100644 index 000000000..a967e4805 --- /dev/null +++ b/test/ref/otccex.c @@ -0,0 +1,148 @@ +/* + !!DESCRIPTION!! OTCC Example (simple K&R Style) + !!ORIGIN!! OTCC + !!LICENCE!! GPL (?), read COPYING.GPL +*/ + +/* + * Sample OTCC C example. You can uncomment the first line and install + * otcc in /usr/local/bin to make otcc scripts ! + */ + +/* Any preprocessor directive except #define are ignored. We put this + include so that a standard C compiler can compile this code too. */ +#include <stdio.h> +#include <limits.h> + +/* defines are handled, but macro arguments cannot be given. No + recursive defines are tolerated */ +#define DEFAULT_BASE 10 + +#ifdef NO_IMPLICIT_FUNC_PROTOTYPES +help(char *name); +#endif + +/* + * Only old style K&R prototypes are parsed. Only int arguments are + * allowed (implicit types). + * + * By benchmarking the execution time of this function (for example + * for fib(35)), you'll notice that OTCC is quite fast because it + * generates native i386 machine code. + */ +fib(n) +{ + printf("[fib(%d)]", n); + if (n <= 2) + return 1; + else + return fib(n-1) + fib(n-2); +} + +/* Identifiers are parsed the same way as C: begins with letter or + '_', and then letters, '_' or digits */ +long fact(n) +{ + /* local variables can be declared. Only 'int' type is supported */ + int i; + long r; + r = 1; + /* 'while' and 'for' loops are supported */ + for(i=2;i<=n;i++) + r = r * i; + return r; +} + +/* Well, we could use printf, but it would be too easy */ +print_num(long n,int b) +{ + int tab, p, c; + /* Numbers can be entered in decimal, hexadecimal ('0x' prefix) and + octal ('0' prefix) */ + /* more complex programs use malloc */ + tab = malloc(0x100); + p = tab; + while (1) { + c = n % b; + /* Character constants can be used */ + if (c >= 10) + c = c + 'a' - 10; + else + c = c + '0'; + *(char *)p = c; + p++; + n = n / b; + /* 'break' is supported */ + if (n == 0) + break; + } + while (p != tab) { + p--; + printf("%c", *(char *)p); + } + free(tab); +} + +/* 'main' takes standard 'argc' and 'argv' parameters */ +mymain(int argc,char **argv) +{ + /* no local name space is supported, but local variables ARE + supported. As long as you do not use a globally defined + variable name as local variable (which is a bad habbit), you + won't have any problem */ + int s, n, f, base; + + + /* && and || operator have the same semantics as C (left to right + evaluation and early exit) */ + if (argc != 2 && argc != 3) { + /* '*' operator is supported with explicit casting to 'int *', + 'char *' or 'int (*)()' (function pointer). Of course, 'int' + are supposed to be used as pointers too. */ + s = *(int *)argv; + help(s); + return 1; + } + /* Any libc function can be used because OTCC uses dynamic linking */ + n = atoi(argv[1]); + base = DEFAULT_BASE; + if (argc >= 3) { + base = atoi(argv[2]); + if (base < 2 || base > 36) { + /* external variables can be used too (here: 'stderr') */ + fprintf(stdout, "Invalid base\n"); + return 1; + } + } + printf("fib(%d) =\n", n); + print_num(fib(n), base); + printf("\n"); + + printf("fact(%d) = ", n); + if (n > 12) { + printf("Overflow"); + } else { + /* why not using a function pointer ? */ + f = &fact; + print_num((*(long (*)())f)(n), base); + } + printf("\n"); + return 0; +} + +/* functions can be used before being defined */ +help(char *name) +{ + printf("usage: %s n [base]\n", name); + printf("Compute fib(n) and fact(n) and output the result in base 'base'\n"); +} + +int main(void) +{ + char *argv[3]; + argv[0]=""; + argv[1]="10"; /* n */ + argv[2]="8"; /* base */ + mymain(3, argv); + return 0; +} \ No newline at end of file diff --git a/test/ref/paranoia.c b/test/ref/paranoia.c new file mode 100644 index 000000000..3616c9391 --- /dev/null +++ b/test/ref/paranoia.c @@ -0,0 +1,2216 @@ +/* + !!DESCRIPTION!! a wellknown floating point test + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +#ifdef NO_FLOATS + +main() +{ + printf("NO_FLOATS\n\r"); +} + +#else + +#undef V9 +#define NOPAUSE +/* A C version of Kahan's Floating Point Test "Paranoia" + + Thos Sumner, UCSF, Feb. 1985 + David Gay, BTL, Jan. 1986 + + This is a rewrite from the Pascal version by + + B. A. Wichmann, 18 Jan. 1985 + + (and does NOT exhibit good C programming style). + +(C) Apr 19 1983 in BASIC version by: + Professor W. M. Kahan, + 567 Evans Hall + Electrical Engineering & Computer Science Dept. + University of California + Berkeley, California 94720 + USA + +converted to Pascal by: + B. A. Wichmann + National Physical Laboratory + Teddington Middx + TW11 OLW + UK + +converted to C by: + + David M. Gay and Thos Sumner + AT&T Bell Labs Computer Center, Rm. U-76 + 600 Mountain Avenue University of California + Murray Hill, NJ 07974 San Francisco, CA 94143 + USA USA + +with simultaneous corrections to the Pascal source (reflected +in the Pascal source available over netlib). +[A couple of bug fixes from dgh = sun!dhough incorporated 31 July 1986.] + +Reports of results on various systems from all the versions +of Paranoia are being collected by Richard Karpinski at the +same address as Thos Sumner. This includes sample outputs, +bug reports, and criticisms. + +You may copy this program freely if you acknowledge its source. +Comments on the Pascal version to NPL, please. + +The C version catches signals from floating-point exceptions. +If signal(SIGFPE,...) is unavailable in your environment, you may +#define NOSIGNAL to comment out the invocations of signal. + +This source file is too big for some C compilers, but may be split +into pieces. Comments containing "SPLIT" suggest convenient places +for this splitting. At the end of these comments is an "ed script" +(for the UNIX(tm) editor ed) that will do this splitting. + +By #defining Single when you compile this source, you may obtain +a single-precision C version of Paranoia. + +The following is from the introductory commentary from Wichmann's work: + +The BASIC program of Kahan is written in Microsoft BASIC using many +facilities which have no exact analogy in Pascal. The Pascal +version below cannot therefore be exactly the same. Rather than be +a minimal transcription of the BASIC program, the Pascal coding +follows the conventional style of block-structured languages. Hence +the Pascal version could be useful in producing versions in other +structured languages. + +Rather than use identifiers of minimal length (which therefore have +little mnemonic significance), the Pascal version uses meaningful +identifiers as follows [Note: A few changes have been made for C]: + +BASIC C BASIC C BASIC C + + A J S StickyBit + A1 AInverse J0 NoErrors T + B Radix [Failure] T0 Underflow + B1 BInverse J1 NoErrors T2 ThirtyTwo + B2 RadixD2 [SeriousDefect] T5 OneAndHalf + B9 BMinusU2 J2 NoErrors T7 TwentySeven + C [Defect] T8 TwoForty + C1 CInverse J3 NoErrors U OneUlp + D [Flaw] U0 UnderflowThreshold + D4 FourD K PageNo U1 + E0 L Milestone U2 + E1 M V + E2 Exp2 N V0 + E3 N1 V8 + E5 MinSqEr O Zero V9 + E6 SqEr O1 One W + E7 MaxSqEr O2 Two X + E8 O3 Three X1 + E9 O4 Four X8 + F1 MinusOne O5 Five X9 Random1 + F2 Half O8 Eight Y + F3 Third O9 Nine Y1 + F6 P Precision Y2 + F9 Q Y9 Random2 + G1 GMult Q8 Z + G2 GDiv Q9 Z0 PseudoZero + G3 GAddSub R Z1 + H R1 RMult Z2 + H1 HInverse R2 RDiv Z9 + I R3 RAddSub + IO NoTrials R4 RSqrt + I3 IEEE R9 Random9 + + SqRWrng + +All the variables in BASIC are true variables and in consequence, +the program is more difficult to follow since the "constants" must +be determined (the glossary is very helpful). The Pascal version +uses Real constants, but checks are added to ensure that the values +are correctly converted by the compiler. + +The major textual change to the Pascal version apart from the +identifiersis that named procedures are used, inserting parameters +wherehelpful. New procedures are also introduced. The +correspondence is as follows: + +BASIC Pascal +lines + + 90- 140 Pause + 170- 250 Instructions + 380- 460 Heading + 480- 670 Characteristics + 690- 870 History +2940-2950 Random +3710-3740 NewD +4040-4080 DoesYequalX +4090-4110 PrintIfNPositive +4640-4850 TestPartialUnderflow + +=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= + +Below is an "ed script" that splits para.c into 10 files +of the form part[1-8].c, subs.c, and msgs.c, plus a header +file, paranoia.h, that these files require. + +r paranoia.c +$ +?SPLIT ++,$w msgs.c + .,$d +?SPLIT + .d ++d +-,$w subs.c +-,$d +?part8 ++d +?include + .,$w part8.c + .,$d +-d +?part7 ++d +?include + .,$w part7.c + .,$d +-d +?part6 ++d +?include + .,$w part6.c + .,$d +-d +?part5 ++d +?include + .,$w part5.c + .,$d +-d +?part4 ++d +?include + .,$w part4.c + .,$d +-d +?part3 ++d +?include + .,$w part3.c + .,$d +-d +?part2 ++d +?include + .,$w part2.c + .,$d +?SPLIT + .d +1,/^#include/-1d +1,$w part1.c +/Computed constants/,$d +1,$s/^int/extern &/ +1,$s/^FLOAT/extern &/ +1,$s/^char/extern &/ +1,$s! = .*!;! +/^Guard/,/^Round/s/^/extern / +/^jmp_buf/s/^/extern / +/^Sig_type/s/^/extern / +s/$/\ +extern void sigfpe();/ +w paranoia.h +q + +*/ + +#include <stdio.h> +#ifndef NOSIGNAL +#include <signal.h> +#endif +#include <setjmp.h> + +extern double fabs(), floor(), log(), pow(), sqrt(); + +#ifdef Single +#define FLOAT float +#define FABS(x) (float)fabs((double)(x)) +#define FLOOR(x) (float)floor((double)(x)) +#define LOG(x) (float)log((double)(x)) +#define POW(x,y) (float)pow((double)(x),(double)(y)) +#define SQRT(x) (float)sqrt((double)(x)) +#else +#define FLOAT double +#define FABS(x) fabs(x) +#define FLOOR(x) floor(x) +#define LOG(x) log(x) +#define POW(x,y) pow(x,y) +#define SQRT(x) sqrt(x) +#endif + +jmp_buf ovfl_buf; +typedef void (*Sig_type)(); +Sig_type sigsave; + +#define KEYBOARD 0 + +FLOAT Radix, BInvrse, RadixD2, BMinusU2; +FLOAT Sign(), Random(); + +/*Small floating point constants.*/ +FLOAT Zero = 0.0; +FLOAT Half = 0.5; +FLOAT One = 1.0; +FLOAT Two = 2.0; +FLOAT Three = 3.0; +FLOAT Four = 4.0; +FLOAT Five = 5.0; +FLOAT Eight = 8.0; +FLOAT Nine = 9.0; +FLOAT TwentySeven = 27.0; +FLOAT ThirtyTwo = 32.0; +FLOAT TwoForty = 240.0; +FLOAT MinusOne = -1.0; +FLOAT OneAndHalf = 1.5; +/*Integer constants*/ +int NoTrials = 20; /*Number of tests for commutativity. */ +#define False 0 +#define True 1 + +/* Definitions for declared types + Guard == (Yes, No); + Rounding == (Chopped, Rounded, Other); + Message == packed array [1..40] of char; + Class == (Flaw, Defect, Serious, Failure); + */ +#define Yes 1 +#define No 0 +#define Chopped 2 +#define Rounded 1 +#define Other 0 +#define Flaw 3 +#define Defect 2 +#define Serious 1 +#define Failure 0 +typedef int Guard, Rounding, Class; +typedef char Message; + +/* Declarations of Variables */ +int Indx; +char ch[8]; +FLOAT AInvrse, A1; +FLOAT C, CInvrse; +FLOAT D, FourD; +FLOAT E0, E1, Exp2, E3, MinSqEr; +FLOAT SqEr, MaxSqEr, E9; +FLOAT Third; +FLOAT F6, F9; +FLOAT H, HInvrse; +int I; +FLOAT StickyBit, J; +FLOAT MyZero; +FLOAT Precision; +FLOAT Q, Q9; +FLOAT R, Random9; +FLOAT T, Underflow, S; +FLOAT OneUlp, UfThold, U1, U2; +FLOAT V, V0, V9; +FLOAT W; +FLOAT X, X1, X2, X8, Random1; +FLOAT Y, Y1, Y2, Random2; +FLOAT Z, PseudoZero, Z1, Z2, Z9; +int ErrCnt[4]; +int fpecount; +int Milestone; +int PageNo; +int M, N, N1; +Guard GMult, GDiv, GAddSub; +Rounding RMult, RDiv, RAddSub, RSqrt; +int Break, Done, NotMonot, Monot, Anomaly, IEEE, + SqRWrng, UfNGrad; +/* Computed constants. */ +/*U1 gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */ +/*U2 gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */ + +/* floating point exception receiver */ + void +sigfpe(i) +{ + fpecount++; + printf("\n* * * FLOATING-POINT ERROR * * *\n"); + fflush(stdout); + if (sigsave) { +#ifndef NOSIGNAL + signal(SIGFPE, sigsave); +#endif + sigsave = 0; + longjmp(ovfl_buf, 1); + } + abort(); +} + +main() +{ +#ifdef mc + char *out; + ieee_flags("set", "precision", "double", &out); +#endif + /* First two assignments use integer right-hand sides. */ + Zero = 0; + One = 1; + Two = One + One; + Three = Two + One; + Four = Three + One; + Five = Four + One; + Eight = Four + Four; + Nine = Three * Three; + TwentySeven = Nine * Three; + ThirtyTwo = Four * Eight; + TwoForty = Four * Five * Three * Four; + MinusOne = -One; + Half = One / Two; + OneAndHalf = One + Half; + ErrCnt[Failure] = 0; + ErrCnt[Serious] = 0; + ErrCnt[Defect] = 0; + ErrCnt[Flaw] = 0; + PageNo = 1; + /*=============================================*/ + Milestone = 0; + /*=============================================*/ +#ifndef NOSIGNAL + signal(SIGFPE, sigfpe); +#endif + Instructions(); + Pause(); + Heading(); + Pause(); + Characteristics(); + Pause(); + History(); + Pause(); + /*=============================================*/ + Milestone = 7; + /*=============================================*/ + printf("Program is now RUNNING tests on small integers:\n"); + + TstCond (Failure, (Zero + Zero == Zero) && (One - One == Zero) + && (One > Zero) && (One + One == Two), + "0+0 != 0, 1-1 != 0, 1 <= 0, or 1+1 != 2"); + Z = - Zero; + if (Z != 0.0) { + ErrCnt[Failure] = ErrCnt[Failure] + 1; + printf("Comparison alleges that -0.0 is Non-zero!\n"); + U1 = 0.001; + Radix = 1; + TstPtUf(); + } + TstCond (Failure, (Three == Two + One) && (Four == Three + One) + && (Four + Two * (- Two) == Zero) + && (Four - Three - One == Zero), + "3 != 2+1, 4 != 3+1, 4+2*(-2) != 0, or 4-3-1 != 0"); + TstCond (Failure, (MinusOne == (0 - One)) + && (MinusOne + One == Zero ) && (One + MinusOne == Zero) + && (MinusOne + FABS(One) == Zero) + && (MinusOne + MinusOne * MinusOne == Zero), + "-1+1 != 0, (-1)+abs(1) != 0, or -1+(-1)*(-1) != 0"); + TstCond (Failure, Half + MinusOne + Half == Zero, + "1/2 + (-1) + 1/2 != 0"); + /*=============================================*/ + /*SPLIT + part2(); + part3(); + part4(); + part5(); + part6(); + part7(); + part8(); + } +#include "paranoia.h" +part2(){ +*/ + Milestone = 10; + /*=============================================*/ + TstCond (Failure, (Nine == Three * Three) + && (TwentySeven == Nine * Three) && (Eight == Four + Four) + && (ThirtyTwo == Eight * Four) + && (ThirtyTwo - TwentySeven - Four - One == Zero), + "9 != 3*3, 27 != 9*3, 32 != 8*4, or 32-27-4-1 != 0"); + TstCond (Failure, (Five == Four + One) && + (TwoForty == Four * Five * Three * Four) + && (TwoForty / Three - Four * Four * Five == Zero) + && ( TwoForty / Four - Five * Three * Four == Zero) + && ( TwoForty / Five - Four * Three * Four == Zero), + "5 != 4+1, 240/3 != 80, 240/4 != 60, or 240/5 != 48"); + if (ErrCnt[Failure] == 0) { + printf("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n"); + printf("\n"); + } + printf("Searching for Radix and Precision.\n"); + W = One; + do { + W = W + W; + Y = W + One; + Z = Y - W; + Y = Z - One; + } while (MinusOne + FABS(Y) < Zero); + /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ...*/ + Precision = Zero; + Y = One; + do { + Radix = W + Y; + Y = Y + Y; + Radix = Radix - W; + } while ( Radix == Zero); + if (Radix < Two) Radix = One; + printf("Radix = %f .\n", Radix); + if (Radix != 1) { + W = One; + do { + Precision = Precision + One; + W = W * Radix; + Y = W + One; + } while ((Y - W) == One); + } + /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1 + ...*/ + U1 = One / W; + U2 = Radix * U1; + printf("Closest relative separation found is U1 = %.7e .\n\n", U1); + printf("Recalculating radix and precision\n "); + + /*save old values*/ + E0 = Radix; + E1 = U1; + E9 = U2; + E3 = Precision; + + X = Four / Three; + Third = X - One; + F6 = Half - Third; + X = F6 + F6; + X = FABS(X - Third); + if (X < U2) X = U2; + + /*... now X = (unknown no.) ulps of 1+...*/ + do { + U2 = X; + Y = Half * U2 + ThirtyTwo * U2 * U2; + Y = One + Y; + X = Y - One; + } while ( ! ((U2 <= X) || (X <= Zero))); + + /*... now U2 == 1 ulp of 1 + ... */ + X = Two / Three; + F6 = X - Half; + Third = F6 + F6; + X = Third - Half; + X = FABS(X + F6); + if (X < U1) X = U1; + + /*... now X == (unknown no.) ulps of 1 -... */ + do { + U1 = X; + Y = Half * U1 + ThirtyTwo * U1 * U1; + Y = Half - Y; + X = Half + Y; + Y = Half - X; + X = Half + Y; + } while ( ! ((U1 <= X) || (X <= Zero))); + /*... now U1 == 1 ulp of 1 - ... */ + if (U1 == E1) printf("confirms closest relative separation U1 .\n"); + else printf("gets better closest relative separation U1 = %.7e .\n", U1); + W = One / U1; + F9 = (Half - U1) + Half; + Radix = FLOOR(0.01 + U2 / U1); + if (Radix == E0) printf("Radix confirmed.\n"); + else printf("MYSTERY: recalculated Radix = %.7e .\n", Radix); + TstCond (Defect, Radix <= Eight + Eight, + "Radix is too big: roundoff problems"); + TstCond (Flaw, (Radix == Two) || (Radix == 10) + || (Radix == One), "Radix is not as good as 2 or 10"); + /*=============================================*/ + Milestone = 20; + /*=============================================*/ + TstCond (Failure, F9 - Half < Half, + "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?"); + X = F9; + I = 1; + Y = X - Half; + Z = Y - Half; + TstCond (Failure, (X != One) + || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0"); + X = One + U2; + I = 0; + /*=============================================*/ + Milestone = 25; + /*=============================================*/ + /*... BMinusU2 = nextafter(Radix, 0) */ + BMinusU2 = Radix - One; + BMinusU2 = (BMinusU2 - U2) + One; + /* Purify Integers */ + if (Radix != One) { + X = - TwoForty * LOG(U1) / LOG(Radix); + Y = FLOOR(Half + X); + if (FABS(X - Y) * Four < One) X = Y; + Precision = X / TwoForty; + Y = FLOOR(Half + Precision); + if (FABS(Precision - Y) * TwoForty < Half) Precision = Y; + } + if ((Precision != FLOOR(Precision)) || (Radix == One)) { + printf("Precision cannot be characterized by an Integer number\n"); + printf("of significant digits but, by itself, this is a minor flaw.\n"); + } + if (Radix == One) + printf("logarithmic encoding has precision characterized solely by U1.\n"); + else printf("The number of significant digits of the Radix is %f .\n", + Precision); + TstCond (Serious, U2 * Nine * Nine * TwoForty < One, + "Precision worse than 5 decimal figures "); + /*=============================================*/ + Milestone = 30; + /*=============================================*/ + /* Test for extra-precise subepressions */ + X = FABS(((Four / Three - One) - One / Four) * Three - One / Four); + do { + Z2 = X; + X = (One + (Half * Z2 + ThirtyTwo * Z2 * Z2)) - One; + } while ( ! ((Z2 <= X) || (X <= Zero))); + X = Y = Z = FABS((Three / Four - Two / Three) * Three - One / Four); + do { + Z1 = Z; + Z = (One / Two - ((One / Two - (Half * Z1 + ThirtyTwo * Z1 * Z1)) + + One / Two)) + One / Two; + } while ( ! ((Z1 <= Z) || (Z <= Zero))); + do { + do { + Y1 = Y; + Y = (Half - ((Half - (Half * Y1 + ThirtyTwo * Y1 * Y1)) + Half + )) + Half; + } while ( ! ((Y1 <= Y) || (Y <= Zero))); + X1 = X; + X = ((Half * X1 + ThirtyTwo * X1 * X1) - F9) + F9; + } while ( ! ((X1 <= X) || (X <= Zero))); + if ((X1 != Y1) || (X1 != Z1)) { + BadCond(Serious, "Disagreements among the values X1, Y1, Z1,\n"); + printf("respectively %.7e, %.7e, %.7e,\n", X1, Y1, Z1); + printf("are symptoms of inconsistencies introduced\n"); + printf("by extra-precise evaluation of arithmetic subexpressions.\n"); + notify("Possibly some part of this"); + if ((X1 == U1) || (Y1 == U1) || (Z1 == U1)) printf( + "That feature is not tested further by this program.\n") ; + } + else { + if ((Z1 != U1) || (Z2 != U2)) { + if ((Z1 >= U1) || (Z2 >= U2)) { + BadCond(Failure, ""); + notify("Precision"); + printf("\tU1 = %.7e, Z1 - U1 = %.7e\n",U1,Z1-U1); + printf("\tU2 = %.7e, Z2 - U2 = %.7e\n",U2,Z2-U2); + } + else { + if ((Z1 <= Zero) || (Z2 <= Zero)) { + printf("Because of unusual Radix = %f", Radix); + printf(", or exact rational arithmetic a result\n"); + printf("Z1 = %.7e, or Z2 = %.7e ", Z1, Z2); + notify("of an\nextra-precision"); + } + if (Z1 != Z2 || Z1 > Zero) { + X = Z1 / U1; + Y = Z2 / U2; + if (Y > X) X = Y; + Q = - LOG(X); + printf("Some subexpressions appear to be calculated extra\n"); + printf("precisely with about %g extra B-digits, i.e.\n", + (Q / LOG(Radix))); + printf("roughly %g extra significant decimals.\n", + Q / LOG(10.)); + } + printf("That feature is not tested further by this program.\n"); + } + } + } + Pause(); + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +part3(){ +*/ + Milestone = 35; + /*=============================================*/ + if (Radix >= Two) { + X = W / (Radix * Radix); + Y = X + One; + Z = Y - X; + T = Z + U2; + X = T - Z; + TstCond (Failure, X == U2, + "Subtraction is not normalized X=Y,X+Z != Y+Z!"); + if (X == U2) printf( + "Subtraction appears to be normalized, as it should be."); + } + printf("\nChecking for guard digit in *, /, and -.\n"); + Y = F9 * One; + Z = One * F9; + X = F9 - Half; + Y = (Y - Half) - X; + Z = (Z - Half) - X; + X = One + U2; + T = X * Radix; + R = Radix * X; + X = T - Radix; + X = X - Radix * U2; + T = R - Radix; + T = T - Radix * U2; + X = X * (Radix - One); + T = T * (Radix - One); + if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)) GMult = Yes; + else { + GMult = No; + TstCond (Serious, False, + "* lacks a Guard Digit, so 1*X != X"); + } + Z = Radix * U2; + X = One + Z; + Y = FABS((X + Z) - X * X) - U2; + X = One - U2; + Z = FABS((X - U2) - X * X) - U1; + TstCond (Failure, (Y <= Zero) + && (Z <= Zero), "* gets too many final digits wrong.\n"); + Y = One - U2; + X = One + U2; + Z = One / Y; + Y = Z - X; + X = One / Three; + Z = Three / Nine; + X = X - Z; + T = Nine / TwentySeven; + Z = Z - T; + TstCond(Defect, X == Zero && Y == Zero && Z == Zero, + "Division lacks a Guard Digit, so error can exceed 1 ulp\nor 1/3 and 3/9 and 9/27 may disagree"); + Y = F9 / One; + X = F9 - Half; + Y = (Y - Half) - X; + X = One + U2; + T = X / One; + X = T - X; + if ((X == Zero) && (Y == Zero) && (Z == Zero)) GDiv = Yes; + else { + GDiv = No; + TstCond (Serious, False, + "Division lacks a Guard Digit, so X/1 != X"); + } + X = One / (One + U2); + Y = X - Half - Half; + TstCond (Serious, Y < Zero, + "Computed value of 1/1.000..1 >= 1"); + X = One - U2; + Y = One + Radix * U2; + Z = X * Radix; + T = Y * Radix; + R = Z / Radix; + StickyBit = T / Radix; + X = R - X; + Y = StickyBit - Y; + TstCond (Failure, X == Zero && Y == Zero, + "* and/or / gets too many last digits wrong"); + Y = One - U1; + X = One - F9; + Y = One - Y; + T = Radix - U2; + Z = Radix - BMinusU2; + T = Radix - T; + if ((X == U1) && (Y == U1) && (Z == U2) && (T == U2)) GAddSub = Yes; + else { + GAddSub = No; + TstCond (Serious, False, + "- lacks Guard Digit, so cancellation is obscured"); + } + if (F9 != One && F9 - One >= Zero) { + BadCond(Serious, "comparison alleges (1-U1) < 1 although\n"); + printf(" subtraction yields (1-U1) - 1 = 0 , thereby vitiating\n"); + printf(" such precautions against division by zero as\n"); + printf(" ... if (X == 1.0) {.....} else {.../(X-1.0)...}\n"); + } + if (GMult == Yes && GDiv == Yes && GAddSub == Yes) printf( + " *, /, and - appear to have guard digits, as they should.\n"); + /*=============================================*/ + Milestone = 40; + /*=============================================*/ + Pause(); + printf("Checking rounding on multiply, divide and add/subtract.\n"); + RMult = Other; + RDiv = Other; + RAddSub = Other; + RadixD2 = Radix / Two; + A1 = Two; + Done = False; + do { + AInvrse = Radix; + do { + X = AInvrse; + AInvrse = AInvrse / A1; + } while ( ! (FLOOR(AInvrse) != AInvrse)); + Done = (X == One) || (A1 > Three); + if (! Done) A1 = Nine + One; + } while ( ! (Done)); + if (X == One) A1 = Radix; + AInvrse = One / A1; + X = A1; + Y = AInvrse; + Done = False; + do { + Z = X * Y - Half; + TstCond (Failure, Z == Half, + "X * (1/X) differs from 1"); + Done = X == Radix; + X = Radix; + Y = One / X; + } while ( ! (Done)); + Y2 = One + U2; + Y1 = One - U2; + X = OneAndHalf - U2; + Y = OneAndHalf + U2; + Z = (X - U2) * Y2; + T = Y * Y1; + Z = Z - X; + T = T - X; + X = X * Y2; + Y = (Y + U2) * Y1; + X = X - OneAndHalf; + Y = Y - OneAndHalf; + if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T <= Zero)) { + X = (OneAndHalf + U2) * Y2; + Y = OneAndHalf - U2 - U2; + Z = OneAndHalf + U2 + U2; + T = (OneAndHalf - U2) * Y1; + X = X - (Z + U2); + StickyBit = Y * Y1; + S = Z * Y2; + T = T - Y; + Y = (U2 - Y) + StickyBit; + Z = S - (Z + U2 + U2); + StickyBit = (Y2 + U2) * Y1; + Y1 = Y2 * Y1; + StickyBit = StickyBit - Y2; + Y1 = Y1 - Half; + if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero) + && ( StickyBit == Zero) && (Y1 == Half)) { + RMult = Rounded; + printf("Multiplication appears to round correctly.\n"); + } + else if ((X + U2 == Zero) && (Y < Zero) && (Z + U2 == Zero) + && (T < Zero) && (StickyBit + U2 == Zero) + && (Y1 < Half)) { + RMult = Chopped; + printf("Multiplication appears to chop.\n"); + } + else printf("* is neither chopped nor correctly rounded.\n"); + if ((RMult == Rounded) && (GMult == No)) notify("Multiplication"); + } + else printf("* is neither chopped nor correctly rounded.\n"); + /*=============================================*/ + Milestone = 45; + /*=============================================*/ + Y2 = One + U2; + Y1 = One - U2; + Z = OneAndHalf + U2 + U2; + X = Z / Y2; + T = OneAndHalf - U2 - U2; + Y = (T - U2) / Y1; + Z = (Z + U2) / Y2; + X = X - OneAndHalf; + Y = Y - T; + T = T / Y1; + Z = Z - (OneAndHalf + U2); + T = (U2 - OneAndHalf) + T; + if (! ((X > Zero) || (Y > Zero) || (Z > Zero) || (T > Zero))) { + X = OneAndHalf / Y2; + Y = OneAndHalf - U2; + Z = OneAndHalf + U2; + X = X - Y; + T = OneAndHalf / Y1; + Y = Y / Y1; + T = T - (Z + U2); + Y = Y - Z; + Z = Z / Y2; + Y1 = (Y2 + U2) / Y2; + Z = Z - OneAndHalf; + Y2 = Y1 - Y2; + Y1 = (F9 - U1) / F9; + if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero) + && (Y2 == Zero) && (Y2 == Zero) + && (Y1 - Half == F9 - Half )) { + RDiv = Rounded; + printf("Division appears to round correctly.\n"); + if (GDiv == No) notify("Division"); + } + else if ((X < Zero) && (Y < Zero) && (Z < Zero) && (T < Zero) + && (Y2 < Zero) && (Y1 - Half < F9 - Half)) { + RDiv = Chopped; + printf("Division appears to chop.\n"); + } + } + if (RDiv == Other) printf("/ is neither chopped nor correctly rounded.\n"); + BInvrse = One / Radix; + TstCond (Failure, (BInvrse * Radix - Half == Half), + "Radix * ( 1 / Radix ) differs from 1"); + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +part4(){ +*/ + Milestone = 50; + /*=============================================*/ + TstCond (Failure, ((F9 + U1) - Half == Half) + && ((BMinusU2 + U2 ) - One == Radix - One), + "Incomplete carry-propagation in Addition"); + X = One - U1 * U1; + Y = One + U2 * (One - U2); + Z = F9 - Half; + X = (X - Half) - Z; + Y = Y - One; + if ((X == Zero) && (Y == Zero)) { + RAddSub = Chopped; + printf("Add/Subtract appears to be chopped.\n"); + } + if (GAddSub == Yes) { + X = (Half + U2) * U2; + Y = (Half - U2) * U2; + X = One + X; + Y = One + Y; + X = (One + U2) - X; + Y = One - Y; + if ((X == Zero) && (Y == Zero)) { + X = (Half + U2) * U1; + Y = (Half - U2) * U1; + X = One - X; + Y = One - Y; + X = F9 - X; + Y = One - Y; + if ((X == Zero) && (Y == Zero)) { + RAddSub = Rounded; + printf("Addition/Subtraction appears to round correctly.\n"); + if (GAddSub == No) notify("Add/Subtract"); + } + else printf("Addition/Subtraction neither rounds nor chops.\n"); + } + else printf("Addition/Subtraction neither rounds nor chops.\n"); + } + else printf("Addition/Subtraction neither rounds nor chops.\n"); + S = One; + X = One + Half * (One + Half); + Y = (One + U2) * Half; + Z = X - Y; + T = Y - X; + StickyBit = Z + T; + if (StickyBit != Zero) { + S = Zero; + BadCond(Flaw, "(X - Y) + (Y - X) is non zero!\n"); + } + StickyBit = Zero; + if ((GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes) + && (RMult == Rounded) && (RDiv == Rounded) + && (RAddSub == Rounded) && (FLOOR(RadixD2) == RadixD2)) { + printf("Checking for sticky bit.\n"); + X = (Half + U1) * U2; + Y = Half * U2; + Z = One + Y; + T = One + X; + if ((Z - One <= Zero) && (T - One >= U2)) { + Z = T + Y; + Y = Z - X; + if ((Z - T >= U2) && (Y - T == Zero)) { + X = (Half + U1) * U1; + Y = Half * U1; + Z = One - Y; + T = One - X; + if ((Z - One == Zero) && (T - F9 == Zero)) { + Z = (Half - U1) * U1; + T = F9 - Z; + Q = F9 - Y; + if ((T - F9 == Zero) && (F9 - U1 - Q == Zero)) { + Z = (One + U2) * OneAndHalf; + T = (OneAndHalf + U2) - Z + U2; + X = One + Half / Radix; + Y = One + Radix * U2; + Z = X * Y; + if (T == Zero && X + Radix * U2 - Z == Zero) { + if (Radix != Two) { + X = Two + U2; + Y = X / Two; + if ((Y - One == Zero)) StickyBit = S; + } + else StickyBit = S; + } + } + } + } + } + } + if (StickyBit == One) printf("Sticky bit apparently used correctly.\n"); + else printf("Sticky bit used incorrectly or not at all.\n"); + TstCond (Flaw, !(GMult == No || GDiv == No || GAddSub == No || + RMult == Other || RDiv == Other || RAddSub == Other), + "lack(s) of guard digits or failure(s) to correctly round or chop\n(noted above) count as one flaw in the final tally below"); + /*=============================================*/ + Milestone = 60; + /*=============================================*/ + printf("\n"); + printf("Does Multiplication commute? "); + printf("Testing on %d random pairs.\n", NoTrials); + Random9 = SQRT(3.0); + Random1 = Third; + I = 1; + do { + X = Random(); + Y = Random(); + Z9 = Y * X; + Z = X * Y; + Z9 = Z - Z9; + I = I + 1; + } while ( ! ((I > NoTrials) || (Z9 != Zero))); + if (I == NoTrials) { + Random1 = One + Half / Three; + Random2 = (U2 + U1) + One; + Z = Random1 * Random2; + Y = Random2 * Random1; + Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half / + Three) * ((U2 + U1) + One); + } + if (! ((I == NoTrials) || (Z9 == Zero))) + BadCond(Defect, "X * Y == Y * X trial fails.\n"); + else printf(" No failures found in %d integer pairs.\n", NoTrials); + /*=============================================*/ + Milestone = 70; + /*=============================================*/ + printf("\nRunning test of square root(x).\n"); + TstCond (Failure, (Zero == SQRT(Zero)) + && (- Zero == SQRT(- Zero)) + && (One == SQRT(One)), "Square root of 0.0, -0.0 or 1.0 wrong"); + MinSqEr = Zero; + MaxSqEr = Zero; + J = Zero; + X = Radix; + OneUlp = U2; + SqXMinX (Serious); + X = BInvrse; + OneUlp = BInvrse * U1; + SqXMinX (Serious); + X = U1; + OneUlp = U1 * U1; + SqXMinX (Serious); + if (J != Zero) Pause(); + printf("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials); + J = Zero; + X = Two; + Y = Radix; + if ((Radix != One)) do { + X = Y; + Y = Radix * Y; + } while ( ! ((Y - X >= NoTrials))); + OneUlp = X * U2; + I = 1; + while (I <= NoTrials) { + X = X + One; + SqXMinX (Defect); + if (J > Zero) break; + I = I + 1; + } + printf("Test for sqrt monotonicity.\n"); + I = - 1; + X = BMinusU2; + Y = Radix; + Z = Radix + Radix * U2; + NotMonot = False; + Monot = False; + while ( ! (NotMonot || Monot)) { + I = I + 1; + X = SQRT(X); + Q = SQRT(Y); + Z = SQRT(Z); + if ((X > Q) || (Q > Z)) NotMonot = True; + else { + Q = FLOOR(Q + Half); + if ((I > 0) || (Radix == Q * Q)) Monot = True; + else if (I > 0) { + if (I > 1) Monot = True; + else { + Y = Y * BInvrse; + X = Y - U1; + Z = Y + U1; + } + } + else { + Y = Q; + X = Y - U2; + Z = Y + U2; + } + } + } + if (Monot) printf("sqrt has passed a test for Monotonicity.\n"); + else { + BadCond(Defect, ""); + printf("sqrt(X) is non-monotonic for X near %.7e .\n", Y); + } + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +part5(){ +*/ + Milestone = 80; + /*=============================================*/ + MinSqEr = MinSqEr + Half; + MaxSqEr = MaxSqEr - Half; + Y = (SQRT(One + U2) - One) / U2; + SqEr = (Y - One) + U2 / Eight; + if (SqEr > MaxSqEr) MaxSqEr = SqEr; + SqEr = Y + U2 / Eight; + if (SqEr < MinSqEr) MinSqEr = SqEr; + Y = ((SQRT(F9) - U2) - (One - U2)) / U1; + SqEr = Y + U1 / Eight; + if (SqEr > MaxSqEr) MaxSqEr = SqEr; + SqEr = (Y + One) + U1 / Eight; + if (SqEr < MinSqEr) MinSqEr = SqEr; + OneUlp = U2; + X = OneUlp; + for( Indx = 1; Indx <= 3; ++Indx) { + Y = SQRT((X + U1 + X) + F9); + Y = ((Y - U2) - ((One - U2) + X)) / OneUlp; + Z = ((U1 - X) + F9) * Half * X * X / OneUlp; + SqEr = (Y + Half) + Z; + if (SqEr < MinSqEr) MinSqEr = SqEr; + SqEr = (Y - Half) + Z; + if (SqEr > MaxSqEr) MaxSqEr = SqEr; + if (((Indx == 1) || (Indx == 3))) + X = OneUlp * Sign (X) * FLOOR(Eight / (Nine * SQRT(OneUlp))); + else { + OneUlp = U1; + X = - OneUlp; + } + } + /*=============================================*/ + Milestone = 85; + /*=============================================*/ + SqRWrng = False; + Anomaly = False; + RSqrt = Other; /* ~dgh */ + if (Radix != One) { + printf("Testing whether sqrt is rounded or chopped.\n"); + D = FLOOR(Half + POW(Radix, One + Precision - FLOOR(Precision))); + /* ... == Radix^(1 + fract) if (Precision == Integer + fract. */ + X = D / Radix; + Y = D / A1; + if ((X != FLOOR(X)) || (Y != FLOOR(Y))) { + Anomaly = True; + } + else { + X = Zero; + Z2 = X; + Y = One; + Y2 = Y; + Z1 = Radix - One; + FourD = Four * D; + do { + if (Y2 > Z2) { + Q = Radix; + Y1 = Y; + do { + X1 = FABS(Q + FLOOR(Half - Q / Y1) * Y1); + Q = Y1; + Y1 = X1; + } while ( ! (X1 <= Zero)); + if (Q <= One) { + Z2 = Y2; + Z = Y; + } + } + Y = Y + Two; + X = X + Eight; + Y2 = Y2 + X; + if (Y2 >= FourD) Y2 = Y2 - FourD; + } while ( ! (Y >= D)); + X8 = FourD - Z2; + Q = (X8 + Z * Z) / FourD; + X8 = X8 / Eight; + if (Q != FLOOR(Q)) Anomaly = True; + else { + Break = False; + do { + X = Z1 * Z; + X = X - FLOOR(X / Radix) * Radix; + if (X == One) + Break = True; + else + Z1 = Z1 - One; + } while ( ! (Break || (Z1 <= Zero))); + if ((Z1 <= Zero) && (! Break)) Anomaly = True; + else { + if (Z1 > RadixD2) Z1 = Z1 - Radix; + do { + NewD(); + } while ( ! (U2 * D >= F9)); + if (D * Radix - D != W - D) Anomaly = True; + else { + Z2 = D; + I = 0; + Y = D + (One + Z) * Half; + X = D + Z + Q; + SR3750(); + Y = D + (One - Z) * Half + D; + X = D - Z + D; + X = X + Q + X; + SR3750(); + NewD(); + if (D - Z2 != W - Z2) Anomaly = True; + else { + Y = (D - Z2) + (Z2 + (One - Z) * Half); + X = (D - Z2) + (Z2 - Z + Q); + SR3750(); + Y = (One + Z) * Half; + X = Q; + SR3750(); + if (I == 0) Anomaly = True; + } + } + } + } + } + if ((I == 0) || Anomaly) { + BadCond(Failure, "Anomalous arithmetic with Integer < "); + printf("Radix^Precision = %.7e\n", W); + printf(" fails test whether sqrt rounds or chops.\n"); + SqRWrng = True; + } + } + if (! Anomaly) { + if (! ((MinSqEr < Zero) || (MaxSqEr > Zero))) { + RSqrt = Rounded; + printf("Square root appears to be correctly rounded.\n"); + } + else { + if ((MaxSqEr + U2 > U2 - Half) || (MinSqEr > Half) + || (MinSqEr + Radix < Half)) SqRWrng = True; + else { + RSqrt = Chopped; + printf("Square root appears to be chopped.\n"); + } + } + } + if (SqRWrng) { + printf("Square root is neither chopped nor correctly rounded.\n"); + printf("Observed errors run from %.7e ", MinSqEr - Half); + printf("to %.7e ulps.\n", Half + MaxSqEr); + TstCond (Serious, MaxSqEr - MinSqEr < Radix * Radix, + "sqrt gets too many last digits wrong"); + } + /*=============================================*/ + Milestone = 90; + /*=============================================*/ + Pause(); + printf("Testing powers Z^i for small Integers Z and i.\n"); + N = 0; + /* ... test powers of zero. */ + I = 0; + Z = -Zero; + M = 3.0; + Break = False; + do { + X = One; + SR3980(); + if (I <= 10) { + I = 1023; + SR3980(); + } + if (Z == MinusOne) Break = True; + else { + Z = MinusOne; + PrintIfNPositive(); + N = 0; + /* .. if(-1)^N is invalid, replace MinusOne by One. */ + I = - 4; + } + } while ( ! Break); + PrintIfNPositive(); + N1 = N; + N = 0; + Z = A1; + M = FLOOR(Two * LOG(W) / LOG(A1)); + Break = False; + do { + X = Z; + I = 1; + SR3980(); + if (Z == AInvrse) Break = True; + else Z = AInvrse; + } while ( ! (Break)); + /*=============================================*/ + Milestone = 100; + /*=============================================*/ + /* Powers of Radix have been tested, */ + /* next try a few primes */ + M = NoTrials; + Z = Three; + do { + X = Z; + I = 1; + SR3980(); + do { + Z = Z + Two; + } while ( Three * FLOOR(Z / Three) == Z ); + } while ( Z < Eight * Three ); + if (N > 0) { + printf("Errors like this may invalidate financial calculations\n"); + printf("\tinvolving interest rates.\n"); + } + PrintIfNPositive(); + N += N1; + if (N == 0) printf("... no discrepancis found.\n"); + if (N > 0) Pause(); + else printf("\n"); + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +part6(){ +*/ + Milestone = 110; + /*=============================================*/ + printf("Seeking Underflow thresholds UfThold and E0.\n"); + D = U1; + if (Precision != FLOOR(Precision)) { + D = BInvrse; + X = Precision; + do { + D = D * BInvrse; + X = X - One; + } while ( X > Zero); + } + Y = One; + Z = D; + /* ... D is power of 1/Radix < 1. */ + do { + C = Y; + Y = Z; + Z = Y * Y; + } while ((Y > Z) && (Z + Z > Z)); + Y = C; + Z = Y * D; + do { + C = Y; + Y = Z; + Z = Y * D; + } while ((Y > Z) && (Z + Z > Z)); + if (Radix < Two) HInvrse = Two; + else HInvrse = Radix; + H = One / HInvrse; + /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */ + CInvrse = One / C; + E0 = C; + Z = E0 * H; + /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */ + do { + Y = E0; + E0 = Z; + Z = E0 * H; + } while ((E0 > Z) && (Z + Z > Z)); + UfThold = E0; + E1 = Zero; + Q = Zero; + E9 = U2; + S = One + E9; + D = C * S; + if (D <= C) { + E9 = Radix * U2; + S = One + E9; + D = C * S; + if (D <= C) { + BadCond(Failure, "multiplication gets too many last digits wrong.\n"); + Underflow = E0; + Y1 = Zero; + PseudoZero = Z; + Pause(); + } + } + else { + Underflow = D; + PseudoZero = Underflow * H; + UfThold = Zero; + do { + Y1 = Underflow; + Underflow = PseudoZero; + if (E1 + E1 <= E1) { + Y2 = Underflow * HInvrse; + E1 = FABS(Y1 - Y2); + Q = Y1; + if ((UfThold == Zero) && (Y1 != Y2)) UfThold = Y1; + } + PseudoZero = PseudoZero * H; + } while ((Underflow > PseudoZero) + && (PseudoZero + PseudoZero > PseudoZero)); + } + /* Comment line 4530 .. 4560 */ + if (PseudoZero != Zero) { + printf("\n"); + Z = PseudoZero; + /* ... Test PseudoZero for "phoney- zero" violates */ + /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero + ... */ + if (PseudoZero <= Zero) { + BadCond(Failure, "Positive expressions can underflow to an\n"); + printf("allegedly negative value\n"); + printf("PseudoZero that prints out as: %g .\n", PseudoZero); + X = - PseudoZero; + if (X <= Zero) { + printf("But -PseudoZero, which should be\n"); + printf("positive, isn't; it prints out as %g .\n", X); + } + } + else { + BadCond(Flaw, "Underflow can stick at an allegedly positive\n"); + printf("value PseudoZero that prints out as %g .\n", PseudoZero); + } + TstPtUf(); + } + /*=============================================*/ + Milestone = 120; + /*=============================================*/ + if (CInvrse * Y > CInvrse * Y1) { + S = H * S; + E0 = Underflow; + } + if (! ((E1 == Zero) || (E1 == E0))) { + BadCond(Defect, ""); + if (E1 < E0) { + printf("Products underflow at a higher"); + printf(" threshold than differences.\n"); + if (PseudoZero == Zero) + E0 = E1; + } + else { + printf("Difference underflows at a higher"); + printf(" threshold than products.\n"); + } + } + printf("Smallest strictly positive number found is E0 = %g .\n", E0); + Z = E0; + TstPtUf(); + Underflow = E0; + if (N == 1) Underflow = Y; + I = 4; + if (E1 == Zero) I = 3; + if (UfThold == Zero) I = I - 2; + UfNGrad = True; + switch (I) { + case 1: + UfThold = Underflow; + if ((CInvrse * Q) != ((CInvrse * Y) * S)) { + UfThold = Y; + BadCond(Failure, "Either accuracy deteriorates as numbers\n"); + printf("approach a threshold = %.17e\n", UfThold);; + printf(" coming down from %.17e\n", C); + printf(" or else multiplication gets too many last digits wrong.\n"); + } + Pause(); + break; + + case 2: + BadCond(Failure, "Underflow confuses Comparison, which alleges that\n"); + printf("Q == Y while denying that |Q - Y| == 0; these values\n"); + printf("print out as Q = %.17e, Y = %.17e .\n", Q, Y2); + printf ("|Q - Y| = %.17e .\n" , FABS(Q - Y2)); + UfThold = Q; + break; + + case 3: + X = X; + break; + + case 4: + if ((Q == UfThold) && (E1 == E0) + && (FABS( UfThold - E1 / E9) <= E1)) { + UfNGrad = False; + printf("Underflow is gradual; it incurs Absolute Error =\n"); + printf("(roundoff in UfThold) < E0.\n"); + Y = E0 * CInvrse; + Y = Y * (OneAndHalf + U2); + X = CInvrse * (One + U2); + Y = Y / X; + IEEE = (Y == E0); + } + } + if (UfNGrad) { + printf("\n"); + sigsave = sigfpe; + if (setjmp(ovfl_buf)) { + printf("Underflow / UfThold failed!\n"); + R = H + H; + } + else R = SQRT(Underflow / UfThold); + sigsave = 0; + if (R <= H) { + Z = R * UfThold; + X = Z * (One + R * H * (One + H)); + } + else { + Z = UfThold; + X = Z * (One + H * H * (One + H)); + } + if (! ((X == Z) || (X - Z != Zero))) { + BadCond(Flaw, ""); + printf("X = %.17e\n\tis not equal to Z = %.17e .\n", X, Z); + Z9 = X - Z; + printf("yet X - Z yields %.17e .\n", Z9); + printf(" Should this NOT signal Underflow, "); + printf("this is a SERIOUS DEFECT\nthat causes "); + printf("confusion when innocent statements like\n");; + printf(" if (X == Z) ... else"); + printf(" ... (f(X) - f(Z)) / (X - Z) ...\n"); + printf("encounter Division by Zero although actually\n"); + sigsave = sigfpe; + if (setjmp(ovfl_buf)) printf("X / Z fails!\n"); + else printf("X / Z = 1 + %g .\n", (X / Z - Half) - Half); + sigsave = 0; + } + } + printf("The Underflow threshold is %.17e, %s\n", UfThold, + " below which"); + printf("calculation may suffer larger Relative error than "); + printf("merely roundoff.\n"); + Y2 = U1 * U1; + Y = Y2 * Y2; + Y2 = Y * U1; + if (Y2 <= UfThold) { + if (Y > E0) { + BadCond(Defect, ""); + I = 5; + } + else { + BadCond(Serious, ""); + I = 4; + } + printf("Range is too narrow; U1^%d Underflows.\n", I); + } + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +part7(){ +*/ + Milestone = 130; + /*=============================================*/ + Y = - FLOOR(Half - TwoForty * LOG(UfThold) / LOG(HInvrse)) / TwoForty; + Y2 = Y + Y; + printf("Since underflow occurs below the threshold\n"); + printf("UfThold = (%.17e) ^ (%.17e)\nonly underflow ", HInvrse, Y); + printf("should afflict the expression\n\t(%.17e) ^ (%.17e);\n", HInvrse, Y); + V9 = POW(HInvrse, Y2); + printf("actually calculating yields: %.17e .\n", V9); + if (! ((V9 >= Zero) && (V9 <= (Radix + Radix + E9) * UfThold))) { + BadCond(Serious, "this is not between 0 and underflow\n"); + printf(" threshold = %.17e .\n", UfThold); + } + else if (! (V9 > UfThold * (One + E9))) + printf("This computed value is O.K.\n"); + else { + BadCond(Defect, "this is not between 0 and underflow\n"); + printf(" threshold = %.17e .\n", UfThold); + } + /*=============================================*/ + Milestone = 140; + /*=============================================*/ + printf("\n"); + /* ...calculate Exp2 == exp(2) == 7.389056099... */ + X = Zero; + I = 2; + Y = Two * Three; + Q = Zero; + N = 0; + do { + Z = X; + I = I + 1; + Y = Y / (I + I); + R = Y + Q; + X = Z + R; + Q = (Z - X) + R; + } while(X > Z); + Z = (OneAndHalf + One / Eight) + X / (OneAndHalf * ThirtyTwo); + X = Z * Z; + Exp2 = X * X; + X = F9; + Y = X - U1; + printf("Testing X^((X + 1) / (X - 1)) vs. exp(2) = %.17e as X -> 1.\n", + Exp2); + for(I = 1;;) { + Z = X - BInvrse; + Z = (X + One) / (Z - (One - BInvrse)); + Q = POW(X, Z) - Exp2; + if (FABS(Q) > TwoForty * U2) { + N = 1; + V9 = (X - BInvrse) - (One - BInvrse); + BadCond(Defect, "Calculated"); + printf(" %.17e for\n", POW(X,Z)); + printf("\t(1 + (%.17e) ^ (%.17e);\n", V9, Z); + printf("\tdiffers from correct value by %.17e .\n", Q); + printf("\tThis much error may spoil financial\n"); + printf("\tcalculations involving tiny interest rates.\n"); + break; + } + else { + Z = (Y - X) * Two + Y; + X = Y; + Y = Z; + Z = One + (X - F9)*(X - F9); + if (Z > One && I < NoTrials) I++; + else { + if (X > One) { + if (N == 0) + printf("Accuracy seems adequate.\n"); + break; + } + else { + X = One + U2; + Y = U2 + U2; + Y += X; + I = 1; + } + } + } + } + /*=============================================*/ + Milestone = 150; + /*=============================================*/ + printf("Testing powers Z^Q at four nearly extreme values.\n"); + N = 0; + Z = A1; + Q = FLOOR(Half - LOG(C) / LOG(A1)); + Break = False; + do { + X = CInvrse; + Y = POW(Z, Q); + IsYeqX(); + Q = - Q; + X = C; + Y = POW(Z, Q); + IsYeqX(); + if (Z < One) Break = True; + else Z = AInvrse; + } while ( ! (Break)); + PrintIfNPositive(); + if (N == 0) printf(" ... no discrepancies found.\n"); + printf("\n"); + + /*=============================================*/ + Milestone = 160; + /*=============================================*/ + Pause(); + printf("Searching for Overflow threshold:\n"); + printf("This may generate an error.\n"); + Y = - CInvrse; + V9 = HInvrse * Y; + sigsave = sigfpe; + if (setjmp(ovfl_buf)) { I = 0; V9 = Y; goto overflow; } + do { + V = Y; + Y = V9; + V9 = HInvrse * Y; + } while(V9 < Y); + I = 1; +overflow: + sigsave = 0; + Z = V9; + printf("Can `Z = -Y' overflow?\n"); + printf("Trying it on Y = %.17e .\n", Y); + V9 = - Y; + V0 = V9; + if (V - Y == V + V0) printf("Seems O.K.\n"); + else { + printf("finds a "); + BadCond(Flaw, "-(-Y) differs from Y.\n"); + } + if (Z != Y) { + BadCond(Serious, ""); + printf("overflow past %.17e\n\tshrinks to %.17e .\n", Y, Z); + } + if (I) { + Y = V * (HInvrse * U2 - HInvrse); + Z = Y + ((One - HInvrse) * U2) * V; + if (Z < V0) Y = Z; + if (Y < V0) V = Y; + if (V0 - V < V0) V = V0; + } + else { + V = Y * (HInvrse * U2 - HInvrse); + V = V + ((One - HInvrse) * U2) * Y; + } + printf("Overflow threshold is V = %.17e .\n", V); + if (I) printf("Overflow saturates at V0 = %.17e .\n", V0); + else printf("There is no saturation value because the system traps on overflow.\n"); + V9 = V * One; + printf("No Overflow should be signaled for V * 1 = %.17e\n", V9); + V9 = V / One; + printf(" nor for V / 1 = %.17e .\n", V9); + printf("Any overflow signal separating this * from the one\n"); + printf("above is a DEFECT.\n"); + /*=============================================*/ + Milestone = 170; + /*=============================================*/ + if (!(-V < V && -V0 < V0 && -UfThold < V && UfThold < V)) { + BadCond(Failure, "Comparisons involving "); + printf("+-%g, +-%g\nand +-%g are confused by Overflow.", + V, V0, UfThold); + } + /*=============================================*/ + Milestone = 175; + /*=============================================*/ + printf("\n"); + for(Indx = 1; Indx <= 3; ++Indx) { + switch (Indx) { + case 1: Z = UfThold; break; + case 2: Z = E0; break; + case 3: Z = PseudoZero; break; + } + if (Z != Zero) { + V9 = SQRT(Z); + Y = V9 * V9; + if (Y / (One - Radix * E9) < Z + || Y > (One + Radix * E9) * Z) { /* dgh: + E9 --> * E9 */ + if (V9 > U1) BadCond(Serious, ""); + else BadCond(Defect, ""); + printf("Comparison alleges that what prints as Z = %.17e\n", Z); + printf(" is too far from sqrt(Z) ^ 2 = %.17e .\n", Y); + } + } + } + /*=============================================*/ + Milestone = 180; + /*=============================================*/ + for(Indx = 1; Indx <= 2; ++Indx) { + if (Indx == 1) Z = V; + else Z = V0; + V9 = SQRT(Z); + X = (One - Radix * E9) * V9; + V9 = V9 * X; + if (((V9 < (One - Two * Radix * E9) * Z) || (V9 > Z))) { + Y = V9; + if (X < W) BadCond(Serious, ""); + else BadCond(Defect, ""); + printf("Comparison alleges that Z = %17e\n", Z); + printf(" is too far from sqrt(Z) ^ 2 (%.17e) .\n", Y); + } + } + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +part8(){ +*/ + Milestone = 190; + /*=============================================*/ + Pause(); + X = UfThold * V; + Y = Radix * Radix; + if (X*Y < One || X > Y) { + if (X * Y < U1 || X > Y/U1) BadCond(Defect, "Badly"); + else BadCond(Flaw, ""); + + printf(" unbalanced range; UfThold * V = %.17e\n\t%s\n", + X, "is too far from 1.\n"); + } + /*=============================================*/ + Milestone = 200; + /*=============================================*/ + for (Indx = 1; Indx <= 5; ++Indx) { + X = F9; + switch (Indx) { + case 2: X = One + U2; break; + case 3: X = V; break; + case 4: X = UfThold; break; + case 5: X = Radix; + } + Y = X; + sigsave = sigfpe; + if (setjmp(ovfl_buf)) + printf(" X / X traps when X = %g\n", X); + else { + V9 = (Y / X - Half) - Half; + if (V9 == Zero) continue; + if (V9 == - U1 && Indx < 5) BadCond(Flaw, ""); + else BadCond(Serious, ""); + printf(" X / X differs from 1 when X = %.17e\n", X); + printf(" instead, X / X - 1/2 - 1/2 = %.17e .\n", V9); + } + sigsave = 0; + } + /*=============================================*/ + Milestone = 210; + /*=============================================*/ + MyZero = Zero; + printf("\n"); + printf("What message and/or values does Division by Zero produce?\n") ; +#ifndef NOPAUSE + printf("This can interupt your program. You can "); + printf("skip this part if you wish.\n"); + printf("Do you wish to compute 1 / 0? "); + fflush(stdout); + read (KEYBOARD, ch, 8); + if ((ch[0] == 'Y') || (ch[0] == 'y')) { +#endif + sigsave = sigfpe; + printf(" Trying to compute 1 / 0 produces ..."); + if (!setjmp(ovfl_buf)) printf(" %.7e .\n", One / MyZero); + sigsave = 0; +#ifndef NOPAUSE + } + else printf("O.K.\n"); + printf("\nDo you wish to compute 0 / 0? "); + fflush(stdout); + read (KEYBOARD, ch, 80); + if ((ch[0] == 'Y') || (ch[0] == 'y')) { +#endif + sigsave = sigfpe; + printf("\n Trying to compute 0 / 0 produces ..."); + if (!setjmp(ovfl_buf)) printf(" %.7e .\n", Zero / MyZero); + sigsave = 0; +#ifndef NOPAUSE + } + else printf("O.K.\n"); +#endif + /*=============================================*/ + Milestone = 220; + /*=============================================*/ + Pause(); + printf("\n"); + { + static char *msg[] = { + "FAILUREs encountered =", + "SERIOUS DEFECTs discovered =", + "DEFECTs discovered =", + "FLAWs discovered =" }; + int i; + for(i = 0; i < 4; i++) if (ErrCnt[i]) + printf("The number of %-29s %d.\n", + msg[i], ErrCnt[i]); + } + printf("\n"); + if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] + + ErrCnt[Flaw]) > 0) { + if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[ + Defect] == 0) && (ErrCnt[Flaw] > 0)) { + printf("The arithmetic diagnosed seems "); + printf("Satisfactory though flawed.\n"); + } + if ((ErrCnt[Failure] + ErrCnt[Serious] == 0) + && ( ErrCnt[Defect] > 0)) { + printf("The arithmetic diagnosed may be Acceptable\n"); + printf("despite inconvenient Defects.\n"); + } + if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0) { + printf("The arithmetic diagnosed has "); + printf("unacceptable Serious Defects.\n"); + } + if (ErrCnt[Failure] > 0) { + printf("Potentially fatal FAILURE may have spoiled this"); + printf(" program's subsequent diagnoses.\n"); + } + } + else { + printf("No failures, defects nor flaws have been discovered.\n"); + if (! ((RMult == Rounded) && (RDiv == Rounded) + && (RAddSub == Rounded) && (RSqrt == Rounded))) + printf("The arithmetic diagnosed seems Satisfactory.\n"); + else { + if (StickyBit >= One && + (Radix - Two) * (Radix - Nine - One) == Zero) { + printf("Rounding appears to conform to "); + printf("the proposed IEEE standard P"); + if ((Radix == Two) && + ((Precision - Four * Three * Two) * + ( Precision - TwentySeven - + TwentySeven + One) == Zero)) + printf("754"); + else printf("854"); + if (IEEE) printf(".\n"); + else { + printf(",\nexcept for possibly Double Rounding"); + printf(" during Gradual Underflow.\n"); + } + } + printf("The arithmetic diagnosed appears to be Excellent!\n"); + } + } + if (fpecount) + printf("\nA total of %d floating point exceptions were registered.\n", + fpecount); + printf("END OF TEST.\n"); + return 0; + } + +/*SPLIT subs.c +#include "paranoia.h" +*/ + +/* Sign */ + +FLOAT Sign (X) +FLOAT X; +{ return X >= 0. ? 1.0 : -1.0; } + +/* Pause */ + +Pause() +{ +#ifndef NOPAUSE + char ch[8]; + + printf("\nTo continue, press RETURN"); + fflush(stdout); + read(KEYBOARD, ch, 8); +#endif + printf("\nDiagnosis resumes after milestone Number %d", Milestone); + printf(" Page: %d\n\n", PageNo); + ++Milestone; + ++PageNo; + } + + /* TstCond */ + +TstCond (K, Valid, T) +int K, Valid; +char *T; +{ if (! Valid) { BadCond(K,T); printf(".\n"); } } + +BadCond(K, T) +int K; +char *T; +{ + static char *msg[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" }; + + ErrCnt [K] = ErrCnt [K] + 1; + printf("%s: %s", msg[K], T); + } + +/* Random */ +/* Random computes + X = (Random1 + Random9)^5 + Random1 = X - FLOOR(X) + 0.000005 * X; + and returns the new value of Random1 +*/ + +FLOAT Random() +{ + FLOAT X, Y; + + X = Random1 + Random9; + Y = X * X; + Y = Y * Y; + X = X * Y; + Y = X - FLOOR(X); + Random1 = Y + X * 0.000005; + return(Random1); + } + +/* SqXMinX */ + +SqXMinX (ErrKind) +int ErrKind; +{ + FLOAT XA, XB; + + XB = X * BInvrse; + XA = X - XB; + SqEr = ((SQRT(X * X) - XB) - XA) / OneUlp; + if (SqEr != Zero) { + if (SqEr < MinSqEr) MinSqEr = SqEr; + if (SqEr > MaxSqEr) MaxSqEr = SqEr; + J = J + 1.0; + BadCond(ErrKind, "\n"); + printf("sqrt( %.17e) - %.17e = %.17e\n", X * X, X, OneUlp * SqEr); + printf("\tinstead of correct value 0 .\n"); + } + } + +/* NewD */ + +NewD() +{ + X = Z1 * Q; + X = FLOOR(Half - X / Radix) * Radix + X; + Q = (Q - X * Z) / Radix + X * X * (D / Radix); + Z = Z - Two * X * D; + if (Z <= Zero) { + Z = - Z; + Z1 = - Z1; + } + D = Radix * D; + } + +/* SR3750 */ + +SR3750() +{ + if (! ((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2))) { + I = I + 1; + X2 = SQRT(X * D); + Y2 = (X2 - Z2) - (Y - Z2); + X2 = X8 / (Y - Half); + X2 = X2 - Half * X2 * X2; + SqEr = (Y2 + Half) + (Half - X2); + if (SqEr < MinSqEr) MinSqEr = SqEr; + SqEr = Y2 - X2; + if (SqEr > MaxSqEr) MaxSqEr = SqEr; + } + } + +/* IsYeqX */ + +IsYeqX() +{ + if (Y != X) { + if (N <= 0) { + if (Z == Zero && Q <= Zero) + printf("WARNING: computing\n"); + else BadCond(Defect, "computing\n"); + printf("\t(%.17e) ^ (%.17e)\n", Z, Q); + printf("\tyielded %.17e;\n", Y); + printf("\twhich compared unequal to correct %.17e ;\n", + X); + printf("\t\tthey differ by %.17e .\n", Y - X); + } + N = N + 1; /* ... count discrepancies. */ + } + } + +/* SR3980 */ + +SR3980() +{ + do { + Q = (FLOAT) I; + Y = POW(Z, Q); + IsYeqX(); + if (++I > M) break; + X = Z * X; + } while ( X < W ); + } + +/* PrintIfNPositive */ + +PrintIfNPositive() +{ + if (N > 0) printf("Similar discrepancies have occurred %d times.\n", N); + } + +/* TstPtUf */ + +TstPtUf() +{ + N = 0; + if (Z != Zero) { + printf("Since comparison denies Z = 0, evaluating "); + printf("(Z + Z) / Z should be safe.\n"); + sigsave = sigfpe; + if (setjmp(ovfl_buf)) goto very_serious; + Q9 = (Z + Z) / Z; + printf("What the machine gets for (Z + Z) / Z is %.17e .\n", + Q9); + if (FABS(Q9 - Two) < Radix * U2) { + printf("This is O.K., provided Over/Underflow"); + printf(" has NOT just been signaled.\n"); + } + else { + if ((Q9 < One) || (Q9 > Two)) { +very_serious: + N = 1; + ErrCnt [Serious] = ErrCnt [Serious] + 1; + printf("This is a VERY SERIOUS DEFECT!\n"); + } + else { + N = 1; + ErrCnt [Defect] = ErrCnt [Defect] + 1; + printf("This is a DEFECT!\n"); + } + } + sigsave = 0; + V9 = Z * One; + Random1 = V9; + V9 = One * Z; + Random2 = V9; + V9 = Z / One; + if ((Z == Random1) && (Z == Random2) && (Z == V9)) { + if (N > 0) Pause(); + } + else { + N = 1; + BadCond(Defect, "What prints as Z = "); + printf("%.17e\n\tcompares different from ", Z); + if (Z != Random1) printf("Z * 1 = %.17e ", Random1); + if (! ((Z == Random2) + || (Random2 == Random1))) + printf("1 * Z == %g\n", Random2); + if (! (Z == V9)) printf("Z / 1 = %.17e\n", V9); + if (Random2 != Random1) { + ErrCnt [Defect] = ErrCnt [Defect] + 1; + BadCond(Defect, "Multiplication does not commute!\n"); + printf("\tComparison alleges that 1 * Z = %.17e\n", + Random2); + printf("\tdiffers from Z * 1 = %.17e\n", Random1); + } + Pause(); + } + } + } + +notify(s) +char *s; +{ + printf("%s test appears to be inconsistent...\n", s); + printf(" PLEASE NOTIFY KARPINKSI!\n"); + } + +/*SPLIT msgs.c */ + +/* Instructions */ + +msglist(s) +char **s; +{ while(*s) printf("%s\n", *s++); } + +Instructions() +{ + static char *instr[] = { + "Lest this program stop prematurely, i.e. before displaying\n", + " `END OF TEST',\n", + "try to persuade the computer NOT to terminate execution when an", + "error like Over/Underflow or Division by Zero occurs, but rather", + "to persevere with a surrogate value after, perhaps, displaying some", + "warning. If persuasion avails naught, don't despair but run this", + "program anyway to see how many milestones it passes, and then", + "amend it to make further progress.\n", + "Answer questions with Y, y, N or n (unless otherwise indicated).\n", + 0}; + + msglist(instr); + } + +/* Heading */ + +Heading() +{ + static char *head[] = { + "Users are invited to help debug and augment this program so it will", + "cope with unanticipated and newly uncovered arithmetic pathologies.\n", + "Please send suggestions and interesting results to", + "\tRichard Karpinski", + "\tComputer Center U-76", + "\tUniversity of California", + "\tSan Francisco, CA 94143-0704, USA\n", + "In doing so, please include the following information:", +#ifdef Single + "\tPrecision:\tsingle;", +#else + "\tPrecision:\tdouble;", +#endif + "\tVersion:\t10 February 1989;", + "\tComputer:\n", + "\tCompiler:\n", + "\tOptimization level:\n", + "\tOther relevant compiler options:", + 0}; + + msglist(head); + } + +/* Characteristics */ + +Characteristics() +{ + static char *chars[] = { + "Running this program should reveal these characteristics:", + " Radix = 1, 2, 4, 8, 10, 16, 100, 256 ...", + " Precision = number of significant digits carried.", + " U2 = Radix/Radix^Precision = One Ulp", + "\t(OneUlpnit in the Last Place) of 1.000xxx .", + " U1 = 1/Radix^Precision = One Ulp of numbers a little less than 1.0 .", + " Adequacy of guard digits for Mult., Div. and Subt.", + " Whether arithmetic is chopped, correctly rounded, or something else", + "\tfor Mult., Div., Add/Subt. and Sqrt.", + " Whether a Sticky Bit used correctly for rounding.", + " UnderflowThreshold = an underflow threshold.", + " E0 and PseudoZero tell whether underflow is abrupt, gradual, or fuzzy.", + " V = an overflow threshold, roughly.", + " V0 tells, roughly, whether Infinity is represented.", + " Comparisions are checked for consistency with subtraction", + "\tand for contamination with pseudo-zeros.", + " Sqrt is tested. Y^X is not tested.", + " Extra-precise subexpressions are revealed but NOT YET tested.", + " Decimal-Binary conversion is NOT YET tested for accuracy.", + 0}; + + msglist(chars); + } + +History() + +{ /* History */ + /* Converted from Brian Wichmann's Pascal version to C by Thos Sumner, + with further massaging by David M. Gay. */ + + static char *hist[] = { + "The program attempts to discriminate among", + " FLAWs, like lack of a sticky bit,", + " Serious DEFECTs, like lack of a guard digit, and", + " FAILUREs, like 2+2 == 5 .", + "Failures may confound subsequent diagnoses.\n", + "The diagnostic capabilities of this program go beyond an earlier", + "program called `MACHAR', which can be found at the end of the", + "book `Software Manual for the Elementary Functions' (1980) by", + "W. J. Cody and W. Waite. Although both programs try to discover", + "the Radix, Precision and range (over/underflow thresholds)", + "of the arithmetic, this program tries to cope with a wider variety", + "of pathologies, and to say how well the arithmetic is implemented.", + "\nThe program is based upon a conventional radix representation for", + "floating-point numbers, but also allows logarithmic encoding", + "as used by certain early WANG machines.\n", + "BASIC version of this program (C) 1983 by Prof. W. M. Kahan;", + "see source comments for more history.", + 0}; + + msglist(hist); + } + +double +pow(x, y) /* return x ^ y (exponentiation) */ +double x, y; +{ + extern double exp(), frexp(), ldexp(), log(), modf(); + double xy, ye; + long i; + int ex, ey = 0, flip = 0; + + if (!y) return 1.0; + + if ((y < -1100. || y > 1100.) && x != -1.) return exp(y * log(x)); + + if (y < 0.) { y = -y; flip = 1; } + y = modf(y, &ye); + if (y) xy = exp(y * log(x)); + else xy = 1.0; + /* next several lines assume >= 32 bit integers */ + x = frexp(x, &ex); + if (i = ye) for(;;) { + if (i & 1) { xy *= x; ey += ex; } + if (!(i >>= 1)) break; + x *= x; + ex *= 2; + if (x < .5) { x *= 2.; ex -= 1; } + } + if (flip) { xy = 1. / xy; ey = -ey; } + return ldexp(xy, ey); +} + +#endif /* NO_FLOATS */ diff --git a/test/ref/pointer2.c b/test/ref/pointer2.c new file mode 100644 index 000000000..69d04a989 --- /dev/null +++ b/test/ref/pointer2.c @@ -0,0 +1,111 @@ +/* + !!DESCRIPTION!! pointer test + !!ORIGIN!! + !!LICENCE!! public domain +*/ + +#include <stdio.h> + +/* + check behaviour on incompletely declared arrays +*/ + +char i1[]; + +void test1(void) { +int a; + + a=sizeof(i1[0]); + printf("%04x - ",a); + if(sizeof(i1[0])==sizeof(char)) { + /* gcc gives size of element */ + printf("sizeof(i1[0]) gives size of element\n"); + } + if(sizeof(i1[0])==sizeof(char*)) { + printf("sizeof(i1[0]) gives size of pointer to element\n"); + } +} + +/* + check behaviour on string init +*/ + +char t1[]="abcde"; +char t2[]={"abcde"}; + +char *t3="abcde"; +char *t4={"abcde"}; + +void test2(void) { +char c1,c2,c3,c4; +int i,e=0; + for(i=0;i<5;i++){ + c1=t1[i];c2=t2[i];c3=t3[i];c4=t4[i]; +/* printf("%02x %02x %02x %02x\n",c1,c2,c3,c4); */ + printf("%c %c %c %c\n",c1,c2,c3,c4); + if(!((c1==c2)&(c1==c3)&(c1==c4))) e=1; + } + if(e) printf("test2 failed.\n"); + else printf("test2 ok.\n"); +} + +/* + check behaviour on extern-declarations inside functions +*/ + +typedef struct { + char *name; + void *func; +} A3; + +#ifdef NO_SLOPPY_STRUCT_INIT +A3 a3[] = { + { "test3", (void*) NULL }, + { "test3", (void*) NULL }, +}; +#else +/*gcc warning: missing braces around initializer (near initialization for `a3[0]') + this type of struct-initialization seems to be kinda common */ +A3 a3[] = { + "test3", (void*) NULL , + "test3", (void*) NULL , +}; +#endif + +void test3a(A3 *list, int number){ + printf("%s %d\n",list->name,number); +} + +static void test31(void) +{ + extern A3 a3[]; + test3a(a3, -1); +} + +#if 0 +/* this variation compiles and works with cc65, but gives an error with gcc :=P */ +static void test32(void) +{ + extern A3 *a3; + test3a(a3, -1); +} +#endif + +static void test30(void) +{ + test3a(a3, -1); +} + +/* + todo: add test on function pointers in the form of (*func)(arg) ... + cc65 seems to have problems here aswell ;/ +*/ + +int main(void) { + test1(); + test2(); + test30(); + test31(); +/* test32(); */ + return 0; +} diff --git a/test/ref/return.c b/test/ref/return.c new file mode 100644 index 000000000..0ea12d509 --- /dev/null +++ b/test/ref/return.c @@ -0,0 +1,96 @@ +/* + !!DESCRIPTION!! return values, implicit type conversion on return + !!ORIGIN!! cc65 devel list + !!LICENCE!! Public Domain +*/ + +#include <stdio.h> +#include <stdlib.h> + +unsigned char val_char=0x76; +unsigned int val_int=0x5678; +unsigned long val_long=0x12345678; + +int test1_int_char(void) +{ + return val_char; +} +int test1_int_int(void) +{ + return val_int; +} + +int test2_int_char(void) +{ + return (int)val_char; +} +int test2_int_int(void) +{ + return (int)val_int; +} + +long test1_long_char(void) +{ + return val_char; +} +long test1_long_int(void) +{ + return val_int; +} +long test1_long_long(void) +{ + return val_long; +} + +long test2_long_char(void) +{ + return (long)val_char; +} +long test2_long_int(void) +{ + return (long)val_int; +} +long test2_long_long(void) +{ + return (long)val_long; +} + +#define dotest(_n,_a,_v) \ + _n=_a; \ + printf("%04lx %04lx,",(unsigned long)_n,(unsigned long)_v); \ + if(_n!=_v) printf("failed\n"); \ + else printf("ok\n") + +int main(void) +{ +int i; +unsigned long l; + + printf("\nwithout cast:\n"); + + printf("return int\n"); + + dotest(i,test1_int_char(),0x76); + dotest(i,test1_int_int(),0x5678); + + printf("return long\n"); + + dotest(l,test1_long_char(),0x76); + dotest(l,test1_long_int(),0x5678); + dotest(l,test1_long_long(),0x12345678); + + printf("\nwith cast:\n"); + + printf("return int\n"); + + dotest(i,test2_int_char(),0x76); + dotest(i,test2_int_int(),0x5678); + + printf("return long\n"); + + dotest(l,test2_long_char(),0x76); + dotest(l,test2_long_int(),0x5678); + dotest(l,test2_long_long(),0x12345678); + + return 0; +} diff --git a/test/ref/sort.c b/test/ref/sort.c new file mode 100644 index 000000000..5db5cf01b --- /dev/null +++ b/test/ref/sort.c @@ -0,0 +1,75 @@ +/* + !!DESCRIPTION!! simple quicksort, tests recursion + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +#include <stdlib.h> +#include <stdio.h> + +int in[] = {10, 32, -1, 567, 3, 18, 1, -51, 789, 0}; +int *xx; + +/* exchange - exchange *x and *y */ +exchange(int *x,int *y) { +int t; + + printf("exchange(%d,%d)\n", x - xx, y - xx); + t = *x; *x = *y; *y = t; +} + +/* partition - partition a[i..j] */ +int partition(int a[], int i, int j) { +int v, k; + + j++; + k = i; + v = a[k]; + while (i < j) { + i++; while (a[i] < v) i++; + j--; while (a[j] > v) j--; + if (i < j) exchange(&a[i], &a[j]); + } + exchange(&a[k], &a[j]); + return j; +} + +/* quick - quicksort a[lb..ub] */ +void quick(int a[], int lb, int ub) { + int k; + + if (lb >= ub) + return; + k = partition(a, lb, ub); + quick(a, lb, k - 1); + quick(a, k + 1, ub); +} + +/* sort - sort a[0..n-1] into increasing order */ +sort(int a[], int n) { + quick(xx = a, 0, --n); +} + +/* putd - output decimal number */ +void putd(int n) { + if (n < 0) { + putchar('-'); + n = -n; + } + if (n/10) + putd(n/10); + putchar(n%10 + '0'); +} + +int main(void) { + int i; + + sort(in, (sizeof in)/(sizeof in[0])); + for (i = 0; i < (sizeof in)/(sizeof in[0]); i++) { + putd(in[i]); + putchar('\n'); + } + + return 0; +} + diff --git a/test/ref/spill.c b/test/ref/spill.c new file mode 100644 index 000000000..2aedf0c8c --- /dev/null +++ b/test/ref/spill.c @@ -0,0 +1,55 @@ +/* + !!DESCRIPTION!! register spilling + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +#include <stdio.h> + +int main(void) +{ + printf("disassemble this program to check the generated code.\n"); + return 0; +} + +#ifdef NO_EMPTY_FUNC_ARGS + f(i){return i+i;} + f2(i){return f(i)+(i?f(i):1);} + f3(int i,int *p){ + register r1=0,r2=0,r3=0,r4=0,r5=0,r6=0,r7=0,r8=0,r9=0,r10=0; + *p++=i?f(i):0; + } +#else + f(i){i=f()+f();} + f2(i){i=f()+(i?f():1);} + f3(int i,int *p){ + register r1=0,r2=0,r3=0,r4=0,r5=0,r6=0,r7=0,r8=0,r9=0,r10=0; + *p++=i?f():0; + } +#endif + +#ifdef NO_FLOATS + signed a[10],b[10]; +#else + double a[10],b[10]; +#endif + +int i; + +f4(){ +register r6=0,r7=0,r8=0,r9=0,r10=0,r11=0; + i=a[i]+b[i] && i && a[i]-b[i]; +} +/* f4 causes parent to spill child on vax when odd double regs are enabled */ + +int j, k, m, n; +#ifdef NO_FLOATS + signed *A, *B, x; +#else + double *A, *B, x; +#endif + +f5(){ + x=A[k*m]*A[j*m]+B[k*n]*B[j*n]; + x=A[k*m]*B[j*n]-B[k*n]*A[j*m]; +} diff --git a/test/ref/stdarg.c b/test/ref/stdarg.c new file mode 100644 index 000000000..b476cf338 --- /dev/null +++ b/test/ref/stdarg.c @@ -0,0 +1,93 @@ +/* + !!DESCRIPTION!! variable argument lists + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +#include <stdarg.h> + +#ifndef NO_FUNCS_TAKE_STRUCTS +struct node +{ + int a[4]; +} x = +{ +#ifdef NO_SLOPPY_STRUCT_INIT + { +#endif + 1,2,3,4 +#ifdef NO_SLOPPY_STRUCT_INIT + } +#endif +}; +#endif + +print(char *fmt, ...); + +main() +{ + print("test 1\n"); + print("test %s\n", "2"); + print("test %d%c", 3, '\n'); + print("%s%s %w%c", "te", "st", 4, '\n'); + #ifdef NO_FLOATS + print("%s%s %f%c", "te", "st", (signed long) 5, '\n'); + #else + print("%s%s %f%c", "te", "st", 5.0, '\n'); + #endif + #ifndef NO_FUNCS_TAKE_STRUCTS + print("%b %b %b %b %b %b\n", x, x, x, x, x, x); + #endif + return 0; +} + +print(char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + for (; *fmt; fmt++) + { + if (*fmt == '%') + switch (*++fmt) { + case 'b': { + #ifdef NO_FUNCS_TAKE_STRUCTS + printf("(1 2 3 4)"); + #else + struct node x = + va_arg( + ap, + struct node + ); + printf("(%d %d %d %d)", x.a[0], x.a[1], x.a[2], x.a[3]); + #endif + break; + } + case 'c': + /* printf("%c", va_arg(ap, char)); */ + printf("%c", va_arg(ap, int)); + break; + case 'd': + printf("%d", va_arg(ap, int)); + break; + case 'w': + /* printf("%x", va_arg(ap, short)); */ + printf("%x", va_arg(ap, int)); + break; + case 's': + printf("%s", va_arg(ap, char *)); + break; + case 'f': + #ifdef NO_FLOATS + printf("%ld.000000", va_arg(ap, signed long)); + #else + printf("%f", va_arg(ap, double)); + #endif + break; + default: + printf("%c", *fmt); + break; + } + else + printf("%c", *fmt); + } + va_end(ap); +} diff --git a/test/ref/strptr.c b/test/ref/strptr.c new file mode 100644 index 000000000..8bfa983a8 --- /dev/null +++ b/test/ref/strptr.c @@ -0,0 +1,130 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Groepaz/Hitmen +*/ + +/* + this test reproduces a bug that prevented the testsuites directory + reading stuff for the c64 from working before. the bug appears to + only occur when optimizations are enabled. it also disappears if + the buffers inside the readdir function are declared static or + made global. +*/ + +/*#define STANDALONE*/ + +#ifdef STANDALONE + +FILE *outfile=NULL; +#define OPENTEST() outfile=stdout; +#define CLOSETEST() + +#else + +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> + +#define XNAME_MAX 16 + +struct Xdirent +{ + char d_name[XNAME_MAX+1]; + unsigned short d_off; + unsigned short d_reclen; + unsigned char d_type; + unsigned char d_namlen; +}; + +typedef struct +{ + unsigned char fd; + unsigned short off; + char name[XNAME_MAX+1]; +} XDIR; + +unsigned char b1[4]; +unsigned char b2[0x10]={" \"test\" "}; + +struct Xdirent *Xreaddir(XDIR *dir) +{ +unsigned char buffer[0x40]; +unsigned char temp; +unsigned char i,ii; + +static struct Xdirent entry; +unsigned char fd; +static unsigned char ch; + + entry.d_off=dir->off; + + /* basic line-link / file-length */ + memcpy(buffer,b1,4); + + dir->off=dir->off+4; + entry.d_reclen=254*(buffer[2]+(buffer[3]<<8)); + + /* read file entry */ + memcpy(buffer,b2,0x10); + + dir->off=dir->off+i; + + printf("Xreaddir: '%s'\n",buffer); + + /* skip until either quote (file) or b (blocks free => end) */ + i=0;ii=0; + while(i==0){ + temp=buffer[ii];ii++; + if(ii>16){ + /* something went wrong...this shouldnt happen! */ + return(NULL); + } + else if(temp=='\"') i++; + else if(temp=='b') { + /* "blocks free" */ + return(NULL); + } + } + printf("Xreaddir: '%s'\n",buffer); + + /* process file entry */ + + i=0; temp=buffer[ii];ii++; + while(temp!='\"'){ + entry.d_name[i]=temp; + i++; + temp=buffer[ii];ii++; + } + entry.d_name[i]=0; + entry.d_namlen=i; + + /* set type flag */ + + return(&entry); +} + +int main(void) +{ +char mydirname[XNAME_MAX+1]="."; +XDIR mydir; +struct Xdirent *mydirent; + + printf("start\n"); + + if((mydirent=Xreaddir(&mydir))==NULL) + { + printf("NULL\n"); + } + else + { + printf("=%s\n",mydirent->d_name); + } + printf("done\n"); + + return 0; +} diff --git a/test/ref/struct.c b/test/ref/struct.c new file mode 100644 index 000000000..ccd74953f --- /dev/null +++ b/test/ref/struct.c @@ -0,0 +1,261 @@ +/* + !!DESCRIPTION!! structs + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +typedef struct point { int x,y; } point; +typedef struct rect { point pt1, pt2; } rect; + +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) > (b) ? (a) : (b)) + +#ifdef NO_FUNCS_RETURN_STRUCTS +# ifdef NO_FUNCS_TAKE_STRUCTS +/* canonicalize rectangle coordinates */ +void canonrect(rect *d,rect *r) { + d->pt1.x = min(r->pt1.x, r->pt2.x); + d->pt1.y = min(r->pt1.y, r->pt2.y); + d->pt2.x = max(r->pt1.x, r->pt2.x); + d->pt2.y = max(r->pt1.y, r->pt2.y); +} +/* add two points */ +void addpoint(point *p, point *p1, point *p2) { + p->x= p1->x + p2->x; + p->y= p1->y + p2->y; +} +/* make a point from x and y components */ +void makepoint(point *p,int x, int y) { + p->x = x; + p->y = y; +} +/* make a rectangle from two points */ +void makerect(rect *d,point *p1, point *p2) { +rect r; + r.pt1.x = p1->x; + r.pt1.y = p1->y; + r.pt2.x = p2->x; + r.pt2.y = p2->y; + + canonrect(d,&r); +} + +#ifdef NO_SLOPPY_STRUCT_INIT +struct odd {char a[3]; } y = {{'a', 'b', 0 }}; +#else +struct odd {char a[3]; } y = {'a', 'b', 0}; +#endif + +odd(struct odd *y) { + struct odd *x = y; + printf("%s\n\r", x->a); +} + +# else /* FUNCS_TAKE_STRUCTS */ +/* canonicalize rectangle coordinates */ +void canonrect(rect *d,rect r) { + d->pt1.x = min(r.pt1.x, r.pt2.x); + d->pt1.y = min(r.pt1.y, r.pt2.y); + d->pt2.x = max(r.pt1.x, r.pt2.x); + d->pt2.y = max(r.pt1.y, r.pt2.y); +} +/* add two points */ +void addpoint(point *p, point p1, point p2) { + p->x= p1.x + p2.x; + p->y= p1.y + p2.y; +} +/* make a point from x and y components */ +void makepoint(point *p,int x, int y) { + p->x = x; + p->y = y; +} +/* make a rectangle from two points */ +void makerect(rect *d,point p1, point p2) { +rect r; + r.pt1 = p1; + r.pt2 = p2; + + canonrect(d,r); +} + +#ifdef NO_SLOPPY_STRUCT_INIT +struct odd {char a[3]; } y = {{'a', 'b', 0}}; +#else +struct odd {char a[3]; } y = {'a', 'b', 0}; +#endif + +odd(struct odd y) { + struct odd x = y; + printf("%s\n\r", x.a); +} + +# endif /* FUNCS_TAKE_STRUCTS */ + +#else /* FUNCS_RETURN_STRUCTS */ + +/* add two points */ +point addpoint(point p1, point p2) { + p1.x += p2.x; + p1.y += p2.y; + return p1; +} +/* canonicalize rectangle coordinates */ +rect canonrect(rect r) { + rect temp; + + temp.pt1.x = min(r.pt1.x, r.pt2.x); + temp.pt1.y = min(r.pt1.y, r.pt2.y); + temp.pt2.x = max(r.pt1.x, r.pt2.x); + temp.pt2.y = max(r.pt1.y, r.pt2.y); + return temp; +} +/* make a point from x and y components */ +point makepoint(int x, int y) { + point p; + + p.x = x; + p.y = y; + return p; +} + +/* make a rectangle from two points */ +rect makerect(point p1, point p2) { + rect r; + + r.pt1 = p1; + r.pt2 = p2; + return canonrect(r); +} + +struct odd {char a[3]; } y = +{ +#ifdef NO_SLOPPY_STRUCT_INIT + { +#endif + 'a', 'b', 0 +#ifdef NO_SLOPPY_STRUCT_INIT + } +#endif +}; + +odd(struct odd y) +{ + struct odd x + = y; + printf("%s\n\r", x.a); +} + +#endif + +/* is p in r? */ +# ifdef NO_FUNCS_TAKE_STRUCTS +int ptinrect(point *p, rect *r) { + return p->x >= r->pt1.x && p->x < r->pt2.x + && p->y >= r->pt1.y && p->y < r->pt2.y; +} +#else +int ptinrect(point p, rect r) { + return p.x >= r.pt1.x && p.x < r.pt2.x + && p.y >= r.pt1.y && p.y < r.pt2.y; +} +#endif + +#ifdef NO_FUNCS_RETURN_STRUCTS + +#ifdef NO_LOCAL_STRUCT_INIT +#ifdef NO_SLOPPY_STRUCT_INIT +point pts[] = { {-1, -1},{ 1, 1},{ 20, 300},{ 500, 400 } }; +#else +point pts[] = { -1, -1, 1, 1, 20, 300, 500, 400 }; +#endif +point origin = { 0, 0 }; +point maxpt = { 320, 320 }; +#endif + +main() { +int i; +point x; +rect screen; +#ifndef NO_LOCAL_STRUCT_INIT +point origin = { 0, 0 }; +point maxpt = { 320, 320 }; +#ifdef NO_SLOPPY_STRUCT_INIT +point pts[] = { {-1, -1},{ 1, 1},{ 20, 300},{ 500, 400 } }; +#else +point pts[] = { -1, -1, 1, 1, 20, 300, 500, 400 }; +#endif +#endif + + makepoint ( &x, -10, -10); +#ifdef NO_FUNCS_TAKE_STRUCTS + addpoint ( &maxpt, &maxpt, &x); +#else + addpoint ( &maxpt, maxpt, x); +#endif + makepoint ( &x, 10, 10); + +#ifdef NO_FUNCS_TAKE_STRUCTS + addpoint (&origin,&origin, &x); + makerect (&screen, &maxpt,&origin); +#else + addpoint (&origin,origin, x); + makerect (&screen, maxpt,origin); +#endif + + for (i = 0; i < sizeof pts/sizeof pts[0]; i++) { + makepoint(&x,pts[i].x, pts[i].y); + printf("(%d,%d) is ", pts[i].x, x.y); +#ifdef NO_FUNCS_TAKE_STRUCTS + if (ptinrect(&x, &screen) == 0) +#else + if (ptinrect(x, screen) == 0) +#endif + { + printf("not "); + } + printf("within (%d,%d; %d,%d)\n\r", screen.pt1.x, screen.pt1.y, + screen.pt2.x, screen.pt2.y); + } +#ifdef NO_FUNCS_TAKE_STRUCTS + odd(&y); +#else + odd(y); +#endif + + return 0; +} + +#else /* FUNCS_RETURN_STRUCTS */ + +main() { +int i; +point x, origin = { 0, 0 }, maxpt = { 320, 320 }; + +#ifdef NO_SLOPPY_STRUCT_INIT +point pts[] = { {-1, -1}, {1, 1}, {20, 300}, {500, 400} }; +#else +point pts[] = { -1, -1, 1, 1, 20, 300, 500, 400 }; +#endif + +rect screen = + makerect( + addpoint(maxpt, makepoint(-10, -10)), + addpoint(origin, makepoint(10, 10)) + ); + + test1(); + + for (i = 0; i < sizeof pts/sizeof pts[0]; i++) { + printf("(%d,%d) is ", pts[i].x, + (x = makepoint(pts[i].x, pts[i].y)).y); + if (ptinrect(x, screen) == 0) + printf("not "); + printf("within (%d,%d; %d,%d)\n\r", screen.pt1.x, screen.pt1.y, + screen.pt2.x, screen.pt2.y); + } + odd(y); + + return 0; +} + +#endif /* FUNCS_RETURN_STRUCTS */ diff --git a/test/ref/switch.c b/test/ref/switch.c new file mode 100644 index 000000000..1fc315d90 --- /dev/null +++ b/test/ref/switch.c @@ -0,0 +1,216 @@ +/* + !!DESCRIPTION!! switch statement + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +#include <limits.h> + +#ifdef NO_IMPLICIT_FUNC_PROTOTYPES +testbig(); +testbackslash(); +backslash(int c); +f(); +g(); +h(); +limit(); + +big( +# ifdef ASSUME_32BIT_UNSIGNED + unsigned +# else + unsigned long +# endif +x); + +#endif + +main() +{ + testbackslash(); + f(); + g(); + h(); + testbig(); /* ! broken long int compare (?) */ + limit(); /* ! broken long int compare (?) */ + + return 0; +} + +testbig() +{ + #ifdef ASSUME_32BIT_INT + int i; + #else + signed long i; + #endif + /* 2341234 2341234 2341234 */ + for (i = 0x1000000; i&0x7000000; i += 0x1000000) { +/* printf("i = 0x%lx\n", i); */ + big(i); + } +} + +#ifdef NO_LOCAL_STRING_INIT +/* static char _s[8]={"bfnrtvx"}; */ + static char _s[8]="bfnrtvx"; +#endif + +testbackslash() +{ + char *s; + +#ifdef NO_STRINGS_IN_FOR +# ifndef NO_LOCAL_STRING_INIT + char _s[8]={"bfnrtvx"}; +# endif + for (s=_s; *s; s++) { +#else + for (s = "bfnrtvx"; *s; s++) { +#endif + printf("%c = %c\n", *s, backslash(*s)); + } +} + +backslash(c) +{ + switch (c) + { + case 'b': + return 'b'; + case 'f': + return 'f'; + case 'n': + return 'n'; + case 'r': + return 'r'; + case 't': + return 't'; + case 'v': + return 'v'; + } + + return 'x'; +} + +f() { + int i, x = 0, y; + + printf("f:\n"); + for (i = 0; i <= 20; i++) { + y = i; + switch (i) { + case 1: x = i; break; + case 2: x = i; break; + case 7: x = i; break; + case 8: x = i; break; + case 9: x = i; break; + case 16: x = i; break; + case 17: x = i; break; + case 18: x = i; break; + case 19: x = i; break; + case 20: x = i; break; + } + printf("x = %d\n", x); + } +} + +g() { + int i; + + printf("g:\n"); + for (i = 1; i <= 10; i++) + switch (i) { + case 1: case 2: printf("1 %d\n", i); break; + case 3: case 4: case 5: printf("2 %d\n", i); break; + case 6: case 7: case 8: printf("3 %d\n", i); + default: + printf("d %d\n", i); break; + case 1001: case 1002: case 1003: case 1004: + printf("5 %d\n", i); break; + case 3001: case 3002: case 3003: case 3004: + printf("6 %d\n", i); break; + } +} + +h() +{ + int i, n=0; + + printf("h:\n"); + for (i = 1; i <= 500; i++) + switch (i) { + default: n++; continue; + case 128: printf("i = %d\n", i); break; + case 16: printf("i = %d\n", i); break; + case 8: printf("i = %d\n", i); break; + case 120: printf("i = %d\n", i); break; + case 280: printf("i = %d\n", i); break; + case 264: printf("i = %d\n", i); break; + case 248: printf("i = %d\n", i); break; + case 272: printf("i = %d\n", i); break; + case 304: printf("i = %d\n", i); break; + case 296: printf("i = %d\n", i); break; + case 288: printf("i = %d\n", i); break; + case 312: printf("i = %d\n", i); break; + } + printf("%d defaults\n", n); +} + +#ifdef NO_OLD_FUNC_DECL + big( +#else + big(x) +#endif + +# ifdef ASSUME_32BIT_UNSIGNED + unsigned +# else + unsigned long +# endif + +#ifdef NO_OLD_FUNC_DECL + x) { +#else + x; { +#endif + +/* printf("x = 0x%x\n", x); */ + + switch(x&0x6000000){ + case -1: + case -2: + case 0x0000000: + printf("x = 0x%lx\n", x); break; + case 0x2000000: + printf("x = 0x%lx\n", x); break; + case 0x4000000: + printf("x = 0x%lx\n", x); break; + default: + printf("x = 0x%lx (default)\n", x); break; + } +} + +limit() { + int i; + + for (i = INT_MIN; i <= INT_MIN+5; i++) +/* for (i = INT_MIN; i < INT_MIN+6; i++) */ + switch (i) { + case INT_MIN: printf("0\n"); break; + case INT_MIN+1: printf("1\n"); break; + case INT_MIN+2: printf("2\n"); break; + case INT_MIN+3: printf("3\n"); break; + case INT_MIN+4: printf("4\n"); break; + default: printf("5\n"); break; + } + for (i = INT_MAX; i >= INT_MAX-5; i--) + switch (i) { + case INT_MAX: printf("0\n"); break; + case INT_MAX-1: printf("1\n"); break; + case INT_MAX-2: printf("2\n"); break; + case INT_MAX-3: printf("3\n"); break; + case INT_MAX-4: printf("4\n"); break; + default: printf("5\n"); break; + } +} diff --git a/test/ref/switch2.c b/test/ref/switch2.c new file mode 100644 index 000000000..e75cfe71e --- /dev/null +++ b/test/ref/switch2.c @@ -0,0 +1,262 @@ +/* + !!DESCRIPTION!! switch test + !!ORIGIN!! + !!LICENCE!! public domain +*/ + +/*#define STANDALONE*/ + +#include <stdio.h> + +void testlimits(int i) { + printf("%d:",i); + + switch(i) { + case -1: /* works */ + /* case 0xffff: */ /* 'range error' (-1) */ + + printf("-1\n"); + break; + /* max int */ + +/* case 0x7fff: */ /* works */ + case 32767: /* works */ + /* case 32768: */ /* 'range error' (correct for that one!) */ + + printf("max\n"); + break; + /* min int */ + + case -32768: /* 'warning. constant is long' */ + /* case 0x8000: */ /* 'range error' */ + /* case -32769: */ /* 'range error' (correct for that one!) */ + printf("min\n"); + break; + } + printf("\n"); +} + +void testdefault1(unsigned char i) { +/* we want a signed char */ +#ifdef REFCC + +#ifdef REFCC_UNSIGNED_CHARS +signed char k; +#else +char k; +#endif + +#else + +#ifdef UNSIGNED_CHARS +signed char k; +#else +char k; +#endif + +#endif + + for(;i<254;) { + k = i; + printf(">%d\n",i);i++; + switch(k) { + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + case 12: + break; + case 13: + break; + case 14: + break; + case 15: + break; + case 17: + break; + /* triggers bug ? */ + /* gcc warning: case label value exceeds maximum value for type */ + /* cc65 error: range error */ + + /* + case 170: + break; + */ + case 18: + break; + case 19: + break; + case 20: + break; + case 21: + break; + case 22: + break; + case 23: + break; + case 24: + switch(k) { + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + case 5: + break; + case 6: + case 7: + break; + case 8: + case 9: + break; + } + break; + case 100: + break; + default: + printf(">>>default\n"); + /* triggers bug if this break; is missing? */ + /* break; */ + } + } +} + +void testdefault2(unsigned char i) { +/* we want a unsigned char */ +#ifdef REFCC + +#ifdef REFCC_UNSIGNED_CHARS +char k; +#else +unsigned char k; +#endif + +#else + +#ifdef UNSIGNED_CHARS +char k; +#else +unsigned char k; +#endif + +#endif + + for(;i<254;) { + k = i; + printf(">%d\n",i);i++; + switch(k) { + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + case 12: + break; + case 13: + break; + case 14: + break; + case 15: + break; + case 17: + break; + /* triggers bug ? */ + + case 170: + break; + + case 18: + break; + case 19: + break; + case 20: + break; + case 21: + break; + case 22: + break; + case 23: + break; + case 24: + switch(k) { + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + case 5: + break; + case 6: + case 7: + break; + case 8: + case 9: + break; + } + break; + case 100: + break; + default: + printf(">>>default\n"); + /* triggers bug if this break; is missing? */ + /* break; */ + } + } +} + +int main(void) { + testlimits(32767); + testlimits(-32768); + testlimits(-1); + + testdefault1(1); + testdefault1(2); + testdefault1(3); + testdefault1(4); + + testdefault2(1); + testdefault2(2); + testdefault2(3); + testdefault2(4); + + return 0; +} diff --git a/test/ref/varargs.c b/test/ref/varargs.c new file mode 100644 index 000000000..11fd33b38 --- /dev/null +++ b/test/ref/varargs.c @@ -0,0 +1,105 @@ +/* + !!DESCRIPTION!! varargs test + !!ORIGIN!! + !!LICENCE!! public domain +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> + +void chk0(char *format,...); +void chk1(int fd,char *format,...); + +#if 0 +// old workaround for broken varargs + +void chk0(char *format,...){ + __asm__ ("pha"); // save argument size + { +//va_list ap; +char *ap; +char *_format; +static char string[0x100]; + +// va_start(ap,format); + __asm__ ("pla"); // restore argument size + __asm__ ("ldx #$00"); // clear hibyte of AX + ap=__AX__; + ap+=(char*)&format; + // get value of format + ap-=2; + _format=*((char**)ap); + +// vsprintf(string,format,ap); + vsprintf(&string[0],_format,ap); + printf("format:%s,string:%s\n",_format,string); +// va_end(ap); + + } +} + +void chk1(int fd,char *format,...){ + __asm__ ("pha"); // save argument size + { +//va_list ap; +char *ap; +char *_format; +int _fd; +static char string[0x100]; + +// va_start(ap,format); + __asm__ ("pla"); // restore argument size + __asm__ ("ldx #$00"); // clear hibyte of AX + ap=__AX__; + ap+=(char*)&format; + // get value of fd + ap-=2; + _fd=*((int*)ap); + // get value of format + ap-=2; + _format=*((char**)ap); + +// vsprintf(string,format,ap); + vsprintf(&string[0],_format,ap); + printf("fd:%d,format:%s,string:%s\n",_fd,_format,string); +// va_end(ap); + + } +} + +#endif + +void chk0(char *format,...){ +va_list ap; +static char string[0x100]; + va_start(ap,format); + vsprintf(string,format,ap); + printf("format:%s,string:%s\n",format,string); + va_end(ap); +} + +void chk1(int fd,char *format,...){ +va_list ap; +static char string[0x100]; + + va_start(ap,format); + + vsprintf(string,format,ap); + printf("fd:%d,format:%s,string:%s\n",fd,format,string); + va_end(ap); +} + +int main(int argc,char **argv) { + printf("varargs test\n"); + + printf("\nchk0/0:\n");chk0("chk0 %s","arg0"); + printf("\nchk0/1:\n");chk0("chk0 %s %s","arg0","arg1"); + printf("\nchk0/2:\n");chk0("chk0 %s %s %s","arg0","arg1","arg2"); + + printf("\nchk1/0:\n");chk1(0xfd,"chk1 %s","arg0"); + printf("\nchk1/1:\n");chk1(0xfd,"chk1 %s %s","arg0","arg1"); + printf("\nchk1/2:\n");chk1(0xfd,"chk1 %s %s %s","arg0","arg1","arg2"); + + return 0; +} diff --git a/test/ref/wf1.c b/test/ref/wf1.c new file mode 100644 index 000000000..3e9c80fb2 --- /dev/null +++ b/test/ref/wf1.c @@ -0,0 +1,132 @@ +/* + !!DESCRIPTION!! print word frequencies; uses structures + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#define MAXWORDS 250 + +struct node +{ + int count; /* frequency count */ + struct node *left; /* left subtree */ + struct node *right; /* right subtree */ + char *word; /* word itself */ +} words[MAXWORDS]; +int next; /* index of next free entry in words */ + +/*struct node *lookup();*/ + +#if defined(NO_NEW_PROTOTYPES_FOR_OLD_FUNC_DECL) && !defined(NO_OLD_FUNC_DECL) + +#else + +int err(char *s); +int getword(char *buf); +void tprint(struct node *tree); +struct node *lookup(char *word, struct node **p); + +#endif + +int isletter(char c); + +/* err - print error message s and die */ +#ifndef NO_OLD_FUNC_DECL +err(s) char *s; { +#else +int err(char *s) { +#endif + printf("? %s\n", s); + exit(1); +} + +/* getword - get next input word into buf, return 0 on EOF */ +#ifndef NO_OLD_FUNC_DECL +int getword(buf) char *buf; +#else +int getword(char *buf) +#endif +{ + char *s; + int c; + + while (((c = getchar()) != -1) && (isletter(c) == 0)) + ; + for (s = buf; (c = isletter(c)); c = getchar()) + *s++ = c; + *s = 0; + if (s > buf) + return 1; + return 0; +} + +/* isletter - return folded version of c if it is a letter, 0 otherwise */ +int isletter(char c) +{ + if ((c >= 'A') && (c <= 'Z')) c += 'a' - 'A'; + if ((c >= 'a') && (c <= 'z')) return c; + return 0; +} + +/* lookup - lookup word in tree; install if necessary */ +#ifndef NO_OLD_FUNC_DECL +struct node *lookup(word, p) +char *word; struct node **p; +#else +struct node *lookup(char *word, struct node **p) +#endif +{ + int cond; +/* char *malloc(); */ + + if (*p) { + cond = strcmp(word, (*p)->word); + if (cond < 0) + return lookup(word, &(*p)->left); + else if (cond > 0) + return lookup(word, &(*p)->right); + else + return *p; + } + if (next >= MAXWORDS) + err("out of node storage"); + words[next].count = 0; + words[next].left = words[next].right = 0; + words[next].word = malloc(strlen(word) + 1); + if (words[next].word == 0) + err("out of word storage"); + strcpy(words[next].word, word); + return *p = &words[next++]; +} + +/* tprint - print tree */ +#ifndef NO_OLD_FUNC_DECL +void tprint(tree) struct node *tree; { +#else +void tprint(struct node *tree) { +#endif + if (tree) { + tprint(tree->left); + printf("%d:%s\n", tree->count, tree->word); + tprint(tree->right); + } +} + +int main(void) +{ + struct node *root; + char word[20]; + + root = 0; + next = 0; + while (getword(word)) + lookup(word, &root)->count++; + tprint(root); + + return 0; +} diff --git a/test/ref/yacc.c b/test/ref/yacc.c new file mode 100644 index 000000000..3baefd348 --- /dev/null +++ b/test/ref/yacc.c @@ -0,0 +1,996 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +/*#define STANDALONE*/ + +#ifndef YACCDBG + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +/* +#define LEXDEBUG +#define YYDEBUG +*/ + +#endif + +/* hack the original tables to work with both petscii and ascii */ +#define CHARSETHACK + +# define ID 257 +# define CON 258 +# define UNARYMINUS 259 +#define yyclearin yychar = -1 +#define yyerrok yyerrflag = 0 +extern int yychar; +extern short yyerrflag; +#ifndef YYMAXDEPTH +/*#define YYMAXDEPTH 150*/ +#define YYMAXDEPTH 50 +#endif +#ifndef YYSTYPE +#define YYSTYPE int +#endif +YYSTYPE yylval, yyval; +# define YYERRCODE 256 + +# define U(x) x +# define NLSTATE yyprevious=YYNEWLINE +# define BEGIN yybgin = yysvec + 1 + +# define INITIAL 0 +# define YYLERR yysvec +# define YYSTATE (yyestate-yysvec-1) +# define YYOPTIM 1 +# define YYLMAX 200 +# define output(c) (void)putc(c,yyout) + +/* # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) */ +# define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getchar())==('\n')?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) + +# define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} +# define yymore() (yymorfg=1) +# define ECHO fprintf(yyout, "%s",yytext) +# define REJECT { nstr = yyreject(); goto yyfussy;} +int yyleng; extern char yytext[]; +int yymorfg; +extern char *yysptr, yysbuf[]; +int yytchar; + +/*FILE *yyin ={stdin}, *yyout ={stdout};*/ +#define yyin infile +#define yyout outfile + +extern int yylineno; +struct yysvf +{ + struct yywork *yystoff; + struct yysvf *yyother; + int *yystops; +}; +struct yysvf *yyestate; +extern struct yysvf yysvec[], *yybgin; + +/*# define YYNEWLINE 10 */ +# define YYNEWLINE ('\n') + +#ifdef NO_IMPLICIT_FUNC_PROTOTYPES +yylook(); +int yywrap(); +yyparse(); +yyerror(char *s); +yyunput(int c); +yyoutput(int c); +yyinput(); +yyback(int *p,int m); +#endif + +#ifdef YYDEBUG +void printchar(char *name,int ch) +{ + if((ch==YYNEWLINE)) + { + fprintf(yyout," %s=YYNEWLINE\n",name); + } + else if((ch<0)||(ch>0xf0)||(!isprint(ch))) + { + fprintf(yyout," %s=%04x\n",name,ch &0xffff); + } + else + { + fprintf(yyout," %s='%c'\n",name,ch); + } +} +#endif + +yylex() +{ +int nstr; +extern int yyprevious; + +#ifdef YYDEBUG + fprintf(yyout,"yylex()\n"); +#endif + + while((nstr = yylook()) >= 0) + { +#ifdef YYDEBUG + fprintf(yyout,"yylex: nstr=%d\n",nstr); +#endif +yyfussy: + switch(nstr) + { + case 0: + if(yywrap()) return(0); + break; + case 1: + return ID; + break; + case 2: + return CON; + break; + case 3: + ; + break; + case 4: + return yytext[0]; + break; + case -1: + break; + default: + fprintf(yyout,"yylex: bad switch yylook %d\n",nstr); + } + + } + +#ifdef YYDEBUG + fprintf(yyout,"yylex: return 0\n"); +#endif + return(0); +} +/* end of yylex */ + +int yyvstop[] = +{ + 0,4,0,3,4,0,2,4,0,1,4,0,2,0,1,0,0 +}; + +# define YYTYPE char +struct yywork +{ + YYTYPE verify, advance; +} yycrank[] = +{ + {0,0}, {0,0}, {1,3}, {0,0}, + {0,0}, {0,0}, {0,0}, {0,0}, + {0,0}, {0,0}, {1,4}, {1,3}, + {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}, {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}, {0,0}, {0,0}, + + {0,0}, {1,5}, {5,7}, {5,7}, + {5,7}, {5,7}, {5,7}, {5,7}, + {5,7}, {5,7}, {5,7}, {5,7}, + {0,0}, {0,0}, {0,0}, {0,0}, +/* 0x40 */ + {0,0}, {0,0}, {1,6}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {0,0}, {0,0}, {0,0}, + + {0,0}, {0,0}, {0,0}, {0,0}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {0,0}, {0,0}, + + {0,0}, {0,0}, {6,8}, {0,0}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, +/* 0x80 */ + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {0,0}, {0,0}, + +#ifdef CHARSETHACK + {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}, {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}, {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}, + +/* 0xc0 */ + {0,0}, {0,0}, {1,6}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {0,0}, {0,0}, {0,0}, +#endif + {0,0} +}; + +/* +struct yysvf +{ + struct yywork *yystoff; + struct yysvf *yyother; + int *yystops; +}; +*/ +struct yysvf yysvec[] = +{ + {0, 0, 0}, + {yycrank+-1, 0, 0}, + {yycrank+0, yysvec+1, 0}, + {yycrank+0, 0, yyvstop+1}, + {yycrank+0, 0, yyvstop+3}, + {yycrank+2, 0, yyvstop+6}, + {yycrank+19, 0, yyvstop+9}, + {yycrank+0, yysvec+5, yyvstop+12}, + {yycrank+0, yysvec+6, yyvstop+14}, + {0, 0, 0} +}; + /* 0x8d */ +/* struct yywork *yytop = yycrank+141; */ + /* 0xff */ +struct yywork *yytop = yycrank+255; + +struct yysvf *yybgin = yysvec+1; + +/* + WARNING: this table contains one entry per character + in the execution character set and must match it. +*/ +char yymatch[] = +{ + 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , +#ifdef CHARSETHACK + 01 ,011 ,012 ,01 ,01 ,012 ,01 ,01 , +#else + 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , +#endif + 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , + 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , + + 011 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , + 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , + + '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , + '0' ,'0' ,01 ,01 ,01 ,01 ,01 ,01 , + +/* 0x40 (ascii) @A... (petscii) @a... */ + 01 ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , + 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , + + 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , + 'A' ,'A' ,'A' ,01 ,01 ,01 ,01 ,'A' , + +/* 0x60 (ascii) @a... */ + 01 ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , + 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , + + 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , + 'A' ,'A' ,'A' ,01 ,01 ,01 ,01 ,01 , + +#ifdef CHARSETHACK +/* 0x80 */ + 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,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, + +/* 0xc0 (petcii) @A... */ + 01 ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , + 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , + + 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , + 'A' ,'A' ,'A' ,01 ,01 ,01 ,01 ,01 , + + 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,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, +#endif + 0 +}; +char yyextra[] = +{ + 0,0,0,0,0,0,0,0,0 +}; + +/* ncform 4.1 83/08/11 */ + +int yylineno =1; +# define YYU(x) x +# define NLSTATE yyprevious=YYNEWLINE +char yytext[YYLMAX]; +struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; +char yysbuf[YYLMAX]; +char *yysptr = yysbuf; +int *yyfnd; +extern struct yysvf *yyestate; +int yyprevious = YYNEWLINE; + +unsigned char testbreak=0; + +yylook() +{ + register struct yysvf *yystate, **lsp; + register struct yywork *yyt; + struct yysvf *yyz; + int yych; + struct yywork *yyr; +/* +# ifdef LEXDEBUG + int debug; +# endif +*/ + + char *yylastch; + + /* start off machines */ + +/* +# ifdef LEXDEBUG + debug = 1; +# else + debug = 0; +# endif +*/ + +# ifdef LEXDEBUG +#define debug 1 +# else +#define debug 0 +#endif + +#ifdef YYDEBUG + fprintf(yyout,"yylook()\n"); +# endif + + if (!yymorfg) + yylastch = yytext; + else + { + yymorfg=0; + yylastch = yytext+yyleng; + } + +#ifdef YYDEBUG + fprintf(yyout,"yylook: yymorfg=%d\n",yymorfg); +# endif + + for(;;) + { +#ifdef YYDEBUG + fprintf(yyout,"yylook: (outer loop)"); + printchar("yyprevious",yyprevious); +# endif + lsp = yylstate; + yyestate = yystate = yybgin; + if (yyprevious==YYNEWLINE) yystate++; + + testbreak=0; + + for (;;) + { +# ifdef LEXDEBUG + fprintf(yyout,"yylook: (inner loop) state %d\n",yystate-yysvec-1); +# endif + if(testbreak==5) + { + fprintf(yyout,"yylook: error, aborted after 5 loops\n"); + exit(0); + } + testbreak++; + + yyt = yystate->yystoff; + +/* fprintf(yyout,"yylook: yyt offs: %02x\n",yyt-yycrank); */ + + + if(yyt == yycrank) + { /* may not be any transitions */ + yyz = yystate->yyother; + if(yyz == 0)break; + if(yyz->yystoff == yycrank)break; + } + *yylastch++ = yych = input(); + +# ifdef LEXDEBUG + fprintf(yyout,"yylook: input "); + printchar("yych",yych); +# endif + + tryagain: + +# ifdef LEXDEBUG +/* fprintf(yyout,"yylook: yych=%02x yymatch[yych]=%02x\n",yych,yymatch[yych]); */ + fprintf(yyout,"yylook: tryagain\n"); +# endif + yyr = yyt; + +/* fprintf(yyout,"yylook: yyr offs: %02x\n",yyr-yycrank); */ + + if ( yyt > yycrank) + { + yyt = yyr + yych; + if (yyt <= yytop && yyt->verify+yysvec == yystate) + { + if(yyt->advance+yysvec == YYLERR) /* error transitions */ + { +# ifdef LEXDEBUG + fprintf(yyout,"yylook: unput (1) "); + printchar("*yylastch",*yylastch); +# endif + unput(*--yylastch); + break; + } + *lsp++ = yystate = yyt->advance+yysvec; +# ifdef LEXDEBUG + fprintf(yyout,"yylook: continue (1)\n"); +# endif + goto contin; + } +# ifdef LEXDEBUG + fprintf(yyout,"yylook: ( yyt > yycrank)\n"); +# endif + } +# ifdef YYOPTIM + else if(yyt < yycrank) /* r < yycrank */ + { + yyt = yyr = yycrank+(yycrank-yyt); +# ifdef LEXDEBUG + fprintf(yyout,"yylook: compressed state\n"); +# endif + yyt = yyt + yych; + if(yyt <= yytop && yyt->verify+yysvec == yystate) + { +# ifdef LEXDEBUG + fprintf(yyout,"yylook: (1)\n"); +# endif + if(yyt->advance+yysvec == YYLERR) /* error transitions */ + { +# ifdef LEXDEBUG + fprintf(yyout,"yylook: unput (2) "); + printchar("*yylastch",*yylastch); +# endif + unput(*--yylastch); + break; + } + *lsp++ = yystate = yyt->advance+yysvec; +# ifdef LEXDEBUG + fprintf(yyout,"yylook: continue (2)\n"); +# endif + goto contin; + + } +# ifdef LEXDEBUG +/* + fprintf(yyout,"yylook: yych=%02x yymatch[yych]=%02x\n",yych,yymatch[yych]); + fprintf(yyout,"yylook: yyt offs: %02x\n",yyt-yycrank); + fprintf(yyout,"yylook: yyr offs: %02x\n",yyr-yycrank); +*/ +# endif + yyt = yyr + YYU(yymatch[yych]); +# ifdef LEXDEBUG +/* + fprintf(yyout,"yylook: yyt offs: %02x <= yytop offs: %02x\n",yyt-yycrank,yytop-yycrank); + fprintf(yyout,"yylook: yyt->verify=%04x yysvec=%04x (yyt->verify+yysvec)=%04x == yystate=%04x\n",yyt->verify,yysvec,(yyt->verify+yysvec),yystate); +*/ + fprintf(yyout,"yylook: try fall back character\n"); +# endif + if(yyt <= yytop && yyt->verify+yysvec == yystate) + { +# ifdef LEXDEBUG + fprintf(yyout,"yylook: (2a)\n"); +# endif + + if(yyt->advance+yysvec == YYLERR) /* error transition */ + { +# ifdef LEXDEBUG +/* cc65 compiles this ?! fprintf(yyout,"yylook: unput (3) ",); */ + fprintf(yyout,"yylook: unput (3) "); + printchar("*yylastch",*yylastch); +# endif + unput(*--yylastch); + break; + } + *lsp++ = yystate = yyt->advance+yysvec; +# ifdef LEXDEBUG +/* fprintf(yyout,"yylook: yyt offs: %02x yyt->advance=%d\n",yyt-yycrank,yyt->advance); */ + fprintf(yyout,"yylook: continue (3)\n"); +# endif + goto contin; + + } +# ifdef LEXDEBUG + fprintf(yyout,"yylook: (2)\n"); +# endif + } + if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank) + { +# ifdef LEXDEBUG + fprintf(yyout,"yylook: fall back to state %d\n",yystate-yysvec-1); +# endif + goto tryagain; + } +# endif + else + { +# ifdef LEXDEBUG + fprintf(yyout,"yylook: unput (4) "); + printchar("*yylastch",*yylastch); +# endif + unput(*--yylastch); + break; + } + contin: +# ifdef LEXDEBUG + fprintf(yyout,"yylook: contin state=%d\n",yystate-yysvec-1); +# endif + ; + } + +# ifdef LEXDEBUG + if((*(lsp-1)-yysvec-1)<0) + { + fprintf(yyout,"yylook: stopped (end)\n"); + } + else + { + fprintf(yyout,"yylook: stopped at %d with\n",*(lsp-1)-yysvec-1); + } +# endif + while (lsp-- > yylstate) + { + *yylastch-- = 0; + if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0) + { + yyolsp = lsp; + if(yyextra[*yyfnd]) /* must backup */ + { + while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate) + { + lsp--; +# ifdef LEXDEBUG + fprintf(yyout,"yylook: unput (5) "); + printchar("*yylastch",*yylastch); +# endif + unput(*yylastch--); + } + } + yyprevious = YYU(*yylastch); + yylsp = lsp; + yyleng = yylastch-yytext+1; + yytext[yyleng] = 0; +# ifdef LEXDEBUG + fprintf(yyout,"\nyylook: match action %d\n",*yyfnd); + fprintf(yyout,"yylook: done loops: %d\n",testbreak); +# endif + return(*yyfnd++); + } + unput(*yylastch); + } + if (yytext[0] == 0 /* && feof(yyin) */) + { + yysptr=yysbuf; +# ifdef LEXDEBUG + fprintf(yyout,"yylook: done loops: %d\n",testbreak); +# endif + return(0); + } + yyprevious = yytext[0] = input(); + +# ifdef LEXDEBUG + fprintf(yyout,"yylook: input "); + printchar("yyprevious",yyprevious); +# endif + + if (yyprevious>0) + output(yyprevious); + yylastch=yytext; +# ifdef LEXDEBUG +/* if(debug)putchar('\n'); */ +# endif + } + +# ifdef LEXDEBUG + fprintf(yyout,"yylook: done loops: %d\n",testbreak); + fprintf(yyout,"yylook: return <void>\n"); +# endif +} + + +yyback(p, m) + int *p; +{ + if (p==0) return(0); + while (*p) + { + if (*p++ == m) + { + return(1); + } + } + return(0); +} + /* the following are only used in the lex library */ +yyinput() +{ + int out=input(); + +#ifdef YYDEBUG + fprintf(yyout,"yylook: input "); + printchar("out",out); +#endif + return(out); +} +yyoutput(c) + int c; +{ + output(c); +} +yyunput(c) + int c; +{ + unput(c); +} + +main() +{ + printf("main start\n"); + yyparse(); + printf("main end\n"); + return 0; +} + +/* yyerror - issue error message */ +yyerror(s) +char *s; +{ + printf("[%s]\n", s); +} +short yyexca[] = +{ +-1, 1, + 0, -1, + -2, 0, +}; + +# define YYNPROD 15 +# define YYLAST 249 + +short yyact[]= +{ + 12, 2, 9, 8, 17, 11, 25, 17, 15, 18, + 16, 10, 18, 17, 15, 7, 16, 13, 18, 5, + 3, 1, 0, 19, 20, 0, 0, 21, 22, 23, + 24, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 14, 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, 4, 6 +}; +short yypact[]= +{ +-1000, -9,-1000, 5, -7, -59,-1000,-1000,-1000, -40, + -29, -40, -40,-1000,-1000, -40, -40, -40, -40, -38, + -35, -38, -38,-1000,-1000,-1000 +}; +short yypgo[]= +{ + 0, 21, 20, 17, 11 +}; +short yyr1[]= +{ + 0, 1, 1, 1, 1, 2, 4, 4, 4, 4, + 4, 4, 4, 4, 3 +}; +short yyr2[]= +{ + 0, 0, 2, 3, 3, 3, 3, 3, 3, 3, + 2, 3, 1, 1, 1 +}; +short yychk[]= +{ +-1000, -1, 10, -2, 256, -3, 257, 10, 10, 61, + -4, 45, 40, -3, 258, 43, 45, 42, 47, -4, + -4, -4, -4, -4, -4, 41 +}; +short yydef[]= +{ + 1, -2, 2, 0, 0, 0, 14, 3, 4, 0, + 5, 0, 0, 12, 13, 0, 0, 0, 0, 10, + 0, 6, 7, 8, 9, 11 +}; + +# define YYFLAG -1000 +# define YYERROR goto yyerrlab +# define YYACCEPT return(0) +# define YYABORT return(1) + +/* parser for yacc output */ + +#ifdef YYDEBUG +int yydebug = 1; /* 1 for debugging */ +#else +int yydebug = 0; /* 1 for debugging */ +#endif +YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ +int yychar = -1; /* current input token number */ +int yynerrs = 0; /* number of errors */ +short yyerrflag = 0; /* error recovery flag */ + +yyparse() +{ + short yys[YYMAXDEPTH]; + short yyj, yym; + register YYSTYPE *yypvt; + register short yystate, *yyps, yyn; + register YYSTYPE *yypv; + register short *yyxi; + + yystate = 0; + yychar = -1; + yynerrs = 0; + yyerrflag = 0; + yyps= &yys[-1]; + yypv= &yyv[-1]; + + yystack: /* put a state and value onto the stack */ +#ifdef YYDEBUG + printf("yyparse: yystack\n"); +#endif + +#ifdef YYDEBUG + printf("yyparse: yystate=%d, ", yystate); + printchar("yychar",yychar); +#endif + if( ++yyps> &yys[YYMAXDEPTH] ) + { + yyerror( "yyparse: yacc stack overflow" ); + return(1); + } + *yyps = yystate; + ++yypv; + *yypv = yyval; + + yynewstate: +#ifdef YYDEBUG + printf("yyparse: yynewstate\n"); +#endif + + yyn = yypact[yystate]; + + if( yyn<= YYFLAG ) goto yydefault; /* simple state */ + +#ifdef YYDEBUG + printf("yyparse: yynewstate (1)\n"); +#endif + + if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0; + +#ifdef YYDEBUG + + printf("yyparse: yynewstate yyn=%d ",yyn); + printchar("yychar",yychar); +#endif + + if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault; + +#ifdef YYDEBUG + printf("yyparse: yynewstate (2)\n"); +#endif + + if( yychk[ yyn=yyact[ yyn ] ] == yychar ) /* valid shift */ + { + yychar = -1; + yyval = yylval; + yystate = yyn; + +#ifdef YYDEBUG + printf("yyparse: yynewstate (3)\n"); +#endif + + if( yyerrflag > 0 ) --yyerrflag; + goto yystack; + } + + yydefault: +#ifdef YYDEBUG + printf("yyparse: yydefault yystate=%d\n",yystate); +#endif + /* default state action */ + + if( (yyn=yydef[yystate]) == -2 ) + { + if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0; + /* look through exception table */ + + for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */ + + while( *(yyxi+=2) >= 0 ) + { + if( *yyxi == yychar ) break; + } + if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */ + } + +#ifdef YYDEBUG + printf("yyparse: yyn=%d yyerrflag=%d\n",yyn,yyerrflag); +#endif + + if( yyn == 0 ) /* error */ + { + /* error ... attempt to resume parsing */ + + switch( yyerrflag ){ + case 0: /* brand new error */ + + yyerror( "yyparse: syntax error" ); + yyerrlab: + ++yynerrs; + + case 1: + case 2: /* incompletely recovered error ... try again */ + + yyerrflag = 3; + + /* find a state where "error" is a legal shift action */ + + while ( yyps >= yys ) { + yyn = yypact[*yyps] + YYERRCODE; + if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){ + yystate = yyact[yyn]; /* simulate a shift of "error" */ + goto yystack; + } + yyn = yypact[*yyps]; + + /* the current yyps has no shift onn "error", pop stack */ + +#ifdef YYDEBUG + printf("yyparse: error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] ); +#endif + --yyps; + --yypv; + } + + /* there is no state on the stack with an error shift ... abort */ + + yyabort: + return(1); + + case 3: /* no shift yet; clobber input char */ + +#ifdef YYDEBUG + printf("yyparse: error recovery discards char "); + printchar("yychar",yychar); +#endif + + if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */ + yychar = -1; + goto yynewstate; /* try again in the same state */ + + } + + } + + /* reduction by production yyn */ + +#ifdef YYDEBUG + printf("yyparse: reduce %d\n",yyn); +#endif + yyps -= yyr2[yyn]; + yypvt = yypv; + yypv -= yyr2[yyn]; + yyval = yypv[1]; + yym=yyn; + /* consult goto table to find next state */ + yyn = yyr1[yyn]; + yyj = yypgo[yyn] + *yyps + 1; + if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]]; + + switch(yym) + { + case 4: + { + yyerrok; + } + break; + case 5: + { + printf("[STORE]\n"); + } + break; + case 6: + { + printf("[ADD]\n"); + } + break; + case 7: + { + printf("[NEG]\n[ADD]\n"); + } + break; + case 8: + { + printf("[MUL]\n"); + } + break; + case 9: + { + printf("[DIV]\n"); + } + break; + case 10: + { + printf("[NEG]\n"); + } + break; + case 12: + { + printf("[LOAD]\n"); + } + break; + case 13: + { + printf("[PUSH %s]\n", yytext); + } + break; + case 14: + { + printf("[%s]\n", yytext); + } + break; + } + + goto yystack; /* stack new state and value */ +} + +int yywrap() +{ + return 1; +} diff --git a/test/ref/yacc2.c b/test/ref/yacc2.c new file mode 100644 index 000000000..c62fca34a --- /dev/null +++ b/test/ref/yacc2.c @@ -0,0 +1,227 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Groepaz/Hitmen +*/ + +# define YYTYPE char +struct yywork +{ + YYTYPE verify, advance; +} yycrank[] = +{ + {0,0}, {0,0}, {1,3}, {0,0}, + {0,0}, {0,0}, {0,0}, {0,0}, + {0,0}, {0,0}, {1,4}, {1,3}, + {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}, {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}, {0,0}, {0,0}, + + {0,0}, {1,5}, {5,7}, {5,7}, + {5,7}, {5,7}, {5,7}, {5,7}, + {5,7}, {5,7}, {5,7}, {5,7}, + {0,0}, {0,0}, {0,0}, {0,0}, +/* 0x40 */ + {0,0}, {0,0}, {1,6}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {0,0}, {0,0}, {0,0}, + + {0,0}, {0,0}, {0,0}, {0,0}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {0,0}, {0,0}, + + {0,0}, {0,0}, {6,8}, {0,0}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, +/* 0x80 */ + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {0,0}, {0,0}, + +#ifdef CHARSETHACK + {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}, {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}, {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}, + +/* 0xc0 */ + {0,0}, {0,0}, {1,6}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {6,8}, {6,8}, {6,8}, + {6,8}, {0,0}, {0,0}, {0,0}, +#endif + {0,0} +}; + +struct yywork *yytop = yycrank+255; + +int yyvstop[] = +{ + 0,4,0,3,4,0,2,4,0,1,4,0,2,0,1,0,0 +}; + +struct yysvf +{ + struct yywork *yystoff; + struct yysvf *yyother; + int *yystops; +}; + +struct yysvf yysvec[] = +{ + {0, 0, 0}, + {yycrank+-1, 0, 0}, + {yycrank+0, yysvec+1, 0}, + {yycrank+0, 0, yyvstop+1}, + {yycrank+0, 0, yyvstop+3}, + {yycrank+2, 0, yyvstop+6}, + {yycrank+19, 0, yyvstop+9}, + {yycrank+0, yysvec+5, yyvstop+12}, + {yycrank+0, yysvec+6, yyvstop+14}, + {0, 0, 0} +}; + +#if 0 +# define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):GETCHAR())==('\n')?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) +// *yylastch++ = yych = input(); +void subtest1(void) +{ + *yylastch++ = yych = input(); +} +#endif + +// do some bogus operation to destroy all registers etc +static int bog=1234; +#if 0 +void bogus(void) +{ + bog*=0x1234; +} +#else +#define bogus() bog+=0x1234 +#endif + +#if 1 +// yyt = yyt + yych; +void subtest2(void) +{ + register struct yywork *yyt; + int yych; + + yyt=yycrank; + yych=10; + + bogus(); + yyt = yyt + yych; + + printf("yyt: %d %d\n",yyt->verify,yyt->advance); +} +#endif + +#if 1 +// if(yyt <= yytop && yyt->verify+yysvec == yystate) +void subtest3(void) +{ + register struct yywork *yyt; + register struct yysvf *yystate; + + yyt=yycrank; + yystate=yysvec; + + bogus(); + if(yyt <= yytop && yyt->verify+yysvec == yystate) + { + printf("if ok %d %d\n",yyt->verify,yyt->advance); + } + else + { + printf("if not ok %d %d\n",yyt->verify,yyt->advance); + } +} +#endif + +short yyr2[]= +{ + 0, 0, 2, 3, 3, 3, 3, 3, 3, 3, + 2, 3, 1, 1, 1 +}; + +// yyps -= yyr2[yyn]; +void subtest4(void) +{ + register short *yyps, yyn; + + yyps=0x8004; + yyn=0; + + while(yyn<14) + { + bogus(); + yyps -= yyr2[yyn]; + + yyn++; + } + printf("yyps: %04x\n",yyps); +} + +#if 1 + +int yylookret=10; +yylook() +{ + yylookret--; + return yylookret; +} + +// while((nstr = yylook()) >= 0) +void subtest5(void) +{ + int nstr; + + bogus(); + while((nstr = yylook()) >= 0) + { + printf("nstr: %04x\n",nstr); + bogus(); + } +} +#endif + +int main(void) +{ +// subtest1(); + subtest2(); + subtest3(); + subtest4(); + subtest5(); + + return 0; +} diff --git a/test/ref/yaccdbg.c b/test/ref/yaccdbg.c new file mode 100644 index 000000000..41e1afcdd --- /dev/null +++ b/test/ref/yaccdbg.c @@ -0,0 +1,19 @@ +/* + !!DESCRIPTION!! verbose/debug version of yacc.c (if one fails and the other does not you most likely have a stack related problem) + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +/*#define STANDALONE*/ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#define INFILE "yaccdbg.in" + +#define LEXDEBUG +#define YYDEBUG + +#define YACCDBG +#include "yacc.c" diff --git a/test/val/add1.c b/test/val/add1.c new file mode 100644 index 000000000..381d12e26 --- /dev/null +++ b/test/val/add1.c @@ -0,0 +1,181 @@ +/* + !!DESCRIPTION!! Addition tests + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES + +bit bit0 = 0; +bit bit1 = 0; +bit bit2 = 0; +bit bit3 = 0; +bit bit4 = 0; +bit bit5 = 0; +bit bit6 = 0; +bit bit7 = 0; +bit bit8 = 0; +bit bit9 = 0; +bit bit10 = 0; +bit bit11 = 0; + +#endif + +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned char achar0 = 0; +unsigned char achar1 = 0; +unsigned char achar2 = 0; +unsigned char achar3 = 0; +unsigned char *acharP = 0; + +void done() +{ + dummy++; +} + +void add_lit2uchar(void) +{ + achar0 = achar0 + 5; + + if(achar0 != 5) + failures++; + + achar0 += 10; + + if(achar0 != 15) + failures++; + + achar0 = achar0 +1; /*Should be an increment */ + if(achar0 != 16) + failures++; + + for(achar1 = 0; achar1 < 100; achar1++) + achar0 += 2; + + if(achar0 != 216) + failures++; +} + +void add_uchar2uchar(void) +{ + achar1 = achar1 + achar0; + + if(achar1 != 16) + failures++; + + for(achar2 = 0; achar2<7; achar2++) + achar1 += achar0; + + if(achar1 != 128) + failures++; +} + +/* assumes + achar0 = 0 + achar1 = 32 + achar2, achar3 can be anything. +*/ +void add_uchar2uchar2(void) +{ + achar0++; + achar0 = achar0 + 1; + achar0 = achar0 + 2; + achar0 = achar0 + 3; + if(achar0 != 7) + failures++; + + achar1 += achar0; + if(achar1 != 39) + failures++; + + achar2 = achar1 + achar0; + if(achar2 != 46) + failures++; + + achar3 = achar2 + achar1 + achar0; + if(achar3 != 92) + failures++; +} + +#ifdef SUPPORT_BIT_TYPES +void add_bits(void) +{ + bit1 = bit0; + + bit0 = 1; + + if(bit1 != 0) + failures++; + + bit1 = bit1+bit0; + if(bit1 != 1) + failures++; + +#ifdef SUPPORT_BIT_ARITHMETIC + bit2 = bit1+bit3; + if(!bit2) + failures++; + + bit3 = bit4+bit5+bit6+bit7+bit0; + if(!bit3) + failures++; +#endif +} + +/* add_bit2uchar(void) - assumes bit0 = 1, achar0 = 7 */ + +void add_bit2uchar(void) +{ + achar0 += bit0; + + if(achar0 != 8) + failures++; + + if(achar0 == bit0) + failures++; +} + +void add_bit2uint(void) +{ + if(aint0 != bit11) + failures++; + + aint0 += bit0; + if(aint0!=1) + failures++; +} +#endif + +int main(void) +{ + add_lit2uchar(); + + achar0=16; + achar1=0; + add_uchar2uchar(); + + achar0 = 0; + achar1 = 32; + add_uchar2uchar2(); + +#ifdef SUPPORT_BIT_TYPES + add_bits(); + + add_bit2uchar(); + add_bit2uint(); +#endif + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/add1.o b/test/val/add1.o new file mode 100644 index 000000000..bc6b2f505 Binary files /dev/null and b/test/val/add1.o differ diff --git a/test/val/add1.prg b/test/val/add1.prg new file mode 100644 index 000000000..c0bdb01a2 Binary files /dev/null and b/test/val/add1.prg differ diff --git a/test/val/add2.c b/test/val/add2.c new file mode 100644 index 000000000..90f0f4175 --- /dev/null +++ b/test/val/add2.c @@ -0,0 +1,328 @@ +/* + !!DESCRIPTION!! Addition tests - mostly int's + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SIZEOF_INT_16BIT +#if defined(__LINUX__) || defined(LINUX) +unsigned short aint0 = 0; +unsigned short aint1 = 0; +unsigned short aint2 = 0; +unsigned short aint3 = 0; + +#else +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned int aint2 = 0; +unsigned int aint3 = 0; + +#endif + +#else +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned int aint2 = 0; +unsigned int aint3 = 0; + +#endif + +unsigned char achar0 = 0; +unsigned char achar1 = 0; +unsigned char achar2 = 0; +unsigned char achar3 = 0; +unsigned char *acharP = 0; + +#ifdef SUPPORT_BIT_TYPES + +bit bit0 = 0; +bit bit1 = 0; +bit bit2 = 0; +bit bit3 = 0; +bit bit4 = 0; +bit bit5 = 0; +bit bit6 = 0; +bit bit7 = 0; +bit bit8 = 0; +bit bit9 = 0; +bit bit10 = 0; +bit bit11 = 0; + +#endif + +void done() +{ + dummy++; +} + +void add_lit2uint(void) +{ + aint0 = aint0 + 5; + + if(aint0 != 5) + failures++; + + aint0 += 10; + + if(aint0 != 15) + failures++; + + aint0 = aint0 +1; /* Should be an increment */ + if(aint0 != 16) + failures++; + + for(aint1 = 0; aint1 < 100; aint1++) + aint0 += 2; + + if(aint0 != 216) + failures++; +} + +void add_uint2uint (void) +{ + aint1 = aint1 + aint0; + + if(aint1 != 16) + failures++; + + for(aint2 = 0; aint2<7; aint2++) + aint1 += aint0; + + if(aint1 != 128) + failures++; +} + +/* assumes + aint0 = 0 + aint1 = 32 + aint2, aint3 can be anything. +*/ +void add_uint2uint2(void) +{ + aint0++; + aint0 = aint0 + 1; + aint0 = aint0 + 2; + aint0 = aint0 + 3; + if(aint0 != 7) + failures++; + + aint1 += aint0; + if(aint1 != 0x27) + failures++; + + aint2 = aint1 + aint0; + if(aint2 != 0x2e) + failures++; + + aint3 = aint2 + aint1 + aint0; + if(aint3 != 0x5c) + failures++; + + aint3 += 0xa0; + if(aint3 != 0xfc) + failures++; + + aint3 += aint0; + if(aint3 != 0x103) + failures++; + + aint1 += 0xffc0; + if(aint1 != 0xffe7) + failures++; + + aint3 = aint2 + aint1 + aint0; + if(aint3 != 0x1c) + failures++; +} + +#ifdef SUPPORT_BIT_TYPES +void add_bits(void) +{ + bit1 = bit0; + + bit0 = 1; + + if(bit1 != 0) + failures++; + + bit1 = bit1+bit0; + if(bit1 != 1) + failures++; + + bit2 = bit1+bit3; + if(!bit2) + failures++; + + bit3 = bit4+bit5+bit6+bit7+bit0; + if(!bit3) + failures++; +} + +/* add_bit2uchar(void) - assumes bit0 = 1, aint0 = 7 */ + +void add_bit2uchar(void) +{ + achar0 += bit0; + + if(achar0 != 8) + failures++; + + if(achar0 == bit0) + failures++; +} + +void add_bit2uint(void) +{ + if(aint0 != bit11) + failures++; + + aint0 += bit0; + if(aint0!=1) + failures++; +} +#endif + +/***********************************/ + +void addlits(void) +{ + aint0 += 0x0001; + + if(aint0 != 1) + failures++; + + aint0 += 0x00; + + if(aint0 != 1) + failures++; + + aint0 += 0x00fe; + if(aint0 != 0x00ff) + failures++; + + aint0 += 0x0001; + + if(aint0 != 0x0100) + failures++; + + aint0++; + if(aint0 != 0x0101) + failures++; + + aint0 += 0x00ff; + if(aint0 != 0x0200) + failures++; + + aint0 += 0x00a0; + if(aint0 != 0x02a0) + failures++; + + aint0 += 0x0061; + if(aint0 != 0x0301) + failures++; + + aint0 += 0x0100; + if(aint0 != 0x0401) + failures++; + + aint0 += 0x0101; + if(aint0 != 0x0502) + failures++; + + aint0 += 0x00fd; + if(aint0 != 0x05ff) + failures++; + + aint0 += 0x0101; + if(aint0 != 0x0700) + failures++; + + aint0 += 0x01ff; + if(aint0 != 0x08ff) + failures++; + + aint0 += 0x01ff; + if(aint0 != 0x0afe) + failures++; + + aint0 += 0xff02; + if(aint0 != 0x0a00) + failures++; + + aint0 += 0xffff; + if(aint0 != 0x09ff) + failures++; + + aint0 += 0xff01; + if(aint0 != 0x0900) + failures++; + + aint0 += 0xff00; + if(aint0 != 0x0800) + failures++; + + aint0 += 0xff01; + if(aint0 != 0x0701) + failures++; + + aint0 += 0x0300; + if(aint0 != 0x0a01) + failures++; + + aint0 += 0x03ff; + if(aint0 != 0x0e00) + failures++; + + aint0 += 0x0301; + if(aint0 != 0x1101) + failures++; + + aint0 += 0x03fe; + if(aint0 != 0x14ff) + failures++; + + aint0 += 0x0301; + if(aint0 != 0x1800) + failures++; +} + +int main(void) +{ + add_lit2uint(); + + aint0=16; + aint1=0; + add_uint2uint(); + + aint0 = 0; + aint1 = 32; + aint2 = 0; + add_uint2uint2(); + +#ifdef SUPPORT_BIT_TYPES + add_bits(); + + achar0 = 7; + add_bit2uchar(); + + aint0 = 0; + bit0 = 1; + add_bit2uint(); +#endif + + aint0 = 0; + addlits(); + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/add3.c b/test/val/add3.c new file mode 100644 index 000000000..abbc93b47 --- /dev/null +++ b/test/val/add3.c @@ -0,0 +1,263 @@ +/* + !!DESCRIPTION!! Addition tests - mostly int's + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> + +unsigned char failures=0; + +char char0 = 0; +char char1 = 0; +char char2 = 0; + +/* + this test assumes: + sizeof(char) == 1 + sizeof(int) == 2 + sizeof(long) == 4 +*/ + +#ifdef REFERENCE + +/* + make sure the reference output uses types with + proper size +*/ + +#include <stdint.h> + +#ifdef SIZEOF_INT_16BIT +int16_t int0 = 0; +int16_t int1 = 0; +#else +int32_t int0 = 0; +int32_t int1 = 0; +#endif +int32_t long0 = 0; +int32_t long1 = 0; +uint32_t ulong0 = 0; +uint32_t ulong1 = 0; + +#else + +int int0 = 0; +int int1 = 0; +long long0 = 0; +long long1 = 0; +unsigned long ulong0 = 0; +unsigned long ulong1 = 0; + +#endif + +#ifdef SUPPORT_BIT_TYPES + +bit bit0 = 0; +bit bit1 = 0; +bit bit2 = 0; +bit bit3 = 0; +bit bit4 = 0; +bit bit5 = 0; +bit bit6 = 0; +bit bit7 = 0; +bit bit8 = 0; +bit bit9 = 0; +bit bit10 = 0; +bit bit11 = 0; + +#endif + +void done(char *name) +{ + printf("%s done - failures: %d\n", name, failures); + + if(failures) + exit(failures); +} + +void add_char2char(void) +{ + if(char0 != 4) + failures++; + if(char1 != 5) + failures++; + + char0 = char0 + char1; + + if(char0 != 9) + failures++; + + char0 += 127; + +#if (!defined(REFCC) && defined(UNSIGNED_CHARS)) || (defined(REFCC) && defined(REFCC_UNSIGNED_CHARS)) + if(char0 < 0) + failures++; + + if(char0 != (127+9)) + failures++; +#else + if(char0 > 0) + failures++; + + if(char0 != -0x78) + failures++; +#endif + + done("add_char2char"); +} + +void add_compound_char(void) +{ + char0 = char1+5; + + if(char0 != 9) + failures++; + + if((char0+char1) != 13) + failures++; + + done("add_compound_char"); +} + +void add_int2int(void) +{ + if(int0 != 4) + failures++; + if(int1 != 5) + failures++; + + int0 += int1; + if(int0 != 9) + failures++; + + int0 += 0x7fff; + if(int0 != -0x7ff8) + failures++; + + done("add_int2int"); +} + +void add_compound_int(void) +{ + int0 = int1+5; + + if(int0 != 9) + failures++; + + if((int0+int1) != 13) + failures++; + + done("add_compound_int"); +} + +void add_lit2long(void) +{ + if(long0 != 0) + failures++; + + long0++; + + if(long0 != 1) + failures++; + + long0 = long0 + 0xff; + + if(long0 != 0x100) + failures++; + + long0 = long0 + 0x100; + if(long0 != 0x200) + failures++; + + long0 = long0 + 0xfe00; + if(long0 != 0x10000) + failures++; + + long0 = long0 + 0xff0000; + if(long0 != 0x1000000) + failures++; + + long0 = long0 + 0x7e000000; + if(long0 != 0x7f000000) + failures++; + + /* wrap around zero */ + long0 = long0 + 0x2000000; + if(long0 != -0x7f000000) + failures++; + + long0 = long0 + 0x7f000000; + if(long0 != 0) + failures++; + + done("add_lit2long"); +} + +void add_lit2ulong(void) +{ + if(ulong0 != 0) + failures++; + + ulong0++; + + if(ulong0 != 1) + failures++; + + ulong0 = ulong0 + 0xff; + + if(ulong0 != 0x100) + failures++; + + ulong0 = ulong0 + 0x100; + if(ulong0 != 0x200) + failures++; + + ulong0 = ulong0 + 0xfe00; + if(ulong0 != 0x10000) + failures++; + + ulong0 = ulong0 + 0xff0000; + if(ulong0 != 0x1000000) + failures++; + + ulong0 = ulong0 + 0x7e000000; + if(ulong0 != 0x7f000000) + failures++; + + ulong0 = ulong0 + 0x2000000; + if(ulong0 != 0x81000000) + failures++; + + /* wrap around zero */ + ulong0 = ulong0 + 0x7f000000; + if(ulong0) + failures++; + + done("add_lit2ulong"); +} + +int main(void) +{ + char0=4; + char1 = char0 + 1; + add_char2char(); + + char1=4; + add_compound_char(); + + int0 = 4; + int1 = int0 + 1; + add_int2int(); + + int1=4; + add_compound_int(); + + add_lit2long(); + add_lit2ulong(); + + /* if not exit() */ + return 0; +} diff --git a/test/val/add3.o b/test/val/add3.o new file mode 100644 index 000000000..53a40880f Binary files /dev/null and b/test/val/add3.o differ diff --git a/test/val/add3.prg b/test/val/add3.prg new file mode 100644 index 000000000..9ababe609 Binary files /dev/null and b/test/val/add3.prg differ diff --git a/test/val/add4.c b/test/val/add4.c new file mode 100644 index 000000000..f02a7fb9c --- /dev/null +++ b/test/val/add4.c @@ -0,0 +1,94 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +int int0 = 0; +int int1 = 0; +char char0 = 0; +char char1 = 0; +long long0 = 0; +long long1 = 0; +unsigned long ulong0 = 0; +unsigned long ulong1 = 0; +#define NULL 0 +char *cP0=NULL; +char *cP1=NULL; +int *iP0=NULL; +int *iP1=NULL; + +void +done () +{ + dummy++; +} + +/* pointer to char arithmetic */ + +void pc_add(void) +{ + if(*cP1) + failures++; + + *cP1 += 1; + if(*cP1 != 1) + failures++; + + if(char0 != 1) + failures++; + + char0++; + + if(*cP1 != 2) + failures++; + + char1 = char0 + *cP1; + + if(char1 != 4) + failures++; +} + +/* pointer to integer arithmetic */ +void pi_add(void) +{ + if(*iP0) + failures++; + + *iP0 += 1; + + if(*iP0 != 1) + failures++; + + if(int0 != 1) + failures++; + + int1 = int0 + *iP0; + if(int1 != 2) + failures++; +} + +int main(void) +{ + cP1 = &char0; + pc_add(); + + iP0 = &int0; + pi_add(); + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/add4.o b/test/val/add4.o new file mode 100644 index 000000000..cc6c6aa52 Binary files /dev/null and b/test/val/add4.o differ diff --git a/test/val/add4.prg b/test/val/add4.prg new file mode 100644 index 000000000..b00f31329 Binary files /dev/null and b/test/val/add4.prg differ diff --git a/test/val/and1.c b/test/val/and1.c new file mode 100644 index 000000000..2409fe63e --- /dev/null +++ b/test/val/and1.c @@ -0,0 +1,145 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +unsigned int uint0 = 0; +unsigned int uint1 = 0; +unsigned char uchar0 = 0; +unsigned char uchar1 = 0; +unsigned long ulong0 = 0; + +void done() +{ + dummy++; +} + +/* uchar0 = 0xff; */ +void and_lit2uchar(void) +{ + if(uchar0 != 0xff) + failures++; + + uchar0 &= 0x7f; + + if(uchar0 != 0x7f) + failures++; + + uchar0 &= 0x3f; + + if(uchar0 != 0x3f) + failures++; + + uchar0 &= 0xdf; + + if(uchar0 != 0x1f) + failures++; +} + +void and_lit2uint(void) +{ + if(uint0 != 0xffff) + failures++; + + uint0 &= 0x7fff; + + if(uint0 != 0x7fff) + failures++; + + uint0 &= 0x3fff; + + if(uint0 != 0x3fff) + failures++; + + uint0 &= 0xdfff; + + if(uint0 != 0x1fff) + failures++; + + uint0 &= 0xff7f; + + if(uint0 != 0x1f7f) + failures++; + + uint0 &= 0x0f0f; + + if(uint0 != 0x0f0f) + failures++; + + uint0 &= 0xfefe; + + if(uint0 != 0x0e0e) + failures++; + + uint0 &= 0xf0f0; + + if(uint0 != 0) + failures++; +} + +void and_lit2ulong(void) +{ + if(ulong0 != 0xffffffff) + failures++; + + ulong0 &= 0x7fffffff; + + if(ulong0 != 0x7fffffff) + failures++; + + ulong0 &= 0xff00ffff; + + if(ulong0 != 0x7f00ffff) + failures++; + + ulong0 &= 0xfeff00ff; + + if(ulong0 != 0x7e0000ff) + failures++; +} + +/*-----------*/ +void and_uchar2uchar(void) +{ + uchar0 &= uchar1; + + if(uchar0 != 0x0f) + failures++; + + uchar1 &= 0xf7; + + uchar0 = uchar1 & 0xfe; + + if(uchar0 != 0x06) + failures++; +} + +int main(void) +{ + uchar0 = 0xff; + and_lit2uchar(); + + uint0 = 0xffff; + and_lit2uint(); + + ulong0 = 0xffffffff; + and_lit2ulong(); + + uchar0 = 0xff; + uchar1 = 0x0f; + and_uchar2uchar(); + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/and2.c b/test/val/and2.c new file mode 100644 index 000000000..672bd6019 --- /dev/null +++ b/test/val/and2.c @@ -0,0 +1,118 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +unsigned int uint0 = 0; +unsigned int uint1 = 0; +unsigned char uchar0 = 0; +unsigned char uchar1 = 0; +unsigned long ulong0 = 0; + +void done() +{ + dummy++; +} + +/* uchar0 = 0x13; */ +void and_compound1(void) +{ + uchar0 = (uchar0 + 1) & 0x0f; + if(uchar0 != 4) + failures++; +} + +/* uchar1 = 0x42; */ +void and_compound2(void) +{ + uchar0 = (uchar1 + 1) & 0x0f; + if(uchar0 != 3) + failures++; + + if(uchar1 != 0x42) + failures++; +} + +/* uchar0 = 0x13; */ +void or_compound1(void) +{ + uchar0 = (uchar0 + 0xe) | 0x0f; + if(uchar0 != 0x2f) + failures++; +} + +/* uchar1 = 0x47; */ +void or_compound2(void) +{ + uchar0 = (uchar1 + 0xf) | 0x0f; + if(uchar0 != 0x5f) + failures++; + + if(uchar1 != 0x47) + failures++; +} + +/* uchar0 = 0x13; */ +void xor_compound1(void) +{ + uchar0 = (uchar0 + 1) ^ 0x0f; + if(uchar0 != 0x1b) + failures++; +} + +/* uchar1 = 0x47; */ +void xor_compound2(void) +{ + uchar0 = (uchar1 + 0xf) ^ 0x0f; + if(uchar0 != 0x59) + failures++; + + if(uchar1 != 0x47) + failures++; +} + +/* uchar0 = 0x13; */ +void neg_compound1(void) +{ + uchar0 = ~(uchar0 + 1); + if(uchar0 != 0xeb) + failures++; +} + +int main(void) +{ + uchar0 = 0x13; + and_compound1(); + + uchar1 = 0x42; + and_compound2(); + + uchar0 = 0x13; + or_compound1(); + + uchar1 = 0x47; + or_compound2(); + + uchar0 = 0x13; + xor_compound1(); + + uchar1 = 0x47; + xor_compound2(); + + uchar0 = 0x13; + neg_compound1(); + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/atoi-test.c b/test/val/atoi-test.c new file mode 100644 index 000000000..5f5fa65e7 --- /dev/null +++ b/test/val/atoi-test.c @@ -0,0 +1,42 @@ +/* + !!DESCRIPTION!! A small test for atoi. Assumes twos complement + !!ORIGIN!! + !!LICENCE!! + !!AUTHOR!! +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <errno.h> + +static unsigned int Failures = 0; + +static void CheckAtoi (const char* Str, int Val) +{ + int Res = atoi (Str); + if (Res != Val) { + printf ("atoi error in \"%s\":\n" + " result = %d, should be %d\n", Str, Res, Val); + ++Failures; + } +} + +int main (void) +{ + CheckAtoi ("\t +0A", 0); + CheckAtoi ("\t -0.123", 0); + CheckAtoi (" -32 ", -32); + CheckAtoi (" +32 ", 32); + CheckAtoi ("0377", 377); + CheckAtoi (" 0377 ", 377); + CheckAtoi (" +0377 ", 377); + CheckAtoi (" -0377 ", -377); + CheckAtoi ("0x7FFF", 0); + CheckAtoi (" +0x7FFF", 0); + CheckAtoi (" -0x7FFF", 0); + printf ("Failures: %u\n", Failures); + + return Failures; +} diff --git a/test/val/bool1.c b/test/val/bool1.c new file mode 100644 index 000000000..2bdccd436 --- /dev/null +++ b/test/val/bool1.c @@ -0,0 +1,130 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned char achar0 = 0; +unsigned char achar1 = 0; + +void done() +{ + dummy++; +} + +void bool_or1(void) +{ + if( (achar0 >0) || (achar1 >0 )) + failures++; +} + +void bool_or2(void) +{ + if( achar0 || achar1) + failures++; +} + +void bool_test1(void) +{ + if( (achar0==0) || achar1) + failures++; +} + +void bool_test2(void) +{ + if( (achar0==0) || aint0) + failures++; +} + +void bool_and1(void) +{ + if( achar0 && achar1) + failures++; +} + +void bin_or1(void) +{ + char t; + + t = achar0 | achar1; + if(t) + failures++; +} + +void bin_xor1(void) +{ + if(achar0 ^ achar1) + failures++; +} + +void bool_test3(void) +{ + if((achar0 == 0x42) || (achar1 == 42)) + failures++; +} + +void bool_or_lit1(void) +{ + achar0 |= 0x0f; + + if(achar0 > 0x10) + failures++; + + if( (achar0 | 0x10) > 0xf0) + failures++; +} + +void bool_and_lit1(void) +{ + achar0 &= 0xf0; + + if(achar0 > 0x10) + failures++; + + if( (achar0 & 0x10) > 0xf0) + failures++; + + achar0 &= 0xef; +} + +int main(void) +{ + bool_or1(); + bool_or2(); + bool_and1(); + bin_or1(); + bin_xor1(); + + achar0++; + bool_and1(); + bool_test1(); + bool_test2(); + bool_test3(); + + achar0--; achar1++; + bool_and1(); + + achar0=0; + achar1=0; + + bool_or_lit1(); + bool_and_lit1(); + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/bool3.c b/test/val/bool3.c new file mode 100644 index 000000000..73c03a3e2 --- /dev/null +++ b/test/val/bool3.c @@ -0,0 +1,66 @@ +/* + !!DESCRIPTION!! Compound comparisons + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +bit bit1 = 0; +#endif +unsigned int ui0 = 0; +unsigned int ui1 = 0; +unsigned char uc0 = 0; +unsigned char uc1 = 0; +unsigned long uL0 = 0; +unsigned long uL1 = 0; + +void done() +{ + dummy++; +} + +void compound_compare_uc(void) +{ + failures += (uc0 != uc1); +} + +void compound_compare_ui(void) +{ + failures += (ui0 != ui1); +} + +void compound_compare_ul(void) +{ + failures += (uL0 != uL1); +} + +void compound_compare_uc_lit(void) +{ + failures += (uc0 != 0xff); + failures += (uc0 != 0xff); + failures += (uc0 == 0); +} + +int main(void) +{ + compound_compare_uc(); + compound_compare_ui(); + compound_compare_ul(); + + uc0 = 0xff; + compound_compare_uc_lit(); + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/call1.c b/test/val/call1.c new file mode 100644 index 000000000..c7ac920b3 --- /dev/null +++ b/test/val/call1.c @@ -0,0 +1,157 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int uint0 = 0; +unsigned int uint1 = 0; +unsigned char uchar0 = 0; +unsigned char uchar1 = 0; + +unsigned char call3 (void); + +void +done () +{ + dummy++; +} + +void +call1 (unsigned char uc0) +{ + if (uc0) + failures++; +} + +void +call2 (unsigned int ui0) +{ + if (ui0) + failures++; +} + +unsigned char +call3 (void) +{ + if (uchar0) + failures++; + + return (failures); +} + +unsigned int +call4 (void) +{ + unsigned int i = 0; + + if (uint0) + i++; + + return (i); +} + +unsigned int +call5 (unsigned int k) +{ + if (k) + failures++; + + return (k); +} + +unsigned char +call6a(unsigned char uc) +{ + if(uc>uchar1) + return 1; + else + return 0; +} + +unsigned char +call6(unsigned char uc) +{ + return(call6a(uc)); +} + +unsigned int +call7a(unsigned int ui) +{ + if(ui) + return 1; + else + return 0; +} + +unsigned int +call7(unsigned int ui) +{ + return(call7a(ui)); +} + +unsigned char +call8(unsigned char uc1,unsigned char uc2) +{ + return uc1+uc2; +} + +void call9(unsigned int ui1, unsigned int ui2) +{ + if(ui1 != 0x1234) + failures++; + if(ui2 != 0x5678) + failures++; +} + +int +main (void) +{ + call1 (uchar0); + call2 (uint0); + uchar1 = call3 (); + uint1 = call4 (); + if (uint1) + failures++; + + uint1 = call5 (uint0); + if (uint1) + failures++; + + if(call6(uchar0)) + failures++; + + if(call7(0)) + failures++; + + if(!call7(1)) + failures++; + + if(!call7(0xff00)) + failures++; + + uchar0=4; + uchar1=3; + uchar0 = call8(uchar0,uchar1); + + if(uchar0 != 7) + failures++; + + call9(0x1234,0x5678); + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/cc65091020.c b/test/val/cc65091020.c new file mode 100644 index 000000000..8ec11ef8d --- /dev/null +++ b/test/val/cc65091020.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! bit field bug + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Johan Kotlinski +*/ + +#include <assert.h> + +struct { + int foo : 7; + int bar : 4; +} baz = { 0, 2 }; + +int main() { + char bar = baz.bar; + + assert(2 == bar); + + printf("it works :)\n"); + + /* if not assert() */ + return 0; +} + +/* Assert fails. (SVN rev 4381) */ \ No newline at end of file diff --git a/test/val/compare1.c b/test/val/compare1.c new file mode 100644 index 000000000..0127e3b1b --- /dev/null +++ b/test/val/compare1.c @@ -0,0 +1,183 @@ +/* + !!DESCRIPTION!! test compare + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +/* + compare.c +*/ + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +bit bit1 = 0; +#endif + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; + +unsigned char achar0 = 0; +unsigned char achar1 = 0; +unsigned int aint0 = 0; +unsigned int aint1 = 0; + +char schar0 = 0; +char schar1 = 0; + +void +done () +{ + dummy++; +} + +/* achar0 should be zero */ + +void +compare_char_to_lits1 (void) +{ + if (achar0) + failures++; + + if (achar0 == 1) + failures++; + + if (achar0 == 7) + failures++; + + if (achar0 != 0) + failures++; +} + +/* achar0 should be `5' */ +void +compare_char_to_lits2 (void) +{ + if (!achar0) + failures++; + + if (achar0 == 1) + failures++; + + if (achar0 == 7) + failures++; + + if (achar0 != 5) + failures++; +} + +/* achar0 should equal achar1 */ +void +compare_char_to_char1 (void) +{ + if (achar0 != achar1) + failures++; + + if (schar0 != schar1) + failures++; +} + +/* achar0 should be different than achar1 */ +void +compare_char_to_char2 (void) +{ + if (achar0 == achar1) + failures++; +} + +/* aint0 should be zero */ + +void +compare_int_to_lits1 (void) +{ + if (aint0) + failures++; + + if (aint0 == 1) + failures++; + + if (aint0 == 7) + failures++; + + if (aint0 != 0) + failures++; +} + +/* aint0 should be `5' */ +void +compare_int_to_lits2 (void) +{ + if (!aint0) + failures++; + + if (aint0 == 1) + failures++; + + if (aint0 == 7) + failures++; + + if (aint0 != 5) + failures++; +} + +/* aint0 should be `0x1234' */ +void +compare_int_to_lits3 (void) +{ + if (!aint0) + failures++; + + if (aint0 == 1) + failures++; + + if (aint0 == 7) + failures++; + + if (aint0 != 0x1234) + failures++; +} + +/* aint0 should equal aint1 */ +void +compare_int_to_int1 (void) +{ + if (aint0 != aint1) + failures++; +} + +/* aint0 should be different than aint1 */ +void +compare_int_to_int2 (void) +{ + if (aint0 == aint1) + failures++; +} + +int +main (void) +{ + compare_char_to_lits1 (); + compare_char_to_char1 (); + achar0 = 5; + compare_char_to_lits2 (); + compare_char_to_char2 (); + + compare_int_to_lits1 (); + aint0 = 5; + compare_int_to_lits2 (); + aint0 = 0x1234; + compare_int_to_lits3 (); + compare_int_to_int2 (); + aint0 = 0; + compare_int_to_int1 (); + + success = failures; + done (); + + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/compare10.c b/test/val/compare10.c new file mode 100644 index 000000000..861a02d64 --- /dev/null +++ b/test/val/compare10.c @@ -0,0 +1,319 @@ +/* + !!DESCRIPTION!! Signed comparisons of the form: (variable>=LIT) + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +/* This regression test exercises all of the boundary + conditions in literal less than comparisons. There + are numerous opportunities to optimize these comparison + and each one has an astonishing capability of failing + a boundary condition. +*/ +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; +unsigned char result = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +int int0 = 0; +int int1 = 0; +unsigned char uchar0 = 0; +unsigned char uchar1 = 0; +signed char char0 = 0; +signed char char1 = 0; +char long0 = 0; +char long1 = 0; + +/* *** NOTE *** This particular test takes quite a while to run + * ~ 10,000,000 instruction cycles. (2.5 seconds on a 20Mhz PIC). + * The WDT will reset the CPU if it's enabled. So disable it... +*/ + +void +done () +{ + dummy++; +} + +void c_char_gte_lit1(unsigned char expected_result) +{ + result = 0; + + if(char0 >= -0x7f) + result |= 1; + + if(char0 >= -1) + result |= 2; + + if(char0 >= 0) + result |= 4; + + if(char0 >= 1) + result |= 8; + + if(char0 >= 0x7e) + result |= 0x10; + + if(char0 >= 0x7f) + result |= 0x20; + + if(result != expected_result) + { +/* LOG_ERROR(1); */ + printf("c_char_gte_lit1: char %02x - result %02x expected: %02x\n",char0,result,expected_result); + failures++; + } + +/* printf("char %02x - %02x failures: %d\n",char0,expected_result,failures); */ +} + +void char_compare(void) +{ + char0 = 0x7f; + c_char_gte_lit1(0x3f); + + char0 = 0x7e; + c_char_gte_lit1(0x1f); + + char0 = 0x40; + c_char_gte_lit1(0x0f); + + char0 = 0x2; + c_char_gte_lit1(0x0f); + + char0 = 0x1; + c_char_gte_lit1(0x0f); + + char0 = 0; + c_char_gte_lit1(0x07); + + char0 = -1; + c_char_gte_lit1(0x03); + + char0 = -2; + c_char_gte_lit1(0x01); + + char0 = -0x40; + c_char_gte_lit1(0x01); + + char0 = -0x7e; + c_char_gte_lit1(0x01); + + char0 = -0x7f; + c_char_gte_lit1(0x01); + + char0 = 0x80; + c_char_gte_lit1(0x00); + + /* Now test entire range */ + + for(char0=1; char0 != 0x7e; char0++) + c_char_gte_lit1(0x0f); + + for(char0=-0x7f; char0 != -1; char0++) + c_char_gte_lit1(0x01); +} + +void c_int_gte_lit1(unsigned char expected_result) +{ + result = 0; + + if(int0 >= 0) + result |= 1; + + if(int0 >= 1) + result |= 2; + + if(int0 >= 0xff) + result |= 4; + + if(int0 >= 0x100) + result |= 8; + + if(int0 >= 0x0101) + result |= 0x10; + + if(int0 >= 0x01ff) + result |= 0x20; + + if(int0 >= 0x0200) + result |= 0x40; + + if(int0 >= 0x0201) + result |= 0x80; + + if(result != expected_result) + failures=1; +} + +void int_compare1(void) +{ + int0 = -1; + c_int_gte_lit1(0x00); + + int0 = 0; + c_int_gte_lit1(0x01); + + int0 = 1; + c_int_gte_lit1(0x03); + + int0 = 2; + c_int_gte_lit1(0x03); + + int0 = 0xfe; + c_int_gte_lit1(0x03); + + int0 = 0xff; + c_int_gte_lit1(0x07); + + int0 = 0x100; + c_int_gte_lit1(0x0f); + + int0 = 0x101; + c_int_gte_lit1(0x1f); + + int0 = 0x102; + c_int_gte_lit1(0x1f); + + int0 = 0x1fe; + c_int_gte_lit1(0x1f); + + int0 = 0x1ff; + c_int_gte_lit1(0x3f); + + int0 = 0x200; + c_int_gte_lit1(0x7f); + + int0 = 0x201; + c_int_gte_lit1(0xff); + + int0 = 0x7f00; + c_int_gte_lit1(0xff); + + /* now check contiguous ranges */ + + for(int0 = -0x7fff; int0 != -1; int0++) + c_int_gte_lit1(0x00); + + for(int0 = 1; int0 != 0xff; int0++) + c_int_gte_lit1(0x03); + + for(int0 = 0x201; int0 != 0x7fff; int0++) + c_int_gte_lit1(0xff); +} + +void c_int_gte_lit2(unsigned char expected_result) +{ + result = 0; + + if(int0 >= -0x7fff) + result |= 1; + + if(int0 >= -0x7f00) + result |= 2; + + if(int0 >= -0x7eff) + result |= 4; + + if(int0 >= -0x7e00) + result |= 8; + + if(int0 >= -0x0101) + result |= 0x10; + + if(int0 >= -0x0100) + result |= 0x20; + + if(int0 >= -0xff) + result |= 0x40; + + if(int0 >= -1) + result |= 0x80; + + if(result != expected_result) + failures=1; +} + +void int_compare2(void) +{ + int0 = -0x7fff; + c_int_gte_lit2(0x01); + + int0 = -0x7f00; + c_int_gte_lit2(0x03); + + int0 = -0x7eff; + c_int_gte_lit2(0x07); + + int0 = -0x7e00; + c_int_gte_lit2(0x0f); + + int0 = -0x7dff; + c_int_gte_lit2(0x0f); + + int0 = -0x4567; + c_int_gte_lit2(0x0f); + + int0 = -0x200; + c_int_gte_lit2(0x0f); + + int0 = -0x102; + c_int_gte_lit2(0x0f); + + int0 = -0x101; + c_int_gte_lit2(0x1f); + + int0 = -0x100; + c_int_gte_lit2(0x3f); + + int0 = -0xff; + c_int_gte_lit2(0x7f); + + int0 = -0x02; + c_int_gte_lit2(0x7f); + + int0 = -0x01; + c_int_gte_lit2(0xff); + + int0 = 0; + c_int_gte_lit2(0xff); + + int0 = 1; + c_int_gte_lit2(0xff); + + int0 = 0x7fff; + c_int_gte_lit2(0xff); + + /* now check contiguous ranges */ + + for(int0 = -0x7fff; int0 != -0x7f00; int0++) + c_int_gte_lit2(0x01); + + for(int0 = -0x7e00; int0 != -0x101; int0++) + c_int_gte_lit2(0x0f); + + for(int0 = -1; int0 != 0x7fff; int0++) + c_int_gte_lit2(0xff); +} + +int +main (void) +{ + char_compare(); + printf("failures: %d\n",failures); + int_compare1(); + printf("failures: %d\n",failures); + int_compare2(); + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/compare2.c b/test/val/compare2.c new file mode 100644 index 000000000..afc2db8fc --- /dev/null +++ b/test/val/compare2.c @@ -0,0 +1,362 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned char achar0 = 0; +unsigned char achar1 = 0; + +void +done () +{ + dummy++; +} + +void +char_lt_char (void) +{ + if (achar0 < achar1) + failures++; +} + +void +char_gt_char (void) +{ + if (achar1 > achar0) + failures++; +} + +void +char_lte_char (void) +{ + if (achar0 <= achar1) + failures++; +} + +void +char_gte_char (void) +{ + if (achar1 >= achar0) + failures++; +} + +void +char_lt_lit (void) +{ + if (achar1 < 0x10) + failures++; +} + +void +char_gt_lit (void) +{ + if (achar1 > 0x10) + failures++; +} + +void +char_lte_lit (void) +{ + if (achar1 <= 0x0f) + failures++; +} + +void +char_gte_lit (void) +{ + if (achar1 >= 0x11) + failures++; +} + +/* now repeat test using negative logic */ +void +char_lt_char_else (void) +{ + if (achar0 >= achar1) + dummy++; + else + failures++; +} + +void +char_gt_char_else (void) +{ + if (achar1 <= achar0) + dummy++; + else + failures++; +} + +void +char_lte_char_else (void) +{ + if (achar0 > achar1) + dummy++; + else + failures++; +} + +void +char_gte_char_else (void) +{ + if (achar1 < achar0) + dummy++; + else + failures++; +} + +void +char_lt_lit_else (void) +{ + if (achar1 >= 0x10) + dummy++; + else + failures++; +} + +void +char_gt_lit_else (void) +{ + if (achar1 <= 0x10) + dummy++; + else + failures++; +} + +void +char_lte_lit_else (void) +{ + if (achar1 > 0x0f) + dummy++; + else + failures++; +} + +void +char_gte_lit_else (void) +{ + if (achar1 < 0x11) + dummy++; + else + failures++; +} + +/* ints */ + +void +int_lt_int (void) +{ + if (aint0 < aint1) + failures++; +} + +void +int_gt_int (void) +{ + if (aint1 > aint0) + failures++; +} + +void +int_lte_int (void) +{ + if (aint0 <= aint1) + failures++; +} + +void +int_gte_int (void) +{ + if (aint1 >= aint0) + failures++; +} + +void +int_lt_lit (void) +{ + if (aint1 < 0x10) + failures++; +} + +void +int_gt_lit (void) +{ + if (aint1 > 0x10) + failures++; +} + +void +int_lte_lit (void) +{ + if (aint1 <= 0x0f) + failures++; +} + +void +int_gte_lit (void) +{ + if (aint1 >= 0x11) + failures++; +} + +/* now repeat int comparisons using negative logic */ + +void +int_lt_int_else (void) +{ + if (aint0 >= aint1) + dummy++; + else + failures++; +} + +void +int_gt_int_else (void) +{ + if (aint1 <= aint0) + dummy++; + else + failures++; +} + +void +int_lte_int_else (void) +{ + if (aint0 > aint1) + dummy++; + else + failures++; +} + +void +int_gte_int_else (void) +{ + if (aint1 < aint0) + dummy++; + else + failures++; +} + +void +int_lt_lit_else (void) +{ + if (aint1 >= 0x10) + dummy++; + else + failures++; +} + +void +int_gt_lit_else (void) +{ + if (aint1 <= 0x10) + dummy++; + else + failures++; +} + +void +int_lte_lit_else (void) +{ + if (aint1 > 0x0f) + dummy++; + else + failures++; +} + +void +int_gte_lit_else (void) +{ + if (aint1 < 0x11) + dummy++; + else + failures++; +} + +int +main (void) +{ + char_lt_char (); + char_gt_char (); + + achar0++; + char_lt_char (); + char_gt_char (); + char_gte_char (); + char_lte_char (); + + achar1 = 0x10; + char_lt_lit (); + char_gt_lit (); + char_lte_lit (); + char_gte_lit (); + + achar0 = 0; + achar1 = 0; + + char_lt_char_else (); + char_gt_char_else (); + + achar0++; + char_lt_char_else (); + char_gt_char_else (); + char_gte_char_else (); + char_lte_char_else (); + + achar1 = 0x10; + char_lt_lit_else (); + char_gt_lit_else (); + char_lte_lit_else (); + char_gte_lit_else (); + + int_lt_int (); + int_gt_int (); + + aint0++; + int_lt_int (); + int_gt_int (); + int_gte_int (); + int_lte_int (); + + aint1 = 0x10; + int_lt_lit (); + int_gt_lit (); + int_lte_lit (); + int_gte_lit (); + + aint0=0; + aint1=0; + int_lt_int_else (); + int_gt_int_else (); + + aint0++; + int_lt_int_else (); + int_gt_int_else (); + int_gte_int_else (); + int_lte_int_else (); + + aint1 = 0x10; + int_lt_lit_else (); + int_gt_lit_else (); + int_lte_lit_else (); + int_gte_lit_else (); + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/compare3.c b/test/val/compare3.c new file mode 100644 index 000000000..614efd5e9 --- /dev/null +++ b/test/val/compare3.c @@ -0,0 +1,246 @@ +/* + !!DESCRIPTION!! regression testing program for comparing literals to variables + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +/* + compare3.c +*/ + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned char achar0 = 0; +unsigned char achar1 = 0; + +void +done () +{ + dummy++; +} + +/* compare to 0 + assumes + achar0 == 0 + achar1 != 0 + aint0 == 0 + aint1 != 0 +*/ +void c_0(void) +{ + if(achar0 != 0) + failures++; + + if(achar0) + failures++; + + if(achar1 == 0) + failures++; + + if(!achar1) + failures++; + + if(aint0 != 0) + failures++; + + if(aint0) + failures++; + + if(aint1 == 0) + failures++; + + if(!aint1) + failures++; +} + +/* compare to 1 + assumes + achar0 != 1 + achar1 == 1 + aint0 != 1 + aint1 == 1 +*/ +void c_1(void) +{ + if(achar0 == 1) + failures++; + + if(achar1 != 1) + failures++; + + if(aint0 == 1) + failures++; + + if(aint1 != 1) + failures++; +} + +/* compare to 2 + assumes + achar0 == 2 + aint0 == 2 +*/ +void c_2(void) +{ + if(achar0 != 2) + failures++; + + if(aint0 != 2) + failures++; +} + +/* compare to 0xff + assumes + achar0 == 0xff + aint0 == 0xff +*/ +void c_ff(void) +{ + if(achar0 != 0xff) + failures++; + + if(aint0 != 0xff) + failures++; + + if(aint0 == 0xfe) + failures++; + + if(aint0 == 0xff00) + failures++; +} + +/* compare to 0x00a5 + assumes + achar0 == 0xa5 + aint0 == 0x00a5 +*/ +void c_a5(void) +{ + if(achar0 != 0xa5) + failures++; + + if(aint0 != 0xa5) + failures++; + + if(aint0 == 0xa4) + failures++; + + if(aint0 == 0xa500) + failures++; +} + +/* compare to 0xa500 + assumes + achar0 == 0xa5 + aint0 == 0xa500 +*/ +void c_a500(void) +{ + if(achar0 == 0xa500) + failures++; + + if(aint0 != 0xa500) + failures++; + + if(aint0 == 0xa400) + failures++; + + if(aint0 == 0x00a5) + failures++; +} + +/* compare to 0xabcd + assumes + achar0 == 0xa5 + aint0 == 0xabcd +*/ +void c_abcd(void) +{ + if(achar0 == 0xabcd) + failures++; + + if(aint0 != 0xabcd) + failures++; + + if(aint0 == 0xab00) + failures++; + + if(aint0 == 0x00cd) + failures++; + + if(aint0 == 0x05cd) + failures++; + + if(aint0 == 0xab05) + failures++; + + if(aint0 == 0xab01) + failures++; + + if(aint0 == 0x01cd) + failures++; + + /* + if(aint0 == 0x1234abcd) + failures++; + */ +} + +/* assumes achar1 == 0 */ +void c_ifelse1(void) +{ + if(achar0) + achar0 = achar1; + else + achar0 = 0; + + if(achar0) + failures++; +} + +int +main (void) +{ + aint1 = 1; + achar1 = 1; + c_0(); + c_1(); + + aint0 = 2; + achar0 = 2; + c_2(); + + aint0 = 0xff; + achar0 = 0xff; + c_ff(); + + aint0 = 0xa5; + achar0 = 0xa5; + c_a5(); + + aint0 = 0xabcd; + c_abcd(); + + achar0 = 0; + achar1 = 0; + c_ifelse1(); + + achar0 = 1; + c_ifelse1(); + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/compare4.c b/test/val/compare4.c new file mode 100644 index 000000000..47948c3a3 --- /dev/null +++ b/test/val/compare4.c @@ -0,0 +1,349 @@ +/* + !!DESCRIPTION!! regression testing program for comparing signed chars and ints + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +/* + compare4.c +*/ + +/*#define COMPARE_OUT_OF_RANGE 1*/ + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +#ifdef SIZEOF_INT_16BIT +#if defined(__LINUX__) || defined(LINUX) +short int0 = 0; +short int1 = 0; + +#else +int int0 = 0; +int int1 = 0; + +#endif + +#else +int int0 = 0; +int int1 = 0; + +#endif + +signed char char0 = 0; +signed char char1 = 0; + +void +done () +{ + dummy++; +} + +/* compare to 0 + assumes + char0 == 0 + char1 != 0 + int0 == 0 + int1 != 0 +*/ +void c_0(void) +{ + if(char0 != 0) + failures++; + + if(char0) + failures++; + + if(char1 == 0) + failures++; + + if(!char1) + failures++; + + if(int0 != 0) + failures++; + + if(int0) + failures++; + + if(int1 == 0) + failures++; + + if(!int1) + failures++; + + if(char0>0) + failures++; + + if(int0>0) + failures++; + + if(char0<0) + failures++; + + if(int0<0) + failures++; +} + +/* compare to 1 + assumes + char0 != 1 + char1 == 1 + int0 != 1 + int1 == 1 +*/ +void c_1(void) +{ + if(char0 == 1) + failures++; + + if(char1 != 1) + failures++; + + if(int0 == 1) + failures++; + + if(int1 != 1) + failures++; + + if(char0 < 0) + failures++; + + if(int0 < 0) + failures++; +} + +/* compare to 2 + assumes + achar0 == 2 + aint0 == 2 +*/ +void c_2(void) +{ + if(char0 != 2) + failures++; + + if(int0 != 2) + failures++; +} + +/* compare to 0xff + assumes + achar0 == 0xff + aint0 == 0xff +*/ +void c_ff(void) +{ + if((unsigned char)char0 != 0xff) + failures++; + + if((unsigned short)int0 != 0xff) + failures++; + + if((unsigned short)int0 == 0xfe) + failures++; + + if((unsigned short)int0 == 0xff00) + failures++; +} + +/* compare to 0x00a5 + assumes + char0 == 0xa5 + int0 == 0x00a5 +*/ +void c_a5(void) +{ + if((unsigned char)char0 != 0xa5) + failures++; + + if((unsigned short)int0 != 0xa5) + failures++; + + if((unsigned short)int0 == 0xa4) + failures++; + + if((unsigned short)int0 == 0xa500) + failures++; +} + +/* compare to 0xa500 + assumes + char0 == 0xa5 + int0 == 0xa500 +*/ +void c_a500(void) +{ +#ifdef COMPARE_OUT_OF_RANGE + if(char0 == 0xa500) + failures++; +#endif + + if((unsigned short)int0 != 0xa500) + failures++; + + if(int0 != 0x44) + int0 = 0x28; + + if((unsigned short)int0 == 0xa400) + failures++; + + if(int0 == 0x00a5) + failures++; +} + +/* compare to 0xabcd + assumes + char0 == 0xa5 + int0 == 0xabcd +*/ +void c_abcd(void) +{ +#ifdef COMPARE_OUT_OF_RANGE + if(char0 == 0xabcd) + failures++; +#endif +/* + if(int0 != 0xabcd) + failures++; +*/ + if((unsigned short)int0 == 0xab00) + failures++; + + if(int0 == 0x00cd) + failures++; + + if(int0 == 0x05cd) + failures++; + + if((unsigned short)int0 == 0xab05) + failures++; + + if((unsigned short)int0 == 0xab01) + failures++; + + if(int0 == 0x01cd) + failures++; + + if(int0 > 0) + failures++; + +#ifdef COMPARE_OUT_OF_RANGE + if(int0 == 0x1234abcd) + failures++; +#endif +} + +/* assumes char1 == 0 */ +void c_ifelse1(void) +{ + if(char0) + char0 = char1; + else + char0 = 0; + + if(char0) + failures++; +} + +/* assumes char0 = -1 + assumes int0 = -1 +*/ +void c_minus1(void) +{ + if(char0 != -1) + failures++; + + printf("%d\n",failures); + + if(int0 != -1) + failures++; + + printf("%d\n",failures); + + if(char0 != int0) + failures++; + + printf("%d\n",failures); + + if(char0>0) + failures++; + + printf("%d\n",failures); + + if(int0>0) + failures++; + + printf("%d\n",failures); +} + +void c_c0gtc1(void) +{ + if(char0 < char1) + failures++; + + printf("%d\n",failures); +} + +int main(void) +{ + int1 = 1; + char1 = 1; + c_0(); + printf("failures: %d\n",failures); + c_1(); + printf("failures: %d\n",failures); + + int0 = 2; + char0 = 2; + c_2(); + printf("failures: %d\n",failures); + + int0 = 0xff; + char0 = 0xff; + c_ff(); + printf("failures: %d\n",failures); + + int0 = 0xa5; + char0 = 0xa5; + c_a5(); + printf("failures: %d\n",failures); + + int0 = 0xabcd; + /*c_abcd();*/ + + char0 = 0; + char1 = 0; + c_ifelse1(); + printf("failures: %d\n",failures); + + char0 = 1; + c_ifelse1(); + printf("failures: %d\n",failures); + + char0 = -1; + int0 = -1; + c_minus1(); + printf("failures: %d\n",failures); + + char0 = 5; + char1 = 3; + c_c0gtc1(); + printf("failures: %d\n",failures); + + char1 = -3; + c_c0gtc1(); + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/compare5.c b/test/val/compare5.c new file mode 100644 index 000000000..b5dd93f01 --- /dev/null +++ b/test/val/compare5.c @@ -0,0 +1,445 @@ +/* + !!DESCRIPTION!! regression testing program for comparing longs + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +/* + compare5.c +*/ + +#define COMPARE_OUT_OF_RANGE 1 + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +int int0 = 0; +int int1 = 0; +char char0 = 0; +char char1 = 0; +long long0 = 0; +long long1 = 0; +unsigned long ulong0 = 0; +unsigned long ulong1 = 0; + +void +done () +{ + dummy++; +} + +/* compare to 0 + assumes + long0 == 0 + ulong0 == 0 +*/ +void c_0(void) +{ + if(long0 != 0) + failures++; + + if(long0 > 0) + failures++; + + if(ulong0 != 0) + failures++; + + if(ulong0 > 0) + failures++; +} + +/* compare to 1 + assumes + long1 == 1 + ulong1 == 1 +*/ +void c_1(void) +{ + if(long0 == 1) + failures++; + + if(long1 != 1) + failures++; + + if(ulong0 == 1) + failures++; + + if(ulong1 != 1) + failures++; + + if(long1 < 0) + failures++; + + if(long1 < 1) + failures++; + + if(ulong1 < 1) + failures++; + + if(long1 > 1) + failures++; + + if(ulong1 > 1) + failures++; +} + +/* compare to 2 + assumes + long0 == 2 + ulong0 == 2 +*/ +void c_2(void) +{ + if(long0 != 2) + failures++; + + if(ulong0 != 2) + failures++; + + if(long1 == 2) + failures++; + + if(ulong1 == 2) + failures++; +} + +/* compare to 0xff + assumes + achar0 == 0xff + aint0 == 0xff +*/ +void c_ff(void) +{ + if(long0 != 0xff) + failures++; + + if(ulong0 != 0xff) + failures++; + + if(long1 == 0xff) + failures++; + + if(ulong1 == 0xff) + failures++; +} + +/* compare to 0x200 + assumes + achar0 == 0x200 + aint0 == 0x200 +*/ +void c_200(void) +{ + if(long0 != 0x200) + failures++; + + if(ulong0 != 0x200) + failures++; + + if(long1 == 0x200) + failures++; + + if(ulong1 == 0x200) + failures++; +} + +/* compare to 0x20000 + assumes + long0 == 0x20000 + ulong0 == 0x20000 + long1 != 0x20000 + ulong1 != 0x20000 +*/ +void c_20000(void) +{ + if(long0 != 0x20000) + failures++; + + if(ulong0 != 0x20000) + failures++; + + if(long1 == 0x20000) + failures++; + + if(ulong1 == 0x20000) + failures++; + + if(long0 <= 0x10000) + failures++; + + if(long0 < 0x10000) + failures++; + +/* if(long0 < 0x12345) + failures++; +*/ + if(long0 == 0) + failures++; +} + +/* compare to 0x00a5 + assumes + char0 == 0xa5 + int0 == 0x00a5 +*/ +void c_a5(void) +{ + if(char0 != 0xa5) + failures++; + + if(int0 != 0xa5) + failures++; + + if(int0 == 0xa4) + failures++; + + if(int0 == 0xa500) + failures++; +} + +/* compare to 0xa500 + assumes + char0 == 0xa5 + int0 == 0xa500 +*/ +void c_a500(void) +{ +#ifdef COMPARE_OUT_OF_RANGE + if(char0 == 0xa500) + failures++; +#endif + + if(int0 != 0xa500) + failures++; + + if(int0 == 0xa400) + failures++; + + if(int0 == 0x00a5) + failures++; +} + +/* compare to 0xabcd + assumes + char0 == 0xa5 + int0 == 0xabcd +*/ +void c_abcd(void) +{ +#ifdef COMPARE_OUT_OF_RANGE + if(char0 == 0xabcd) + failures++; +#endif + + if(int0 != 0xabcd) + failures++; + + if(int0 == 0xab00) + failures++; + + if(int0 == 0x00cd) + failures++; + + if(int0 == 0x05cd) + failures++; + + if(int0 == 0xab05) + failures++; + + if(int0 == 0xab01) + failures++; + + if(int0 == 0x01cd) + failures++; + + if(int0 > 0) + failures++; + +#ifdef COMPARE_OUT_OF_RANGE + if(int0 == 0x1234abcd) + failures++; +#endif +} + +/* assumes char1 == 0 */ +void c_ifelse1(void) +{ + if(char0) + char0 = char1; + else + char0 = 0; + + if(char0) + failures++; +} + +/* + assumes long0 = -1 + assumes long1 = 1 +*/ +void c_minus1(void) +{ + printf("long0:%ld long1:%ld\n",long0,long1); + + printf("(long0 != -1)\n"); + if(long0 != -1) + { + LOG_ERROR(1); + failures++; + } + printf("(long0 > 0)\n"); + if(long0 > 0) + { + LOG_ERROR(1); + failures++; + } + printf("(long1 < 0)\n"); + if(long1 < 0) + { + LOG_ERROR(1); + failures++; + } +/* + if(long1 < 2) + failures++; +*/ +} + +/* assumes + long0 = long1 = ulong0 = ulong1 == 0 +*/ +void c_long2long_eq(void) +{ + if(long0 != long1) + failures++; + + if(ulong0 != ulong1) + failures++; + + if(long0 != ulong1) + failures++; + + if(long0 > long1) + failures++; + + if(long0 < long1) + failures++; + + if(long0 > ulong0) + failures++; + + if(long0 < ulong0) + failures++; +} + +/* assumes + long0 = ulong0 == 0 + long1 = ulong1 == 1 +*/ +void c_long2long_neq(void) +{ + if(long0 == long1) + failures++; + + if(ulong0 == ulong1) + failures++; + + if(long1 != ulong1) + failures++; + + if(long1 < long0) + failures++; + + if(long1 <= long0) + failures++; + + if(ulong1 < ulong0) + failures++; + + if(ulong1 <= ulong0) + failures++; +} + +/* long0=-100; + long1=-1000; +*/ +void +c_long2neglit(void) +{ + if(long0>0) + failures++; + if(long1>0) + failures++; + + if(long1 > long0) + failures++; + + if(long1 > 100) + failures++; + + if(long0 > -50) + failures++; + + if(long1 < -5000) + failures++; +} + +int +main (void) +{ + c_0(); + printf("c_0: %d\n",failures); + + c_long2long_eq(); + printf("c_long2long_eq: %d\n",failures); + + long1 = 1; + ulong1 = 1; + c_1(); + printf("c_1: %d\n",failures); + c_long2long_neq(); + printf("c_long2long_neq: %d\n",failures); + + long0 = 2; + ulong0 = 2; + c_2(); + printf("c_2: %d\n",failures); + + long0 = 0xff; + ulong0 = 0xff; + c_ff(); + printf("c_ff: %d\n",failures); + + long0 = 0x200; + ulong0 = 0x200; + c_200(); + printf("c_200: %d\n",failures); + + long0 = 0x20000; + ulong0 = 0x20000; + c_20000(); + printf("c_20000: %d\n",failures); + + long0 = -1; + c_minus1(); + printf("c_minus1: %d\n",failures); + + long0=-100; + long1=-1000; + c_long2neglit(); + printf("c_long2neglit: %d\n",failures); + + success = failures; + done (); + + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/compare6.c b/test/val/compare6.c new file mode 100644 index 000000000..85f16a1c4 --- /dev/null +++ b/test/val/compare6.c @@ -0,0 +1,176 @@ +/* + !!DESCRIPTION!! Compound comparisons + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +int int0 = 0; +int int1 = 0; +unsigned char uchar0 = 0; +unsigned char uchar1 = 0; +char char0 = 0; +char char1 = 0; +char long0 = 0; +char long1 = 0; + +void +done () +{ + dummy++; +} + +void c_char(void) +{ + if(char0 || char1) + failures++; + + if(char0 && char1) + failures++; + + if(char0 > char1) + failures++; + + if((char0+1) < char1) + failures++; + + if((char0+5) >= (char1+9)) + failures++; + + char0++; + + if(char0 && char1) + failures++; + + if(char0 != (char1+1) ) + failures++; + + if(!char0) + failures++; + + if(char1 || !char0) + failures++; + + if((char0 >5 ) && (char0 < 10)) + failures++; + + char0 +=5; /* char0 = 6 now */ + + if(!((char0 >5 ) && (char0 < 10))) + failures++; +} + +void c_int(void) +{ + if(int0 || int1) + failures++; + + if(int0 && int1) + failures++; + + if(int0 > int1) + failures++; + + if((int0+1) < int1) + failures++; + + if((int0+5) >= (int1+9)) + failures++; + + int0++; + + if(int0 && int1) + failures++; + + if(int0 != (int1+1) ) + failures++; + + if(!int0) + failures++; + + if(int1 || !int0) + failures++; + + if((int0 >5 ) && (int0 < 10)) + failures++; + + int0 +=5; /* int0 = 6 now */ + + if(!((int0 >5 ) && (int0 < 10))) + failures++; +} + +void c_long(void) +{ + if(long0 || long1) + failures++; + + if(long0 && long1) + failures++; + + if(long0 > long1) + failures++; + + if((long0+1) < long1) + failures++; + + if((long0+5) >= (long1+9)) + failures++; + + long0++; + + if(long0 && long1) + failures++; + + if(long0 != (long1+1) ) + failures++; + + if(!long0) + failures++; + + if(long1 || !long0) + failures++; + + if((long0 >5 ) && (long0 < 10)) + failures++; + + long0 +=5; /* long0 = 6 now */ + + if(!((long0 >5 ) && (long0 < 10))) + failures++; +} + +void c_uminus(void) +{ + int1 = -int0; + if(int1 < 0) + failures++; +} + +int +main (void) +{ + c_char(); + c_int(); + c_long(); + + int0 = -1; + c_uminus(); + if(int1 != 1) + failures++; + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/compare7.c b/test/val/compare7.c new file mode 100644 index 000000000..6c9636dec --- /dev/null +++ b/test/val/compare7.c @@ -0,0 +1,307 @@ +/* + !!DESCRIPTION!! Signed comparisons of the form: (variable<LIT) + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +/* This regression test exercises all of the boundary + conditions in literal less than comparisons. There + are numerous opportunities to optimize these comparison + and each one has an astonishing capability of failing + a boundary condition. +*/ +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; +unsigned char result = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +int int0 = 0; +int int1 = 0; +signed char char0 = 0; +signed char char1 = 0; +char long0 = 0; +char long1 = 0; + +/* *** NOTE *** This particular test takes quite a while to run + * ~ 10,000,000 instruction cycles. (2.5 seconds on a 20Mhz PIC). + * The WDT will reset the CPU if it's enabled. So disable it... +*/ + +void +done () +{ + dummy++; +} + +void c_char_lt_lit1(unsigned char expected_result) +{ + result = 0; + + if(char0 < -0x7f) + result |= 1; + + if(char0 < -1) + result |= 2; + + if(char0 < 0) + result |= 4; + + if(char0 < 1) + result |= 8; + + if(char0 < 0x7f) + result |= 0x10; + + if(result != expected_result) + failures++; +} + +void char_compare(void) +{ + char0 = 0x7f; + c_char_lt_lit1(0); + +/* return; */ + + char0 = 0x7e; + c_char_lt_lit1(0x10); + + char0 = 0x40; + c_char_lt_lit1(0x10); + + char0 = 0x2; + c_char_lt_lit1(0x10); + + char0 = 0x1; + c_char_lt_lit1(0x10); + + char0 = 0; + c_char_lt_lit1(0x18); + + char0 = -1; + c_char_lt_lit1(0x1c); + + char0 = -2; + c_char_lt_lit1(0x1e); + + char0 = -0x40; + c_char_lt_lit1(0x1e); + + char0 = -0x7e; + c_char_lt_lit1(0x1e); + + char0 = -0x7f; + c_char_lt_lit1(0x1e); + + char0 = 0x80; + c_char_lt_lit1(0x1f); + + /* Now test entire range */ + + for(char0=1; char0 != 0x7f; char0++) + c_char_lt_lit1(0x10); + + for(char0=-0x7f; char0 != -1; char0++) + c_char_lt_lit1(0x1e); +} + +void c_int_lt_lit1(unsigned char expected_result) +{ + result = 0; + + if(int0 < 0) + result |= 1; + + if(int0 < 1) + result |= 2; + + if(int0 < 0xff) + result |= 4; + + if(int0 < 0x100) + result |= 8; + + if(int0 < 0x0101) + result |= 0x10; + + if(int0 < 0x01ff) + result |= 0x20; + + if(int0 < 0x0200) + result |= 0x40; + + if(int0 < 0x0201) + result |= 0x80; + + if(result != expected_result) + failures=1; +} + +void int_compare1(void) +{ + int0 = -1; + c_int_lt_lit1(0xff); + + int0 = 0; + c_int_lt_lit1(0xfe); + + int0 = 1; + c_int_lt_lit1(0xfc); + + int0 = 2; + c_int_lt_lit1(0xfc); + + int0 = 0xfe; + c_int_lt_lit1(0xfc); + + int0 = 0xff; + c_int_lt_lit1(0xf8); + + int0 = 0x100; + c_int_lt_lit1(0xf0); + + int0 = 0x101; + c_int_lt_lit1(0xe0); + + int0 = 0x1fe; + c_int_lt_lit1(0xe0); + + int0 = 0x1ff; + c_int_lt_lit1(0xc0); + + int0 = 0x200; + c_int_lt_lit1(0x80); + + int0 = 0x201; + c_int_lt_lit1(0x0); + + int0 = 0x7f00; + c_int_lt_lit1(0x0); + + /* now check contiguous ranges */ + + for(int0 = -0x7fff; int0 != -1; int0++) + c_int_lt_lit1(0xff); + + for(int0 = 1; int0 != 0xff; int0++) + c_int_lt_lit1(0xfc); + + for(int0 = 0x201; int0 != 0x7fff; int0++) + c_int_lt_lit1(0); +} + +void c_int_lt_lit2(unsigned char expected_result) +{ + result = 0; + + if(int0 < -0x7fff) + result |= 1; + + if(int0 < -0x7f00) + result |= 2; + + if(int0 < -0x7eff) + result |= 4; + + if(int0 < -0x7e00) + result |= 8; + + if(int0 < -0x0101) + result |= 0x10; + + if(int0 < -0x0100) + result |= 0x20; + + if(int0 < -0xff) + result |= 0x40; + + if(int0 < -1) + result |= 0x80; + + if(result != expected_result) + failures=1; +} + +void int_compare2(void) +{ + int0 = -0x7fff; + c_int_lt_lit2(0xfe); + + int0 = -0x7f00; + c_int_lt_lit2(0xfc); + + int0 = -0x7eff; + c_int_lt_lit2(0xf8); + + int0 = -0x7e00; + c_int_lt_lit2(0xf0); + + int0 = -0x4567; + c_int_lt_lit2(0xf0); + + int0 = -0x200; + c_int_lt_lit2(0xf0); + + int0 = -0x102; + c_int_lt_lit2(0xf0); + + int0 = -0x101; + c_int_lt_lit2(0xe0); + + int0 = -0x100; + c_int_lt_lit2(0xc0); + + int0 = -0xff; + c_int_lt_lit2(0x80); + + int0 = -0x02; + c_int_lt_lit2(0x80); + + int0 = -0x01; + c_int_lt_lit2(0x00); + + int0 = 0; + c_int_lt_lit2(0x00); + + int0 = 1; + c_int_lt_lit2(0x00); + + int0 = 0x7fff; + c_int_lt_lit2(0x00); + + /* now check contiguous ranges */ + int0 = -0x7f01; + c_int_lt_lit2(0xfe); + + for(int0 = -0x7ffe; int0 != -0x7f01; int0++) + c_int_lt_lit2(0xfe); + + for(int0 = -0x7e00; int0 != -0x101; int0++) + c_int_lt_lit2(0xf0); + + for(int0 = -1; int0 != 0x7fff; int0++) + c_int_lt_lit2(0); +} + +int +main (void) +{ + char_compare(); + printf("failures: %d\n",failures); + + int_compare1(); + printf("failures: %d\n",failures); + int_compare2(); + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/compare8.c b/test/val/compare8.c new file mode 100644 index 000000000..0abff8c69 --- /dev/null +++ b/test/val/compare8.c @@ -0,0 +1,311 @@ +/* + !!DESCRIPTION!! Signed comparisons of the form: (variable>LIT) + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +/* This regression test exercises all of the boundary + conditions in literal less than comparisons. There + are numerous opportunities to optimize these comparison + and each one has an astonishing capability of failing + a boundary condition. +*/ +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; +unsigned char result = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +int int0 = 0; +int int1 = 0; +unsigned char uchar0 = 0; +unsigned char uchar1 = 0; +signed char char0 = 0; +signed char char1 = 0; +char long0 = 0; +char long1 = 0; + +/* *** NOTE *** This particular test takes quite a while to run + * ~ 10,000,000 instruction cycles. (2.5 seconds on a 20Mhz PIC). + * The WDT will reset the CPU if it's enabled. So disable it... +*/ + +void +done () +{ + dummy++; +} + +void c_char_gt_lit1(unsigned char expected_result) +{ + result = 0; + + if(char0 > -0x7f) + result |= 1; + + if(char0 > -1) + result |= 2; + + if(char0 > 0) + result |= 4; + + if(char0 > 1) + result |= 8; + + if(char0 > 0x7e) + result |= 0x10; + + if(char0 > 0x7f) + result |= 0x20; + + if(result != expected_result) + failures++; +} + +void char_compare(void) +{ + char0 = 0x7f; + c_char_gt_lit1(0x1f); + + char0 = 0x7e; + c_char_gt_lit1(0x0f); + + char0 = 0x40; + c_char_gt_lit1(0x0f); + + char0 = 0x2; + c_char_gt_lit1(0x0f); + + char0 = 0x1; + c_char_gt_lit1(0x07); + + char0 = 0; + c_char_gt_lit1(0x03); + + char0 = -1; + c_char_gt_lit1(0x01); + + char0 = -2; + c_char_gt_lit1(0x01); + + char0 = -0x40; + c_char_gt_lit1(0x01); + + char0 = -0x7e; + c_char_gt_lit1(0x01); + + char0 = -0x7f; + c_char_gt_lit1(0x00); + + char0 = 0x80; + c_char_gt_lit1(0x00); + + /* Now test entire range */ + + for(char0=2; char0 != 0x7f; char0++) + c_char_gt_lit1(0x0f); + + for(char0=-0x7e; char0 != -1; char0++) + c_char_gt_lit1(0x01); +} + +void c_int_gt_lit1(unsigned char expected_result) +{ + result = 0; + + if(int0 > 0) + result |= 1; + + if(int0 > 1) + result |= 2; + + if(int0 > 0xff) + result |= 4; + + if(int0 > 0x100) + result |= 8; + + if(int0 > 0x0101) + result |= 0x10; + + if(int0 > 0x01ff) + result |= 0x20; + + if(int0 > 0x0200) + result |= 0x40; + + if(int0 > 0x0201) + result |= 0x80; + + if(result != expected_result) + failures=1; +} + +void int_compare1(void) +{ + int0 = -1; + c_int_gt_lit1(0x00); + + int0 = 0; + c_int_gt_lit1(0x00); + + int0 = 1; + c_int_gt_lit1(0x01); + + int0 = 2; + c_int_gt_lit1(0x03); + + int0 = 0xfe; + c_int_gt_lit1(0x03); + + int0 = 0xff; + c_int_gt_lit1(0x03); + + int0 = 0x100; + c_int_gt_lit1(0x07); + + int0 = 0x101; + c_int_gt_lit1(0x0f); + + int0 = 0x102; + c_int_gt_lit1(0x1f); + + int0 = 0x1fe; + c_int_gt_lit1(0x1f); + + int0 = 0x1ff; + c_int_gt_lit1(0x1f); + + int0 = 0x200; + c_int_gt_lit1(0x3f); + + int0 = 0x201; + c_int_gt_lit1(0x7f); + + int0 = 0x7f00; + c_int_gt_lit1(0xff); + + /* now check contiguous ranges */ + + for(int0 = -0x7fff; int0 != -1; int0++) + c_int_gt_lit1(0x00); + + for(int0 = 2; int0 != 0xff; int0++) + c_int_gt_lit1(0x03); + + for(int0 = 0x202; int0 != 0x7fff; int0++) + c_int_gt_lit1(0xff); +} + +void c_int_gt_lit2(unsigned char expected_result) +{ + result = 0; + + if(int0 > -0x7fff) + result |= 1; + + if(int0 > -0x7f00) + result |= 2; + + if(int0 > -0x7eff) + result |= 4; + + if(int0 > -0x7e00) + result |= 8; + + if(int0 > -0x0101) + result |= 0x10; + + if(int0 > -0x0100) + result |= 0x20; + + if(int0 > -0xff) + result |= 0x40; + + if(int0 > -1) + result |= 0x80; + + if(result != expected_result) + failures=1; +} + +void int_compare2(void) +{ + int0 = -0x7fff; + c_int_gt_lit2(0x00); + + int0 = -0x7f00; + c_int_gt_lit2(0x01); + + int0 = -0x7eff; + c_int_gt_lit2(0x03); + + int0 = -0x7e00; + c_int_gt_lit2(0x07); + + int0 = -0x7dff; + c_int_gt_lit2(0x0f); + + int0 = -0x4567; + c_int_gt_lit2(0x0f); + + int0 = -0x200; + c_int_gt_lit2(0x0f); + + int0 = -0x102; + c_int_gt_lit2(0x0f); + + int0 = -0x101; + c_int_gt_lit2(0x0f); + + int0 = -0x100; + c_int_gt_lit2(0x1f); + + int0 = -0xff; + c_int_gt_lit2(0x3f); + + int0 = -0x02; + c_int_gt_lit2(0x7f); + + int0 = -0x01; + c_int_gt_lit2(0x7f); + + int0 = 0; + c_int_gt_lit2(0xff); + + int0 = 1; + c_int_gt_lit2(0xff); + + int0 = 0x7fff; + c_int_gt_lit2(0xff); + + /* now check contiguous ranges */ + + for(int0 = -0x7ffe; int0 != -0x7f01; int0++) + c_int_gt_lit2(0x01); + + for(int0 = -0x7dff; int0 != -0x101; int0++) + c_int_gt_lit2(0x0f); + + for(int0 = 0; int0 != 0x7fff; int0++) + c_int_gt_lit2(0xff); +} + +int +main (void) +{ + char_compare(); + int_compare1(); + int_compare2(); + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/compare9.c b/test/val/compare9.c new file mode 100644 index 000000000..4a3714199 --- /dev/null +++ b/test/val/compare9.c @@ -0,0 +1,297 @@ +/* + !!DESCRIPTION!! Signed comparisons of the form: (variable<=LIT) + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +/* + This regression test exercises all of the boundary + conditions in literal less than or equal comparisons. There + are numerous opportunities to optimize these comparison + and each one has an astonishing capability of failing + a boundary condition. +*/ + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; +unsigned char result = 0; + +int int0 = 0; +int int1 = 0; +signed char char0 = 0; +signed char char1 = 0; + +/* *** NOTE *** This particular test takes quite a while to run + * ~ 10,000,000 instruction cycles. (2.5 seconds on a 20Mhz PIC). + * The WDT will reset the CPU if it's enabled. So disable it... +*/ + +void +done () +{ + dummy++; +} + +void c_char_lte_lit1(unsigned char expected_result) +{ + result = 0; + + if(char0 <= -0x7f) + result |= 1; + + if(char0 <= -1) + result |= 2; + + if(char0 <= 0) + result |= 4; + + if(char0 <= 1) + result |= 8; + + if(char0 <= 0x7f) + result |= 0x10; + + if(result != expected_result) + failures++; +} + +void char_compare(void) +{ + char0 = 0x7f; + c_char_lte_lit1(0x10); + + char0 = 0x7e; + c_char_lte_lit1(0x10); + + char0 = 0x40; + c_char_lte_lit1(0x10); + + char0 = 0x2; + c_char_lte_lit1(0x10); + + char0 = 0x1; + c_char_lte_lit1(0x18); + + char0 = 0; + c_char_lte_lit1(0x1c); + + char0 = -1; + c_char_lte_lit1(0x1e); + + char0 = -2; + c_char_lte_lit1(0x1e); + + char0 = -0x40; + c_char_lte_lit1(0x1e); + + char0 = -0x7e; + c_char_lte_lit1(0x1e); + + char0 = -0x7f; + c_char_lte_lit1(0x1f); + + char0 = 0x80; + /* c_char_lte_lit1(0x1f); */ + + /* Now test entire range */ + + for(char0=2; char0 != 0x7f; char0++) + c_char_lte_lit1(0x10); + + for(char0=-0x7e; char0 != 0; char0++) + c_char_lte_lit1(0x1e); +} + +void c_int_lte_lit1(unsigned char expected_result) +{ + result = 0; + + if(int0 <= 0) + result |= 1; + + if(int0 <= 1) + result |= 2; + + if(int0 <= 0xff) + result |= 4; + + if(int0 <= 0x100) + result |= 8; + + if(int0 <= 0x0101) + result |= 0x10; + + if(int0 <= 0x01ff) + result |= 0x20; + + if(int0 <= 0x0200) + result |= 0x40; + + if(int0 <= 0x0201) + result |= 0x80; + + if(result != expected_result) + failures=1; +} + +void int_compare1(void) +{ + int0 = -1; + c_int_lte_lit1(0xff); + + int0 = 0; + c_int_lte_lit1(0xff); + + int0 = 1; + c_int_lte_lit1(0xfe); + + int0 = 2; + c_int_lte_lit1(0xfc); + + int0 = 0xfe; + c_int_lte_lit1(0xfc); + + int0 = 0xff; + c_int_lte_lit1(0xfc); + + int0 = 0x100; + c_int_lte_lit1(0xf8); + + int0 = 0x101; + c_int_lte_lit1(0xf0); + + int0 = 0x1fe; + c_int_lte_lit1(0xe0); + + int0 = 0x1ff; + c_int_lte_lit1(0xe0); + + int0 = 0x200; + c_int_lte_lit1(0xc0); + + int0 = 0x201; + c_int_lte_lit1(0x80); + + int0 = 0x7f00; + c_int_lte_lit1(0x0); + + /* now check contiguous ranges */ + + for(int0 = -0x7fff; int0 != 1; int0++) + c_int_lte_lit1(0xff); + + for(int0 = 2; int0 != 0xff; int0++) + c_int_lte_lit1(0xfc); + + for(int0 = 0x202; int0 != 0x7fff; int0++) + c_int_lte_lit1(0); +} + +void c_int_lte_lit2(unsigned char expected_result) +{ + result = 0; + + if(int0 <= -0x7fff) + result |= 1; + + if(int0 <= -0x7f00) + result |= 2; + + if(int0 <= -0x7eff) + result |= 4; + + if(int0 <= -0x7e00) + result |= 8; + + if(int0 <= -0x0101) + result |= 0x10; + + if(int0 <= -0x0100) + result |= 0x20; + + if(int0 <= -0xff) + result |= 0x40; + + if(int0 <= -1) + result |= 0x80; + + if(result != expected_result) + failures=1; +} + +void int_compare2(void) +{ + int0 = -0x7fff; + c_int_lte_lit2(0xff); + + int0 = -0x7f00; + c_int_lte_lit2(0xfe); + + int0 = -0x7eff; + c_int_lte_lit2(0xfc); + + int0 = -0x7e00; + c_int_lte_lit2(0xf8); + + int0 = -0x4567; + c_int_lte_lit2(0xf0); + + int0 = -0x200; + c_int_lte_lit2(0xf0); + + int0 = -0x102; + c_int_lte_lit2(0xf0); + + int0 = -0x101; + c_int_lte_lit2(0xf0); + + int0 = -0x100; + c_int_lte_lit2(0xe0); + + int0 = -0xff; + c_int_lte_lit2(0xc0); + + int0 = -0x02; + c_int_lte_lit2(0x80); + + int0 = -0x01; + c_int_lte_lit2(0x80); + + int0 = 0; + c_int_lte_lit2(0x00); + + int0 = 1; + c_int_lte_lit2(0x00); + + int0 = 0x7fff; + c_int_lte_lit2(0x00); + + /* now check contiguous ranges */ + + for(int0 = -0x7ffe; int0 != -0x7f00; int0++) + c_int_lte_lit2(0xfe); + + for(int0 = -0x7dff; int0 != -0x101; int0++) + c_int_lte_lit2(0xf0); + + for(int0 = 0; int0 != 0x7fff; int0++) + c_int_lte_lit2(0); +} + +int +main (void) +{ + char_compare(); + int_compare1(); + int_compare2(); + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/cq22.c b/test/val/cq22.c new file mode 100644 index 000000000..4ce40ecc0 --- /dev/null +++ b/test/val/cq22.c @@ -0,0 +1,144 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 2.2: identifiers (names) + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +/* + 2.2 Identifiers (Names) +*/ + +#ifndef NO_OLD_FUNC_DECL +s22(pd0) +struct defs *pd0; +{ +#else +int s22(struct defs *pd0) +{ +#endif + + int a234, a; + int _, _234, A, rc; + + static char s22er[] = "s22,er%d\n"; + static char qs22[8] = "s22 "; + + char *ps, *pt; + /* Initialize */ + + rc = 0; + ps = qs22; + pt = pd0 -> rfs; + while (*pt++ = *ps++); + + /* An identifier is a sequence of letters and digits; + the first character must be a letter. The under- + score _ counts as a letter. */ + + a=1; + _=2; + _234=3; + a234=4; + if(a+_+_234+a234 != 10) { + rc = rc+1; + if(pd0->flgd != 0) printf(s22er,1); + } + + /* Upper and lower case letters are different. */ + + A = 2; + if (A == a) { + rc = rc+4; + if (pd0->flgd != 0) printf(s22er,4); + } + + return(rc); +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#define cq_sections 1 + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s22(pd0); + } +} + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq241.c b/test/val/cq241.c new file mode 100644 index 000000000..d7d8ed952 --- /dev/null +++ b/test/val/cq241.c @@ -0,0 +1,286 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 2.41: integer constants, 2.42: explizit long constants + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +/* + 2.4.1 Integer constants + 2.4.2 Explicit long constants +*/ + +/* Calculate 2**n by multiplying, not shifting */ +#ifndef NO_OLD_FUNC_DECL +long pow2(n) +long n; +{ +#else +long pow2(long n) { +#endif + long s; + s = 1; + while(n--) s = s*2; + return s; +} + + long d[39], o[39], x[39]; + +#ifndef NO_OLD_FUNC_DECL +s241(pd0) +struct defs *pd0; +{ +#else +int s241(struct defs *pd0) { +#endif + +/* long pow2(); */ + static char s241er[] = "s241,er%d\n"; + static char qs241[8] = "s241 "; + char *ps, *pt; + int rc, j, lrc; + static long g[39] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,6,0,8,0,12,0,16,0,18,0,20,0,24, + 0,28,0,30,0,32,0,36}; +/* long d[39], o[39], x[39]; */ + + rc = 0; + lrc = 0; + ps = qs241; + pt = pd0 -> rfs; + while (*pt++ = *ps++); + + /* An integer constant consisting of a sequence of digits is + taken to be octal if it begins with 0 (digit zero), decimal + otherwise. */ + + if ( 8 != 010 + || 16 != 020 + || 24 != 030 + || 32 != 040 + || 40 != 050 + || 48 != 060 + || 56 != 070 + || 64 != 0100 + || 72 != 0110 + || 80 != 0120 + || 9 != 0011 + || 17 != 0021 + || 25 != 0031 + || 33 != 0041 + || 41 != 0051 + || 49 != 0061 + || 57 != 0071 + || 65 != 0101 + || 73 != 0111 + || 81 != 0121 ){ + rc = rc+1; + if( pd0->flgd != 0 ) printf(s241er,1); + } + + /* A sequence of digits preceded by 0x or 0X (digit zero) + is taken to be a hexadecimal integer. The hexadecimal + digits include a or A through f or F with values 10 + through 15. */ + + if ( 0x00abcdef != 0xabcdef + || 0xabcdef != 0Xabcdef || 0Xabcdef != 0XAbcdef + || 0XAbcdef != 0XABcdef || 0XABcdef != 0XABCdef + || 0XABCdef != 0XABCDef || 0XABCDef != 0XABCDEf + || 0XABCDEf != 0XABCDEF || 0xABCDEF != 11259375 ){ + rc = rc+2; + if( pd0->flgd != 0 ) printf(s241er,2); + } + + /* A decimal constant whose value exceeds the largest signed + machine integer is taken to be long; an octal or hex con- + stant which exceeds the largest unsigned machine integer + is likewise taken to be long. */ +#if defined(REFERENCE) && defined(REFCC_SIZEOF_LONG_64BIT) +/*#warning "sizeof(long)!=4, skipping test"*/ +#else + if ( sizeof 010000000000 != sizeof(long) /* 2**30 */ + || sizeof 1073741824 != sizeof(long) /* ditto */ + || sizeof 0x40000000 != sizeof(long) ){ /* " */ + + rc = rc+4; + if( pd0->flgd != 0 ) printf(s241er,4); + } +#endif + /* A decimal, octal, or hexadecimal constant immediately followed + by l (letter ell) or L is a long constant. */ + + if ( sizeof 67l != sizeof(long) + || sizeof 67L != sizeof(long) + || sizeof 067l != sizeof(long) + || sizeof 067L != sizeof(long) + || sizeof 0X67l != sizeof(long) + || sizeof 0x67L != sizeof(long) ){ + rc = rc+8; + if( pd0 -> flgd != 0 ) printf(s241er,8); + } + + /* Finally, we test to see that decimal (d), octal (o), + and hexadecimal (x) constants representing the same values + agree among themselves, and with computed values, at spec- + ified points over an appropriate range. The points select- + ed here are those with the greatest potential for caus- + ing trouble, i.e., zero, 1-16, and values of 2**n and + 2**n - 1 where n is some multiple of 4 or 6. Unfortunately, + just what happens when a value is too big to fit in a + long is undefined; however, it would be nice if what + happened were at least consistent... */ + + for ( j=0; j<17; j++ ) g[j] = j; + for ( j=18; j<39; ) { + g[j] = pow2(g[j]); + g[j-1] = g[j] - 1; + j = j+2; + } + + d[0] = 0; o[0] = 00; x[0] = 0x0; + d[1] = 1; o[1] = 01; x[1] = 0x1; + d[2] = 2; o[2] = 02; x[2] = 0x2; + d[3] = 3; o[3] = 03; x[3] = 0x3; + d[4] = 4; o[4] = 04; x[4] = 0x4; + d[5] = 5; o[5] = 05; x[5] = 0x5; + d[6] = 6; o[6] = 06; x[6] = 0x6; + d[7] = 7; o[7] = 07; x[7] = 0x7; + d[8] = 8; o[8] = 010; x[8] = 0x8; + d[9] = 9; o[9] = 011; x[9] = 0x9; + d[10] = 10; o[10] = 012; x[10] = 0xa; + d[11] = 11; o[11] = 013; x[11] = 0xb; + d[12] = 12; o[12] = 014; x[12] = 0xc; + d[13] = 13; o[13] = 015; x[13] = 0xd; + d[14] = 14; o[14] = 016; x[14] = 0xe; + d[15] = 15; o[15] = 017; x[15] = 0xf; + d[16] = 16; o[16] = 020; x[16] = 0x10; + d[17] = 63; o[17] = 077; x[17] = 0x3f; + d[18] = 64; o[18] = 0100; x[18] = 0x40; + d[19] = 255; o[19] = 0377; x[19] = 0xff; + d[20] = 256; o[20] = 0400; x[20] = 0x100; + d[21] = 4095; o[21] = 07777; x[21] = 0xfff; + d[22] = 4096; o[22] = 010000; x[22] = 0x1000; + d[23] = 65535; o[23] = 0177777; x[23] = 0xffff; + d[24] = 65536; o[24] = 0200000; x[24] = 0x10000; + d[25] = 262143; o[25] = 0777777; x[25] = 0x3ffff; + d[26] = 262144; o[26] = 01000000; x[26] = 0x40000; + d[27] = 1048575; o[27] = 03777777; x[27] = 0xfffff; + d[28] = 1048576; o[28] = 04000000; x[28] = 0x100000; + d[29] = 16777215; o[29] = 077777777; x[29] = 0xffffff; + d[30] = 16777216; o[30] = 0100000000; x[30] = 0x1000000; + d[31] = 268435455; o[31] = 01777777777; x[31] = 0xfffffff; + d[32] = 268435456; o[32] = 02000000000; x[32] = 0x10000000; + d[33] = 1073741823; o[33] = 07777777777; x[33] = 0x3fffffff; + d[34] = 1073741824; o[34] = 010000000000; x[34] = 0x40000000; + d[35] = 4294967295; o[35] = 037777777777; x[35] = 0xffffffff; + d[36] = 4294967296; o[36] = 040000000000; x[36] = 0x100000000; + d[37] = 68719476735; o[37] = 0777777777777; x[37] = 0xfffffffff; + d[38] = 68719476736; o[38] = 01000000000000; x[38] = 0x1000000000; + + /* WHEW! */ + + for (j=0; j<39; j++){ + if ( g[j] != d[j] + || d[j] != o[j] + || o[j] != x[j]) { + if( pd0 -> flgm != 0 ) { +/* printf(s241er,16); save in case opinions change... */ + printf("Decimal and octal/hex constants sometimes give\n"); + printf(" different results when assigned to longs.\n"); + } +/* lrc = 1; save... */ + } + } + + if (lrc != 0) rc =16; + + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#define cq_sections 1 + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s241(pd0); + } +} + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq243.c b/test/val/cq243.c new file mode 100644 index 000000000..03b08b4d2 --- /dev/null +++ b/test/val/cq243.c @@ -0,0 +1,264 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 2.43: character constants + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +/********************************************************************************************* + 2.4.3 Character constants +**********************************************************************************************/ + +#ifndef NO_OLD_FUNC_DECL +zerofill(x) +char *x; +{ +#else +void zerofill(char *x) { +#endif + int j; + + for (j=0; j<256; j++) *x++ = 0; +} + +#ifndef NO_OLD_FUNC_DECL +sumof(x) +char *x; +{ +#else +int sumof(char *x) { +#endif + char *p; + int total, j; + + p = x; + total = 0; + + for(j=0; j<256; j++) total = total+ *p++; + return total; +} + +char chars[256]; + +#ifndef NO_OLD_FUNC_DECL +s243(pd0) +struct defs *pd0; +{ +#else +int s243(struct defs *pd0) { +#endif + static char s243er[] = "s243,er%d\n"; + static char qs243[8] = "s243 "; + char *ps, *pt; + int rc; +/* char chars[256]; */ + + rc = 0; + ps = qs243; + pt = pd0->rfs; + while(*pt++ = *ps++); + + /* One of the problems that arises when testing character constants + is that of definition: What, exactly, is the character set? + In order to guarantee a certain amount of machine independence, + the character set we will use here is the set of characters writ- + able as escape sequences in C, plus those characters used in writ- + ing C programs, i.e., + + letters: + ABCDEFGHIJKLMNOPQRSTUVWXYZ 26 + abcdefghijklmnopqrstuvwxyz 26 + numbers: + 0123456789 10 + special characters: + ~!"#%&()_=-^|{}[]+;*:<>,.?/ 27 + extra special characters: + newline \n + horizontal tab \t + backspace \b + carriage return \r + form feed \f + backslash \\ + single quote \' 7 + blank & NUL 2 + --- + 98 + + Any specific implementation of C may of course support additional + characters. */ + + /* Since the value of a character constant is the numerical value + of the character in the machine's character set, there should + be a one-to-one correspondence between characters and values. */ + + zerofill(chars); + + chars['a'] = 1; chars['A'] = 1; chars['~'] = 1; chars['0'] = 1; + chars['b'] = 1; chars['B'] = 1; chars['!'] = 1; chars['1'] = 1; + chars['c'] = 1; chars['C'] = 1; chars['"'] = 1; chars['2'] = 1; + chars['d'] = 1; chars['D'] = 1; chars['#'] = 1; chars['3'] = 1; + chars['e'] = 1; chars['E'] = 1; chars['%'] = 1; chars['4'] = 1; + chars['f'] = 1; chars['F'] = 1; chars['&'] = 1; chars['5'] = 1; + chars['g'] = 1; chars['G'] = 1; chars['('] = 1; chars['6'] = 1; + chars['h'] = 1; chars['H'] = 1; chars[')'] = 1; chars['7'] = 1; + chars['i'] = 1; chars['I'] = 1; chars['_'] = 1; chars['8'] = 1; + chars['j'] = 1; chars['J'] = 1; chars['='] = 1; chars['9'] = 1; + chars['k'] = 1; chars['K'] = 1; chars['-'] = 1; + chars['l'] = 1; chars['L'] = 1; chars['^'] = 1; + chars['m'] = 1; chars['M'] = 1; chars['|'] = 1; chars['\n'] = 1; + chars['n'] = 1; chars['N'] = 1; chars['\t'] = 1; + chars['o'] = 1; chars['O'] = 1; chars['{'] = 1; chars['\b'] = 1; + chars['p'] = 1; chars['P'] = 1; chars['}'] = 1; chars['\r'] = 1; + chars['q'] = 1; chars['Q'] = 1; chars['['] = 1; chars['\f'] = 1; + chars['r'] = 1; chars['R'] = 1; chars[']'] = 1; + chars['s'] = 1; chars['S'] = 1; chars['+'] = 1; chars['\\'] = 1; + chars['t'] = 1; chars['T'] = 1; chars[';'] = 1; chars['\''] = 1; + chars['u'] = 1; chars['U'] = 1; chars['*'] = 1; + chars['v'] = 1; chars['V'] = 1; chars[':'] = 1; chars['\0'] = 1; + chars['w'] = 1; chars['W'] = 1; chars['<'] = 1; chars[' '] = 1; + chars['x'] = 1; chars['X'] = 1; chars['>'] = 1; + chars['y'] = 1; chars['Y'] = 1; chars[','] = 1; + chars['z'] = 1; chars['Z'] = 1; chars['.'] = 1; + chars['?'] = 1; + chars['/'] = 1; + + if(sumof(chars) != 98){ + rc = rc+1; + if(pd0->flgd != 0) printf(s243er,1); + } + + #ifndef NO_BACKSLASH_CHARCODE + + /* Finally, the escape \ddd consists of the backslash followed + by 1, 2, or 3 octal digits which are taken to specify the + desired character. */ + +/* + this test is non portable and inaccurate, we replace it + by a more failproof version + + if( + '\0' != 0 || + '\01' != 1 || + '\02' != 2 || + '\03' != 3 || + '\04' != 4 || + '\05' != 5 || + '\06' != 6 || + '\07' != 7 || + '\10' != 8 || + '\17' != 15 || + '\20' != 16 || + '\77' != 63 || + '\100' != 64 || + '\177' != 127 + ) +*/ + if( + ('0' != '\60') || + ('9' != '\71') || + ('A' != '\101') || + ('Z' != '\132') || + ('a' != '\141') || + ('z' != '\172') + ) + + { + rc = rc+8; + if(pd0->flgd != 0) + { + printf(s243er,8); + } + } + + #endif + + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#define cq_sections 1 + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s243(pd0); + } +} + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq244.c b/test/val/cq244.c new file mode 100644 index 000000000..52695bfb6 --- /dev/null +++ b/test/val/cq244.c @@ -0,0 +1,159 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 2.44: floating point constants + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#ifndef NO_OLD_FUNC_DECL +s244(pd0) +struct defs *pd0; +{ +#else +s244(struct defs *pd0) { +#endif + + #ifndef NO_FLOATS + double a[8]; + + int rc, lrc, j; + static char s244er[] = "s244,er%d\n"; + static char qs244[8] = "s244 "; + char *ps, *pt; + + ps = qs244; + pt = pd0->rfs; + while(*pt++ = *ps++); + rc = 0; + lrc = 0; + + /* Unfortunately, there's not a lot we can do with floating constants. + We can check to see that the various representations can be com- + piled, that the conversion is such that they yield the same hard- + ware representations in all cases, and that all representations + thus checked are double precision. */ + + a[0] = .1250E+04; + a[1] = 1.250E3; + a[2] = 12.50E02; + a[3] = 125.0e+1; + a[4] = 1250e00; + a[5] = 12500.e-01; + a[6] = 125000e-2; + a[7] = 1250.; + + lrc = 0; + for (j=0; j<7; j++) if(a[j] != a[j+1]) lrc = 1; + + if(lrc != 0) { + if(pd0->flgd != 0) printf(s244er,1); + rc = rc+1; + } + + if ( (sizeof .1250E+04 ) != sizeof(double) + || (sizeof 1.250E3 ) != sizeof(double) + || (sizeof 12.50E02 ) != sizeof(double) + || (sizeof 1.250e+1 ) != sizeof(double) + || (sizeof 1250e00 ) != sizeof(double) + || (sizeof 12500.e-01) != sizeof(double) + || (sizeof 125000e-2 ) != sizeof(double) + || (sizeof 1250. ) != sizeof(double)){ + if(pd0->flgd != 0) printf(s244er,2); + rc = rc+2; + } + + return rc; + + #else + + return 0; + + #endif +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#define cq_sections 1 + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s244(pd0); + } +} + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq25.c b/test/val/cq25.c new file mode 100644 index 000000000..d4a0c4a90 --- /dev/null +++ b/test/val/cq25.c @@ -0,0 +1,171 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 2.5: strings + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#ifndef NO_OLD_FUNC_DECL +s25(pd0) +struct defs *pd0; +{ +#else +int s25(struct defs *pd0) { +#endif + char *s, *s2; + int rc, lrc, j; + static char s25er[] = "s25,er%d\n"; + static char qs25[8] = "s25 "; + char *ps, *pt; + + ps = qs25; + pt = pd0->rfs; + while(*pt++ = *ps++); + rc = 0; + + /* A string is a sequence of characters surrounded by double + quotes, as in "...". */ + + s = "..."; + + /* A string has type "array of characters" and storage class + static and is initialized with the given characters. */ + + if ( s[0] != s[1] || s[1] != s[2] + || s[2] != '.' ) { + rc = rc+1; + if(pd0->flgd != 0) printf(s25er,1); + } + + /* The compiler places a null byte \0 at the end of each string + so the program which scans the string can find its end. */ + + if( s[3] != '\0' ){ + rc = rc+4; + if(pd0->flgd != 0) printf(s25er,4); + } + + /* In a string, the double quote character " must be preceded + by a \. */ + + if( ".\"."[1] != '"' ){ + rc = rc+8; + if(pd0->flgd != 0) printf(s25er,8); + } + + /* In addition, the same escapes described for character constants + may be used. */ + + s = "\n\t\b\r\f\\\'"; + + if( s[0] != '\n' + || s[1] != '\t' + || s[2] != '\b' + || s[3] != '\r' + || s[4] != '\f' + || s[5] != '\\' + || s[6] != '\'' ){ + rc = rc+16; + if( pd0->flgd != 0) printf(s25er,16); + } + + /* Finally, a \ and an immediately following newline are ignored */ + + s2 = "queep!"; + s = "queep!"; + + lrc = 0; + for (j=0; j<sizeof "queep!"; j++) if(s[j] != s2[j]) lrc = 1; + if (lrc != 0){ + rc = rc+32; + if(pd0->flgd != 0) printf(s25er,32); + } + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#define cq_sections 1 + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s25(pd0); + } +} + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq26.c b/test/val/cq26.c new file mode 100644 index 000000000..42527e80f --- /dev/null +++ b/test/val/cq26.c @@ -0,0 +1,217 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 2.6: Hardware Characteristics + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +#ifndef CQ26_INCLUDED +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#endif + +/* + section s26, which pokes around at the hardware + trying to figure out the characteristics of the machine that + it is running on, saves information that is subsequently + used by sections s626, s72, and s757. If this program is + to be broken up into smallish pieces, say for running on + a microcomputer, take care to see that s26 is called before + calling any of the latter three sections. +*/ + +/* + 2.6 Hardware Characteristics +*/ + +#ifndef NO_OLD_FUNC_DECL +s26(pd0) +struct defs *pd0; +{ +#else +s26(struct defs *pd0) { +#endif + static char qs26[8] = "s26 "; + char *ps, *pt; + char c0, c1; + #ifndef NO_FLOATS + float temp, one, delta; + double tempd, oned; + #endif + static char s[] = "%3d bits in %ss.\n"; + static char s2[] = "%e is the least number that can be added to 1. (%s).\n"; + + ps = qs26; + pt = pd0->rfs; + + while(*pt++ = *ps++); + + /* Here, we shake the machinery a little to see what falls + out. First, we find out how many bits are in a char. */ + + pd0->cbits = 0; + c0 = 0; + c1 = 1; + + while(c0 != c1) { + c1 = c1<<1; + pd0->cbits = pd0->cbits+1; + } + /* That information lets us determine the size of everything else. */ + + pd0->ibits = pd0->cbits * sizeof(int); + pd0->sbits = pd0->cbits * sizeof(short); + pd0->lbits = pd0->cbits * sizeof(long); + pd0->ubits = pd0->cbits * sizeof(unsigned); + #ifndef NO_FLOATS + pd0->fbits = pd0->cbits * sizeof(float); + pd0->dbits = pd0->cbits * sizeof(double); + #endif + + /* We have now almost reconstructed the table in section 2.6, the + exception being the range of the floating point hardware. + Now there are just so many ways to conjure up a floating point + representation system that it's damned near impossible to guess + what's going on by writing a program to interpret bit patterns. + Further, the information isn't all that useful, if we consider + the fact that machines that won't handle numbers between 10**30 + and 10**-30 are very hard to find, and that people playing with + numbers outside that range have a lot more to worry about than + just the capacity of the characteristic. + + A much more useful measure is the precision, which can be ex- + pressed in terms of the smallest number that can be added to + 1. without loss of significance. We calculate that here, for + float and double. */ + +#ifndef NO_FLOATS + one = 1.; + delta = 1.; + temp = 0.; + while(temp != one) { + temp = one+delta; + delta = delta/2.; + } + pd0->fprec = delta * 4.; + oned = 1.; + delta = 1.; + tempd = 0.; + while(tempd != oned) { + tempd = oned+delta; + delta = delta/2.; + } + pd0->dprec = delta * 4.; +#endif + + /* Now, if anyone's interested, we publish the results. */ + +#ifndef CQ26_INCLUDED + if(pd0->flgm != 0) { + printf(s,pd0->cbits,"char"); + printf(s,pd0->ibits,"int"); + printf(s,pd0->sbits,"short"); + printf(s,pd0->lbits,"long"); + printf(s,pd0->ubits,"unsigned"); + printf(s,pd0->fbits,"float"); + printf(s,pd0->dbits,"double"); + #ifndef NO_FLOATS + printf(s2,pd0->fprec,"float"); + printf(s2,pd0->dprec,"double"); + #else + printf("NO_FLOATS\n"); + #endif + } +#endif + /* Since we are only exploring and perhaps reporting, but not + testing any features, we cannot return an error code. */ + + return 0; +} + +#ifndef CQ26_INCLUDED + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s26(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} +#endif diff --git a/test/val/cq4.c b/test/val/cq4.c new file mode 100644 index 000000000..94f4d5fb7 --- /dev/null +++ b/test/val/cq4.c @@ -0,0 +1,242 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 4: what's in a name? + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +/*#include "cq26.c"*/ /* hardware check */ + +int extvar; + +#ifdef NO_IMPLICIT_FUNC_PROTOTYPES +int s4(struct defs *pd0); +int svtest(int n); +zero(); +testev(); +setev(); +#endif + +#ifndef NO_OLD_FUNC_DECL +s4(pd0) /* 4. What's in a name? */ +struct defs *pd0; +{ +#else +int s4(struct defs *pd0) { +#endif + static char s4er[] = "s4,er%d\n"; + static char qs4[8] = "s4 "; + char *ps, *pt; + int j, rc; + + short sint; /* short integer, for size test */ + int pint; /* plain */ + long lint; /* long */ + unsigned target; + unsigned int mask; + + rc = 0; + ps = qs4; + pt = pd0->rfs; + + while(*pt++ = *ps++); + +/* There are four declarable storage classes: automatic, +static, external, and register. Automatic variables have +been dealt with extensively thus far, and will not be specif- +ically treated in this section. Register variables are treated +in section s81. + + Static variables are local to a block, but retain their +values upon reentry to a block, even after control has left +the block. */ + + for (j=0; j<3; j++) + if(svtest(j) != zero()){ + rc = 1; + if(pd0->flgd != 0) printf(s4er,1); + } + ; + +/* External variables exist and retain their values throughout +the execution of the entire program, and may be used for comm- +unication between functions, even separately compiled functions. + */ + + setev(); + if(testev() != 0){ + rc=rc+2; + if(pd0->flgd != 0) printf(s4er,2); + } +/* + Characters have been tested elsewhere (in s243). + + Up to three sizes of integer, declared short int, int, and +long int, are available. Longer integers provide no less storage +than shorter ones, but implementation may make either short +integers, or long integers, or both, equivalent to plain +integers. + */ + + if(sizeof lint < sizeof pint || sizeof pint < sizeof sint){ + rc = rc+4; + if(pd0->flgd != 0) printf(s4er,4); + } + +/* Unsigned integers, declared unsigned, obey the laws of +arithmetic modulo 2**n, where n is the number of bits in the +implementation */ + + target = ~0U; + mask = 1; + + for(j=0; j<(sizeof target)*pd0->cbits; j++){ + mask = mask⌖ + target = target>>1; + } + + if(mask != 1 || target != 0){ + rc = rc+8; + if(pd0->flgd != 0) printf(s4er,8); + } + + return rc; +} + +#ifndef NO_OLD_FUNC_DECL +svtest(n) +int n; +{ +#else +int svtest(int n) { +#endif + + static k; + int rc; + switch (n) { + case 0: k = 1978; + rc = 0; + break; + + case 1: if(k != 1978) rc = 1; + else{ + k = 1929; + rc = 0; + } + break; + + case 2: if(k != 1929) rc = 1; + else rc = 0; + break; + } + return rc; +} +zero(){ /* Returns a value of zero, possibly */ + static k; /* with side effects, as it's called */ + int rc; /* alternately with svtest, above, */ + k = 2; /* and has the same internal storage */ + rc = 0; /* requirements. */ + return rc; +} +testev(){ + if(extvar != 1066) return 1; + else return 0; +} + +/* Sets an external variable. Used */ +/* by s4, and should be compiled */ +/* separately from s4. */ + +setev(){ +#ifndef NO_SLOPPY_EXTERN + extern int extvar; +#endif + extvar = 1066; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s4(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq61.c b/test/val/cq61.c new file mode 100644 index 000000000..f40b21d61 --- /dev/null +++ b/test/val/cq61.c @@ -0,0 +1,186 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 6.1: characters and integers + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +/*#include "cq26.c"*/ /* hardware check */ + +int extvar; + +#ifndef NO_OLD_FUNC_DECL +s61(pd0) /* Characters and integers */ +struct defs *pd0; +{ +#else +int s61(struct defs *pd0){ +#endif + static char s61er[] = "s61,er%d\n"; + static char s61ok[] = "s61,ok%d\n"; + static char qs61[8] = "s61 "; + short from, shortint; + long int to, longint; + int rc, lrc; + int j; + char fromc, charint; + char *wd, *pc[6]; + + static char upper_alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + static char lower_alpha[] = "abcdefghijklmnopqrstuvwxyz"; + static char numbers[] = "0123456789"; + static char special_characters[] = "~!\"#%&()_=-^|{}[]+;*:<>,.?/"; + static char extra_special_characters[] = "\n\t\b\r\f\\\'"; + static char blank_and_NUL[] = " \0"; + + char *ps, *pt; + ps = qs61; + pt = pd0->rfs; + rc = 0; + + printf(s61ok,0); + + while (*pt++ = *ps++); + +/* A character or a short integer may be used wherever +an integer may be used. In all cases, the value is converted +to integer. This principle is extensively used throughout this +program, and will not be explicitly tested here. */ + +/* Conversion of a shorter integer to a longer always +involves sign extension. */ + + from = -19; + to = from; + + if(to != -19){ + rc = rc+1; + if(pd0->flgd != 0) printf(s61er,1); + } + else if(pd0->flgd != 0) printf(s61ok,1); + +/* It is guaranteed that a member of the standard char- +acter set is nonnegative. */ + + pc[0] = upper_alpha; + pc[1] = lower_alpha; + pc[2] = numbers; + pc[3] = special_characters; + pc[4] = extra_special_characters; + pc[5] = blank_and_NUL; + + lrc = 0; + for (j=0; j<6; j++) + while(*pc[j]) if(*pc[j]++ < 0) lrc =1; + + if(lrc != 0){ + rc=rc+2; + if(pd0->flgd != 0) printf(s61er,2); + } + else if(pd0->flgd != 0) printf(s61ok,2); + +/* When a longer integer is converted to a shorter or +to a char, it is truncated on the left; excess bits are +simply discarded. */ + + longint = 1048579; /* =2**20+3 */ + shortint = longint; + charint = longint; + + if((shortint != longint && shortint != 3) || + (charint != longint && charint != 3)) { + rc = rc+8; + if(pd0->flgd != 0) printf(s61er,8); + } + else if(pd0->flgd != 0) printf(s61ok,8); + + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + /*case 0: return s26(pd0);*/ + case 0: return s61(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq626.c b/test/val/cq626.c new file mode 100644 index 000000000..7fab43f53 --- /dev/null +++ b/test/val/cq626.c @@ -0,0 +1,337 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 6.2: Float and double, 6.3 Floating and integral, 6.4 Pointers and integers, 6.5 Unsigned, 6.6 Arithmetic conversions + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#define CQ26_INCLUDED +/* + section s26, which pokes around at the hardware + trying to figure out the characteristics of the machine that + it is running on, saves information that is subsequently + used by sections s626, s72, and s757. If this program is + to be broken up into smallish pieces, say for running on + a microcomputer, take care to see that s26 is called before + calling any of the latter three sections. +*/ + +/* + 2.6 Hardware Characteristics +*/ + +#ifndef NO_OLD_FUNC_DECL +s26(pd0) +struct defs *pd0; +{ +#else +s26(struct defs *pd0) { +#endif + static char qs26[8] = "s26 "; + char *ps, *pt; + char c0, c1; + #ifndef NO_FLOATS + float temp, one, delta; + double tempd, oned; + #endif + static char s[] = "%3d bits in %ss.\n"; + static char s2[] = "%e is the least number that can be added to 1. (%s).\n"; + + ps = qs26; + pt = pd0->rfs; + + while(*pt++ = *ps++); + + /* Here, we shake the machinery a little to see what falls + out. First, we find out how many bits are in a char. */ + + pd0->cbits = 0; + c0 = 0; + c1 = 1; + + while(c0 != c1) { + c1 = c1<<1; + pd0->cbits = pd0->cbits+1; + } + /* That information lets us determine the size of everything else. */ + + pd0->ibits = pd0->cbits * sizeof(int); + pd0->sbits = pd0->cbits * sizeof(short); + pd0->lbits = pd0->cbits * sizeof(long); + pd0->ubits = pd0->cbits * sizeof(unsigned); + #ifndef NO_FLOATS + pd0->fbits = pd0->cbits * sizeof(float); + pd0->dbits = pd0->cbits * sizeof(double); + #endif + + /* We have now almost reconstructed the table in section 2.6, the + exception being the range of the floating point hardware. + Now there are just so many ways to conjure up a floating point + representation system that it's damned near impossible to guess + what's going on by writing a program to interpret bit patterns. + Further, the information isn't all that useful, if we consider + the fact that machines that won't handle numbers between 10**30 + and 10**-30 are very hard to find, and that people playing with + numbers outside that range have a lot more to worry about than + just the capacity of the characteristic. + + A much more useful measure is the precision, which can be ex- + pressed in terms of the smallest number that can be added to + 1. without loss of significance. We calculate that here, for + float and double. */ + +#ifndef NO_FLOATS + one = 1.; + delta = 1.; + temp = 0.; + while(temp != one) { + temp = one+delta; + delta = delta/2.; + } + pd0->fprec = delta * 4.; + oned = 1.; + delta = 1.; + tempd = 0.; + while(tempd != oned) { + tempd = oned+delta; + delta = delta/2.; + } + pd0->dprec = delta * 4.; +#endif + + /* Now, if anyone's interested, we publish the results. */ + +#ifndef CQ26_INCLUDED + if(pd0->flgm != 0) { + printf(s,pd0->cbits,"char"); + printf(s,pd0->ibits,"int"); + printf(s,pd0->sbits,"short"); + printf(s,pd0->lbits,"long"); + printf(s,pd0->ubits,"unsigned"); + printf(s,pd0->fbits,"float"); + printf(s,pd0->dbits,"double"); + #ifndef NO_FLOATS + printf(s2,pd0->fprec,"float"); + printf(s2,pd0->dprec,"double"); + #else + printf("NO_FLOATS\n"); + #endif + } +#endif + /* Since we are only exploring and perhaps reporting, but not + testing any features, we cannot return an error code. */ + + return 0; +} + +int extvar; + +#ifndef NO_OLD_FUNC_DECL +s626(pd0) /* 6.2 Float and double */ + /* 6.3 Floating and integral */ + /* 6.4 Pointers and integers */ + /* 6.5 Unsigned */ + /* 6.6 Arithmetic conversions */ +struct defs *pd0; +{ +#else +int s626(struct defs *pd0){ +#endif + static char s626er[] = "s626,er%d\n"; + static char qs626[8] = "s626 "; + int rc; + char *ps, *pt; + #ifndef NO_FLOATS + float eps, f1, f2, f3, f4, f; + #endif + long lint1, lint2, l, ls; + char c, t[28], t0; + short s; + int is, i, j; + unsigned u, us; + #ifndef NO_FLOATS + double d, ds; + #endif + ps = qs626; + pt = pd0->rfs; + rc = 0; + while (*pt++ = *ps++); + + #ifndef NO_FLOATS + + /* Conversions of integral values to floating type are + well-behaved. */ + + f1 = 1.; + lint1 = 1.; + lint2 = 1.; + + for(j=0;j<pd0->lbits-2;j++){ + f1 = f1*2; + lint2 = (lint2<<1)|lint1; + } + f2 = lint2; + f1 = (f1-f2)/f1; + if(f1>2.*pd0->fprec){ + rc = rc+2; + if(pd0->flgd != 0) printf(s626er,2); + } + + /* Pointer-integer combinations are discussed in s74, + "Additive operators". The unsigned-int combination + appears below. */ + + c = 125; + s = 125; + i = 125; is = 15625; + u = 125; us = 15625; + l = 125; ls = 15625; + f = 125.; + d = 125.; ds = 15625.; + + for(j=0;j<28;j++) t[j] = 0; + + if(c*c != is) t[ 0] = 1; + if(s*c != is) t[ 1] = 1; + if(s*s != is) t[ 2] = 1; + if(i*c != is) t[ 3] = 1; + if(i*s != is) t[ 4] = 1; + if(i*i != is) t[ 5] = 1; + if(u*c != us) t[ 6] = 1; + if(u*s != us) t[ 7] = 1; + if(u*i != us) t[ 8] = 1; + if(u*u != us) t[ 9] = 1; + if(l*c != ls) t[10] = 1; + if(l*s != ls) t[11] = 1; + if(l*i != ls) t[12] = 1; + if(l*u != us) t[13] = 1; + if(l*l != ls) t[14] = 1; + if(f*c != ds) t[15] = 1; + if(f*s != ds) t[16] = 1; + if(f*i != ds) t[17] = 1; + if(f*u != ds) t[18] = 1; + if(f*l != ds) t[19] = 1; + if(f*f != ds) t[20] = 1; + if(d*c != ds) t[21] = 1; + if(d*s != ds) t[22] = 1; + if(d*i != ds) t[23] = 1; + if(d*u != ds) t[24] = 1; + if(d*l != ds) t[25] = 1; + if(d*f != ds) t[26] = 1; + if(d*d != ds) t[27] = 1; + + t0 = 0; + for(j=0; j<28; j++) t0 = t0+t[j]; + + if(t0 != 0){ + rc = rc+4; + if(pd0->flgd != 0){ + printf(s626er,4); + printf(" key="); + for(j=0;j<28;j++) printf("%d",t[j]); + printf("\n"); + } + } + + #endif + + /* When an unsigned integer is converted to long, + the value of the result is the same numerically + as that of the unsigned integer. */ + + l = (unsigned)0100000; + if((long)l > (unsigned)0100000){ + rc = rc+8; + if(pd0->flgd != 0) printf(s626er,8); + } + + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s26(pd0); + case 1: return s626(pd0); + } +} + +#define cq_sections 2 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq71.c b/test/val/cq71.c new file mode 100644 index 000000000..342b9809a --- /dev/null +++ b/test/val/cq71.c @@ -0,0 +1,240 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 7.1: primary expressions + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +/*include "cq26.c"*/ /* hardware check */ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +int extvar; + +#ifndef NO_OLD_FUNC_DECL +s71(pd0) /* 7.1 Primary expressions */ +struct defs *pd0; +{ +#else +int s71(struct defs *pd0){ +#endif + static char s71er[] = "s71,er%d\n"; + static char qs71[8] = "s71 "; + int rc; + char *ps, *pt; + static char q = 'q'; +#ifndef NO_SLOPPY_EXTERN + int x[10], McCarthy(), clobber(), a, b, *p; +#else + int x[10], a, b, *p; +#endif + ps = qs71; + pt = pd0->rfs; + rc = 0; + while (*pt++ = *ps++); + +/* Testing of expressions and operators is quite complicated, + because (a) problems are apt to surface in queer combinations + of operators and operands, rather than in isolation, + and (b) the number of expressions needed to provoke a case + of improper behaviour may be quite large. Hence, we take the + following approach: for this section, and for subsequent + sections through 7.15, we will check the primitive operations + in isolation, thus verifying that the primitives work, + after a fashion. The job of testing combinations, we will + leave to a separate, machine-generated program, to be included + in the C test package at some later date. + */ + +/* A string is a primary expression. The identifier points to + the first character of a string. + */ + + if(*"queep" != q){ + rc = rc+1; + if(pd0->flgd != 0) printf(s71er,1); + } +/* A parenthesized expression is a primary expression whose + type and value are the same as those of the unadorned + expression. + */ + if((2+3) != 2+3) { + rc = rc+2; + if(pd0->flgd != 0) printf(s71er,2); + } + +/* A primary expression followed by an expression in square + brackets is a primary expression. The intuitive meaning is + that of a subscript. The expression E1[E2] is identical + (by definition) to *((E1)+(E2)). + */ + + x[5] = 1942; + if(x[5] != 1942 || x[5] != *((x)+(5))){ + rc = rc+4; + if(pd0->flgd != 0) printf(s71er,4); + } + +/* If the various flavors of function calls didn't work, we + would never have gotten this far; however, we do need to + show that functions can be recursive... + */ + + if ( McCarthy(-5) != 91){ + rc = rc+8; + if(pd0->flgd != 0) printf(s71er,8); + } + +/* and that argument passing is strictly by value. */ + + a = 2; + b = 3; + p = &b; + + clobber(a,p); + + if(a != 2 || b != 2){ + rc = rc+16; + if(pd0->flgd != 0) printf(s71er,16); + } + +/* Finally, structures and unions are addressed thusly: */ + + #ifndef NO_FLOATS + + if(pd0->dprec != (*pd0).dprec){ + rc = rc+32; + if(pd0->flgd != 0) printf(s71er,32); + } + + #endif + + return rc; +} +#ifndef NO_OLD_FUNC_DECL +McCarthy(x) +int x; +{ +#else +int McCarthy(int x){ +#endif + if(x>100) return x-10; + else return McCarthy( McCarthy(x+11)); +} + +#ifndef NO_OLD_FUNC_DECL +clobber(x,y) +int x,*y; +#else +int clobber(int x,int *y) +#endif + +/* +#ifndef NO_OLD_FUNC_DECL +clobber(x,y) +int x, +#ifdef NO_TYPELESS_INT_PTR +int +#endif +*y; +{ +#else +int clobber(int x, +#ifdef NO_TYPELESS_INT_PTR +int +#endif +*y +){ +#endif +*/ + +{ + x = 3; + *y = 2; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + /*case 0: return s26(pd0);*/ + case 0: return s71(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq714.c b/test/val/cq714.c new file mode 100644 index 000000000..1d36b18ab --- /dev/null +++ b/test/val/cq714.c @@ -0,0 +1,1795 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 7.14: assignment operators + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#ifndef NO_OLD_FUNC_DECL +s714(pd0) /* 7.14 Assignment operators */ +struct defs *pd0; +{ +#else +int s714(struct defs *pd0){ +#endif + static char f[] = "Local error %d.\n"; + static char s714er[] = "s714,er%d\n"; + static char qs714[8] = "s714 "; + register int prlc, lrc; + int rc; + char cl, cr; + short sl, sr; + int il, ir; + long ll, lr; + unsigned ul, ur; + #ifndef NO_FLOATS + float fl, fr; + double dl, dr; + #else + signed fl, fr; + signed dl, dr; + #endif + char *ps, *pt; + ps = qs714; + pt = pd0->rfs; + rc = 0; + lrc = 0; + prlc = pd0->flgl; + while (*pt++ = *ps++); + + /* This section tests the assignment operators. + + It is an exhaustive test of all assignment statements + of the form: + + vl op vr + + where vl and vr are variables from the set + {char,short,int,long,unsigned,float,double} and op is + one of the assignment operators. There are 395 such + statements. + + The initial values for the variables have been chosen + so that both the initial values and the results will + "fit" in just about any implementation, and that the re- + sults will be such that they test for the proper form- + ation of composite operators, rather than checking for + the valid operation of those operators' components. + For example, in checking >>=, we want to verify that + a right shift and a move take place, rather than + whether or not there may be some peculiarities about + the right shift. Such tests have been made previously, + and to repeat them here would be to throw out a red + herring. + + The table below lists the operators, assignment targets, + initial values for left and right operands, and the + expected values of the results. + + = += -= *= /= %= >>= <<= &= ^= |= +char 2 7 3 10 2 1 1 20 8 6 14 +short 2 7 3 10 2 1 1 20 8 6 14 +int 2 7 3 10 2 1 1 20 8 6 14 +long 2 7 3 10 2 1 1 20 8 6 14 +unsigned 2 7 3 10 2 1 1 20 8 6 14 +float 2 7 3 10 2.5 | | +double 2 7 3 10 2.5 | | + | | +initial (5,2) | (5,2) | (12,10) + + The following machine-generated program reflects the + tests described in the table. + */ + + cl = 5; cr = 2; + cl = cr; + if(cl != 2){ + lrc = 1; + if(prlc) printf(f,lrc); + } + cl = 5; sr = 2; + cl = sr; + if(cl != 2){ + lrc = 2; + if(prlc) printf(f,lrc); + } + cl = 5; ir = 2; + cl = ir; + if(cl != 2){ + lrc = 3; + if(prlc) printf(f,lrc); + } + cl = 5; lr = 2; + cl = lr; + if(cl != 2){ + lrc = 4; + if(prlc) printf(f,lrc); + } + cl = 5; ur = 2; + cl = ur; + if(cl != 2){ + lrc = 5; + if(prlc) printf(f,lrc); + } + cl = 5; fr = 2; + cl = fr; + if(cl != 2){ + lrc = 6; + if(prlc) printf(f,lrc); + } + cl = 5; dr = 2; + cl = dr; + if(cl != 2){ + lrc = 7; + if(prlc) printf(f,lrc); + } + sl = 5; cr = 2; + sl = cr; + if(sl != 2){ + lrc = 8; + if(prlc) printf(f,lrc); + } + sl = 5; sr = 2; + sl = sr; + if(sl != 2){ + lrc = 9; + if(prlc) printf(f,lrc); + } + sl = 5; ir = 2; + sl = ir; + if(sl != 2){ + lrc = 10; + if(prlc) printf(f,lrc); + } + sl = 5; lr = 2; + sl = lr; + if(sl != 2){ + lrc = 11; + if(prlc) printf(f,lrc); + } + sl = 5; ur = 2; + sl = ur; + if(sl != 2){ + lrc = 12; + if(prlc) printf(f,lrc); + } + sl = 5; fr = 2; + sl = fr; + if(sl != 2){ + lrc = 13; + if(prlc) printf(f,lrc); + } + sl = 5; dr = 2; + sl = dr; + if(sl != 2){ + lrc = 14; + if(prlc) printf(f,lrc); + } + il = 5; cr = 2; + il = cr; + if(il != 2){ + lrc = 15; + if(prlc) printf(f,lrc); + } + il = 5; sr = 2; + il = sr; + if(il != 2){ + lrc = 16; + if(prlc) printf(f,lrc); + } + il = 5; ir = 2; + il = ir; + if(il != 2){ + lrc = 17; + if(prlc) printf(f,lrc); + } + il = 5; lr = 2; + il = lr; + if(il != 2){ + lrc = 18; + if(prlc) printf(f,lrc); + } + il = 5; ur = 2; + il = ur; + if(il != 2){ + lrc = 19; + if(prlc) printf(f,lrc); + } + il = 5; fr = 2; + il = fr; + if(il != 2){ + lrc = 20; + if(prlc) printf(f,lrc); + } + il = 5; dr = 2; + il = dr; + if(il != 2){ + lrc = 21; + if(prlc) printf(f,lrc); + } + ll = 5; cr = 2; + ll = cr; + if(ll != 2){ + lrc = 22; + if(prlc) printf(f,lrc); + } + ll = 5; sr = 2; + ll = sr; + if(ll != 2){ + lrc = 23; + if(prlc) printf(f,lrc); + } + ll = 5; ir = 2; + ll = ir; + if(ll != 2){ + lrc = 24; + if(prlc) printf(f,lrc); + } + ll = 5; lr = 2; + ll = lr; + if(ll != 2){ + lrc = 25; + if(prlc) printf(f,lrc); + } + ll = 5; ur = 2; + ll = ur; + if(ll != 2){ + lrc = 26; + if(prlc) printf(f,lrc); + } + ll = 5; fr = 2; + ll = fr; + if(ll != 2){ + lrc = 27; + if(prlc) printf(f,lrc); + } + ll = 5; dr = 2; + ll = dr; + if(ll != 2){ + lrc = 28; + if(prlc) printf(f,lrc); + } + ul = 5; cr = 2; + ul = cr; + if(ul != 2){ + lrc = 29; + if(prlc) printf(f,lrc); + } + ul = 5; sr = 2; + ul = sr; + if(ul != 2){ + lrc = 30; + if(prlc) printf(f,lrc); + } + ul = 5; ir = 2; + ul = ir; + if(ul != 2){ + lrc = 31; + if(prlc) printf(f,lrc); + } + ul = 5; lr = 2; + ul = lr; + if(ul != 2){ + lrc = 32; + if(prlc) printf(f,lrc); + } + ul = 5; ur = 2; + ul = ur; + if(ul != 2){ + lrc = 33; + if(prlc) printf(f,lrc); + } + ul = 5; fr = 2; + ul = fr; + if(ul != 2){ + lrc = 34; + if(prlc) printf(f,lrc); + } + ul = 5; dr = 2; + ul = dr; + if(ul != 2){ + lrc = 35; + if(prlc) printf(f,lrc); + } + fl = 5; cr = 2; + fl = cr; + if(fl != 2){ + lrc = 36; + if(prlc) printf(f,lrc); + } + fl = 5; sr = 2; + fl = sr; + if(fl != 2){ + lrc = 37; + if(prlc) printf(f,lrc); + } + fl = 5; ir = 2; + fl = ir; + if(fl != 2){ + lrc = 38; + if(prlc) printf(f,lrc); + } + fl = 5; lr = 2; + fl = lr; + if(fl != 2){ + lrc = 39; + if(prlc) printf(f,lrc); + } + fl = 5; ur = 2; + fl = ur; + if(fl != 2){ + lrc = 40; + if(prlc) printf(f,lrc); + } + fl = 5; fr = 2; + fl = fr; + if(fl != 2){ + lrc = 41; + if(prlc) printf(f,lrc); + } + fl = 5; dr = 2; + fl = dr; + if(fl != 2){ + lrc = 42; + if(prlc) printf(f,lrc); + } + dl = 5; cr = 2; + dl = cr; + if(dl != 2){ + lrc = 43; + if(prlc) printf(f,lrc); + } + dl = 5; sr = 2; + dl = sr; + if(dl != 2){ + lrc = 44; + if(prlc) printf(f,lrc); + } + dl = 5; ir = 2; + dl = ir; + if(dl != 2){ + lrc = 45; + if(prlc) printf(f,lrc); + } + dl = 5; lr = 2; + dl = lr; + if(dl != 2){ + lrc = 46; + if(prlc) printf(f,lrc); + } + dl = 5; ur = 2; + dl = ur; + if(dl != 2){ + lrc = 47; + if(prlc) printf(f,lrc); + } + dl = 5; fr = 2; + dl = fr; + if(dl != 2){ + lrc = 48; + if(prlc) printf(f,lrc); + } + dl = 5; dr = 2; + dl = dr; + if(dl != 2){ + lrc = 49; + if(prlc) printf(f,lrc); + } + cl = 5; cr = 2; + cl += cr; + if(cl != 7){ + lrc = 50; + if(prlc) printf(f,lrc); + } + cl = 5; sr = 2; + cl += sr; + if(cl != 7){ + lrc = 51; + if(prlc) printf(f,lrc); + } + cl = 5; ir = 2; + cl += ir; + if(cl != 7){ + lrc = 52; + if(prlc) printf(f,lrc); + } + cl = 5; lr = 2; + cl += lr; + if(cl != 7){ + lrc = 53; + if(prlc) printf(f,lrc); + } + cl = 5; ur = 2; + cl += ur; + if(cl != 7){ + lrc = 54; + if(prlc) printf(f,lrc); + } + cl = 5; fr = 2; + cl += fr; + if(cl != 7){ + lrc = 55; + if(prlc) printf(f,lrc); + } + cl = 5; dr = 2; + cl += dr; + if(cl != 7){ + lrc = 56; + if(prlc) printf(f,lrc); + } + sl = 5; cr = 2; + sl += cr; + if(sl != 7){ + lrc = 57; + if(prlc) printf(f,lrc); + } + sl = 5; sr = 2; + sl += sr; + if(sl != 7){ + lrc = 58; + if(prlc) printf(f,lrc); + } + sl = 5; ir = 2; + sl += ir; + if(sl != 7){ + lrc = 59; + if(prlc) printf(f,lrc); + } + sl = 5; lr = 2; + sl += lr; + if(sl != 7){ + lrc = 60; + if(prlc) printf(f,lrc); + } + sl = 5; ur = 2; + sl += ur; + if(sl != 7){ + lrc = 61; + if(prlc) printf(f,lrc); + } + sl = 5; fr = 2; + sl += fr; + if(sl != 7){ + lrc = 62; + if(prlc) printf(f,lrc); + } + sl = 5; dr = 2; + sl += dr; + if(sl != 7){ + lrc = 63; + if(prlc) printf(f,lrc); + } + il = 5; cr = 2; + il += cr; + if(il != 7){ + lrc = 64; + if(prlc) printf(f,lrc); + } + il = 5; sr = 2; + il += sr; + if(il != 7){ + lrc = 65; + if(prlc) printf(f,lrc); + } + il = 5; ir = 2; + il += ir; + if(il != 7){ + lrc = 66; + if(prlc) printf(f,lrc); + } + il = 5; lr = 2; + il += lr; + if(il != 7){ + lrc = 67; + if(prlc) printf(f,lrc); + } + il = 5; ur = 2; + il += ur; + if(il != 7){ + lrc = 68; + if(prlc) printf(f,lrc); + } + il = 5; fr = 2; + il += fr; + if(il != 7){ + lrc = 69; + if(prlc) printf(f,lrc); + } + il = 5; dr = 2; + il += dr; + if(il != 7){ + lrc = 70; + if(prlc) printf(f,lrc); + } + ll = 5; cr = 2; + ll += cr; + if(ll != 7){ + lrc = 71; + if(prlc) printf(f,lrc); + } + ll = 5; sr = 2; + ll += sr; + if(ll != 7){ + lrc = 72; + if(prlc) printf(f,lrc); + } + ll = 5; ir = 2; + ll += ir; + if(ll != 7){ + lrc = 73; + if(prlc) printf(f,lrc); + } + ll = 5; lr = 2; + ll += lr; + if(ll != 7){ + lrc = 74; + if(prlc) printf(f,lrc); + } + ll = 5; ur = 2; + ll += ur; + if(ll != 7){ + lrc = 75; + if(prlc) printf(f,lrc); + } + ll = 5; fr = 2; + ll += fr; + if(ll != 7){ + lrc = 76; + if(prlc) printf(f,lrc); + } + ll = 5; dr = 2; + ll += dr; + if(ll != 7){ + lrc = 77; + if(prlc) printf(f,lrc); + } + ul = 5; cr = 2; + ul += cr; + if(ul != 7){ + lrc = 78; + if(prlc) printf(f,lrc); + } + ul = 5; sr = 2; + ul += sr; + if(ul != 7){ + lrc = 79; + if(prlc) printf(f,lrc); + } + ul = 5; ir = 2; + ul += ir; + if(ul != 7){ + lrc = 80; + if(prlc) printf(f,lrc); + } + ul = 5; lr = 2; + ul += lr; + if(ul != 7){ + lrc = 81; + if(prlc) printf(f,lrc); + } + ul = 5; ur = 2; + ul += ur; + if(ul != 7){ + lrc = 82; + if(prlc) printf(f,lrc); + } + ul = 5; fr = 2; + ul += fr; + if(ul != 7){ + lrc = 83; + if(prlc) printf(f,lrc); + } + ul = 5; dr = 2; + ul += dr; + if(ul != 7){ + lrc = 84; + if(prlc) printf(f,lrc); + } + fl = 5; cr = 2; + fl += cr; + if(fl != 7){ + lrc = 85; + if(prlc) printf(f,lrc); + } + fl = 5; sr = 2; + fl += sr; + if(fl != 7){ + lrc = 86; + if(prlc) printf(f,lrc); + } + fl = 5; ir = 2; + fl += ir; + if(fl != 7){ + lrc = 87; + if(prlc) printf(f,lrc); + } + fl = 5; lr = 2; + fl += lr; + if(fl != 7){ + lrc = 88; + if(prlc) printf(f,lrc); + } + fl = 5; ur = 2; + fl += ur; + if(fl != 7){ + lrc = 89; + if(prlc) printf(f,lrc); + } + fl = 5; fr = 2; + fl += fr; + if(fl != 7){ + lrc = 90; + if(prlc) printf(f,lrc); + } + fl = 5; dr = 2; + fl += dr; + if(fl != 7){ + lrc = 91; + if(prlc) printf(f,lrc); + } + dl = 5; cr = 2; + dl += cr; + if(dl != 7){ + lrc = 92; + if(prlc) printf(f,lrc); + } + dl = 5; sr = 2; + dl += sr; + if(dl != 7){ + lrc = 93; + if(prlc) printf(f,lrc); + } + dl = 5; ir = 2; + dl += ir; + if(dl != 7){ + lrc = 94; + if(prlc) printf(f,lrc); + } + dl = 5; lr = 2; + dl += lr; + if(dl != 7){ + lrc = 95; + if(prlc) printf(f,lrc); + } + dl = 5; ur = 2; + dl += ur; + if(dl != 7){ + lrc = 96; + if(prlc) printf(f,lrc); + } + dl = 5; fr = 2; + dl += fr; + if(dl != 7){ + lrc = 97; + if(prlc) printf(f,lrc); + } + dl = 5; dr = 2; + dl += dr; + if(dl != 7){ + lrc = 98; + if(prlc) printf(f,lrc); + } + cl = 5; cr = 2; + cl -= cr; + if(cl != 3){ + lrc = 99; + if(prlc) printf(f,lrc); + } + cl = 5; sr = 2; + cl -= sr; + if(cl != 3){ + lrc = 100; + if(prlc) printf(f,lrc); + } + cl = 5; ir = 2; + cl -= ir; + if(cl != 3){ + lrc = 101; + if(prlc) printf(f,lrc); + } + cl = 5; lr = 2; + cl -= lr; + if(cl != 3){ + lrc = 102; + if(prlc) printf(f,lrc); + } + cl = 5; ur = 2; + cl -= ur; + if(cl != 3){ + lrc = 103; + if(prlc) printf(f,lrc); + } + cl = 5; fr = 2; + cl -= fr; + if(cl != 3){ + lrc = 104; + if(prlc) printf(f,lrc); + } + cl = 5; dr = 2; + cl -= dr; + if(cl != 3){ + lrc = 105; + if(prlc) printf(f,lrc); + } + sl = 5; cr = 2; + sl -= cr; + if(sl != 3){ + lrc = 106; + if(prlc) printf(f,lrc); + } + sl = 5; sr = 2; + sl -= sr; + if(sl != 3){ + lrc = 107; + if(prlc) printf(f,lrc); + } + sl = 5; ir = 2; + sl -= ir; + if(sl != 3){ + lrc = 108; + if(prlc) printf(f,lrc); + } + sl = 5; lr = 2; + sl -= lr; + if(sl != 3){ + lrc = 109; + if(prlc) printf(f,lrc); + } + sl = 5; ur = 2; + sl -= ur; + if(sl != 3){ + lrc = 110; + if(prlc) printf(f,lrc); + } + sl = 5; fr = 2; + sl -= fr; + if(sl != 3){ + lrc = 111; + if(prlc) printf(f,lrc); + } + sl = 5; dr = 2; + sl -= dr; + if(sl != 3){ + lrc = 112; + if(prlc) printf(f,lrc); + } + il = 5; cr = 2; + il -= cr; + if(il != 3){ + lrc = 113; + if(prlc) printf(f,lrc); + } + il = 5; sr = 2; + il -= sr; + if(il != 3){ + lrc = 114; + if(prlc) printf(f,lrc); + } + il = 5; ir = 2; + il -= ir; + if(il != 3){ + lrc = 115; + if(prlc) printf(f,lrc); + } + il = 5; lr = 2; + il -= lr; + if(il != 3){ + lrc = 116; + if(prlc) printf(f,lrc); + } + il = 5; ur = 2; + il -= ur; + if(il != 3){ + lrc = 117; + if(prlc) printf(f,lrc); + } + il = 5; fr = 2; + il -= fr; + if(il != 3){ + lrc = 118; + if(prlc) printf(f,lrc); + } + il = 5; dr = 2; + il -= dr; + if(il != 3){ + lrc = 119; + if(prlc) printf(f,lrc); + } + ll = 5; cr = 2; + ll -= cr; + if(ll != 3){ + lrc = 120; + if(prlc) printf(f,lrc); + } + ll = 5; sr = 2; + ll -= sr; + if(ll != 3){ + lrc = 121; + if(prlc) printf(f,lrc); + } + ll = 5; ir = 2; + ll -= ir; + if(ll != 3){ + lrc = 122; + if(prlc) printf(f,lrc); + } + ll = 5; lr = 2; + ll -= lr; + if(ll != 3){ + lrc = 123; + if(prlc) printf(f,lrc); + } + ll = 5; ur = 2; + ll -= ur; + if(ll != 3){ + lrc = 124; + if(prlc) printf(f,lrc); + } + ll = 5; fr = 2; + ll -= fr; + if(ll != 3){ + lrc = 125; + if(prlc) printf(f,lrc); + } + ll = 5; dr = 2; + ll -= dr; + if(ll != 3){ + lrc = 126; + if(prlc) printf(f,lrc); + } + ul = 5; cr = 2; + ul -= cr; + if(ul != 3){ + lrc = 127; + if(prlc) printf(f,lrc); + } + ul = 5; sr = 2; + ul -= sr; + if(ul != 3){ + lrc = 128; + if(prlc) printf(f,lrc); + } + ul = 5; ir = 2; + ul -= ir; + if(ul != 3){ + lrc = 129; + if(prlc) printf(f,lrc); + } + ul = 5; lr = 2; + ul -= lr; + if(ul != 3){ + lrc = 130; + if(prlc) printf(f,lrc); + } + ul = 5; ur = 2; + ul -= ur; + if(ul != 3){ + lrc = 131; + if(prlc) printf(f,lrc); + } + ul = 5; fr = 2; + ul -= fr; + if(ul != 3){ + lrc = 132; + if(prlc) printf(f,lrc); + } + ul = 5; dr = 2; + ul -= dr; + if(ul != 3){ + lrc = 133; + if(prlc) printf(f,lrc); + } + fl = 5; cr = 2; + fl -= cr; + if(fl != 3){ + lrc = 134; + if(prlc) printf(f,lrc); + } + fl = 5; sr = 2; + fl -= sr; + if(fl != 3){ + lrc = 135; + if(prlc) printf(f,lrc); + } + fl = 5; ir = 2; + fl -= ir; + if(fl != 3){ + lrc = 136; + if(prlc) printf(f,lrc); + } + fl = 5; lr = 2; + fl -= lr; + if(fl != 3){ + lrc = 137; + if(prlc) printf(f,lrc); + } + fl = 5; ur = 2; + fl -= ur; + if(fl != 3){ + lrc = 138; + if(prlc) printf(f,lrc); + } + fl = 5; fr = 2; + fl -= fr; + if(fl != 3){ + lrc = 139; + if(prlc) printf(f,lrc); + } + fl = 5; dr = 2; + fl -= dr; + if(fl != 3){ + lrc = 140; + if(prlc) printf(f,lrc); + } + dl = 5; cr = 2; + dl -= cr; + if(dl != 3){ + lrc = 141; + if(prlc) printf(f,lrc); + } + dl = 5; sr = 2; + dl -= sr; + if(dl != 3){ + lrc = 142; + if(prlc) printf(f,lrc); + } + dl = 5; ir = 2; + dl -= ir; + if(dl != 3){ + lrc = 143; + if(prlc) printf(f,lrc); + } + dl = 5; lr = 2; + dl -= lr; + if(dl != 3){ + lrc = 144; + if(prlc) printf(f,lrc); + } + dl = 5; ur = 2; + dl -= ur; + if(dl != 3){ + lrc = 145; + if(prlc) printf(f,lrc); + } + dl = 5; fr = 2; + dl -= fr; + if(dl != 3){ + lrc = 146; + if(prlc) printf(f,lrc); + } + dl = 5; dr = 2; + dl -= dr; + if(dl != 3){ + lrc = 147; + if(prlc) printf(f,lrc); + } + cl = 5; cr = 2; + cl *= cr; + if(cl != 10){ + lrc = 148; + if(prlc) printf(f,lrc); + } + cl = 5; sr = 2; + cl *= sr; + if(cl != 10){ + lrc = 149; + if(prlc) printf(f,lrc); + } + cl = 5; ir = 2; + cl *= ir; + if(cl != 10){ + lrc = 150; + if(prlc) printf(f,lrc); + } + cl = 5; lr = 2; + cl *= lr; + if(cl != 10){ + lrc = 151; + if(prlc) printf(f,lrc); + } + cl = 5; ur = 2; + cl *= ur; + if(cl != 10){ + lrc = 152; + if(prlc) printf(f,lrc); + } + cl = 5; fr = 2; + cl *= fr; + if(cl != 10){ + lrc = 153; + if(prlc) printf(f,lrc); + } + cl = 5; dr = 2; + cl *= dr; + if(cl != 10){ + lrc = 154; + if(prlc) printf(f,lrc); + } + sl = 5; cr = 2; + sl *= cr; + if(sl != 10){ + lrc = 155; + if(prlc) printf(f,lrc); + } + sl = 5; sr = 2; + sl *= sr; + if(sl != 10){ + lrc = 156; + if(prlc) printf(f,lrc); + } + sl = 5; ir = 2; + sl *= ir; + if(sl != 10){ + lrc = 157; + if(prlc) printf(f,lrc); + } + sl = 5; lr = 2; + sl *= lr; + if(sl != 10){ + lrc = 158; + if(prlc) printf(f,lrc); + } + sl = 5; ur = 2; + sl *= ur; + if(sl != 10){ + lrc = 159; + if(prlc) printf(f,lrc); + } + sl = 5; fr = 2; + sl *= fr; + if(sl != 10){ + lrc = 160; + if(prlc) printf(f,lrc); + } + sl = 5; dr = 2; + sl *= dr; + if(sl != 10){ + lrc = 161; + if(prlc) printf(f,lrc); + } + il = 5; cr = 2; + il *= cr; + if(il != 10){ + lrc = 162; + if(prlc) printf(f,lrc); + } + il = 5; sr = 2; + il *= sr; + if(il != 10){ + lrc = 163; + if(prlc) printf(f,lrc); + } + il = 5; ir = 2; + il *= ir; + if(il != 10){ + lrc = 164; + if(prlc) printf(f,lrc); + } + il = 5; lr = 2; + il *= lr; + if(il != 10){ + lrc = 165; + if(prlc) printf(f,lrc); + } + il = 5; ur = 2; + il *= ur; + if(il != 10){ + lrc = 166; + if(prlc) printf(f,lrc); + } + il = 5; fr = 2; + il *= fr; + if(il != 10){ + lrc = 167; + if(prlc) printf(f,lrc); + } + il = 5; dr = 2; + il *= dr; + if(il != 10){ + lrc = 168; + if(prlc) printf(f,lrc); + } + ll = 5; cr = 2; + ll *= cr; + if(ll != 10){ + lrc = 169; + if(prlc) printf(f,lrc); + } + ll = 5; sr = 2; + ll *= sr; + if(ll != 10){ + lrc = 170; + if(prlc) printf(f,lrc); + } + ll = 5; ir = 2; + ll *= ir; + if(ll != 10){ + lrc = 171; + if(prlc) printf(f,lrc); + } + ll = 5; lr = 2; + ll *= lr; + if(ll != 10){ + lrc = 172; + if(prlc) printf(f,lrc); + } + ll = 5; ur = 2; + ll *= ur; + if(ll != 10){ + lrc = 173; + if(prlc) printf(f,lrc); + } + ll = 5; fr = 2; + ll *= fr; + if(ll != 10){ + lrc = 174; + if(prlc) printf(f,lrc); + } + ll = 5; dr = 2; + ll *= dr; + if(ll != 10){ + lrc = 175; + if(prlc) printf(f,lrc); + } + ul = 5; cr = 2; + ul *= cr; + if(ul != 10){ + lrc = 176; + if(prlc) printf(f,lrc); + } + ul = 5; sr = 2; + ul *= sr; + if(ul != 10){ + lrc = 177; + if(prlc) printf(f,lrc); + } + ul = 5; ir = 2; + ul *= ir; + if(ul != 10){ + lrc = 178; + if(prlc) printf(f,lrc); + } + ul = 5; lr = 2; + ul *= lr; + if(ul != 10){ + lrc = 179; + if(prlc) printf(f,lrc); + } + ul = 5; ur = 2; + ul *= ur; + if(ul != 10){ + lrc = 180; + if(prlc) printf(f,lrc); + } + ul = 5; fr = 2; + ul *= fr; + if(ul != 10){ + lrc = 181; + if(prlc) printf(f,lrc); + } + ul = 5; dr = 2; + ul *= dr; + if(ul != 10){ + lrc = 182; + if(prlc) printf(f,lrc); + } + fl = 5; cr = 2; + fl *= cr; + if(fl != 10){ + lrc = 183; + if(prlc) printf(f,lrc); + } + fl = 5; sr = 2; + fl *= sr; + if(fl != 10){ + lrc = 184; + if(prlc) printf(f,lrc); + } + fl = 5; ir = 2; + fl *= ir; + if(fl != 10){ + lrc = 185; + if(prlc) printf(f,lrc); + } + fl = 5; lr = 2; + fl *= lr; + if(fl != 10){ + lrc = 186; + if(prlc) printf(f,lrc); + } + fl = 5; ur = 2; + fl *= ur; + if(fl != 10){ + lrc = 187; + if(prlc) printf(f,lrc); + } + fl = 5; fr = 2; + fl *= fr; + if(fl != 10){ + lrc = 188; + if(prlc) printf(f,lrc); + } + fl = 5; dr = 2; + fl *= dr; + if(fl != 10){ + lrc = 189; + if(prlc) printf(f,lrc); + } + dl = 5; cr = 2; + dl *= cr; + if(dl != 10){ + lrc = 190; + if(prlc) printf(f,lrc); + } + dl = 5; sr = 2; + dl *= sr; + if(dl != 10){ + lrc = 191; + if(prlc) printf(f,lrc); + } + dl = 5; ir = 2; + dl *= ir; + if(dl != 10){ + lrc = 192; + if(prlc) printf(f,lrc); + } + dl = 5; lr = 2; + dl *= lr; + if(dl != 10){ + lrc = 193; + if(prlc) printf(f,lrc); + } + dl = 5; ur = 2; + dl *= ur; + if(dl != 10){ + lrc = 194; + if(prlc) printf(f,lrc); + } + dl = 5; fr = 2; + dl *= fr; + if(dl != 10){ + lrc = 195; + if(prlc) printf(f,lrc); + } + dl = 5; dr = 2; + dl *= dr; + if(dl != 10){ + lrc = 196; + if(prlc) printf(f,lrc); + } + cl = 5; cr = 2; + cl /= cr; + if(cl != 2){ + lrc = 197; + if(prlc) printf(f,lrc); + } + cl = 5; sr = 2; + cl /= sr; + if(cl != 2){ + lrc = 198; + if(prlc) printf(f,lrc); + } + cl = 5; ir = 2; + cl /= ir; + if(cl != 2){ + lrc = 199; + if(prlc) printf(f,lrc); + } + cl = 5; lr = 2; + cl /= lr; + if(cl != 2){ + lrc = 200; + if(prlc) printf(f,lrc); + } + cl = 5; ur = 2; + cl /= ur; + if(cl != 2){ + lrc = 201; + if(prlc) printf(f,lrc); + } + cl = 5; fr = 2; + cl /= fr; + if(cl != 2){ + lrc = 202; + if(prlc) printf(f,lrc); + } + cl = 5; dr = 2; + cl /= dr; + if(cl != 2){ + lrc = 203; + if(prlc) printf(f,lrc); + } + sl = 5; cr = 2; + sl /= cr; + if(sl != 2){ + lrc = 204; + if(prlc) printf(f,lrc); + } + sl = 5; sr = 2; + sl /= sr; + if(sl != 2){ + lrc = 205; + if(prlc) printf(f,lrc); + } + sl = 5; ir = 2; + sl /= ir; + if(sl != 2){ + lrc = 206; + if(prlc) printf(f,lrc); + } + sl = 5; lr = 2; + sl /= lr; + if(sl != 2){ + lrc = 207; + if(prlc) printf(f,lrc); + } + sl = 5; ur = 2; + sl /= ur; + if(sl != 2){ + lrc = 208; + if(prlc) printf(f,lrc); + } + sl = 5; fr = 2; + sl /= fr; + if(sl != 2){ + lrc = 209; + if(prlc) printf(f,lrc); + } + sl = 5; dr = 2; + sl /= dr; + if(sl != 2){ + lrc = 210; + if(prlc) printf(f,lrc); + } + il = 5; cr = 2; + il /= cr; + if(il != 2){ + lrc = 211; + if(prlc) printf(f,lrc); + } + il = 5; sr = 2; + il /= sr; + if(il != 2){ + lrc = 212; + if(prlc) printf(f,lrc); + } + il = 5; ir = 2; + il /= ir; + if(il != 2){ + lrc = 213; + if(prlc) printf(f,lrc); + } + il = 5; lr = 2; + il /= lr; + if(il != 2){ + lrc = 214; + if(prlc) printf(f,lrc); + } + il = 5; ur = 2; + il /= ur; + if(il != 2){ + lrc = 215; + if(prlc) printf(f,lrc); + } + il = 5; fr = 2; + il /= fr; + if(il != 2){ + lrc = 216; + if(prlc) printf(f,lrc); + } + il = 5; dr = 2; + il /= dr; + if(il != 2){ + lrc = 217; + if(prlc) printf(f,lrc); + } + ll = 5; cr = 2; + ll /= cr; + if(ll != 2){ + lrc = 218; + if(prlc) printf(f,lrc); + } + ll = 5; sr = 2; + ll /= sr; + if(ll != 2){ + lrc = 219; + if(prlc) printf(f,lrc); + } + ll = 5; ir = 2; + ll /= ir; + if(ll != 2){ + lrc = 220; + if(prlc) printf(f,lrc); + } + ll = 5; lr = 2; + ll /= lr; + if(ll != 2){ + lrc = 221; + if(prlc) printf(f,lrc); + } + ll = 5; ur = 2; + ll /= ur; + if(ll != 2){ + lrc = 222; + if(prlc) printf(f,lrc); + } + ll = 5; fr = 2; + ll /= fr; + if(ll != 2){ + lrc = 223; + if(prlc) printf(f,lrc); + } + ll = 5; dr = 2; + ll /= dr; + if(ll != 2){ + lrc = 224; + if(prlc) printf(f,lrc); + } + ul = 5; cr = 2; + ul /= cr; + if(ul != 2){ + lrc = 225; + if(prlc) printf(f,lrc); + } + ul = 5; sr = 2; + ul /= sr; + if(ul != 2){ + lrc = 226; + if(prlc) printf(f,lrc); + } + ul = 5; ir = 2; + ul /= ir; + if(ul != 2){ + lrc = 227; + if(prlc) printf(f,lrc); + } + ul = 5; lr = 2; + ul /= lr; + if(ul != 2){ + lrc = 228; + if(prlc) printf(f,lrc); + } + ul = 5; ur = 2; + ul /= ur; + if(ul != 2){ + lrc = 229; + if(prlc) printf(f,lrc); + } + ul = 5; fr = 2; + ul /= fr; + if(ul != 2){ + lrc = 230; + if(prlc) printf(f,lrc); + } + ul = 5; dr = 2; + ul /= dr; + if(ul != 2){ + lrc = 231; + if(prlc) printf(f,lrc); + } + + #ifdef NO_FLOATS + fl = 5; cr = 2; + fl /= cr; + if(fl != 2){ + lrc = 232; + if(prlc) printf(f,lrc); + } + fl = 5; sr = 2; + fl /= sr; + if(fl != 2){ + lrc = 233; + if(prlc) printf(f,lrc); + } + fl = 5; ir = 2; + fl /= ir; + if(fl != 2){ + lrc = 234; + if(prlc) printf(f,lrc); + } + fl = 5; lr = 2; + fl /= lr; + if(fl != 2){ + lrc = 235; + if(prlc) printf(f,lrc); + } + fl = 5; ur = 2; + fl /= ur; + if(fl != 2){ + lrc = 236; + if(prlc) printf(f,lrc); + } + fl = 5; fr = 2; + fl /= fr; + if(fl != 2){ + lrc = 237; + if(prlc) printf(f,lrc); + } + fl = 5; dr = 2; + fl /= dr; + if(fl != 2){ + lrc = 238; + if(prlc) printf(f,lrc); + } + dl = 5; cr = 2; + dl /= cr; + if(dl != 2){ + lrc = 239; + if(prlc) printf(f,lrc); + } + dl = 5; sr = 2; + dl /= sr; + if(dl != 2){ + lrc = 240; + if(prlc) printf(f,lrc); + } + dl = 5; ir = 2; + dl /= ir; + if(dl != 2){ + lrc = 241; + if(prlc) printf(f,lrc); + } + dl = 5; lr = 2; + dl /= lr; + if(dl != 2){ + lrc = 242; + if(prlc) printf(f,lrc); + } + dl = 5; ur = 2; + dl /= ur; + if(dl != 2){ + lrc = 243; + if(prlc) printf(f,lrc); + } + dl = 5; fr = 2; + dl /= fr; + if(dl != 2){ + lrc = 244; + if(prlc) printf(f,lrc); + } + dl = 5; dr = 2; + dl /= dr; + if(dl != 2){ + lrc = 245; + if(prlc) printf(f,lrc); + } + #else + fl = 5; cr = 2; + fl /= cr; + if(fl != 2.5){ + lrc = 232; + if(prlc) printf(f,lrc); + } + fl = 5; sr = 2; + fl /= sr; + if(fl != 2.5){ + lrc = 233; + if(prlc) printf(f,lrc); + } + fl = 5; ir = 2; + fl /= ir; + if(fl != 2.5){ + lrc = 234; + if(prlc) printf(f,lrc); + } + fl = 5; lr = 2; + fl /= lr; + if(fl != 2.5){ + lrc = 235; + if(prlc) printf(f,lrc); + } + fl = 5; ur = 2; + fl /= ur; + if(fl != 2.5){ + lrc = 236; + if(prlc) printf(f,lrc); + } + fl = 5; fr = 2; + fl /= fr; + if(fl != 2.5){ + lrc = 237; + if(prlc) printf(f,lrc); + } + fl = 5; dr = 2; + fl /= dr; + if(fl != 2.5){ + lrc = 238; + if(prlc) printf(f,lrc); + } + dl = 5; cr = 2; + dl /= cr; + if(dl != 2.5){ + lrc = 239; + if(prlc) printf(f,lrc); + } + dl = 5; sr = 2; + dl /= sr; + if(dl != 2.5){ + lrc = 240; + if(prlc) printf(f,lrc); + } + dl = 5; ir = 2; + dl /= ir; + if(dl != 2.5){ + lrc = 241; + if(prlc) printf(f,lrc); + } + dl = 5; lr = 2; + dl /= lr; + if(dl != 2.5){ + lrc = 242; + if(prlc) printf(f,lrc); + } + dl = 5; ur = 2; + dl /= ur; + if(dl != 2.5){ + lrc = 243; + if(prlc) printf(f,lrc); + } + dl = 5; fr = 2; + dl /= fr; + if(dl != 2.5){ + lrc = 244; + if(prlc) printf(f,lrc); + } + dl = 5; dr = 2; + dl /= dr; + if(dl != 2.5){ + lrc = 245; + if(prlc) printf(f,lrc); + } + #endif + cl = 5; cr = 2; + cl %= cr; + if(cl != 1){ + lrc = 246; + if(prlc) printf(f,lrc); + } + cl = 5; sr = 2; + cl %= sr; + if(cl != 1){ + lrc = 247; + if(prlc) printf(f,lrc); + } + cl = 5; ir = 2; + cl %= ir; + if(cl != 1){ + lrc = 248; + if(prlc) printf(f,lrc); + } + cl = 5; lr = 2; + cl %= lr; + if(cl != 1){ + lrc = 249; + if(prlc) printf(f,lrc); + } + cl = 5; ur = 2; + cl %= ur; + if(cl != 1){ + lrc = 250; + if(prlc) printf(f,lrc); + } + sl = 5; cr = 2; + sl %= cr; + if(sl != 1){ + lrc = 251; + if(prlc) printf(f,lrc); + } + sl = 5; sr = 2; + sl %= sr; + if(sl != 1){ + lrc = 252; + if(prlc) printf(f,lrc); + } + sl = 5; ir = 2; + sl %= ir; + if(sl != 1){ + lrc = 253; + if(prlc) printf(f,lrc); + } + sl = 5; lr = 2; + sl %= lr; + if(sl != 1){ + lrc = 254; + if(prlc) printf(f,lrc); + } + sl = 5; ur = 2; + sl %= ur; + if(sl != 1){ + lrc = 255; + if(prlc) printf(f,lrc); + } + + if(lrc != 0) { + rc = 1; + if(pd0->flgd != 0) printf(s714er,1); + } + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s714(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq714b.c b/test/val/cq714b.c new file mode 100644 index 000000000..9a09a88f0 --- /dev/null +++ b/test/val/cq714b.c @@ -0,0 +1,1016 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 9: Statements + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#ifndef NO_OLD_FUNC_DECL +s714(pd0) /* 7.14 Assignment operators */ +struct defs *pd0; +{ +#else +int s714(struct defs *pd0){ +#endif + static char f[] = "Local error %d.\n"; + static char s714er[] = "s714,er%d\n"; + static char qs714[8] = "s714 "; + register int prlc, lrc; + int rc; + char cl, cr; + short sl, sr; + int il, ir; + long ll, lr; + unsigned ul, ur; + #ifndef NO_FLOATS + float fl, fr; + double dl, dr; + #else + signed fl, fr; + signed dl, dr; + #endif + char *ps, *pt; + ps = qs714; + pt = pd0->rfs; + rc = 0; + lrc = 0; + prlc = pd0->flgl; + while (*pt++ = *ps++); + + /* This section tests the assignment operators. + + It is an exhaustive test of all assignment statements + of the form: + + vl op vr + + where vl and vr are variables from the set + {char,short,int,long,unsigned,float,double} and op is + one of the assignment operators. There are 395 such + statements. + + The initial values for the variables have been chosen + so that both the initial values and the results will + "fit" in just about any implementation, and that the re- + sults will be such that they test for the proper form- + ation of composite operators, rather than checking for + the valid operation of those operators' components. + For example, in checking >>=, we want to verify that + a right shift and a move take place, rather than + whether or not there may be some peculiarities about + the right shift. Such tests have been made previously, + and to repeat them here would be to throw out a red + herring. + + The table below lists the operators, assignment targets, + initial values for left and right operands, and the + expected values of the results. + + = += -= *= /= %= >>= <<= &= ^= |= +char 2 7 3 10 2 1 1 20 8 6 14 +short 2 7 3 10 2 1 1 20 8 6 14 +int 2 7 3 10 2 1 1 20 8 6 14 +long 2 7 3 10 2 1 1 20 8 6 14 +unsigned 2 7 3 10 2 1 1 20 8 6 14 +float 2 7 3 10 2.5 | | +double 2 7 3 10 2.5 | | + | | +initial (5,2) | (5,2) | (12,10) + + The following machine-generated program reflects the + tests described in the table. + */ + + il = 5; cr = 2; + il %= cr; + if(il != 1){ + lrc = 256; + if(prlc) printf(f,lrc); + } + il = 5; sr = 2; + il %= sr; + if(il != 1){ + lrc = 257; + if(prlc) printf(f,lrc); + } + il = 5; ir = 2; + il %= ir; + if(il != 1){ + lrc = 258; + if(prlc) printf(f,lrc); + } + il = 5; lr = 2; + il %= lr; + if(il != 1){ + lrc = 259; + if(prlc) printf(f,lrc); + } + il = 5; ur = 2; + il %= ur; + if(il != 1){ + lrc = 260; + if(prlc) printf(f,lrc); + } + ll = 5; cr = 2; + ll %= cr; + if(ll != 1){ + lrc = 261; + if(prlc) printf(f,lrc); + } + ll = 5; sr = 2; + ll %= sr; + if(ll != 1){ + lrc = 262; + if(prlc) printf(f,lrc); + } + ll = 5; ir = 2; + ll %= ir; + if(ll != 1){ + lrc = 263; + if(prlc) printf(f,lrc); + } + ll = 5; lr = 2; + ll %= lr; + if(ll != 1){ + lrc = 264; + if(prlc) printf(f,lrc); + } + ll = 5; ur = 2; + ll %= ur; + if(ll != 1){ + lrc = 265; + if(prlc) printf(f,lrc); + } + ul = 5; cr = 2; + ul %= cr; + if(ul != 1){ + lrc = 266; + if(prlc) printf(f,lrc); + } + ul = 5; sr = 2; + ul %= sr; + if(ul != 1){ + lrc = 267; + if(prlc) printf(f,lrc); + } + ul = 5; ir = 2; + ul %= ir; + if(ul != 1){ + lrc = 268; + if(prlc) printf(f,lrc); + } + ul = 5; lr = 2; + ul %= lr; + if(ul != 1){ + lrc = 269; + if(prlc) printf(f,lrc); + } + ul = 5; ur = 2; + ul %= ur; + if(ul != 1){ + lrc = 270; + if(prlc) printf(f,lrc); + } + cl = 5; cr = 2; + cl >>= cr; + if(cl != 1){ + lrc = 271; + if(prlc) printf(f,lrc); + } + cl = 5; sr = 2; + cl >>= sr; + if(cl != 1){ + lrc = 272; + if(prlc) printf(f,lrc); + } + cl = 5; ir = 2; + cl >>= ir; + if(cl != 1){ + lrc = 273; + if(prlc) printf(f,lrc); + } + cl = 5; lr = 2; + cl >>= lr; + if(cl != 1){ + lrc = 274; + if(prlc) printf(f,lrc); + } + cl = 5; ur = 2; + cl >>= ur; + if(cl != 1){ + lrc = 275; + if(prlc) printf(f,lrc); + } + sl = 5; cr = 2; + sl >>= cr; + if(sl != 1){ + lrc = 276; + if(prlc) printf(f,lrc); + } + sl = 5; sr = 2; + sl >>= sr; + if(sl != 1){ + lrc = 277; + if(prlc) printf(f,lrc); + } + sl = 5; ir = 2; + sl >>= ir; + if(sl != 1){ + lrc = 278; + if(prlc) printf(f,lrc); + } + sl = 5; lr = 2; + sl >>= lr; + if(sl != 1){ + lrc = 279; + if(prlc) printf(f,lrc); + } + sl = 5; ur = 2; + sl >>= ur; + if(sl != 1){ + lrc = 280; + if(prlc) printf(f,lrc); + } + il = 5; cr = 2; + il >>= cr; + if(il != 1){ + lrc = 281; + if(prlc) printf(f,lrc); + } + il = 5; sr = 2; + il >>= sr; + if(il != 1){ + lrc = 282; + if(prlc) printf(f,lrc); + } + il = 5; ir = 2; + il >>= ir; + if(il != 1){ + lrc = 283; + if(prlc) printf(f,lrc); + } + il = 5; lr = 2; + il >>= lr; + if(il != 1){ + lrc = 284; + if(prlc) printf(f,lrc); + } + il = 5; ur = 2; + il >>= ur; + if(il != 1){ + lrc = 285; + if(prlc) printf(f,lrc); + } + ll = 5; cr = 2; + ll >>= cr; + if(ll != 1){ + lrc = 286; + if(prlc) printf(f,lrc); + } + ll = 5; sr = 2; + ll >>= sr; + if(ll != 1){ + lrc = 287; + if(prlc) printf(f,lrc); + } + ll = 5; ir = 2; + ll >>= ir; + if(ll != 1){ + lrc = 288; + if(prlc) printf(f,lrc); + } + ll = 5; lr = 2; + ll >>= lr; + if(ll != 1){ + lrc = 289; + if(prlc) printf(f,lrc); + } + ll = 5; ur = 2; + ll >>= ur; + if(ll != 1){ + lrc = 290; + if(prlc) printf(f,lrc); + } + ul = 5; cr = 2; + ul >>= cr; + if(ul != 1){ + lrc = 291; + if(prlc) printf(f,lrc); + } + ul = 5; sr = 2; + ul >>= sr; + if(ul != 1){ + lrc = 292; + if(prlc) printf(f,lrc); + } + ul = 5; ir = 2; + ul >>= ir; + if(ul != 1){ + lrc = 293; + if(prlc) printf(f,lrc); + } + ul = 5; lr = 2; + ul >>= lr; + if(ul != 1){ + lrc = 294; + if(prlc) printf(f,lrc); + } + ul = 5; ur = 2; + ul >>= ur; + if(ul != 1){ + lrc = 295; + if(prlc) printf(f,lrc); + } + cl = 5; cr = 2; + cl <<= cr; + if(cl != 20){ + lrc = 296; + if(prlc) printf(f,lrc); + } + cl = 5; sr = 2; + cl <<= sr; + if(cl != 20){ + lrc = 297; + if(prlc) printf(f,lrc); + } + cl = 5; ir = 2; + cl <<= ir; + if(cl != 20){ + lrc = 298; + if(prlc) printf(f,lrc); + } + cl = 5; lr = 2; + cl <<= lr; + if(cl != 20){ + lrc = 299; + if(prlc) printf(f,lrc); + } + cl = 5; ur = 2; + cl <<= ur; + if(cl != 20){ + lrc = 300; + if(prlc) printf(f,lrc); + } + sl = 5; cr = 2; + sl <<= cr; + if(sl != 20){ + lrc = 301; + if(prlc) printf(f,lrc); + } + sl = 5; sr = 2; + sl <<= sr; + if(sl != 20){ + lrc = 302; + if(prlc) printf(f,lrc); + } + sl = 5; ir = 2; + sl <<= ir; + if(sl != 20){ + lrc = 303; + if(prlc) printf(f,lrc); + } + sl = 5; lr = 2; + sl <<= lr; + if(sl != 20){ + lrc = 304; + if(prlc) printf(f,lrc); + } + sl = 5; ur = 2; + sl <<= ur; + if(sl != 20){ + lrc = 305; + if(prlc) printf(f,lrc); + } + il = 5; cr = 2; + il <<= cr; + if(il != 20){ + lrc = 306; + if(prlc) printf(f,lrc); + } + il = 5; sr = 2; + il <<= sr; + if(il != 20){ + lrc = 307; + if(prlc) printf(f,lrc); + } + il = 5; ir = 2; + il <<= ir; + if(il != 20){ + lrc = 308; + if(prlc) printf(f,lrc); + } + il = 5; lr = 2; + il <<= lr; + if(il != 20){ + lrc = 309; + if(prlc) printf(f,lrc); + } + il = 5; ur = 2; + il <<= ur; + if(il != 20){ + lrc = 310; + if(prlc) printf(f,lrc); + } + ll = 5; cr = 2; + ll <<= cr; + if(ll != 20){ + lrc = 311; + if(prlc) printf(f,lrc); + } + ll = 5; sr = 2; + ll <<= sr; + if(ll != 20){ + lrc = 312; + if(prlc) printf(f,lrc); + } + ll = 5; ir = 2; + ll <<= ir; + if(ll != 20){ + lrc = 313; + if(prlc) printf(f,lrc); + } + ll = 5; lr = 2; + ll <<= lr; + if(ll != 20){ + lrc = 314; + if(prlc) printf(f,lrc); + } + ll = 5; ur = 2; + ll <<= ur; + if(ll != 20){ + lrc = 315; + if(prlc) printf(f,lrc); + } + ul = 5; cr = 2; + ul <<= cr; + if(ul != 20){ + lrc = 316; + if(prlc) printf(f,lrc); + } + ul = 5; sr = 2; + ul <<= sr; + if(ul != 20){ + lrc = 317; + if(prlc) printf(f,lrc); + } + ul = 5; ir = 2; + ul <<= ir; + if(ul != 20){ + lrc = 318; + if(prlc) printf(f,lrc); + } + ul = 5; lr = 2; + ul <<= lr; + if(ul != 20){ + lrc = 319; + if(prlc) printf(f,lrc); + } + ul = 5; ur = 2; + ul <<= ur; + if(ul != 20){ + lrc = 320; + if(prlc) printf(f,lrc); + } + cl = 12; cr = 10; + cl &= cr; + if(cl != 8){ + lrc = 321; + if(prlc) printf(f,lrc); + } + cl = 12; sr = 10; + cl &= sr; + if(cl != 8){ + lrc = 322; + if(prlc) printf(f,lrc); + } + cl = 12; ir = 10; + cl &= ir; + if(cl != 8){ + lrc = 323; + if(prlc) printf(f,lrc); + } + cl = 12; lr = 10; + cl &= lr; + if(cl != 8){ + lrc = 324; + if(prlc) printf(f,lrc); + } + cl = 12; ur = 10; + cl &= ur; + if(cl != 8){ + lrc = 325; + if(prlc) printf(f,lrc); + } + sl = 12; cr = 10; + sl &= cr; + if(sl != 8){ + lrc = 326; + if(prlc) printf(f,lrc); + } + sl = 12; sr = 10; + sl &= sr; + if(sl != 8){ + lrc = 327; + if(prlc) printf(f,lrc); + } + sl = 12; ir = 10; + sl &= ir; + if(sl != 8){ + lrc = 328; + if(prlc) printf(f,lrc); + } + sl = 12; lr = 10; + sl &= lr; + if(sl != 8){ + lrc = 329; + if(prlc) printf(f,lrc); + } + sl = 12; ur = 10; + sl &= ur; + if(sl != 8){ + lrc = 330; + if(prlc) printf(f,lrc); + } + il = 12; cr = 10; + il &= cr; + if(il != 8){ + lrc = 331; + if(prlc) printf(f,lrc); + } + il = 12; sr = 10; + il &= sr; + if(il != 8){ + lrc = 332; + if(prlc) printf(f,lrc); + } + il = 12; ir = 10; + il &= ir; + if(il != 8){ + lrc = 333; + if(prlc) printf(f,lrc); + } + il = 12; lr = 10; + il &= lr; + if(il != 8){ + lrc = 334; + if(prlc) printf(f,lrc); + } + il = 12; ur = 10; + il &= ur; + if(il != 8){ + lrc = 335; + if(prlc) printf(f,lrc); + } + ll = 12; cr = 10; + ll &= cr; + if(ll != 8){ + lrc = 336; + if(prlc) printf(f,lrc); + } + ll = 12; sr = 10; + ll &= sr; + if(ll != 8){ + lrc = 337; + if(prlc) printf(f,lrc); + } + ll = 12; ir = 10; + ll &= ir; + if(ll != 8){ + lrc = 338; + if(prlc) printf(f,lrc); + } + ll = 12; lr = 10; + ll &= lr; + if(ll != 8){ + lrc = 339; + if(prlc) printf(f,lrc); + } + ll = 12; ur = 10; + ll &= ur; + if(ll != 8){ + lrc = 340; + if(prlc) printf(f,lrc); + } + ul = 12; cr = 10; + ul &= cr; + if(ul != 8){ + lrc = 341; + if(prlc) printf(f,lrc); + } + ul = 12; sr = 10; + ul &= sr; + if(ul != 8){ + lrc = 342; + if(prlc) printf(f,lrc); + } + ul = 12; ir = 10; + ul &= ir; + if(ul != 8){ + lrc = 343; + if(prlc) printf(f,lrc); + } + ul = 12; lr = 10; + ul &= lr; + if(ul != 8){ + lrc = 344; + if(prlc) printf(f,lrc); + } + ul = 12; ur = 10; + ul &= ur; + if(ul != 8){ + lrc = 345; + if(prlc) printf(f,lrc); + } + cl = 12; cr = 10; + cl ^= cr; + if(cl != 6){ + lrc = 346; + if(prlc) printf(f,lrc); + } + cl = 12; sr = 10; + cl ^= sr; + if(cl != 6){ + lrc = 347; + if(prlc) printf(f,lrc); + } + cl = 12; ir = 10; + cl ^= ir; + if(cl != 6){ + lrc = 348; + if(prlc) printf(f,lrc); + } + cl = 12; lr = 10; + cl ^= lr; + if(cl != 6){ + lrc = 349; + if(prlc) printf(f,lrc); + } + cl = 12; ur = 10; + cl ^= ur; + if(cl != 6){ + lrc = 350; + if(prlc) printf(f,lrc); + } + sl = 12; cr = 10; + sl ^= cr; + if(sl != 6){ + lrc = 351; + if(prlc) printf(f,lrc); + } + sl = 12; sr = 10; + sl ^= sr; + if(sl != 6){ + lrc = 352; + if(prlc) printf(f,lrc); + } + sl = 12; ir = 10; + sl ^= ir; + if(sl != 6){ + lrc = 353; + if(prlc) printf(f,lrc); + } + sl = 12; lr = 10; + sl ^= lr; + if(sl != 6){ + lrc = 354; + if(prlc) printf(f,lrc); + } + sl = 12; ur = 10; + sl ^= ur; + if(sl != 6){ + lrc = 355; + if(prlc) printf(f,lrc); + } + il = 12; cr = 10; + il ^= cr; + if(il != 6){ + lrc = 356; + if(prlc) printf(f,lrc); + } + il = 12; sr = 10; + il ^= sr; + if(il != 6){ + lrc = 357; + if(prlc) printf(f,lrc); + } + il = 12; ir = 10; + il ^= ir; + if(il != 6){ + lrc = 358; + if(prlc) printf(f,lrc); + } + il = 12; lr = 10; + il ^= lr; + if(il != 6){ + lrc = 359; + if(prlc) printf(f,lrc); + } + il = 12; ur = 10; + il ^= ur; + if(il != 6){ + lrc = 360; + if(prlc) printf(f,lrc); + } + ll = 12; cr = 10; + ll ^= cr; + if(ll != 6){ + lrc = 361; + if(prlc) printf(f,lrc); + } + ll = 12; sr = 10; + ll ^= sr; + if(ll != 6){ + lrc = 362; + if(prlc) printf(f,lrc); + } + ll = 12; ir = 10; + ll ^= ir; + if(ll != 6){ + lrc = 363; + if(prlc) printf(f,lrc); + } + ll = 12; lr = 10; + ll ^= lr; + if(ll != 6){ + lrc = 364; + if(prlc) printf(f,lrc); + } + ll = 12; ur = 10; + ll ^= ur; + if(ll != 6){ + lrc = 365; + if(prlc) printf(f,lrc); + } + ul = 12; cr = 10; + ul ^= cr; + if(ul != 6){ + lrc = 366; + if(prlc) printf(f,lrc); + } + ul = 12; sr = 10; + ul ^= sr; + if(ul != 6){ + lrc = 367; + if(prlc) printf(f,lrc); + } + ul = 12; ir = 10; + ul ^= ir; + if(ul != 6){ + lrc = 368; + if(prlc) printf(f,lrc); + } + ul = 12; lr = 10; + ul ^= lr; + if(ul != 6){ + lrc = 369; + if(prlc) printf(f,lrc); + } + ul = 12; ur = 10; + ul ^= ur; + if(ul != 6){ + lrc = 370; + if(prlc) printf(f,lrc); + } + cl = 12; cr = 10; + cl |= cr; + if(cl != 14){ + lrc = 371; + if(prlc) printf(f,lrc); + } + cl = 12; sr = 10; + cl |= sr; + if(cl != 14){ + lrc = 372; + if(prlc) printf(f,lrc); + } + cl = 12; ir = 10; + cl |= ir; + if(cl != 14){ + lrc = 373; + if(prlc) printf(f,lrc); + } + cl = 12; lr = 10; + cl |= lr; + if(cl != 14){ + lrc = 374; + if(prlc) printf(f,lrc); + } + cl = 12; ur = 10; + cl |= ur; + if(cl != 14){ + lrc = 375; + if(prlc) printf(f,lrc); + } + sl = 12; cr = 10; + sl |= cr; + if(sl != 14){ + lrc = 376; + if(prlc) printf(f,lrc); + } + sl = 12; sr = 10; + sl |= sr; + if(sl != 14){ + lrc = 377; + if(prlc) printf(f,lrc); + } + sl = 12; ir = 10; + sl |= ir; + if(sl != 14){ + lrc = 378; + if(prlc) printf(f,lrc); + } + sl = 12; lr = 10; + sl |= lr; + if(sl != 14){ + lrc = 379; + if(prlc) printf(f,lrc); + } + sl = 12; ur = 10; + sl |= ur; + if(sl != 14){ + lrc = 380; + if(prlc) printf(f,lrc); + } + il = 12; cr = 10; + il |= cr; + if(il != 14){ + lrc = 381; + if(prlc) printf(f,lrc); + } + il = 12; sr = 10; + il |= sr; + if(il != 14){ + lrc = 382; + if(prlc) printf(f,lrc); + } + il = 12; ir = 10; + il |= ir; + if(il != 14){ + lrc = 383; + if(prlc) printf(f,lrc); + } + il = 12; lr = 10; + il |= lr; + if(il != 14){ + lrc = 384; + if(prlc) printf(f,lrc); + } + il = 12; ur = 10; + il |= ur; + if(il != 14){ + lrc = 385; + if(prlc) printf(f,lrc); + } + ll = 12; cr = 10; + ll |= cr; + if(ll != 14){ + lrc = 386; + if(prlc) printf(f,lrc); + } + ll = 12; sr = 10; + ll |= sr; + if(ll != 14){ + lrc = 387; + if(prlc) printf(f,lrc); + } + ll = 12; ir = 10; + ll |= ir; + if(ll != 14){ + lrc = 388; + if(prlc) printf(f,lrc); + } + ll = 12; lr = 10; + ll |= lr; + if(ll != 14){ + lrc = 389; + if(prlc) printf(f,lrc); + } + ll = 12; ur = 10; + ll |= ur; + if(ll != 14){ + lrc = 390; + if(prlc) printf(f,lrc); + } + ul = 12; cr = 10; + ul |= cr; + if(ul != 14){ + lrc = 391; + if(prlc) printf(f,lrc); + } + ul = 12; sr = 10; + ul |= sr; + if(ul != 14){ + lrc = 392; + if(prlc) printf(f,lrc); + } + ul = 12; ir = 10; + ul |= ir; + if(ul != 14){ + lrc = 393; + if(prlc) printf(f,lrc); + } + ul = 12; lr = 10; + ul |= lr; + if(ul != 14){ + lrc = 394; + if(prlc) printf(f,lrc); + } + ul = 12; ur = 10; + ul |= ur; + if(ul != 14){ + lrc = 395; + if(prlc) printf(f,lrc); + } + if(lrc != 0) { + rc = 1; + if(pd0->flgd != 0) printf(s714er,1); + } + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s714(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq715.c b/test/val/cq715.c new file mode 100644 index 000000000..dd829156c --- /dev/null +++ b/test/val/cq715.c @@ -0,0 +1,151 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 7.15: Comma operator + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +/*#include "cq26.c"*/ /* hardware check */ +#ifdef NO_IMPLICIT_FUNC_PROTOTYPES +s715f(int x,int y,int z); +#endif + +#ifndef NO_OLD_FUNC_DECL +s715(pd0) /* 7.15 Comma operator */ +struct defs *pd0; +{ +#else +int s715(struct defs *pd0) { +#endif + static char s715er[] = "s715,er%d\n"; + static char qs715[8] = "s715 "; + int rc; + char *ps, *pt; + int a, t, c, i; + a = c = 0; + ps = qs715; + pt = pd0->rfs; + rc = 0; + while (*pt++ = *ps++); + + /* A pair of expressions separated by a comma is + evaluated left to right and the value of the left + expression is discarded. + */ + i = 1; + if( i++,i++,i++,i++,++i != 6 ){ + if(pd0->flgd != 0) printf(s715er,1); + rc = rc+1; + } + + /* In contexts where the comma is given a special mean- + ing, for example in a list of actual arguments to + functions (sic) and lists of initializers, the comma + operator as described in this section can only appear + in parentheses; for example + + f( a, (t=3, t+2), c) + + has three arguments, the second of which has the + value 5. + */ + + if(s715f(a, (t=3, t+2), c) != 5){ + if(pd0->flgd != 0) printf(s715er,2); + rc = rc+2; + } + return rc; +} +s715f(x,y,z) +int x, y, z; +{ + return y; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + /*case 0: return s26(pd0);*/ + case 0: return s715(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq72.c b/test/val/cq72.c new file mode 100644 index 000000000..5f60fdcad --- /dev/null +++ b/test/val/cq72.c @@ -0,0 +1,345 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 7.2: Unary Operators + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#define CQ26_INCLUDED +/* + section s26, which pokes around at the hardware + trying to figure out the characteristics of the machine that + it is running on, saves information that is subsequently + used by sections s626, s72, and s757. If this program is + to be broken up into smallish pieces, say for running on + a microcomputer, take care to see that s26 is called before + calling any of the latter three sections. +*/ + +/* + 2.6 Hardware Characteristics +*/ + +#ifndef NO_OLD_FUNC_DECL +s26(pd0) +struct defs *pd0; +{ +#else +s26(struct defs *pd0) { +#endif + static char qs26[8] = "s26 "; + char *ps, *pt; + char c0, c1; + #ifndef NO_FLOATS + float temp, one, delta; + double tempd, oned; + #endif + static char s[] = "%3d bits in %ss.\n"; + static char s2[] = "%e is the least number that can be added to 1. (%s).\n"; + + ps = qs26; + pt = pd0->rfs; + + while(*pt++ = *ps++); + + /* Here, we shake the machinery a little to see what falls + out. First, we find out how many bits are in a char. */ + + pd0->cbits = 0; + c0 = 0; + c1 = 1; + + while(c0 != c1) { + c1 = c1<<1; + pd0->cbits = pd0->cbits+1; + } + /* That information lets us determine the size of everything else. */ + + pd0->ibits = pd0->cbits * sizeof(int); + pd0->sbits = pd0->cbits * sizeof(short); + pd0->lbits = pd0->cbits * sizeof(long); + pd0->ubits = pd0->cbits * sizeof(unsigned); + #ifndef NO_FLOATS + pd0->fbits = pd0->cbits * sizeof(float); + pd0->dbits = pd0->cbits * sizeof(double); + #endif + + /* We have now almost reconstructed the table in section 2.6, the + exception being the range of the floating point hardware. + Now there are just so many ways to conjure up a floating point + representation system that it's damned near impossible to guess + what's going on by writing a program to interpret bit patterns. + Further, the information isn't all that useful, if we consider + the fact that machines that won't handle numbers between 10**30 + and 10**-30 are very hard to find, and that people playing with + numbers outside that range have a lot more to worry about than + just the capacity of the characteristic. + + A much more useful measure is the precision, which can be ex- + pressed in terms of the smallest number that can be added to + 1. without loss of significance. We calculate that here, for + float and double. */ + +#ifndef NO_FLOATS + one = 1.; + delta = 1.; + temp = 0.; + while(temp != one) { + temp = one+delta; + delta = delta/2.; + } + pd0->fprec = delta * 4.; + oned = 1.; + delta = 1.; + tempd = 0.; + while(tempd != oned) { + tempd = oned+delta; + delta = delta/2.; + } + pd0->dprec = delta * 4.; +#endif + + /* Now, if anyone's interested, we publish the results. */ + +#ifndef CQ26_INCLUDED + if(pd0->flgm != 0) { + printf(s,pd0->cbits,"char"); + printf(s,pd0->ibits,"int"); + printf(s,pd0->sbits,"short"); + printf(s,pd0->lbits,"long"); + printf(s,pd0->ubits,"unsigned"); + printf(s,pd0->fbits,"float"); + printf(s,pd0->dbits,"double"); + #ifndef NO_FLOATS + printf(s2,pd0->fprec,"float"); + printf(s2,pd0->dprec,"double"); + #else + printf("NO_FLOATS\n"); + #endif + } +#endif + /* Since we are only exploring and perhaps reporting, but not + testing any features, we cannot return an error code. */ + + return 0; +} + +#ifndef NO_OLD_FUNC_DECL +s72(pd0) /* 7.2 Unary operators */ +struct defs *pd0; +{ +#else +int s72(struct defs *pd0){ +#endif + static char s72er[] = "s72,er%d\n"; + static char qs72[8] = "s72 "; + int rc; + char *ps, *pt; + int k, j, i, lrc; + char c; + short s; + long l; + unsigned u; + + #ifndef NO_FLOATS + double d; + float f; + #else + signed d; + signed f; + #endif + + ps = qs72; + pt = pd0->rfs; + rc = 0; + while (*pt++ = *ps++); + + /* The *, denoting indirection, and the &, denoting a + pointer, are duals of each other, and ought to behave as + such... */ + + k = 2; + if(*&*&k != 2){ + rc = rc+1; + printf(s72er,1); + } + + /* The unary minus has the conventional meaning. */ + + if(k+(-k) != 0){ + rc = rc+2; + printf(s72er,2); + } + + /* The negation operator (!) has been thoroughly checked out, + perhaps more thoroughly than any of the others. The ~ oper- + ator gets us a ones complement. */ + + k = 0; + for(j=0;j<pd0->ibits;j++) k = (k<<1)|1; + if(~k != 0){ + rc = rc+4; + printf(s72er,4); + } + + /* Now we look at the ++ and -- operators, which can be + used in either prefix or suffix form. With side + effects they're loaded. */ + + k = 5; + + if( ++k != 6 || --k != 5 + || k++ != 5 || k-- != 6 + || k != 5 ){ + rc = rc+8; + printf(s72er,8); + } + + /* An expression preceded by the parenthesised name of a + data type causes conversion of the value of the expression + to the named type. This construction is called a cast. + Here, we check to see that all of the possible casts and + their simple combinations are accepted by the compiler, + and that they all produce a correct result for this sample + of size one. */ + + c = 26; l = 26; + s = 26; u = 26; + i = 26; + #ifndef NO_FLOATS + f = 26.; + d = 26.; + #else + f = 26; + d = 26; + #endif + + lrc = 0; + + if( (char)s != 26 || (char)i != 26 + || (char)l != 26 || (char)u != 26 + || (char)f != 26 || (char)d != 26 ) lrc = lrc+1; + + if( (short)c != 26 || (short)i != 26 + || (short)l != 26 || (short)u != 26 + || (short)f != 26 || (short)d != 26) lrc = lrc+2; + + if( (int)c != 26 || (int)s != 26 + || (int)l != 26 || (int)u != 26 + || (int)f != 26 || (int)d != 26 ) lrc = lrc+4; + + if( (long)c != 26 || (long)s != 26 + || (long)i != 26 || (long)u != 26 + || (long)f != 26 || (long)d != 26 ) lrc = lrc+8; + + if( (unsigned)c != 26 || (unsigned)s != 26 + || (unsigned)i != 26 || (unsigned)l != 26 + || (unsigned)f != 26 || (unsigned)d != 26 ) lrc = lrc+16; + + #ifndef NO_FLOATS + if( (float)c != 26. || (float)s != 26. + || (float)i != 26. || (float)l != 26. + || (float)u != 26. || (float)d != 26. ) lrc = lrc+32; + + if( (double)c != 26. || (double)s != 26. + || (double)i != 26. || (double)l != 26. + || (double)u != 26. || (double)f != 26. ) lrc = lrc+64; + #endif + + if(lrc != 0){ + rc = rc+16; + printf(s72er,16); + } + + /* The sizeof operator has been tested previously. */ + + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s26(pd0); + case 1: return s72(pd0); + } +} + +#define cq_sections 2 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq757.c b/test/val/cq757.c new file mode 100644 index 000000000..7c898ca5b --- /dev/null +++ b/test/val/cq757.c @@ -0,0 +1,335 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 7.5: Shift operators, 7.6 Relational operators, 7.7 Equality operator + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#define CQ26_INCLUDED +/* + section s26, which pokes around at the hardware + trying to figure out the characteristics of the machine that + it is running on, saves information that is subsequently + used by sections s626, s72, and s757. If this program is + to be broken up into smallish pieces, say for running on + a microcomputer, take care to see that s26 is called before + calling any of the latter three sections. +*/ + +/* + 2.6 Hardware Characteristics +*/ + +#ifndef NO_OLD_FUNC_DECL +s26(pd0) +struct defs *pd0; +{ +#else +s26(struct defs *pd0) { +#endif + static char qs26[8] = "s26 "; + char *ps, *pt; + char c0, c1; + #ifndef NO_FLOATS + float temp, one, delta; + double tempd, oned; + #endif + static char s[] = "%3d bits in %ss.\n"; + static char s2[] = "%e is the least number that can be added to 1. (%s).\n"; + + ps = qs26; + pt = pd0->rfs; + + while(*pt++ = *ps++); + + /* Here, we shake the machinery a little to see what falls + out. First, we find out how many bits are in a char. */ + + pd0->cbits = 0; + c0 = 0; + c1 = 1; + + while(c0 != c1) { + c1 = c1<<1; + pd0->cbits = pd0->cbits+1; + } + /* That information lets us determine the size of everything else. */ + + pd0->ibits = pd0->cbits * sizeof(int); + pd0->sbits = pd0->cbits * sizeof(short); + pd0->lbits = pd0->cbits * sizeof(long); + pd0->ubits = pd0->cbits * sizeof(unsigned); + #ifndef NO_FLOATS + pd0->fbits = pd0->cbits * sizeof(float); + pd0->dbits = pd0->cbits * sizeof(double); + #endif + + /* We have now almost reconstructed the table in section 2.6, the + exception being the range of the floating point hardware. + Now there are just so many ways to conjure up a floating point + representation system that it's damned near impossible to guess + what's going on by writing a program to interpret bit patterns. + Further, the information isn't all that useful, if we consider + the fact that machines that won't handle numbers between 10**30 + and 10**-30 are very hard to find, and that people playing with + numbers outside that range have a lot more to worry about than + just the capacity of the characteristic. + + A much more useful measure is the precision, which can be ex- + pressed in terms of the smallest number that can be added to + 1. without loss of significance. We calculate that here, for + float and double. */ + +#ifndef NO_FLOATS + one = 1.; + delta = 1.; + temp = 0.; + while(temp != one) { + temp = one+delta; + delta = delta/2.; + } + pd0->fprec = delta * 4.; + oned = 1.; + delta = 1.; + tempd = 0.; + while(tempd != oned) { + tempd = oned+delta; + delta = delta/2.; + } + pd0->dprec = delta * 4.; +#endif + + /* Now, if anyone's interested, we publish the results. */ + +#ifndef CQ26_INCLUDED + if(pd0->flgm != 0) { + printf(s,pd0->cbits,"char"); + printf(s,pd0->ibits,"int"); + printf(s,pd0->sbits,"short"); + printf(s,pd0->lbits,"long"); + printf(s,pd0->ubits,"unsigned"); + printf(s,pd0->fbits,"float"); + printf(s,pd0->dbits,"double"); + #ifndef NO_FLOATS + printf(s2,pd0->fprec,"float"); + printf(s2,pd0->dprec,"double"); + #else + printf("NO_FLOATS\n"); + #endif + } +#endif + /* Since we are only exploring and perhaps reporting, but not + testing any features, we cannot return an error code. */ + + return 0; +} + +#ifndef NO_OLD_FUNC_DECL +s757(pd0) /* 7.5 Shift operators */ + /* 7.6 Relational operators */ + /* 7.7 Equality operator */ +struct defs *pd0; +{ +#else +int s757(struct defs *pd0){ +#endif + static char s757er[] = "s757,er%d\n"; + static char qs757[8] = "s757 "; + int rc; + char *ps, *pt; + int t,lrc,k,j,a,b,c,d,x[16],*p; + unsigned rs, ls, rt, lt; + ps = qs757; + pt = pd0->rfs; + rc = 0; + while (*pt++ = *ps++); + + /* The shift operators << and >> group left-to-right. + */ + + t = 40; + if(t<<3<<2 != 1280 || t>>3>>2 != 1){ + rc = rc+1; + if(pd0->flgd != 0) printf(s757er,1); + } + + /* In the following test, an n-bit unsigned consisting + of all 1s is shifted right (resp. left) k bits, 0<=k<n. + We expect to find k 0s followed by n-k 1s (resp. n-k 1s + followed by k 0s). If not, we complain. + */ + + lrc = 0; + for(k=0; k<pd0->ubits; k++){ + rs = 1; + ls = rs<<(pd0->ubits-1); + + rt = 0; + lt = ~rt>>k; + rt = ~rt<<k; + + for(j=0; j<pd0->ubits;j++){ + if((j<k) != ((rs&rt) == 0) || (j<k) != ((ls<) == 0)) lrc = 1; + rs = rs<<1; + ls = ls>>1; + } + } + + if(lrc != 0){ + rc = rc+2; + if(pd0->flgd != 0) printf(s757er,2); + } + + /* The relational operators group left-to-right, but this + fact is not very useful; a<b<c does not mean what it + seems to... + */ + + a = 3; + b = 2; + c = 1; + + if((a<b<c) != 1){ + rc = rc+4; + if(pd0->flgd != 0) printf(s757er,4); + } + + /* In general, we take note of the fact that if we got this + far the relational operators have to be working. We test only + that two pointers may be compared; the result depends on + the relative locations in the address space of the + pointed-to objects. + */ + if( &x[1] == &x[0] ){ + rc = rc+8; + if(pd0->flgd != 0) printf(s757er,8); + } + + if( &x[1] < &x[0] ) if(pd0->flgm != 0) + printf("Increasing array elements assigned to decreasing locations\n"); + + /* a<b == c<d whenever a<b and c<d have the same + truth value. */ + + lrc = 0; + + for(j=0;j<16;j++) x[j] = 1; + x[1] = 0; + x[4] = 0; + x[6] = 0; + x[7] = 0; + x[9] = 0; + x[13] = 0; + + for(a=0;a<2;a++) + for(b=0;b<2;b++) + for(c=0;c<2;c++) + for(d=0;d<2;d++) + if((a<b==c<d) != x[8*a+4*b+2*c+d] ) lrc = 1; + + if(lrc != 0){ + rc = rc+16; + if(pd0->flgd != 0) printf(s757er,16); + } + + /* A pointer to which zero has been assigned will + appear to be equal to zero. + */ + + p = 0; + + if(p != 0){ + rc = rc+32; + if(pd0->flgd != 0) printf(s757er,32); + } + + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s26(pd0); + case 1: return s757(pd0); + } +} + +#define cq_sections 2 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq7813.c b/test/val/cq7813.c new file mode 100644 index 000000000..77d34a2a6 --- /dev/null +++ b/test/val/cq7813.c @@ -0,0 +1,381 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 7.8: Bitwise AND operator, 7.9 Bitwise OR operator, 7.10 Bitwise exclusive OR operator, 7.11 Logical AND operator, 7.12 Logical OR operator, 7.13 Conditional operator + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#ifndef NO_OLD_FUNC_DECL +s7813(pd0) /* 7.8 Bitwise AND operator + 7.9 Bitwise OR operator + 7.10 Bitwise exclusive OR operator + 7.11 Logical AND operator + 7.12 Logical OR operator + 7.13 Conditional operator */ +struct defs *pd0; +{ +#else +int s7813(struct defs *pd0){ +#endif + register int prlc, lrc; + int i, j, r, zero, one; + static char fl[] = "Local error %d.\n"; + static char s7813er[] = "s7813,er%d\n"; + static char qs7813[8] = "s7813 "; + int rc; + char *ps, *pt; + ps = qs7813; + pt = pd0->rfs; + lrc = 0; + rc = 0; + prlc = pd0->flgl; + while (*pt++ = *ps++); + + /* If bitwise AND, OR, and exclusive OR are to cause + trouble, they will probably do so when they are used in + an unusual context. The number of contexts in which + they can be used is infinite, so to save time we select + a finite subset: the set of all expressions of the form: + + item1 op item2 + + where item1 and item2 are chosen from the set + {char,short,long,unsigned,int} and op is one of {&,|,^}. + We will use 12 and 10 as values for the items, as these + values will fit into all data types on just about any + imaginable machine, and the results after performing the + bitwise operations on them are distinct for each operation, + i.e., + + 12 | 10 -> 1100 | 1010 -> 1110 -> 14 + 12 ^ 10 -> 1100 ^ 1010 -> 0110 -> 6 + 12 & 10 -> 1100 & 1010 -> 1000 -> 8 + + There are 75 such combinations: + */ + + if(((char)12 & (char)10) != 8) {lrc = 1; + if(prlc) printf(fl,lrc);} + if(((char)12 | (char)10) != 14) {lrc = 2; + if(prlc) printf(fl,lrc);} + if(((char)12 ^ (char)10) != 6) {lrc = 3; + if(prlc) printf(fl,lrc);} + if(((char)12 & (short)10) != 8) {lrc = 4; + if(prlc) printf(fl,lrc);} + if(((char)12 | (short)10) != 14) {lrc = 5; + if(prlc) printf(fl,lrc);} + if(((char)12 ^ (short)10) != 6) {lrc = 6; + if(prlc) printf(fl,lrc);} + if(((char)12 & (long)10) != 8) {lrc = 7; + if(prlc) printf(fl,lrc);} + if(((char)12 | (long)10) != 14) {lrc = 8; + if(prlc) printf(fl,lrc);} + if(((char)12 ^ (long)10) != 6) {lrc = 9; + if(prlc) printf(fl,lrc);} + if(((char)12 & (unsigned)10) != 8) {lrc = 10; + if(prlc) printf(fl,lrc);} + if(((char)12 | (unsigned)10) != 14) {lrc = 11; + if(prlc) printf(fl,lrc);} + if(((char)12 ^ (unsigned)10) != 6) {lrc = 12; + if(prlc) printf(fl,lrc);} + if(((char)12 & (int)10) != 8) {lrc = 13; + if(prlc) printf(fl,lrc);} + if(((char)12 | (int)10) != 14) {lrc = 14; + if(prlc) printf(fl,lrc);} + if(((char)12 ^ (int)10) != 6) {lrc = 15; + if(prlc) printf(fl,lrc);} + if(((short)12 & (char)10) != 8) {lrc = 16; + if(prlc) printf(fl,lrc);} + if(((short)12 | (char)10) != 14) {lrc = 17; + if(prlc) printf(fl,lrc);} + if(((short)12 ^ (char)10) != 6) {lrc = 18; + if(prlc) printf(fl,lrc);} + if(((short)12 & (short)10) != 8) {lrc = 16; + if(prlc) printf(fl,lrc);} + if(((short)12 | (short)10) != 14) {lrc = 20; + if(prlc) printf(fl,lrc);} + if(((short)12 ^ (short)10) != 6) {lrc = 21; + if(prlc) printf(fl,lrc);} + if(((short)12 & (long)10) != 8) {lrc = 22; + if(prlc) printf(fl,lrc);} + if(((short)12 | (long)10) != 14) {lrc = 23; + if(prlc) printf(fl,lrc);} + if(((short)12 ^ (long)10) != 6) {lrc = 24; + if(prlc) printf(fl,lrc);} + if(((short)12 & (unsigned)10) != 8) {lrc = 25; + if(prlc) printf(fl,lrc);} + if(((short)12 | (unsigned)10) != 14) {lrc = 26; + if(prlc) printf(fl,lrc);} + if(((short)12 ^ (unsigned)10) != 6) {lrc = 27; + if(prlc) printf(fl,lrc);} + if(((short)12 & (int)10) != 8) {lrc = 28; + if(prlc) printf(fl,lrc);} + if(((short)12 | (int)10) != 14) {lrc = 26; + if(prlc) printf(fl,lrc);} + if(((short)12 ^ (int)10) != 6) {lrc = 30; + if(prlc) printf(fl,lrc);} + if(((long)12 & (char)10) != 8) {lrc = 31; + if(prlc) printf(fl,lrc);} + if(((long)12 | (char)10) != 14) {lrc = 32; + if(prlc) printf(fl,lrc);} + if(((long)12 ^ (char)10) != 6) {lrc = 33; + if(prlc) printf(fl,lrc);} + if(((long)12 & (short)10) != 8) {lrc = 34; + if(prlc) printf(fl,lrc);} + if(((long)12 | (short)10) != 14) {lrc = 35; + if(prlc) printf(fl,lrc);} + if(((long)12 ^ (short)10) != 6) {lrc = 36; + if(prlc) printf(fl,lrc);} + if(((long)12 & (long)10) != 8) {lrc = 37; + if(prlc) printf(fl,lrc);} + if(((long)12 | (long)10) != 14) {lrc = 38; + if(prlc) printf(fl,lrc);} + if(((long)12 ^ (long)10) != 6) {lrc = 39; + if(prlc) printf(fl,lrc);} + if(((long)12 & (unsigned)10) != 8) {lrc = 40; + if(prlc) printf(fl,lrc);} + if(((long)12 | (unsigned)10) != 14) {lrc = 41; + if(prlc) printf(fl,lrc);} + if(((long)12 ^ (unsigned)10) != 6) {lrc = 42; + if(prlc) printf(fl,lrc);} + if(((long)12 & (int)10) != 8) {lrc = 43; + if(prlc) printf(fl,lrc);} + if(((long)12 | (int)10) != 14) {lrc = 44; + if(prlc) printf(fl,lrc);} + if(((long)12 ^ (int)10) != 6) {lrc = 45; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 & (char)10) != 8) {lrc = 46; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 | (char)10) != 14) {lrc = 47; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 ^ (char)10) != 6) {lrc = 48; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 & (short)10) != 8) {lrc = 49; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 | (short)10) != 14) {lrc = 50; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 ^ (short)10) != 6) {lrc = 51; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 & (long)10) != 8) {lrc = 52; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 | (long)10) != 14) {lrc = 53; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 ^ (long)10) != 6) {lrc = 54; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 & (unsigned)10) != 8) {lrc = 55; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 | (unsigned)10) != 14) {lrc = 56; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 ^ (unsigned)10) != 6) {lrc = 57; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 & (int)10) != 8) {lrc = 58; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 | (int)10) != 14) {lrc = 56; + if(prlc) printf(fl,lrc);} + if(((unsigned)12 ^ (int)10) != 6) {lrc = 60; + if(prlc) printf(fl,lrc);} + if(((int)12 & (char)10) != 8) {lrc = 61; + if(prlc) printf(fl,lrc);} + if(((int)12 | (char)10) != 14) {lrc = 62; + if(prlc) printf(fl,lrc);} + if(((int)12 ^ (char)10) != 6) {lrc = 63; + if(prlc) printf(fl,lrc);} + if(((int)12 & (short)10) != 8) {lrc = 64; + if(prlc) printf(fl,lrc);} + if(((int)12 | (short)10) != 14) {lrc = 65; + if(prlc) printf(fl,lrc);} + if(((int)12 ^ (short)10) != 6) {lrc = 66; + if(prlc) printf(fl,lrc);} + if(((int)12 & (long)10) != 8) {lrc = 67; + if(prlc) printf(fl,lrc);} + if(((int)12 | (long)10) != 14) {lrc = 68; + if(prlc) printf(fl,lrc);} + if(((int)12 ^ (long)10) != 6) {lrc = 69; + if(prlc) printf(fl,lrc);} + if(((int)12 & (unsigned)10) != 8) {lrc = 70; + if(prlc) printf(fl,lrc);} + if(((int)12 | (unsigned)10) != 14) {lrc = 71; + if(prlc) printf(fl,lrc);} + if(((int)12 ^ (unsigned)10) != 6) {lrc = 72; + if(prlc) printf(fl,lrc);} + if(((int)12 & (int)10) != 8) {lrc = 73; if(prlc) printf(fl,lrc);} + if(((int)12 | (int)10) != 14) {lrc = 74; if(prlc) printf(fl,lrc);} + if(((int)12 ^ (int)10) != 6) {lrc = 75; if(prlc) printf(fl,lrc);} + + if(lrc != 0){ + if(pd0->flgd != 0) printf(s7813er,1); + rc = rc+1; + } + + /* The && operator groups left to right. It returns 1 + if both of the operands are nonzero; 0 otherwise. + It guarantees left to right evaluation; moreover, the + second operand is not evaluated if the value of the + first operand is 0. + */ + + lrc = 0; + i = j = 0; + + r = i++ && j++; + if(i!=1) {lrc = 1; if(prlc) printf(fl,lrc);} + if(j!=0) {lrc = 2; if(prlc) printf(fl,lrc);} + if(r!=0) {lrc = 3; if(prlc) printf(fl,lrc);} + r = i && j++; + if(i!=1) {lrc = 4; if(prlc) printf(fl,lrc);} + if(j!=1) {lrc = 5; if(prlc) printf(fl,lrc);} + if(r!=0) {lrc = 6; if(prlc) printf(fl,lrc);} + r = i-- && j; + if(i!=0) {lrc = 7; if(prlc) printf(fl,lrc);} + if(j!=1) {lrc = 8; if(prlc) printf(fl,lrc);} + if(r!=1) {lrc = 9; if(prlc) printf(fl,lrc);} + r = i && j--; + if(i!=0) {lrc = 10; if(prlc) printf(fl,lrc);} + if(j!=1) {lrc = 11; if(prlc) printf(fl,lrc);} + if(r!=0) {lrc = 12; if(prlc) printf(fl,lrc);} + + if(lrc!=0){ + if(pd0->flgd != 0) printf(s7813er,2); + rc = rc+2; + } + + /* The || operator groups left to right. It returns 1 + if either of its operands is nonzero; 0 otherwise. It + guarantees left to right evaluation; moreover, the second + operand is not evaluated if the value of the first + operand is nonzero. + */ + + lrc = 0; + i = j = 0; + r = i++ || j; + if(i!=1) {lrc = 1; if(prlc) printf(fl,lrc);} + if(j!=0) {lrc = 2; if(prlc) printf(fl,lrc);} + if(r!=0) {lrc = 3; if(prlc) printf(fl,lrc);} + r = j++ || i; + if(i!=1) {lrc = 4; if(prlc) printf(fl,lrc);} + if(j!=1) {lrc = 5; if(prlc) printf(fl,lrc);} + if(r!=1) {lrc = 6; if(prlc) printf(fl,lrc);} + r = i-- || j--; + if(i!=0) {lrc = 7; if(prlc) printf(fl,lrc);} + if(j!=1) {lrc = 8; if(prlc) printf(fl,lrc);} + if(r!=1) {lrc = 9; if(prlc) printf(fl,lrc);} + r = i || j--; + if(i!=0) {lrc = 10; if(prlc) printf(fl,lrc);} + if(j!=0) {lrc = 11; if(prlc) printf(fl,lrc);} + if(r!=1) {lrc = 12; if(prlc) printf(fl,lrc);} + + if(lrc!=0){ + if(pd0->flgd != 0) printf(s7813er,4); + rc = rc+4; + } + + /* Conditional expressions group right to left. */ + + i = j = 0; + zero = 0; + one = 1; + r = one?zero:one?i++:j++; + if(r!=0 || i!=0 || j!=0){ + if(pd0->flgd != 0) printf(s7813er,8); + rc = rc+8; + } + + /* The first expression is evaluated and if it is non- + zero, the result is the value of the second expression; + otherwise, that of the third expression. + */ + + if((one?zero:1) != 0 || (zero?1:zero) != 0){ + if(pd0->flgd != 0) printf(s7813er,16); + rc = rc+16; + } + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s7813(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq81.c b/test/val/cq81.c new file mode 100644 index 000000000..198cbc4f6 --- /dev/null +++ b/test/val/cq81.c @@ -0,0 +1,727 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 8.1: storage class specifiers + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#ifdef NO_IMPLICIT_FUNC_PROTOTYPES +regc(); +regp(); +regi(); +#endif + +#ifndef NO_OLD_FUNC_DECL +s81(pd0) /* 8.1 Storage Class Specifiers */ +struct defs *pd0; +#else +int s81(struct defs *pd0) +#endif +{ + static char s81er[] = "s81,er%d\n"; + static char qs81[8] = "s81 "; + char *ps, *pt; + int k, rc, j, crc, prc, irc; + register char rchar; + char nrchar; + register int *rptr; + int *nrptr; + register int rint; + int nrint; + static char badtest[] = "Register count for %s is unreliable.\n"; + static char goodtest[] = "%d registers assigned to %s variables.\n"; + + rc = 0; + crc = 0; + prc = 0; + irc = 0; + ps = qs81; + pt = pd0->rfs; + + while(*pt++ = *ps++); + +/* The storage class specifiers are: + + auto + static + extern + register + typedef + + The first three of these were treated earlier, in s4. The last + will be checked in s88. "Register" remains. + + There are three flavors of register, viz., char, int and pointer. + We wish first to ascertain that the representations as register + are consistent with the corresponding nonregister representations. + */ + + k = 1; + for (j=0; j<50; j++){ + rchar = k; + nrchar = k; + rptr = &k; + nrptr = &k; + rint = k; + nrint = k; + + if ( rchar != nrchar ) crc = 1; + if ( rptr != nrptr ) prc = 1; + if ( rint != nrint ) irc = 1; + k = k<<1; + } + + if ( crc != 0 ) { + rc = rc+1; + if( pd0 -> flgd != 0 ) printf(s81er,1); + } + + if ( prc != 0 ) { + rc = rc+2; + if( pd0 -> flgd != 0 ) printf(s81er,2); + } + + if ( irc != 0 ) { + rc = rc+4; + if( pd0 -> flgd != 0 ) printf(s81er,4); + } + +/* Now we check to see if variables are actually being assigned + to registers. */ + + k = regc(); + if ( pd0->flgm != 0 ) { + if ( k < 0 ) printf(badtest,"char"); + else printf(goodtest,k,"char"); + } + + k = regp(); + if ( pd0->flgm != 0 ) { + if ( k<0 ) printf(badtest,"pointer"); + else printf(goodtest,k,"pointer"); + } + + k = regi(); + if ( pd0->flgm != 0 ) { + if ( k<0 ) printf(badtest,"int"); + else printf(goodtest,k,"int"); + } + + return rc; +} +regc() { /* char to register assignment */ +/* Testing a variable whose storage class has been spec- +ified as "register" is somewhat tricky, but it can be done in a +fairly reliable fashion by taking advantage of our knowledge of the +ways in which compilers operate. If we declare a collection of vari- +ables of the same storage class, we would expect that, when storage +for these variables is actually allocated, the variables will be +bunched together and ordered according to one of the following +criteria: + + (a) the order in which they were defined. + (b) the order in which they are used. + (c) alphabetically. + (d) the order in which they appear in the compiler's + symbol table. + (e) some other way. + + Hence, if we define a sequence of variables in close alpha- +betical order, and use them in the same order in which we define +them, we would expect the differences between the addresses of +successive variables to be constant, except in case (d) where the +symbol table is a hash table, or in case (e). If a subsequence in +the middle of this sequence is selected, and for this subsequence, +every other variable is specified to be "register", and address +differences are taken between adjacent nonregister variables, we would +still expect to find constant differences if the "register" vari- +ables were actually assigned to registers, and some other diff- +erences if they were not. Specifically, if we had N variables +specified as "register" of which the first n were actually ass- +igned to registers, we would expect the sequence of differences +to consist of a number of occurrences of some number, followed by +N-n occurrences of some other number, followed by several occurr- +ences of the first number. If we get a sequence like this, we can +determine, by simple subtraction, how many (if any) variables are +being assigned to registers. If we get some other sequence, we know +that the test is invalid. */ + + char r00; + char r01; + char r02; + char r03; + register char r04; + char r05; + register char r06; + char r07; + register char r08; + char r09; + register char r10; + char r11; + register char r12; + char r13; + register char r14; + char r15; + register char r16; + char r17; + register char r18; + char r19; + register char r20; + char r21; + register char r22; + char r23; + register char r24; + char r25; + register char r26; + char r27; + register char r28; + char r29; + register char r30; + char r31; + register char r32; + char r33; + register char r34; + char r35; + char r36; + char r37; + char r38; + + int s, n1, n2, nr, j, d[22]; + r00 = 0; + r01 = 1; + r02 = 2; + r03 = 3; + r04 = 4; + r05 = 5; + r06 = 6; + r07 = 7; + r08 = 8; + r09 = 9; + r10 = 10; + r11 = 11; + r12 = 12; + r13 = 13; + r14 = 14; + r15 = 15; + r16 = 16; + r17 = 17; + r18 = 18; + r19 = 19; + r20 = 20; + r21 = 21; + r22 = 22; + r23 = 23; + r24 = 24; + r25 = 25; + r26 = 26; + r27 = 27; + r28 = 28; + r29 = 29; + r30 = 30; + r31 = 31; + r32 = 32; + r33 = 33; + r34 = 34; + r35 = 35; + r36 = 36; + r37 = 37; + r38 = 38; + + d[0] = &r01 - &r00; + d[1] = &r02 - &r01; + d[2] = &r03 - &r02; + d[3] = &r05 - &r03; + d[4] = &r07 - &r05; + d[5] = &r09 - &r07; + d[6] = &r11 - &r09; + d[7] = &r13 - &r11; + d[8] = &r15 - &r13; + d[9] = &r17 - &r15; + d[10] = &r19 - &r17; + d[11] = &r21 - &r19; + d[12] = &r23 - &r21; + d[13] = &r25 - &r23; + d[14] = &r27 - &r25; + d[15] = &r29 - &r27; + d[16] = &r31 - &r29; + d[17] = &r33 - &r31; + d[18] = &r35 - &r33; + d[19] = &r36 - &r35; + d[20] = &r37 - &r36; + d[21] = &r38 - &r37; + +/* The following FSM analyzes the string of differences. It accepts +strings of the form a+b+a+ and returns 16 minus the number of bs, +which is the number of variables that actually got into registers. +Otherwise it signals rejection by returning -1., indicating that the +test is unreliable. */ + + n1 = d[0]; + s = 1; + + for (j=0; j<22; j++) + switch (s) { + case 1: if (d[j] != n1) { + n2 = d[j]; + s = 2; + nr = 1; + } + break; + case 2: if (d[j] == n1) { + s = 3; + break; + } + if (d[j] == n2) { + nr = nr+1; + break; + } + s = 4; + break; + case 3: if (d[j] != n1) s = 4; + break; + } + ; + + if (s == 3) return 16-nr; + else return -1; +} +regi() { /* int to register assignment */ +/* Testing a variable whose storage class has been spec- +ified as "register" is somewhat tricky, but it can be done in a +fairly reliable fashion by taking advantage of our knowledge of the +ways in which compilers operate. If we declare a collection of vari- +ables of the same storage class, we would expect that, when storage +for these variables is actually allocated, the variables will be +bunched together and ordered according to one of the following +criteria: + + (a) the order in which they were defined. + (b) the order in which they are used. + (c) alphabetically. + (d) the order in which they appear in the compiler's + symbol table. + (e) some other way. + + Hence, if we define a sequence of variables in close alpha- +betical order, and use them in the same order in which we define +them, we would expect the differences between the addresses of +successive variables to be constant, except in case (d) where the +symbol table is a hash table, or in case (e). If a subsequence in +the middle of this sequence is selected, and for this subsequence, +every other variable is specified to be "register", and address +differences are taken between adjacent nonregister variables, we would +still expect to find constant differences if the "register" vari- +ables were actually assigned to registers, and some other diff- +erences if they were not. Specifically, if we had N variables +specified as "register" of which the first n were actually ass- +igned to registers, we would expect the sequence of differences +to consist of a number of occurrences of some number, followed by +N-n occurrences of some other number, followed by several occurr- +ences of the first number. If we get a sequence like this, we can +determine, by simple subtraction, how many (if any) variables are +being assigned to registers. If we get some other sequence, we know +that the test is invalid. */ + + int r00; + int r01; + int r02; + int r03; + register int r04; + int r05; + register int r06; + int r07; + register int r08; + int r09; + register int r10; + int r11; + register int r12; + int r13; + register int r14; + int r15; + register int r16; + int r17; + register int r18; + int r19; + register int r20; + int r21; + register int r22; + int r23; + register int r24; + int r25; + register int r26; + int r27; + register int r28; + int r29; + register int r30; + int r31; + register int r32; + int r33; + register int r34; + int r35; + int r36; + int r37; + int r38; + + int s, n1, n2, nr, j, d[22]; + + r00 = 0; + r01 = 1; + r02 = 2; + r03 = 3; + r04 = 4; + r05 = 5; + r06 = 6; + r07 = 7; + r08 = 8; + r09 = 9; + r10 = 10; + r11 = 11; + r12 = 12; + r13 = 13; + r14 = 14; + r15 = 15; + r16 = 16; + r17 = 17; + r18 = 18; + r19 = 19; + r20 = 20; + r21 = 21; + r22 = 22; + r23 = 23; + r24 = 24; + r25 = 25; + r26 = 26; + r27 = 27; + r28 = 28; + r29 = 29; + r30 = 30; + r31 = 31; + r32 = 32; + r33 = 33; + r34 = 34; + r35 = 35; + r36 = 36; + r37 = 37; + r38 = 38; + + d[0] = &r01 - &r00; + d[1] = &r02 - &r01; + d[2] = &r03 - &r02; + d[3] = &r05 - &r03; + d[4] = &r07 - &r05; + d[5] = &r09 - &r07; + d[6] = &r11 - &r09; + d[7] = &r13 - &r11; + d[8] = &r15 - &r13; + d[9] = &r17 - &r15; + d[10] = &r19 - &r17; + d[11] = &r21 - &r19; + d[12] = &r23 - &r21; + d[13] = &r25 - &r23; + d[14] = &r27 - &r25; + d[15] = &r29 - &r27; + d[16] = &r31 - &r29; + d[17] = &r33 - &r31; + d[18] = &r35 - &r33; + d[19] = &r36 - &r35; + d[20] = &r37 - &r36; + d[21] = &r38 - &r37; + +/* The following FSM analyzes the string of differences. It accepts +strings of the form a+b+a+ and returns 16 minus the number of bs, +which is the number of variables that actually got into registers. +Otherwise it signals rejection by returning -1., indicating that the +test is unreliable. */ + + n1 = d[0]; + s = 1; + + for (j=0; j<22; j++) + switch (s) { + case 1: if (d[j] != n1) { + n2 = d[j]; + s = 2; + nr = 1; + } + break; + case 2: if (d[j] == n1) { + s = 3; + break; + } + if (d[j] == n2) { + nr = nr+1; + break; + } + s = 4; + break; + case 3: if (d[j] != n1) s = 4; + break; + } + ; + + if (s == 3) return 16-nr; + else return -1; +} +regp() { /* pointer to register assignment */ +/* Testing a variable whose storage class has been spec- +ified as "register" is somewhat tricky, but it can be done in a +fairly reliable fashion by taking advantage of our knowledge of the +ways in which compilers operate. If we declare a collection of vari- +ables of the same storage class, we would expect that, when storage +for these variables is actually allocated, the variables will be +bunched together and ordered according to one of the following +criteria: + + (a) the order in which they were defined. + (b) the order in which they are used. + (c) alphabetically. + (d) the order in which they appear in the compiler's + symbol table. + (e) some other way. + + Hence, if we define a sequence of variables in close alpha- +betical order, and use them in the same order in which we define +them, we would expect the differences between the addresses of +successive variables to be constant, except in case (d) where the +symbol table is a hash table, or in case (e). If a subsequence in +the middle of this sequence is selected, and for this subsequence, +every other variable is specified to be "register", and address +differences are taken between adjacent nonregister variables, we would +still expect to find constant differences if the "register" vari- +ables were actually assigned to registers, and some other diff- +erences if they were not. Specifically, if we had N variables +specified as "register" of which the first n were actually ass- +igned to registers, we would expect the sequence of differences +to consist of a number of occurrences of some number, followed by +N-n occurrences of some other number, followed by several occurr- +ences of the first number. If we get a sequence like this, we can +determine, by simple subtraction, how many (if any) variables are +being assigned to registers. If we get some other sequence, we know +that the test is invalid. */ + + int *r00; + int *r01; + int *r02; + int *r03; + register int *r04; + int *r05; + register int *r06; + int *r07; + register int *r08; + int *r09; + register int *r10; + int *r11; + register int *r12; + int *r13; + register int *r14; + int *r15; + register int *r16; + int *r17; + register int *r18; + int *r19; + register int *r20; + int *r21; + register int *r22; + int *r23; + register int *r24; + int *r25; + register int *r26; + int *r27; + register int *r28; + int *r29; + register int *r30; + int *r31; + register int *r32; + int *r33; + register int *r34; + int *r35; + int *r36; + int *r37; + int *r38; + + int s, n1, n2, nr, j, d[22]; + + r00 = (int *)&r00; + r01 = (int *)&r01; + r02 = (int *)&r02; + r03 = (int *)&r03; + r04 = (int *)&r05; + r05 = (int *)&r05; + r06 = (int *)&r07; + r07 = (int *)&r07; + r08 = (int *)&r09; + r09 = (int *)&r09; + r10 = (int *)&r11; + r11 = (int *)&r11; + r12 = (int *)&r13; + r13 = (int *)&r13; + r14 = (int *)&r15; + r15 = (int *)&r15; + r16 = (int *)&r17; + r17 = (int *)&r17; + r18 = (int *)&r19; + r19 = (int *)&r19; + r20 = (int *)&r21; + r21 = (int *)&r21; + r22 = (int *)&r23; + r23 = (int *)&r23; + r24 = (int *)&r25; + r25 = (int *)&r25; + r26 = (int *)&r27; + r27 = (int *)&r27; + r28 = (int *)&r29; + r29 = (int *)&r29; + r30 = (int *)&r31; + r31 = (int *)&r31; + r32 = (int *)&r33; + r33 = (int *)&r33; + r34 = (int *)&r35; + r35 = (int *)&r35; + r36 = (int *)&r36; + r37 = (int *)&r37; + r38 = (int *)&r38; + + d[0] = &r01 - &r00; + d[1] = &r02 - &r01; + d[2] = &r03 - &r02; + d[3] = &r05 - &r03; + d[4] = &r07 - &r05; + d[5] = &r09 - &r07; + d[6] = &r11 - &r09; + d[7] = &r13 - &r11; + d[8] = &r15 - &r13; + d[9] = &r17 - &r15; + d[10] = &r19 - &r17; + d[11] = &r21 - &r19; + d[12] = &r23 - &r21; + d[13] = &r25 - &r23; + d[14] = &r27 - &r25; + d[15] = &r29 - &r27; + d[16] = &r31 - &r29; + d[17] = &r33 - &r31; + d[18] = &r35 - &r33; + d[19] = &r36 - &r35; + d[20] = &r37 - &r36; + d[21] = &r38 - &r37; + +/* The following FSM analyzes the string of differences. It accepts +strings of the form a+b+a+ and returns 16 minus the number of bs, +which is the number of variables that actually got into registers. +Otherwise it signals rejection by returning -1., indicating that the +test is unreliable. */ + + n1 = d[0]; + s = 1; + for (j=0; j<22; j++) + switch (s) { + case 1: if (d[j] != n1) { + n2 = d[j]; + s = 2; + nr = 1; + } + break; + case 2: if (d[j] == n1) { + s = 3; + break; + } + if (d[j] == n2) { + nr = nr+1; + break; + } + s = 4; + break; + case 3: if (d[j] != n1) s = 4; + break; + } + ; + + if (s == 3) return 16-nr; + else return -1; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s81(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq84.c b/test/val/cq84.c new file mode 100644 index 000000000..fcadd9af6 --- /dev/null +++ b/test/val/cq84.c @@ -0,0 +1,268 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 8.4: meaning of declarators + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#ifdef NO_SLOPPY_EXTERN + int *fip(int x); + int array(int a[],int size,int start); + int glork(int x); +#endif + +#ifndef NO_OLD_FUNC_DECL +s84(pd0) /* 8.4 Meaning of declarators */ +struct defs *pd0; +{ +#else +int s84(struct defs *pd0){ +#endif +#ifndef NO_SLOPPY_EXTERN + int *ip, i, *fip(), (*pfi)(), j, k, array(), glork(); +#else + int *ip, i, j, k,(*pfi)(); +/* + extern int + *fip(), + array(), + glork(); + int *fip(int x); + int array(int a[],int size,int start); +*/ +#endif + static int x3d[3][5][7]; + #ifndef NO_FLOATS + float fa[17], *afp[17], sum; + #else + signed fa[17], *afp[17], sum; + #endif + static char s84er[] = "s84,er%d\n"; + static char qs84[8] = "s84 "; + int rc; + char *ps, *pt; + ps = qs84; + pt = pd0->rfs; + rc = 0; + while (*pt++ = *ps++); + + /* The more common varieties of declarators have al- + ready been touched upon, some more than others. It + is useful to compare *fip() and (*pfi)(). + */ + + ip = fip(3); + if(*ip != 3){ + if(pd0->flgd != 0) printf(s84er,1); + rc = rc+1; + } + + /* kludges */ + #if defined(FORCE_POINTERS) | defined(NO_OLD_FUNC_DECL) + if(glork(4) != 4){ + if(pd0->flgd != 0) printf(s84er,2); + rc = rc+2; + } + #else + pfi = glork; + if((*pfi)(4) != 4){ + if(pd0->flgd != 0) printf(s84er,2); + rc = rc+2; + } + #endif + + /* Float fa[17] declares an array of floating point + numbers, and *afp[17] declares an array of pointers + to floats. + */ + + for(j=0; j<17; j++){ + fa[j] = j; + afp[j] = &fa[j]; + } + + #ifndef NO_FLOATS + sum = 0.; + #else + sum = 0; + #endif + for(j=0; j<17; j++) sum += *afp[j]; + if(sum != 136){ + if(pd0->flgd != 0) printf(s84er,4); + rc = rc+4; + } + + /* static int x3d[3][5][7] declares a static three + dimensional array of integers, with rank 3x5x7. + In complete detail, x3d is an array of three items; + each item is an array of five arrays, and each of + the latter arrays is an array of seven integers. + Any of the expressions x3d, x3d[i], x3d[i][j], + and x3d[i][j][k] may reasonably appear in an express- + ion. The first three have type "array"; the last has + type int. + */ + + for (i=0; i<3; i++) + for (j=0; j<5; j++) + for (k=0; k<7; k++) + x3d[i][j][k] = i*35+j*7+k; + + i = 1; j = 2; k = 3; + + /* kludges */ + #if defined(FORCE_POINTERS) | defined(NO_OLD_FUNC_DECL) + if( array((int*)x3d,105,0) + +array((int*)x3d[i],35,35) + #else + if( array(x3d,105,0) + +array(x3d[i],35,35) + #endif + +array(x3d[i][j],7,49) + + x3d[i][j][k]-52){ + if(pd0->flgd != 0) printf(s84er,8); + rc = rc+8; + } + + return rc; +} + +#ifndef NO_OLD_FUNC_DECL +array(a,size,start) +int a[],size,start; +#else +int array(int a[],int size,int start) +#endif +{ +/* +#ifndef NO_OLD_FUNC_DECL +array(a,size,start) +int a[], +#else +int array(int a[], +#endif +#ifdef NO_TYPELESS_INT +int +#endif +#ifdef NO_TYPELESS_INT +int +#endif + +#ifndef NO_OLD_FUNC_DECL +start; { +#else +start){ +#endif +*/ + int i; + for(i=0; i<size; i++) + if(a[i] != i+start) return 1; + + return 0; +} +#ifndef NO_OLD_FUNC_DECL +int *fip(x) +int x; +{ +#else +int *fip(int x){ +#endif + static int y; + y = x; + return &y; +} +#ifndef NO_OLD_FUNC_DECL +glork(x) +int x; +{ +#else +int glork(int x){ +#endif +return x;} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s84(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq85.c b/test/val/cq85.c new file mode 100644 index 000000000..3e5ef938d --- /dev/null +++ b/test/val/cq85.c @@ -0,0 +1,313 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 8.5: Structure and Union declarations + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#ifndef NO_OLD_FUNC_DECL +s85(pd0) /* 8.5 Structure and union declarations */ +struct defs *pd0; +{ +#else +int s85(struct defs *pd0){ +#endif + static char s85er[] = "s85,er%d\n"; + static char qs85[8] = "s85 "; + int rc; + char *ps, *pt; + + struct tnode { + char tword[20]; + int count; + struct tnode *left; + struct tnode *right; + }; + + struct tnode s1, s2, *sp; + + struct{ + char cdummy; + char c; + } sc; + + struct{ + char cdummy; + short s; + } ss; + + struct{ + char cdummy; + int i; + } si; + + struct{ + char cdummy; + long l; + } sl; + + struct{ + char cdummy; + unsigned u; + } su; + + struct{ + char cdummy; + #ifndef NO_FLOATS + float f; + #else + signed f; + #endif + } sf; + + struct{ + char cdummy; + #ifndef NO_FLOATS + double d; + #else + signed d; + #endif + } sd; + + int diff[7], j; + + static char *type[] = { + "char", + "short", + "int", + "long", + "unsigned", + #ifdef NO_FLOATS + "signed", + "signed", + #else + "float", + "double" + #endif + }; + + static char aln[] = " alignment: "; + + #ifndef NO_BITFIELDS + struct{ + int twobit:2; + int :1; + int threebit:3; + int onebit:1; + } s3; + #else + struct{ + unsigned char twobit; + unsigned char threebit; + unsigned char onebit; + } s3; + #endif + + union{ + char u1[30]; + short u2[30]; + int u3[30]; + long u4[30]; + unsigned u5[30]; + #ifndef NO_FLOATS + float u6[30]; + double u7[30]; + #else + signed u6[30]; + signed u7[30]; + #endif + } u0; + + ps = qs85; + pt = pd0->rfs; + rc = 0; + while (*pt++ = *ps++); + + /* Within a structure, the objects declared have + addresses which increase as their declarations are + read left to right. + */ + + if( (char *)&s1.count - &s1.tword[0] <= 0 + ||(char *)&s1.left - (char *)&s1.count <= 0 + ||(char *)&s1.right - (char *)&s1.left <= 0){ + if(pd0->flgd != 0) printf(s85er,1); + rc = rc+1; + } + + /* Each non-field member of a structure begins on an + addressing boundary appropriate to its type. + */ + + diff[0] = &sc.c - &sc.cdummy; + diff[1] = (char *)&ss.s - &ss.cdummy; + diff[2] = (char *)&si.i - &si.cdummy; + diff[3] = (char *)&sl.l - &sl.cdummy; + diff[4] = (char *)&su.u - &su.cdummy; + diff[5] = (char *)&sf.f - &sf.cdummy; + diff[6] = (char *)&sd.d - &sd.cdummy; + + if(pd0->flgm != 0) + for(j=0; j<7; j++) + printf("%s%s%d\n",type[j],aln,diff[j]); + + /* Field specifications are highly implementation de- + pendent. About the only thing we can do here is to + check is that the compiler accepts the field constructs, + and that they seem to work, after a fashion, at + run time... + */ + + s3.threebit = 7; + s3.twobit = s3.threebit; + s3.threebit = s3.twobit; + + if(s3.threebit != 3){ + if(s3.threebit == -1){ + if(pd0->flgm != 0) printf("Sign extension in fields\n"); + } + else{ + #ifdef NO_BITFIELDS + if(pd0->flgd != 0) printf("NO_BITFIELDS\n"); + #else + if(pd0->flgd != 0) printf(s85er,2); + rc = rc+2; + #endif + } + } + + s3.onebit = 1; + if(s3.onebit != 1){ + if(pd0->flgm != 0) + printf("Be especially careful with 1-bit fields!\n"); + } + + /* A union may be thought of as a structure all of whose + members begin at offset 0 and whose size is sufficient + to contain any of its members. + */ + + if( (char *)u0.u1 - (char *)&u0 != 0 + ||(char *)u0.u2 - (char *)&u0 != 0 + ||(char *)u0.u3 - (char *)&u0 != 0 + ||(char *)u0.u4 - (char *)&u0 != 0 + ||(char *)u0.u5 - (char *)&u0 != 0 + ||(char *)u0.u6 - (char *)&u0 != 0 + ||(char *)u0.u7 - (char *)&u0 != 0){ + if(pd0->flgd != 0) printf(s85er,4); + rc = rc+4; + } + + if( sizeof u0 < sizeof u0.u1 + ||sizeof u0 < sizeof u0.u2 + ||sizeof u0 < sizeof u0.u3 + ||sizeof u0 < sizeof u0.u4 + ||sizeof u0 < sizeof u0.u5 + ||sizeof u0 < sizeof u0.u6 + ||sizeof u0 < sizeof u0.u7){ + if(pd0->flgd != 0) printf(s85er,8); + rc = rc+8; + } + + /* Finally, we check that the pointers work. */ + + s1.right = &s2; + s2.tword[0] = 2; + s1.right->tword[0] += 1; + if(s2.tword[0] != 3){ + if(pd0->flgd != 0) printf(s85er,16); + rc = rc+16; + } + return rc; +} + +#ifdef NO_LOCAL_PROTOTYPES +int one(); +#endif + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s85(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq86.c b/test/val/cq86.c new file mode 100644 index 000000000..2800307f7 --- /dev/null +++ b/test/val/cq86.c @@ -0,0 +1,228 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 8.6: Initialization + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#ifdef NO_LOCAL_PROTOTYPES +int one(); +#endif + +#ifndef NO_OLD_FUNC_DECL +s86(pd0) /* 8.6 Initialization */ +struct defs *pd0; +{ +#else +int s86(struct defs *pd0){ +#endif + static char s86er[] = "s86,er%d\n"; + static char qs86[8] = "s86 "; + int lrc, rc; + char *ps, *pt; + #ifndef NO_LOCAL_PROTOTYPES + int one(); + #endif + int i, j, k; + static int x[] = {1,3,5}; + static int *pint = x+2; + static int zero[10]; + int *apint = pint-1; + register int *rpint = apint+one(); + + #ifndef NO_FLOATS + static float y0[] = {1,3,5,2,4,6,3,5,7,0,0,0}; + static float y1[4][3] = { + {1,3,5}, + {2,4,6}, + {3,5,7}, + }; + static float y2[4][3] = {1,3,5,2,4,6,3,5,7}; + static float y3[4][3] = { + {1},{2},{3},{4} + }; + #else + static signed y0[] = {1,3,5,2,4,6,3,5,7,0,0,0}; + static signed y1[4][3] = { + {1,3,5}, + {2,4,6}, + {3,5,7}, + }; + #ifndef NO_SLOPPY_STRUCT_INIT + static signed y2[4][3] = {1,3,5,2,4,6,3,5,7}; + #else + static signed y2[4][3] = {{1,3,5},{2,4,6},{3,5,7}}; + #endif + static signed y3[4][3] = { + {1},{2},{3},{4} + }; + #endif + + ps = qs86; + pt = pd0->rfs; + rc = 0; + while (*pt++ = *ps++); + + /* The expression in an initializer for a static or + external variable must be a constant expression or + an expression that reduces to the address of a pre- + viously declared variable, possibly offset by a + constant expression. + */ + + if(*pint != 5){ + if(pd0->flgd != 0) printf(s86er,1); + rc = rc+1; + } + + /* Automatic and register variables may be initialized + by arbitrary expressions involving constants and previously + declared variables and functions. + */ + + if(*apint != 3){ + if(pd0->flgd != 0) printf(s86er,2); + rc = rc+2; + } + + if(*rpint != 5){ + if(pd0->flgd != 0) printf(s86er,4); + rc = rc+4; + } + + /* Static variables that are not initialized are guar- + anteed to start off as zero. + */ + + lrc = 0; + for(j=0; j<10; j++) + if(zero[j] != 0) lrc = 1; + if(lrc != 0){ + if(pd0->flgd != 0) printf(s86er,8); + rc = rc+8; + } + + /* y0, y1, and y2, as declared, should define and + initialize identical arrays. + */ + lrc = 0; + for(i=0; i<4; i++) + for(j=0; j<3; j++){ + k = 3*i+j; + if( y1[i][j] != y2[i][j] + ||y1[i][j] != y0[k]) lrc = 1; + } + + if(lrc != 0){ + if(pd0->flgd != 0) printf(s86er,16); + rc = rc+16; + } + + /* y3 initializes the first column of the array and + leaves the rest zero. + */ + + lrc = 0; + for(j=0; j<4; j++) if(y3[j][0] != j+1) lrc = 1; + + if(lrc != 0){ + if(pd0->flgd != 0) printf(s86er,32); + rc = rc+32; + } + return rc; +} +#ifndef NO_OLD_FUNC_DECL +one(){ +#else +int one(){ +#endif + return 1; +} +int *metricp; + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s86(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq88.c b/test/val/cq88.c new file mode 100644 index 000000000..77bb9e88c --- /dev/null +++ b/test/val/cq88.c @@ -0,0 +1,184 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 8.8: typedef + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +one(){ + return 1; +} +int *metricp; +#ifndef NO_OLD_FUNC_DECL +s88(pd0) /* 8.8 Typedef */ +struct defs *pd0; +{ +#else +int s88(struct defs *pd0){ +#endif + static char s88er[] = "s88,er%d\n"; + static char qs88[8] = "s88 "; + int rc; + char *ps, *pt; + + /* Declarations whose "storage class" is typdef do not + define storage, but instead define identifiers which + can later be used as if they were type keywords naming + fundamental or derived types. + */ + + typedef int MILES, *KLICKSP; + + #ifndef NO_FLOATS + typedef struct {double re, im;} complex; + #else + typedef struct {signed re, im;} complex; + #endif + + MILES distance; + #ifndef NO_SLOPPY_EXTERN + extern KLICKSP metricp; + #else + KLICKSP metricp; + #endif + complex z, *zp; + + ps = qs88; + pt = pd0->rfs; + rc = 0; + while(*pt++ = *ps++); + + /* Hopefully, all of this stuff will compile. After that, + we can only make some superficial tests. + + The type of distance is int, + */ + + if(sizeof distance != sizeof(int)){ + if(pd0->flgd != 0) printf(s88er,1); + rc = rc+1; + } + + /* that of metricp is "pointer to int", */ + + metricp = &distance; + distance = 2; + *metricp = 3; + + if(distance != 3){ + if(pd0->flgd != 0) printf(s88er,2); + rc = rc+2; + } + + /* and that of z is the specified structure. zp is a + pointer to such a structure. + */ + + #ifndef NO_FLOATS + z.re = 0.; + z.im = 0.; + zp = &z; + zp->re = 1.; + zp->im = 1.; + if(z.re+z.im != 2.){ + #else + z.re = 0; + z.im = 0; + zp = &z; + zp->re = 1; + zp->im = 1; + if(z.re+z.im != 2){ + #endif + if(pd0->flgd != 0) printf(s88er,4); + rc = rc+4; + } + + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s88(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/cq9.c b/test/val/cq9.c new file mode 100644 index 000000000..698443ce6 --- /dev/null +++ b/test/val/cq9.c @@ -0,0 +1,154 @@ +/* + !!DESCRIPTION!! C-Manual Chapter 9: Statements + !!ORIGIN!! LCC 4.1 Testsuite + !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC +*/ + +struct defs { + int cbits; /* No. of bits per char */ + int ibits; /* int */ + int sbits; /* short */ + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ +}; + + int lbits; /* long */ + int ubits; /* unsigned */ + int fbits; /* float */ + int dbits; /* double */ + #ifndef NO_FLOATS + float fprec; /* Smallest number that can be */ + float dprec; /* significantly added to 1. */ + #endif + int flgs; /* Print return codes, by section */ + int flgm; /* Announce machine dependencies */ + int flgd; /* give explicit diagnostics */ + int flgl; /* Report local return codes. */ + int rrc; /* recent return code */ + int crc; /* Cumulative return code */ + char rfs[8]; /* Return from section */ + +#ifndef NO_OLD_FUNC_DECL +s9(pd0) /* 9 Statements */ +struct defs *pd0; +{ +#else +int s9(struct defs *pd0){ +#endif + static char s9er[] = "s9,er%d\n"; + static char qs9[8] = "s9 "; + int rc; + char *ps, *pt; + int lrc, i; + + ps = qs9; + pt = pd0->rfs; + rc = 0; + while (*pt++ = *ps++); + + /* One would think that the section on statements would + provide the most variety in the entire sequence of tests. + As it turns out, most of the material in this section has + already been checked in the process of checking out + everything else, and the section at this point is somewhat + anticlimactic. For this reason, we restrict ourselves + to testing two features not already covered. + + Compound statements are delimited by braces. They have the + nice property that identifiers of the auto and register + variety are pushed and popped. It is currently legal to + transfer into a block, but we wont... + */ + + lrc = 0; + for(i=0; i<2; i++){ + int j; + register int k; + j = k = 2; + { + int j; + register int k; + j = k = 3; + if((j != 3) || (k != 3)) lrc = 1; + } + if((j != 2) || (k != 2)) lrc = 1; + } + + if(lrc != 0){ + if(pd0->flgd != 0) printf(s9er,1); + rc = rc+1; + } + + /* Goto statements go to labeled statements, we hope. */ + + goto nobarf; + if(pd0->flgd != 0) printf(s9er,2); + rc = rc+2; + nobarf:; + + return rc; +} + +/********************************************************************************************* + the main loop that launches the sections +*********************************************************************************************/ + +#ifndef NO_TYPELESS_STRUCT_PTR + int section(int j,struct* pd0){ +#else + int section(int j,void* pd0){ +#endif + switch(j){ + case 0: return s9(pd0); + } +} + +#define cq_sections 1 + +/* + C REFERENCE MANUAL (main) +*/ + +#ifndef NO_OLD_FUNC_DECL +main(n,args) +int n; +char **args; +{ +#else +int main(int n,char **args) { +#endif + +int j; +static struct defs d0, *pd0; + + d0.flgs = 1; /* These flags dictate */ + d0.flgm = 1; /* the verbosity of */ + d0.flgd = 1; /* the program. */ + d0.flgl = 1; + + pd0 = &d0; + + for (j=0; j<cq_sections; j++) { + d0.rrc=section(j,pd0); + d0.crc=d0.crc+d0.rrc; + if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); + } + + if(d0.crc == 0) printf("\nNo errors detected.\n"); + else printf("\nFailed.\n"); + + return d0.crc; +} diff --git a/test/val/for.c b/test/val/for.c new file mode 100644 index 000000000..58a608611 --- /dev/null +++ b/test/val/for.c @@ -0,0 +1,109 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int uint0 = 0; +unsigned int uint1 = 0; +unsigned char uchar0 = 0; +unsigned char uchar1 = 0; + +void done() +{ + dummy++; +} + +void for1(void) +{ + unsigned char i=0; + + for(i=0; i<10; i++) + uchar0++; + + if(uchar0 != 10) + failures++; +} + +void for2(void) +{ + unsigned char i=0; + + for(i=0; i<10; i++) + uchar0++; + + if(i < 10) + failures++; +} + +void for3(void) +{ + unsigned int i=0; + + for(i=0; i<10; i++) + uint0++; + + if(i < 10) + failures++; +} + +void for4(void) +{ + for(uint0=1; uint0<10; uint0++) + uchar0++; + + if(uchar0 != 9) + failures++; +} + +void for5(void) +{ + for(uint0=1; uint0<=10; uint0++) + uchar0++; + + if(uchar0 != 10) + failures++; +} + +void inc_uchar0(void) +{ + uchar0++; +} + +void for6(void) +{ + uchar0 = 0; + for(uint0=1; uint0<=10; uint0++) + inc_uchar0(); +} + +int main(void) +{ + for1(); + for2(); + for3(); + uchar0 = 0; + for4(); + uchar0 = 0; + for5(); + + for6(); + if(uchar0 != 10) + failures++; + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/mult1.c b/test/val/mult1.c new file mode 100644 index 000000000..831bde7ec --- /dev/null +++ b/test/val/mult1.c @@ -0,0 +1,117 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +#define TESTLIT 0x05 + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +signed char c1,c2,c3; +unsigned char uc1,uc2,uc3; + +unsigned int ui1,ui2,ui3; +signed int i1,i2; + +void done() +{ + dummy++; +} + +void m1(void) +{ + c1 = c1*5; /* char = char * lit */ + + c2 = c1 *c3; /* char = char * char */ + + uc1= uc1*5; /* uchar = uchar * lit * + uc2=uc1*uc3; /* uchar = uchar * uchar */ + + if(c2 != 25) + failures++; +} + +void m2(unsigned char uc) +{ + uc2 = uc1 * uc; + + if(uc2 != 0x20) + failures++; +} + +void m3(unsigned char uc) +{ + volatile unsigned char vuc; + + /* uchar = uchar * lit */ + /* testing literal multiply with same source and destination */ + vuc = uc; + uc2 = 0; + uc1 = vuc; uc1 = uc1*1; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*2; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*3; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*4; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*5; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*6; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*7; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*8; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*9; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*10; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*11; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*12; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*13; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*14; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*15; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*16; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*17; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*18; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*19; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*20; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*21; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*22; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*23; if( uc1 != (uc2+=TESTLIT) ) failures++; + uc1 = vuc; uc1 = uc1*24; if( uc1 != (uc2+=TESTLIT) ) failures++; + + uc1 = vuc; uc1 = uc1*31; if( uc1 != ((31*TESTLIT) & 0xff) ) failures++; + uc1 = vuc; uc1 = uc1*32; if( uc1 != ((32*TESTLIT) & 0xff) ) failures++; + uc1 = vuc; uc1 = uc1*64; if( uc1 != ((64*TESTLIT) & 0xff) ) failures++; + uc1 = vuc; uc1 = uc1*128;if( uc1 != ((128*TESTLIT)& 0xff) ) failures++; + + /* testing literal multiply with different source and destination */ + uc1 = vuc*1; if( uc1 != ((1*TESTLIT) & 0xff) ) failures++; + uc1 = vuc*2; if( uc1 != ((2*TESTLIT) & 0xff) ) failures++; + uc1 = vuc*4; if( uc1 != ((4*TESTLIT) & 0xff) ) failures++; +} + +int main(void) +{ + dummy = 0; + + c1 = 1; + c3 = 5; + + m1(); + + uc1 = 0x10; + m2(2); + + ui1 = uc1*uc2; /* uint = uchar * uchar */ + + i1 = c1*c2; /* int = char * char */ + + ui3 = ui1*ui2; /* uint = uint * unit */ + + /*m3(TESTLIT);*/ + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/nestfor.c b/test/val/nestfor.c new file mode 100644 index 000000000..735da21de --- /dev/null +++ b/test/val/nestfor.c @@ -0,0 +1,151 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int uint0 = 0; +unsigned int uint1 = 0; +unsigned char uchar0 = 0; +unsigned char uchar1 = 0; + +void dput(unsigned char val) +{ + /*PORTB = val; + PORTA = 0x01; + PORTA = 0x00; + */ +} + +void done() +{ + dummy++; +} + +/* both loops use the loop variable inside the inner loop */ +void for1(void) +{ + unsigned char i, j; + + uchar0 = 0; + uchar1 = 0; + for(i = 0; i < 3; i++) { + uchar0++; + for(j = 0; j < 4; j++) { + uchar1++; + dput(i); + dput(j); + } + } + if(uchar0 != 3) + failures++; + if(uchar1 != 12) + failures++; +} + +/* only the outer loop's variable is used inside, inner can be optimized into a repeat-loop */ +void for2(void) +{ + unsigned char i, j; + + uchar0 = 0; + uchar1 = 0; + for(i = 0; i < 3; i++) { + uchar0++; + for(j = 0; j < 4; j++) { + uchar1++; + dput(i); + } + } + if(uchar0 != 3) + failures++; + if(uchar1 != 12) + failures++; +} + +/* only the inner loop's variable is used inside */ +void for3(void) +{ + unsigned char i, j; + + uchar0 = 0; + uchar1 = 0; + for(i = 0; i < 3; i++) { + uchar0++; + for(j = 0; j < 4; j++) { + uchar1++; + dput(j); + } + } + if(uchar0 != 3) + failures++; + if(uchar1 != 12) + failures++; +} + +/* neither loop variable used inside the loops */ +void for4(void) +{ + unsigned char i, j; + + uchar0 = 0; + uchar1 = 0; + for(i = 0; i < 3; i++) { + uchar0++; + for(j = 0; j < 4; j++) { + uchar1++; + dput(uchar0); + dput(uchar1); + } + } + if(uchar0 != 3) + failures++; + if(uchar1 != 12) + failures++; +} + +/* like for1 but different condition in inner loop */ +void for5(void) +{ + unsigned char i, j; + + uchar0 = 0; + uchar1 = 0; + for(i = 0; i < 3; i++) { + uchar0++; + for(j = 10; j >= 5; j--) { + uchar1++; + dput(i); + dput(j); + } + } + if(uchar0 != 3) + failures++; + if(uchar1 != 18) + failures++; +} + +int main(void) +{ + for1(); + for2(); + for3(); + for4(); + for5(); + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/or1.c b/test/val/or1.c new file mode 100644 index 000000000..9e41d7a39 --- /dev/null +++ b/test/val/or1.c @@ -0,0 +1,192 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#if SUPPORT_BIT_TYPES +bit bit0 = 0; +bit bit1 = 0; +bit bit2 = 0; +#endif + +unsigned int uint0 = 0; +unsigned int uint1 = 0; +unsigned char uchar0 = 0; +unsigned char uchar1 = 0; +unsigned long ulong0 = 0; +unsigned long ulong1 = 0; + +void done() +{ + dummy++; +} + +/* uchar0 = 0; */ +void or_lit2uchar(void) +{ + if(uchar0) + failures++; + + uchar0 |= 1; + + if(uchar0 != 1) + failures++; + + uchar0 |= 2; + + if(uchar0 != 3) + failures++; + + uchar0 |= 0x0e; + + if(uchar0 != 0x0f) + failures++; +} + +void or_lit2uint(void) +{ + if(uint0) + failures++; + + uint0 |= 1; + if(uint0 != 1) + failures++; + + uint0 |= 2; + if(uint0 != 3) + failures++; + + uint0 |= 0x100; + if(uint0 != 0x103) + failures++; + + uint0 |= 0x102; + if(uint0 != 0x103) + failures++; + + uint0 |= 0x303; + if(uint0 != 0x303) + failures++; +} + +void or_lit2ulong(void) +{ + if(ulong0) + failures++; + + ulong0 |= 1; + if(ulong0 != 1) + failures++; + + ulong0 |= 2; + if(ulong0 != 3) + failures++; + + ulong0 |= 0x100; + if(ulong0 != 0x103) + failures++; + + ulong0 |= 0x102; + if(ulong0 != 0x103) + failures++; + + ulong0 |= 0x303; + if(ulong0 != 0x303) + failures++; + + ulong0 |= 0x80000000; + if(ulong0 != 0x80000303) + failures++; +} + +/*-----------*/ +void or_uchar2uchar(void) +{ + uchar0 |= uchar1; + + if(uchar0 != 1) + failures++; + + uchar1 |= 0x0f; + + uchar0 = uchar1 | 0x10; + + if(uchar0 != 0x1f) + failures++; +} + +void or_uint2uint(void) +{ + uint0 |= uint1; + + if(uint0 != 1) + failures++; + + uint1 |= 0x0f; + + uint0 = uint1 | 0x10; + + if(uint0 != 0x1f) + failures++; +} + +#if SUPPORT_BIT_TYPES + +void or_bits1(void) +{ + bit0 = bit0 | bit1 | bit2; +} + +void or_bits2(void) +{ + bit0 = bit1 | bit2; +} +#endif + +int main(void) +{ + or_lit2uchar(); + or_lit2uint(); + or_lit2ulong(); + + uchar0=0; + uchar1=1; + or_uchar2uchar(); + + uint0=0; + uint1=1; + or_uint2uint(); + +#if SUPPORT_BIT_TYPES + or_bits1(); + if(bit0) + failures++; + + or_bits2(); + if(bit0) + failures++; + + bit1=1; + or_bits1(); + if(!bit0) + failures++; + + or_bits2(); + if(!bit0) + failures++; +#endif + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/pointer1.c b/test/val/pointer1.c new file mode 100644 index 000000000..b108bfeb9 --- /dev/null +++ b/test/val/pointer1.c @@ -0,0 +1,134 @@ +/* + !!DESCRIPTION!! Pointer tests + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned char achar0 = 0; +unsigned char achar1 = 0; +unsigned char *acharP = 0; + +char buff[10]; + +void +done () +{ + dummy++; +} + +void +f1 (unsigned char *ucP) +{ + if (ucP == 0) + { + failures++; + return; + } + + if (*ucP) + failures++; +} + +void +f2 (unsigned int *uiP) +{ + if (uiP == 0) + { + failures++; + return; + } + + if (*uiP) + failures++; +} + +unsigned char * +f3 (void) +{ + return &achar0; +} + +void f4(unsigned char *ucP, unsigned char uc) +{ + if(!ucP) { + failures++; + return; + } + + if(*ucP != uc) + failures++; +} + +void init_array(char start_value) +{ + unsigned char c; + + for(c=0; c<sizeof(buff); c++) + buff[c] = start_value++; +} + +void check_array(char base_value) +{ + unsigned char c; + + for(c=0; c<sizeof(buff); c++) + if(buff[c] != (base_value+c)) + failures++; +} + +void index_by_pointer(unsigned char *index, unsigned char expected_value) +{ + if(buff[*index] != expected_value) + failures++; +} + +int +main (void) +{ + init_array(4); + check_array(4); + + if(buff[achar0 + 7] != 4+7) + failures++; + + dummy = buff[achar0]; + + if(dummy != 4) + failures++; + + if(dummy != (buff[achar0+1] -1)) + failures++; + + index_by_pointer(&dummy, 8); + + f1 (&achar0); + f2 (&aint0); + + acharP = f3 (); + if ((acharP == 0) || (*acharP)) + failures++; + achar0 = 42; + if(*acharP != 42) + failures++; + + achar0 = 5; + f4(&achar0, achar0); + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/ptrfunc.c b/test/val/ptrfunc.c new file mode 100644 index 000000000..e1682507a --- /dev/null +++ b/test/val/ptrfunc.c @@ -0,0 +1,136 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int uint0 = 0; +unsigned int uint1 = 0; + +/* + * BUG: if these aren't volatile, an overzealous optimizer or somthing + * wreaks havoc with the simple tests like "if(uchar != 3)failures++" + */ + +#if 0 +unsigned char uchar0 = 0; +unsigned char uchar1 = 0; +unsigned char uchar2 = 0; +#else +volatile unsigned char uchar0 = 0; +volatile unsigned char uchar1 = 0; +volatile unsigned char uchar2 = 0; +#endif + +#ifdef NO_IMPLICIT_FUNCPTR_CONV +void (*pfunc)(void); +void (*p1func)(void); +unsigned char (*pcfunc)(void); +#else +void (*pfunc)(); +void (*p1func)(); +unsigned char (*pcfunc)(); +#endif + +void done() +{ + dummy++; +} + +void call0(void) +{ + uchar0++; +} + +void call1(void) +{ + uchar1++; +} + +unsigned char call2(void) +{ + return uchar0 + 9; +} + +void docall0(void) +{ + pfunc = call0; + (pfunc)(); + if(uchar0 != 1) + failures++; +} + +void docall1() +{ + unsigned char i; + for(i = 0; i < 3; i++) { + (*p1func)(); + } +} + +#ifdef NO_IMPLICIT_FUNCPTR_CONV +void docall2( void(*pf)(void) ) +#else +void docall2( void(*pf)() ) +#endif +{ + unsigned char i; + for(i = 0; i < 2; i++) { + pf(); + } +} + +int main(void) +{ + docall0(); + + p1func = call1; + docall1(); + if(uchar1 != 3) + failures++; + if(uchar0 != 1) + failures++; + + p1func = call0; + docall1(); + if(uchar1 != 3) + failures++; + if(uchar0 != 4) + failures++; + + docall2(call0); + if(uchar1 != 3) + failures++; + if(uchar0 != 6) + failures++; + + docall2(call1); + if(uchar1 != 5) + failures++; + if(uchar0 != 6) + failures++; + + pcfunc = call2; + uchar2 = (*pcfunc)(); + if(uchar2 != 15) + failures++; + + uchar2 += (pcfunc)(); + uchar2 += pcfunc(); + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/rotate1.c b/test/val/rotate1.c new file mode 100644 index 000000000..b7d6e6484 --- /dev/null +++ b/test/val/rotate1.c @@ -0,0 +1,201 @@ +/* + !!DESCRIPTION!! Shift bytes left and right by a constant. + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned char achar0 = 0; +unsigned char achar1 = 0; +unsigned char achar2 = 0; + +void done() +{ + dummy++; +} + +void check(void) +{ + if(achar0 != achar1) + failures++; +} + +void shift_left_1(void) +{ + achar0 <<= 1; + + check(); +} + +void shift_left_2(void) +{ + achar0 <<= 2; + + if(achar0 != achar1) + failures++; +} + +void shift_left_3(void) +{ + achar0 <<= 3; + + if(achar0 != achar1) + failures++; +} + +void shift_left_4(void) +{ + achar0 <<= 4; + + if(achar0 != achar1) + failures++; +} + +void shift_left_5(void) +{ + achar0 <<= 5; + + if(achar0 != achar1) + failures++; +} + +void shift_left_6(void) +{ + achar0 <<= 6; + + if(achar0 != achar1) + failures++; +} + +void shift_left_7(void) +{ + achar0 <<= 7; + + if(achar0 != achar1) + failures++; +} + +void shift_right_1(void) +{ + achar0 >>= 1; + + check(); +} + +void shift_right_2(void) +{ + achar0 >>= 2; + + check(); +} + +void shift_right_3(void) +{ + achar0 >>= 3; + + check(); +} + +void shift_right_4(void) +{ + achar0 >>= 4; + + check(); +} + +void shift_right_5(void) +{ + achar0 >>= 5; + + check(); +} + +void shift_right_6(void) +{ + achar0 >>= 6; + + check(); +} + +void shift_right_7(void) +{ + achar0 >>= 7; + + check(); +} + +int main(void) +{ + /* call with both values zero */ + shift_left_1(); + + achar0 = 1; + achar1 = 2; + for(achar2=0; achar2<6; achar2++) { + shift_left_1(); + achar1 <<=1; + } + + achar0 = 1; + achar1 = 4; + shift_left_2(); + + achar0 = 1; + achar1 = 8; + shift_left_3(); + + achar0 = 1; + achar1 = 0x10; + shift_left_4(); + + achar0 = 1; + achar1 = 0x20; + shift_left_5(); + + achar0 = 1; + achar1 = 0x40; + shift_left_6(); + + achar0 = 1; + achar1 = 0x80; + shift_left_7(); + + achar0 = 2; + achar1 = 1; + shift_right_1(); + + achar0 = 4; + shift_right_2(); + + achar0 = 8; + shift_right_3(); + + achar0 = 0x10; + shift_right_4(); + + achar0 = 0x20; + shift_right_5(); + + achar0 = 0x40; + shift_right_6(); + + achar0 = 0x80; + shift_right_7(); + + success=failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/rotate2.c b/test/val/rotate2.c new file mode 100644 index 000000000..7622736aa --- /dev/null +++ b/test/val/rotate2.c @@ -0,0 +1,71 @@ +/* + !!DESCRIPTION!! Shift bytes left and right by a variable. + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned char achar0 = 0; +unsigned char achar1 = 0; +unsigned char achar2 = 0; +unsigned char achar3 = 0; + +void done() +{ + dummy++; +} + +void shift_right_var(void) +{ + achar0 >>= achar1; +} + +void shift_left_var(void) +{ + achar0 <<= achar1; +} + +void shift_int_left_1(void) +{ + aint0 <<= 1; +} + +int main(void) +{ + char i; + + achar0 = 1; + achar1 = 1; + shift_left_var(); + + if(achar0 !=2) + failures++; + + achar0 = 1; + achar1 = 1; + achar2 = 1; + for(i=0; i<7; i++) { + shift_left_var(); + achar2 <<= 1; + + if(achar2 != achar0) + failures++; + } + + success=failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/rotate3.c b/test/val/rotate3.c new file mode 100644 index 000000000..21b2dc370 --- /dev/null +++ b/test/val/rotate3.c @@ -0,0 +1,384 @@ +/* + !!DESCRIPTION!! Shift ints left and right + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +#ifdef SIZEOF_INT_16BIT +#if defined(__LINUX__) || defined(LINUX) +unsigned short aint0 = 0; +unsigned short aint1 = 0; + +#else +unsigned int aint0 = 0; +unsigned int aint1 = 0; + +#endif + +#else +unsigned int aint0 = 0; +unsigned int aint1 = 0; + +#endif +unsigned char achar0 = 0; +unsigned char achar1 = 0; +unsigned char achar2 = 0; +unsigned char achar3 = 0; + +void done() +{ + dummy++; +} + +void shift_int_left_1(void) +{ + aint0 <<= 1; +} + +void shift_int_left_2(void) +{ + aint0 <<= 2; +} + +void shift_int_left_3(void) +{ + aint0 <<= 3; +} + +void shift_int_left_4(void) +{ + aint0 <<= 4; +} + +void shift_int_left_5(void) +{ + aint0 <<= 5; +} + +void shift_int_left_6(void) +{ + aint0 <<= 6; +} + +void shift_int_left_7(void) +{ + aint0 <<= 7; +} + +void shift_int_left_8(void) +{ + aint0 <<= 8; +} + +void shift_int_left_9(void) +{ + aint0 <<= 9; +} + +void shift_int_left_10(void) +{ + aint0 <<= 10; +} + +void shift_int_left_11(void) +{ + aint0 <<= 11; +} + +void shift_int_left_12(void) +{ + aint0 <<= 12; +} + +void shift_int_left_13(void) +{ + aint0 <<= 13; +} + +void shift_int_left_14(void) +{ + aint0 <<= 14; +} + +void shift_int_left_15(void) +{ + aint0 <<= 15; +} + +/*****************************************************/ +void shift_int_right_1(void) +{ + aint0 >>= 1; +} + +void shift_int_right_2(void) +{ + aint0 >>= 2; +} + +void shift_int_right_3(void) +{ + aint0 >>= 3; +} + +void shift_int_right_4(void) +{ + aint0 >>= 4; +} + +void shift_int_right_5(void) +{ + aint0 >>= 5; +} + +void shift_int_right_6(void) +{ + aint0 >>= 6; +} + +void shift_int_right_7(void) +{ + aint0 >>= 7; +} + +void shift_int_right_8(void) +{ + aint0 >>= 8; +} + +void shift_int_right_9(void) +{ + aint0 >>= 9; +} + +void shift_int_right_10(void) +{ + aint0 >>= 10; +} + +void shift_int_right_11(void) +{ + aint0 >>= 11; +} + +void shift_int_right_12(void) +{ + aint0 >>= 12; +} + +void shift_int_right_13(void) +{ + aint0 >>= 13; +} + +void shift_int_right_14(void) +{ + aint0 >>= 14; +} + +void shift_int_right_15(void) +{ + aint0 >>= 15; +} + +/*****************************************************/ +int main(void) +{ + /*char i;*/ + aint0 = 0xabcd; + + shift_int_left_1(); + if(aint0 != 0x579a) + failures++; + + aint0 = 0xabcd; + + shift_int_left_2(); + if(aint0 != 0xaf34) + failures++; + + aint0 = 0xabcd; + + shift_int_left_3(); + if(aint0 != 0x5e68) + failures++; + + aint0 = 0xabcd; + + shift_int_left_4(); + if(aint0 != 0xbcd0) + failures++; + + aint0 = 0xabcd; + + shift_int_left_5(); + if(aint0 != 0x79a0) + failures++; + + aint0 = 0xabcd; + + shift_int_left_6(); + if(aint0 != 0xf340) + failures++; + + aint0 = 0xabcd; + + shift_int_left_7(); + if(aint0 != 0xe680) + failures++; + + aint0 = 0xabcd; + + shift_int_left_8(); + if(aint0 != 0xcd00) + failures++; + + aint0 = 0xabcd; + + shift_int_left_9(); + if(aint0 != 0x9a00) + failures++; + + aint0 = 0xabcd; + + shift_int_left_10(); + if(aint0 != 0x3400) + failures++; + + aint0 = 0xabcd; + + shift_int_left_11(); + if(aint0 != 0x6800) + failures++; + + aint0 = 0xabcd; + + shift_int_left_12(); + if(aint0 != 0xd000) + failures++; + + aint0 = 0xabcd; + + shift_int_left_13(); + if(aint0 != 0xa000) + failures++; + + aint0 = 0xabcd; + + shift_int_left_14(); + if(aint0 != 0x4000) + failures++; + + aint0 = 0xabcd; + + shift_int_left_15(); + if(aint0 != 0x8000) + failures++; + + /***********************/ + aint0 = 0xabcd; + + shift_int_right_1(); + if(aint0 != 0x55e6) + failures++; + + aint0 = 0xabcd; + + shift_int_right_2(); + if(aint0 != 0x2af3) + failures++; + + aint0 = 0xabcd; + + shift_int_right_3(); + if(aint0 != 0x1579) + failures++; + + aint0 = 0xabcd; + + shift_int_right_4(); + if(aint0 != 0x0abc) + failures++; + + aint0 = 0xabcd; + + shift_int_right_5(); + if(aint0 != 0x055e) + failures++; + + aint0 = 0xabcd; + + shift_int_right_6(); + if(aint0 != 0x02af) + failures++; + + aint0 = 0xabcd; + + shift_int_right_7(); + if(aint0 != 0x0157) + failures++; + + aint0 = 0xabcd; + + shift_int_right_8(); + if(aint0 != 0x00ab) + failures++; + + aint0 = 0xabcd; + + shift_int_right_9(); + if(aint0 != 0x0055) + failures++; + + aint0 = 0xabcd; + + shift_int_right_10(); + if(aint0 != 0x002a) + failures++; + + aint0 = 0xabcd; + + shift_int_right_11(); + if(aint0 != 0x0015) + failures++; + + aint0 = 0xabcd; + + shift_int_right_12(); + if(aint0 != 0x000a) + failures++; + + aint0 = 0xabcd; + + shift_int_right_13(); + if(aint0 != 0x0005) + failures++; + + aint0 = 0xabcd; + + shift_int_right_14(); + if(aint0 != 0x0002) + failures++; + + aint0 = 0xabcd; + + shift_int_right_15(); + if(aint0 != 0x0001) + failures++; + + success=failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/rotate4.c b/test/val/rotate4.c new file mode 100644 index 000000000..09b1ebf4c --- /dev/null +++ b/test/val/rotate4.c @@ -0,0 +1,228 @@ +/* + !!DESCRIPTION!! rotate bytes left and right by a constant. + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +#ifdef SIZEOF_INT_16BIT +#if defined(__LINUX__) || defined(LINUX) +unsigned short aint0 = 0; +unsigned short aint1 = 0; + +#else +unsigned int aint0 = 0; +unsigned int aint1 = 0; + +#endif + +#else +unsigned int aint0 = 0; +unsigned int aint1 = 0; + +#endif +unsigned char uchar0 = 0; +unsigned char uchar1 = 0; +unsigned char uchar2 = 0; + +void done() +{ + dummy++; +} + +void check(void) +{ + if(uchar0 != uchar1) + failures++; +} + +void rotate_left_1(void) +{ + uchar0 = (uchar0<<1) | (uchar0>>7); + + check(); +} + +void rotate_left_2(void) +{ + uchar0 = (uchar0<<2) | (uchar0>>6); + + check(); +} + +void rotate_left_3(void) +{ + uchar0 <<= 3; + + if(uchar0 != uchar1) + failures++; +} + +void rotate_left_4(void) +{ + uchar0 <<= 4; + + if(uchar0 != uchar1) + failures++; +} + +void rotate_left_5(void) +{ + uchar0 <<= 5; + + if(uchar0 != uchar1) + failures++; +} + +void rotate_left_6(void) +{ + uchar0 <<= 6; + + if(uchar0 != uchar1) + failures++; +} + +void rotate_left_7(void) +{ + uchar0 <<= 7; + + if(uchar0 != uchar1) + failures++; +} + +void rotate_right_1(void) +{ + uchar0 = (uchar0>>1) | (uchar0<<7); + + check(); +} + +void rotate_right_2(void) +{ + uchar0 = (uchar0>>2) | (uchar0<<6); + + check(); +} + +void rotate_right_3(void) +{ + uchar0 >>= 3; + + check(); +} + +void rotate_right_4(void) +{ + uchar0 >>= 4; + + check(); +} + +void rotate_right_5(void) +{ + uchar0 >>= 5; + + check(); +} + +void rotate_right_6(void) +{ + uchar0 >>= 6; + + check(); +} + +void rotate_right_7(void) +{ + uchar0 >>= 7; + + check(); +} + +int main(void) +{ + /* call with both values zero */ + rotate_left_1(); + + uchar0 = 1; + uchar1 = 2; + + rotate_left_1(); + + uchar0 = 0x80; + uchar1 = 1; + + rotate_left_1(); + + uchar1 = 2; + for(uchar2=0; uchar2<6; uchar2++) { + rotate_left_1(); + uchar1 <<=1; + } + + uchar0 = 1; + uchar1 = 4; + rotate_left_2(); + + uchar0 = 1; + uchar1 = 8; + rotate_left_3(); + + uchar0 = 1; + uchar1 = 0x10; + rotate_left_4(); + + uchar0 = 1; + uchar1 = 0x20; + rotate_left_5(); + + uchar0 = 1; + uchar1 = 0x40; + rotate_left_6(); + + uchar0 = 1; + uchar1 = 0x80; + rotate_left_7(); + + uchar0 = 2; + uchar1 = 1; + rotate_right_1(); + + uchar0 = 1; + uchar1 = 0x80; + rotate_right_1(); + + uchar0 = 4; + uchar1 = 1; + rotate_right_2(); + + uchar0 = 8; + rotate_right_3(); + + uchar0 = 0x10; + rotate_right_4(); + + uchar0 = 0x20; + rotate_right_5(); + + uchar0 = 0x40; + rotate_right_6(); + + uchar0 = 0x80; + rotate_right_7(); + + success=failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/rotate5.c b/test/val/rotate5.c new file mode 100644 index 000000000..501e2e567 --- /dev/null +++ b/test/val/rotate5.c @@ -0,0 +1,260 @@ +/* + !!DESCRIPTION!! Shift bytes left and right by a constant. + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +#ifdef SIZEOF_INT_16BIT +#if defined(__LINUX__) || defined(LINUX) +signed short aint0 = 0; +signed short aint1 = 0; + +#else +signed int aint0 = 0; +signed int aint1 = 0; + +#endif + +#else +signed int aint0 = 0; +signed int aint1 = 0; + +#endif +signed char achar0 = 0; +signed char achar1 = 0; +signed char achar2 = 0; + +void done() +{ + dummy++; +} + +void check(void) +{ + if(achar0 != achar1) + failures++; +} + +void shift_left_1(void) +{ + achar0 <<= 1; + + check(); +} + +void shift_left_2(void) +{ + achar0 <<= 2; + + if(achar0 != achar1) + failures++; +} + +void shift_left_3(void) +{ + achar0 <<= 3; + + if(achar0 != achar1) + failures++; +} + +void shift_left_4(void) +{ + achar0 <<= 4; + + if(achar0 != achar1) + failures++; +} + +void shift_left_5(void) +{ + achar0 <<= 5; + + if(achar0 != achar1) + failures++; +} + +void shift_left_6(void) +{ + achar0 <<= 6; + + if(achar0 != achar1) + failures++; +} + +void shift_left_7(void) +{ + achar0 <<= 7; + + if(achar0 != achar1) + failures++; +} + +void shift_right_1(void) +{ + achar0 >>= 1; + + check(); +} + +void shift_right_2(void) +{ + achar0 >>= 2; + + check(); +} + +void shift_right_3(void) +{ + achar0 >>= 3; + + check(); +} + +void shift_right_4(void) +{ + achar0 >>= 4; + + check(); +} + +void shift_right_5(void) +{ + achar0 >>= 5; + + check(); +} + +void shift_right_6(void) +{ + achar0 >>= 6; + + check(); +} + +void shift_right_7(void) +{ + achar0 >>= 7; + + check(); +} + +int main(void) +{ + /* call with both values zero */ + shift_left_1(); + printf("failures: %d\n",failures); + + achar0 = 1; + achar1 = 2; + for(achar2=0; achar2<6; achar2++) { + shift_left_1(); + achar1 <<=1; + } + printf("failures: %d\n",failures); + + achar0 = 1; + achar1 = 4; + shift_left_2(); + printf("failures: %d\n",failures); + + achar0 = 1; + achar1 = 8; + shift_left_3(); + printf("failures: %d\n",failures); + + achar0 = 1; + achar1 = 0x10; + shift_left_4(); + printf("failures: %d\n",failures); + + achar0 = 1; + achar1 = 0x20; + shift_left_5(); + printf("failures: %d\n",failures); + + achar0 = 1; + achar1 = 0x40; + shift_left_6(); + printf("failures: %d\n",failures); + + achar0 = 1; + achar1 = 0x80; + shift_left_7(); + printf("failures: %d\n",failures); + + achar0 = 2; + achar1 = 1; + shift_right_1(); + printf("failures: %d\n",failures); + + achar0 = 4; + shift_right_2(); + printf("failures: %d\n",failures); + + achar0 = 8; + shift_right_3(); + printf("failures: %d\n",failures); + + achar0 = 0x10; + shift_right_4(); + printf("failures: %d\n",failures); + + achar0 = 0x20; + shift_right_5(); + printf("failures: %d\n",failures); + + achar0 = 0x40; + shift_right_6(); + printf("failures: %d\n",failures); + + achar0 = 0xff; + achar1 = 0xff; + shift_right_1(); + printf("failures: %d\n",failures); + + achar0 = 0xfe; + achar1 = 0xff; + shift_right_1(); + printf("failures: %d\n",failures); + + achar0 = 0xfc; + shift_right_2(); + printf("failures: %d\n",failures); + + achar0 = 0xf8; + shift_right_3(); + printf("failures: %d\n",failures); + + achar0 = 0xf0; + shift_right_4(); + printf("failures: %d\n",failures); + + achar0 = 0xe0; + shift_right_5(); + printf("failures: %d\n",failures); + + achar0 = 0xc0; + shift_right_6(); + printf("failures: %d\n",failures); + + achar0 = 0x80; + achar1 = 0xff; + shift_right_7(); + + success=failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/rotate6.c b/test/val/rotate6.c new file mode 100644 index 000000000..9109e124e --- /dev/null +++ b/test/val/rotate6.c @@ -0,0 +1,158 @@ +/* + !!DESCRIPTION!! Shift bytes left and right by a variable. + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +#ifdef SIZEOF_INT_16BIT +#if defined(__LINUX__) || defined(LINUX) +signed short aint0 = 0; +signed short aint1 = 0; + +#else +signed int aint0 = 0; +signed int aint1 = 0; + +#endif + +#else +signed int aint0 = 0; +signed int aint1 = 0; + +#endif +signed char achar0 = 0; +signed char achar1 = 0; +signed char achar2 = 0; +signed char achar3 = 0; + +void done() +{ + dummy++; +} + +void shift_right_var(void) +{ + achar0 >>= achar1; +} + +void shift_left_var(void) +{ + achar0 <<= achar1; +} + +void shift_int_left_var(void) +{ + aint0 <<= achar1; +} + +void shift_int_right_var(void) +{ + aint0 >>= achar1; +} + +void shift_int_right_var2(void) +{ + aint0 = aint1 >> achar1; +} + +void shift_int_left_var2(void) +{ + aint0 = aint1 << achar1; +} + +int +main (void) +{ + char i; + + achar0 = 1; + achar1 = 1; + shift_left_var(); + + if(achar0 !=2) + failures++; + printf("failures: %d\n",failures); + + achar0 = 1; + achar1 = 1; + achar2 = 1; + for(i=0; i<7; i++) { + shift_left_var(); + achar2 <<= 1; + + if(achar2 != achar0) + failures++; + } + printf("failures: %d\n",failures); + + achar1 = 4; + achar0 = 0xf0; + shift_right_var(); + if(((unsigned char)achar0) != 0xff) + failures++; + printf("failures: %d\n",failures); + + aint0 = 1; + aint1 = 1; + achar1 = 1; + + for(i=0; i<15; i++) { + shift_int_left_var(); + aint1 <<= 1; + if(aint0 != aint1) + failures++; + } + printf("failures: %d\n",failures); + + aint0 = 0x4000; + aint1 = 0x4000; + + for(i=0; i<15; i++) { + shift_int_right_var(); + aint1 >>= 1; + if(aint0 != aint1) + failures++; + } + printf("failures: %d\n",failures); + + aint0 = -0x4000; + aint1 = -0x4000; + + for(i=0; i<15; i++) { + shift_int_right_var(); + aint1 >>= 1; + if(aint0 != aint1) + failures++; + } + printf("failures: %d\n",failures); + + aint1 = 0xf000; + achar1 = 10; + shift_int_right_var2(); + + if(((unsigned short)aint0) != 0xfffc) + failures++; + printf("failures: %d\n",failures); + + aint1 = aint0; + shift_int_left_var2(); + + if(((unsigned short)aint0) != 0xf000) + failures++; + + success=failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/rotate7.c b/test/val/rotate7.c new file mode 100644 index 000000000..2b30b86dd --- /dev/null +++ b/test/val/rotate7.c @@ -0,0 +1,413 @@ +/* + !!DESCRIPTION!! Shift ints left and right + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SIZEOF_INT_16BIT +#if defined(__LINUX__) || defined(LINUX) +signed short aint0 = 0; +signed short aint1 = 0; + +#else +signed int aint0 = 0; +signed int aint1 = 0; + +#endif + +#else +signed int aint0 = 0; +signed int aint1 = 0; + +#endif + +/* +signed char achar0 = 0; +signed char achar1 = 0; +signed char achar2 = 0; +signed char achar3 = 0; +*/ + +void done() +{ + dummy++; +} + +void shift_int_left_1(void) +{ + aint0 <<= 1; +} + +void shift_int_left_2(void) +{ + aint0 <<= 2; +} + +void shift_int_left_3(void) +{ + aint0 <<= 3; +} + +void shift_int_left_4(void) +{ + aint0 <<= 4; +} + +void shift_int_left_5(void) +{ + aint0 <<= 5; +} + +void shift_int_left_6(void) +{ + aint0 <<= 6; +} + +void shift_int_left_7(void) +{ + aint0 <<= 7; +} + +void shift_int_left_8(void) +{ + aint0 <<= 8; +} + +void shift_int_left_9(void) +{ + aint0 <<= 9; +} + +void shift_int_left_10(void) +{ + aint0 <<= 10; +} + +void shift_int_left_11(void) +{ + aint0 <<= 11; +} + +void shift_int_left_12(void) +{ + aint0 <<= 12; +} + +void shift_int_left_13(void) +{ + aint0 <<= 13; +} + +void shift_int_left_14(void) +{ + aint0 <<= 14; +} + +void shift_int_left_15(void) +{ + aint0 <<= 15; +} + +/*****************************************************/ +void shift_int_right_1(void) +{ + aint0 >>= 1; +} + +void shift_int_right_2(void) +{ + aint0 >>= 2; +} + +void shift_int_right_3(void) +{ + aint0 >>= 3; +} + +void shift_int_right_4(void) +{ + aint0 >>= 4; +} + +void shift_int_right_5(void) +{ + aint0 >>= 5; +} + +void shift_int_right_6(void) +{ + aint0 >>= 6; +} + +void shift_int_right_7(void) +{ + aint0 >>= 7; +} + +void shift_int_right_8(void) +{ + aint0 >>= 8; +} + +void shift_int_right_9(void) +{ + aint0 >>= 9; +} + +void shift_int_right_10(void) +{ + aint0 >>= 10; +} + +void shift_int_right_11(void) +{ + aint0 >>= 11; +} + +void shift_int_right_12(void) +{ + aint0 >>= 12; +} + +void shift_int_right_13(void) +{ + aint0 >>= 13; +} + +void shift_int_right_14(void) +{ + aint0 >>= 14; +} + +void shift_int_right_15(void) +{ + aint0 >>= 15; +} + +/*****************************************************/ +int +main (void) +{ + aint0 = 0xabcd; + + shift_int_left_1(); + if(aint0 != 0x579a) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_2(); + if((unsigned short)aint0 != 0xaf34) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_3(); + if(aint0 != 0x5e68) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_4(); + if((unsigned short)aint0 != 0xbcd0) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_5(); + if(aint0 != 0x79a0) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_6(); + if((unsigned short)aint0 != 0xf340) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_7(); + if((unsigned short)aint0 != 0xe680) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_8(); + if((unsigned short)aint0 != 0xcd00) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_9(); + if((unsigned short)aint0 != 0x9a00) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_10(); + if(aint0 != 0x3400) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_11(); + if(aint0 != 0x6800) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_12(); + if((unsigned short)aint0 != 0xd000) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_13(); + if((unsigned short)aint0 != 0xa000) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_14(); + if(aint0 != 0x4000) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_left_15(); + if((unsigned short)aint0 != 0x8000) + failures++; + printf("failures: %d\n",failures); + + /***********************/ + aint0 = 0xabcd; + + shift_int_right_1(); + if((unsigned short)aint0 != 0xd5e6) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_2(); + if((unsigned short)aint0 != 0xeaf3) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_3(); + if((unsigned short)aint0 != 0xf579) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_4(); + if((unsigned short)aint0 != 0xfabc) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_5(); + if((unsigned short)aint0 != 0xfd5e) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_6(); + if((unsigned short)aint0 != 0xfeaf) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_7(); + if((unsigned short)aint0 != 0xff57) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_8(); + if((unsigned short)aint0 != 0xffab) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_9(); + if((unsigned short)aint0 != 0xffd5) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_10(); + if((unsigned short)aint0 != 0xffea) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_11(); + if((unsigned short)aint0 != 0xfff5) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_12(); + if((unsigned short)aint0 != 0xfffa) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_13(); + if((unsigned short)aint0 != 0xfffd) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_14(); + if((unsigned short)aint0 != 0xfffe) + failures++; + printf("failures: %d\n",failures); + + aint0 = 0xabcd; + + shift_int_right_15(); + if(aint0 != -1) + failures++; + + success=failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/sitest.c b/test/val/sitest.c new file mode 100644 index 000000000..9570f4989 --- /dev/null +++ b/test/val/sitest.c @@ -0,0 +1,1591 @@ +/* + !!DESCRIPTION!! C99 WCHAR test + !!ORIGIN!! + !!LICENCE!! public domain +*/ + +/* + sitest -- exercise features of C99 <stdint.h> and <inttypes.h> + + This source code has been placed into the PUBLIC DOMAIN by its author. + + last edit: 1999/11/05 gwyn@arl.mil + + Tries to accommodate pre-C99 versions of <inttypes.h>. + + Takes advantage of __Q8_* symbols defined by a particular + implementation of <stdint.h>, but doesn't require them. + + NOTE: This is not a thorough validation test of the facilities. +*/ + +#define NO_INTERNAL_WCHAR +/*#define STANDALONE*/ + +#include <errno.h> +#include <limits.h> /* for CHAR_BIT */ +#include <stdio.h> +#include <stddef.h> /* for ptrdiff_t */ +#include <stdlib.h> +#include <string.h> + +#if !defined(STANDARD_C99) && !defined(STANDARD_CC65) + +#error "this test checks C99 features, which are not available in the selected standard." + +#else + +#ifdef NO_WCHAR + +#warn "this test checks C99 features, but NO_WCHAR is defined so the test will most definetly fails." + +#endif + +#include <inttypes.h> /* embeds <stdint.h> */ + +#include <signal.h> /* for sig_atomic_t */ + +#if defined(INTMAX_MAX) /* <inttypes.h> has C99 features */ +#include <wchar.h> +#endif + +#include <inttypes.h> /* test idempotency */ + +#ifdef STANDALONE + +FILE *outfile=NULL; +#define opentest(x) outfile=stdout; +#define closetest(x) + +#else + +#endif + +#if __STDC_VERSION__ >= 199901 +#ifndef __Q8_QT +#define __Q8_QT long long +#endif +#endif + +#ifdef PRIdMAX +#define HAVE_PRIdMAX +#ifndef __Q8_MT +#define __Q8_MT intmax_t +#endif +#else +#ifdef PRIdLEAST64 +#ifndef __Q8_MT +#define __Q8_MT int_least64_t +#endif +#define PRIdMAX PRIdLEAST64 +#else +#ifndef __Q8_MT +#define __Q8_MT long +#endif +#define PRIdMAX "ld" +#endif +#endif + +#ifdef PRIuMAX +#define HAVE_PRIuMAX +#define U__Q8_MT uintmax_t +#else +#ifdef PRIuLEAST64 +#define U__Q8_MT uint_least64_t +#define PRIuMAX PRIuLEAST64 +#else +#define U__Q8_MT unsigned long +#define PRIuMAX "lu" +#endif +#endif + +#define STR_SUB(s) # s +#define STRINGIZE(s) STR_SUB(s) /* extra level to expand argument */ + +#if defined(SCNo32) || defined(PRIo32) +static int32_t int32; +#endif +static int_least16_t intl16; +static uint_least16_t uintl16; +static uint_fast16_t uintf16; +static intmax_t intmax; +static uintmax_t uintmax; + +int +main() { + int status = 0; /* exit status to be returned */ + + + /* <stdint.h> features: */ + + printf("CHAR_BIT=%u\n", (unsigned)CHAR_BIT ); + printf("sizeof(char)=%u\n", (unsigned)sizeof(char)); /* s.b. 1 */ + printf("sizeof(short)=%u\n", (unsigned)sizeof(short)); + printf("sizeof(int)=%u\n", (unsigned)sizeof(int)); + printf("sizeof(long)=%u\n", (unsigned)sizeof(long)); +#ifdef __Q8_QT + printf("sizeof(long long)=%u\n", (unsigned)sizeof(__Q8_QT)); +#else + printf("*** long long isn't defined ***\n"); +#endif + printf("sizeof(intmax_t)=%u\n", (unsigned)sizeof(intmax_t)); + printf("sizeof(ptrdiff_t)=%u\n", (unsigned)sizeof(ptrdiff_t)); + printf("sizeof(size_t)=%u\n", (unsigned)sizeof(size_t)); + printf("sizeof(sig_atomic_t)=%u\n", (unsigned)sizeof(sig_atomic_t)); + printf("sizeof(wchar_t)=%u\n", (unsigned)sizeof(wchar_t)); +#if defined(WINT_MAX) || __STDC_VERSION__ >= 199901 + printf("sizeof(wint_t)=%u\n", (unsigned)sizeof(wint_t)); +#else + printf("*** wint_t isn't defined ***\n"); + status = EXIT_FAILURE; +#endif +#ifdef INT8_MAX + printf("sizeof(int8_t)=%u\n", (unsigned)sizeof(int8_t)); + printf("sizeof(uint8_t)=%u\n", (unsigned)sizeof(uint8_t)); +#endif +#ifdef INT9_MAX + printf("sizeof(int9_t)=%u\n", (unsigned)sizeof(int9_t)); + printf("sizeof(uint9_t)=%u\n", (unsigned)sizeof(uint9_t)); +#endif +#ifdef INT12_MAX + printf("sizeof(int12_t)=%u\n", (unsigned)sizeof(int12_t)); + printf("sizeof(uint12_t)=%u\n", (unsigned)sizeof(uint12_t)); +#endif +#ifdef INT16_MAX + printf("sizeof(int16_t)=%u\n", (unsigned)sizeof(int16_t)); + printf("sizeof(uint16_t)=%u\n", (unsigned)sizeof(uint16_t)); +#endif +#ifdef INT18_MAX + printf("sizeof(int18_t)=%u\n", (unsigned)sizeof(int18_t)); + printf("sizeof(uint18_t)=%u\n", (unsigned)sizeof(uint18_t)); +#endif +#ifdef INT24_MAX + printf("sizeof(int24_t)=%u\n", (unsigned)sizeof(int24_t)); + printf("sizeof(uint24_t)=%u\n", (unsigned)sizeof(uint24_t)); +#endif +#ifdef INT32_MAX + printf("sizeof(int32_t)=%u\n", (unsigned)sizeof(int32_t)); + printf("sizeof(uint32_t)=%u\n", (unsigned)sizeof(uint32_t)); +#endif +#ifdef INT36_MAX + printf("sizeof(int36_t)=%u\n", (unsigned)sizeof(int36_t)); + printf("sizeof(uint36_t)=%u\n", (unsigned)sizeof(uint36_t)); +#endif +#ifdef INT40_MAX + printf("sizeof(int40_t)=%u\n", (unsigned)sizeof(int40_t)); + printf("sizeof(uint40_t)=%u\n", (unsigned)sizeof(uint40_t)); +#endif +#ifdef INT48_MAX + printf("sizeof(int48_t)=%u\n", (unsigned)sizeof(int48_t)); + printf("sizeof(uint48_t)=%u\n", (unsigned)sizeof(uint48_t)); +#endif +#ifdef INT60_MAX + printf("sizeof(int60_t)=%u\n", (unsigned)sizeof(int60_t)); + printf("sizeof(uint60_t)=%u\n", (unsigned)sizeof(uint60_t)); +#endif +#ifdef INT64_MAX + printf("sizeof(int64_t)=%u\n", (unsigned)sizeof(int64_t)); + printf("sizeof(uint64_t)=%u\n", (unsigned)sizeof(uint64_t)); +#endif +#ifdef INT72_MAX + printf("sizeof(int72_t)=%u\n", (unsigned)sizeof(int72_t)); + printf("sizeof(uint72_t)=%u\n", (unsigned)sizeof(uint72_t)); +#endif +#ifdef INT128_MAX + printf("sizeof(int128_t)=%u\n", (unsigned)sizeof(int128_t)); + printf("sizeof(uint128_t)=%u\n", (unsigned)sizeof(uint128_t)); +#endif + printf("sizeof(int_least8_t)=%u\n", (unsigned)sizeof(int_least8_t)); + printf("sizeof(uint_least8_t)=%u\n", (unsigned)sizeof(uint_least8_t)); + printf("sizeof(int_least16_t)=%u\n", (unsigned)sizeof(int_least16_t)); + printf("sizeof(uint_least16_t)=%u\n", (unsigned)sizeof(uint_least16_t)); + printf("sizeof(int_least32_t)=%u\n", (unsigned)sizeof(int_least32_t)); + printf("sizeof(uint_least32_t)=%u\n", (unsigned)sizeof(uint_least32_t)); +#ifdef INT_LEAST64_MAX + printf("sizeof(int_least64_t)=%u\n", (unsigned)sizeof(int_least64_t)); + printf("sizeof(uint_least64_t)=%u\n", (unsigned)sizeof(uint_least64_t)); +#else + printf("*** uint_least64_t isn't defined ***\n"); + status = EXIT_FAILURE; +#endif +#ifdef INT_LEAST128_MAX + printf("sizeof(int_least128_t)=%u\n", (unsigned)sizeof(int_least128_t)); + printf("sizeof(uint_least128_t)=%u\n", + (unsigned)sizeof(uint_least128_t)); +#endif + printf("sizeof(int_fast8_t)=%u\n", (unsigned)sizeof(int_fast8_t)); + printf("sizeof(uint_fast8_t)=%u\n", (unsigned)sizeof(uint_fast8_t)); + printf("sizeof(int_fast16_t)=%u\n", (unsigned)sizeof(int_fast16_t)); + printf("sizeof(uint_fast16_t)=%u\n", (unsigned)sizeof(uint_fast16_t)); + printf("sizeof(int_fast32_t)=%u\n", (unsigned)sizeof(int_fast32_t)); + printf("sizeof(uint_fast32_t)=%u\n", (unsigned)sizeof(uint_fast32_t)); +#ifdef INT_FAST64_MAX + printf("sizeof(int_fast64_t)=%u\n", (unsigned)sizeof(int_fast64_t)); + printf("sizeof(uint_fast64_t)=%u\n", (unsigned)sizeof(uint_fast64_t)); +#else + printf("*** int_fast64_t isn't defined ***\n"); + status = EXIT_FAILURE; +#endif +#ifdef INT_FAST128_MAX + printf("sizeof(int_fast128_t)=%u\n", (unsigned)sizeof(int_fast128_t)); + printf("sizeof(uint_fast128_t)=%u\n", (unsigned)sizeof(uint_fast128_t)); +#endif +#if defined(INTPTR_MAX) + printf("sizeof(intptr_t)=%u\n", (unsigned)sizeof(intptr_t)); +#if defined(UINTPTR_MAX) + printf("sizeof(uintptr_t)=%u\n", (unsigned)sizeof(uintptr_t)); +#else + printf("*** intptr_t is defined but uintptr_t isn't ***\n"); + status = EXIT_FAILURE; +#endif +#elif defined(UINTPTR_MAX) + printf("sizeof(uintptr_t)=%u\n", (unsigned)sizeof(uintptr_t)); + printf("*** uintptr_t is defined but intptr_t isn't ***\n"); + status = EXIT_FAILURE; +#else + printf("*** neither intptr_t nor uintptr_t is defined ***\n"); + status = EXIT_FAILURE; +#endif +#ifdef INTMAX_MAX + printf("sizeof(intmax_t)=%u\n", (unsigned)sizeof(intmax_t)); + printf("sizeof(uintmax_t)=%u\n", (unsigned)sizeof(uintmax_t)); +#else + printf("*** intmax_t isn't defined ***\n"); + status = EXIT_FAILURE; +#endif + +#ifdef INT8_MAX + printf("INT8_MIN=%"PRIdMAX"\n", (__Q8_MT)INT8_MIN); + printf("INT8_MAX=%"PRIdMAX"\n", (__Q8_MT)INT8_MAX); + printf("UINT8_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT8_MAX); +#endif +#ifdef INT9_MAX + printf("INT9_MIN=%"PRIdMAX"\n", (__Q8_MT)INT9_MIN); + printf("INT9_MAX=%"PRIdMAX"\n", (__Q8_MT)INT9_MAX); + printf("UINT9_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT9_MAX); +#endif +#ifdef INT12_MAX + printf("INT12_MIN=%"PRIdMAX"\n", (__Q8_MT)INT12_MIN); + printf("INT12_MAX=%"PRIdMAX"\n", (__Q8_MT)INT12_MAX); + printf("UINT12_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT12_MAX); +#endif +#ifdef INT16_MAX + printf("INT16_MIN=%"PRIdMAX"\n", (__Q8_MT)INT16_MIN); + printf("INT16_MAX=%"PRIdMAX"\n", (__Q8_MT)INT16_MAX); + printf("UINT16_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT16_MAX); +#endif +#ifdef INT18_MAX + printf("INT18_MIN=%"PRIdMAX"\n", (__Q8_MT)INT18_MIN); + printf("INT18_MAX=%"PRIdMAX"\n", (__Q8_MT)INT18_MAX); + printf("UINT18_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT18_MAX); +#endif +#ifdef INT24_MAX + printf("INT24_MIN=%"PRIdMAX"\n", (__Q8_MT)INT24_MIN); + printf("INT24_MAX=%"PRIdMAX"\n", (__Q8_MT)INT24_MAX); + printf("UINT24_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT24_MAX); +#endif +#ifdef INT32_MAX + printf("INT32_MIN=%"PRIdMAX"\n", (__Q8_MT)INT32_MIN); + printf("INT32_MAX=%"PRIdMAX"\n", (__Q8_MT)INT32_MAX); + printf("UINT32_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT32_MAX); +#endif +#ifdef INT36_MAX + printf("INT36_MIN=%"PRIdMAX"\n", (__Q8_MT)INT36_MIN); + printf("INT36_MAX=%"PRIdMAX"\n", (__Q8_MT)INT36_MAX); + printf("UINT36_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT36_MAX); +#endif +#ifdef INT40_MAX + printf("INT40_MIN=%"PRIdMAX"\n", (__Q8_MT)INT40_MIN); + printf("INT40_MAX=%"PRIdMAX"\n", (__Q8_MT)INT40_MAX); + printf("UINT40_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT40_MAX); +#endif +#ifdef INT48_MAX + printf("INT48_MIN=%"PRIdMAX"\n", (__Q8_MT)INT48_MIN); + printf("INT48_MAX=%"PRIdMAX"\n", (__Q8_MT)INT48_MAX); + printf("UINT48_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT48_MAX); +#endif +#ifdef INT60_MAX + printf("INT60_MIN=%"PRIdMAX"\n", (__Q8_MT)INT60_MIN); + printf("INT60_MAX=%"PRIdMAX"\n", (__Q8_MT)INT60_MAX); + printf("UINT60_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT60_MAX); +#endif +#ifdef INT64_MAX + printf("INT64_MIN=%"PRIdMAX"\n", (__Q8_MT)INT64_MIN); + printf("INT64_MAX=%"PRIdMAX"\n", (__Q8_MT)INT64_MAX); + printf("UINT64_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT64_MAX); +#endif +#ifdef INT72_MAX + printf("INT72_MIN=%"PRIdMAX"\n", (__Q8_MT)INT72_MIN); + printf("INT72_MAX=%"PRIdMAX"\n", (__Q8_MT)INT72_MAX); + printf("UINT72_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT72_MAX); +#endif +#ifdef INT128_MAX + printf("INT128_MIN=%"PRIdMAX"\n", (__Q8_MT)INT128_MIN); + printf("INT128_MAX=%"PRIdMAX"\n", (__Q8_MT)INT128_MAX); + printf("UINT128_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT128_MAX); +#endif + printf("INT_LEAST8_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST8_MIN); + printf("INT_LEAST8_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST8_MAX); + printf("UINT_LEAST8_MAX=%"PRIuMAX"\n", + (U__Q8_MT)UINT_LEAST8_MAX); + printf("INT_LEAST16_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST16_MIN); + printf("INT_LEAST16_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST16_MAX); + printf("UINT_LEAST16_MAX=%"PRIuMAX"\n", + (U__Q8_MT)UINT_LEAST16_MAX); + printf("INT_LEAST32_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST32_MIN); + printf("INT_LEAST32_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST32_MAX); + printf("UINT_LEAST32_MAX=%"PRIuMAX"\n", + (U__Q8_MT)UINT_LEAST32_MAX); +#ifdef INT_LEAST64_MAX + printf("INT_LEAST64_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST64_MIN); + printf("INT_LEAST64_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST64_MAX); + printf("UINT_LEAST64_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_LEAST64_MAX); +#endif +#ifdef INT_LEAST128_MAX + printf("INT_LEAST128_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST128_MIN); + printf("INT_LEAST128_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST128_MAX); + printf("UINT_LEAST128_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_LEAST128_MAX); +#endif + printf("INT_FAST8_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_FAST8_MIN); + printf("INT_FAST8_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_FAST8_MAX); + printf("UINT_FAST8_MAX=%"PRIuMAX"\n", + (U__Q8_MT)UINT_FAST8_MAX); + printf("INT_FAST16_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_FAST16_MIN); + printf("INT_FAST16_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_FAST16_MAX); + printf("UINT_FAST16_MAX=%"PRIuMAX"\n", + (U__Q8_MT)UINT_FAST16_MAX); + printf("INT_FAST32_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_FAST32_MIN); + printf("INT_FAST32_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_FAST32_MAX); + printf("UINT_FAST32_MAX=%"PRIuMAX"\n", + (U__Q8_MT)UINT_FAST32_MAX); +#ifdef INT_FAST64_MAX + printf("INT_FAST64_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_FAST64_MIN); + printf("INT_FAST64_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_FAST64_MAX); + printf("UINT_FAST64_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_FAST64_MAX); +#endif +#ifdef INT_FAST128_MAX + printf("INT_FAST128_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_FAST128_MIN); + printf("INT_FAST128_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_FAST128_MAX); + printf("UINT_FAST128_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_FAST128_MAX); +#endif +#ifdef INTPTR_MAX + printf("INTPTR_MIN=%"PRIdMAX"\n", (__Q8_MT)INTPTR_MIN); + printf("INTPTR_MAX=%"PRIdMAX"\n", (__Q8_MT)INTPTR_MAX); +#endif +#ifdef UINTPTR_MAX + printf("UINTPTR_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINTPTR_MAX); +#endif +#ifdef INTMAX_MAX + printf("INTMAX_MIN=%"PRIdMAX"\n", (__Q8_MT)INTMAX_MIN); + printf("INTMAX_MAX=%"PRIdMAX"\n", (__Q8_MT)INTMAX_MAX); + printf("UINTMAX_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINTMAX_MAX); +#endif +#ifdef PTRDIFF_MAX + printf("PTRDIFF_MIN=%"PRIdMAX"\n", (__Q8_MT)PTRDIFF_MIN); + printf("PTRDIFF_MAX=%"PRIdMAX"\n", (__Q8_MT)PTRDIFF_MAX); +#endif +#ifdef SIG_ATOMIC_MAX +#if SIG_ATOMIC_MIN < 0 + printf("SIG_ATOMIC_MIN=%"PRIdMAX"\n", (__Q8_MT)SIG_ATOMIC_MIN); + printf("SIG_ATOMIC_MAX=%"PRIdMAX"\n", (__Q8_MT)SIG_ATOMIC_MAX); +#else + printf("SIG_ATOMIC_MIN=%"PRIuMAX"\n", (U__Q8_MT)SIG_ATOMIC_MIN); + printf("SIG_ATOMIC_MAX=%"PRIuMAX"\n", (U__Q8_MT)SIG_ATOMIC_MAX); +#endif +#endif +#ifdef SIZE_MAX + printf("SIZE_MAX=%"PRIuMAX"\n", (U__Q8_MT)SIZE_MAX); +#endif + +#ifdef WCHAR_MAX +#if WCHAR_MIN < 0 + printf("WCHAR_MIN=%"PRIdMAX"\n", (__Q8_MT)WCHAR_MIN); + printf("WCHAR_MAX=%"PRIdMAX"\n", (__Q8_MT)WCHAR_MAX); +#else + printf("WCHAR_MIN=%"PRIuMAX"\n", (U__Q8_MT)WCHAR_MIN); + printf("WCHAR_MAX=%"PRIuMAX"\n", (U__Q8_MT)WCHAR_MAX); +#endif +#endif +#ifdef WINT_MAX +#if WINT_MIN < 0 + printf("WINT_MIN=%"PRIdMAX"\n", (__Q8_MT)WINT_MIN); + printf("WINT_MAX=%"PRIdMAX"\n", (__Q8_MT)WINT_MAX); +#else + printf("WINT_MIN=%"PRIuMAX"\n", (U__Q8_MT)WINT_MIN); + printf("WINT_MAX=%"PRIuMAX"\n", (U__Q8_MT)WINT_MAX); +#endif +#endif + + /* + 7.18.4 Macros for integer constants + */ + + /* INTn_C for n=8 and 16 were at one point unimplementable + on most platforms, so they're treated as "optional": */ +#ifdef INT8_C + if ( INT8_C(-123) != -123 ) + printf("*** INT8_C(-123) produced %"PRIdMAX" ***\n", + (__Q8_MT)INT8_C(-123) + ); + if ( UINT8_C(123) != 123 ) + printf("*** UINT8_C(123) produced %"PRIuMAX" ***\n", + (U__Q8_MT)UINT8_C(123) + ); +#endif +#ifdef INT16_C + if ( INT16_C(-12345) != -12345 ) + printf("*** INT16_C(-12345) produced %"PRIdMAX" ***\n", + (__Q8_MT)INT16_C(-12345) + ); + if ( UINT16_C(12345) != 12345 ) + printf("*** UINT16_C(12345) produced %"PRIuMAX" ***\n", + (U__Q8_MT)UINT16_C(12345) + ); +#endif + if ( INT32_C(-123456789) != -123456789 ) + printf("*** INT32_C(-123456789) produced %"PRIdMAX" ***\n", + (__Q8_MT)INT32_C(-123456789) + ); + if ( UINT32_C(123456789) != 123456789 ) + printf("*** UINT32_C(123456789) produced %"PRIuMAX" ***\n", + (U__Q8_MT)UINT32_C(123456789) + ); +#ifdef INT_LEAST64_MAX + if ( INT64_C(-1234567890123456789) != -1234567890123456789 ) + printf("*** INT64_C(-1234567890123456789) produced %"PRIdMAX + " ***\n", + (__Q8_MT)INT64_C(-1234567890123456789) + ); + if ( UINT64_C(1234567890123456789) != 1234567890123456789 ) + printf("*** UINT64_C(1234567890123456789) produced %"PRIuMAX + " ***\n", + (U__Q8_MT)UINT64_C(1234567890123456789) + ); +#endif +#ifdef INTMAX_MAX + if ( INTMAX_C(-1234567890123456789) != -1234567890123456789 ) + printf("*** INTMAX_C(-1234567890123456789) produced %"PRIdMAX + " ***\n", + (__Q8_MT)INTMAX_C(-1234567890123456789) + ); + if ( UINTMAX_C(1234567890123456789) != 1234567890123456789 ) + printf("*** UINTMAX_C(1234567890123456789) produced %"PRIuMAX + " ***\n", + (U__Q8_MT)UINTMAX_C(1234567890123456789) + ); +#endif + + /* <inttypes.h> features: */ + +#if __STDC_VERSION__ >= 199901 + printf("sizeof(imaxdiv_t)=%u\n", (unsigned)sizeof(imaxdiv_t)); +#endif + + /* + 7.8.1 Macros for format specifiers + */ + + { + /* scanf these strings */ + static const char in_dn[] = "Z119bZ"; + static const char in_dmo[] = "Z-0119bZ"; + static const char in_dspx[] = "Z \t\n +0X119bZ"; + static const char in_dsmx[] = "Z \t\n -0x119bZ"; + static const char in_dsn[] = "Z \t\n 119bZ"; + static const char in_dp[] = "Z+119bZ"; + static const char in_dpx[] = "Z+0X119bz"; + + /* sprintf into this */ + static char buffer[1024]; + +#if 1 + +#define SCAN(buf,fs,var,exp) if ( sscanf(buf, "Z%" fs, &var) != 1 ) \ + { \ + printf("***%s=",fs, STR_SUB(fs) \ + " failed ***\n" \ + ); \ + status = EXIT_FAILURE; \ + } \ + else if ( var != (exp) ) \ + { \ + printf("***%s=",fs, STR_SUB(fs) \ + " should be: " STR_SUB(exp) \ + ", was: %" fs " ***\n", var \ + ); \ + status = EXIT_FAILURE; \ + } \ + else /* for trailing semicolon */ + +#define PRINT(fs,var,exp) if ( sprintf(buffer, "%" fs, var ) <= 0 ) \ + { \ + printf("***%s=",fs, STR_SUB(fs) \ + " failed ***\n" \ + ); \ + status = EXIT_FAILURE; \ + } \ + else if ( strcmp(buffer, STR_SUB(exp)) != 0 ) \ + { \ + printf("***%s=",fs, STR_SUB(fs) \ + " should be: " STR_SUB(exp) \ + ", was: %s ***\n", buffer \ + ); \ + status = EXIT_FAILURE; \ + } \ + else /* for trailing semicolon */ + +#else + +#define SCAN(buf,fs,var,exp) +#define PRINT(fs,var,exp) + +#endif + +#ifdef SCNo32 + + SCAN(in_dn, SCNo32, int32, 9); + +#endif +#ifdef PRIo32 + PRINT(PRIo32, int32, 11); +#endif + SCAN(in_dmo, SCNiLEAST16, intl16, -9); + SCAN(in_dspx, SCNdLEAST16, intl16, 0); + SCAN(in_dsmx, SCNiLEAST16, intl16, -4507); + PRINT(PRIdLEAST16, intl16, -4507); + PRINT(PRIiLEAST16, intl16, -4507); + SCAN(in_dsn, SCNxLEAST16, uintl16, 4507); + PRINT(PRIoLEAST16, uintl16, 10633); + PRINT(PRIuLEAST16, uintl16, 4507); + PRINT(PRIxLEAST16, uintl16, 119b); + PRINT(PRIXLEAST16, uintl16, 119B); + SCAN(in_dp, SCNxFAST16, uintf16, 4507); + PRINT(PRIxFAST16, uintf16, 119b); +#ifdef SCNdMAX + SCAN(in_dp, SCNdMAX, intmax, 119); +#endif +#ifdef PRIiMAX + PRINT(PRIiMAX, intmax, 119); +#endif +#ifdef SCNoMAX + SCAN(in_dpx, SCNoMAX, uintmax, 0); +#endif +#ifdef PRIxMAX + PRINT(PRIxMAX, uintmax, 0); +#endif + /* Obviously there should be a much larger battery of such tests. */ + } + +#if defined(INTMAX_MAX) /* <inttypes.h> has C99 features */ + /* + 7.8.2 Functions for greatest-width integer types + */ + + { + static struct + { + intmax_t input; + intmax_t expect; + } abs_data[] = + { +#ifdef INT8_MAX + { INT8_MAX, INT8_MAX, }, + { -INT8_MAX, INT8_MAX, }, + { UINT8_MAX, UINT8_MAX, }, +#endif + +#if 0 + +#ifdef INT16_MAX + { INT16_MAX, INT16_MAX, }, + { -INT16_MAX, INT16_MAX, }, + { UINT16_MAX, UINT16_MAX, }, +#endif +#ifdef INT32_MAX + { INT32_MAX, INT32_MAX, }, + { -INT32_MAX, INT32_MAX, }, +#ifdef INT_LEAST64_MAX /* else might support only 32 bits */ + { UINT32_MAX, UINT32_MAX, }, +#endif +#endif +#ifdef INT64_MAX + { INT64_MAX, INT64_MAX, }, + { -INT64_MAX, INT64_MAX, }, +#endif + { INT_LEAST8_MAX, INT_LEAST8_MAX, }, + { -INT_LEAST8_MAX, INT_LEAST8_MAX, }, + { UINT_LEAST8_MAX, UINT_LEAST8_MAX, }, + { INT_LEAST16_MAX, INT_LEAST16_MAX, }, + { -INT_LEAST16_MAX, INT_LEAST16_MAX, }, + { UINT_LEAST16_MAX, UINT_LEAST16_MAX, }, + { INT_LEAST32_MAX, INT_LEAST32_MAX, }, + { -INT_LEAST32_MAX, INT_LEAST32_MAX, }, +#ifdef INT_LEAST64_MAX + { UINT_LEAST32_MAX, UINT_LEAST32_MAX, }, + { INT_LEAST64_MAX, INT_LEAST64_MAX, }, + { -INT_LEAST64_MAX, INT_LEAST64_MAX, }, +#endif + { INT_FAST8_MAX, INT_FAST8_MAX, }, + { -INT_FAST8_MAX, INT_FAST8_MAX, }, + { UINT_FAST8_MAX, UINT_FAST8_MAX, }, + { INT_FAST16_MAX, INT_FAST16_MAX, }, + { -INT_FAST16_MAX, INT_FAST16_MAX, }, + { UINT_FAST16_MAX, UINT_FAST16_MAX, }, + { INT_FAST32_MAX, INT_FAST32_MAX, }, + { -INT_FAST32_MAX, INT_FAST32_MAX, }, +#ifdef INT_FAST64_MAX + { UINT_FAST32_MAX, UINT_FAST32_MAX, }, + { INT_FAST64_MAX, INT_FAST64_MAX, }, + { -INT_FAST64_MAX, INT_FAST64_MAX, }, +#endif +#ifdef INTPTR_MAX + { INTPTR_MAX, INTPTR_MAX, }, + { -INTPTR_MAX, INTPTR_MAX, }, +#endif +#ifdef UINTPTR_MAX + { UINTPTR_MAX, UINTPTR_MAX, }, +#endif + { INTMAX_MAX, INTMAX_MAX, }, +#ifdef PTRDIFF_MAX + { PTRDIFF_MAX, PTRDIFF_MAX, }, +#endif +#ifdef SIG_ATOMIC_MAX + { SIG_ATOMIC_MAX, SIG_ATOMIC_MAX, }, +#if SIG_ATOMIC_MIN < 0 + { -SIG_ATOMIC_MAX, SIG_ATOMIC_MAX, }, +#endif +#endif +#ifdef SIZE_MAX + { SIZE_MAX, SIZE_MAX, }, +#endif +#ifdef WCHAR_MAX + { WCHAR_MAX, WCHAR_MAX, }, +#if WCHAR_MIN < 0 + { -WCHAR_MAX, WCHAR_MAX, }, +#endif +#endif +#ifdef WINT_MAX + { WINT_MAX, WINT_MAX, }, +#if WINT_MIN < 0 + { -WINT_MAX, WINT_MAX, }, +#endif +#endif + { 127, 127, }, + { -127, 127, }, + { 128, 128, }, + { -127-1, 128, }, + { 255, 255, }, + { -256+1, 255, }, + { 256, 256, }, + { -256, 256, }, + { 32767, 32767, }, + { -32767, 32767, }, + { 32768, 32768, }, + { -32767-1, 32768, }, + { 65535, 65535, }, + { -65536+1, 65535, }, + { 65536, 65536, }, + { -65536, 65536, }, + { 2147483647, 2147483647, }, + { -2147483647, 2147483647, }, + { 2147483648, 2147483648, }, + { -2147483647-1, 2147483648, }, +#ifdef INT_LEAST64_MAX /* else might support only 32 bits */ + { 4294967295, 4294967295, }, + { -4294967296+1, 4294967295, }, + { 4294967296, 4294967296, }, + { -4294967296, 4294967296, }, + { 9223372036854775807, 9223372036854775807, }, + { -9223372036854775807, 9223372036854775807, }, + { 1234567890123456789, 1234567890123456789, }, + { -1234567890123456789, 1234567890123456789, }, +#endif + { 1, 1, }, + { -1, 1, }, + { 2, 2, }, + { -2, 2, }, + { 10, 10, }, + { -10, 10, }, + { 16, 16, }, + { -16, 16, }, +#endif + /* Other test cases can be added here. */ + { 0, 0 /* terminates the list */ }, + }, *adp = abs_data; + + do { + if ( (intmax = imaxabs(adp->input)) != adp->expect ) + { + printf("*** imaxabs(%"PRIdMAX") failed; should be: %" + PRIdMAX", was: %"PRIdMAX" ***\n", + adp->input, adp->expect, intmax + ); + status = EXIT_FAILURE; + } +// } while ( adp++->input != 0 ); + } while ( (adp++)->input != 0 ); + } + + { + imaxdiv_t result; + static struct + { + intmax_t numer; + intmax_t denom; + intmax_t exp_quot; + intmax_t exp_rem; + } div_data[] = + { + { 0, 1, 0, 0, }, +#if 0 + { 0, -1, 0, 0, }, + { 0, 2, 0, 0, }, + { 0, -2, 0, 0, }, + { 0, 5, 0, 0, }, + { 0, -5, 0, 0, }, + { 1, 1, 1, 0, }, + { 1, -1, -1, 0, }, + { 1, 2, 0, 1, }, + { 1, -2, 0, 1, }, + { 1, 5, 0, 1, }, + { 1, -5, 0, 1, }, + { -1, 1, -1, 0, }, + { -1, -1, 1, 0, }, + { -1, 2, 0, -1, }, + { -1, -2, 0, -1, }, + { -1, 5, 0, -1, }, + { -1, -5, 0, -1, }, + { 2, 1, 2, 0, }, + { 2, -1, -2, 0, }, + { 2, 2, 1, 0, }, + { 2, -2, -1, 0, }, + { 2, 5, 0, 2, }, + { 2, -5, 0, 2, }, + { -2, 1, -2, 0, }, + { -2, -1, 2, 0, }, + { -2, 2, -1, 0, }, + { -2, -2, 1, 0, }, + { -2, 5, 0, -2, }, + { -2, -5, 0, -2, }, + { 17, 5, 3, 2, }, + { -17, -5, 3, -2, }, + { 17, -5, -3, 2, }, + { -17, 5, -3, -2, }, + { 2147483647, 1, 2147483647, 0, }, + { -2147483647, 1, -2147483647, 0, }, + { 2147483648, 1, 2147483648, 0, }, + { -2147483647-1, 1, -2147483647-1, 0, }, + { 2147483647, 2, 1073741823, 1, }, + { -2147483647, 2, -1073741823, -1, }, + { 2147483648, 2, 1073741824, 0, }, + { -2147483647-1, 2, -1073741824, 0, }, +#ifdef INT_LEAST64_MAX /* else might support only 32 bits */ + { 4294967295, 1, 4294967295, 0, }, + { -4294967296+1, 1, -4294967296+1, 0, }, + { 4294967296, 1, 4294967296, 0, }, + { -4294967296, 1, -4294967296, 0, }, + { 4294967295, -1, -4294967296+1, 0, }, + { -4294967296+1, -1, 4294967295, 0, }, + { 4294967296, -1, -4294967296, 0, }, + { -4294967296, -1, 4294967296, 0, }, + { 4294967295, 2, 2147483647, 1, }, + { -4294967296+1, 2, -2147483647, -1, }, + { 4294967296, 2, 2147483648, 0, }, + { -4294967296, 2, -2147483647-1, 0, }, + { 4294967295, 2147483647, 2, 1, }, + { -4294967296+1, 2147483647, -2, -1, }, + { 4294967296, 2147483647, 2, 2, }, + { -4294967296, 2147483647, -2, -2, }, + { 4294967295, -2147483647, -2, 1, }, + { -4294967296+1, -2147483647, 2, -1, }, + { 4294967296, -2147483647, -2, 2, }, + { -4294967296, -2147483647, 2, -2, }, + { 4294967295, 2147483648, 1, 2147483647, }, + { -4294967296+1, 2147483648, -1, -2147483647, }, + { 4294967296, 2147483648, 2, 0, }, + { -4294967296, 2147483648, -2, 0, }, + { 4294967295, -2147483647-1, -1, 2147483647, }, + { -4294967296+1, -2147483647-1, 1, -2147483647,}, + { 4294967296, -2147483647-1, -2, 0, }, + { -4294967296, -2147483647-1, 2, 0, }, + { 9223372036854775807, 1, 9223372036854775807, 0, }, + { -9223372036854775807, 1, -9223372036854775807, 0, }, + { 9223372036854775807, 2, 4611686018427387903, 1, }, + { -9223372036854775807, 2, -4611686018427387903, -1, }, +#endif +#endif + /* There should be a much larger battery of such tests. */ + { 0, 0, 0, 0 }, /* 0 denom terminates the list */ + }, *ddp; + +#if 0 + for ( ddp = div_data; ddp->denom != 0; ++ddp ) + if ( (result = imaxdiv(ddp->numer, ddp->denom)).quot + != ddp->exp_quot || result.rem != ddp->exp_rem + ) { +// printf("*** imaxdiv(%"PRIdMAX",%"PRIdMAX +// ") failed; should be: (%"PRIdMAX",%"PRIdMAX +// "), was: (%"PRIdMAX",%"PRIdMAX") ***\n", +// ddp->numer, ddp->denom, ddp->exp_quot, +// ddp->exp_rem, result.quot, result.rem +// ); + printf("err:imaxdiv(%"PRIdMAX",%"PRIdMAX + ") = (%"PRIdMAX",%"PRIdMAX + "), is: (%"PRIdMAX",%"PRIdMAX")\n", + ddp->numer, ddp->denom, ddp->exp_quot, + ddp->exp_rem, result.quot, result.rem + ); + status = EXIT_FAILURE; + } +#endif + } + + { + char *endptr; + wchar_t *wendptr; + static char saved[64]; /* holds copy of input string */ + static wchar_t wnptr[64]; /* holds wide copy of test string */ + static int warned; /* "warned for null endptr" flag */ + register int i; + static struct + { + char * nptr; + int base; + intmax_t exp_val; + int exp_len; + } str_data[] = + { + { "", 0, 0, 0, }, + { "", 2, 0, 0, }, + { "", 8, 0, 0, }, + { "", 9, 0, 0, }, + { "", 10, 0, 0, }, + { "", 16, 0, 0, }, + { "", 36, 0, 0, }, + { "0", 0, 0, 1, }, + { "0", 2, 0, 1, }, + { "0", 8, 0, 1, }, + { "0", 9, 0, 1, }, + { "0", 10, 0, 1, }, + { "0", 16, 0, 1, }, + { "0", 36, 0, 1, }, + { "+0", 0, 0, 2, }, + { "+0", 2, 0, 2, }, + { "+0", 8, 0, 2, }, + { "+0", 9, 0, 2, }, + { "+0", 10, 0, 2, }, + { "+0", 16, 0, 2, }, + { "+0", 36, 0, 2, }, + { "-0", 0, 0, 2, }, + { "-0", 2, 0, 2, }, + { "-0", 8, 0, 2, }, + { "-0", 9, 0, 2, }, + { "-0", 10, 0, 2, }, + { "-0", 16, 0, 2, }, + { "-0", 36, 0, 2, }, + { "Inf", 0, 0, 0, }, + { "Inf", 2, 0, 0, }, + { "Inf", 8, 0, 0, }, + { "Inf", 9, 0, 0, }, + { "Inf", 10, 0, 0, }, + { "Inf", 16, 0, 0, }, + { "Inf", 36, 24171, 3, }, + { "+Inf", 0, 0, 0, }, + { "+Inf", 2, 0, 0, }, + { "+Inf", 8, 0, 0, }, + { "+Inf", 9, 0, 0, }, + { "+Inf", 10, 0, 0, }, + { "+Inf", 16, 0, 0, }, + { "+Inf", 36, 24171, 4, }, + { "-Inf", 0, 0, 0, }, + { "-Inf", 2, 0, 0, }, + { "-Inf", 8, 0, 0, }, + { "-Inf", 9, 0, 0, }, + { "-Inf", 10, 0, 0, }, + { "-Inf", 16, 0, 0, }, + { "-Inf", 36, -24171, 4, }, + { "inf", 0, 0, 0, }, + { "inf", 2, 0, 0, }, + { "inf", 8, 0, 0, }, + { "inf", 9, 0, 0, }, + { "inf", 10, 0, 0, }, + { "inf", 16, 0, 0, }, + { "inf", 36, 24171, 3, }, + { "+inf", 0, 0, 0, }, + { "+inf", 2, 0, 0, }, + { "+inf", 8, 0, 0, }, + { "+inf", 9, 0, 0, }, + { "+inf", 10, 0, 0, }, + { "+inf", 16, 0, 0, }, + { "+inf", 36, 24171, 4, }, + { "-inf", 0, 0, 0, }, + { "-inf", 2, 0, 0, }, + { "-inf", 8, 0, 0, }, + { "-inf", 9, 0, 0, }, + { "-inf", 10, 0, 0, }, + { "-inf", 16, 0, 0, }, + { "-inf", 36, -24171, 4, }, + { "119b8Z", 0, 119, 3, }, + { "119bZ", 0, 119, 3, }, + { "-0119bZ", 0, -9, 4, }, + { " \t\n 0X119bZ", 0, 4507, 10, }, + { " \t\n +0X119bZ", 0, 4507, 11, }, + { " \t\n -0x119bZ", 0, -4507, 11, }, + { " \t\n 119bZ", 0, 119, 7, }, + { "+119bZ", 0, 119, 4, }, + { "+0X119bz", 0, 4507, 7, }, + { "119b8Z", 2, 3, 2, }, + { "119bZ", 2, 3, 2, }, + { "-0119bZ", 2, -3, 4, }, + { " \t\n 0X119bZ", 2, 0, 5, }, + { " \t\n +0X119bZ", 2, 0, 6, }, + { " \t\n -0x119bZ", 2, 0, 6, }, + { " \t\n 119bZ", 2, 3, 6, }, + { "+119bZ", 2, 3, 3, }, + { "+0X119bz", 2, 0, 2, }, + { "119b8Z", 8, 9, 2, }, + { "119bZ", 8, 9, 2, }, + { "-0119bZ", 8, -9, 4, }, + { " \t\n 0X119bZ", 8, 0, 5, }, + { " \t\n +0X119bZ", 8, 0, 6, }, + { " \t\n -0x119bZ", 8, 0, 6, }, + { " \t\n 119bZ", 8, 9, 6, }, + { "+119bZ", 8, 9, 3, }, + { "+0X119bz", 8, 0, 2, }, + { "119b8Z", 9, 10, 2, }, + { "119bZ", 9, 10, 2, }, + { "-0119bZ", 9, -10, 4, }, + { " \t\n 0X119bZ", 9, 0, 5, }, + { " \t\n +0X119bZ", 9, 0, 6, }, + { " \t\n -0x119bZ", 9, 0, 6, }, + { " \t\n 119bZ", 9, 10, 6, }, + { "+119bZ", 9, 10, 3, }, + { "+0X119bz", 9, 0, 2, }, + { "119b8Z", 10, 119, 3, }, + { "119bZ", 10, 119, 3, }, + { "-0119bZ", 10, -119, 5, }, + { " \t\n 0X119bZ", 10, 0, 5, }, + { " \t\n +0X119bZ", 10, 0, 6, }, + { " \t\n -0x119bZ", 10, 0, 6, }, + { " \t\n 119bZ", 10, 119, 7, }, + { "+119bZ", 10, 119, 4, }, + { "+0X119bz", 10, 0, 2, }, + { "119b8Z", 16, 72120, 5, }, + { "119bZ", 16, 4507, 4, }, + { "-0119bZ", 16, -4507, 6, }, + { " \t\n 0X119bZ", 16, 4507, 10, }, + { " \t\n +0X119bZ", 16, 4507, 11, }, + { " \t\n -0x119bZ", 16, -4507, 11, }, + { " \t\n 119bZ", 16, 4507,8, }, + { "+119bZ", 16, 4507, 5, }, + { "+0X119bz", 16, 4507, 7, }, + { "119b8Z", 36, 62580275, 6, }, + { "119bZ", 36, 1738367, 5, }, + { "-0119bZ", 36, -1738367, 7, }, + { " \t\n 0X119bZ", 36, 1997122175, 11, }, + { " \t\n +0X119bZ", 36, 1997122175, 12, }, + { " \t\n -0x119bZ", 36, -1997122175, 12, }, + { " \t\n 119bZ", 36, 1738367, 9, }, + { "+119bZ", 36, 1738367, 6, }, + { "+0X119bz", 36, 1997122175, 8, }, + /* There should be a much larger battery of such tests. */ + { "127", 0, 127, 3, }, + { "-127", 0, -127, 4, }, + { "128", 0, 128, 3, }, + { "-128", 0, -127-1, 4, }, + { "255", 0, 255, 3, }, + { "-255", 0, -255, 4, }, + { "256", 0, 256, 3, }, + { "-256", 0, -255-1, 4, }, + { "32767", 0, 32767, 5, }, + { "-32767", 0, -32767, 6, }, + { "32768", 0, 32768, 5, }, + { "-32768", 0, -32767-1, 6, }, + { "65535", 0, 65535, 5, }, + { "-65535", 0, -65536+1, 6, }, + { "65536", 0, 65536, 5, }, + { "-65536", 0, -65536, 6, }, + { "2147483647", 0, 2147483647, 10, }, + { "-2147483647", 0, -2147483647, 11, }, + { "2147483648", 0, 2147483648, 10, }, + { "-2147483648", 0, -2147483647-1, 11, }, + { "4294967295", 0, 4294967295, 10, }, + { "-4294967295", 0, -4294967296+1, 11, }, + { "4294967296", 0, 4294967296, 10, }, + { "-4294967296", 0, -4294967296, 11, }, + { "9223372036854775807", 0, 9223372036854775807, 19, }, + { "-9223372036854775807", 0, -9223372036854775807, 20, }, + { "1234567890123456789", 0, 1234567890123456789, 19, }, + { "-1234567890123456789", 0, -1234567890123456789, 20, }, + { "1", 0, 1, 1, }, + { "-1", 0, -1, 2, }, + { "2", 0, 2, 1, }, + { "-2", 0, -2, 2, }, + { "10", 0, 10, 2, }, + { "-10", 0, -10, 3, }, + { "16", 0, 16, 2, }, + { "-16", 0, -16, 3, }, + /* Other test cases can be added here. */ + { NULL, 0, 0, 0 }, /* terminates the list */ + }, *sdp; + + for ( sdp = str_data; sdp->nptr != NULL ; ++sdp ) + { + /* + 7.8.2.3 The strtoimax and strtoumax functions + */ + + strcpy(saved, sdp->nptr); + + errno = 0; /* shouldn't be changed */ + + if ( (intmax = strtoimax(sdp->nptr, &endptr, sdp->base)) + != sdp->exp_val + ) { + int save = errno; + + printf("*** strtoimax(%s,,%d) failed; should be: %" + PRIdMAX", was: %"PRIdMAX" ***\n", sdp->nptr, + sdp->base, sdp->exp_val, intmax + ); + status = EXIT_FAILURE; + errno = save; + } + else if ( endptr != sdp->nptr + sdp->exp_len ) + { + int save = errno; + + printf("*** strtoimax(%s,,%d) returned wrong endptr" + " ***\n", sdp->nptr, sdp->base + ); + status = EXIT_FAILURE; + errno = save; + } + + if ( errno != 0 ) + { + printf("*** strtoimax modified errno ***\n"); + status = EXIT_FAILURE; + } + + if ( strcmp(sdp->nptr, saved) != 0 ) + { + printf("*** strtoimax modified its input ***\n"); + status = EXIT_FAILURE; + strcpy(saved, sdp->nptr); + } + + if ( sdp->exp_val >= 0 ) /* else some sign extension */ + { + errno = 0; /* shouldn't be changed */ + + if ( (uintmax = strtoumax(sdp->nptr, &endptr, sdp->base + ) + ) != sdp->exp_val + ) { + int save = errno; + + printf("*** strtoumax(%s,,%d) failed; " + "should be: %"PRIuMAX", was: %"PRIuMAX + " ***\n", sdp->nptr, sdp->base, + sdp->exp_val, uintmax + ); + status = EXIT_FAILURE; + errno = save; + } + else if ( endptr != sdp->nptr + sdp->exp_len ) + { + int save = errno; + + printf("*** strtoumax(%s,,%d) returned wrong " + "endptr ***\n", sdp->nptr, sdp->base + ); + status = EXIT_FAILURE; + errno = save; + } + + if ( errno != 0 ) + { + printf("*** strtoumax modified errno ***\n"); + status = EXIT_FAILURE; + } + + if ( strcmp(sdp->nptr, saved) != 0 ) + { + printf("*** strtoumax" + " modified its input ***\n" + ); + status = EXIT_FAILURE; + strcpy(saved, sdp->nptr); + } + } + + /* tests for null endptr */ + +#define WARN() if (!warned) warned = 1, printf("*** Using null endptr: ***\n") + + warned = 0; + errno = 0; /* shouldn't be changed */ + + if ( (intmax = strtoimax(sdp->nptr, (char **)NULL, sdp->base)) + != sdp->exp_val + ) { + int save = errno; + + WARN(); + printf("*** strtoimax(%s,NULL,%d) failed; " + "should be: %"PRIdMAX", was: %"PRIdMAX" ***\n", + sdp->nptr, sdp->base, sdp->exp_val, intmax + ); + status = EXIT_FAILURE; + errno = save; + } + + if ( errno != 0 ) + { + WARN(); + printf("*** strtoimax modified errno ***\n"); + status = EXIT_FAILURE; + } + + if ( strcmp(sdp->nptr, saved) != 0 ) + { + WARN(); + printf("*** strtoimax modified its input ***\n"); + status = EXIT_FAILURE; + strcpy(saved, sdp->nptr); + } + + if ( sdp->exp_val >= 0 ) /* else some sign extension */ + { + errno = 0; /* shouldn't be changed */ + + if ( (uintmax = strtoumax(sdp->nptr, (char **)NULL, + sdp->base + ) + ) != sdp->exp_val + ) { + int save = errno; + + WARN(); + printf("*** strtoumax(%s,NULL,%d) failed; " + "should be: %"PRIuMAX", was: %"PRIuMAX + " ***\n", sdp->nptr, sdp->base, + sdp->exp_val, uintmax + ); + status = EXIT_FAILURE; + errno = save; + } + + if ( errno != 0 ) + { + WARN(); + printf("*** strtoumax modified errno ***\n"); + status = EXIT_FAILURE; + } + + if ( strcmp(sdp->nptr, saved) != 0 ) + { + WARN(); + printf("*** strtoumax" + " modified its input ***\n" + ); + status = EXIT_FAILURE; + strcpy(saved, sdp->nptr); + } + } + + /* + 7.8.2.4 The wcstoimax and wcstoumax functions + */ + + for ( i = 0; i < 64; ++i ) + if ( (wnptr[i] = sdp->nptr[i]) == '\0' ) + break; + + errno = 0; /* shouldn't be changed */ + + if ( (intmax = wcstoimax(wnptr, &wendptr, sdp->base)) + != sdp->exp_val + ) { + int save = errno; + + printf("*** wcstoimax(%s,,%d) failed; should be: %" + PRIdMAX", was: %"PRIdMAX" ***\n", sdp->nptr, + sdp->base, sdp->exp_val, intmax + ); + status = EXIT_FAILURE; + errno = save; + } + else if ( wendptr != wnptr + sdp->exp_len ) + { + int save = errno; + + printf("*** wcstoimax(%s,,%d) returned wrong endptr" + " ***\n", sdp->nptr, sdp->base + ); + status = EXIT_FAILURE; + errno = save; + } + + if ( errno != 0 ) + { + printf("*** wcstoimax modified errno ***\n"); + status = EXIT_FAILURE; + } + + for ( i = 0; i < 64; ++i ) + if ( wnptr[i] != sdp->nptr[i] ) + { + printf("*** wcstoimax modified its input ***\n" + ); + status = EXIT_FAILURE; + + for ( ; i < 64; ++i ) + if ( (wnptr[i] = sdp->nptr[i]) == '\0' ) + break; + + break; + } + else if ( wnptr[i] == '\0' ) + break; + + if ( sdp->exp_val >= 0 ) /* else some sign extension */ + { + errno = 0; /* shouldn't be changed */ + + if ( (uintmax = wcstoumax(wnptr, &wendptr, sdp->base) + ) != sdp->exp_val + ) { + int save = errno; + + printf("*** wcstoumax(%s,,%d) failed; " + "should be: %"PRIuMAX", was: %"PRIuMAX + " ***\n", sdp->nptr, sdp->base, + sdp->exp_val, uintmax + ); + status = EXIT_FAILURE; + errno = save; + } + else if ( wendptr != wnptr + sdp->exp_len ) + { + int save = errno; + + printf("*** wcstoumax(%s,,%d) returned wrong " + "endptr ***\n", sdp->nptr, sdp->base + ); + status = EXIT_FAILURE; + errno = save; + } + + if ( errno != 0 ) + { + printf("*** wcstoumax modified errno ***\n"); + status = EXIT_FAILURE; + } + + for ( i = 0; i < 64; ++i ) + if ( wnptr[i] != sdp->nptr[i] ) + { + printf("*** wcstoumax" + " modified its input ***\n" + ); + status = EXIT_FAILURE; + + for ( ; i < 64; ++i ) + if ( (wnptr[i] = sdp->nptr[i]) + == '\0' + ) + break; + + break; + } + else if ( wnptr[i] == '\0' ) + break; + } + + /* tests for null endptr */ + + warned = 0; + errno = 0; /* shouldn't be changed */ + + if ( (intmax = wcstoimax(wnptr, (wchar_t **)NULL, sdp->base)) + != sdp->exp_val + ) { + int save = errno; + + WARN(); + printf("*** wcstoimax(%s,NULL,%d) failed; should be: %" + PRIdMAX", was: %"PRIdMAX" ***\n", sdp->nptr, + sdp->base, sdp->exp_val, intmax + ); + status = EXIT_FAILURE; + errno = save; + } + + if ( errno != 0 ) + { + WARN(); + printf("*** wcstoimax modified errno ***\n"); + status = EXIT_FAILURE; + } + + for ( i = 0; i < 64; ++i ) + if ( wnptr[i] != sdp->nptr[i] ) + { + WARN(); + printf("*** wcstoimax modified its input ***\n" + ); + status = EXIT_FAILURE; + + for ( ; i < 64; ++i ) + if ( (wnptr[i] = sdp->nptr[i]) + == '\0' + ) + break; + + break; + } + else if ( wnptr[i] == '\0' ) + break; + + if ( sdp->exp_val >= 0 ) /* else some sign extension */ + { + errno = 0; /* shouldn't be changed */ + + if ( (uintmax = wcstoumax(wnptr, (wchar_t **)NULL, + sdp->base + ) + ) != sdp->exp_val + ) { + int save = errno; + + WARN(); + printf("*** wcstoumax(%s,NULL,%d) failed; " + "should be: %"PRIuMAX", was: %"PRIuMAX + " ***\n", sdp->nptr, sdp->base, + sdp->exp_val, uintmax + ); + status = EXIT_FAILURE; + errno = save; + } + + if ( errno != 0 ) + { + WARN(); + printf("*** wcstoumax modified errno ***\n"); + status = EXIT_FAILURE; + } + + for ( i = 0; i < 64; ++i ) + if ( wnptr[i] != sdp->nptr[i] ) + { + WARN(); + printf("*** wcstoumax" + " modified its input ***\n" + ); + status = EXIT_FAILURE; + + for ( ; i < 64; ++i ) + if ( (wnptr[i] = sdp->nptr[i]) + == '\0' + ) + break; + + break; + } + else if ( wnptr[i] == '\0' ) + break; + } + } + + /* + 7.8.2.3 The strtoimax and strtoumax functions (continued) + */ + + if ( (intmax = strtoimax("1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + &endptr, 0 + ) + ) != INTMAX_MAX || errno != ERANGE + ) { + printf("*** strtoimax failed overflow test ***\n"); + status = EXIT_FAILURE; + } + + if ( (intmax = strtoimax("+1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + &endptr, 0 + ) + ) != INTMAX_MAX || errno != ERANGE + ) { + printf("*** strtoimax failed +overflow test ***\n"); + status = EXIT_FAILURE; + } + + if ( (intmax = strtoimax("-1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + &endptr, 0 + ) + ) != INTMAX_MIN || errno != ERANGE + ) { + printf("*** strtoimax failed -overflow test ***\n"); + status = EXIT_FAILURE; + } + + if ( (uintmax = strtoumax("1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + &endptr, 0 + ) + ) != UINTMAX_MAX || errno != ERANGE + ) { + printf("*** strtoumax failed overflow test ***\n"); + status = EXIT_FAILURE; + } + + if ( (uintmax = strtoumax("+1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + &endptr, 0 + ) + ) != UINTMAX_MAX || errno != ERANGE + ) { + printf("*** strtoumax failed +overflow test ***\n"); + status = EXIT_FAILURE; + } + + if ( (uintmax = strtoumax("-1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + &endptr, 0 + ) + ) != UINTMAX_MAX || errno != ERANGE + ) { + printf("*** strtoumax failed -overflow test ***\n"); + status = EXIT_FAILURE; + } + + /* + 7.8.2.4 The wcstoimax and wcstoumax functions (continued) + */ + +#ifdef NO_INTERNAL_WCHAR + printf("NO_INTERNAL_WCHAR\n"); +#else + + if ( (intmax = wcstoimax(L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890", + &wendptr, 0 + ) + ) != INTMAX_MAX || errno != ERANGE + ) { + printf("*** wcstoimax failed overflow test ***\n"); + status = EXIT_FAILURE; + } + + if ( (intmax = wcstoimax(L"+1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890", + &wendptr, 0 + ) + ) != INTMAX_MAX || errno != ERANGE + ) { + printf("*** wcstoimax failed +overflow test ***\n"); + status = EXIT_FAILURE; + } + + if ( (intmax = wcstoimax(L"-1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890", + &wendptr, 0 + ) + ) != INTMAX_MIN || errno != ERANGE + ) { + printf("*** wcstoimax failed -overflow test ***\n"); + status = EXIT_FAILURE; + } + + if ( (uintmax = wcstoumax(L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890", + &wendptr, 0 + ) + ) != UINTMAX_MAX || errno != ERANGE + ) { + printf("*** wcstoumax failed overflow test ***\n"); + status = EXIT_FAILURE; + } + + if ( (uintmax = wcstoumax(L"+1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890", + &wendptr, 0 + ) + ) != UINTMAX_MAX || errno != ERANGE + ) { + printf("*** wcstoumax failed +overflow test ***\n"); + status = EXIT_FAILURE; + } + + if ( (uintmax = wcstoumax(L"-1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890" + L"1234567890123456789012345678901234567890", + &wendptr, 0 + ) + ) != UINTMAX_MAX || errno != ERANGE + ) { + printf("*** wcstoumax failed -overflow test ***\n"); + status = EXIT_FAILURE; + } +#endif // NO_INTERNAL_WCHAR + } +#endif /* defined(INTMAX_MAX) */ + + if ( status != 0 ) + printf("sitest failed.\n"); + + return status; +} + +#endif \ No newline at end of file diff --git a/test/val/strtol-test.c b/test/val/strtol-test.c new file mode 100644 index 000000000..76daef791 --- /dev/null +++ b/test/val/strtol-test.c @@ -0,0 +1,135 @@ +/* + !!DESCRIPTION!! A small test for atoi/strtol. Assumes twos complement + !!ORIGIN!! + !!LICENCE!! + !!AUTHOR!! +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <errno.h> + +#define ERROR 0 +#define OK 1 + +static unsigned int Failures = 0; + +static void IncStr (char* Buf) +/* Increment a number represented as a string by one. The string MUST not + * start with a '9', we cannot handle overflow in this case. + */ +{ + int Len = strlen (Buf); + + while (--Len >= 0) { + switch (Buf[Len]) { + case '9': + Buf[Len] = '0'; + break; + + default: + ++(Buf[Len]); + return; + } + } +} + +static void CheckStrToL (const char* Str, int Base, long Val, unsigned char Ok) +{ + char* EndPtr; + long Res = strtol (Str, &EndPtr, Base); + if (Ok) { + if (Res != Val) { + printf ("strtol error in \"%s\":\n" + " result = %ld, should be %ld, chars = %d\n", + Str, Res, Val, EndPtr - Str); + ++Failures; + } + } else { + if (errno != ERANGE) { + printf ("strtol error in \"%s\":\n" + " should not convert, but errno = %d\n", + Str, errno); + ++Failures; + } + if (Res != Val) { + printf ("strtol error in \"%s\":\n" + " result = %ld, should be %ld, chars = %d\n", + Str, Res, Val, EndPtr - Str); + ++Failures; + } + } +} + +int main (void) +{ + char Buf[80]; + + /* Prefixed allowed if base = 0 */ + CheckStrToL ("\t 0x10G ", 0, 16L, OK); + CheckStrToL ("\t 0X10G ", 0, 16L, OK); + CheckStrToL (" \t0377\t", 0, 255L, OK); + CheckStrToL (" 377", 0, 377L, OK); + + CheckStrToL ("\t -0x10G ", 0, -16L, OK); + CheckStrToL ("\t -0X10G ", 0, -16L, OK); + CheckStrToL (" \t-0377\t", 0, -255L, OK); + CheckStrToL (" -377", 0, -377L, OK); + + /* No prefixes if base = 10 */ + CheckStrToL ("\t 1234 ", 10, 1234L, OK); + CheckStrToL ("\t -1234 ", 10, -1234L, OK); + CheckStrToL ("\t -0x10G ", 10, 0L, OK); + CheckStrToL ("\t -0X10G ", 10, 0L, OK); + CheckStrToL (" \t-0377\t", 10, -377L, OK); + CheckStrToL (" 0377", 10, 377L, OK); + + /* 0x prefix is allowed if base = 16 */ + CheckStrToL ("\t 0x1234 ", 16, 0x1234L, OK); + CheckStrToL ("\t -0x1234 ", 16, -0x1234L, OK); + CheckStrToL ("\t -010G ", 16, -16L, OK); + CheckStrToL ("\t 10G ", 16, 16L, OK); + + /* Check LONG_MIN and LONG_MAX */ + sprintf (Buf, "%ld", LONG_MIN); + CheckStrToL (Buf, 0, LONG_MIN, OK); + sprintf (Buf, "%ld", LONG_MAX); + CheckStrToL (Buf, 0, LONG_MAX, OK); + + /* Check value one smaller */ + sprintf (Buf+1, "%ld", LONG_MIN); + Buf[1] = '0'; /* Overwrite '-' */ + IncStr (Buf+1); + if (Buf[1] == '0') { + Buf[1] = '-'; + Buf[0] = ' '; + } else { + Buf[0] = '-'; + } + CheckStrToL (Buf, 0, LONG_MIN, ERROR); + + /* Check value one larger */ + sprintf (Buf+1, "%ld", LONG_MAX); + Buf[0] = '0'; + IncStr (Buf); + if (Buf[0] == '0') { + Buf[0] = ' '; + } + CheckStrToL (Buf, 0, LONG_MAX, ERROR); + + /* Check numbers that are much too large or small */ + CheckStrToL ("-999999999999999999999999999999999999999999999999999999999", 0, LONG_MIN, ERROR); + CheckStrToL ("+999999999999999999999999999999999999999999999999999999999", 0, LONG_MAX, ERROR); + CheckStrToL (" 999999999999999999999999999999999999999999999999999999999", 0, LONG_MAX, ERROR); + + /* Check a few other bases */ + CheckStrToL ("aBcD", 36, 481261L, OK); + CheckStrToL ("zyaB", 35, 0L, ERROR); + CheckStrToL ("zyaB", 36, 1677395L, ERROR); + + printf ("Failures: %u\n", Failures); + + return Failures; +} diff --git a/test/val/strtoul-test.c b/test/val/strtoul-test.c new file mode 100644 index 000000000..803fd452c --- /dev/null +++ b/test/val/strtoul-test.c @@ -0,0 +1,121 @@ +/* + !!DESCRIPTION!! A small test for strtuol. Assumes twos complement + !!ORIGIN!! + !!LICENCE!! + !!AUTHOR!! +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <errno.h> + +#define ERROR 0 +#define OK 1 + +static unsigned int Failures = 0; + +static void IncStr (char* Buf) +/* Increment a number represented as a string by one. The string MUST not + * start with a '9', we cannot handle overflow in this case. + */ +{ + int Len = strlen (Buf); + + while (--Len >= 0) { + switch (Buf[Len]) { + case '9': + Buf[Len] = '0'; + break; + + default: + ++(Buf[Len]); + return; + } + } +} + +static void CheckStrToUL (const char* Str, int Base, unsigned long Val, unsigned char Ok) +{ + char* EndPtr; + unsigned long Res = strtoul (Str, &EndPtr, Base); + if (Ok) { + if (Res != Val) { + printf ("strtol error in \"%s\":\n" + " result = %lu, should be %lu, chars = %d\n", + Str, Res, Val, EndPtr - Str); + ++Failures; + } + } else { + if (errno != ERANGE) { + printf ("strtol error in \"%s\":\n" + " should not convert, but errno = %d\n", + Str, errno); + ++Failures; + } + if (Res != Val) { + printf ("strtol error in \"%s\":\n" + " result = %lu, should be %lu, chars = %d\n", + Str, Res, Val, EndPtr - Str); + ++Failures; + } + } +} + +int main (void) +{ + char Buf[80]; + + /* Prefixed allowed if base = 0 */ + CheckStrToUL ("\t 0x10G ", 0, 16UL, OK); + CheckStrToUL ("\t 0X10G ", 0, 16UL, OK); + CheckStrToUL (" \t0377\t", 0, 255UL, OK); + CheckStrToUL (" 377", 0, 377UL, OK); + + CheckStrToUL ("\t -0x10G ", 0, (unsigned long) -16L, OK); + CheckStrToUL ("\t -0X10G ", 0, (unsigned long) -16L, OK); + CheckStrToUL (" \t-0377\t", 0, (unsigned long) -255L, OK); + CheckStrToUL (" -377", 0, (unsigned long) -377L, OK); + + /* No prefixes if base = 10 */ + CheckStrToUL ("\t 1234 ", 10, 1234UL, OK); + CheckStrToUL ("\t -1234 ", 10, (unsigned long) -1234L, OK); + CheckStrToUL ("\t -0x10G ", 10, 0UL, OK); + CheckStrToUL ("\t -0X10G ", 10, 0UL, OK); + CheckStrToUL (" \t-0377\t", 10, (unsigned long) -377L, OK); + CheckStrToUL (" 0377", 10, 377UL, OK); + + /* 0x prefix is allowed if base = 16 */ + CheckStrToUL ("\t 0x1234 ", 16, 0x1234UL, OK); + CheckStrToUL ("\t -0x1234 ", 16, (unsigned long) -0x1234L, OK); + CheckStrToUL ("\t -010G ", 16, (unsigned long) -16L, OK); + CheckStrToUL ("\t 10G ", 16, 16UL, OK); + + /* Check ULONG_MAX */ + sprintf (Buf, "%lu", ULONG_MAX); + CheckStrToUL (Buf, 0, ULONG_MAX, OK); + + /* Check value one larger */ + sprintf (Buf+1, "%lu", ULONG_MAX); + Buf[0] = '0'; + IncStr (Buf); + if (Buf[0] == '0') { + Buf[0] = ' '; + } + CheckStrToUL (Buf, 0, ULONG_MAX, ERROR); + + /* Check numbers that are much too large or small */ + CheckStrToUL ("-999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR); + CheckStrToUL ("+999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR); + CheckStrToUL (" 999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR); + + /* Check a few other bases */ + CheckStrToUL ("aBcD", 36, 481261UL, OK); + CheckStrToUL ("zyaB", 35, 0UL, ERROR); + CheckStrToUL ("zyaB", 36, 1677395UL, ERROR); + + printf ("Failures: %u\n", Failures); + + return Failures; +} diff --git a/test/val/struct1.c b/test/val/struct1.c new file mode 100644 index 000000000..71dbf7946 --- /dev/null +++ b/test/val/struct1.c @@ -0,0 +1,100 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; + +#if SUPPORT_BIT_TYPES + +bit bit0 = 0; +bit bit1 = 0; +bit bit2 = 0; +bit bit3 = 0; +bit bit4 = 0; +bit bit5 = 0; +bit bit6 = 0; +bit bit7 = 0; +bit bit8 = 0; +bit bit9 = 0; +bit bit10 = 0; +bit bit11 = 0; + +#endif + +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned char achar0 = 0; +unsigned char achar1 = 0; +unsigned char *acharP = 0; + +struct chars + { + unsigned char c0, c1; + unsigned int i0, i1; + }; + +struct chars struct1; + +void +done () +{ + dummy++; +} + +void +struct_test (void) +{ + if (struct1.c0 || struct1.c1) + failures++; + + struct1.c0++; + + if (struct1.c0 != 1) + failures++; +} + +void +ptr_to_struct (struct chars *p) +{ + if (p->c1) + failures++; + + p->c1++; + + if (p->c1 != 1) + failures++; +} + +void add_chars(void) +{ + achar0 = struct1.c0 + struct1.c1; + + if(achar0 != 1) + failures++; +} + +int +main (void) +{ + struct1.c0 = 0; + struct1.c1 = 0; + struct_test (); + ptr_to_struct (&struct1); + + struct1.c0 = 0; + struct1.c1 = 1; + add_chars(); + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/sub1.c b/test/val/sub1.c new file mode 100644 index 000000000..f1ae9394f --- /dev/null +++ b/test/val/sub1.c @@ -0,0 +1,272 @@ +/* + !!DESCRIPTION!! Substraction Test + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#if SUPPORT_BIT_TYPES + +bit bit0 = 0; +bit bit1 = 0; +bit bit2 = 0; +bit bit3 = 0; +bit bit4 = 0; +bit bit5 = 0; +bit bit6 = 0; +bit bit7 = 0; +bit bit8 = 0; +bit bit9 = 0; +bit bit10 = 0; +bit bit11 = 0; + +#endif + +#ifdef SIZEOF_INT_16BIT +#if defined(__LINUX__) || defined(LINUX) +unsigned short aint0 = 0; +unsigned short aint1 = 0; +#else +unsigned int aint0 = 0; +unsigned int aint1 = 0; +#endif + +#else +unsigned int aint0 = 0; +unsigned int aint1 = 0; +#endif +unsigned char achar0 = 0; +unsigned char achar1 = 0; +unsigned char achar2 = 0; +unsigned char achar3 = 0; +unsigned char *acharP = 0; + +void done() +{ + dummy++; +} + +void sub_lit_from_uchar(void) +{ + achar0 = achar0 - 5; + + if(achar0 != 0xfb) + failures++; + + achar0 -= 10; + + if(achar0 != 0xf1) + failures++; + + achar0 = achar0 -1; /* Should be a decrement */ + if(achar0 != 0xf0) + failures++; + + for(achar1 = 0; achar1 < 100; achar1++) + achar0 -= 2; + + if(achar0 != 40) + failures++; +} + +/* achar0 = 1 + achar1 = 100 +*/ + +void sub_uchar2uchar(void) +{ + achar1 = achar1 - achar0; + + if(achar1 != 99) + failures++; + + for(achar2 = 0; achar2<7; achar2++) + achar1 -= achar0; + + if(achar1 != 92) + failures++; +} + +/* assumes + achar0 = 10 + achar1 = 32 + achar2, achar3 can be anything. +*/ +void sub_uchar2uchar2(void) +{ + achar0--; + achar0 = achar0 - 1; + achar0 = achar0 - 2; + achar0 = achar0 - 3; + if(achar0 != 3) + failures++; + + achar1 -= achar0; + if(achar1 != 29) + failures++; + + achar2 = achar1 - achar0; + if(achar2 != 26) + failures++; + + achar3 = achar2 - achar1 - achar0; + if(achar3 != 0xfa) + failures++; +} + +/* sub_bits + all bit variables are 0 upon entry. +*/ +#if SUPPORT_BIT_TYPES +void sub_bits(void) +{ + bit1 = bit0; + + bit0 = 1; + + if(bit1 != 0) + failures++; + + bit1 = bit0-bit1; /* 1 - 0 => 1 */ + if(bit1 != 1) + failures++; + +#if SUPPORT_BIT_ARITHMETIC + bit2 = bit1-bit0; /* 1 - 1 => 0 */ + if(bit2) + failures++; + + bit7 = bit4-bit5; + bit6 = bit4+bit5; + bit3 = bit4-bit5-bit6-bit7-bit0; /* 0-0-0-0-1 => 1 */ + if(!bit3) + failures++; +#endif +} + +/* sub_bit2uchar(void) - assumes bit0 = 1, achar0 = 7 */ + +void sub_bit2uchar(void) +{ + achar0 -= bit0; + + if(achar0 != 6) + failures++; + + if(achar0 == bit0) + failures++; +} + +void sub_bit2uint(void) +{ + if(aint0 != bit11) + failures++; + + aint0 -= bit0; + if(aint0!=0xffff) + failures++; +} +#endif + +void sub_ucharFromLit(void) +{ + achar0 = 2 - achar0; + + if(achar0 != 2) + { + printf("%x != %x\n",0x02,achar0); + failures++; + } + + aint0 = 2 - aint0; + + if(aint0 != 2) + { + printf("%x != %x\n",0x02,aint0); + failures++; + } + + aint0--; + + if(aint0 != 1) + { + printf("%x != %x\n",0x01,aint0); + failures++; + } + + aint0 = 0x100 - aint0; + + if(aint0 != 0xff) + { + printf("%x != %x\n",0xff,aint0); + failures++; + } + + aint0 = 0xff00 - aint0; + + if(aint0 != 0xfe01) + { + printf("%x != %x\n",0xfe01,aint0); + failures++; + } + + aint0 = 0x0e01 - aint0; + + if(aint0 != 0x1000) + { + printf("%x != %x\n",0x1000,aint0); + failures++; + } + + aint0 = 0x10ff - aint0; + + if(aint0 != 0xff) + { + printf("%x != %x\n",0xff,aint0); + failures++; + } +} + +int main(void) +{ + sub_lit_from_uchar(); + printf("failures: %d\n",failures); + + achar0=1; + achar1=100; + sub_uchar2uchar(); + printf("failures: %d\n",failures); + + achar0 = 10; + achar1 = 32; + sub_uchar2uchar2(); + printf("failures: %d\n",failures); + +#if SUPPORT_BIT_TYPES + sub_bits(); + + achar0 = 7; + bit0 = 1; + sub_bit2uchar(); + printf("failures: %d\n",failures); + sub_bit2uint(); + printf("failures: %d\n",failures); +#endif + + aint0 = 0; + achar0 = 0; + sub_ucharFromLit(); + + success = failures; + done(); + + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/sub2.c b/test/val/sub2.c new file mode 100644 index 000000000..835e65733 --- /dev/null +++ b/test/val/sub2.c @@ -0,0 +1,169 @@ +/* + !!DESCRIPTION!! Substraction Test + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#if SUPPORT_BIT_TYPES + +bit bit0 = 0; +bit bit1 = 0; +bit bit2 = 0; +bit bit3 = 0; +bit bit4 = 0; +bit bit5 = 0; +bit bit6 = 0; +bit bit7 = 0; +bit bit8 = 0; +bit bit9 = 0; +bit bit10 = 0; +bit bit11 = 0; + +#endif + +int int0 = 0; +int int1 = 0; + +signed char char0 = 0; +signed char char1 = 0; +signed char char2 = 0; + +void done() +{ + dummy++; +} + +void sub_int1(void) +{ + if(int0 != 5) + failures++; + + if(int1 != 4) + failures++; + + int0 = int0 - int1; + + if(int0 != 1) + failures++; + + int0 = 4 - int0; + if(int0 != 3) + failures++; + + int0 = int0 - int1; + + if(int0 != -1) + failures++; + + int0 = int0 - 0xff; + + if(int0 != -0x100) + failures++; + + int0 = 0xff - int0; + + if(int0 != 0x1ff) + failures++; +} + +void sub_char_int(void) +{ + int0 = int0 - char0; + + if(int0 != 3) + failures++; + + if(int0 < char0) + failures++; + + int0 = int0 - char0; + + if(int0 != 1) + failures++; + + if(int0 > char0) + failures++; + + int0 = int0 - char0; + if(int0 != -1) + failures++; + + if(int0>0) + failures++; +} + +void assign_char2int(void) +{ + int0 = char0; + if(int0 != 0x7f) + failures++; + + /* printf("%2x %2x %2x %d\n",0x7f,int0,char0,failures); */ + + int1 = char1; + if(int1 != -5) + failures++; + + /* printf("%2x,%d %2x,%d %2x,%d %d\n",-5,-5,(int)int1,(int)int1,(int)char1,(int)char1,failures); */ +} + +void sub_compound_char(void) +{ + char0 = char1 - 5; + if(char0 != 4) + failures++; + + if((char1 - char0 - 5) != 0) + failures++; +} + +void sub_compound_int(void) +{ + int0 = int1 - 5; + if(int0 != 4) + failures++; + + if((int1 - int0 - 5) != 0) + failures++; +} + +int main(void) +{ + int0 = 5; + int1 = 4; + + sub_int1(); + printf("failures: %d\n",failures); + + int0 = 5; + int1 = 4; + char0 = 2; + + sub_char_int(); + printf("failures: %d\n",failures); + + char0 = 0x7f; + char1 = -5; + assign_char2int(); + printf("failures: %d\n",failures); + + char1 = 9; + sub_compound_char(); + printf("failures: %d\n",failures); + + int1 = 9; + sub_compound_int(); + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/switch1.c b/test/val/switch1.c new file mode 100644 index 000000000..8d31b4ecf --- /dev/null +++ b/test/val/switch1.c @@ -0,0 +1,91 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned char achar0 = 0; +unsigned char achar1 = 0; + +void done() +{ + dummy++; +} + +void switch1(void) +{ + switch(achar0) { + case 0: + achar0 = 9; + break; + case 1: + achar0 = 18; + break; + + default: + achar0 = 0; + } +} + +void switch2(void) +{ + switch(achar1) { + case 0: achar0 = 9; break; + case 1: achar0 = 8; break; + case 2: achar0 = 7; break; + case 3: achar0 = 6; break; + case 4: achar0 = 5; break; + case 5: achar0 = 4; break; + case 6: achar0 = 3; break; + case 7: achar0 = 2; break; + case 8: achar0 = 1; break; + case 9: achar0 = 0; break; + case 10: achar0 = 9; break; + case 11: achar0 = 8; break; + case 12: achar0 = 7; break; + default: achar0 = 0xff; break; + } +} + +int main(void) +{ + achar0 = 0; + switch1(); + if(achar0 != 9) + failures++; + + switch1(); + if(achar0 != 0) + failures++; + + achar0++; + + switch1(); + if(achar0 != 18) + failures++; + + for(achar1=0; achar1<10;achar1++){ + switch2(); + if(achar0 != (9-achar1)) + failures++; + + } + + success=failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/while.c b/test/val/while.c new file mode 100644 index 000000000..cf2147052 --- /dev/null +++ b/test/val/while.c @@ -0,0 +1,53 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success = 0; +unsigned char failures = 0; +unsigned char dummy = 0; + +#ifdef SUPPORT_BIT_TYPES +bit bit0 = 0; +#endif +unsigned int aint0 = 0; +unsigned int aint1 = 0; +unsigned char achar0 = 0; +unsigned char achar1 = 0; + +void +done () +{ + dummy++; +} + +void +while1 (void) +{ + unsigned char i = 10; + + do + { + achar0++; + } + while (--i); + + if (achar0 != 10) + failures++; +} + +int +main (void) +{ + while1 (); + + success = failures; + done (); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/test/val/xor.c b/test/val/xor.c new file mode 100644 index 000000000..2a346023e --- /dev/null +++ b/test/val/xor.c @@ -0,0 +1,64 @@ +/* + !!DESCRIPTION!! + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <limits.h> + +unsigned char success=0; +unsigned char failures=0; +unsigned char dummy=0; + +unsigned char achar0 = 0; +unsigned char achar1 = 0; +unsigned char achar2 = 0; + +void done() +{ + dummy++; +} + +void xor_chars_0_1(void) +{ + achar2 = achar0 ^ achar1; + + achar0 = achar0 ^ 0x1; + + achar1 = achar0 ^ achar1 ^ 4; +} + +void xor_if(void) +{ + if(achar0 ^ achar1) + failures++; + + achar0 ^= 0xff; + + if( !(achar0 ^ achar1) ) + failures++; +} + +int main(void) +{ + xor_chars_0_1(); + + if(achar2) + failures++; + + if(achar0 != 1) + failures++; + + if(achar1 != 5) + failures++; + + achar0 = achar1; + xor_if(); + + success = failures; + done(); + printf("failures: %d\n",failures); + + return failures; +} diff --git a/testcode/lib/atari/defdev.c b/testcode/lib/atari/defdev.c index aef8400ae..f679985ec 100644 --- a/testcode/lib/atari/defdev.c +++ b/testcode/lib/atari/defdev.c @@ -1,8 +1,8 @@ /* - * testprogram printing the default device - * - * 26-Nov-2009, Christian Groessler - */ +** testprogram printing the default device +** +** 26-Nov-2009, Christian Groessler +*/ #include <stdio.h> #include <conio.h> diff --git a/testcode/lib/atari/mem.c b/testcode/lib/atari/mem.c index 5e9855da0..36222e08b 100644 --- a/testcode/lib/atari/mem.c +++ b/testcode/lib/atari/mem.c @@ -1,8 +1,8 @@ /* - * show some memory stuff - * - * 04-Aug-2004, Christian Groessler - */ +** show some memory stuff +** +** 04-Aug-2004, Christian Groessler +*/ #include <stdio.h> #include <stdlib.h> diff --git a/testcode/lib/atari/ostype.c b/testcode/lib/atari/ostype.c index f5e9296ca..552735ac8 100644 --- a/testcode/lib/atari/ostype.c +++ b/testcode/lib/atari/ostype.c @@ -1,8 +1,8 @@ /* - * testprogram for get_ostype() and get_tv() functions - * - * 09-Jul-2004, chris@groessler.org - */ +** testprogram for get_ostype() and get_tv() functions +** +** 09-Jul-2004, chris@groessler.org +*/ #include <stdio.h> #include <atari.h> diff --git a/testcode/lib/atari/sys.c b/testcode/lib/atari/sys.c index a35be9dac..9ec7aa631 100644 --- a/testcode/lib/atari/sys.c +++ b/testcode/lib/atari/sys.c @@ -1,10 +1,10 @@ /* - * testprogram for _sys() function on Atari - * - * 17-Sep-2013, chris@groessler.org - * - * uses PUTCHR IOCB function to display a string - */ +** testprogram for _sys() function on Atari +** +** 17-Sep-2013, chris@groessler.org +** +** uses PUTCHR IOCB function to display a string +*/ #include <atari.h> #include <6502.h> diff --git a/testcode/lib/clock.c b/testcode/lib/clock.c index a4d046d52..ac1ab3c67 100644 --- a/testcode/lib/clock.c +++ b/testcode/lib/clock.c @@ -1,8 +1,8 @@ /* - * simple clock test - * - * 06-Nov-2001, Christian Groessler - */ +** simple clock test +** +** 06-Nov-2001, Christian Groessler +*/ #include <stdio.h> #include <conio.h> diff --git a/testcode/lib/cprintf.c b/testcode/lib/cprintf.c index bc8f47af2..ca3a06de6 100644 --- a/testcode/lib/cprintf.c +++ b/testcode/lib/cprintf.c @@ -1,24 +1,24 @@ /* - * test program for the cprintf() function - * (for the \r and \n special operators) - * CPG - * - * The output generated by this program should look - * like this: - * - * ---- top of screen -------- - * 12345 - * 67890 - * - * - * 67890 - * - * hit return to exit.... +** test program for the cprintf() function +** (for the \r and \n special operators) +** CPG +** +** The output generated by this program should look +** like this: +** +** ---- top of screen -------- +** 12345 +** 67890 +** +** +** 67890 +** +** hit return to exit.... . . . - * ---- bottom of screen ----- - */ +** ---- bottom of screen ----- +*/ #include <stdio.h> #include <conio.h> diff --git a/testcode/lib/cursor.c b/testcode/lib/cursor.c index a608236cb..fc6e3ccb9 100644 --- a/testcode/lib/cursor.c +++ b/testcode/lib/cursor.c @@ -1,9 +1,9 @@ /* - * test for conio cursor() function - * CPG 2002 - * - * the cursor should be in the same state as mentioned in the printfs - */ +** test for conio cursor() function +** CPG 2002 +** +** the cursor should be in the same state as mentioned in the printfs +*/ #include <conio.h> diff --git a/testcode/lib/deb.c b/testcode/lib/deb.c index b054fc14f..06a8d06af 100644 --- a/testcode/lib/deb.c +++ b/testcode/lib/deb.c @@ -1,9 +1,9 @@ /* - * test program for the debugger - * - * press 'd' to enter the debugger - * - */ +** test program for the debugger +** +** press 'd' to enter the debugger +** +*/ #include <stdio.h> #include <conio.h> diff --git a/testcode/lib/em-test.c b/testcode/lib/em-test.c index 41a7eb2c8..bd4eddc6a 100644 --- a/testcode/lib/em-test.c +++ b/testcode/lib/em-test.c @@ -143,8 +143,8 @@ int main (void) cputs ("\r\nTesting em_copyfrom/em_copyto"); /* We're filling now 384 bytes per run to test the copy routines with - * other sizes. - */ + ** other sizes. + */ PageCount = (PageCount * 2) / 3; /* Setup the copy structure */ diff --git a/testcode/lib/exec-test1.c b/testcode/lib/exec-test1.c index e2548fb0a..ea74ee60a 100644 --- a/testcode/lib/exec-test1.c +++ b/testcode/lib/exec-test1.c @@ -1,5 +1,5 @@ /* -** These programs test CC65's exec() program-chaining function. +** These programs test cc65's exec() program-chaining function. ** exec-test1 runs exec-test2 -- that tests the loading and starting of another ** program. Then, exec-test2 runs arg-test -- that tests command-line argument ** passing. diff --git a/testcode/lib/exec-test2.c b/testcode/lib/exec-test2.c index e6c844a8e..a0aa82a3f 100644 --- a/testcode/lib/exec-test2.c +++ b/testcode/lib/exec-test2.c @@ -1,5 +1,5 @@ /* -** These programs test CC65's exec() program-chaining function. +** These programs test cc65's exec() program-chaining function. ** exec-test1 runs exec-test2 -- that tests the loading and starting of another ** program. Then, exec-test2 runs arg-test -- that tests command-line argument ** passing. diff --git a/testcode/lib/ft.c b/testcode/lib/ft.c index ff335240d..880df6369 100644 --- a/testcode/lib/ft.c +++ b/testcode/lib/ft.c @@ -1,19 +1,19 @@ /* - * simple file i/o test - * - * 12-Jun-2000, Christian Groessler - * - * please compile with - * cl65 -tsystem ft.c getsp.s -o ft.com - * - * The program asks for a filename (if it hasn't - * got one from argv). I then opens the file, - * reads the the first 16 bytes and displays them - * (as hex values). - * The values of sp (cc65 runtime stack pointer) - * are displayed at some places. The displayed - * value should always be the same. - */ +** simple file I/O test +** +** 12-Jun-2000, Christian Groessler +** +** please compile with +** cl65 -tsystem ft.c getsp.s -o ft.com +** +** The program asks for a filename (if it hasn't +** got one from argv). I then opens the file, +** reads the the first 16 bytes and displays them +** (as hex values). +** The values of sp (cc65 runtime stack pointer) +** are displayed at some places. The displayed +** value should always be the same. +*/ #include <stdio.h> #include <string.h> diff --git a/testcode/lib/getopt-test.c b/testcode/lib/getopt-test.c index 28dbd025d..2f1155419 100644 --- a/testcode/lib/getopt-test.c +++ b/testcode/lib/getopt-test.c @@ -1,17 +1,17 @@ /* - * This is part of a changed public domain getopt implementation that - * had the following text on top: - * - * I got this off net.sources from Henry Spencer. - * It is a public domain getopt(3) like in System V. - * I have made the following modifications: - * - * A test main program was added, ifdeffed by GETOPT. - * This main program is a public domain implementation - * of the getopt(1) program like in System V. The getopt - * program can be used to standardize shell option handling. - * e.g. cc -DGETOPT getopt.c -o getopt - */ +** This is part of a changed public domain getopt implementation that +** had the following text on top: +** +** I got this off net.sources from Henry Spencer. +** It is a public domain getopt(3) like in System V. +** I have made the following modifications: +** +** A test main program was added, ifdeffed by GETOPT. +** This main program is a public domain implementation +** of the getopt(1) program like in System V. The getopt +** program can be used to standardize shell option handling. +** e.g. cc -DGETOPT getopt.c -o getopt +*/ #include <stdio.h> #include <stdlib.h> diff --git a/testcode/lib/heaptest.c b/testcode/lib/heaptest.c index fb10646cd..d776e2f0c 100644 --- a/testcode/lib/heaptest.c +++ b/testcode/lib/heaptest.c @@ -20,8 +20,8 @@ static char* Alloc (void) unsigned char* P = malloc (Size); /* Set the string to a defined value. We use the size, since this will - * also allow us to retrieve it later. - */ + ** also allow us to retrieve it later. + */ if (P) { memset (P, Size, Size); } else { diff --git a/testcode/lib/joy-test.c b/testcode/lib/joy-test.c index c4bda1e53..0a5c80902 100644 --- a/testcode/lib/joy-test.c +++ b/testcode/lib/joy-test.c @@ -6,31 +6,65 @@ #include <joystick.h> +#ifdef JOYSTICK_DRIVER + +/* A statically linked driver was named on the compiler's command line. +** Make sure that it is used instead of a dynamic one. +*/ +# undef DYN_DRV +# define DYN_DRV 0 +#else + +/* Use a dynamically loaded driver, by default. */ +# ifndef DYN_DRV +# define DYN_DRV 1 +# endif +#endif + + int main (void) { unsigned char j; unsigned char count; unsigned char i; -#ifdef __NES__ - extern void *co65_joy; - unsigned char Res = joy_install (&co65_joy); -#else +#if DYN_DRV unsigned char Res = joy_load_driver (joy_stddrv); +#elif defined(JOYSTICK_DRIVER) + unsigned char Res = joy_install (&JOYSTICK_DRIVER); +#else + unsigned char Res = joy_install (&joy_static_stddrv); #endif + if (Res != JOY_ERR_OK) { cprintf ("Error in joy_load_driver: %u\r\n", Res); +#if DYN_DRV cprintf ("os: %u, %s\r\n", _oserror, _stroserror (_oserror)); +#endif exit (EXIT_FAILURE); } clrscr (); count = joy_count (); +#ifdef __ATARI5200__ + cprintf ("JOYSTICKS: %d", count); +#else cprintf ("Driver supports %d joystick(s)", count); +#endif while (1) { for (i = 0; i < count; ++i) { gotoxy (0, i+1); j = joy_read (i); +#ifdef __ATARI5200__ + cprintf ("%1d:%-3s%-3s%-3s%-3s%-3s%-3s", + i, + (j & joy_masks[JOY_UP])? " U " : " u ", + (j & joy_masks[JOY_DOWN])? " D " : " d ", + (j & joy_masks[JOY_LEFT])? " L " : " l ", + (j & joy_masks[JOY_RIGHT])? " R " : " r ", + (j & joy_masks[JOY_FIRE])? " 1 " : " ", + (j & joy_masks[JOY_FIRE2])? " 2 " : " "); +#else cprintf ("%2d: %-6s%-6s%-6s%-6s%-6s%-6s", i, (j & joy_masks[JOY_UP])? " up " : " ---- ", @@ -39,8 +73,8 @@ int main (void) (j & joy_masks[JOY_RIGHT])? "right " : " ---- ", (j & joy_masks[JOY_FIRE])? " fire " : " ---- ", (j & joy_masks[JOY_FIRE2])? "fire2 " : " ---- "); +#endif } } return 0; } - diff --git a/testcode/lib/mul-test.c b/testcode/lib/mul-test.c index 5db42d4ab..2daf5aa06 100644 --- a/testcode/lib/mul-test.c +++ b/testcode/lib/mul-test.c @@ -6,8 +6,8 @@ /* Number of elements in the progress bar. Use a power of 2, to avoid the - * multiplication (which is about to be tested). - */ +** multiplication (which is about to be tested). +*/ #define BAR_ELEMENTS 32U #if defined(__CBM__) diff --git a/testcode/lib/scanf-test.c b/testcode/lib/scanf-test.c index 85cfe39a7..9fce01b77 100644 --- a/testcode/lib/scanf-test.c +++ b/testcode/lib/scanf-test.c @@ -78,8 +78,9 @@ static const struct { {"qwerty 095 2", "qwerty %i%i", 2, INT, {0} , INT, {95}}, {"qwerty 0e5 2", "qwerty %i%i", 1, INT, {0} , INT, {0}}, - /* (String pointers are cast as (int), - * in order to avoid cc65 warnings.) */ + /* [String pointers are cast as (int), + ** in order to avoid cc65 warnings.] + */ /* Test that character specifiers can handle end-of-file. */ {"qwerty" , "qwerty %s%s" , EOF, CHAR, {(int)""}, CHAR, {(int)""}}, diff --git a/testcode/lib/seek.c b/testcode/lib/seek.c index a01e6e94f..0cb1c6ad6 100644 --- a/testcode/lib/seek.c +++ b/testcode/lib/seek.c @@ -1,6 +1,6 @@ /* - * seek test program - */ +** seek test program +*/ #include <stdio.h> #include <string.h> diff --git a/testcode/lib/ser-test.c b/testcode/lib/ser-test.c index c929189a3..6e3f5fc8a 100644 --- a/testcode/lib/ser-test.c +++ b/testcode/lib/ser-test.c @@ -17,6 +17,10 @@ #define DRIVERNAME "a2e.ssc.ser" #elif defined(__APPLE2__) #define DRIVERNAME "a2.ssc.ser" +#elif defined(__ATARIXL__) +#define DRIVERNAME "atrxrdev.ser" +#elif defined(__ATARI__) +#define DRIVERNAME "atrrdev.ser" #else #define DRIVERNAME "unknown" #error "Unknown target system" @@ -24,7 +28,7 @@ static const struct ser_params Params = { - SER_BAUD_19200, /* Baudrate */ + SER_BAUD_9600, /* Baudrate */ SER_BITS_8, /* Number of data bits */ SER_STOP_1, /* Number of stop bits */ SER_PAR_NONE, /* Parity setting */ diff --git a/testcode/lib/sprintf-test.c b/testcode/lib/sprintf-test.c index 36fd4f4a5..55354be20 100644 --- a/testcode/lib/sprintf-test.c +++ b/testcode/lib/sprintf-test.c @@ -18,8 +18,8 @@ /* Struct used to test the 'n' conversion specifier. It is machine dependent / - * not portable. - */ +** not portable. +*/ typedef union WriteCount WriteCount; union WriteCount { signed char C; @@ -41,9 +41,9 @@ static unsigned Failures = 0; static void OneTest (int Line, const char* RString, int RCount, const char* Format, ...) /* Test one conversion. Line is the line number (to make the life of the - * tester easier), RString the expected result and RCount the expected return - * count. The other parameters are used for formatting. - */ +** tester easier), RString the expected result and RCount the expected return +** count. The other parameters are used for formatting. +*/ { int Count; char Buf[128]; @@ -70,9 +70,9 @@ static void OneTest (int Line, const char* RString, int RCount, const char* Form static void WriteTest (int Line, const char* Format, WriteCount* W, long Count) /* Test one write conversion. Line is the line number (to make the life of the - * tester easier), Format is the format specification. W is a WriteCount - * variable and Count is the expected result. - */ +** tester easier), Format is the format specification. W is a WriteCount +** variable and Count is the expected result. +*/ { /* Clear the counter in full length */ W->L = 0x5A5A5A5AL; @@ -227,9 +227,9 @@ int main (void) OneTest (__LINE__, "EF98", 4, "%+X", -4200U); /* ' ': If the first character of a signed conversion is not a sign, or if - * a signed conversion results in no characters, a space is prefixed - * to the result. - */ + ** a signed conversion results in no characters, a space is prefixed + ** to the result. + */ OneTest (__LINE__, "u", 1, "% c", 'u'); OneTest (__LINE__, " 4200", 5, "% d", 4200); OneTest (__LINE__, "-4200", 5, "% d", -4200); @@ -310,10 +310,10 @@ int main (void) OneTest (__LINE__, "EF98 ", 15, "%-15X", -4200U); /* A negative field width specified via an argument is treated as if the - * '-' flag and a positive field width were given. - * - * Beware: These tests will crash the old printf routine! - */ + ** '-' flag and a positive field width were given. + ** + ** Beware: These tests will crash the old printf routine! + */ #ifndef NOCRASH OneTest (__LINE__, "u ", 15, "%*c", -15, 'u'); OneTest (__LINE__, "4200 ", 15, "%*d", -15, 4200); @@ -442,8 +442,8 @@ int main (void) OneTest (__LINE__, " 000000EF98", 15, "%15.10X", -4200U); /* For d, i, o, u, x and X conversions, if a precision is specified, the - * '0' flag is ignored. - */ + ** '0' flag is ignored. + */ OneTest (__LINE__, " 0000004200", 15, "%015.10d", 4200); OneTest (__LINE__, " -0000004200", 15, "%015.10d", -4200); OneTest (__LINE__, " 0000004200", 15, "%015.10i", 4200); diff --git a/testcode/lib/strqtok-test.c b/testcode/lib/strqtok-test.c new file mode 100644 index 000000000..27328cc4a --- /dev/null +++ b/testcode/lib/strqtok-test.c @@ -0,0 +1,51 @@ +/* strqtok-test.c +** +** 2014-04-21, Paul Foerster +** 2014-05-20, Greg King +** +** This program tests that strqtok() correctly will parse strings +** with quotation marks in them. It should show this list of tokens +** from the test strings: +** +** >This< +** > is only < +** >a< +** >short< +** >quoting< +** >test , honoring blanks, commas< +** >and< +** >(4)< +** >empty< +** >< +** >< +** >< +** >< +** >strings, EOT < +** +** It shouldn't show +** +** >Bogus token< +** +*/ + +#include <string.h> +#include <stdio.h> + +void main (void) +{ + /* b[] and s[] are declared as automatic, not static, variables + ** because strqtok() will change them. + ** They must be defined together; and, b[] must be defined first + ** (because they're copied onto the top-down stack). + */ + char b[] = "Bogus token "; + char s[] = " This , \" is only \"a short " + "quoting\"test , honoring blanks" + ", commas\", and (4) empty \"\"\"\"\"\"\"\" \"strings, EOT "; + char* t = strqtok (s, " ,"); + + while (t != NULL) { + printf (">%s<\n", t); + t = strqtok (NULL, " ,"); + } +} diff --git a/testcode/lib/strtol-test.c b/testcode/lib/strtol-test.c index db64c144d..86c56d4db 100644 --- a/testcode/lib/strtol-test.c +++ b/testcode/lib/strtol-test.c @@ -22,8 +22,8 @@ static unsigned int Failures = 0; static void IncStr (char* Buf) /* Increment a number represented as a string by one. The string MUST not - * start with a '9', we cannot handle overflow in this case. - */ +** start with a '9', we cannot handle overflow in this case. +*/ { int Len = strlen (Buf); diff --git a/testcode/lib/strtoul-test.c b/testcode/lib/strtoul-test.c index afd0decd9..cc37d1dd4 100644 --- a/testcode/lib/strtoul-test.c +++ b/testcode/lib/strtoul-test.c @@ -22,8 +22,8 @@ static unsigned int Failures = 0; static void IncStr (char* Buf) /* Increment a number represented as a string by one. The string MUST not - * start with a '9', we cannot handle overflow in this case. - */ +** start with a '9', we cannot handle overflow in this case. +*/ { int Len = strlen (Buf); diff --git a/testcode/lib/tinyshell.c b/testcode/lib/tinyshell.c index 141065257..de57a3d0e 100644 --- a/testcode/lib/tinyshell.c +++ b/testcode/lib/tinyshell.c @@ -1,7 +1,7 @@ /* - * Simple ("tiny") shell to test filename and directory functions. - * Copyright (c) 2013, Christian Groessler, chris@groessler.org - */ +** Simple ("tiny") shell to test filename and directory functions. +** Copyright (c) 2013, Christian Groessler, chris@groessler.org +*/ #define VERSION_ASC "0.90" diff --git a/src/ca65html/ca65html b/util/ca65html old mode 100755 new mode 100644 similarity index 100% rename from src/ca65html/ca65html rename to util/ca65html diff --git a/util/zlib/deflater.c b/util/zlib/deflater.c index 34fac2779..32d01a36e 100644 --- a/util/zlib/deflater.c +++ b/util/zlib/deflater.c @@ -1,11 +1,11 @@ /* - * Compresses data to the DEFLATE format. - * The compressed data is ready to use with inflatemem(). - * Compile using e.g. - * gcc -O2 -o deflater deflater.c -lz - * - * Author: Piotr Fusik <fox@scene.pl> - */ +** Compresses data to the DEFLATE format. +** The compressed data is ready to use with inflatemem(). +** Compile using e.g. +** gcc -O2 -o deflater deflater.c -lz +** +** Author: Piotr Fusik <fox@scene.pl> +*/ #include <stdio.h> #include <stdlib.h> #include <zlib.h>