assert_msg(rsdp, "Fail to locate ACPI_RSDP");
assert_msg(acpi_rsdp_validate(rsdp), "Invalid ACPI_RSDP (checksum failed)");
- kprintf(KDEBUG "RSDP found at %p, RSDT: %p\n", rsdp, rsdp->rsdt);
-
acpi_rsdt_t* rsdt = rsdp->rsdt;
ctx = lxcalloc(1, sizeof(acpi_context));
}
}
- kprintf(KINFO "OEM: %s\n", ctx->oem_id);
-
- for (size_t i = 0; i < 24; i++) {
- acpi_intso_t* intso = ctx->madt.irq_exception[i];
- if (!intso)
- continue;
-
- kprintf(KDEBUG "IRQ #%u -> GSI #%u\n", intso->source, intso->gsi);
- }
+ kprintf(KINFO "ACPI: %s\n", ctx->oem_id);
}
acpi_context*
#include <stdarg.h>
#include <stddef.h>
-void
+size_t
__sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs);
-void sprintf(char* buffer, char* fmt, ...);
-void snprintf(char* buffer, size_t n, char* fmt, ...);
+size_t
+sprintf(char* buffer, char* fmt, ...);
+size_t
+snprintf(char* buffer, size_t n, char* fmt, ...);
#endif /* __LUNAIX_STDIO_H */
#define __LUNAIX_BLOCK_H
#include <hal/ahci/hba.h>
+#include <lunaix/device.h>
#define LPT_SIG 0x414e554c
#define PARTITION_NAME_SIZE 48
char bdev_id[DEV_ID_SIZE];
char name[PARTITION_NAME_SIZE];
struct hba_device* hd_dev;
+ struct device* dev;
uint64_t base_lba;
uint64_t end_lba;
};
--- /dev/null
+#ifndef __LUNAIX_DEVICE_H
+#define __LUNAIX_DEVICE_H
+
+#define DEVICE_NAME_SIZE 32
+
+#include <lunaix/ds/hstr.h>
+#include <lunaix/ds/llist.h>
+
+struct device
+{
+ struct llist_header dev_list;
+ struct device* parent;
+ struct hstr name;
+ char name_val[DEVICE_NAME_SIZE];
+ void* underlay;
+ void* fs_node;
+ int (*read)(struct device* dev,
+ void* buf,
+ unsigned int offset,
+ unsigned int len);
+ int (*write)(struct device* dev,
+ void* buf,
+ unsigned int offset,
+ unsigned int len);
+};
+
+void
+device_init();
+
+struct device*
+device_add(struct device* parent, void* underlay, char* name_fmt, ...);
+
+void
+device_remove(struct device* dev);
+
+#endif /* __LUNAIX_DEVICE_H */
#define VFS_IOBUF_FDIRTY 0x1
+#define FSTYPE_ROFS 0x1
+
#define VFS_VALID_CHAR(chr) \
('A' <= (chr) && (chr) <= 'Z' || 'a' <= (chr) && (chr) <= 'z' || \
'0' <= (chr) && (chr) <= '9' || (chr) == '.' || (chr) == '_' || \
(chr) == '-')
+extern struct hstr vfs_ddot;
+extern struct hstr vfs_dot;
+
struct v_dnode;
struct filesystem
{
struct hlist_node fs_list;
struct hstr fs_name;
+ uint32_t types;
int (*mount)(struct v_superblock* vsb, struct v_dnode* mount_point);
int (*unmount)(struct v_superblock* vsb);
};
struct twifs_node*
twifs_toplevel_node(const char* name, int name_len);
+void
+twifs_rm_node(struct twifs_node* node);
+
#endif /* __LUNAIX_TWIFS_H */
}
int
-__block_read(struct v_file* file, void* buffer, size_t len);
-
-int
-__block_write(struct v_file* file, void* buffer, size_t len);
-
-void
-block_twifs_create()
+__block_read(struct device* dev,
+ void* buf,
+ unsigned int offset,
+ unsigned int len)
{
- struct twifs_node* dev = twifs_toplevel_node("dev", 3);
- struct twifs_node* dev_block = twifs_dir_node(dev, "block", 5);
-
- if (!dev_block) {
- kprintf(KERROR "fail to create twifs node");
- return;
- }
-
- struct block_dev* bdev;
- struct twifs_node* bdev_node;
- for (size_t i = 0; i < MAX_DEV; i++) {
- if (!(bdev = dev_registry[i])) {
- continue;
- }
-
- bdev_node =
- twifs_dir_node(dev_block, bdev->bdev_id, strlen(bdev->bdev_id));
- bdev_node->fops.read = __block_read;
- bdev_node->fops.write = __block_write;
- bdev_node->data = i;
- bdev_node->inode->fsize = bdev->hd_dev->max_lba;
- }
-}
-
-int
-__block_read(struct v_file* file, void* buffer, size_t len)
-{
- int index = (int)((struct twifs_node*)file->inode->data)->data;
int errno;
- struct block_dev* bdev;
- if (index < 0 || index >= MAX_DEV || !(bdev = dev_registry[index])) {
- return ENXIO;
- }
+ struct block_dev* bdev = (struct block_dev*)dev->underlay;
size_t acc_size = 0, rd_size = 0, bsize = bdev->hd_dev->block_size,
rd_block = 0;
void* block = valloc(bsize);
while (acc_size < len) {
if (!bdev->hd_dev->ops.read_buffer(
- bdev->hd_dev, file->f_pos + rd_block, block, bsize)) {
+ bdev->hd_dev, offset + rd_block, block, bsize)) {
errno = ENXIO;
goto error;
}
rd_size = MIN(len - acc_size, bsize);
- memcpy(buffer + acc_size, block, rd_size);
+ memcpy(buf + acc_size, block, rd_size);
acc_size += rd_size;
rd_block++;
}
}
int
-__block_write(struct v_file* file, void* buffer, size_t len)
+__block_write(struct device* dev,
+ void* buf,
+ unsigned int offset,
+ unsigned int len)
{
- int index = (int)((struct twifs_node*)file->inode->data)->data;
int errno;
- struct block_dev* bdev;
- if (index < 0 || index >= MAX_DEV || !(bdev = dev_registry[index])) {
- return ENXIO;
- }
+ struct block_dev* bdev = (struct block_dev*)dev->underlay;
size_t acc_size = 0, wr_size = 0, bsize = bdev->hd_dev->block_size,
wr_block = 0;
void* block = valloc(bsize);
while (acc_size < len) {
wr_size = MIN(len - acc_size, bsize);
- memcpy(block, buffer + acc_size, wr_size);
+ memcpy(block, buf + acc_size, wr_size);
if (!bdev->hd_dev->ops.write_buffer(
- bdev->hd_dev, file->f_pos + wr_block, block, bsize)) {
+ bdev->hd_dev, offset + wr_block, block, bsize)) {
errno = ENXIO;
break;
}
block_mount_disk(struct hba_device* hd_dev)
{
int errno = 0;
- struct block_dev* dev = cake_grab(lbd_pile);
- strncpy(dev->name, hd_dev->model, PARTITION_NAME_SIZE);
- dev->hd_dev = hd_dev;
- dev->base_lba = 0;
- dev->end_lba = hd_dev->max_lba;
- if (!__block_register(dev)) {
+ struct block_dev* bdev = cake_grab(lbd_pile);
+ strncpy(bdev->name, hd_dev->model, PARTITION_NAME_SIZE);
+ bdev->hd_dev = hd_dev;
+ bdev->base_lba = 0;
+ bdev->end_lba = hd_dev->max_lba;
+ if (!__block_register(bdev)) {
errno = BLOCK_EFULL;
goto error;
}
-errno);
}
-// FIXME make it more general, manipulate the device through vfs mapping
int
-__block_mount_partitions(struct hba_device* hd_dev)
-{
- int errno = 0;
- void* buffer = valloc_dma(hd_dev->block_size);
- if (!hd_dev->ops.read_buffer(hd_dev, 1, buffer, hd_dev->block_size)) {
- errno = BLOCK_EREAD;
- goto done;
- }
-
- struct lpt_header* header = (struct lpt_header*)buffer;
- if (header->signature != LPT_SIG) {
- errno = BLOCK_ESIG;
- goto done;
- }
-
- if (header->crc != crc32b(buffer, sizeof(*header))) {
- errno = BLOCK_ECRC;
- goto done;
- }
-
- uint64_t lba = header->pt_start_lba;
- int j = 0;
- int count_per_sector = hd_dev->block_size / sizeof(struct lpt_entry);
- while (lba < header->pt_end_lba) {
- if (!hd_dev->ops.read_buffer(hd_dev, lba, buffer, hd_dev->block_size)) {
- errno = BLOCK_EREAD;
- goto done;
- }
- struct lpt_entry* entry = (struct lpt_entry*)buffer;
- for (int i = 0; i < count_per_sector; i++, j++) {
- struct block_dev* dev = cake_grab(lbd_pile);
- strncpy(dev->name, entry->part_name, PARTITION_NAME_SIZE);
- dev->hd_dev = hd_dev;
- dev->base_lba = entry->base_lba;
- dev->end_lba = entry->end_lba;
- __block_register(dev);
-
- if (j >= header->table_len) {
- goto done;
- }
- }
- }
-
-done:
- vfree_dma(buffer);
- return -errno;
-}
-
-int
-__block_register(struct block_dev* dev)
+__block_register(struct block_dev* bdev)
{
if (free_slot >= MAX_DEV) {
return 0;
}
- snprintf(dev->bdev_id, DEV_ID_SIZE, "bd%x", free_slot);
- dev_registry[free_slot++] = dev;
+
+ struct device* dev = device_add(NULL, bdev, "sd%c", 'a' + free_slot);
+ dev->write = __block_write;
+ dev->read = __block_read;
+
+ bdev->dev = dev;
+ dev_registry[free_slot++] = bdev;
return 1;
}
\ No newline at end of file
char test_sequence[] = "Once upon a time, in a magical land of Equestria. "
"There were two regal sisters who ruled together "
"and created harmony for all the land.";
- int fd = open("/dev/block/bd0", 0);
- if (fd < 0) {
+ int fd = open("/dev/sda", 0); // bd0 设备 - 硬盘
+ int tty = open("/dev/tty", 0); // tty 设备 - 控制台
+
+ if (fd < 0 || tty < 0) {
kprintf(KERROR "fail to open (%d)\n", geterrno());
return;
}
+ // 移动指针至第二个逻辑扇区(LBA=1),并写入
lseek(fd, 1, FSEEK_SET);
write(fd, test_sequence, sizeof(test_sequence));
- lseek(fd, -1, FSEEK_CUR);
+ // 读出我们写的内容
char read_out[256];
+ lseek(fd, -1, FSEEK_CUR);
read(fd, read_out, sizeof(read_out));
- kprintf("%s", read_out);
+ write(tty, read_out, sizeof(read_out));
+
+ close(fd);
+ close(tty);
+
+ kprint_hex(read_out, sizeof(read_out));
}
\ No newline at end of file
--- /dev/null
+#include <klibc/stdio.h>
+#include <lunaix/device.h>
+#include <lunaix/fs/twifs.h>
+#include <lunaix/mm/valloc.h>
+
+struct llist_header dev_list;
+
+static struct twifs_node* dev_root;
+
+int
+__dev_read(struct v_file* file, void* buffer, size_t len);
+
+int
+__dev_write(struct v_file* file, void* buffer, size_t len);
+
+void
+device_init()
+{
+ dev_root = twifs_toplevel_node("dev", 3);
+
+ llist_init_head(&dev_list);
+}
+
+struct device*
+device_add(struct device* parent, void* underlay, char* name_fmt, ...)
+{
+ struct device* dev = vzalloc(sizeof(struct device));
+
+ va_list args;
+ va_start(args, name_fmt);
+
+ size_t strlen =
+ __sprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args);
+
+ dev->name = HSTR(dev->name_val, strlen);
+ dev->parent = parent;
+ dev->underlay = underlay;
+
+ hstr_rehash(&dev->name, HSTR_FULL_HASH);
+ llist_append(&dev_list, &dev->dev_list);
+
+ struct twifs_node* dev_node =
+ twifs_file_node(dev_root, dev->name_val, strlen);
+ dev_node->data = dev;
+ dev_node->fops.read = __dev_read;
+ dev_node->fops.write = __dev_write;
+
+ dev->fs_node = dev_node;
+
+ va_end(args);
+ return dev;
+}
+
+int
+__dev_read(struct v_file* file, void* buffer, size_t len)
+{
+ struct twifs_node* dev_node = (struct twifs_node*)file->inode->data;
+ struct device* dev = (struct device*)dev_node->data;
+
+ if (!dev->read) {
+ return ENOTSUP;
+ }
+ return dev->read(dev, buffer, file->f_pos, len);
+}
+
+int
+__dev_write(struct v_file* file, void* buffer, size_t len)
+{
+ struct twifs_node* dev_node = (struct twifs_node*)file->inode->data;
+ struct device* dev = (struct device*)dev_node->data;
+
+ if (!dev->write) {
+ return ENOTSUP;
+ }
+ return dev->write(dev, buffer, file->f_pos, len);
+}
+
+void
+device_remove(struct device* dev)
+{
+ llist_delete(&dev->dev_list);
+ twifs_rm_node((struct twifs_node*)dev->fs_node);
+ vfree(dev);
+}
\ No newline at end of file
int
__twifs_mount(struct v_superblock* vsb, struct v_dnode* mount_point);
+int
+__twifs_mkdir(struct v_inode* inode, struct v_dnode* dnode);
+
void
twifs_init()
{
fsm_register(twifs);
fs_root = twifs_dir_node(NULL, NULL, 0);
-
- // 预备一些常用的类别
- twifs_toplevel_node("kernel", 6);
- twifs_toplevel_node("dev", 3);
- twifs_toplevel_node("bus", 3);
}
struct twifs_node*
return node;
}
+void
+twifs_rm_node(struct twifs_node* node)
+{
+ // TODO recursivly delete any sub-directories.
+ if ((node->itype & VFS_INODE_TYPE_DIR)) {
+ struct twifs_node* dir = __twifs_get_node(node, &vfs_dot);
+ struct twifs_node* dir2 = __twifs_get_node(node, &vfs_ddot);
+ vfs_i_free(dir->inode);
+ vfs_i_free(dir2->inode);
+ cake_release(twi_pile, dir);
+ cake_release(twi_pile, dir2);
+ }
+ llist_delete(&node->siblings);
+ vfs_i_free(node->inode);
+ cake_release(twi_pile, node);
+}
+
struct twifs_node*
twifs_file_node(struct twifs_node* parent, const char* name, int name_len)
{
struct v_inode* twi_inode = __twifs_create_inode(twi_node);
twi_node->inode = twi_inode;
- return twi_inode;
+ return twi_node;
}
struct twifs_node*
return twifs_dir_node(fs_root, name, name_len);
}
+int
+__twifs_mkdir(struct v_inode* inode, struct v_dnode* dnode)
+{
+ struct twifs_node* parent_node = (struct twifs_node*)inode->data;
+ if (!(parent_node->itype & VFS_INODE_TYPE_DIR)) {
+ return ENOTDIR;
+ }
+ struct twifs_node* new_node =
+ twifs_dir_node(parent_node, dnode->name.value, dnode->name.len);
+ dnode->inode = new_node->inode;
+
+ return 0;
+}
+
int
__twifs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
{
mount_point->inode = fs_root->inode;
- // FIXME: try to mitigate this special case or pull it up to higher level of
+ // FIXME try to mitigate this special case or pull it up to higher level of
// abstraction
if (mount_point->parent && mount_point->parent->inode) {
struct hstr ddot_name = HSTR("..", 2);
.mtime = 0,
.ref_count = 0 };
inode->ops.dir_lookup = __twifs_dirlookup;
+ inode->ops.mkdir = __twifs_mkdir;
inode->ops.open = __twifs_openfile;
return inode;
{
struct twifs_node* twi_node = (struct twifs_node*)inode->data;
+ if (!(twi_node->itype & VFS_INODE_TYPE_DIR)) {
+ return ENOTDIR;
+ }
+
struct twifs_node* child_node = __twifs_get_node(twi_node, &dnode->name);
if (child_node) {
dnode->inode = child_node->inode;
static int fs_id = 0;
+struct hstr vfs_ddot = HSTR("..", 2);
+struct hstr vfs_dot = HSTR(".", 1);
+
struct v_dnode*
vfs_d_alloc();
dnode_cache = vzalloc(DNODE_HASHTABLE_SIZE * sizeof(struct hbucket));
+ hstr_rehash(&vfs_ddot, HSTR_FULL_HASH);
+ hstr_rehash(&vfs_dot, HSTR_FULL_HASH);
+
// 创建一个根superblock,用来蕴含我们的根目录。
root_sb = vfs_sb_alloc();
root_sb->root = vfs_d_alloc();
vfs_d_alloc()
{
struct v_dnode* dnode = cake_grab(dnode_pile);
+ memset(dnode, 0, sizeof(*dnode));
llist_init_head(&dnode->children);
+ return dnode;
}
void
cake_release(inode_pile, inode);
}
-__DEFINE_LXSYSCALL2(int, open, const char*, path, int, options)
+int
+__vfs_do_open(struct v_file** file_out, const char* path, int options)
{
char name_str[VFS_NAME_MAXLEN];
struct hstr name = HSTR(name_str, 0);
struct v_dnode *dentry, *file;
- int errno, fd;
+ int errno;
if ((errno = vfs_walk(NULL, path, &dentry, &name, VFS_WALK_PARENT))) {
- return -1;
+ return ENOENT;
}
vfs_walk(dentry, name.value, &file, NULL, 0);
errno = vfs_open(file, &opened_file);
}
+ *file_out = opened_file;
+ return errno;
+}
+
+__DEFINE_LXSYSCALL2(int, open, const char*, path, int, options)
+{
+ struct v_file* opened_file;
+ int errno = __vfs_do_open(&opened_file, path, options), fd;
+
__current->k_status = errno;
if (!errno && !(errno = vfs_alloc_fdslot(&fd))) {
struct v_fd* fd_s = vzalloc(sizeof(*fd_s));
fd_s->file = opened_file;
- fd_s->pos = file->inode->fsize & -((options & FO_APPEND) != 0);
+ fd_s->pos = opened_file->inode->fsize & -((options & FO_APPEND) != 0);
__current->fdtable->fds[fd] = fd_s;
+ return fd;
}
return SYSCALL_ESTATUS(errno);
goto done;
}
- if (!parent->inode->ops.mkdir) {
+ if ((parent->super_block->fs->types & FSTYPE_ROFS)) {
+ errno = ENOTSUP;
+ } else if (!parent->inode->ops.mkdir) {
errno = ENOTSUP;
} else if (!(parent->inode->itype & VFS_INODE_TYPE_DIR)) {
errno = ENOTDIR;
#include <lunaix/tty/tty.h>
#include <lunaix/clock.h>
+#include <lunaix/device.h>
#include <lunaix/lxconsole.h>
#include <lunaix/mm/kalloc.h>
#include <lunaix/mm/page.h>
void
_kernel_init()
{
- lxconsole_init();
cake_init();
valloc_init();
- kprintf(KINFO "[MM] Allocated %d pages for stack start at %p\n",
- KSTACK_SIZE >> PG_SIZE_BITS,
- KSTACK_START);
+ fsm_init();
+ vfs_init();
+ twifs_init();
+
+ device_init();
+
+ // 挂载 TwiFS 为根目录
+ vfs_mount("/", "twifs", -1);
+
+ lxconsole_init();
sched_init();
#include <klibc/string.h>
+#include <lunaix/device.h>
#include <lunaix/lxconsole.h>
#include <lunaix/mm/pmm.h>
#include <lunaix/mm/vmm.h>
static struct console lx_console;
+int
+__tty_write(struct device* dev,
+ void* buf,
+ unsigned int offset,
+ unsigned int len);
+
void
lxconsole_init()
{
memset(lx_console.buffer.data, 0, lx_console.buffer.size);
lx_console.flush_timer = NULL;
+
+ struct device* tty_dev = device_add(NULL, &lx_console, "tty");
+ tty_dev->write = __tty_write;
+}
+
+int
+__tty_write(struct device* dev,
+ void* buf,
+ unsigned int offset,
+ unsigned int len)
+{
+ struct console* console = (struct console*)dev->underlay;
+ console_write(console, buf, len);
}
void
extern uint8_t __init_hhk_end; /* link/linker.ld */
extern multiboot_info_t* _k_init_mb_info; /* k_init.c */
-extern void
-block_twifs_create();
-
void
init_platform()
{
block_init();
ahci_init();
// ahci_list_device();
-
- fsm_init();
- vfs_init();
- twifs_init();
-
- block_twifs_create();
-
- vfs_mount("/", "twifs", -1);
-
- //__test_disk_io();
-
// cake_stats();
syscall_install();
#include <hal/apic.h>
#include <hal/rtc.h>
-#include <lunaix/mm/kalloc.h>
+#include <lunaix/mm/cake.h>
+#include <lunaix/mm/valloc.h>
#include <lunaix/sched.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
static volatile uint32_t sched_ticks = 0;
static volatile uint32_t sched_ticks_counter = 0;
+static struct cake_pile* timer_pile;
+
#define APIC_CALIBRATION_CONST 0x100000
void
timer_init_context()
{
+ timer_pile = cake_new_pile("timer", sizeof(struct lx_timer), 1, 0);
timer_ctx =
- (struct lx_timer_context*)lxmalloc(sizeof(struct lx_timer_context));
+ (struct lx_timer_context*)valloc(sizeof(struct lx_timer_context));
assert_msg(timer_ctx, "Fail to initialize timer contex");
- timer_ctx->active_timers =
- (struct lx_timer*)lxmalloc(sizeof(struct lx_timer));
+ timer_ctx->active_timers = (struct lx_timer*)cake_grab(timer_pile);
llist_init_head(timer_ctx->active_timers);
}
struct lx_timer*
timer_run(ticks_t ticks, void (*callback)(void*), void* payload, uint8_t flags)
{
- struct lx_timer* timer =
- (struct lx_timer*)lxmalloc(sizeof(struct lx_timer));
+ struct lx_timer* timer = (struct lx_timer*)cake_grab(timer_pile);
if (!timer)
return NULL;
pos->counter = pos->deadline;
} else {
llist_delete(&pos->link);
- lxfree(pos);
+ cake_release(timer_pile, pos);
}
}
static const char flag_chars[] = "#0- +";
-#define FLAG_ALT (1<<0)
-#define FLAG_ZERO (1<<1)
-#define FLAG_LEFTJUSTIFY (1<<2)
-#define FLAG_SPACEPOSITIVE (1<<3)
-#define FLAG_PLUSPOSITIVE (1<<4)
-#define FLAG_NUMERIC (1<<5)
-#define FLAG_SIGNED (1<<6)
-#define FLAG_NEGATIVE (1<<7)
-#define FLAG_ALT2 (1<<8)
-#define FLAG_CAPS (1<<9)
-
-
-// FIXME: use something like IO_FILE to abstract this into a more flexible, stream based, vprintf
-void
+#define FLAG_ALT (1 << 0)
+#define FLAG_ZERO (1 << 1)
+#define FLAG_LEFTJUSTIFY (1 << 2)
+#define FLAG_SPACEPOSITIVE (1 << 3)
+#define FLAG_PLUSPOSITIVE (1 << 4)
+#define FLAG_NUMERIC (1 << 5)
+#define FLAG_SIGNED (1 << 6)
+#define FLAG_NEGATIVE (1 << 7)
+#define FLAG_ALT2 (1 << 8)
+#define FLAG_CAPS (1 << 9)
+
+// FIXME: use something like IO_FILE to abstract this into a more flexible,
+// stream based, vprintf
+size_t
__sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
{
// This sprintf just a random implementation I found it on Internet . lol.
if (max_len && ptr >= max_len - 1) {
break;
}
-
+
if (*fmt != '%') {
buffer[ptr++] = *fmt;
continue;
// process width
int width = -1;
if (*fmt >= '1' && *fmt <= '9') {
- for (width = 0; *fmt >= '0' && *fmt <= '9'; ) {
+ for (width = 0; *fmt >= '0' && *fmt <= '9';) {
width = 10 * width + *fmt++ - '0';
}
} else if (*fmt == '*') {
if (*fmt == '.') {
++fmt;
if (*fmt >= '0' && *fmt <= '9') {
- for (precision = 0; *fmt >= '0' && *fmt <= '9'; ) {
+ for (precision = 0; *fmt >= '0' && *fmt <= '9';) {
precision = 10 * precision + *fmt++ - '0';
}
} else if (*fmt == '*') {
char* data = "";
again:
switch (*fmt) {
- case 'l':
- case 'z':
- length = 1;
- ++fmt;
- goto again;
- case 'd':
- case 'i': {
- long x = length ? va_arg(vargs, long) : va_arg(vargs, int);
- int negative = x < 0 ? FLAG_NEGATIVE : 0;
- num = negative ? -x : x;
- flags |= FLAG_NUMERIC | FLAG_SIGNED | negative;
- break;
- }
- case 'u':
- format_unsigned:
- num = length ? va_arg(vargs, unsigned long) : va_arg(vargs, unsigned);
- flags |= FLAG_NUMERIC;
- break;
- case 'x':
- base = 16;
- goto format_unsigned;
- case 'X':
- flags = flags | FLAG_CAPS;
- base = 16;
- goto format_unsigned;
- case 'p':
- num = (uintptr_t) va_arg(vargs, void*);
- base = 16;
- flags |= FLAG_ALT | FLAG_ALT2 | FLAG_NUMERIC;
- break;
- case 's':
- data = va_arg(vargs, char*);
- break;
- case 'c':
- data = numbuf;
- numbuf[0] = va_arg(vargs, int);
- numbuf[1] = '\0';
- break;
- default:
- data = numbuf;
- numbuf[0] = (*fmt ? *fmt : '%');
- numbuf[1] = '\0';
- if (!*fmt) {
- fmt--;
+ case 'l':
+ case 'z':
+ length = 1;
+ ++fmt;
+ goto again;
+ case 'd':
+ case 'i': {
+ long x = length ? va_arg(vargs, long) : va_arg(vargs, int);
+ int negative = x < 0 ? FLAG_NEGATIVE : 0;
+ num = negative ? -x : x;
+ flags |= FLAG_NUMERIC | FLAG_SIGNED | negative;
+ break;
}
- break;
+ case 'u':
+ format_unsigned:
+ num = length ? va_arg(vargs, unsigned long)
+ : va_arg(vargs, unsigned);
+ flags |= FLAG_NUMERIC;
+ break;
+ case 'x':
+ base = 16;
+ goto format_unsigned;
+ case 'X':
+ flags = flags | FLAG_CAPS;
+ base = 16;
+ goto format_unsigned;
+ case 'p':
+ num = (uintptr_t)va_arg(vargs, void*);
+ base = 16;
+ flags |= FLAG_ALT | FLAG_ALT2 | FLAG_NUMERIC;
+ break;
+ case 's':
+ data = va_arg(vargs, char*);
+ break;
+ case 'c':
+ data = numbuf;
+ numbuf[0] = va_arg(vargs, int);
+ numbuf[1] = '\0';
+ break;
+ default:
+ data = numbuf;
+ numbuf[0] = (*fmt ? *fmt : '%');
+ numbuf[1] = '\0';
+ if (!*fmt) {
+ fmt--;
+ }
+ break;
}
if (flags & FLAG_NUMERIC) {
data = itoa(num, numbuf, base);
int i = 0;
char c;
- while ((flags & FLAG_CAPS) && (c = data[i]))
- {
+ while ((flags & FLAG_CAPS) && (c = data[i])) {
data[i] = c & ~((c & 0x40) >> 1);
i++;
}
} else if (flags & FLAG_SPACEPOSITIVE) {
prefix = " ";
}
- } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ALT)
- && (base == 16 || base == -16)
- && (num || (flags & FLAG_ALT2))) {
+ } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ALT) &&
+ (base == 16 || base == -16) &&
+ (num || (flags & FLAG_ALT2))) {
prefix = "0x";
}
int zeros;
if ((flags & FLAG_NUMERIC) && precision >= 0) {
zeros = precision > len ? precision - len : 0;
- } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ZERO)
- && !(flags & FLAG_LEFTJUSTIFY)
- && len + (int) strlen(prefix) < width) {
+ } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ZERO) &&
+ !(flags & FLAG_LEFTJUSTIFY) &&
+ len + (int)strlen(prefix) < width) {
zeros = width - len - strlen(prefix);
} else {
zeros = 0;
}
}
buffer[ptr++] = '\0';
+
+ return ptr;
}
-void
+size_t
sprintf(char* buffer, char* fmt, ...)
{
va_list args;
va_start(args, fmt);
- __sprintf_internal(buffer, fmt, 0, args);
+ size_t len = __sprintf_internal(buffer, fmt, 0, args);
va_end(args);
+ return len;
}
-void
+size_t
snprintf(char* buffer, size_t n, char* fmt, ...)
{
va_list args;
va_start(args, fmt);
- __sprintf_internal(buffer, fmt, n, args);
+ size_t len = __sprintf_internal(buffer, fmt, n, args);
va_end(args);
+ return len;
}
\ No newline at end of file