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 0000000..3bc5fd8 Binary files /dev/null and b/initrd/init differ 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 7bf8246..0000000 Binary files a/initrd/test and /dev/null differ diff --git a/initrd/test.c b/initrd/test.c deleted file mode 100644 index b79f315..0000000 --- a/initrd/test.c +++ /dev/null @@ -1,16 +0,0 @@ -#include -#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 0000000..cd72d1e Binary files /dev/null and b/src/pdclib/platform/example.tar.gz differ 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); }