]> git.sur5r.net Git - cc65/commitdiff
Merge remote-tracking branch 'upstream/master' into pcenginetarget
authormrdudz <mrdudz@users.noreply.github.com>
Mon, 20 Jul 2015 16:42:04 +0000 (18:42 +0200)
committermrdudz <mrdudz@users.noreply.github.com>
Mon, 20 Jul 2015 16:42:04 +0000 (18:42 +0200)
libsrc/common/vsnprintf.s
libsrc/sim6502/errno.s
samples/Makefile
samples/README
src/ca65/scanner.c
testcode/lib/snprintf-test.c [new file with mode: 0644]

index a8ed50e065395c4a8e95d178a674fb81ea1e9968..228e531d0430b72829c6bfdc9aef1a2b75264e86 100644 (file)
@@ -1,7 +1,8 @@
 ;
 ; int __fastcall__ vsnprintf (char* Buf, size_t size, const char* Format, va_list ap);
 ;
-; Ullrich von Bassewitz, 2009-09-26
+; 2009-09-26, Ullrich von Bassewitz
+; 2015-07-17, Greg King
 ;
 
         .export         _vsnprintf, vsnprintf
@@ -9,6 +10,8 @@
         .import         _memcpy, __printf
         .importzp       sp, ptr1
 
+        .include        "errno.inc"
+
         .macpack        generic
 
 .data
@@ -46,8 +49,10 @@ vsnprintf:
         sta     ccount+1        ; Clear ccount
 
 ; Get the size parameter and replace it by a pointer to outdesc. This is to
-; build a stack frame for the call to _printf.
-; If size is zero, there's nothing to do.
+; build a stack frame for the call to _printf. The size must not be greater
+; than INT_MAX because the return type is int. If the size is zero,
+; then nothing will be written into the buffer; but, the arguments still will
+; be formatted and counted.
 
         ldy     #2
         lda     (sp),y
@@ -58,15 +63,13 @@ vsnprintf:
 
         iny
         lda     (sp),y
+        bmi     L9              ; More than $7FFF
         sta     ptr1+1
 
-        ora     ptr1
-        beq     L9
-
         lda     #>outdesc
         sta     (sp),y
 
-; Write size-1 to outdesc.uns
+; Write size-1 to outdesc.uns.  It will be -1 if there is no buffer.
 
         ldy     ptr1+1
         ldx     ptr1
@@ -83,24 +86,32 @@ L1:     dex
         sta     bufptr+0
         stx     bufptr+1
 
+; There must be a buffer if its size is non-zero.
+
+        bit     bufsize+1
+        bmi     L5
+        ora     bufptr+1
+        bze     L0              ; The pointer shouldn't be NULL
+
 ; Restore ap and call _printf
 
-        pla
+L5:     pla
         tax
         pla
         jsr     __printf
 
-; Terminate the string. The last char is either at bufptr+ccount or
-; bufptr+bufsize, whichever is smaller.
+; Terminate the string if there is a buffer.  The last char. is at either
+; bufptr+bufsize or bufptr+ccount, whichever is smaller.
 
-        lda     ccount+0
-        ldx     ccount+1
-        cpx     bufsize+1
+        ldx     bufsize+1
+        bmi     L4              ; -1 -- No buffer
+        lda     bufsize+0
+        cpx     ccount+1
         bne     L2
-        cmp     bufsize+0
+        cmp     ccount+0
 L2:     bcc     L3
-        lda     bufsize+0
-        ldx     bufsize+1
+        lda     ccount+0
+        ldx     ccount+1
         clc
 L3:     adc     bufptr+0
         sta     ptr1
@@ -114,16 +125,22 @@ L3:     adc     bufptr+0
 
 ; Return the number of bytes written and drop buf
 
-        lda     ccount+0
+L4:     lda     ccount+0
         ldx     ccount+1
         jmp     incsp2
 
-; Bail out if size is zero.
+; Bail out if size is too high.
 
-L9:     pla
-        pla                     ; Discard ap
-        lda     #0
-        tax
+L9:     ldy     #ERANGE
+        .byte   $2C             ;(bit $xxxx)
+
+; NULL buffer pointers usually are invalid.
+
+L0:     ldy     #EINVAL
+        pla                     ; Drop ap
+        pla
+        tya
+        jsr     __directerrno   ; Return -1
         jmp     incsp6          ; Drop parameters
 
 
@@ -146,10 +163,11 @@ out:
         sbc     ccount+0                ; Low byte of bytes already written
         sta     ptr1
         lda     bufsize+1
+        bmi     @L9                     ; -1 -- No buffer
         sbc     ccount+1
         sta     ptr1+1
         bcs     @L0                     ; Branch if space left
-        lda     #$00
+@L9:    lda     #$0000
         sta     ptr1
         sta     ptr1+1                  ; No space left
 
index e6c2422c126eab3019f81e3657c427623f31e6a8..d9f7e397ec07fabd12653965c439749c316da2d0 100644 (file)
@@ -1,11 +1,29 @@
 ;
-; Oliver Schmidt, 2013-05-16
+; 2013-05-16, Oliver Schmidt
+; 2015-07-18, Greg King
 ;
-; extern int errno;
+; Helper functions for several high-level functions.
 ;
 
         .include        "errno.inc"
 
+; ----------------------------------------------------------------------------
+; int __fastcall__ _directerrno (unsigned char code);
+; /* Set errno to a specific error code; and, return -1. Used
+; ** by the library.
+; */
+
+__directerrno:
+        jsr     __seterrno              ; Save in errno
+fail:   lda     #$FF                    ; Return -1
+        tax
+ok:     rts
+
+
+; ----------------------------------------------------------------------------
+;
+; extern int _errno;
+;
         .bss
 
 __errno:
index 79988ea7085fdff2f2118d652ba47251eafb755f..951706ce6a50c674e1f670b2ae8b7f5065886149 100644 (file)
@@ -44,7 +44,7 @@ endif
 C1541  = c1541
 
 # --------------------------------------------------------------------------
-# System dependent settings
+# System-dependent settings
 
 # The Apple machines need the start address adjusted when using TGI
 LDFLAGS_mandelbrot_apple2 = --start-addr 0x4000
@@ -81,10 +81,10 @@ LDFLAGS_tgidemo_atari = -D __RESERVED_MEMORY__=0x2000
 .PRECIOUS: %.o
 
 .o:
-       @$(LD) $(LDFLAGS_$(basename $@)_$(SYS)) -o $@ -t $(SYS) -m $@.map $^ $(CLIB)
+       @$(LD) $(LDFLAGS_$(@F)_$(SYS)) -o $@ -t $(SYS) -m $@.map $^ $(CLIB)
 
 # --------------------------------------------------------------------------
-# List of executables. This list could be made target dependent by checking
+# List of executables. This list could be made target-dependent by checking
 # $(SYS).
 
 EXELIST        =       ascii           \
@@ -103,13 +103,23 @@ EXELIST   =       ascii           \
                tgidemo
 
 # --------------------------------------------------------------------------
-# Rules how to make each one of the binaries
+# Rules to make the binaries
 
 .PHONY:        all
 all:   $(EXELIST)
 
 # --------------------------------------------------------------------------
-# Rule to make a disk with all samples. Needs the c1541 program that comes
+# Overlay rules. Overlays need special ld65 configuration files.  Also, the
+# overlay file-names are shortenned to fit the Atari's 8.3-character limit.
+
+multdemo:      multidemo.o
+       @$(LD) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(CLIB)
+
+ovrldemo:      overlaydemo.o
+       @$(LD) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(CLIB)
+
+# --------------------------------------------------------------------------
+# Rule to make a CBM disk with all samples. Needs the c1541 program that comes
 # with the VICE emulator.
 
 .PHONY:        disk
@@ -125,7 +135,7 @@ samples.d64:        all
        done
 
 # --------------------------------------------------------------------------
-# Cleanup rules
+# Clean-up rules
 
 .PHONY:        clean
 clean:
@@ -134,3 +144,4 @@ clean:
 .PHONY:        zap
 zap:   clean
        $(RM) $(EXELIST) samples.d64
+       $(RM) multdemo.? ovrldemo.?
index 5997fc8d04aba01d5c4608912586a187d232dc98..edd06ff02bd0c28a0223d4997b77154f4bd606ba 100644 (file)
@@ -11,6 +11,7 @@ Please note:
     the programs manually.
 
   * The makefile specifies the C64 as the default target platform, because all
+    but one
     of the programs run on this platform. When compiling for another platform,
     you will have to change the line that specifies the target system at the
     top of the makefile.
index 97ed2c9d9014f0e440cc39ac8ecc23bd3507b4b1..20053e7e6a332f0939d731226210c1c4442bfe44 100644 (file)
@@ -1012,7 +1012,7 @@ Again:
                 break;
             }
             DVal = DigitVal (Buf[I]);
-            if (DVal > Base) {
+            if (DVal >= Base) {
                 Error ("Invalid digits in number");
                 CurTok.IVal = 0;
                 break;
diff --git a/testcode/lib/snprintf-test.c b/testcode/lib/snprintf-test.c
new file mode 100644 (file)
index 0000000..d3af47d
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+** Test a function that formats and writes characters into a string buffer.
+** This program does not test formatting.  It tests some behaviors that are
+** specific to the buffer.  It tests that certain conditions are handled
+** properly.
+**
+** 2015-07-17, Greg King
+*/
+
+#include <conio.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+static const char format[] = "1234567890\nabcdefghijklmnopqrstuvwxyz\n%u\n%s\n\n";
+#define FORMAT_SIZE (sizeof format - 2u - 2u - 1u)
+
+#define arg1 12345u
+#define ARG1_SIZE (5u)
+
+static const char arg2[] = "!@#$%^&*()-+";
+#define ARG2_SIZE (sizeof arg2 - 1u)
+
+#define STRING_SIZE (FORMAT_SIZE + ARG1_SIZE + ARG2_SIZE)
+
+static char buf[256];
+static int size;
+
+
+static void fillbuf(void)
+{
+    memset(buf, 0xFF, sizeof buf - 1u);
+    buf[sizeof buf - 1u] = '\0';
+}
+
+
+unsigned char main(void)
+{
+    static unsigned char failures = 0;
+
+    /* Show what sprintf() should create. */
+
+    if ((size = printf(format, arg1, arg2)) != STRING_SIZE) {
+        ++failures;
+        printf("printf() gave the wrong size: %d.\n", size);
+    }
+
+    /* Test the normal behavior of sprintf(). */
+
+    fillbuf();
+    size = sprintf(buf, format, arg1, arg2);
+    fputs(buf, stdout);
+    if (size != STRING_SIZE) {
+        ++failures;
+        printf("sprintf() gave the wrong size: %d.\n", size);
+    }
+
+    /* Test the normal behavior of snprintf(). */
+
+    fillbuf();
+    size = snprintf(buf, sizeof buf, format, arg1, arg2);
+    fputs(buf, stdout);
+    if (size != STRING_SIZE) {
+        ++failures;
+        printf("snprintf(sizeof buf) gave the wrong size:\n %d.\n", size);
+    }
+
+    /* Does snprintf() return the full-formatted size even when the buffer
+    ** is short?  Does it write beyond the end of that buffer?
+    */
+
+    fillbuf();
+    size = snprintf(buf, STRING_SIZE - 5u, format, arg1, arg2);
+    if (size != STRING_SIZE) {
+        ++failures;
+        printf("snprintf(STRING_SIZE-5) gave the wrong size:\n %d.\n", size);
+    }
+    if (buf[STRING_SIZE - 5u - 1u] != '\0' || buf[STRING_SIZE - 5u] != 0xFF) {
+        ++failures;
+        printf("snprintf(STRING_SIZE-5) wrote beyond\n the end of the buffer.\n");
+    }
+
+    /* Does snprintf() detect a buffer size that is too big? */
+
+    fillbuf();
+    errno = 0;
+    size = snprintf(buf, 0x8000, format, arg1, arg2);
+    if (size >= 0) {
+        ++failures;
+        printf("snprintf(0x8000) didn't give an error:\n %d; errno=%d.\n", size, errno);
+    } else {
+        printf("snprintf(0x8000) did give an error:\n errno=%d.\n", errno);
+    }
+    if (buf[0] != 0xFF) {
+        ++failures;
+        printf("snprintf(0x8000) wrote into the buffer.\n");
+    }
+
+    /* snprintf() must measure the length of the formatted output even when the
+    ** buffer size is zero.  But, it must not touch the buffer.
+    */
+
+    fillbuf();
+    size = snprintf(buf, 0, format, arg1, arg2);
+    if (size != STRING_SIZE) {
+        ++failures;
+        printf("snprintf(0) gave the wrong size:\n %d.\n", size);
+    }
+    if (buf[0] != 0xFF) {
+        ++failures;
+        printf("snprintf(0) wrote into the buffer.\n");
+    }
+
+    /* Does sprintf() detect a zero buffer-pointer? */
+
+    errno = 0;
+    size = sprintf(NULL, format, arg1, arg2);
+    if (size >= 0) {
+        ++failures;
+        printf("sprintf(NULL) didn't give an error:\n %d; errno=%d.\n", size, errno);
+    } else {
+        printf("sprintf(NULL) did give an error:\n errno=%d.\n", errno);
+    }
+
+    /* snprintf() must measure the length of the formatted output even when the
+    ** buffer size is zero.  A zero pointer is not an error, in that case.
+    */
+
+    size = snprintf(NULL, 0, format, arg1, arg2);
+    if (size != STRING_SIZE) {
+        ++failures;
+        printf("snprintf(NULL,0) gave the wrong size:\n %d.\n", size);
+    }
+
+    if (failures != 0) {
+        printf("There were %u", failures);
+    } else {
+        printf("There were no");
+    }
+    printf(" failures.\nTap a key. ");
+    cgetc();
+
+    return failures;
+}