fix whitespace

This commit is contained in:
Freya Murphy 2024-01-31 13:11:47 -05:00
parent 50fee8495e
commit 690210c944
Signed by: freya
GPG key ID: 744AB800E383AE52
9 changed files with 381 additions and 384 deletions

View file

@ -2,6 +2,6 @@ set timeout=1
set default=0
menuentry "corn" {
multiboot2 /boot/kernel.bin
boot
multiboot2 /boot/kernel.bin
boot
}

View file

@ -1,3 +0,0 @@
#pragma once

View file

@ -65,79 +65,79 @@ struct xsdt {
// generic address structure
struct gas {
uint8_t address_space;
uint8_t bit_width;
uint8_t bit_offset;
uint8_t access_size;
uint64_t address;
uint8_t address_space;
uint8_t bit_width;
uint8_t bit_offset;
uint8_t access_size;
uint64_t address;
};
// fixed acpi description table
struct fadt {
struct acpi_header h;
uint32_t firmware_ctrl;
uint32_t dsdt;
struct acpi_header h;
uint32_t firmware_ctrl;
uint32_t dsdt;
// field used in ACPI 1.0; no longer in use, for compatibility only
uint8_t reserved;
// field used in ACPI 1.0; no longer in use, for compatibility only
uint8_t reserved;
uint8_t preferred_power_management_profile;
uint16_t sci_interrupt;
uint32_t smi_command_port;
uint8_t acpi_enable;
uint8_t acpi_disable;
uint8_t s4bios_req;
uint8_t pstate_control;
uint32_t pm1_a_event_block;
uint32_t pm1_b_event_block;
uint32_t pm1_a_control_block;
uint32_t pm1_b_control_block;
uint32_t pm2_control_block;
uint32_t pm_timer_block;
uint32_t gpe0_block;
uint32_t gpe1_block;
uint8_t pm1_event_length;
uint8_t pm1_control_length;
uint8_t pm2_control_length;
uint8_t pm_timer_length;
uint8_t gpe0_length;
uint8_t gpe1_length;
uint8_t gpe1_base;
uint8_t cstate_control;
uint16_t worst_c2_latency;
uint16_t worst_c3_latency;
uint16_t flush_size;
uint16_t flush_stride;
uint8_t duty_offset;
uint8_t duty_width;
uint8_t day_alarm;
uint8_t month_alarm;
uint8_t century;
uint8_t preferred_power_management_profile;
uint16_t sci_interrupt;
uint32_t smi_command_port;
uint8_t acpi_enable;
uint8_t acpi_disable;
uint8_t s4bios_req;
uint8_t pstate_control;
uint32_t pm1_a_event_block;
uint32_t pm1_b_event_block;
uint32_t pm1_a_control_block;
uint32_t pm1_b_control_block;
uint32_t pm2_control_block;
uint32_t pm_timer_block;
uint32_t gpe0_block;
uint32_t gpe1_block;
uint8_t pm1_event_length;
uint8_t pm1_control_length;
uint8_t pm2_control_length;
uint8_t pm_timer_length;
uint8_t gpe0_length;
uint8_t gpe1_length;
uint8_t gpe1_base;
uint8_t cstate_control;
uint16_t worst_c2_latency;
uint16_t worst_c3_latency;
uint16_t flush_size;
uint16_t flush_stride;
uint8_t duty_offset;
uint8_t duty_width;
uint8_t day_alarm;
uint8_t month_alarm;
uint8_t century;
// reserved in ACPI 1.0; used since ACPI 2.0+
uint16_t boot_architecture_flags;
// reserved in ACPI 1.0; used since ACPI 2.0+
uint16_t boot_architecture_flags;
uint8_t reserved_2;
uint32_t flags;
uint8_t reserved_2;
uint32_t flags;
// 12 byte structure; see below for details
struct gas reset_reg;
// 12 byte structure; see below for details
struct gas reset_reg;
uint8_t reset_value;
uint8_t reserved_3[3];
uint8_t reset_value;
uint8_t reserved_3[3];
// 64bit pointers - Available on ACPI 2.0+
uint64_t x_firmware_control;
uint64_t x_dsdt;
// 64bit pointers - Available on ACPI 2.0+
uint64_t x_firmware_control;
uint64_t x_dsdt;
struct gas x_pm1_a_event_block;
struct gas x_pm1_b_event_block;
struct gas x_pm1_a_control_block;
struct gas x_pm1_b_control_block;
struct gas x_pm2_control_block;
struct gas x_pm_timer_block;
struct gas x_gpe0_block;
struct gas x_gpe1_block;
struct gas x_pm1_a_event_block;
struct gas x_pm1_b_event_block;
struct gas x_pm1_a_control_block;
struct gas x_pm1_b_control_block;
struct gas x_pm2_control_block;
struct gas x_pm_timer_block;
struct gas x_gpe0_block;
struct gas x_gpe1_block;
};
struct acpi_state {
@ -154,49 +154,49 @@ struct acpi_state {
};
static bool checksum(uint8_t *data, size_t len) {
unsigned char sum = 0;
for (size_t i = 0; i < len; i++)
sum += data[i];
return sum == 0;
unsigned char sum = 0;
for (size_t i = 0; i < len; i++)
sum += data[i];
return sum == 0;
}
static int read_s5_addr(struct acpi_state *state) {
serial_out_str("a");
uintptr_t ptr = state->fadt.dsdt;
char *s5_addr = (void*) (ptr + 36);
uintptr_t ptr = state->fadt.dsdt;
char *s5_addr = (void*) (ptr + 36);
serial_out_str("a");
int dsdt_len = *((int*) (ptr+1)) - 36;
while (0 < dsdt_len--) {
if ( memcmp(s5_addr, "_S5_", 4) == 0)
break;
s5_addr++;
}
int dsdt_len = *((int*) (ptr+1)) - 36;
while (0 < dsdt_len--) {
if ( memcmp(s5_addr, "_S5_", 4) == 0)
break;
s5_addr++;
}
if (dsdt_len > 0) {
// check for valid AML structure
if ( ( *(s5_addr-1) == 0x08 || ( *(s5_addr-2) == 0x08 && *(s5_addr-1) == '\\') ) && *(s5_addr+4) == 0x12 ) {
s5_addr += 5;
s5_addr += ((*s5_addr &0xC0)>>6) +2; // calculate PkgLength size
if (dsdt_len > 0) {
// check for valid AML structure
if ( ( *(s5_addr-1) == 0x08 || ( *(s5_addr-2) == 0x08 && *(s5_addr-1) == '\\') ) && *(s5_addr+4) == 0x12 ) {
s5_addr += 5;
s5_addr += ((*s5_addr &0xC0)>>6) +2; // calculate PkgLength size
if (*s5_addr == 0x0A)
s5_addr++; // skip byteprefix
state->SLP_TYPa = *(s5_addr)<<10;
s5_addr++;
if (*s5_addr == 0x0A)
s5_addr++; // skip byteprefix
state->SLP_TYPa = *(s5_addr)<<10;
s5_addr++;
if (*s5_addr == 0x0A)
s5_addr++; // skip byteprefix
state->SLP_TYPb = *(s5_addr)<<10;
if (*s5_addr == 0x0A)
s5_addr++; // skip byteprefix
state->SLP_TYPb = *(s5_addr)<<10;
state->SLP_EN = 1<<13;
state->SCI_EN = 1;
state->SLP_EN = 1<<13;
state->SCI_EN = 1;
} else {
} else {
return -1;
}
} else {
return -1;
}
}
} else {
return -1;
}
return -1;
}
@ -302,12 +302,12 @@ int acpi_init(void *rootsdp) {
if (!ret)
return ret;
outb(state.fadt.smi_command_port,state.fadt.acpi_enable);
outb(state.fadt.smi_command_port,state.fadt.acpi_enable);
return 0;
}
int acpi_shutdown(void) {
outw((unsigned int) state.fadt.pm1_a_control_block, state.SLP_TYPb | state.SLP_EN);
outw((unsigned int) state.fadt.pm1_a_control_block, state.SLP_TYPb | state.SLP_EN);
return -1;
}

View file

@ -26,17 +26,17 @@ mb_end:
section .bss
align 4096
kernel_pml4: ; reserve memory for initial 512 pml4 entires
kernel_pml4: ; reserve memory for initial 512 pml4 entires
resb 4096
kernel_pdpt_0: ; reserve memory for initial 512 pdpt entires
kernel_pdpt_0: ; reserve memory for initial 512 pdpt entires
resb 4096
kernel_pd_0: ; reserve memory for initial 512 pd entries
kernel_pd_0: ; reserve memory for initial 512 pd entries
resb 4096
kernel_pt_0: ; reserve memory for initial 512 pt entries
kernel_pt_0: ; reserve memory for initial 512 pt entries
resb 4096
paging_pt: ; reserve pages for pager mappings
paging_pt: ; reserve pages for pager mappings
resb 4096
bootstrap_pt: ; reserve pages to bootstrap pager
bootstrap_pt: ; reserve pages to bootstrap pager
resb 4096
align 16
@ -53,33 +53,33 @@ EXEC equ 1 << 3
DC equ 1 << 2
RW equ 1 << 1
ACCESSED equ 1 << 0
; Flags bits
GRAN_4K equ 1 << 7
SZ_32 equ 1 << 6
LONG_MODE equ 1 << 5
GDT:
.Null: equ $ - GDT
dq 0
.Code: equ $ - GDT
dd 0xFFFF ; Limit & Base (low, bits 0-15)
db 0 ; Base (mid, bits 16-23)
db PRESENT | NOT_SYS | EXEC | RW ; Access
db GRAN_4K | LONG_MODE | 0xF ; Flags & Limit (high, bits 16-19)
db 0 ; Base (high, bits 24-31)
.Data: equ $ - GDT
dd 0xFFFF ; Limit & Base (low, bits 0-15)
db 0 ; Base (mid, bits 16-23)
db PRESENT | NOT_SYS | RW ; Access
db GRAN_4K | SZ_32 | 0xF ; Flags & Limit (high, bits 16-19)
db 0 ; Base (high, bits 24-31)
.TSS: equ $ - GDT
dd 0x00000068
dd 0x00CF8900
.Pointer:
dw $ - GDT - 1
dq GDT
.Null: equ $ - GDT
dq 0
.Code: equ $ - GDT
dd 0xFFFF ; Limit & Base (low, bits 0-15)
db 0 ; Base (mid, bits 16-23)
db PRESENT | NOT_SYS | EXEC | RW ; Access
db GRAN_4K | LONG_MODE | 0xF ; Flags & Limit (high, bits 16-19)
db 0 ; Base (high, bits 24-31)
.Data: equ $ - GDT
dd 0xFFFF ; Limit & Base (low, bits 0-15)
db 0 ; Base (mid, bits 16-23)
db PRESENT | NOT_SYS | RW ; Access
db GRAN_4K | SZ_32 | 0xF ; Flags & Limit (high, bits 16-19)
db 0 ; Base (high, bits 24-31)
.TSS: equ $ - GDT
dd 0x00000068
dd 0x00CF8900
.Pointer:
dw $ - GDT - 1
dq GDT
section .text
align 8
@ -107,7 +107,7 @@ start:
mov ebx, 0x00000003 ; Set the B-register to 0x00000003.
mov ecx, 512 ; Set the C-register to 512.
.SetEntry:
mov DWORD [edi], ebx ; Set the uint32_t at the destination index to the B-register.
add ebx, 0x1000 ; Add 0x1000 to the B-register.

View file

@ -7,39 +7,39 @@ extern idt_pic_mouse
extern idt_pic_eoi
%macro PUSHALL 0
push rax
push rbx
push rcx
push rdx
push rbp
push rdi
push rsi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
push rax
push rbx
push rcx
push rdx
push rbp
push rdi
push rsi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
%endmacro
%macro POPALL 0
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rbp
pop rdx
pop rcx
pop rbx
pop rax
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rbp
pop rdx
pop rcx
pop rbx
pop rax
%endmacro
; call the exception handler with the interrupt number
@ -47,15 +47,15 @@ extern idt_pic_eoi
%macro ISRException 1
align 8
isr_stub_%+%1:
PUSHALL
cld
mov rdi, %1 ; exception number
mov rsi, 0 ; placeholder error code
mov rdx, [rsp + 15 * 8] ; instruction pointer
mov rcx, rbp ; base pointer for stack trace
call idt_exception_handler
POPALL
iretq
PUSHALL
cld
mov rdi, %1 ; exception number
mov rsi, 0 ; placeholder error code
mov rdx, [rsp + 15 * 8] ; instruction pointer
mov rcx, rbp ; base pointer for stack trace
call idt_exception_handler
POPALL
iretq
%endmacro
; call the exception handler with the interrupt number
@ -64,59 +64,59 @@ isr_stub_%+%1:
%macro ISRExceptionCode 1
align 8
isr_stub_%+%1:
PUSHALL
cld
mov rdi, %1 ; exception number
mov rsi, [rsp + 15 * 8] ; error code
mov rdx, [rsp + 16 * 8] ; instruction pointer
mov rcx, rbp ; base pointer for stack trace
call idt_exception_handler
POPALL
sub rsp, 8 ; discard error code
iretq
PUSHALL
cld
mov rdi, %1 ; exception number
mov rsi, [rsp + 15 * 8] ; error code
mov rdx, [rsp + 16 * 8] ; instruction pointer
mov rcx, rbp ; base pointer for stack trace
call idt_exception_handler
POPALL
sub rsp, 8 ; discard error code
iretq
%endmacro
%macro PICGeneric 1
isr_stub_%+%1:
PUSHALL
cld
mov rdi, %1
call idt_pic_eoi
POPALL
iretq
PUSHALL
cld
mov rdi, %1
call idt_pic_eoi
POPALL
iretq
%endmacro
%macro PICTimer 1
isr_stub_%+%1:
PUSHALL
cld
call idt_pic_timer
mov rdi, %1
call idt_pic_eoi
POPALL
iretq
PUSHALL
cld
call idt_pic_timer
mov rdi, %1
call idt_pic_eoi
POPALL
iretq
%endmacro
%macro PICKeyboard 1
isr_stub_%+%1:
PUSHALL
cld
call idt_pic_keyboard
mov rdi, %1
call idt_pic_eoi
POPALL
iretq
PUSHALL
cld
call idt_pic_keyboard
mov rdi, %1
call idt_pic_eoi
POPALL
iretq
%endmacro
%macro PICMouse 1
isr_stub_%+%1:
PUSHALL
cld
call idt_pic_mouse
mov rdi, %1
call idt_pic_eoi
POPALL
iretq
PUSHALL
cld
call idt_pic_mouse
mov rdi, %1
call idt_pic_eoi
POPALL
iretq
%endmacro
; do nothing
@ -124,7 +124,7 @@ isr_stub_%+%1:
%macro ISRIgnore 1
align 8
isr_stub_%+%1:
iretq
iretq
%endmacro
; isr stubs
@ -164,7 +164,7 @@ ISRExceptionCode 29
ISRExceptionCode 30
ISRException 31
PICTimer 32 ; 0
PICTimer 32 ; 0
PICKeyboard 33 ; 1
PICGeneric 34 ; 2
PICGeneric 35 ; 3
@ -184,8 +184,8 @@ PICGeneric 47 ; 15
; ignore other interrupts
%assign i 48
%rep 256 - i
ISRIgnore i
%assign i i+1
ISRIgnore i
%assign i i+1
%endrep
; isr stub table
@ -196,6 +196,6 @@ align 16
isr_stub_table:
%assign i 0
%rep 256
dq isr_stub_%+i
dq isr_stub_%+i
%assign i i+1
%endrep

View file

@ -1,38 +1,38 @@
ENTRY(start)
PHDRS {
loadable PT_LOAD FLAGS(7) ;
loadable PT_LOAD FLAGS(7) ;
}
SECTIONS {
. = 1M;
. = 1M;
kernel_start = .;
kernel_start = .;
.boot BLOCK(4K) : ALIGN(4K)
{
*(.multiboot)
}
.boot BLOCK(4K) : ALIGN(4K)
{
*(.multiboot)
}
.rodata BLOCK(4K) : ALIGN(4K)
{
*(.rodata)
}
.rodata BLOCK(4K) : ALIGN(4K)
{
*(.rodata)
}
.text BLOCK(4K) : ALIGN(4K)
{
*(.text)
}
.text BLOCK(4K) : ALIGN(4K)
{
*(.text)
}
.bss BLOCK(4K) : ALIGN(4K)
{
*(.bss)
}
.bss BLOCK(4K) : ALIGN(4K)
{
*(.bss)
}
.symtab : {
symtab = .;
*(.symtab)
} :loadable
.symtab : {
symtab = .;
*(.symtab)
} :loadable
kernel_end = .;
kernel_end = .;
}

View file

@ -133,10 +133,10 @@ static void read_cmdline(
struct mboot_cmdline *cmdline
) {
mboot_uint32_t size = cmdline->size - 8;
if (size >= CMDLINE_MAX)
if (size >= CMDLINE_MAX)
size = CMDLINE_MAX; // truncate :(
memcpy(shim_info->cmdline, cmdline->cmdline, size);
shim_info->cmdline[size] = '\0';
memcpy(shim_info->cmdline, cmdline->cmdline, size);
shim_info->cmdline[size] = '\0';
}
static void read_memorymap(
@ -146,8 +146,8 @@ static void read_memorymap(
int size = map->size - sizeof(mboot_uint32_t) * 4;
int count = size / map->entry_size;
shim_info->map.entry_count = count;
shim_info->map.entry_length = map->entry_size;
shim_info->map.entry_count = count;
shim_info->map.entry_length = map->entry_size;
shim_info->map.entries = map->entries;
}
@ -157,19 +157,19 @@ static void read_rsdp(
) {
if (shim_info->acpi_table != NULL)
return; // xsdp is newer and has been loaded
shim_info->acpi_table = rsdp->rsdp;
shim_info->acpi_table = rsdp->rsdp;
}
static void read_xsdp(
struct boot_info *shim_info,
struct mboot_xsdp *xsdp
) {
shim_info->acpi_table = xsdp->xsdp;
shim_info->acpi_table = xsdp->xsdp;
}
void mboot_load_info(
const void *mboot_data_ptr,
struct boot_info *shim_info
const void *mboot_data_ptr,
struct boot_info *shim_info
) {
memset(shim_info, 0, sizeof(struct boot_info));
@ -180,41 +180,41 @@ void mboot_load_info(
char *tag_ptr = mboot_info->tags;
while (tag_ptr < mboot_end) {
struct mboot_tag *tag = (struct mboot_tag *) tag_ptr;
struct mboot_tag *tag = (struct mboot_tag *) tag_ptr;
switch (tag->type) {
case MBOOT_CMDLINE:
read_cmdline(
read_cmdline(
shim_info,
(struct mboot_cmdline *) tag
);
break;
case MBOOT_MEMORYMAP:
read_memorymap(
break;
case MBOOT_MEMORYMAP:
read_memorymap(
shim_info,
(struct mboot_memory_map *) tag
);
break;
case MBOOT_SYMBOLS:
break;
case MBOOT_SYMBOLS:
read_symbols(
shim_info,
(struct mboot_elf_header_layout *) tag
);
break;
case MBOOT_RSDP:
read_rsdp(
break;
case MBOOT_RSDP:
read_rsdp(
shim_info,
(struct mboot_rsdp *) tag
);
break;
break;
case MBOOT_XSDP:
read_xsdp(
shim_info,
(struct mboot_xsdp *) tag
);
break;
default:
break;
default:
break;
}
int size = tag->size;

View file

@ -15,7 +15,7 @@
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */

256
src/lib.c
View file

@ -3,37 +3,37 @@
#include <stddef.h>
int memcmp(const void *restrict vl, const void *restrict vr, unsigned long n) {
const unsigned char *l = vl, *r = vr;
for (; n && *l == *r; n--, l++, r++);
return n ? *l-*r : 0;
const unsigned char *l = vl, *r = vr;
for (; n && *l == *r; n--, l++, r++);
return n ? *l-*r : 0;
}
void *memcpy(void *restrict dest, const void *restrict src, unsigned long n) {
char *d = dest;
const char *s = src;
for (; n; n--) *d++ = *s++;
return dest;
const char *s = src;
for (; n; n--) *d++ = *s++;
return dest;
}
void *memmove(void *dest, const void *src, unsigned long n) {
char *d = dest;
const char *s = src;
char *d = dest;
const char *s = src;
if (d==s) return d;
if (d==s) return d;
if (d<s) {
for (; n; n--) *d++ = *s++;
} else {
while (n) n--, d[n] = s[n];
}
if (d<s) {
for (; n; n--) *d++ = *s++;
} else {
while (n) n--, d[n] = s[n];
}
return dest;
return dest;
}
void *memset(void *restrict dest, int c, unsigned long n) {
unsigned char *d = dest;
for (; n; n--) *d++ = c;
return dest;
unsigned char *d = dest;
for (; n; n--) *d++ = c;
return dest;
}
int strncmp(const char *restrict lhs, const char *restrict rhs, unsigned long n) {
@ -55,55 +55,55 @@ char *strncpy(char *restrict dest, const char *restrict src, unsigned long n) {
}
size_t strlen(const char *str) {
const char *p;
for(p = str; *p != 0; p++) {}
return p - str;
const char *p;
for(p = str; *p != 0; p++) {}
return p - str;
}
char *strcat(char *restrict dst, const char *restrict src) {
strcpy(dst + strlen(dst), src);
return dst;
strcpy(dst + strlen(dst), src);
return dst;
}
int isspace(int c) {
switch (c) {
case ' ':
case '\t':
case '\v':
case '\f':
case '\r':
case '\n':
return 1;
default:
return 0;
}
switch (c) {
case ' ':
case '\t':
case '\v':
case '\f':
case '\r':
case '\n':
return 1;
default:
return 0;
}
}
int isdigit(int c) {
return c - '0' > -1 && c - '0' < 10;
return c - '0' > -1 && c - '0' < 10;
}
#define ATOX(name, type) \
type name(const char* s) { \
for(; isspace(*s); s++); \
int neg = 0; \
switch (*s) { \
case '-': \
neg = 1; \
/* FALLTHRU */ \
case '+': \
s++; \
break; \
} \
type num = 0; \
for (; *s == '0'; s++); \
for (; isdigit(*s); s++) { \
num *= 10; \
num += *s - '0'; \
} \
return num * (neg ? -1 : 1); \
}
type name(const char* s) { \
for(; isspace(*s); s++); \
int neg = 0; \
switch (*s) { \
case '-': \
neg = 1; \
/* FALLTHRU */ \
case '+': \
s++; \
break; \
} \
type num = 0; \
for (; *s == '0'; s++); \
for (; isdigit(*s); s++) { \
num *= 10; \
num += *s - '0'; \
} \
return num * (neg ? -1 : 1); \
}
ATOX(atoi, int)
ATOX(atol, long int)
@ -118,7 +118,7 @@ char itoc(int i) {
}
int ctoi(char c) {
if(c < 'A') {
if(c < 'A') {
return c - '0';
} else if(c < 'a') {
return c - 'A' + 10;
@ -128,89 +128,89 @@ int ctoi(char c) {
}
#define UXTOA(type, name) \
char *name(unsigned type n, char *buffer, int radix) { \
if (n == 0) { \
buffer[0] = '0'; \
buffer[1] = '\0'; \
return buffer; \
} \
char *start = buffer; \
for (; n; n /= radix) { \
*buffer++ = itoc(n % radix); \
} \
*buffer-- = '\0'; \
while(buffer > start) { \
char tmp = *start; \
*start++ = *buffer; \
*buffer-- = tmp; \
} \
return buffer; \
}
char *name(unsigned type n, char *buffer, int radix) { \
if (n == 0) { \
buffer[0] = '0'; \
buffer[1] = '\0'; \
return buffer; \
} \
char *start = buffer; \
for (; n; n /= radix) { \
*buffer++ = itoc(n % radix); \
} \
*buffer-- = '\0'; \
while(buffer > start) { \
char tmp = *start; \
*start++ = *buffer; \
*buffer-- = tmp; \
} \
return buffer; \
}
UXTOA(int, utoa)
UXTOA(long int, ultoa)
#define XTOA(type, name) \
char *name(type n, char* buffer, int radix) { \
if (n == 0) { \
buffer[0] = '0'; \
buffer[1] = '\0'; \
return buffer; \
} \
if (n < 0) { \
*buffer++ = '-'; \
n = -n; \
} \
char *start = buffer; \
for (; n; n /= radix) { \
*buffer++ = itoc(n % radix); \
} \
*buffer-- = '\0'; \
while(buffer > start) { \
char tmp = *start; \
*start++ = *buffer; \
*buffer-- = tmp; \
} \
return buffer; \
}
char *name(type n, char* buffer, int radix) { \
if (n == 0) { \
buffer[0] = '0'; \
buffer[1] = '\0'; \
return buffer; \
} \
if (n < 0) { \
*buffer++ = '-'; \
n = -n; \
} \
char *start = buffer; \
for (; n; n /= radix) { \
*buffer++ = itoc(n % radix); \
} \
*buffer-- = '\0'; \
while(buffer > start) { \
char tmp = *start; \
*start++ = *buffer; \
*buffer-- = tmp; \
} \
return buffer; \
}
XTOA(int, itoa)
XTOA(long int, ltoa)
#define STRTOX(name, type) \
type name(const char *s, char **endptr, int radix) { \
*endptr = NULL; \
for(; isspace(*s); s++); \
int neg = 0; \
switch (*s) { \
case '-': \
neg = 1; \
/* FALLTHRU */ \
case '+': \
s++; \
break; \
} \
if (!radix) { \
if (*s == '0') { \
s++; \
if (*s == 'x' || *s == 'X') { \
s++; \
radix = 16; \
} else { \
radix = 8; \
} \
} else { \
radix = 10; \
} \
} \
for (; *s == '0'; s++, *endptr = (void*) s); \
type num = 0; \
for (; isdigit(*s); s++, *endptr = (void*) s) { \
num *= radix; \
num += *s - '0'; \
} \
return num * (neg ? -1 : 1); \
}
type name(const char *s, char **endptr, int radix) { \
*endptr = NULL; \
for(; isspace(*s); s++); \
int neg = 0; \
switch (*s) { \
case '-': \
neg = 1; \
/* FALLTHRU */ \
case '+': \
s++; \
break; \
} \
if (!radix) { \
if (*s == '0') { \
s++; \
if (*s == 'x' || *s == 'X') { \
s++; \
radix = 16; \
} else { \
radix = 8; \
} \
} else { \
radix = 10; \
} \
} \
for (; *s == '0'; s++, *endptr = (void*) s); \
type num = 0; \
for (; isdigit(*s); s++, *endptr = (void*) s) { \
num *= radix; \
num += *s - '0'; \
} \
return num * (neg ? -1 : 1); \
}
STRTOX(strtoi, int)
STRTOX(strtol, long int)