sw: fix line endings

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2019-04-11 15:53:08 +08:00
parent f30fbce79f
commit e5a2b29456
11 changed files with 1139 additions and 1318 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,16 @@
#ifndef __GENERATED_MEM_H #ifndef __GENERATED_MEM_H
#define __GENERATED_MEM_H #define __GENERATED_MEM_H
#define SRAM_BASE 0x10000000 #define VEXRISCV_DEBUG_BASE 0xf00f0000
#define SRAM_SIZE 0x00020000 #define VEXRISCV_DEBUG_SIZE 0x00000010
#define ROM_BASE 0x00000000 #define SRAM_BASE 0x10000000
#define ROM_SIZE 0x00002000 #define SRAM_SIZE 0x00020000
#define SPIFLASH_BASE 0x20000000 #define ROM_BASE 0x00000000
#define SPIFLASH_SIZE 0x00200000 #define ROM_SIZE 0x00002000
#endif #define SPIFLASH_BASE 0x20000000
#define SPIFLASH_SIZE 0x00200000
#endif

View File

@ -58,12 +58,9 @@ static inline void mtspr(unsigned long add, unsigned long val)
#include <generated/csr.h> #include <generated/csr.h>
__attribute__((noreturn)) static inline void reboot(void) { __attribute__((noreturn)) void reboot(void);
reboot_ctrl_write(0xac);
while (1);
}
__attribute__((noreturn)) static inline void reboot_to_image(uint8_t image_index) { __attribute__((noreturn)) static inline void warmboot_to_image(uint8_t image_index) {
reboot_ctrl_write(0xac | (image_index & 3) << 0); reboot_ctrl_write(0xac | (image_index & 3) << 0);
while (1); while (1);
} }

View File

@ -1 +1 @@
OUTPUT_FORMAT("elf32-littleriscv") OUTPUT_FORMAT("elf32-littleriscv")

View File

@ -1,4 +1,4 @@
MEMORY { MEMORY {
sram : ORIGIN = 0x10000000, LENGTH = 0x00020000 sram : ORIGIN = 0x10000000, LENGTH = 0x00020000
rom : ORIGIN = 0x00000000, LENGTH = 0x00002000 rom : ORIGIN = 0x00000000, LENGTH = 0x00002000
} }

View File

@ -1,113 +1,135 @@
#include <stdio.h> #include <stdio.h>
#include <irq.h> #include <irq.h>
#include <printf.h> #include <printf.h>
#include <uart.h> #include <uart.h>
#include <usb.h> #include <usb.h>
#include <time.h> #include <time.h>
#include <dfu.h> #include <dfu.h>
#include <rgb.h> #include <rgb.h>
#include <spi.h> #include <spi.h>
#include <generated/csr.h> #include <generated/csr.h>
struct ff_spi *spi; struct ff_spi *spi;
void isr(void) void isr(void)
{ {
unsigned int irqs; unsigned int irqs;
irqs = irq_pending() & irq_getmask(); irqs = irq_pending() & irq_getmask();
if (irqs & (1 << USB_INTERRUPT)) if (irqs & (1 << USB_INTERRUPT))
usb_isr(); usb_isr();
#ifdef CSR_UART_BASE #ifdef CSR_UART_BASE
if (irqs & (1 << UART_INTERRUPT)) if (irqs & (1 << UART_INTERRUPT))
uart_isr(); uart_isr();
#endif #endif
} }
#ifdef CSR_UART_BASE #ifdef CSR_UART_BASE
static void rv_putchar(void *ignored, char c) static void rv_putchar(void *ignored, char c)
{ {
(void)ignored; (void)ignored;
if (c == '\n') if (c == '\n')
uart_write('\r'); uart_write('\r');
if (c == '\r') if (c == '\r')
return; return;
uart_write(c); uart_write(c);
} }
#endif #endif
void reboot_to(uint32_t addr) { #define REBOOT_ADDR 0x20040000
irq_setie(0); void reboot(void) {
usb_disconnect(); irq_setie(0);
spiFree(); irq_setmask(0);
rgb_mode_error(); usb_disconnect();
/* spiFree();
* Set the return address register to the base of the DDR memory at 0x80000000. rgb_mode_error();
* The reset handler of the application loaded to DDR memory by the bootloader
* is expected to be at that location. // Check the first few words for the sync pulse;
*/ int i;
void (*fnc)(void) = (void *)addr; int riscv_boot = 1;
fnc(); uint32_t *destination_array = (uint32_t *)REBOOT_ADDR;
__builtin_unreachable(); for (i = 0; i < 16; i++) {
asm volatile("mv ra,%0\n\t" if (destination_array[i] == 0x7e99aa7e) {
: riscv_boot = 0;
: "r"(addr) break;
); }
}
/*
* Flush the cache. if (riscv_boot) {
*/ // Reset the Return Address, zero out some registers, and return.
// asm volatile ("fence.i"); asm volatile(
"mv ra,%0\n\t" /* x1 */
/* "mv sp,zero\n\t" /* x2 */
* We need to explicitly execute a return intruction in case the compiler had "mv gp,zero\n\t" /* x3 */
* done some return addres register manipulation in this function's veneer. "mv tp,zero\n\t" /* x4 */
*/ "mv t0,zero\n\t" /* x5 */
asm volatile("ret"); "mv t1,zero\n\t" /* x6 */
__builtin_unreachable(); "mv t2,zero\n\t" /* x7 */
} "mv x8,zero\n\t" /* x8 */
"mv s1,zero\n\t" /* x9 */
static void init(void) "mv a0,zero\n\t" /* x10 */
{ "mv a1,zero\n\t" /* x11 */
#ifdef CSR_UART_BASE
init_printf(NULL, rv_putchar); // /* Flush the caches */
#endif // ".word 0x400f\n\t"
irq_setmask(0); // "nop\n\t"
irq_setie(1); // "nop\n\t"
uart_init(); // "nop\n\t"
usb_init();
dfu_init(); "ret\n\t"
time_init();
rgb_init(); :
: "r"(REBOOT_ADDR)
spi = spiAlloc(); );
spiSetPin(spi, SP_MOSI, 0); }
spiSetPin(spi, SP_MISO, 1); else {
spiSetPin(spi, SP_WP, 2); // Issue a reboot
spiSetPin(spi, SP_HOLD, 3); warmboot_to_image(2);
spiSetPin(spi, SP_CLK, 4); }
spiSetPin(spi, SP_CS, 5); __builtin_unreachable();
spiSetPin(spi, SP_D0, 0); }
spiSetPin(spi, SP_D1, 1);
spiSetPin(spi, SP_D2, 2); static void init(void)
spiSetPin(spi, SP_D3, 3); {
spiInit(spi); #ifdef CSR_UART_BASE
} init_printf(NULL, rv_putchar);
#endif
int main(int argc, char **argv) irq_setmask(0);
{ irq_setie(1);
(void)argc; uart_init();
(void)argv; usb_init();
dfu_init();
init(); time_init();
rgb_init();
usb_connect();
while (1) spi = spiAlloc();
{ spiSetPin(spi, SP_MOSI, 0);
usb_poll(); spiSetPin(spi, SP_MISO, 1);
dfu_poll(); spiSetPin(spi, SP_WP, 2);
} spiSetPin(spi, SP_HOLD, 3);
return 0; spiSetPin(spi, SP_CLK, 4);
spiSetPin(spi, SP_CS, 5);
spiSetPin(spi, SP_D0, 0);
spiSetPin(spi, SP_D1, 1);
spiSetPin(spi, SP_D2, 2);
spiSetPin(spi, SP_D3, 3);
spiInit(spi);
}
int main(int argc, char **argv)
{
(void)argc;
(void)argv;
init();
usb_connect();
while (1)
{
usb_poll();
dfu_poll();
}
return 0;
} }

View File

@ -192,10 +192,7 @@ void usb_setup(const struct usb_setup_request *setup)
// to be received. // to be received.
usb_ack_in(); usb_ack_in();
usb_wait_for_send_done(); usb_wait_for_send_done();
reboot_to(0x20040000); reboot();
// Issue a reboot
reboot_to_image(0);
while (1) while (1)
; ;
return; return;

240
sw/third_party/div.S vendored
View File

@ -1,121 +1,121 @@
.text .text
.align 2 .align 2
#ifndef __riscv64 #ifndef __riscv64
/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */ /* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */
# define __udivdi3 __udivsi3 # define __udivdi3 __udivsi3
# define __umoddi3 __umodsi3 # define __umoddi3 __umodsi3
# define __divdi3 __divsi3 # define __divdi3 __divsi3
# define __moddi3 __modsi3 # define __moddi3 __modsi3
#else #else
.globl __udivsi3 .globl __udivsi3
__udivsi3: __udivsi3:
/* Compute __udivdi3(a0 << 32, a1 << 32); cast result to uint32_t. */ /* Compute __udivdi3(a0 << 32, a1 << 32); cast result to uint32_t. */
sll a0, a0, 32 sll a0, a0, 32
sll a1, a1, 32 sll a1, a1, 32
move t0, ra move t0, ra
jal __udivdi3 jal __udivdi3
sext.w a0, a0 sext.w a0, a0
jr t0 jr t0
.globl __umodsi3 .globl __umodsi3
__umodsi3: __umodsi3:
/* Compute __udivdi3((uint32_t)a0, (uint32_t)a1); cast a1 to uint32_t. */ /* Compute __udivdi3((uint32_t)a0, (uint32_t)a1); cast a1 to uint32_t. */
sll a0, a0, 32 sll a0, a0, 32
sll a1, a1, 32 sll a1, a1, 32
srl a0, a0, 32 srl a0, a0, 32
srl a1, a1, 32 srl a1, a1, 32
move t0, ra move t0, ra
jal __udivdi3 jal __udivdi3
sext.w a0, a1 sext.w a0, a1
jr t0 jr t0
.globl __modsi3 .globl __modsi3
__modsi3 = __moddi3 __modsi3 = __moddi3
.globl __divsi3 .globl __divsi3
__divsi3: __divsi3:
/* Check for special case of INT_MIN/-1. Otherwise, fall into __divdi3. */ /* Check for special case of INT_MIN/-1. Otherwise, fall into __divdi3. */
li t0, -1 li t0, -1
beq a1, t0, .L20 beq a1, t0, .L20
#endif #endif
.globl __divdi3 .globl __divdi3
__divdi3: __divdi3:
bltz a0, .L10 bltz a0, .L10
bltz a1, .L11 bltz a1, .L11
/* Since the quotient is positive, fall into __udivdi3. */ /* Since the quotient is positive, fall into __udivdi3. */
.globl __udivdi3 .globl __udivdi3
__udivdi3: __udivdi3:
mv a2, a1 mv a2, a1
mv a1, a0 mv a1, a0
li a0, -1 li a0, -1
beqz a2, .L5 beqz a2, .L5
li a3, 1 li a3, 1
bgeu a2, a1, .L2 bgeu a2, a1, .L2
.L1: .L1:
blez a2, .L2 blez a2, .L2
slli a2, a2, 1 slli a2, a2, 1
slli a3, a3, 1 slli a3, a3, 1
bgtu a1, a2, .L1 bgtu a1, a2, .L1
.L2: .L2:
li a0, 0 li a0, 0
.L3: .L3:
bltu a1, a2, .L4 bltu a1, a2, .L4
sub a1, a1, a2 sub a1, a1, a2
or a0, a0, a3 or a0, a0, a3
.L4: .L4:
srli a3, a3, 1 srli a3, a3, 1
srli a2, a2, 1 srli a2, a2, 1
bnez a3, .L3 bnez a3, .L3
.L5: .L5:
ret ret
.globl __umoddi3 .globl __umoddi3
__umoddi3: __umoddi3:
/* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */ /* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */
move t0, ra move t0, ra
jal __udivdi3 jal __udivdi3
move a0, a1 move a0, a1
jr t0 jr t0
/* Handle negative arguments to __divdi3. */ /* Handle negative arguments to __divdi3. */
.L10: .L10:
neg a0, a0 neg a0, a0
bgez a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */ bgez a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */
neg a1, a1 neg a1, a1
j __divdi3 /* Compute __udivdi3(-a0, -a1). */ j __divdi3 /* Compute __udivdi3(-a0, -a1). */
.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */ .L11: /* Compute __udivdi3(a0, -a1), then negate the result. */
neg a1, a1 neg a1, a1
.L12: .L12:
move t0, ra move t0, ra
jal __divdi3 jal __divdi3
neg a0, a0 neg a0, a0
jr t0 jr t0
.globl __moddi3 .globl __moddi3
__moddi3: __moddi3:
move t0, ra move t0, ra
bltz a1, .L31 bltz a1, .L31
bltz a0, .L32 bltz a0, .L32
.L30: .L30:
jal __udivdi3 /* The dividend is not negative. */ jal __udivdi3 /* The dividend is not negative. */
move a0, a1 move a0, a1
jr t0 jr t0
.L31: .L31:
neg a1, a1 neg a1, a1
bgez a0, .L30 bgez a0, .L30
.L32: .L32:
neg a0, a0 neg a0, a0
jal __udivdi3 /* The dividend is hella negative. */ jal __udivdi3 /* The dividend is hella negative. */
neg a0, a1 neg a0, a1
jr t0 jr t0
#ifdef __riscv64 #ifdef __riscv64
/* continuation of __divsi3 */ /* continuation of __divsi3 */
.L20: .L20:
sll t0, t0, 31 sll t0, t0, 31
bne a0, t0, __divdi3 bne a0, t0, __divdi3
ret ret
#endif #endif

View File

@ -1,117 +1,117 @@
/* $OpenBSD: strlen.c,v 1.8 2014/06/10 04:17:37 deraadt Exp $ */ /* $OpenBSD: strlen.c,v 1.8 2014/06/10 04:17:37 deraadt Exp $ */
/*- /*-
* Copyright (c) 1990, 1993 * Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include <string.h> #include <string.h>
size_t size_t
strlen(const char *str) strlen(const char *str)
{ {
const char *s; const char *s;
for (s = str; *s; ++s) for (s = str; *s; ++s)
; ;
return (s - str); return (s - str);
} }
/** /**
* memcpy - Copies one area of memory to another * memcpy - Copies one area of memory to another
* @dest: Destination * @dest: Destination
* @src: Source * @src: Source
* @n: The size to copy. * @n: The size to copy.
*/ */
void *memcpy(void *to, const void *from, size_t n) void *memcpy(void *to, const void *from, size_t n)
{ {
void *xto = to; void *xto = to;
size_t temp; size_t temp;
if(!n) if(!n)
return xto; return xto;
if((long)to & 1) { if((long)to & 1) {
char *cto = to; char *cto = to;
const char *cfrom = from; const char *cfrom = from;
*cto++ = *cfrom++; *cto++ = *cfrom++;
to = cto; to = cto;
from = cfrom; from = cfrom;
n--; n--;
} }
if((long)from & 1) { if((long)from & 1) {
char *cto = to; char *cto = to;
const char *cfrom = from; const char *cfrom = from;
for (; n; n--) for (; n; n--)
*cto++ = *cfrom++; *cto++ = *cfrom++;
return xto; return xto;
} }
if(n > 2 && (long)to & 2) { if(n > 2 && (long)to & 2) {
short *sto = to; short *sto = to;
const short *sfrom = from; const short *sfrom = from;
*sto++ = *sfrom++; *sto++ = *sfrom++;
to = sto; to = sto;
from = sfrom; from = sfrom;
n -= 2; n -= 2;
} }
if((long)from & 2) { if((long)from & 2) {
short *sto = to; short *sto = to;
const short *sfrom = from; const short *sfrom = from;
temp = n >> 1; temp = n >> 1;
for (; temp; temp--) for (; temp; temp--)
*sto++ = *sfrom++; *sto++ = *sfrom++;
to = sto; to = sto;
from = sfrom; from = sfrom;
if(n & 1) { if(n & 1) {
char *cto = to; char *cto = to;
const char *cfrom = from; const char *cfrom = from;
*cto = *cfrom; *cto = *cfrom;
} }
return xto; return xto;
} }
temp = n >> 2; temp = n >> 2;
if(temp) { if(temp) {
long *lto = to; long *lto = to;
const long *lfrom = from; const long *lfrom = from;
for(; temp; temp--) for(; temp; temp--)
*lto++ = *lfrom++; *lto++ = *lfrom++;
to = lto; to = lto;
from = lfrom; from = lfrom;
} }
if(n & 2) { if(n & 2) {
short *sto = to; short *sto = to;
const short *sfrom = from; const short *sfrom = from;
*sto++ = *sfrom++; *sto++ = *sfrom++;
to = sto; to = sto;
from = sfrom; from = sfrom;
} }
if(n & 1) { if(n & 1) {
char *cto = to; char *cto = to;
const char *cfrom = from; const char *cfrom = from;
*cto = *cfrom; *cto = *cfrom;
} }
return xto; return xto;
} }

52
sw/third_party/mul.S vendored
View File

@ -1,26 +1,26 @@
.text .text
.align 2 .align 2
#ifdef __riscv64 #ifdef __riscv64
#define _RISCV_SZPTR 64 #define _RISCV_SZPTR 64
#define _RISCV_SZINT 64 #define _RISCV_SZINT 64
#else #else
/* Our RV64 64-bit routine is equivalent to our RV32 32-bit routine. */ /* Our RV64 64-bit routine is equivalent to our RV32 32-bit routine. */
# define __muldi3 __mulsi3 # define __muldi3 __mulsi3
#define _RISCV_SZPTR 32 #define _RISCV_SZPTR 32
#define _RISCV_SZINT 32 #define _RISCV_SZINT 32
#endif #endif
.globl __muldi3 .globl __muldi3
__muldi3: __muldi3:
mv a2, a0 mv a2, a0
li a0, 0 li a0, 0
.L1: .L1:
slli a3, a1, _RISCV_SZPTR-1 slli a3, a1, _RISCV_SZPTR-1
bgez a3, .L2 bgez a3, .L2
add a0, a0, a2 add a0, a0, a2
.L2: .L2:
srli a1, a1, 1 srli a1, a1, 1
slli a2, a2, 1 slli a2, a2, 1
bnez a1, .L1 bnez a1, .L1
ret ret

View File

@ -1,268 +1,268 @@
/* /*
* Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs * Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met: * are permitted provided that the following conditions are met:
* *
* Redistributions of source code must retain the above copyright notice, this list * Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer. * of conditions and the following disclaimer.
* *
* Redistributions in binary form must reproduce the above copyright notice, this * Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other * list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. * materials provided with the distribution.
* *
* Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names of its * Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names of its
* contributors may be used to endorse or promote products derived from this software * contributors may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE. * OF SUCH DAMAGE.
*/ */
#include "printf.h" #include "printf.h"
typedef void (*putcf)(void *, char); typedef void (*putcf)(void *, char);
static putcf stdout_putf; static putcf stdout_putf;
static void *stdout_putp; static void *stdout_putp;
#ifdef PRINTF_LONG_SUPPORT #ifdef PRINTF_LONG_SUPPORT
static void uli2a(unsigned long int num, unsigned int base, int uc, char *bf) static void uli2a(unsigned long int num, unsigned int base, int uc, char *bf)
{ {
int n = 0; int n = 0;
unsigned int d = 1; unsigned int d = 1;
while (num / d >= base) while (num / d >= base)
d *= base; d *= base;
while (d != 0) while (d != 0)
{ {
int dgt = num / d; int dgt = num / d;
num %= d; num %= d;
d /= base; d /= base;
if (n || dgt > 0 || d == 0) if (n || dgt > 0 || d == 0)
{ {
*bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10); *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10);
++n; ++n;
} }
} }
*bf = 0; *bf = 0;
} }
static void li2a(long num, char *bf) static void li2a(long num, char *bf)
{ {
if (num < 0) if (num < 0)
{ {
num = -num; num = -num;
*bf++ = '-'; *bf++ = '-';
} }
uli2a(num, 10, 0, bf); uli2a(num, 10, 0, bf);
} }
#endif #endif
static void ui2a(unsigned int num, unsigned int base, int uc, char *bf) static void ui2a(unsigned int num, unsigned int base, int uc, char *bf)
{ {
int n = 0; int n = 0;
unsigned int d = 1; unsigned int d = 1;
while (num / d >= base) while (num / d >= base)
d *= base; d *= base;
while (d != 0) while (d != 0)
{ {
int dgt = num / d; int dgt = num / d;
num %= d; num %= d;
d /= base; d /= base;
if (n || dgt > 0 || d == 0) if (n || dgt > 0 || d == 0)
{ {
*bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10); *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10);
++n; ++n;
} }
} }
*bf = 0; *bf = 0;
} }
static void i2a(int num, char *bf) static void i2a(int num, char *bf)
{ {
if (num < 0) if (num < 0)
{ {
num = -num; num = -num;
*bf++ = '-'; *bf++ = '-';
} }
ui2a(num, 10, 0, bf); ui2a(num, 10, 0, bf);
} }
static int a2d(char ch) static int a2d(char ch)
{ {
if (ch >= '0' && ch <= '9') if (ch >= '0' && ch <= '9')
return ch - '0'; return ch - '0';
else if (ch >= 'a' && ch <= 'f') else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10; return ch - 'a' + 10;
else if (ch >= 'A' && ch <= 'F') else if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10; return ch - 'A' + 10;
else else
return -1; return -1;
} }
static char a2i(char ch, char **src, int base, int *nump) static char a2i(char ch, char **src, int base, int *nump)
{ {
char *p = *src; char *p = *src;
int num = 0; int num = 0;
int digit; int digit;
while ((digit = a2d(ch)) >= 0) while ((digit = a2d(ch)) >= 0)
{ {
if (digit > base) if (digit > base)
break; break;
num = num * base + digit; num = num * base + digit;
ch = *p++; ch = *p++;
} }
*src = p; *src = p;
*nump = num; *nump = num;
return ch; return ch;
} }
static void putchw(void *putp, putcf putf, int n, char z, char *bf) static void putchw(void *putp, putcf putf, int n, char z, char *bf)
{ {
char fc = z ? '0' : ' '; char fc = z ? '0' : ' ';
char ch; char ch;
char *p = bf; char *p = bf;
while (*p++ && n > 0) while (*p++ && n > 0)
n--; n--;
while (n-- > 0) while (n-- > 0)
putf(putp, fc); putf(putp, fc);
while ((ch = *bf++)) while ((ch = *bf++))
putf(putp, ch); putf(putp, ch);
} }
void tfp_format(void *putp, putcf putf, char *fmt, va_list va) void tfp_format(void *putp, putcf putf, char *fmt, va_list va)
{ {
char bf[12]; char bf[12];
char ch; char ch;
while ((ch = *(fmt++))) while ((ch = *(fmt++)))
{ {
if (ch != '%') if (ch != '%')
putf(putp, ch); putf(putp, ch);
else else
{ {
char lz = 0; char lz = 0;
#ifdef PRINTF_LONG_SUPPORT #ifdef PRINTF_LONG_SUPPORT
char lng = 0; char lng = 0;
#endif #endif
int w = 0; int w = 0;
ch = *(fmt++); ch = *(fmt++);
if (ch == '0') if (ch == '0')
{ {
ch = *(fmt++); ch = *(fmt++);
lz = 1; lz = 1;
} }
if (ch >= '0' && ch <= '9') if (ch >= '0' && ch <= '9')
{ {
ch = a2i(ch, &fmt, 10, &w); ch = a2i(ch, &fmt, 10, &w);
} }
#ifdef PRINTF_LONG_SUPPORT #ifdef PRINTF_LONG_SUPPORT
if (ch == 'l') if (ch == 'l')
{ {
ch = *(fmt++); ch = *(fmt++);
lng = 1; lng = 1;
} }
#endif #endif
switch (ch) switch (ch)
{ {
case 0: case 0:
goto abort; goto abort;
case 'u': case 'u':
{ {
#ifdef PRINTF_LONG_SUPPORT #ifdef PRINTF_LONG_SUPPORT
if (lng) if (lng)
uli2a(va_arg(va, unsigned long int), 10, 0, bf); uli2a(va_arg(va, unsigned long int), 10, 0, bf);
else else
#endif #endif
ui2a(va_arg(va, unsigned int), 10, 0, bf); ui2a(va_arg(va, unsigned int), 10, 0, bf);
putchw(putp, putf, w, lz, bf); putchw(putp, putf, w, lz, bf);
break; break;
} }
case 'd': case 'd':
{ {
#ifdef PRINTF_LONG_SUPPORT #ifdef PRINTF_LONG_SUPPORT
if (lng) if (lng)
li2a(va_arg(va, unsigned long int), bf); li2a(va_arg(va, unsigned long int), bf);
else else
#endif #endif
i2a(va_arg(va, int), bf); i2a(va_arg(va, int), bf);
putchw(putp, putf, w, lz, bf); putchw(putp, putf, w, lz, bf);
break; break;
} }
case 'x': case 'x':
case 'X': case 'X':
#ifdef PRINTF_LONG_SUPPORT #ifdef PRINTF_LONG_SUPPORT
if (lng) if (lng)
uli2a(va_arg(va, unsigned long int), 16, (ch == 'X'), bf); uli2a(va_arg(va, unsigned long int), 16, (ch == 'X'), bf);
else else
#endif #endif
ui2a(va_arg(va, unsigned int), 16, (ch == 'X'), bf); ui2a(va_arg(va, unsigned int), 16, (ch == 'X'), bf);
putchw(putp, putf, w, lz, bf); putchw(putp, putf, w, lz, bf);
break; break;
case 'c': case 'c':
putf(putp, (char)(va_arg(va, int))); putf(putp, (char)(va_arg(va, int)));
break; break;
case 's': case 's':
putchw(putp, putf, w, 0, va_arg(va, char *)); putchw(putp, putf, w, 0, va_arg(va, char *));
break; break;
case '%': case '%':
putf(putp, ch); putf(putp, ch);
default: default:
break; break;
} }
} }
} }
abort:; abort:;
} }
void init_printf(void *putp, void (*putf)(void *, char)) void init_printf(void *putp, void (*putf)(void *, char))
{ {
stdout_putf = putf; stdout_putf = putf;
stdout_putp = putp; stdout_putp = putp;
} }
void tfp_printf(char *fmt, ...) void tfp_printf(char *fmt, ...)
{ {
va_list va; va_list va;
va_start(va, fmt); va_start(va, fmt);
tfp_format(stdout_putp, stdout_putf, fmt, va); tfp_format(stdout_putp, stdout_putf, fmt, va);
va_end(va); va_end(va);
} }
static void putcp(void *p, char c) static void putcp(void *p, char c)
{ {
*(*((char **)p))++ = c; *(*((char **)p))++ = c;
} }
void tfp_sprintf(char *s, char *fmt, ...) void tfp_sprintf(char *s, char *fmt, ...)
{ {
va_list va; va_list va;
va_start(va, fmt); va_start(va, fmt);
tfp_format(&s, putcp, fmt, va); tfp_format(&s, putcp, fmt, va);
putcp(&s, 0); putcp(&s, 0);
va_end(va); va_end(va);
} }
int puts(const char *s) { int puts(const char *s) {
puts_noendl(s); puts_noendl(s);
stdout_putf(stdout_putp, '\n'); stdout_putf(stdout_putp, '\n');
return 1; return 1;
} }
int puts_noendl(const char *s) { int puts_noendl(const char *s) {
while (*s) while (*s)
stdout_putf(stdout_putp, *s++); stdout_putf(stdout_putp, *s++);
return 1; return 1;
} }