From 563c92e6d08c305cb9f7693818ecbe2a2dec527b Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Thu, 29 Nov 2018 20:43:06 -0500 Subject: [PATCH] hello world from initrd --- Makefile | 13 +- initrd/Makefile | 16 +- initrd/hello | 1 - initrd/init | Bin 0 -> 12524 bytes initrd/init.c | 14 + initrd/test | Bin 37024 -> 0 bytes initrd/test.c | 16 - link.ld | 1 + run.sh | 1 - src/crt/Makefile | 42 ++ src/crt/crt0.c | 60 +++ src/fs/Makefile | 22 +- src/fs/initrd.c | 67 ++- src/fs/initrd.h | 23 + src/fs/stdio.c | 37 +- src/fs/stdio.h | 23 + src/kernel/Makefile | 22 +- src/kernel/clock.c | 30 +- src/kernel/clock.h | 12 +- src/kernel/elf.c | 136 ++++++ src/kernel/elf.h | 124 +++++ src/kernel/fault.c | 21 + src/kernel/init.c | 2 +- src/kernel/serial.c | 2 +- src/kernel/svc.c | 3 +- src/kernel/task.c | 20 +- src/kernel/vfs.c | 72 ++- src/kernel/vfs.h | 111 ++++- src/pdclib/Makefile | 4 +- src/pdclib/platform/example.tar.gz | Bin 0 -> 19773 bytes src/pdclib/platform/example/Readme.txt | 21 - .../example/functions/_PDCLIB/_PDCLIB_Exit.c | 40 -- .../example/functions/_PDCLIB/_PDCLIB__Exit.c | 40 -- .../functions/_PDCLIB/_PDCLIB_allocpages.c | 86 ---- .../example/functions/_PDCLIB/_PDCLIB_close.c | 36 -- .../functions/_PDCLIB/_PDCLIB_fillbuffer.c | 78 ---- .../functions/_PDCLIB/_PDCLIB_flushbuffer.c | 110 ----- .../example/functions/_PDCLIB/_PDCLIB_open.c | 167 ------- .../functions/_PDCLIB/_PDCLIB_rename.c | 144 ------ .../example/functions/_PDCLIB/_PDCLIB_seek.c | 82 ---- .../functions/_PDCLIB/_PDCLIB_stdinit.c | 430 ------------------ .../platform/example/functions/signal/raise.c | 114 ----- .../example/functions/signal/signal.c | 75 --- .../platform/example/functions/stdio/remove.c | 75 --- .../example/functions/stdio/tmpfile.c | 114 ----- .../example/functions/stdlib/getenv.c | 45 -- .../example/functions/stdlib/system.c | 57 --- .../platform/example/functions/time/clock.c | 35 -- .../platform/example/functions/time/time.c | 41 -- .../example/functions/time/timespec_get.c | 42 -- src/pdclib/platform/example/include/float.h | 75 --- .../example/include/pdclib/_PDCLIB_config.h | 426 ----------------- src/pdclib/platform/example/include/signal.h | 84 ---- .../functions/_PDCLIB/_PDCLIB_allocpages.c | 70 +-- .../stmos/functions/_PDCLIB/_PDCLIB_stdinit.c | 46 +- .../platform/stmos/functions/os/syscalls.c | 39 +- src/pdclib/platform/stmos/include/syscalls.h | 1 + src/user/Makefile | 22 +- src/user/priv_gpio.h | 58 --- src/user/user.c | 58 +-- 60 files changed, 931 insertions(+), 2675 deletions(-) delete mode 100644 initrd/hello create mode 100755 initrd/init create mode 100644 initrd/init.c delete mode 100755 initrd/test delete mode 100644 initrd/test.c create mode 100644 src/crt/Makefile create mode 100644 src/crt/crt0.c create mode 100644 src/kernel/elf.c create mode 100644 src/kernel/elf.h create mode 100644 src/pdclib/platform/example.tar.gz delete mode 100644 src/pdclib/platform/example/Readme.txt delete mode 100644 src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_Exit.c delete mode 100644 src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB__Exit.c delete mode 100644 src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_allocpages.c delete mode 100644 src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_close.c delete mode 100644 src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_fillbuffer.c delete mode 100644 src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_flushbuffer.c delete mode 100644 src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_open.c delete mode 100644 src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_rename.c delete mode 100644 src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_seek.c delete mode 100644 src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_stdinit.c delete mode 100644 src/pdclib/platform/example/functions/signal/raise.c delete mode 100644 src/pdclib/platform/example/functions/signal/signal.c delete mode 100644 src/pdclib/platform/example/functions/stdio/remove.c delete mode 100644 src/pdclib/platform/example/functions/stdio/tmpfile.c delete mode 100644 src/pdclib/platform/example/functions/stdlib/getenv.c delete mode 100644 src/pdclib/platform/example/functions/stdlib/system.c delete mode 100644 src/pdclib/platform/example/functions/time/clock.c delete mode 100644 src/pdclib/platform/example/functions/time/time.c delete mode 100644 src/pdclib/platform/example/functions/time/timespec_get.c delete mode 100644 src/pdclib/platform/example/include/float.h delete mode 100644 src/pdclib/platform/example/include/pdclib/_PDCLIB_config.h delete mode 100644 src/pdclib/platform/example/include/signal.h delete mode 100644 src/user/priv_gpio.h diff --git a/Makefile b/Makefile index 488f95f..ec2da92 100644 --- a/Makefile +++ b/Makefile @@ -18,17 +18,16 @@ # along with this program. If not, see . # -CROSS = arm-none-eabi- +CROSS = arm-stmos- CC = gcc AS = as OBJCOPY = objcopy MCUFLAGS = -mthumb -mcpu=cortex-m4 #-mfloat-abi=hard -mfpu=fpv4-sp-d16 -AFLAGS = $(MCUFLAGS) -CFLAGS = $(MCUFLAGS) -ggdb -ffreestanding -nostdlib -fsigned-char -I.. \ +AFLAGS = $(MCUFLAGS) -meabi=5 +CFLAGS = $(MCUFLAGS) -ggdb -fsigned-char -I.. \ -Wall -Werror -Wextra -pedantic - #-Wno-overlength-strings -Wno-discarded-qualifiers -LFLAGS = -T link.ld +LFLAGS = -T link.ld OUT = main.elf @@ -46,6 +45,9 @@ all: @$(CROSS)$(CC) $(CFLAGS) $(LFLAGS) -o $(OUT) \ $$(find src/fs src/kernel src/user -name "*.o") initrd.img.o +crt: + @arm-stmos-$(CC) $(MCUFLAGS) -fsigned-char -Os -fPIE -c src/crt/crt0.c \ + -o src/crt/crt0.o clean: @echo " CLEAN" @@ -53,4 +55,5 @@ clean: @$(MAKE) -C src/fs clean @$(MAKE) -C src/user clean @rm -f $(OUT) + @rm -f initrd.img initrd.img.o diff --git a/initrd/Makefile b/initrd/Makefile index 705ac6c..5946eee 100644 --- a/initrd/Makefile +++ b/initrd/Makefile @@ -1,6 +1,12 @@ +## +# A simple Makefile for building executables loadable by stmos. +# + +ARCH = arm-stmos- +CC = gcc -mcpu=cortex-m4 -mthumb -fsigned-char +CFLAGS = -Os -fPIE + all: - @arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -fsigned-char -Os \ - -nostdinc -nostdlib \ - -fdata-sections -ffunction-sections -Wl,--gc-sections \ - -I../src/pdclib/include -I../src/pdclib/platform/stmos/include \ - test.c ../src/pdclib/pdclib.a -s -o test + @$(ARCH)$(CC) $(CFLAGS) init.c -o init + @arm-stmos-strip init + diff --git a/initrd/hello b/initrd/hello deleted file mode 100644 index 5d437a5..0000000 --- a/initrd/hello +++ /dev/null @@ -1 +0,0 @@ -Hello, world!! diff --git a/initrd/init b/initrd/init new file mode 100755 index 0000000000000000000000000000000000000000..3bc5fd87d0e3623978d6eecad88c195a3086ffb0 GIT binary patch literal 12524 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 F{sBp!QZoPm literal 0 HcmV?d00001 diff --git a/initrd/init.c b/initrd/init.c new file mode 100644 index 0000000..5ff4ae5 --- /dev/null +++ b/initrd/init.c @@ -0,0 +1,14 @@ +/** + * @file test.c + * Basic userland code to be loaded by stmos for program load testing. + */ + +#include + +int main(void) +{ + printf("Hello, world!\n"); + while (1); + return 0; +} + diff --git a/initrd/test b/initrd/test deleted file mode 100755 index 7bf8246d7cf1a393b86c12d860796678907245a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37024 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 -#include - -int main(void); - -void _start(void) -{ - exit(main()); -} - -int main(void) -{ - printf("Hello, world!\n"); - return 0; -} - diff --git a/link.ld b/link.ld index 092032e..2a995f8 100644 --- a/link.ld +++ b/link.ld @@ -1,5 +1,6 @@ /** * @file linker.ld + * Linker script for the kernel/os * * Copyright (C) 2018 Clyne Sullivan * diff --git a/run.sh b/run.sh index 0b74844..a1c344c 100755 --- a/run.sh +++ b/run.sh @@ -1,5 +1,4 @@ #!/bin/bash -# # @file run.sh # Starts openocd and connects gdb to the target, for programming/debugging # diff --git a/src/crt/Makefile b/src/crt/Makefile new file mode 100644 index 0000000..ce23a89 --- /dev/null +++ b/src/crt/Makefile @@ -0,0 +1,42 @@ +## +# @file Makefile +# Script to build folder of source files +# +# Copyright (C) 2018 Clyne Sullivan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +CFILES = $(wildcard *.c) +AFILES = $(wildcard *.s) +OFILES = $(patsubst %.c, %.o, $(CFILES)) \ + $(patsubst %.s, %.asm.o, $(AFILES)) + +CFLAGS += -ffreestanding -nostdlib -I.. -I../arch/cmsis + +all: $(OFILES) + +%.o: %.c + @echo " CC " $< + @$(CROSS)$(CC) $(CFLAGS) -c $< -o $@ + +%.asm.o: %.s + @echo " AS " $< + @$(CROSS)$(AS) $(AFLAGS) -c $< -o $@ + +clean: + @echo " CLEAN" + @rm -f $(OFILES) + + diff --git a/src/crt/crt0.c b/src/crt/crt0.c new file mode 100644 index 0000000..ccdb2eb --- /dev/null +++ b/src/crt/crt0.c @@ -0,0 +1,60 @@ +/** + * @file crt0.c + * Userland executable startup code + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +extern int main(int, char **); + +static void stdio_init(void); + +void _start(void) +{ + stdio_init(); + exit(main(0, 0)); +} + +void stdio_init(void) +{ + stderr = calloc(1, sizeof(FILE)); + stderr->handle = 2; + stderr->buffer = malloc(BUFSIZ); + stderr->bufsize = BUFSIZ; + stderr->ungetbuf = malloc(_PDCLIB_UNGETCBUFSIZE); + stderr->status = _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC; + stderr->next = NULL; + + stdout = calloc(1, sizeof(FILE)); + stdout->handle = 1; + stdout->buffer = malloc(BUFSIZ); + stdout->bufsize = BUFSIZ; + stdout->ungetbuf = malloc(_PDCLIB_UNGETCBUFSIZE); + stdout->status = _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC; + stdout->next = stderr; + + stdin = calloc(1, sizeof(FILE)); + stdin->handle = 0; + stdin->buffer = malloc(BUFSIZ); + stdin->bufsize = BUFSIZ; + stdin->ungetbuf = malloc(_PDCLIB_UNGETCBUFSIZE); + stdin->status = _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC; + stdin->next = stdout; +} + diff --git a/src/fs/Makefile b/src/fs/Makefile index d22fbf3..ce23a89 100644 --- a/src/fs/Makefile +++ b/src/fs/Makefile @@ -1,9 +1,29 @@ +## +# @file Makefile +# Script to build folder of source files +# +# Copyright (C) 2018 Clyne Sullivan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + CFILES = $(wildcard *.c) AFILES = $(wildcard *.s) OFILES = $(patsubst %.c, %.o, $(CFILES)) \ $(patsubst %.s, %.asm.o, $(AFILES)) -CFLAGS += -I.. -I../arch/cmsis +CFLAGS += -ffreestanding -nostdlib -I.. -I../arch/cmsis all: $(OFILES) diff --git a/src/fs/initrd.c b/src/fs/initrd.c index 44e5493..de00a4a 100644 --- a/src/fs/initrd.c +++ b/src/fs/initrd.c @@ -1,3 +1,23 @@ +/** + * @file initrd.c + * Filesystem module for handling the initrd + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include #include @@ -5,7 +25,6 @@ typedef struct { char *address; - uint32_t pos; uint32_t size; } initrd_info; @@ -16,8 +35,9 @@ static const uint8_t *initrd_start = (uint8_t *)_binary_initrd_img_start; static const uint32_t initrd_size = (uint32_t)_binary_initrd_img_size; void *initrd_open(const char *file); -uint32_t initrd_read(void *info, uint32_t count, uint8_t *buffer); -int initrd_close(void *info); +uint32_t initrd_read(vfs_file_info *info, uint32_t count, uint8_t *buffer); +int initrd_close(vfs_file_info *info); +int initrd_seek(vfs_file_info *info, uint32_t offset, int whence); char *initrd_getfile(uint32_t offset); @@ -26,7 +46,8 @@ static const vfs_volume_funcs initrd_funcs = { initrd_close, initrd_read, 0, // write - 0 // readdir + 0, // readdir + initrd_seek }; int initrd_strncmp(const char *a, const char *b, unsigned int n) @@ -53,7 +74,6 @@ void *initrd_open(const char *file) initrd_info *file = (initrd_info *)malloc( sizeof(initrd_info)); file->address = ptr + len + 8; - file->pos = 0; file->size = *(uint32_t *)(ptr + len + 4); return file; } @@ -62,41 +82,48 @@ void *initrd_open(const char *file) return 0; } -int initrd_close(void *info) +int initrd_close(vfs_file_info *info) { // Nothing to do - free(info); + free(info->fsinfo); return 0; } -uint32_t initrd_read(void *info, uint32_t count, uint8_t *buffer) +uint32_t initrd_read(vfs_file_info *info, uint32_t count, uint8_t *buffer) { - initrd_info *iinfo = (initrd_info *)info; + initrd_info *iinfo = (initrd_info *)info->fsinfo; if (iinfo == 0 || iinfo->address == 0) return 0; uint32_t i; for (i = 0; i < count; i++) { - if (iinfo->pos >= iinfo->size) + if (info->pos >= iinfo->size) break; - buffer[iinfo->pos] = iinfo->address[iinfo->pos]; - iinfo->pos++; + buffer[info->pos] = iinfo->address[info->pos]; + info->pos++; } return i; } -/*char *readfile(const char *name) +int initrd_seek(vfs_file_info *info, uint32_t offset, int whence) { - char *ptr; - for (uint32_t i = 0; ptr = getfile(i), ptr != 0; i++) { - uint32_t len = *((uint32_t *)ptr); - if (!strncmp(name, ptr + 4, len)) - return ptr + len + 8; - } + initrd_info *iinfo = (initrd_info *)info->fsinfo; + if (iinfo == 0 || iinfo->address == 0) + return 0; + + if (whence == SEEK_SET) + info->pos = offset; + else if (whence == SEEK_CUR) + info->pos += offset; + else if (whence == SEEK_END) + info->pos = iinfo->size + offset; + else + return -1; + return 0; -}*/ +} char *initrd_getfile(uint32_t offset) { diff --git a/src/fs/initrd.h b/src/fs/initrd.h index dbc0079..045b2b9 100644 --- a/src/fs/initrd.h +++ b/src/fs/initrd.h @@ -1,6 +1,29 @@ +/** + * @file initrd.h + * Filesystem module for handling the initrd + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef INTIRD_H_ #define INITRD_H_ +/** + * Mounts the initrd (initrd is built into kernel). + */ void initrd_init(void); #endif // INITRD_H_ diff --git a/src/fs/stdio.c b/src/fs/stdio.c index 6cea2a3..e15003d 100644 --- a/src/fs/stdio.c +++ b/src/fs/stdio.c @@ -1,12 +1,32 @@ +/** + * @file stdio.c + * Filesystem module for handling stdio (stdout, stdin, stderr) + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "stdio.h" #include #include void *stdio_open(const char *path); -int stdio_close(void *info); -uint32_t stdio_read(void *info, uint32_t count, uint8_t *buffer); -uint32_t stdio_write(void *info, uint32_t count, const uint8_t *buffer); +int stdio_close(vfs_file_info *info); +uint32_t stdio_read(vfs_file_info *info, uint32_t count, uint8_t *buffer); +uint32_t stdio_write(vfs_file_info *info, uint32_t count, const uint8_t *buffer); const vfs_volume_funcs stdio_funcs = { stdio_open, @@ -14,6 +34,7 @@ const vfs_volume_funcs stdio_funcs = { stdio_read, stdio_write, 0, // readdir + 0 // seek }; void *stdio_open(const char *path) @@ -30,14 +51,14 @@ void *stdio_open(const char *path) return id; } -int stdio_close(void *info) +int stdio_close(vfs_file_info *info) { // Nothing to do - free(info); + free(info->fsinfo); return 0; } -uint32_t stdio_read(void *info, uint32_t count, uint8_t *buffer) +uint32_t stdio_read(vfs_file_info *info, uint32_t count, uint8_t *buffer) { (void)info; (void)count; @@ -45,11 +66,11 @@ uint32_t stdio_read(void *info, uint32_t count, uint8_t *buffer) return 0; } -uint32_t stdio_write(void *info, uint32_t count, const uint8_t *buffer) +uint32_t stdio_write(vfs_file_info *info, uint32_t count, const uint8_t *buffer) { (void)info; for (uint32_t i = 0; i < count; i++) - serial_put(buffer[count]); + serial_put(buffer[i]); return count; } diff --git a/src/fs/stdio.h b/src/fs/stdio.h index 90d0f68..bf52fa8 100644 --- a/src/fs/stdio.h +++ b/src/fs/stdio.h @@ -1,8 +1,31 @@ +/** + * @file stdio.h + * Filesystem module for handling stdio (stdout, stdin, stderr) + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef INTIRD_H_ #define INITRD_H_ #include +/** + * Structure of function calls for stdio filesystem operations. + */ extern const vfs_volume_funcs stdio_funcs; #endif // INITRD_H_ diff --git a/src/kernel/Makefile b/src/kernel/Makefile index d22fbf3..ce23a89 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -1,9 +1,29 @@ +## +# @file Makefile +# Script to build folder of source files +# +# Copyright (C) 2018 Clyne Sullivan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + CFILES = $(wildcard *.c) AFILES = $(wildcard *.s) OFILES = $(patsubst %.c, %.o, $(CFILES)) \ $(patsubst %.s, %.asm.o, $(AFILES)) -CFLAGS += -I.. -I../arch/cmsis +CFLAGS += -ffreestanding -nostdlib -I.. -I../arch/cmsis all: $(OFILES) diff --git a/src/kernel/clock.c b/src/kernel/clock.c index 950f4ca..a49b4c1 100644 --- a/src/kernel/clock.c +++ b/src/kernel/clock.c @@ -23,20 +23,18 @@ #include // ticks since init -volatile uint32_t ticks = 0; +volatile uint32_t clock_ticks = 0; volatile uint8_t tim2_finished = 1; -extern task_t *current; - void clock_svc(uint32_t *args) { if (args[0] == 0) task_sleep(args[1]); else if (args[0] == 1) - udelay(args[1]); + clock_udelay(args[1]); else if (args[0] == 2) - *((unsigned int *)args[1]) = ticks; + *((unsigned int *)args[1]) = clock_millis(); } void clock_init(void) @@ -79,18 +77,13 @@ void clock_init(void) TIM2->CR1 |= TIM_CR1_OPM | TIM_CR1_CEN; } -uint32_t millis(void) -{ - return ticks; -} - -void delay(uint32_t count) +void clock_delay(uint32_t count) { - uint32_t target = ticks + count; - while (ticks < target); + uint32_t target = clock_ticks + count; + while (clock_ticks < target); } -void udelay(uint32_t count) +void clock_udelay(uint32_t count) { tim2_finished = 0; TIM2->ARR = count; @@ -98,13 +91,18 @@ void udelay(uint32_t count) while (tim2_finished == 0); } +uint32_t clock_millis(void) +{ + return clock_ticks; +} + void SysTick_Handler(void) { // just keep counting - ticks++; + clock_ticks++; // task switch every four ticks (4ms) - if (!(ticks & 3)) + if (!(clock_ticks & 3)) SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; } diff --git a/src/kernel/clock.h b/src/kernel/clock.h index 3ec7857..e5e46c4 100644 --- a/src/kernel/clock.h +++ b/src/kernel/clock.h @@ -28,18 +28,22 @@ */ extern void clock_init(void); -uint32_t millis(void); - /** * Sleeps for given amount of milliseconds. * @param ms Number of milliseconds to sleep for */ -void delay(uint32_t ms); +void clock_delay(uint32_t ms); /** * Sleeps for the given amount of microseconds. * @param count Number of microseconds to sleep for */ -void udelay(uint32_t count); +void clock_udelay(uint32_t count); + +/** + * Returns the number of milliseconds since clock initialization. + * @return milliseconds since init + */ +uint32_t clock_millis(void); #endif // CLOCK_H_ diff --git a/src/kernel/elf.c b/src/kernel/elf.c new file mode 100644 index 0000000..77333a9 --- /dev/null +++ b/src/kernel/elf.c @@ -0,0 +1,136 @@ +/** + * @file elf.c + * Functionality to execute ELF files + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "elf.h" +#include "vfs.h" +#include "heap.h" + +#include + +Elf32_Shdr *elf_find_section(Elf32_Ehdr *ehdr, const char *name) +{ + Elf32_Shdr *shdr = (Elf32_Shdr *)((char *)ehdr + ehdr->e_shoff); + Elf32_Shdr *shdr_str = (Elf32_Shdr *)((char *)ehdr + ehdr->e_shoff + + ehdr->e_shstrndx * ehdr->e_shentsize); + + for (Elf32_Half i = 0; i < ehdr->e_shnum; i++) { + char *section = ((char *)ehdr + shdr_str->sh_offset) + + shdr->sh_name; + if (!strcmp(section, name)) + return shdr; + + shdr = (Elf32_Shdr *)((char *)shdr + ehdr->e_shentsize); + } + + return 0; +} + +uint32_t elf_execve(const char *file, char * const argv[], char * const envp[]) +{ + (void)argv; + (void)envp; + + // Open the given file + int fd = vfs_open(file, VFS_FILE_READ); + if (fd == -1) + return -1; + + // Get file size + vfs_seek(fd, 0, SEEK_END); + unsigned int fileLength = vfs_tell(fd); + vfs_seek(fd, 0, SEEK_SET); + + // Read entire file + char *elfData = malloc(fileLength); + if (vfs_read(fd, fileLength, (uint8_t *)elfData) != fileLength) { + vfs_close(fd); + free(elfData); + return -1; + } + + // ELF signature check + if (elfData[0] != '\177' || elfData[1] != 'E' || elfData[2] != 'L' || + elfData[3] != 'F') { + vfs_close(fd); + free(elfData); + return -1; + } + + + uint32_t ELF_OFFSET = 0; + + // Load program headers + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfData; + Elf32_Phdr *phdr = (Elf32_Phdr *)(elfData + ehdr->e_phoff); + + for (Elf32_Half i = 0; i < ehdr->e_phnum; i++) { + if (phdr->p_type == PT_LOAD) { + // There should only be one PT_LOAD section... + if (ELF_OFFSET != 0) + while (1); + ELF_OFFSET = (uint32_t)malloc(phdr->p_memsz + 8) & ~7; + + uint8_t *src = (uint8_t *)elfData + phdr->p_offset; + uint8_t *dst = (uint8_t *)(ELF_OFFSET + phdr->p_vaddr); + for (uint32_t j = 0; j < phdr->p_filesz; j++) + dst[j] = src[j]; + } + + phdr = (Elf32_Phdr *)((char *)phdr + ehdr->e_phentsize); + } + + // Zero the .bss section + Elf32_Shdr *bssSection = elf_find_section(ehdr, ".bss"); + if (bssSection != 0) { + uint32_t *bssArray = (Elf32_Addr *)(ELF_OFFSET + bssSection->sh_addr); + Elf32_Word bssSize = bssSection->sh_size / sizeof(void *); + for (Elf32_Word i = 0; i < bssSize; i++) + bssArray[i] = 0; + } + + // Fix GOT entries if they exist + Elf32_Shdr *gotSection = elf_find_section(ehdr, ".got"); + if (gotSection != 0) { + Elf32_Addr *gotArray = (Elf32_Addr *)(ELF_OFFSET + gotSection->sh_addr); + Elf32_Word gotSize = gotSection->sh_size / sizeof(void *); + for (Elf32_Word i = 0; i < gotSize; i++) + gotArray[i] += ELF_OFFSET; + } + + // Run any constructors + Elf32_Shdr *initArraySection = elf_find_section(ehdr, ".init_array"); + if (initArraySection != 0) { + Elf32_Addr *initArray = (Elf32_Addr *)(ELF_OFFSET + + initArraySection->sh_addr); + + Elf32_Word initArraySize = initArraySection->sh_size / sizeof(void *); + for (Elf32_Word i = 0; i < initArraySize; i++) { + initArray[i] += ELF_OFFSET; + ((void (*)(void))(initArray[i]))(); + } + } + + vfs_close(fd); + free(elfData); + + // Return entry point + return (ELF_OFFSET + ehdr->e_entry); +} + diff --git a/src/kernel/elf.h b/src/kernel/elf.h new file mode 100644 index 0000000..9143401 --- /dev/null +++ b/src/kernel/elf.h @@ -0,0 +1,124 @@ +/** + * @file elf.h + * Functionality to execute ELF files + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ELF_H_ +#define ELF_H_ + +#include + +/** + * Attempts to open the given ELF file. + * @param file Path of the ELF file + * @param argv argv to be passed to the program + * @param envp envp to be passed to the program + * @return -1 on fail, otherwise returns address of ELF entry + */ +uint32_t elf_execve(const char *file, char * const argv[], char * const envp[]); + +// +// ELF Standard macros and structures below + +#define EI_NIDENT 16 + +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_RESERVED 0x70000000 + +#define ELF32_ST_BIND(i) ((i) >> 4) +#define ELF32_ST_TYPE(i) ((i) & 0xF) +#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t) & 0xF)) + +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((i) & 0xFF) +#define ELF32_R_INFO(s, t) (((s) << 8) + ((t) & 0xFF)) + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} __attribute__((packed)) Elf32_Ehdr; + +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} __attribute__((packed)) Elf32_Shdr; + +typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} __attribute__((packed)) Elf32_Sym; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} __attribute__((packed)) Elf32_Rel; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} __attribute__((packed)) Elf32_Rela; + +typedef struct { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} __attribute__((packed)) Elf32_Phdr; + +#endif // ELF_H_ diff --git a/src/kernel/fault.c b/src/kernel/fault.c index dd491c4..db81c1f 100644 --- a/src/kernel/fault.c +++ b/src/kernel/fault.c @@ -1,5 +1,26 @@ +/** + * @file fault.c + * Fault managing functions + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + __attribute__ ((naked)) void HardFault_Handler(void) { + // TODO have a real fault handler... while (1); } diff --git a/src/kernel/init.c b/src/kernel/init.c index 3bd6b39..48e1800 100644 --- a/src/kernel/init.c +++ b/src/kernel/init.c @@ -63,5 +63,5 @@ void init_idle(void) task_start(user_main, 4096); while (1) - delay(10); + clock_delay(10); } diff --git a/src/kernel/serial.c b/src/kernel/serial.c index 6f112a8..2737b7d 100644 --- a/src/kernel/serial.c +++ b/src/kernel/serial.c @@ -44,7 +44,7 @@ void serial_put(int c) char serial_get(void) { while (!(USART2->ISR & USART_ISR_RXNE)) - delay(10); + clock_delay(10); return USART2->RDR & 0xFF; } diff --git a/src/kernel/svc.c b/src/kernel/svc.c index cf1fbe2..1455841 100644 --- a/src/kernel/svc.c +++ b/src/kernel/svc.c @@ -1,6 +1,6 @@ /** * @file svc.c - * An unused handler for SVC calls + * Handler code for SVC calls * * Copyright (C) 2018 Clyne Sullivan * @@ -48,6 +48,7 @@ void SVC_Handler(void) { * 2 - getpid * 3 - waitpid * 4 - sbrk (TODO bad) + * 5 - execve */ task_svc(args); break; diff --git a/src/kernel/task.c b/src/kernel/task.c index c5e5e96..c5d09d4 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -19,6 +19,7 @@ */ #include "clock.h" +#include "elf.h" #include "heap.h" #include "task.h" #include @@ -49,6 +50,10 @@ void task_svc(uint32_t *args) case 4: *((void **)args[2]) = task_sbrk(args[1]); break; + case 5: + *((uint32_t *)args[4]) = elf_execve((const char *)args[1], + (char * const *)args[2], (char * const *)args[3]); + break; default: break; } @@ -56,18 +61,19 @@ void task_svc(uint32_t *args) void *task_sbrk(uint32_t bytes) { - if (task_current->heap == 0) { + return malloc(bytes); + + /*if (task_current->heap == 0) task_current->heap = malloc(1024 * 16); - return (uint8_t *)task_current->heap + (1024 * 16); - } if (bytes == 0) { alloc_t *alloc = (alloc_t *)((uint8_t *)task_current->heap - sizeof(alloc_t)); - return (uint8_t *)task_current->heap + alloc->size; + return (uint8_t *)(((uint32_t)task_current->heap + alloc->size) + & ~0xFFF); } - return (void *)-1; + return (void *)-1;*/ } void task_hold(uint8_t hold) @@ -81,7 +87,7 @@ void task_hold(uint8_t hold) void task_sleep(uint32_t ms) { task_current->status.state = TASK_SLEEPING; - task_current->status.value = millis() + ms; + task_current->status.value = clock_millis() + ms; YIELD; } @@ -312,7 +318,7 @@ void PendSV_Handler(void) " : "=r" (task_current->sp)); // Load next task - uint32_t ticks = millis(); + uint32_t ticks = clock_millis(); do { task_current = task_current->next; if (task_current == 0) diff --git a/src/kernel/vfs.c b/src/kernel/vfs.c index 6236691..b9be9bc 100644 --- a/src/kernel/vfs.c +++ b/src/kernel/vfs.c @@ -1,3 +1,23 @@ +/** + * @file vfs.c + * An implementation of filesystem abstraction + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "vfs.h" #include @@ -10,6 +30,11 @@ static vfs_volume vfs_volumes[VFS_MAX_VOLS]; static vfs_file vfs_files[VFS_MAX_FILES]; +#define VFS_PID_CHECK(fpid) { \ + uint32_t pid = task_getpid(); \ + if (pid != fpid && fpid != 0) \ + return 0; } + void vfs_svc(uint32_t *args) { switch (args[0]) { @@ -114,7 +139,8 @@ int vfs_open(const char *path, uint32_t flags) vfs_files[file].flags = VFS_FILE_OPEN | flags; vfs_files[file].vol = drive; vfs_files[file].pid = task_getpid(); - vfs_files[file].fsinfo = fsinfo; + vfs_files[file].info.pos = 0; + vfs_files[file].info.fsinfo = fsinfo; return file; } @@ -125,14 +151,13 @@ int vfs_close(int fd) return -1; if (vfs_volumes[vfs_files[fd].vol].funcs->close == 0) return -1; - if (vfs_files[fd].pid != task_getpid()) - return -1; + VFS_PID_CHECK(vfs_files[fd].pid); if (!(vfs_files[fd].flags & VFS_FILE_OPEN)) return 0; // TODO care /*int ret =*/ vfs_volumes[vfs_files[fd].vol].funcs->close( - vfs_files[fd].fsinfo); + &vfs_files[fd].info); vfs_files[fd].flags = 0; vfs_files[fd].pid = 0; @@ -143,16 +168,17 @@ uint32_t vfs_read(int fd, uint32_t count, uint8_t *buffer) { if (fd < 0 || fd > VFS_MAX_FILES || count == 0 || buffer == 0) return 0; + if (!(vfs_files[fd].flags & VFS_FILE_OPEN)) + return -1; if (vfs_volumes[vfs_files[fd].vol].funcs->read == 0) return -1; - if (vfs_files[fd].pid != task_getpid()) - return 0; + VFS_PID_CHECK(vfs_files[fd].pid); if ((!(vfs_files[fd].flags & VFS_FILE_READ)) || (vfs_files[fd].flags & VFS_EOF)) return 0; uint32_t ret = vfs_volumes[vfs_files[fd].vol].funcs->read( - vfs_files[fd].fsinfo, count, buffer); + &vfs_files[fd].info, count, buffer); if (ret < count) vfs_files[fd].flags |= VFS_EOF; @@ -164,17 +190,18 @@ uint32_t vfs_write(int fd, uint32_t count, const uint8_t *buffer) { if (fd < 0 || fd > VFS_MAX_FILES || count == 0 || buffer == 0) return 0; + if (!(vfs_files[fd].flags & VFS_FILE_OPEN)) + return -1; if (vfs_volumes[vfs_files[fd].vol].funcs->write == 0) return -1; - if (vfs_files[fd].pid != task_getpid()) - return 0; + VFS_PID_CHECK(vfs_files[fd].pid); // TODO append? if ((!(vfs_files[fd].flags & VFS_FILE_WRITE)) || (vfs_files[fd].flags & VFS_EOF)) return 0; uint32_t ret = vfs_volumes[vfs_files[fd].vol].funcs->write( - vfs_files[fd].fsinfo, count, buffer); + &vfs_files[fd].info, count, buffer); if (ret < count) vfs_files[fd].flags |= VFS_EOF; @@ -182,3 +209,28 @@ uint32_t vfs_write(int fd, uint32_t count, const uint8_t *buffer) return ret; } +int vfs_seek(int fd, int32_t offset, int whence) +{ + if (fd < 0 || fd > VFS_MAX_FILES) + return -1; + if (!(vfs_files[fd].flags & VFS_FILE_OPEN)) + return -1; + if (vfs_volumes[vfs_files[fd].vol].funcs->seek == 0) + return -1; + VFS_PID_CHECK(vfs_files[fd].pid); + + return vfs_volumes[vfs_files[fd].vol].funcs->seek(&vfs_files[fd].info, + offset, whence); +} + +int32_t vfs_tell(int fd) +{ + if (fd < 0 || fd > VFS_MAX_FILES) + return -1; + if (!(vfs_files[fd].flags & VFS_FILE_OPEN)) + return -1; + VFS_PID_CHECK(vfs_files[fd].pid); + + return (int32_t)vfs_files[fd].info.pos; +} + diff --git a/src/kernel/vfs.h b/src/kernel/vfs.h index 89213f9..ccad67b 100644 --- a/src/kernel/vfs.h +++ b/src/kernel/vfs.h @@ -1,18 +1,95 @@ +/** + * @file vfs.h + * An implementation of filesystem abstraction + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef VFS_H_ #define VFS_H_ #include +/** + * Holds file info that can be used by filesystem drivers/modules. + */ +typedef struct { + uint32_t pos; /**< Position within the file */ + void *fsinfo; /**< Filesystem-specific data, handled by fs driver */ +} vfs_file_info; + +/** + * Directory entry data, used by readdir. + */ typedef struct { char name[32]; } vfs_dirent; +/** + * Functions that a filesystem driver/module should implement. + */ typedef struct vfs_volume_funcs_t { + /** + * Opens the given file. + * @param file Path to the file + * @return 0 on fail, otherwise pointer to be stored in + * vfs_file_info.fsinfo + */ void *(*open)(const char *file); - int (*close)(void *info); - uint32_t (*read)(void *info, uint32_t count, uint8_t *buffer); - uint32_t (*write)(void *info, uint32_t count, const uint8_t *buffer); + + /** + * Closes the file, releasing given info however necessary. + * @param info File info + * @return 0 on success, non-zero on failure + */ + int (*close)(vfs_file_info *info); + + /** + * Reads bytes from the given file. + * @param info Info on the file + * @param count Number of bytes to read + * @param buffer Pre-allocated buffer to store data to + * @return Number of bytes read + */ + uint32_t (*read)(vfs_file_info *info, uint32_t count, uint8_t *buffer); + + /** + * Writes bytes from the given file. + * @param info Info on the file + * @param count Number of bytes to write + * @param buffer Data to write to file + * @return Number of bytes written + */ + uint32_t (*write)(vfs_file_info *info, uint32_t count, const uint8_t *buffer); + + /** + * Creates an array of vfs_dirent for the given directory. + * @param path Directory to read + * @return 0 on fail, an array of vfs_dirent otherwise + */ vfs_dirent *(*readdir)(const char *path); + + /** + * Seeks file to the given position. + * @param info The file's info + * @param offset Offset to seek to + * @param whence Where to seek from (beginning, end, or current pos.) + * @return 0 on succes, non-zero otherwise + */ + int (*seek)(vfs_file_info *info, uint32_t offset, int whence); } vfs_volume_funcs; // Indicates mounted volume @@ -20,9 +97,12 @@ typedef struct vfs_volume_funcs_t { // Set if filesystem is read-only #define VFS_READONLY (1 << 1) +/** + * Data defining a VFS volume. + */ typedef struct { - uint32_t flags; - const vfs_volume_funcs *funcs; + uint32_t flags; /**< Flags regarding volume state */ + const vfs_volume_funcs *funcs; /**< Volume-managing functions */ } vfs_volume; // Indicates an opened file @@ -34,13 +114,19 @@ typedef struct { // Set if EOF has been reached #define VFS_EOF (1 << 3) +/** + * Contains data to manage open files. + */ typedef struct { - uint32_t flags; /**< File attribute flags */ - uint32_t vol; /**< Index of volume file is stored on */ - uint32_t pid; /**< PID of process handling this file */ - void *fsinfo; /**< Filesystem-specific data, handled by fs driver */ + uint32_t flags; /**< File attribute flags */ + uint32_t vol; /**< Index of volume file is stored on */ + uint32_t pid; /**< PID of process handling this file */ + vfs_file_info info; /**< File info used by file IO functions */ } vfs_file; +/** + * Initializes the filesystem abstraction layer. + */ void vfs_init(void); int vfs_mount(const vfs_volume_funcs *funcs, uint32_t flags); @@ -49,4 +135,11 @@ int vfs_close(int fd); uint32_t vfs_read(int fd, uint32_t count, uint8_t *buffer); uint32_t vfs_write(int fd, uint32_t count, const uint8_t *buffer); +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +int vfs_seek(int fd, int32_t offset, int whence); +int32_t vfs_tell(int fd); + #endif // VFS_H_ diff --git a/src/pdclib/Makefile b/src/pdclib/Makefile index bef1e19..5d75638 100644 --- a/src/pdclib/Makefile +++ b/src/pdclib/Makefile @@ -24,10 +24,10 @@ REGDEPFILES := $(patsubst %,$(BUILDDIR)/%.d,$(REGFILES)) # All files belonging to the source distribution ALLFILES := $(SRCFILES) $(HDRFILES) $(AUXFILES) -CC = arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -fsigned-char --specs=nosys.specs +CC = arm-stmos-gcc -mcpu=cortex-m4 -mthumb -fsigned-char WARNINGS := -Wall -Wextra -pedantic -Wno-unused-parameter -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wuninitialized -Wstrict-prototypes -Wdeclaration-after-statement -CFLAGS := -fno-builtin -g -std=c99 -I./testing -I./platform/stmos/include $(WARNINGS) $(USERFLAGS) +CFLAGS := -fPIC -Os -ffreestanding -std=c99 -I./testing -I./platform/stmos/include $(WARNINGS) $(USERFLAGS) .PHONY: all clean srcdist tests testdrivers regtests regtestdrivers todos fixmes help diff --git a/src/pdclib/platform/example.tar.gz b/src/pdclib/platform/example.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..cd72d1e11a79650a8d9221b2ddf601a86580d8e3 GIT binary patch literal 19773 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

WCvt9ynm;k?a6^D+6h4{Z}S*+i%a z051mPQJ}jESdx+$(vj@kpj!ZFZY|2u{+tye10)+l13o!GmPY(jmGKSW^%U}g6q)Y3 zrSD|1yXgklovZ=uhE4#p`1KN~9Sl@Q(`+`0N5)cFJV2{sY6#T~JP-Prfv>DQv9VlM zFH?=*&yu}@CDcEIf&gE~)G!+o?|SPy?lWkwZlKxxf?P2UTW~t@R3(C$we2ka-!K!9 zxC>kYyIY5u(z_fbpkp_R2JPaKS%SNSAHW}qE!3{o{{$Um9tJjJ)m}849h8LYz!Gi~ zI^B-_fO-r}F=w{m)EVw&W6%i-5S5Z_WWYU)))t&KL#w_`vsoY>8+*v=-5KxL8bYlB zAHHQ%HuCANGZ~oavjegi_{5N>&}p!~`eYczV_|M2{3s(%US8(^On25h0Efir>SYeh HUXK3&<=%ok literal 0 HcmV?d00001 diff --git a/src/pdclib/platform/example/Readme.txt b/src/pdclib/platform/example/Readme.txt deleted file mode 100644 index 07dc20e..0000000 --- a/src/pdclib/platform/example/Readme.txt +++ /dev/null @@ -1,21 +0,0 @@ -"Example" Platform Overlay -========================== - -This is an example platform overlay, as described in the main Readme.txt of -this archive. For ease of development, it applies (and tests) correctly on the -machine of the author; no other guarantees can be given. -It should give you a good idea of what is REQUIRED to make a copy of PDCLib -work. There is a lot more you could do, and even some things you SHOULD do, in -order to experience anything but abysmal performance: - -- Read / write operations on binary streams, and even on text streams for - machines that do not do any text conversion, can be made much more efficient - by using some sort of page buffer instead of the linear buffer implemented - here. It requires some special and platform-dependent manipulations, though, - which is why it is not done by default. - -- Anything relating to floating point logic is written in generic C. While - this is (hopefully) highly portable and should get you started on your - platform of choice, it is also highly inefficient and should be replaced by - inline assembly. Just make sure that your assembly keeps all the promises - the C library makes. diff --git a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_Exit.c b/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_Exit.c deleted file mode 100644 index d2e6ee4..0000000 --- a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_Exit.c +++ /dev/null @@ -1,40 +0,0 @@ -/* _PDCLIB_exit( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_exit() fit for use with POSIX - kernels. -*/ - -#include - -#ifndef REGTEST - -#include "pdclib/_PDCLIB_glue.h" - -extern void _exit( int status ) _PDCLIB_NORETURN; - -void _PDCLIB_Exit( int status ) -{ - _exit( status ); -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ -#ifndef REGTEST - int UNEXPECTED_RETURN = 0; - _PDCLIB_Exit( 0 ); - TESTCASE( UNEXPECTED_RETURN ); -#endif - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB__Exit.c b/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB__Exit.c deleted file mode 100644 index d2e6ee4..0000000 --- a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB__Exit.c +++ /dev/null @@ -1,40 +0,0 @@ -/* _PDCLIB_exit( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_exit() fit for use with POSIX - kernels. -*/ - -#include - -#ifndef REGTEST - -#include "pdclib/_PDCLIB_glue.h" - -extern void _exit( int status ) _PDCLIB_NORETURN; - -void _PDCLIB_Exit( int status ) -{ - _exit( status ); -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ -#ifndef REGTEST - int UNEXPECTED_RETURN = 0; - _PDCLIB_Exit( 0 ); - TESTCASE( UNEXPECTED_RETURN ); -#endif - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_allocpages.c b/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_allocpages.c deleted file mode 100644 index d46d46f..0000000 --- a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_allocpages.c +++ /dev/null @@ -1,86 +0,0 @@ -/* _PDCLIB_allocpages( int const ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_allocpages() fit for use with - POSIX kernels. -*/ - -#include -#include - -#ifndef REGTEST - -int brk( void * ); -void * sbrk( intptr_t ); - -#include "pdclib/_PDCLIB_glue.h" - -static void * membreak = NULL; - -void * _PDCLIB_allocpages( int const n ) -{ - void * oldbreak; - if ( membreak == NULL ) - { - /* first call, make sure end-of-heap is page-aligned */ - intptr_t unaligned = 0; - membreak = sbrk( 0 ); - unaligned = _PDCLIB_PAGESIZE - (intptr_t)membreak % _PDCLIB_PAGESIZE; - if ( unaligned < _PDCLIB_PAGESIZE ) - { - /* end-of-heap not page-aligned - adjust */ - if ( sbrk( unaligned ) != membreak ) - { - /* error */ - return NULL; - } - membreak = (char *)membreak + unaligned; - } - } - /* increasing or decreasing heap - standard operation */ - oldbreak = membreak; - membreak = (void *)( (char *)membreak + ( n * _PDCLIB_PAGESIZE ) ); -#ifdef __CYGWIN__ - if ( sbrk( (char*)membreak - (char*)oldbreak ) == membreak ) -#else - if ( brk( membreak ) == 0 ) -#endif - { - /* successful */ - return oldbreak; - } - else - { - /* out of memory */ - membreak = oldbreak; - return NULL; - } -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ -#ifndef REGTEST - char * startbreak = sbrk( 0 ); - TESTCASE( _PDCLIB_allocpages( 0 ) ); - TESTCASE( ( (char *)sbrk( 0 ) - startbreak ) <= _PDCLIB_PAGESIZE ); - startbreak = sbrk( 0 ); - TESTCASE( _PDCLIB_allocpages( 1 ) ); - TESTCASE( sbrk( 0 ) == startbreak + ( 1 * _PDCLIB_PAGESIZE ) ); - TESTCASE( _PDCLIB_allocpages( 5 ) ); - TESTCASE( sbrk( 0 ) == startbreak + ( 6 * _PDCLIB_PAGESIZE ) ); - TESTCASE( _PDCLIB_allocpages( -3 ) ); - TESTCASE( sbrk( 0 ) == startbreak + ( 3 * _PDCLIB_PAGESIZE ) ); -#endif - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_close.c b/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_close.c deleted file mode 100644 index 113290a..0000000 --- a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_close.c +++ /dev/null @@ -1,36 +0,0 @@ -/* _PDCLIB_close( _PDCLIB_fd_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_close() fit for use with POSIX - kernels. -*/ - -#include - -#ifndef REGTEST - -#include "pdclib/_PDCLIB_glue.h" - -extern int close( int fd ); - -int _PDCLIB_close( int fd ) -{ - return close( fd ); -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ - /* No testdriver; tested in driver for _PDCLIB_open(). */ - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_fillbuffer.c b/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_fillbuffer.c deleted file mode 100644 index 012eed8..0000000 --- a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_fillbuffer.c +++ /dev/null @@ -1,78 +0,0 @@ -/* _PDCLIB_fillbuffer( struct _PDCLIB_file_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_fillbuffer() fit for - use with POSIX kernels. -*/ - -#include - -#ifndef REGTEST - -#include "pdclib/_PDCLIB_glue.h" - -#include - -typedef long ssize_t; -extern ssize_t read( int fd, void * buf, size_t count ); - -int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ) -{ - /* No need to handle buffers > INT_MAX, as PDCLib doesn't allow them */ - ssize_t rc = read( stream->handle, stream->buffer, stream->bufsize ); - if ( rc > 0 ) - { - /* Reading successful. */ - if ( ! ( stream->status & _PDCLIB_FBIN ) ) - { - /* TODO: Text stream conversion here */ - } - stream->pos.offset += rc; - stream->bufend = rc; - stream->bufidx = 0; - return 0; - } - if ( rc < 0 ) - { - /* Reading error */ - switch ( errno ) - { - /* See comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - case EBADF: - case EFAULT: - case EINTR: - case EINVAL: - case EIO: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - stream->status |= _PDCLIB_ERRORFLAG; - return EOF; - } - /* End-of-File */ - stream->status |= _PDCLIB_EOFFLAG; - return EOF; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ - /* Testing covered by ftell.c */ - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_flushbuffer.c b/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_flushbuffer.c deleted file mode 100644 index ca6b998..0000000 --- a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_flushbuffer.c +++ /dev/null @@ -1,110 +0,0 @@ -/* _PDCLIB_flushbuffer( struct _PDCLIB_file_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_flushbuffer() fit for - use with POSIX kernels. -*/ - -#include -#include - -#ifndef REGTEST - -#include "pdclib/_PDCLIB_glue.h" - -#include - -typedef long ssize_t; -extern ssize_t write( int fd, const void * buf, size_t count ); - -/* The number of attempts to complete an output buffer flushing before giving - * up. - * */ -#define _PDCLIB_IO_RETRIES 1 - -/* What the system should do after an I/O operation did not succeed, before */ -/* trying again. (Empty by default.) */ -#define _PDCLIB_IO_RETRY_OP( stream ) - -int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream ) -{ - /* No need to handle buffers > INT_MAX, as PDCLib doesn't allow them */ - _PDCLIB_size_t written = 0; - int rc; - unsigned int retries; - if ( ! ( stream->status & _PDCLIB_FBIN ) ) - { - /* TODO: Text stream conversion here */ - } - /* Keep trying to write data until everything is written, an error - occurs, or the configured number of retries is exceeded. - */ - for ( retries = _PDCLIB_IO_RETRIES; retries > 0; --retries ) - { - rc = (int)write( stream->handle, stream->buffer + written, stream->bufidx - written ); - if ( rc < 0 ) - { - /* Write error */ - switch ( errno ) - { - /* See <_PDCLIB_config.h>. There should be differenciated errno - handling here, possibly even a 1:1 mapping; but that is up - to the individual platform. - */ - case EBADF: - case EFAULT: - case EFBIG: - case EINTR: - case EINVAL: - case EIO: - case ENOSPC: - case EPIPE: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - stream->status |= _PDCLIB_ERRORFLAG; - /* Move unwritten remains to begin of buffer. */ - stream->bufidx -= written; - memmove( stream->buffer, stream->buffer + written, stream->bufidx ); - return EOF; - } - written += (_PDCLIB_size_t)rc; - stream->pos.offset += rc; - if ( written == stream->bufidx ) - { - /* Buffer written completely. */ - stream->bufidx = 0; - return 0; - } - } - /* Number of retries exceeded. You probably want a different errno value - here. - */ - _PDCLIB_errno = _PDCLIB_ERROR; - stream->status |= _PDCLIB_ERRORFLAG; - /* Move unwritten remains to begin of buffer. */ - stream->bufidx -= written; - memmove( stream->buffer, stream->buffer + written, stream->bufidx ); - return EOF; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ - /* Testing covered by ftell.c */ - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_open.c b/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_open.c deleted file mode 100644 index e35d65d..0000000 --- a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_open.c +++ /dev/null @@ -1,167 +0,0 @@ -/* _PDCLIB_open( const char * const, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_open() fit for use with POSIX - kernels. -*/ - -#include - -#ifndef REGTEST - -#include "pdclib/_PDCLIB_glue.h" - -#include -#include -#include -#include - -#include "/usr/include/errno.h" - -int _PDCLIB_open( const char * const filename, unsigned int mode ) -{ - /* This is an example implementation of _PDCLIB_open() fit for use with - POSIX kernels. - */ - int osmode; - int rc; - switch ( mode & ( _PDCLIB_FREAD | _PDCLIB_FWRITE | _PDCLIB_FAPPEND | _PDCLIB_FRW ) ) - { - case _PDCLIB_FREAD: /* "r" */ - osmode = O_RDONLY; - break; - case _PDCLIB_FWRITE: /* "w" */ - osmode = O_WRONLY | O_CREAT | O_TRUNC; - break; - case _PDCLIB_FAPPEND: /* "a" */ - osmode = O_WRONLY | O_APPEND | O_CREAT; - break; - case _PDCLIB_FREAD | _PDCLIB_FRW: /* "r+" */ - osmode = O_RDWR; - break; - case _PDCLIB_FWRITE | _PDCLIB_FRW: /* "w+" */ - osmode = O_RDWR | O_CREAT | O_TRUNC; - break; - case _PDCLIB_FAPPEND | _PDCLIB_FRW: /* "a+" */ - osmode = O_RDWR | O_APPEND | O_CREAT; - break; - default: /* Invalid mode */ - return -1; - } - if ( osmode & O_CREAT ) - { - rc = open( filename, osmode, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ); - } - else - { - rc = open( filename, osmode ); - } - if ( rc == -1 ) - { - switch ( errno ) - { - /* See the comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - case EACCES: - case EFAULT: - case EINTR: - case EISDIR: - case ELOOP: - case EMFILE: - case ENAMETOOLONG: - case ENFILE: - case ENODEV: - case ENOENT: - case ENOMEM: - case ENOSPC: - case ENOTDIR: - case EOVERFLOW: - case EROFS: - case ETXTBSY: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - } - return rc; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -#include -#include - -int main( void ) -{ -#ifndef REGTEST - /* This testdriver assumes POSIX, i.e. _PDCLIB_fd_t being int and being - incremented by one on each successful open. - */ - int fh; - char buffer[ 10 ]; - remove( testfile ); - /* Trying to read non-existent file. */ - TESTCASE( _PDCLIB_open( testfile, _PDCLIB_FREAD ) == _PDCLIB_NOHANDLE ); - /* Writing to file, trying to read from it. */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FWRITE ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( write( fh, "test", 4 ) == 4 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( read( fh, buffer, 4 ) == -1 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Reading from file, trying to write to it. */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FREAD ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( write( fh, "test", 4 ) == -1 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Appending to file, trying to read from it. */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FAPPEND ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( write( fh, "app", 3 ) == 3 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( read( fh, buffer, 10 ) == -1 ); - TESTCASE( write( fh, "end", 3 ) == 3 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Reading and writing from file ("r+"). */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FREAD | _PDCLIB_FRW ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( read( fh, buffer, 10 ) == 10 ); - TESTCASE( memcmp( buffer, "testappend", 10 ) == 0 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( write( fh, "wedo", 4 ) == 4 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( read( fh, buffer, 10 ) == 10 ); - TESTCASE( memcmp( buffer, "wedoappend", 10 ) == 0 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Writing and reading from file ("w+"). */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FWRITE | _PDCLIB_FRW ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( write( fh, "test", 4 ) == 4 ); - TESTCASE( lseek( fh, 1, SEEK_SET ) == 1 ); - TESTCASE( read( fh, buffer, 2 ) == 2 ); - TESTCASE( memcmp( buffer, "es", 2 ) == 0 ); - TESTCASE( write( fh, "sie", 3 ) == 3 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( read( fh, buffer, 6 ) == 6 ); - TESTCASE( memcmp( buffer, "tessie", 6 ) == 0 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Appending and reading from file ("a+"). */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FAPPEND | _PDCLIB_FRW ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( write( fh, "baby", 4 ) == 4 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( read( fh, buffer, 10 ) == 10 ); - TESTCASE( memcmp( buffer, "tessiebaby", 10 ) == 0 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Cleaning up. */ - TESTCASE( remove( testfile ) == 0 ); -#endif - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_rename.c b/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_rename.c deleted file mode 100644 index 8c23f79..0000000 --- a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_rename.c +++ /dev/null @@ -1,144 +0,0 @@ -/* _PDCLIB_rename( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_rename() fit for use with - POSIX kernels. - */ - -#include - -#ifndef REGTEST - -#include "pdclib/_PDCLIB_glue.h" - -#include - -extern int unlink( const char * pathname ); -extern int link( const char * old, const char * new ); - -int _PDCLIB_rename( const char * old, const char * new ) -{ - /* Note that the behaviour if new file exists is implementation-defined. - There is nothing wrong with either overwriting it or failing the - operation, but you might want to document whichever you chose. - This example fails if new file exists. - */ - if ( link( old, new ) == 0 ) - { - if ( unlink( old ) == EOF ) - { - switch ( errno ) - { - /* See the comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - case EACCES: - case EFAULT: - case EIO: - case EISDIR: - case ELOOP: - case ENAMETOOLONG: - case ENOENT: - case ENOMEM: - case ENOTDIR: - case EPERM: - case EROFS: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - return -1; - } - else - { - return 0; - } - } - else - { - switch ( errno ) - { - /* See the comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - case EACCES: - case EEXIST: - case EFAULT: - case EIO: - case ELOOP: - case EMLINK: - case ENAMETOOLONG: - case ENOENT: - case ENOMEM: - case ENOSPC: - case ENOTDIR: - case EPERM: - case EROFS: - case EXDEV: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - return EOF; - } -} - -#endif - -#ifdef TEST -#include "_PDCLIB_test.h" - -#include - -int main( void ) -{ -#ifndef REGTEST - FILE * file; - remove( testfile1 ); - remove( testfile2 ); - /* check that neither file exists */ - TESTCASE( fopen( testfile1, "r" ) == NULL ); - TESTCASE( fopen( testfile2, "r" ) == NULL ); - /* rename file 1 to file 2 - expected to fail */ - TESTCASE( _PDCLIB_rename( testfile1, testfile2 ) == -1 ); - /* create file 1 */ - TESTCASE( ( file = fopen( testfile1, "w" ) ) != NULL ); - TESTCASE( fputc( 'x', file ) == 'x' ); - TESTCASE( fclose( file ) == 0 ); - /* check that file 1 exists */ - TESTCASE( ( file = fopen( testfile1, "r" ) ) != NULL ); - TESTCASE( fclose( file ) == 0 ); - /* rename file 1 to file 2 */ - TESTCASE( _PDCLIB_rename( testfile1, testfile2 ) == 0 ); - /* check that file 2 exists, file 1 does not */ - TESTCASE( fopen( testfile1, "r" ) == NULL ); - TESTCASE( ( file = fopen( testfile2, "r" ) ) != NULL ); - TESTCASE( fclose( file ) == 0 ); - /* create another file 1 */ - TESTCASE( ( file = fopen( testfile1, "w" ) ) != NULL ); - TESTCASE( fputc( 'x', file ) == 'x' ); - TESTCASE( fclose( file ) == 0 ); - /* check that file 1 exists */ - TESTCASE( ( file = fopen( testfile1, "r" ) ) != NULL ); - TESTCASE( fclose( file ) == 0 ); - /* rename file 1 to file 2 - expected to fail, see comment in - _PDCLIB_rename() itself. - */ - TESTCASE( _PDCLIB_rename( testfile1, testfile2 ) == -1 ); - /* remove both files */ - remove( testfile1 ); - remove( testfile2 ); -#endif - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_seek.c b/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_seek.c deleted file mode 100644 index 4d09460..0000000 --- a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_seek.c +++ /dev/null @@ -1,82 +0,0 @@ -/* int64_t _PDCLIB_seek( FILE *, int64_t, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_seek() fit for use with POSIX - kernels. - */ - -#include - -#ifndef REGTEST - -#include "pdclib/_PDCLIB_glue.h" - -#include "/usr/include/errno.h" - -extern _PDCLIB_int64_t lseek64( int fd, _PDCLIB_int64_t offset, int whence ); -extern long lseek( int fd, long offset, int whence ); - -_PDCLIB_int64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int64_t offset, int whence ) -{ - _PDCLIB_int64_t rc; - switch ( whence ) - { - case SEEK_SET: - case SEEK_CUR: - case SEEK_END: - /* EMPTY - OK */ - break; - default: - /* See comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - _PDCLIB_errno = _PDCLIB_ERROR; - return EOF; - break; - } -#ifdef __CYGWIN__ - rc = lseek( stream->handle, offset, whence ); -#else - rc = lseek64( stream->handle, offset, whence ); -#endif - if ( rc != EOF ) - { - stream->ungetidx = 0; - stream->bufidx = 0; - stream->bufend = 0; - stream->pos.offset = rc; - return rc; - } - switch ( errno ) - { - case EBADF: - case EFAULT: - /* See comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - return EOF; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ - /* Testing covered by ftell.c */ - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_stdinit.c b/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_stdinit.c deleted file mode 100644 index 52b0651..0000000 --- a/src/pdclib/platform/example/functions/_PDCLIB/_PDCLIB_stdinit.c +++ /dev/null @@ -1,430 +0,0 @@ -/* _PDCLIB_stdinit - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example initialization of stdin, stdout and stderr to the integer - file descriptors 0, 1, and 2, respectively. This applies for a great variety - of operating systems, including POSIX compliant ones. -*/ - -#include -#include -#include - -#ifndef REGTEST - -/* In a POSIX system, stdin / stdout / stderr are equivalent to the (int) file - descriptors 0, 1, and 2 respectively. -*/ -/* TODO: This is proof-of-concept, requires finetuning. */ -static char _PDCLIB_sin_buffer[BUFSIZ]; -static char _PDCLIB_sout_buffer[BUFSIZ]; -static char _PDCLIB_serr_buffer[BUFSIZ]; - -static unsigned char _PDCLIB_sin_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; -static unsigned char _PDCLIB_sout_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; -static unsigned char _PDCLIB_serr_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; - -static struct _PDCLIB_file_t _PDCLIB_serr = { 2, _PDCLIB_serr_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_serr_ungetbuf, _IONBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, NULL }; -static struct _PDCLIB_file_t _PDCLIB_sout = { 1, _PDCLIB_sout_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sout_ungetbuf, _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, &_PDCLIB_serr }; -static struct _PDCLIB_file_t _PDCLIB_sin = { 0, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sin_ungetbuf, _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, NULL, &_PDCLIB_sout }; - -struct _PDCLIB_file_t * stdin = &_PDCLIB_sin; -struct _PDCLIB_file_t * stdout = &_PDCLIB_sout; -struct _PDCLIB_file_t * stderr = &_PDCLIB_serr; - -/* FIXME: This approach is a possible attack vector. */ -struct _PDCLIB_file_t * _PDCLIB_filelist = &_PDCLIB_sin; - -/* "C" locale - defaulting to ASCII-7. - 1 kByte (+ 4 byte) of data. - Each line: flags, lowercase, uppercase, collation. -*/ -static struct _PDCLIB_lc_ctype_entry_t _ctype_entries[ _PDCLIB_CHARSET_SIZE + 1 ] = { - { /* EOF */ 0, 0, 0 }, - { /* NUL */ _PDCLIB_CTYPE_CNTRL, 0x00, 0x00 }, - { /* SOH */ _PDCLIB_CTYPE_CNTRL, 0x01, 0x01 }, - { /* STX */ _PDCLIB_CTYPE_CNTRL, 0x02, 0x02 }, - { /* ETX */ _PDCLIB_CTYPE_CNTRL, 0x03, 0x03 }, - { /* EOT */ _PDCLIB_CTYPE_CNTRL, 0x04, 0x04 }, - { /* ENQ */ _PDCLIB_CTYPE_CNTRL, 0x05, 0x05 }, - { /* ACK */ _PDCLIB_CTYPE_CNTRL, 0x06, 0x06 }, - { /* BEL */ _PDCLIB_CTYPE_CNTRL, 0x07, 0x07 }, - { /* BS */ _PDCLIB_CTYPE_CNTRL, 0x08, 0x08 }, - { /* HT */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_BLANK | _PDCLIB_CTYPE_SPACE, 0x09, 0x09 }, - { /* LF */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0A, 0x0A }, - { /* VT */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0B, 0x0B }, - { /* FF */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0C, 0x0C }, - { /* CR */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0D, 0x0D }, - { /* SO */ _PDCLIB_CTYPE_CNTRL, 0x0E, 0x0E }, - { /* SI */ _PDCLIB_CTYPE_CNTRL, 0x0F, 0x0F }, - { /* DLE */ _PDCLIB_CTYPE_CNTRL, 0x10, 0x10 }, - { /* DC1 */ _PDCLIB_CTYPE_CNTRL, 0x11, 0x11 }, - { /* DC2 */ _PDCLIB_CTYPE_CNTRL, 0x12, 0x12 }, - { /* DC3 */ _PDCLIB_CTYPE_CNTRL, 0x13, 0x13 }, - { /* DC4 */ _PDCLIB_CTYPE_CNTRL, 0x14, 0x14 }, - { /* NAK */ _PDCLIB_CTYPE_CNTRL, 0x15, 0x15 }, - { /* SYN */ _PDCLIB_CTYPE_CNTRL, 0x16, 0x16 }, - { /* ETB */ _PDCLIB_CTYPE_CNTRL, 0x17, 0x17 }, - { /* CAN */ _PDCLIB_CTYPE_CNTRL, 0x18, 0x18 }, - { /* EM */ _PDCLIB_CTYPE_CNTRL, 0x19, 0x19 }, - { /* SUB */ _PDCLIB_CTYPE_CNTRL, 0x1A, 0x1A }, - { /* ESC */ _PDCLIB_CTYPE_CNTRL, 0x1B, 0x1B }, - { /* FS */ _PDCLIB_CTYPE_CNTRL, 0x1C, 0x1C }, - { /* GS */ _PDCLIB_CTYPE_CNTRL, 0x1D, 0x1D }, - { /* RS */ _PDCLIB_CTYPE_CNTRL, 0x1E, 0x1E }, - { /* US */ _PDCLIB_CTYPE_CNTRL, 0x1F, 0x1F }, - { /* SP */ _PDCLIB_CTYPE_BLANK | _PDCLIB_CTYPE_SPACE, 0x20, 0x20 }, - { /* '!' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x21, 0x21 }, - { /* '"' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x22, 0x22 }, - { /* '#' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x23, 0x23 }, - { /* '$' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x24, 0x24 }, - { /* '%' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x25, 0x25 }, - { /* '&' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x26, 0x26 }, - { /* ''' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x27, 0x27 }, - { /* '(' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x28, 0x28 }, - { /* ')' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x29, 0x29 }, - { /* '*' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2A, 0x2A }, - { /* '+' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2B, 0x2B }, - { /* ',' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2C, 0x2C }, - { /* '-' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2D, 0x2D }, - { /* '.' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2E, 0x2E }, - { /* '/' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2F, 0x2F }, - { /* '0' */ _PDCLIB_CTYPE_GRAPH, 0x30, 0x30 }, - { /* '1' */ _PDCLIB_CTYPE_GRAPH, 0x31, 0x31 }, - { /* '2' */ _PDCLIB_CTYPE_GRAPH, 0x32, 0x32 }, - { /* '3' */ _PDCLIB_CTYPE_GRAPH, 0x33, 0x33 }, - { /* '4' */ _PDCLIB_CTYPE_GRAPH, 0x34, 0x34 }, - { /* '5' */ _PDCLIB_CTYPE_GRAPH, 0x35, 0x35 }, - { /* '6' */ _PDCLIB_CTYPE_GRAPH, 0x36, 0x36 }, - { /* '7' */ _PDCLIB_CTYPE_GRAPH, 0x37, 0x37 }, - { /* '8' */ _PDCLIB_CTYPE_GRAPH, 0x38, 0x38 }, - { /* '9' */ _PDCLIB_CTYPE_GRAPH, 0x39, 0x39 }, - { /* ':' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3A, 0x3A }, - { /* ';' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3B, 0x3B }, - { /* '<' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3C, 0x3C }, - { /* '=' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3D, 0x3D }, - { /* '>' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3E, 0x3E }, - { /* '?' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3F, 0x3F }, - { /* '@' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x40, 0x40 }, - { /* 'A' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x41, 0x61 }, - { /* 'B' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x42, 0x62 }, - { /* 'C' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x43, 0x63 }, - { /* 'D' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x44, 0x64 }, - { /* 'E' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x45, 0x65 }, - { /* 'F' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x46, 0x66 }, - { /* 'G' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x47, 0x67 }, - { /* 'H' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x48, 0x68 }, - { /* 'I' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x49, 0x69 }, - { /* 'J' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4A, 0x6A }, - { /* 'K' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4B, 0x6B }, - { /* 'L' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4C, 0x6C }, - { /* 'M' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4D, 0x6D }, - { /* 'N' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4E, 0x6E }, - { /* 'O' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4F, 0x6F }, - { /* 'P' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x50, 0x70 }, - { /* 'Q' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x51, 0x71 }, - { /* 'R' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x52, 0x72 }, - { /* 'S' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x53, 0x73 }, - { /* 'T' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x54, 0x74 }, - { /* 'U' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x55, 0x75 }, - { /* 'V' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x56, 0x76 }, - { /* 'W' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x57, 0x77 }, - { /* 'X' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x58, 0x78 }, - { /* 'Y' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x59, 0x79 }, - { /* 'Z' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x5A, 0x7A }, - { /* '[' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5B, 0x5B }, - { /* '\' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5C, 0x5C }, - { /* ']' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5D, 0x5D }, - { /* '^' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5E, 0x5E }, - { /* '_' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5F, 0x5F }, - { /* '`' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x60, 0x60 }, - { /* 'a' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x41, 0x61 }, - { /* 'b' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x42, 0x62 }, - { /* 'c' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x43, 0x63 }, - { /* 'd' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x44, 0x64 }, - { /* 'e' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x45, 0x65 }, - { /* 'f' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x46, 0x66 }, - { /* 'g' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x47, 0x67 }, - { /* 'h' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x48, 0x68 }, - { /* 'i' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x49, 0x69 }, - { /* 'j' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4A, 0x6A }, - { /* 'k' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4B, 0x6B }, - { /* 'l' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4C, 0x6C }, - { /* 'm' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4D, 0x6D }, - { /* 'n' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4E, 0x6E }, - { /* 'o' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4F, 0x6F }, - { /* 'p' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x50, 0x70 }, - { /* 'q' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x51, 0x71 }, - { /* 'r' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x52, 0x72 }, - { /* 's' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x53, 0x73 }, - { /* 't' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x54, 0x74 }, - { /* 'u' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x55, 0x75 }, - { /* 'v' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x56, 0x76 }, - { /* 'w' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x57, 0x77 }, - { /* 'x' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x58, 0x78 }, - { /* 'y' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x59, 0x79 }, - { /* 'z' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x5A, 0x7A }, - { /* '{' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7B, 0x7B }, - { /* '|' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7C, 0x7C }, - { /* '}' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7D, 0x7D }, - { /* '~' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7E, 0x7E }, - { /* DEL */ _PDCLIB_CTYPE_CNTRL, 0x7F, 0x7F }, - { 0x00, 0x80, 0x80 }, - { 0x00, 0x81, 0x81 }, - { 0x00, 0x82, 0x82 }, - { 0x00, 0x83, 0x83 }, - { 0x00, 0x84, 0x84 }, - { 0x00, 0x85, 0x85 }, - { 0x00, 0x86, 0x86 }, - { 0x00, 0x87, 0x87 }, - { 0x00, 0x88, 0x88 }, - { 0x00, 0x89, 0x89 }, - { 0x00, 0x8A, 0x8A }, - { 0x00, 0x8B, 0x8B }, - { 0x00, 0x8C, 0x8C }, - { 0x00, 0x8D, 0x8D }, - { 0x00, 0x8E, 0x8E }, - { 0x00, 0x8F, 0x8F }, - { 0x00, 0x90, 0x90 }, - { 0x00, 0x91, 0x91 }, - { 0x00, 0x92, 0x92 }, - { 0x00, 0x93, 0x93 }, - { 0x00, 0x94, 0x94 }, - { 0x00, 0x95, 0x95 }, - { 0x00, 0x96, 0x96 }, - { 0x00, 0x97, 0x97 }, - { 0x00, 0x98, 0x98 }, - { 0x00, 0x99, 0x99 }, - { 0x00, 0x9A, 0x9A }, - { 0x00, 0x9B, 0x9B }, - { 0x00, 0x9C, 0x9C }, - { 0x00, 0x9D, 0x9D }, - { 0x00, 0x9E, 0x9E }, - { 0x00, 0x9F, 0x9F }, - { 0x00, 0xA0, 0xA0 }, - { 0x00, 0xA1, 0xA1 }, - { 0x00, 0xA2, 0xA2 }, - { 0x00, 0xA3, 0xA3 }, - { 0x00, 0xA4, 0xA4 }, - { 0x00, 0xA5, 0xA5 }, - { 0x00, 0xA6, 0xA6 }, - { 0x00, 0xA7, 0xA7 }, - { 0x00, 0xA8, 0xA8 }, - { 0x00, 0xA9, 0xA9 }, - { 0x00, 0xAA, 0xAA }, - { 0x00, 0xAB, 0xAB }, - { 0x00, 0xAC, 0xAC }, - { 0x00, 0xAD, 0xAD }, - { 0x00, 0xAE, 0xAE }, - { 0x00, 0xAF, 0xAF }, - { 0x00, 0xB0, 0xB0 }, - { 0x00, 0xB1, 0xB1 }, - { 0x00, 0xB2, 0xB2 }, - { 0x00, 0xB3, 0xB3 }, - { 0x00, 0xB4, 0xB4 }, - { 0x00, 0xB5, 0xB5 }, - { 0x00, 0xB6, 0xB6 }, - { 0x00, 0xB7, 0xB7 }, - { 0x00, 0xB8, 0xB8 }, - { 0x00, 0xB9, 0xB9 }, - { 0x00, 0xBA, 0xBA }, - { 0x00, 0xBB, 0xBB }, - { 0x00, 0xBC, 0xBC }, - { 0x00, 0xBD, 0xBD }, - { 0x00, 0xBE, 0xBE }, - { 0x00, 0xBF, 0xBF }, - { 0x00, 0xC0, 0xC0 }, - { 0x00, 0xC1, 0xC1 }, - { 0x00, 0xC2, 0xC2 }, - { 0x00, 0xC3, 0xC3 }, - { 0x00, 0xC4, 0xC4 }, - { 0x00, 0xC5, 0xC5 }, - { 0x00, 0xC6, 0xC6 }, - { 0x00, 0xC7, 0xC7 }, - { 0x00, 0xC8, 0xC8 }, - { 0x00, 0xC9, 0xC9 }, - { 0x00, 0xCA, 0xCA }, - { 0x00, 0xCB, 0xCB }, - { 0x00, 0xCC, 0xCC }, - { 0x00, 0xCD, 0xCD }, - { 0x00, 0xCE, 0xCE }, - { 0x00, 0xCF, 0xCF }, - { 0x00, 0xD0, 0xD0 }, - { 0x00, 0xD1, 0xD1 }, - { 0x00, 0xD2, 0xD2 }, - { 0x00, 0xD3, 0xD3 }, - { 0x00, 0xD4, 0xD4 }, - { 0x00, 0xD5, 0xD5 }, - { 0x00, 0xD6, 0xD6 }, - { 0x00, 0xD7, 0xD7 }, - { 0x00, 0xD8, 0xD8 }, - { 0x00, 0xD9, 0xD9 }, - { 0x00, 0xDA, 0xDA }, - { 0x00, 0xDB, 0xDB }, - { 0x00, 0xDC, 0xDC }, - { 0x00, 0xDD, 0xDD }, - { 0x00, 0xDE, 0xDE }, - { 0x00, 0xDF, 0xDF }, - { 0x00, 0xE0, 0xE0 }, - { 0x00, 0xE1, 0xE1 }, - { 0x00, 0xE2, 0xE2 }, - { 0x00, 0xE3, 0xE3 }, - { 0x00, 0xE4, 0xE4 }, - { 0x00, 0xE5, 0xE5 }, - { 0x00, 0xE6, 0xE6 }, - { 0x00, 0xE7, 0xE7 }, - { 0x00, 0xE8, 0xE8 }, - { 0x00, 0xE9, 0xE9 }, - { 0x00, 0xEA, 0xEA }, - { 0x00, 0xEB, 0xEB }, - { 0x00, 0xEC, 0xEC }, - { 0x00, 0xED, 0xED }, - { 0x00, 0xEE, 0xEE }, - { 0x00, 0xEF, 0xEF }, - { 0x00, 0xF0, 0xF0 }, - { 0x00, 0xF1, 0xF1 }, - { 0x00, 0xF2, 0xF2 }, - { 0x00, 0xF3, 0xF3 }, - { 0x00, 0xF4, 0xF4 }, - { 0x00, 0xF5, 0xF5 }, - { 0x00, 0xF6, 0xF6 }, - { 0x00, 0xF7, 0xF7 }, - { 0x00, 0xF8, 0xF8 }, - { 0x00, 0xF9, 0xF9 }, - { 0x00, 0xFA, 0xFA }, - { 0x00, 0xFB, 0xFB }, - { 0x00, 0xFC, 0xFC }, - { 0x00, 0xFD, 0xFD }, - { 0x00, 0xFE, 0xFE }, - { 0x00, 0xFF, 0xFF } -}; - -struct _PDCLIB_lc_ctype_t _PDCLIB_lc_ctype = { 0, 0x30, 0x39, 0x41, 0x46, 0x61, 0x66, &_ctype_entries[1] }; - -struct _PDCLIB_lc_collate_t _PDCLIB_lc_collate = { 0 }; - -struct lconv _PDCLIB_lconv = { - /* decimal_point */ (char *)".", - /* thousands_sep */ (char *)"", - /* grouping */ (char *)"", - /* mon_decimal_point */ (char *)"", - /* mon_thousands_sep */ (char *)"", - /* mon_grouping */ (char *)"", - /* positive_sign */ (char *)"", - /* negative_sign */ (char *)"", - /* currency_symbol */ (char *)"", - /* int_curr_symbol */ (char *)"", - /* frac_digits */ CHAR_MAX, - /* p_cs_precedes */ CHAR_MAX, - /* n_cs_precedes */ CHAR_MAX, - /* p_sep_by_space */ CHAR_MAX, - /* n_sep_by_space */ CHAR_MAX, - /* p_sign_posn */ CHAR_MAX, - /* n_sign_posn */ CHAR_MAX, - /* int_frac_digits */ CHAR_MAX, - /* int_p_cs_precedes */ CHAR_MAX, - /* int_n_cs_precedes */ CHAR_MAX, - /* int_p_sep_by_space */ CHAR_MAX, - /* int_n_sep_by_space */ CHAR_MAX, - /* int_p_sign_posn */ CHAR_MAX, - /* int_n_sign_posn */ CHAR_MAX -}; - -struct _PDCLIB_lc_numeric_monetary_t _PDCLIB_lc_numeric_monetary = { - &_PDCLIB_lconv, - 0, /* numeric_allocated */ - 0 /* monetary_allocated */ -}; - -struct _PDCLIB_lc_messages_t _PDCLIB_lc_messages = { - 0, - /* _PDCLIB_errno_texts */ - { - /* no error */ (char *)"", - /* ERANGE */ (char *)"ERANGE (Range error)", - /* EDOM */ (char *)"EDOM (Domain error)", - /* EILSEQ */ (char *)"EILSEQ (Illegal sequence)" - } -}; - -struct _PDCLIB_lc_time_t _PDCLIB_lc_time = { - 0, - /* _PDCLIB_month_name_abbr */ - { - (char *)"Jan", - (char *)"Feb", - (char *)"Mar", - (char *)"Apr", - (char *)"May", - (char *)"Jun", - (char *)"Jul", - (char *)"Aug", - (char *)"Sep", - (char *)"Oct", - (char *)"Now", - (char *)"Dec" - }, - /* _PDCLIB_month_name_full */ - { - (char *)"January", - (char *)"February", - (char *)"March", - (char *)"April", - (char *)"May", - (char *)"June", - (char *)"July", - (char *)"August", - (char *)"September", - (char *)"October", - (char *)"November", - (char *)"December" - }, - /* _PDCLIB_day_name_abbr */ - { - (char *)"Sun", - (char *)"Mon", - (char *)"Tue", - (char *)"Wed", - (char *)"Thu", - (char *)"Fri", - (char *)"Sat" - }, - /* _PDCLIB_day_name_full */ - { - (char *)"Sunday", - (char *)"Monday", - (char *)"Tuesday", - (char *)"Wednesday", - (char *)"Thursday", - (char *)"Friday", - (char *)"Saturday" - }, - /* date / time format */ (char *)"%a %b %e %T %Y", - /* 12h time format */ (char *)"%I:%M:%S %p", - /* date format */ (char *)"%m/%d/%y", - /* time format */ (char *)"%T", - /* AM / PM designation */ - { - (char *)"AM", - (char *)"PM" - } -}; - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ - /* Testing covered by several other testdrivers using stdin / stdout / - stderr. - */ - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/signal/raise.c b/src/pdclib/platform/example/functions/signal/raise.c deleted file mode 100644 index 59ccc9f..0000000 --- a/src/pdclib/platform/example/functions/signal/raise.c +++ /dev/null @@ -1,114 +0,0 @@ -/* raise( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -#ifndef REGTEST - -#include -#include - -extern void (*_PDCLIB_sigabrt)( int ); -extern void (*_PDCLIB_sigfpe)( int ); -extern void (*_PDCLIB_sigill)( int ); -extern void (*_PDCLIB_sigint)( int ); -extern void (*_PDCLIB_sigsegv)( int ); -extern void (*_PDCLIB_sigterm)( int ); - -int raise( int sig ) -{ - void (*sighandler)( int ); - const char * message; - switch ( sig ) - { - case SIGABRT: - sighandler = _PDCLIB_sigabrt; - message = "Abnormal termination (SIGABRT)"; - break; - case SIGFPE: - sighandler = _PDCLIB_sigfpe; - message = "Arithmetic exception (SIGFPE)"; - break; - case SIGILL: - sighandler = _PDCLIB_sigill; - message = "Illegal instruction (SIGILL)"; - break; - case SIGINT: - sighandler = _PDCLIB_sigint; - message = "Interactive attention signal (SIGINT)"; - break; - case SIGSEGV: - sighandler = _PDCLIB_sigsegv; - message = "Invalid memory access (SIGSEGV)"; - break; - case SIGTERM: - sighandler = _PDCLIB_sigterm; - message = "Termination request (SIGTERM)"; - break; - default: - fprintf( stderr, "Unknown signal #%d\n", sig ); - _Exit( EXIT_FAILURE ); - } - if ( sighandler == SIG_DFL ) - { - fputs( message, stderr ); - _Exit( EXIT_FAILURE ); - } - else if ( sighandler != SIG_IGN ) - { - sighandler = signal( sig, SIG_DFL ); - sighandler( sig ); - } - return 0; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -#include - -static volatile sig_atomic_t flag = 0; - -static int expected_signal = 0; - -static void test_handler( int sig ) -{ - TESTCASE( sig == expected_signal ); - flag = 1; -} - -int main( void ) -{ - /* Could be other than SIG_DFL if you changed the implementation. */ - TESTCASE( signal( SIGABRT, SIG_IGN ) == SIG_DFL ); - /* Should be ignored. */ - TESTCASE( raise( SIGABRT ) == 0 ); - /* Installing test handler, old handler should be returned */ - TESTCASE( signal( SIGABRT, test_handler ) == SIG_IGN ); - /* Raising and checking SIGABRT */ - expected_signal = SIGABRT; - TESTCASE( raise( SIGABRT ) == 0 ); - TESTCASE( flag == 1 ); - /* Re-installing test handler, should have been reset to default */ - /* Could be other than SIG_DFL if you changed the implementation. */ - TESTCASE( signal( SIGABRT, test_handler ) == SIG_DFL ); - /* Raising and checking SIGABRT */ - flag = 0; - TESTCASE( raise( SIGABRT ) == 0 ); - TESTCASE( flag == 1 ); - /* Installing test handler for different signal... */ - TESTCASE( signal( SIGTERM, test_handler ) == SIG_DFL ); - /* Raising and checking SIGTERM */ - expected_signal = SIGTERM; - TESTCASE( raise( SIGTERM ) == 0 ); - TESTCASE( flag == 1 ); - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/signal/signal.c b/src/pdclib/platform/example/functions/signal/signal.c deleted file mode 100644 index e6775e7..0000000 --- a/src/pdclib/platform/example/functions/signal/signal.c +++ /dev/null @@ -1,75 +0,0 @@ -/* signal( int, void (*)( int ) ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -#ifndef REGTEST - -#include - -void (*_PDCLIB_sigabrt)( int ) = SIG_DFL; -void (*_PDCLIB_sigfpe)( int ) = SIG_DFL; -void (*_PDCLIB_sigill)( int ) = SIG_DFL; -void (*_PDCLIB_sigint)( int ) = SIG_DFL; -void (*_PDCLIB_sigsegv)( int ) = SIG_DFL; -void (*_PDCLIB_sigterm)( int ) = SIG_DFL; - -void (*signal( int sig, void (*func)( int ) ) )( int ) -{ - void (*oldhandler)( int ); - if ( sig <= 0 || func == SIG_ERR ) - { - return SIG_ERR; - } - switch ( sig ) - { - case SIGABRT: - oldhandler = _PDCLIB_sigabrt; - _PDCLIB_sigabrt = func; - break; - case SIGFPE: - oldhandler = _PDCLIB_sigfpe; - _PDCLIB_sigfpe = func; - break; - case SIGILL: - oldhandler = _PDCLIB_sigill; - _PDCLIB_sigill = func; - break; - case SIGINT: - oldhandler = _PDCLIB_sigint; - _PDCLIB_sigint = func; - break; - case SIGSEGV: - oldhandler = _PDCLIB_sigsegv; - _PDCLIB_sigsegv = func; - break; - case SIGTERM: - oldhandler = _PDCLIB_sigterm; - _PDCLIB_sigterm = func; - break; - default: - /* The standard calls for an unspecified "positive value". You - will probably want to define a specific value for this. - */ - _PDCLIB_errno = 1; - return SIG_ERR; - } - return oldhandler; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ - /* Testing covered by raise.c */ - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/stdio/remove.c b/src/pdclib/platform/example/functions/stdio/remove.c deleted file mode 100644 index aca3eaf..0000000 --- a/src/pdclib/platform/example/functions/stdio/remove.c +++ /dev/null @@ -1,75 +0,0 @@ -/* remove( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of remove() fit for use with POSIX kernels. -*/ - -#include - -#ifndef REGTEST - -#include - -#include "/usr/include/errno.h" - -extern struct _PDCLIB_file_t * _PDCLIB_filelist; - -extern int unlink( const char * pathname ); - -int remove( const char * pathname ) -{ - int rc; - struct _PDCLIB_file_t * current = _PDCLIB_filelist; - while ( current != NULL ) - { - if ( ( current->filename != NULL ) && ( strcmp( current->filename, pathname ) == 0 ) ) - { - return EOF; - } - current = current->next; - } - if ( ( rc = unlink( pathname ) ) == -1 ) - { - switch ( errno ) - { - /* See the comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - case EACCES: - case EFAULT: - case EIO: - case EISDIR: - case ELOOP: - case ENAMETOOLONG: - case ENOENT: - case ENOMEM: - case ENOTDIR: - case EPERM: - case EROFS: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - } - return rc; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ - /* Testing covered by ftell.c (and several others) */ - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/stdio/tmpfile.c b/src/pdclib/platform/example/functions/stdio/tmpfile.c deleted file mode 100644 index 585a61d..0000000 --- a/src/pdclib/platform/example/functions/stdio/tmpfile.c +++ /dev/null @@ -1,114 +0,0 @@ -/* tmpfile( void ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -#ifndef REGTEST - -#include "pdclib/_PDCLIB_glue.h" - -#include -#include -#include - -#include -#include -#include -#include - -extern struct _PDCLIB_file_t * _PDCLIB_filelist; - -/* This is an example implementation of tmpfile() fit for use with POSIX - kernels. -*/ -struct _PDCLIB_file_t * tmpfile( void ) -{ - FILE * rc; - /* This is the chosen way to get high-quality randomness. Replace as - appropriate. - */ - FILE * randomsource = fopen( "/proc/sys/kernel/random/uuid", "rb" ); - char filename[ L_tmpnam ]; - _PDCLIB_fd_t fd; - if ( randomsource == NULL ) - { - return NULL; - } - for ( ;; ) - { - /* Get a filename candidate. What constitutes a valid filename and - where temporary files are usually located is platform-dependent, - which is one reason why this function is located in the platform - overlay. The other reason is that a *good* implementation should - use high-quality randomness instead of a pseudo-random sequence to - generate the filename candidate, which is *also* platform-dependent. - */ - unsigned int random; - fscanf( randomsource, "%u", &random ); - sprintf( filename, "/tmp/%u.tmp", random ); - /* Check if file of this name exists. Note that fopen() is a very weak - check, which does not take e.g. access permissions into account - (file might exist but not readable). Replace with something more - appropriate. - */ - fd = open( filename, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR ); - if ( fd != -1 ) - { - break; - } - close( fd ); - } - fclose( randomsource ); - /* See fopen(). */ - if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + L_tmpnam + BUFSIZ ) ) == NULL ) - { - /* No memory to set up FILE structure */ - close( fd ); - return NULL; - } - rc->status = _PDCLIB_filemode( "wb+" ) | _IOLBF | _PDCLIB_DELONCLOSE; - rc->handle = fd; - rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t ); - rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE; - rc->buffer = rc->filename + L_tmpnam; - strcpy( rc->filename, filename ); - rc->bufsize = BUFSIZ; - rc->bufidx = 0; - rc->ungetidx = 0; - rc->next = _PDCLIB_filelist; - _PDCLIB_filelist = rc; - return rc; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -#include - -int main( void ) -{ - FILE * fh; -#ifndef REGTEST - char filename[ L_tmpnam ]; - FILE * fhtest; -#endif - TESTCASE( ( fh = tmpfile() ) != NULL ); - TESTCASE( fputc( 'x', fh ) == 'x' ); - /* Checking that file is actually there */ - TESTCASE_NOREG( strcpy( filename, fh->filename ) == filename ); - TESTCASE_NOREG( ( fhtest = fopen( filename, "r" ) ) != NULL ); - TESTCASE_NOREG( fclose( fhtest ) == 0 ); - /* Closing tmpfile */ - TESTCASE( fclose( fh ) == 0 ); - /* Checking that file was deleted */ - TESTCASE_NOREG( fopen( filename, "r" ) == NULL ); - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/stdlib/getenv.c b/src/pdclib/platform/example/functions/stdlib/getenv.c deleted file mode 100644 index 72bbcd2..0000000 --- a/src/pdclib/platform/example/functions/stdlib/getenv.c +++ /dev/null @@ -1,45 +0,0 @@ -/* getenv( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of getenv() fit for use with POSIX kernels. -*/ - -#include -#include - -#ifndef REGTEST - -extern char * * environ; - -char * getenv( const char * name ) -{ - size_t len = strlen( name ); - size_t index = 0; - while ( environ[ index ] != NULL ) - { - if ( strncmp( environ[ index ], name, len ) == 0 ) - { - return environ[ index ] + len + 1; - } - index++; - } - return NULL; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ - TESTCASE( strcmp( getenv( "SHELL" ), "/bin/bash" ) == 0 ); - /* TESTCASE( strcmp( getenv( "SHELL" ), "/bin/sh" ) == 0 ); */ - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/stdlib/system.c b/src/pdclib/platform/example/functions/stdlib/system.c deleted file mode 100644 index 15603c3..0000000 --- a/src/pdclib/platform/example/functions/stdlib/system.c +++ /dev/null @@ -1,57 +0,0 @@ -/* system( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -/* This is an example implementation of system() fit for use with POSIX kernels. -*/ - -extern int fork( void ); -extern int execve( const char * filename, char * const argv[], char * const envp[] ); -extern int wait( int * status ); - -int system( const char * string ) -{ - const char * argv[] = { "sh", "-c", NULL, NULL }; - argv[2] = string; - if ( string != NULL ) - { - int pid = fork(); - if ( pid == 0 ) - { - execve( "/bin/sh", (char * * const)argv, NULL ); - } - else if ( pid > 0 ) - { - while( wait( NULL ) != pid ); - } - } - return -1; -} - -#ifdef TEST - -#include "_PDCLIB_test.h" - -#define SHELLCOMMAND "echo 'SUCCESS testing system()'" - -int main( void ) -{ - FILE * fh; - char buffer[25]; - buffer[24] = 'x'; - TESTCASE( ( fh = freopen( testfile, "wb+", stdout ) ) != NULL ); - TESTCASE( system( SHELLCOMMAND ) ); - rewind( fh ); - TESTCASE( fread( buffer, 1, 24, fh ) == 24 ); - TESTCASE( memcmp( buffer, "SUCCESS testing system()", 24 ) == 0 ); - TESTCASE( buffer[24] == 'x' ); - TESTCASE( fclose( fh ) == 0 ); - TESTCASE( remove( testfile ) == 0 ); - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/time/clock.c b/src/pdclib/platform/example/functions/time/clock.c deleted file mode 100644 index 825e040..0000000 --- a/src/pdclib/platform/example/functions/time/clock.c +++ /dev/null @@ -1,35 +0,0 @@ -/* clock( void ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -#ifndef REGTEST - -#include - -clock_t clock( void ) -{ - struct tms buf; - if ( times( &buf ) != (clock_t)-1 ) - { - return buf.tms_utime + buf.tms_stime; - } - return -1; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ - TESTCASE( NO_TESTDRIVER ); - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/time/time.c b/src/pdclib/platform/example/functions/time/time.c deleted file mode 100644 index cbb29e1..0000000 --- a/src/pdclib/platform/example/functions/time/time.c +++ /dev/null @@ -1,41 +0,0 @@ -/* time( time_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -#ifndef REGTEST - -#include - -/* See comments in time.h on the semantics of time_t. */ - -time_t time( time_t * timer ) -{ - struct timeval tv; - if ( gettimeofday( &tv, NULL ) == 0 ) - { - if ( timer != NULL ) - { - *timer = tv.tv_sec; - } - return tv.tv_sec; - } - return -1; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ - TESTCASE( NO_TESTDRIVER ); - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/functions/time/timespec_get.c b/src/pdclib/platform/example/functions/time/timespec_get.c deleted file mode 100644 index d8cbab7..0000000 --- a/src/pdclib/platform/example/functions/time/timespec_get.c +++ /dev/null @@ -1,42 +0,0 @@ -/* timespec_get( struct timespec *, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -#ifndef REGTEST - -#include - -int timespec_get( struct timespec * ts, int base ) -{ - if ( base == TIME_UTC ) - { - /* We can make do with a really thin wrapper here. */ - struct timeval tv; - if ( gettimeofday( &tv, NULL ) == 0 ) - { - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec * 1000; - return base; - } - } - /* Not supporting any other time base than TIME_UTC for now. */ - return 0; -} - -#endif - -#ifdef TEST - -#include "_PDCLIB_test.h" - -int main( void ) -{ - TESTCASE( NO_TESTDRIVER ); - return TEST_RESULTS; -} - -#endif diff --git a/src/pdclib/platform/example/include/float.h b/src/pdclib/platform/example/include/float.h deleted file mode 100644 index 538d69e..0000000 --- a/src/pdclib/platform/example/include/float.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Characteristics of floating types - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#ifndef _PDCLIB_FLOAT_H -#define _PDCLIB_FLOAT_H _PDCLIB_FLOAT_H - -#include "pdclib/_PDCLIB_config.h" - -#define FLT_ROUNDS _PDCLIB_FLT_ROUNDS -#define FLT_EVAL_METHOD _PDCLIB_FLT_EVAL_METHOD -#define DECIMAL_DIG _PDCLIB_DECIMAL_DIG - - /* Radix of exponent representation */ -#define FLT_RADIX __FLT_RADIX__ - /* Number of base-FLT_RADIX digits in the significand of a float */ -#define FLT_MANT_DIG __FLT_MANT_DIG__ - /* Number of decimal digits of precision in a float */ -#define FLT_DIG __FLT_DIG__ - /* Difference between 1.0 and the minimum float greater than 1.0 */ -#define FLT_EPSILON __FLT_EPSILON__ - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ -#define FLT_MIN_EXP __FLT_MIN_EXP__ - /* Minimum normalised float */ -#define FLT_MIN __FLT_MIN__ - /* Minimum int x such that 10**x is a normalised float */ -#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__ - /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ -#define FLT_MAX_EXP __FLT_MAX_EXP__ - /* Maximum float */ -#define FLT_MAX __FLT_MAX__ - /* Maximum int x such that 10**x is a representable float */ -#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__ - - /* Number of base-FLT_RADIX digits in the significand of a double */ -#define DBL_MANT_DIG __DBL_MANT_DIG__ - /* Number of decimal digits of precision in a double */ -#define DBL_DIG __DBL_DIG__ - /* Difference between 1.0 and the minimum double greater than 1.0 */ -#define DBL_EPSILON __DBL_EPSILON__ - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ -#define DBL_MIN_EXP __DBL_MIN_EXP__ - /* Minimum normalised double */ -#define DBL_MIN __DBL_MIN__ - /* Minimum int x such that 10**x is a normalised double */ -#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__ - /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ -#define DBL_MAX_EXP __DBL_MAX_EXP__ - /* Maximum double */ -#define DBL_MAX __DBL_MAX__ - /* Maximum int x such that 10**x is a representable double */ -#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__ - - /* Number of base-FLT_RADIX digits in the significand of a long double */ -#define LDBL_MANT_DIG __LDBL_MANT_DIG__ - /* Number of decimal digits of precision in a long double */ -#define LDBL_DIG __LDBL_DIG__ - /* Difference between 1.0 and the minimum long double greater than 1.0 */ -#define LDBL_EPSILON __LDBL_EPSILON__ - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ -#define LDBL_MIN_EXP __LDBL_MIN_EXP__ - /* Minimum normalised long double */ -#define LDBL_MIN __LDBL_MIN__ - /* Minimum int x such that 10**x is a normalised long double */ -#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ - /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ -#define LDBL_MAX_EXP __LDBL_MAX_EXP__ - /* Maximum long double */ -#define LDBL_MAX __LDBL_MAX__ - /* Maximum int x such that 10**x is a representable long double */ -#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ - -#endif diff --git a/src/pdclib/platform/example/include/pdclib/_PDCLIB_config.h b/src/pdclib/platform/example/include/pdclib/_PDCLIB_config.h deleted file mode 100644 index 9731f86..0000000 --- a/src/pdclib/platform/example/include/pdclib/_PDCLIB_config.h +++ /dev/null @@ -1,426 +0,0 @@ -/* Internal PDCLib configuration <_PDCLIB_config.h> - (Generic Template) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#ifndef _PDCLIB_CONFIG_H -#define _PDCLIB_CONFIG_H _PDCLIB_CONFIG_H - -/* -------------------------------------------------------------------------- */ -/* Misc */ -/* -------------------------------------------------------------------------- */ - -/* The character (sequence) your platform uses as newline. */ -#define _PDCLIB_endl "\n" - -/* exit() can signal success to the host environment by the value of zero or */ -/* the constant EXIT_SUCCESS. Failure is signaled by EXIT_FAILURE. Note that */ -/* any other return value is "implementation-defined", i.e. your environment */ -/* is not required to handle it gracefully. Set your definitions here. */ -#define _PDCLIB_SUCCESS 0 -#define _PDCLIB_FAILURE -1 - -/* qsort() in requires a function that swaps two memory areas. */ -/* Below is a naive implementation that can be improved significantly for */ -/* specific platforms, e.g. by swapping int instead of char. */ -#define _PDCLIB_memswp( i, j, size ) char tmp; do { tmp = *i; *i++ = *j; *j++ = tmp; } while ( --size ); - -/* Define this to some compiler directive that can be written after the */ -/* parameter list of a function declaration to indicate the function does */ -/* never return. If your compiler does not support such a directive, define */ -/* to nothing. (This is to avoid warnings with the exit functions under GCC.) */ -#define _PDCLIB_NORETURN __attribute__(( noreturn )) - -/* -------------------------------------------------------------------------- */ -/* Integers */ -/* -------------------------------------------------------------------------- */ -/* Assuming 8-bit char, two's-complement architecture here. 'short' being */ -/* 16 bit, 'int' being either 16, 32 or 64 bit, 'long' being either 32 or 64 */ -/* bit (but 64 bit only if 'int' is 32 bit), and 'long long' being 64 bit if */ -/* 'long' is not, 64 or 128 bit otherwise. */ -/* Author is quite willing to support other systems but would like to hear of */ -/* interest in such support and details on the to-be-supported architecture */ -/* first, before going to lengths about it. */ -/* -------------------------------------------------------------------------- */ - -/* Set to 0 if your 'char' type is unsigned. */ -#ifdef __CHAR_UNSIGNED__ -#define _PDCLIB_CHAR_SIGNED 0 -#else -#define _PDCLIB_CHAR_SIGNED 1 -#endif - -/* Width of the integer types short, int, long, and long long, in bytes. */ -/* SHRT == 2, INT >= SHRT, LONG >= INT >= 4, LLONG >= LONG - check your */ -/* compiler manuals. */ -#define _PDCLIB_SHRT_BYTES 2 -#define _PDCLIB_INT_BYTES 4 -#ifdef __LP64__ -#define _PDCLIB_LONG_BYTES 8 -#else -#define _PDCLIB_LONG_BYTES 4 -#endif -#define _PDCLIB_LLONG_BYTES 8 - -/* defines the div() function family that allows taking quotient */ -/* and remainder of an integer division in one operation. Many platforms */ -/* support this in hardware / opcode, and the standard permits ordering of */ -/* the return structure in any way to fit the hardware. That is why those */ -/* structs can be configured here. */ - -struct _PDCLIB_div_t -{ - int quot; - int rem; -}; - -struct _PDCLIB_ldiv_t -{ - long int quot; - long int rem; -}; - -struct _PDCLIB_lldiv_t -{ - long long int quot; - long long int rem; -}; - -/* -------------------------------------------------------------------------- */ -/* defines a set of integer types that are of a minimum width, and */ -/* "usually fastest" on the system. (If, for example, accessing a single char */ -/* requires the CPU to access a complete int and then mask out the char, the */ -/* "usually fastest" type of at least 8 bits would be int, not char.) */ -/* If you do not have information on the relative performance of the types, */ -/* the standard allows you to define any type that meets minimum width and */ -/* signedness requirements. */ -/* The defines below are just configuration for the real typedefs and limit */ -/* definitions done in <_PDCLIB_int.h>. The uppercase define shall be either */ -/* SHRT, INT, LONG, or LLONG (telling which values to use for the *_MIN and */ -/* *_MAX limits); the lowercase define either short, int, long, or long long */ -/* (telling the actual type to use). */ -/* The third define is the length modifier used for the type in printf() and */ -/* scanf() functions (used in ). */ -/* If you require a non-standard datatype to define the "usually fastest" */ -/* types, PDCLib as-is doesn't support that. Please contact the author with */ -/* details on your platform in that case, so support can be added. */ -/* -------------------------------------------------------------------------- */ - -#define _PDCLIB_FAST8 INT -#define _PDCLIB_fast8 int -#define _PDCLIB_FAST8_CONV - -#define _PDCLIB_FAST16 INT -#define _PDCLIB_fast16 int -#define _PDCLIB_FAST16_CONV - -#define _PDCLIB_FAST32 INT -#define _PDCLIB_fast32 int -#define _PDCLIB_FAST32_CONV - -#define _PDCLIB_FAST64 LONG -#define _PDCLIB_fast64 long -#define _PDCLIB_FAST64_CONV l - -/* -------------------------------------------------------------------------- */ -/* What follows are a couple of "special" typedefs and their limits. Again, */ -/* the actual definition of the limits is done in <_PDCLIB_int.h>, and the */ -/* defines here are merely "configuration". See above for details. */ -/* -------------------------------------------------------------------------- */ - -/* The result type of substracting two pointers */ -#define _PDCLIB_ptrdiff long -#define _PDCLIB_PTRDIFF LONG -#define _PDCLIB_PTR_CONV l - -/* An integer type that can be accessed as atomic entity (think asynchronous - interrupts). The type itself is not defined in a freestanding environment, - but its limits are. (Don't ask.) -*/ -#define _PDCLIB_sig_atomic int -#define _PDCLIB_SIG_ATOMIC INT - -/* Result type of the 'sizeof' operator (must be unsigned) */ -#define _PDCLIB_size unsigned long -#define _PDCLIB_SIZE ULONG - -/* Large enough an integer to hold all character codes of the largest supported - locale. -*/ -#define _PDCLIB_wchar unsigned int -#define _PDCLIB_WCHAR UINT - -/* Large enough an integer to hold all character codes of the largest supported - locale plus WEOF (which needs not to be equal to EOF, nor needs to be of - negative value). -*/ -#define _PDCLIB_wint unsigned int -#define _PDCLIB_WINT UINT - -/* (Signed) integer type capable of taking the (cast) value of a void *, and - having the value cast back to void *, comparing equal to the original. -*/ -#define _PDCLIB_intptr long -#define _PDCLIB_INTPTR LONG - -/* Largest supported integer type. Implementation note: see _PDCLIB_atomax(). */ -#define _PDCLIB_intmax long long int -#define _PDCLIB_INTMAX LLONG -#define _PDCLIB_MAX_CONV ll -/* You are also required to state the literal suffix for the intmax type */ -#define _PDCLIB_INTMAX_LITERAL ll - -/* defines imaxdiv(), which is equivalent to the div() function */ -/* family (see further above) with intmax_t as basis. */ - -struct _PDCLIB_imaxdiv_t -{ - _PDCLIB_intmax quot; - _PDCLIB_intmax rem; -}; - -/* -------------------------------------------------------------------------- */ -/* Time types */ -/* -------------------------------------------------------------------------- */ - -/* See for a couple of comments on these types and their semantics. */ - -#define _PDCLIB_time long - -#define _PDCLIB_clock long -#define _PDCLIB_CLOCKS_PER_SEC 1000000 - -#define _PDCLIB_TIME_UTC 1 - -/* -------------------------------------------------------------------------- */ -/* Floating Point */ -/* -------------------------------------------------------------------------- */ - -/* Whether the implementation rounds toward zero (0), to nearest (1), toward - positive infinity (2), or toward negative infinity (3). (-1) signifies - indeterminable rounding, any other value implementation-specific rounding. -*/ -#define _PDCLIB_FLT_ROUNDS -1 - -/* Whether the implementation uses exact-width precision (0), promotes float - to double (1), or promotes float and double to long double (2). (-1) - signifies indeterminable behaviour, any other value implementation-specific - behaviour. -*/ -#define _PDCLIB_FLT_EVAL_METHOD -1 - -/* "Number of the decimal digits (n), such that any floating-point number in the - widest supported floating type with p(max) radix (b) digits can be rounded to - a floating-point number with (n) decimal digits and back again without change - to the value p(max) log(10)b if (b) is a power of 10, [1 + p(max) log(10)b] - otherwise." - 64bit IEC 60559 double format (53bit mantissa) is DECIMAL_DIG 17. - 80bit IEC 60559 double-extended format (64bit mantissa) is DECIMAL_DIG 21. -*/ -#define _PDCLIB_DECIMAL_DIG 17 - -/* -------------------------------------------------------------------------- */ -/* Platform-dependent macros defined by the standard headers. */ -/* -------------------------------------------------------------------------- */ - -/* The offsetof macro - Contract: Expand to an integer constant expression of type size_t, which - represents the offset in bytes to the structure member from the beginning - of the structure. If the specified member is a bitfield, behaviour is - undefined. - There is no standard-compliant way to do this. - This implementation casts an integer zero to 'pointer to type', and then - takes the address of member. This is undefined behaviour but should work on - most compilers. -*/ -#define _PDCLIB_offsetof( type, member ) ( (size_t) &( ( (type *) 0 )->member ) ) - -/* Variable Length Parameter List Handling () - The macros defined by are highly dependent on the calling - conventions used, and you probably have to replace them with builtins of - your compiler. -*/ - -#if defined( __i386 ) - -/* The following generic implementation works only for pure - stack-based architectures, and only if arguments are aligned to pointer - type. Credits to Michael Moody, who contributed this to the Public Domain. -*/ - -/* Internal helper macro. va_round is not part of . */ -#define _PDCLIB_va_round( type ) ( (sizeof(type) + sizeof(void *) - 1) & ~(sizeof(void *) - 1) ) - -typedef char * _PDCLIB_va_list; -#define _PDCLIB_va_arg( ap, type ) ( (ap) += (_PDCLIB_va_round(type)), ( *(type*) ( (ap) - (_PDCLIB_va_round(type)) ) ) ) -#define _PDCLIB_va_copy( dest, src ) ( (dest) = (src), (void)0 ) -#define _PDCLIB_va_end( ap ) ( (ap) = (void *)0, (void)0 ) -#define _PDCLIB_va_start( ap, parmN ) ( (ap) = (char *) &parmN + ( _PDCLIB_va_round(parmN) ), (void)0 ) - -#elif defined( __x86_64 ) || defined( __arm__ ) - -/* No way to cover x86_64 or arm with a generic implementation, as it uses - register-based parameter passing. Using compiler builtins here. -*/ -typedef __builtin_va_list _PDCLIB_va_list; -#define _PDCLIB_va_arg( ap, type ) ( __builtin_va_arg( ap, type ) ) -#define _PDCLIB_va_copy( dest, src ) ( __builtin_va_copy( dest, src ) ) -#define _PDCLIB_va_end( ap ) ( __builtin_va_end( ap ) ) -#define _PDCLIB_va_start( ap, parmN ) ( __builtin_va_start( ap, parmN ) ) - -#else - -#error Please create your own _PDCLIB_config.h. Using the existing one as-is will not work. - -#endif - -/* -------------------------------------------------------------------------- */ -/* OS "glue", part 1 */ -/* These are values and data type definitions that you would have to adapt to */ -/* the capabilities and requirements of your OS. */ -/* The actual *functions* of the OS interface are declared in _PDCLIB_glue.h. */ -/* -------------------------------------------------------------------------- */ - -/* Memory management -------------------------------------------------------- */ - -/* Set this to the page size of your OS. If your OS does not support paging, set - to an appropriate value. (Too small, and malloc() will call the kernel too - often. Too large, and you will waste memory.) -*/ -#define _PDCLIB_PAGESIZE 4096 - -/* Set this to the minimum memory node size. Any malloc() for a smaller size - will be satisfied by a malloc() of this size instead (to avoid excessive - fragmentation). -*/ -#define _PDCLIB_MINALLOC 8 - -/* I/O ---------------------------------------------------------------------- */ - -/* The type of the file descriptor returned by _PDCLIB_open(). */ -typedef int _PDCLIB_fd_t; - -/* The value (of type _PDCLIB_fd_t) returned by _PDCLIB_open() if the operation - failed. -*/ -#define _PDCLIB_NOHANDLE ( (_PDCLIB_fd_t) -1 ) - -/* The default size for file buffers. Must be at least 256. */ -#define _PDCLIB_BUFSIZ 1024 - -/* The minimum number of files the implementation can open simultaneously. Must - be at least 8. Depends largely on how the bookkeeping is done by fopen() / - freopen() / fclose(). The example implementation limits the number of open - files only by available memory. -*/ -#define _PDCLIB_FOPEN_MAX 8 - -/* Length of the longest filename the implementation guarantees to support. */ -#define _PDCLIB_FILENAME_MAX 128 - -/* Maximum length of filenames generated by tmpnam(). (See tmpfile.c.) */ -#define _PDCLIB_L_tmpnam 46 - -/* Number of distinct file names that can be generated by tmpnam(). */ -#define _PDCLIB_TMP_MAX 50 - -/* The values of SEEK_SET, SEEK_CUR and SEEK_END, used by fseek(). - Since at least one platform (POSIX) uses the same symbols for its own "seek" - function, we use whatever the host defines (if it does define them). -*/ -#define _PDCLIB_SEEK_SET 0 -#define _PDCLIB_SEEK_CUR 1 -#define _PDCLIB_SEEK_END 2 - -/* The number of characters that can be buffered with ungetc(). The standard - guarantees only one (1); anything larger would make applications relying on - this capability dependent on implementation-defined behaviour (not good). -*/ -#define _PDCLIB_UNGETCBUFSIZE 1 - -/* errno -------------------------------------------------------------------- */ - -/* These are the values that _PDCLIB_errno can be set to by the library. - - By keeping PDCLib's errno in the _PDCLIB_* namespace, the library is capable - to "translate" between errno values used by the hosting operating system and - those used and passed out by the library. - - Example: In the example platform, the remove() function uses the unlink() - system call as backend. Linux sets its errno to EISDIR if you try to unlink() - a directory, but POSIX demands EPERM. Within the remove() function, you can - catch the 'errno == EISDIR', and set '_PDCLIB_errno = _PDCLIB_EPERM'. Anyone - using PDCLib's will "see" EPERM instead of EISDIR (the _PDCLIB_* - prefix removed by mechanics). - - If you do not want that kind of translation, you might want to "match" the - values used by PDCLib with those used by the host OS, as to avoid confusion. - - The standard only defines three distinct errno values: ERANGE, EDOM, and - EILSEQ. The standard leaves it up to "the implementation" whether there are - any more beyond those three. There is some controversy as to whether errno is - such a good idea at all, so you might want to come up with a different error - reporting facility for your platform. Since errno values beyond the three - defined by the standard are not portable anyway (unless you look at POSIX), - having your own error reporting facility would not hurt anybody either. -*/ -#define _PDCLIB_ERANGE 1 -#define _PDCLIB_EDOM 2 -#define _PDCLIB_EILSEQ 3 - -/* The following is not strictly "configuration", but there is no better place - to explain it than here. - - PDCLib strives to be as generic as possible, so by default it does NOT define - any values beyond the three standard ones above, even where it would have - been prudent and convenient to do so. Any errno "caught" from the host OS, - and some internal error conditions as well, are all lumped together into the - value of '_PDCLIB_ERROR'. - - '_PDCLIB_ERROR' is STRICLY meant as a PLACEHOLDER only. - - You should NEVER ship an adaption of PDCLib still using that particular - value. You should NEVER write code that *tests* for that value. Indeed it is - not even conforming, since errno values should be defined as beginning with - an uppercase 'E', and there is no mechanics in to unmask that - particular value (for exactly that reason). - - There also is no error message available for this value through either the - strerror() or perror() functions. It is being reported as "unknown" error. - - The idea is that you scan the source of PDCLib for occurrences of this macro - and replace _PDCLIB_ERROR with whatever additional errno value you came up - with for your platform. - - If you cannot find it within you to do that, tell your clients to check for - an errno value larger than zero. That, at least, would be standard compliant - (and fully portable). -*/ -#define _PDCLIB_ERROR 4 - -/* The maximum value that errno can be set to. This is used to set the size */ -/* of the array in struct _PDCLIB_lc_text_t holding error messages for the */ -/* strerror() and perror() functions. (If you change this value because you */ -/* are using additional errno values, you *HAVE* to provide appropriate error */ -/* messages for *ALL* locales.) */ -/* Default is 4 (0, ERANGE, EDOM, EILSEQ). */ -#define _PDCLIB_ERRNO_MAX 4 - -/* locale data -------------------------------------------------------------- */ - -/* The default path where PDCLib should look for its locale data. */ -/* Must end with the appropriate separator character. */ -#define _PDCLIB_LOCALE_PATH "/usr/share/pdclib/i18n" - -/* The name of the environment variable that can be used to override that */ -/* path setting. */ -#define _PDCLIB_LOCALE_PATH_ENV PDCLIB_I18N - -#ifdef __CYGWIN__ -typedef unsigned int wint_t; -#endif - - -#endif diff --git a/src/pdclib/platform/example/include/signal.h b/src/pdclib/platform/example/include/signal.h deleted file mode 100644 index c5f6f28..0000000 --- a/src/pdclib/platform/example/include/signal.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Signal handling - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#ifndef _PDCLIB_SIGNAL_H -#define _PDCLIB_SIGNAL_H _PDCLIB_SIGNAL_H - -#include "pdclib/_PDCLIB_config.h" - -/* Signals ------------------------------------------------------------------ */ - -/* A word on signals, to the people using PDCLib in their OS projects. - - The definitions of the C standard leave about everything that *could* be - useful to be "implementation defined". Without additional, non-standard - arrangements, it is not possible to turn them into a useful tool. - - This example implementation chose to "not generate any of these signals, - except as a result of explicit calls to the raise function", which is - allowed by the standard but of course does nothing for the usefulness of - . - - A useful signal handling would: - 1) make signal() a system call that registers the signal handler with the OS - 2) make raise() a system call triggering an OS signal to the running process - 3) make provisions that further signals of the same type are blocked until - the signal handler returns (optional for SIGILL) -*/ - -/* These are the values used by Linux. */ - -/* Abnormal termination / abort() */ -#define SIGABRT 6 -/* Arithmetic exception / division by zero / overflow */ -#define SIGFPE 8 -/* Illegal instruction */ -#define SIGILL 4 -/* Interactive attention signal */ -#define SIGINT 2 -/* Invalid memory access */ -#define SIGSEGV 11 -/* Termination request */ -#define SIGTERM 15 - -/* The following should be defined to pointer values that could NEVER point to - a valid signal handler function. (They are used as special arguments to - signal().) Again, these are the values used by Linux. -*/ -#define SIG_DFL (void (*)( int ))0 -#define SIG_ERR (void (*)( int ))-1 -#define SIG_IGN (void (*)( int ))1 - -typedef _PDCLIB_sig_atomic sig_atomic_t; - -/* Installs a signal handler "func" for the given signal. - A signal handler is a function that takes an integer as argument (the signal - number) and returns void. - - Note that a signal handler can do very little else than: - 1) assign a value to a static object of type "volatile sig_atomic_t", - 2) call signal() with the value of sig equal to the signal received, - 3) call _Exit(), - 4) call abort(). - Virtually everything else is undefind. - - The signal() function returns the previous installed signal handler, which - at program start may be SIG_DFL or SIG_ILL. (This implementation uses - SIG_DFL for all handlers.) If the request cannot be honored, SIG_ERR is - returned and errno is set to an unspecified positive value. -*/ -void (*signal( int sig, void (*func)( int ) ) )( int ); - -/* Raises the given signal (executing the registered signal handler with the - given signal number as parameter). - This implementation does not prevent further signals of the same time from - occuring, but executes signal( sig, SIG_DFL ) before entering the signal - handler (i.e., a second signal before the signal handler re-registers itself - or SIG_IGN will end the program). - Returns zero if successful, nonzero otherwise. */ -int raise( int sig ); - -#endif diff --git a/src/pdclib/platform/stmos/functions/_PDCLIB/_PDCLIB_allocpages.c b/src/pdclib/platform/stmos/functions/_PDCLIB/_PDCLIB_allocpages.c index 085857f..75f0e2f 100644 --- a/src/pdclib/platform/stmos/functions/_PDCLIB/_PDCLIB_allocpages.c +++ b/src/pdclib/platform/stmos/functions/_PDCLIB/_PDCLIB_allocpages.c @@ -17,43 +17,47 @@ #include "pdclib/_PDCLIB_glue.h" -static void * membreak = NULL; +//static void * membreak = NULL; void * _PDCLIB_allocpages( int const n ) { - void * oldbreak; - if ( membreak == NULL ) - { - /* first call, make sure end-of-heap is page-aligned */ - intptr_t unaligned = 0; - membreak = sbrk( 0 ); - unaligned = _PDCLIB_PAGESIZE - (intptr_t)membreak % _PDCLIB_PAGESIZE; - if ( unaligned < _PDCLIB_PAGESIZE ) - { - /* end-of-heap not page-aligned - adjust */ - if ( sbrk( unaligned ) != membreak ) - { - /* error */ - return NULL; - } - membreak = (char *)membreak + unaligned; - } - } - /* increasing or decreasing heap - standard operation */ - oldbreak = membreak; - membreak = (void *)( (char *)membreak + ( n * _PDCLIB_PAGESIZE ) ); + // TODO eek + // sbrk actually mallocs (kernel side) + return sbrk(n * _PDCLIB_PAGESIZE); - if ( sbrk( (char*)membreak - (char*)oldbreak ) == membreak ) - { - /* successful */ - return oldbreak; - } - else - { - /* out of memory */ - membreak = oldbreak; - return NULL; - } +// void * oldbreak; +// if ( membreak == NULL ) +// { +// /* first call, make sure end-of-heap is page-aligned */ +// intptr_t unaligned = 0; +// membreak = sbrk( 0 ); +// unaligned = _PDCLIB_PAGESIZE - (intptr_t)membreak % _PDCLIB_PAGESIZE; +// if ( unaligned < _PDCLIB_PAGESIZE ) +// { +// /* end-of-heap not page-aligned - adjust */ +// if ( sbrk( unaligned ) != membreak ) +// { +// /* error */ +// return NULL; +// } +// membreak = (char *)membreak + unaligned; +// } +// } +// /* increasing or decreasing heap - standard operation */ +// oldbreak = membreak; +// membreak = (void *)( (char *)membreak + ( n * _PDCLIB_PAGESIZE ) ); +// +// if ( sbrk( (char*)membreak - (char*)oldbreak ) == membreak ) +// { +// /* successful */ +// return oldbreak; +// } +// else +// { +// /* out of memory */ +// membreak = oldbreak; +// return NULL; +// } } #endif diff --git a/src/pdclib/platform/stmos/functions/_PDCLIB/_PDCLIB_stdinit.c b/src/pdclib/platform/stmos/functions/_PDCLIB/_PDCLIB_stdinit.c index 52b0651..86a7f94 100644 --- a/src/pdclib/platform/stmos/functions/_PDCLIB/_PDCLIB_stdinit.c +++ b/src/pdclib/platform/stmos/functions/_PDCLIB/_PDCLIB_stdinit.c @@ -19,24 +19,42 @@ descriptors 0, 1, and 2 respectively. */ /* TODO: This is proof-of-concept, requires finetuning. */ -static char _PDCLIB_sin_buffer[BUFSIZ]; -static char _PDCLIB_sout_buffer[BUFSIZ]; -static char _PDCLIB_serr_buffer[BUFSIZ]; +/*static char _PDCLIB_serr_buf[BUFSIZ]; +static char _PDCLIB_sout_buf[BUFSIZ]; +static char _PDCLIB_sin_buf[BUFSIZ]; +static unsigned char _PDCLIB_serr_unget[_PDCLIB_UNGETCBUFSIZE]; +static unsigned char _PDCLIB_sout_unget[_PDCLIB_UNGETCBUFSIZE]; +static unsigned char _PDCLIB_sin_unget[_PDCLIB_UNGETCBUFSIZE]; -static unsigned char _PDCLIB_sin_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; -static unsigned char _PDCLIB_sout_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; -static unsigned char _PDCLIB_serr_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; - -static struct _PDCLIB_file_t _PDCLIB_serr = { 2, _PDCLIB_serr_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_serr_ungetbuf, _IONBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, NULL }; -static struct _PDCLIB_file_t _PDCLIB_sout = { 1, _PDCLIB_sout_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sout_ungetbuf, _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, &_PDCLIB_serr }; -static struct _PDCLIB_file_t _PDCLIB_sin = { 0, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sin_ungetbuf, _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, NULL, &_PDCLIB_sout }; +static struct _PDCLIB_file_t _PDCLIB_serr = { + 2, + _PDCLIB_serr_buf, BUFSIZ, 0, 0,{ 0, 0 }, + 0, _PDCLIB_serr_unget, + _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, + NULL, NULL +}; +static struct _PDCLIB_file_t _PDCLIB_sout = { + 1, + _PDCLIB_sout_buf, BUFSIZ, 0, 0,{ 0, 0 }, + 0, _PDCLIB_sout_unget, + _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, + NULL, &_PDCLIB_serr +}; +static struct _PDCLIB_file_t _PDCLIB_sin = { + 0, + _PDCLIB_sin_buf, BUFSIZ, 0, 0,{ 0, 0 }, + 0, _PDCLIB_sin_unget, + _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, + NULL, &_PDCLIB_sout +};*/ -struct _PDCLIB_file_t * stdin = &_PDCLIB_sin; -struct _PDCLIB_file_t * stdout = &_PDCLIB_sout; -struct _PDCLIB_file_t * stderr = &_PDCLIB_serr; +struct _PDCLIB_file_t *stdin = 0;//&_PDCLIB_sin; +struct _PDCLIB_file_t *stdout = 0;//&_PDCLIB_sout; +struct _PDCLIB_file_t *stderr = 0;//&_PDCLIB_serr; /* FIXME: This approach is a possible attack vector. */ -struct _PDCLIB_file_t * _PDCLIB_filelist = &_PDCLIB_sin; +// TODO used by remove/tmpfile +struct _PDCLIB_file_t *_PDCLIB_filelist = 0;//&_PDCLIB_sin; /* "C" locale - defaulting to ASCII-7. 1 kByte (+ 4 byte) of data. diff --git a/src/pdclib/platform/stmos/functions/os/syscalls.c b/src/pdclib/platform/stmos/functions/os/syscalls.c index a58dc50..912b988 100644 --- a/src/pdclib/platform/stmos/functions/os/syscalls.c +++ b/src/pdclib/platform/stmos/functions/os/syscalls.c @@ -39,7 +39,7 @@ int getpid(void) void *sbrk(unsigned int bytes) { - void *ret = 0; + uint32_t ret = 0; register uint32_t r1 __asm("r1") = bytes; register uint32_t r2 __asm("r2") = (uint32_t)&ret; __asm("\ @@ -48,7 +48,30 @@ void *sbrk(unsigned int bytes) mov r2, %1; \ svc 0; \ " :: "r" (r1), "r" (r2)); - return ret; + __asm("mov %0, r2" : "=r" (ret)); + return *((void **)ret); +} + +int execve(const char *file, char * const argv[], char * const envp[]) +{ + volatile uint32_t ret = 0; + register uint32_t r1 __asm("r1") = (uint32_t)file; + register uint32_t r2 __asm("r2") = (uint32_t)argv; + register uint32_t r3 __asm("r3") = (uint32_t)envp; + register uint32_t r12 __asm("r12") = (uint32_t)&ret; + __asm("\ + mov r0, 5; \ + mov r1, %0; \ + mov r2, %1; \ + mov r3, %2; \ + mov r12, %3; \ + svc 0; \ + " :: "r" (r1), "r" (r2), "r" (r3), "r" (r12)); + + if (ret == (uint32_t)-1) + return ret; + + ((void (*)(void))ret)(); } // @@ -131,15 +154,15 @@ int read(int fd, uint32_t count, uint8_t *buffer) register uint32_t r1 __asm("r1") = fd; register uint32_t r2 __asm("r2") = count; register uint32_t r3 __asm("r3") = (uint32_t)buffer; - register uint32_t r4 __asm("r4") = (uint32_t)&ret; + register uint32_t r12 __asm("r12") = (uint32_t)&ret; __asm("\ mov r0, 3; \ mov r1, %0; \ mov r2, %1; \ mov r3, %2; \ - mov r4, %3; \ + mov r12, %3; \ svc 3; \ - " :: "r" (r1), "r" (r2), "r" (r3), "r" (r4)); + " :: "r" (r1), "r" (r2), "r" (r3), "r" (r12)); return ret; } @@ -149,15 +172,15 @@ int write(int fd, uint32_t count, const uint8_t *buffer) register uint32_t r1 __asm("r1") = fd; register uint32_t r2 __asm("r2") = count; register uint32_t r3 __asm("r3") = (uint32_t)buffer; - register uint32_t r4 __asm("r4") = (uint32_t)&ret; + register uint32_t r12 __asm("r12") = (uint32_t)&ret; __asm("\ mov r0, 4; \ mov r1, %0; \ mov r2, %1; \ mov r3, %2; \ - mov r4, %3; \ + mov r12, %3; \ svc 3; \ - " :: "r" (r1), "r" (r2), "r" (r3), "r" (r4)); + " :: "r" (r1), "r" (r2), "r" (r3), "r" (r12)); return ret; } diff --git a/src/pdclib/platform/stmos/include/syscalls.h b/src/pdclib/platform/stmos/include/syscalls.h index b301b31..1285a19 100644 --- a/src/pdclib/platform/stmos/include/syscalls.h +++ b/src/pdclib/platform/stmos/include/syscalls.h @@ -16,6 +16,7 @@ void _exit(int code); int fork(void); int getpid(void); void *sbrk(unsigned int bytes); +int execve(const char *file, char * const argv[], char * const envp[]); // // Clock-related calls diff --git a/src/user/Makefile b/src/user/Makefile index d22fbf3..ce23a89 100644 --- a/src/user/Makefile +++ b/src/user/Makefile @@ -1,9 +1,29 @@ +## +# @file Makefile +# Script to build folder of source files +# +# Copyright (C) 2018 Clyne Sullivan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + CFILES = $(wildcard *.c) AFILES = $(wildcard *.s) OFILES = $(patsubst %.c, %.o, $(CFILES)) \ $(patsubst %.s, %.asm.o, $(AFILES)) -CFLAGS += -I.. -I../arch/cmsis +CFLAGS += -ffreestanding -nostdlib -I.. -I../arch/cmsis all: $(OFILES) diff --git a/src/user/priv_gpio.h b/src/user/priv_gpio.h deleted file mode 100644 index 6b349fe..0000000 --- a/src/user/priv_gpio.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file priv_gpio.h - * GPIO access for unpriviledged processes - * - * Copyright (C) 2018 Clyne Sullivan - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef PRIV_GPIO_H_ -#define PRIV_GPIO_H_ - -// For value flags -#include - -/** - * Possible GPIO calls. - */ -enum GPIO_CALLS { - GPIO_MODE = 0, /**< Change GPIO mode */ - GPIO_TYPE, /**< Change GPIO type (PuPd/ODrain) */ - GPIO_PUPD, /**< Set/clear pullup/pulldown */ - GPIO_SPEED, /**< Set GPIO speed */ - GPIO_OUT, /**< Set GPIO output state */ -}; - -/** - * Provides unpriviledged GPIO access. - * @param call The type of GPIO call to make - * @param pin The pin to modify (0-15 = A, 16-31 = B, ...) - * @param value The value to pass to the call - */ -void gpio(uint32_t call, uint32_t pin, uint32_t value) -{ - register uint32_t r0 asm("r0") = call; - register uint32_t r1 asm("r1") = pin; - register uint32_t r2 asm("r2") = value; - - asm("\ - mov r0, %0; \ - mov r1, %1; \ - mov r2, %2; \ - svc 1; \ - " :: "r" (r0), "r" (r1), "r" (r2)); -} - -#endif // PRIV_GPIO_H_ diff --git a/src/user/user.c b/src/user/user.c index b5ef789..f695936 100644 --- a/src/user/user.c +++ b/src/user/user.c @@ -1,41 +1,29 @@ -#include "priv_gpio.h" +/** + * @file user.c + * Userspace entry + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ -#include -#include -#include - -void user_delay(uint32_t ms) -{ - register uint32_t r1 asm("r1") = ms; - - asm("\ - mov r0, 0; \ - mov r1, %0; \ - svc 2; \ - " :: "r" (r1)); -} +#include +#include void user_main(void) { - gpio(GPIO_MODE, 5, OUTPUT); - - int test = vfs_open("B:/hello", VFS_FILE_READ); - char *buf = malloc(20); - int count = vfs_read(test, 20, (uint8_t *)buf); - buf[count] = '\0'; - vfs_close(test); - -// if (fork() == 0) { -// while (1) { -// gpio(GPIO_OUT, 5, 1); -// user_delay(2000); -// } -// } else { -// while (1) { -// user_delay(1000); -// gpio(GPIO_OUT, 5, 0); -// user_delay(1000); -// } -// } + //gpio(GPIO_MODE, 5, OUTPUT); + execve("B:/init", 0, 0); }