mirror of
https://github.com/kenshineto/kern.git
synced 2025-04-15 15:07:25 +00:00
new libs
This commit is contained in:
parent
4d0603e8e5
commit
ec3c37d1d4
41 changed files with 911 additions and 1321 deletions
lib
atox.cblkmov.cbound.cbtoa.cctoi.ccvtdec.ccvtdec0.ccvthex.ccvtoct.ccvtuns.ccvtuns0.cdelay.centry.Sisdigit.cisspace.citoc.cklibc.cmemclr.cmemcmp.cmemcpy.cmemmove.cmemset.cpad.cpadstr.cprintf.csprint.cstpcpy.cstpncpy.cstr2int.cstrcat.cstrcmp.cstrcpy.cstrlen.cstrncmp.cstrncpy.cstrtoux.cstrtox.culibc.culibs.Suxtoa.cxtoa.c
30
lib/atox.c
Normal file
30
lib/atox.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define ATOX(name, type) \
|
||||
type name(const char *s) \
|
||||
{ \
|
||||
for (; isspace(*s); s++) \
|
||||
; \
|
||||
int neg = 0; \
|
||||
switch (*s) { \
|
||||
case '-': \
|
||||
neg = 1; \
|
||||
/* fallthrough */ \
|
||||
case '+': \
|
||||
s++; \
|
||||
break; \
|
||||
} \
|
||||
type num = 0; \
|
||||
for (; *s == '0'; s++) \
|
||||
; \
|
||||
for (; isdigit(*s); s++) { \
|
||||
num *= 10; \
|
||||
num += *s - '0'; \
|
||||
} \
|
||||
return num * (neg ? -1 : 1); \
|
||||
}
|
||||
|
||||
ATOX(atoi, int)
|
||||
ATOX(atol, long int)
|
||||
ATOX(atoll, long long int)
|
57
lib/blkmov.c
57
lib/blkmov.c
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
** @file blkmov.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef BLKMOV_SRC_INC
|
||||
#define BLKMOV_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** blkmov(dst,src,len)
|
||||
**
|
||||
** Copy a word-aligned block from src to dst. Deals with overlapping
|
||||
** buffers.
|
||||
**
|
||||
** @param dst Destination buffer
|
||||
** @param src Source buffer
|
||||
** @param len Buffer size (in bytes)
|
||||
*/
|
||||
void blkmov(void *dst, const void *src, register uint32_t len)
|
||||
{
|
||||
// verify that the addresses are aligned and
|
||||
// the length is a multiple of four bytes
|
||||
if ((((uint32_t)dst) & 0x3) != 0 || (((uint32_t)src) & 0x3) != 0 ||
|
||||
(len & 0x3) != 0) {
|
||||
// something isn't aligned, so just use memmove()
|
||||
memmove(dst, src, len);
|
||||
return;
|
||||
}
|
||||
|
||||
// everything is nicely aligned, so off we go
|
||||
register uint32_t *dest = dst;
|
||||
register const uint32_t *source = src;
|
||||
|
||||
// now copying 32-bit values
|
||||
len /= 4;
|
||||
|
||||
if (source < dest && (source + len) > dest) {
|
||||
source += len;
|
||||
dest += len;
|
||||
while (len-- > 0) {
|
||||
*--dest = *--source;
|
||||
}
|
||||
} else {
|
||||
while (len--) {
|
||||
*dest++ = *source++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
30
lib/bound.c
30
lib/bound.c
|
@ -1,30 +1,6 @@
|
|||
/**
|
||||
** @file bound.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef BOUND_SRC_INC
|
||||
#define BOUND_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** bound(min,value,max)
|
||||
**
|
||||
** This function confines an argument within specified bounds.
|
||||
**
|
||||
** @param min Lower bound
|
||||
** @param value Value to be constrained
|
||||
** @param max Upper bound
|
||||
**
|
||||
** @return The constrained value
|
||||
*/
|
||||
uint32_t bound(uint32_t min, uint32_t value, uint32_t max)
|
||||
unsigned int bound(unsigned int min, unsigned int value, unsigned int max)
|
||||
{
|
||||
if (value < min) {
|
||||
value = min;
|
||||
|
@ -34,5 +10,3 @@ uint32_t bound(uint32_t min, uint32_t value, uint32_t max)
|
|||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
43
lib/btoa.c
Normal file
43
lib/btoa.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
static char suffixes[] = { 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q' };
|
||||
|
||||
char *btoa(size_t bytes, char *buf)
|
||||
{
|
||||
// no suffix if under 1K, print up to four digits
|
||||
if (bytes < 1024) {
|
||||
ultoa(bytes, buf, 10);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// store one digit of remainder for decimal
|
||||
unsigned int remainder;
|
||||
// power of 1024
|
||||
int power = 0;
|
||||
|
||||
// iterate until remaining bytes fits in three digits
|
||||
while (bytes >= 1000) {
|
||||
remainder = (bytes % 1024) * 10 / 1024;
|
||||
bytes /= 1024;
|
||||
power += 1;
|
||||
}
|
||||
|
||||
// end of number
|
||||
char *end;
|
||||
|
||||
if (bytes >= 10) {
|
||||
// no decimal
|
||||
end = ultoa(bytes, buf, 10);
|
||||
} else {
|
||||
// decimal
|
||||
end = ultoa(bytes, buf, 10);
|
||||
end[0] = '.';
|
||||
end = ultoa(remainder, end + 1, 10);
|
||||
}
|
||||
|
||||
// add suffix
|
||||
end[0] = suffixes[power - 1];
|
||||
end[1] = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
14
lib/ctoi.c
Normal file
14
lib/ctoi.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
int ctoi(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
} else if (c >= 'A' && c <= 'Z') {
|
||||
return c - 'A' + 10;
|
||||
} else if (c >= 'a' && c <= 'z') {
|
||||
return c - 'a' + 10;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
44
lib/cvtdec.c
44
lib/cvtdec.c
|
@ -1,44 +0,0 @@
|
|||
/**
|
||||
** @file cvtdec.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef CVTDEC_SRC_INC
|
||||
#define CVTDEC_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** cvtdec(buf,value)
|
||||
**
|
||||
** convert a 32-bit signed value into a NUL-terminated character string
|
||||
**
|
||||
** @param buf Destination buffer
|
||||
** @param value Value to convert
|
||||
**
|
||||
** @return The number of characters placed into the buffer
|
||||
** (not including the NUL)
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
int cvtdec(char *buf, int32_t value)
|
||||
{
|
||||
char *bp = buf;
|
||||
|
||||
if (value < 0) {
|
||||
*bp++ = '-';
|
||||
value = -value;
|
||||
}
|
||||
|
||||
bp = cvtdec0(bp, value);
|
||||
*bp = '\0';
|
||||
|
||||
return (bp - buf);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,45 +0,0 @@
|
|||
/**
|
||||
** @file cvtdec0.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef CVTDEC0_SRC_INC
|
||||
#define CVTDEC0_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** cvtdec0(buf,value) - local support routine for cvtdec()
|
||||
**
|
||||
** convert a 32-bit unsigned integer into a NUL-terminated character string
|
||||
**
|
||||
** @param buf Destination buffer
|
||||
** @param value Value to convert
|
||||
**
|
||||
** @return The number of characters placed into the buffer
|
||||
** (not including the NUL)
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
char *cvtdec0(char *buf, int value)
|
||||
{
|
||||
int quotient;
|
||||
|
||||
quotient = value / 10;
|
||||
if (quotient < 0) {
|
||||
quotient = 214748364;
|
||||
value = 8;
|
||||
}
|
||||
if (quotient != 0) {
|
||||
buf = cvtdec0(buf, quotient);
|
||||
}
|
||||
*buf++ = value % 10 + '0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif
|
50
lib/cvthex.c
50
lib/cvthex.c
|
@ -1,50 +0,0 @@
|
|||
/**
|
||||
** @file cvthex.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef CVTHEX_SRC_INC
|
||||
#define CVTHEX_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** cvthex(buf,value)
|
||||
**
|
||||
** convert a 32-bit unsigned value into a minimal-length (up to
|
||||
** 8-character) NUL-terminated character string
|
||||
**
|
||||
** @param buf Destination buffer
|
||||
** @param value Value to convert
|
||||
**
|
||||
** @return The number of characters placed into the buffer
|
||||
** (not including the NUL)
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
int cvthex(char *buf, uint32_t value)
|
||||
{
|
||||
const char hexdigits[] = "0123456789ABCDEF";
|
||||
int chars_stored = 0;
|
||||
|
||||
for (int i = 0; i < 8; i += 1) {
|
||||
uint32_t val = value & 0xf0000000;
|
||||
if (chars_stored || val != 0 || i == 7) {
|
||||
++chars_stored;
|
||||
val = (val >> 28) & 0xf;
|
||||
*buf++ = hexdigits[val];
|
||||
}
|
||||
value <<= 4;
|
||||
}
|
||||
|
||||
*buf = '\0';
|
||||
|
||||
return (chars_stored);
|
||||
}
|
||||
|
||||
#endif
|
54
lib/cvtoct.c
54
lib/cvtoct.c
|
@ -1,54 +0,0 @@
|
|||
/**
|
||||
** @file cvtoct.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef CVTOCT_SRC_INC
|
||||
#define CVTOCT_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** cvtoct(buf,value)
|
||||
**
|
||||
** convert a 32-bit unsigned value into a mininal-length (up to
|
||||
** 11-character) NUL-terminated character string
|
||||
**
|
||||
** @param buf Destination buffer
|
||||
** @param value Value to convert
|
||||
**
|
||||
** @return The number of characters placed into the buffer
|
||||
** (not including the NUL)
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
int cvtoct(char *buf, uint32_t value)
|
||||
{
|
||||
int i;
|
||||
int chars_stored = 0;
|
||||
char *bp = buf;
|
||||
uint32_t val;
|
||||
|
||||
val = (value & 0xc0000000);
|
||||
val >>= 30;
|
||||
for (i = 0; i < 11; i += 1) {
|
||||
if (i == 10 || val != 0 || chars_stored) {
|
||||
chars_stored = 1;
|
||||
val &= 0x7;
|
||||
*bp++ = val + '0';
|
||||
}
|
||||
value <<= 3;
|
||||
val = (value & 0xe0000000);
|
||||
val >>= 29;
|
||||
}
|
||||
*bp = '\0';
|
||||
|
||||
return bp - buf;
|
||||
}
|
||||
|
||||
#endif
|
38
lib/cvtuns.c
38
lib/cvtuns.c
|
@ -1,38 +0,0 @@
|
|||
/**
|
||||
** @file cvtuns.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef CVTUNS_SRC_INC
|
||||
#define CVTUNS_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** cvtuns(buf,value)
|
||||
**
|
||||
** Convert a 32-bit unsigned value into a NUL-terminated character string
|
||||
**
|
||||
** @param buf Result buffer
|
||||
** @param value Value to be converted
|
||||
**
|
||||
** @return Length of the resulting buffer
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
int cvtuns(char *buf, uint32_t value)
|
||||
{
|
||||
char *bp = buf;
|
||||
|
||||
bp = cvtuns0(bp, value);
|
||||
*bp = '\0';
|
||||
|
||||
return bp - buf;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,40 +0,0 @@
|
|||
/**
|
||||
** @file cvtuns0.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef CVTUNS0_SRC_INC
|
||||
#define CVTUNS0_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** cvtuns0(buf,value) - local support routine for cvtuns()
|
||||
**
|
||||
** Convert a 32-bit unsigned value into a NUL-terminated character string
|
||||
**
|
||||
** @param buf Result buffer
|
||||
** @param value Value to be converted
|
||||
**
|
||||
** @return Pointer to the first unused byte in the buffer
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
char *cvtuns0(char *buf, uint32_t value)
|
||||
{
|
||||
uint32_t quotient;
|
||||
|
||||
quotient = value / 10;
|
||||
if (quotient != 0) {
|
||||
buf = cvtdec0(buf, quotient);
|
||||
}
|
||||
*buf++ = value % 10 + '0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif
|
8
lib/delay.c
Normal file
8
lib/delay.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
void delay(int count)
|
||||
{
|
||||
while (count-- > 0)
|
||||
for (int i = 0; i < 100000; i++)
|
||||
;
|
||||
}
|
25
lib/entry.S
25
lib/entry.S
|
@ -1,25 +0,0 @@
|
|||
//
|
||||
// user-level startup routine
|
||||
//
|
||||
.text
|
||||
.globl _start
|
||||
.globl main
|
||||
.globl exit
|
||||
|
||||
// entry point - this is where the kernel starts us running
|
||||
_start:
|
||||
// we immediately call main()
|
||||
call main
|
||||
|
||||
// if we come back from that, it means the user
|
||||
// program didn't call exit(), in which case the
|
||||
// value returned from main() is the exit status
|
||||
|
||||
// push that value onto the stack and call exit()
|
||||
subl $12, %esp
|
||||
pushl %eax
|
||||
call exit
|
||||
|
||||
// if we come back from that, something bad has
|
||||
// happened, so we just lock up
|
||||
1: jmp 1b
|
6
lib/isdigit.c
Normal file
6
lib/isdigit.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include <ctype.h>
|
||||
|
||||
int isdigit(int c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
16
lib/isspace.c
Normal file
16
lib/isspace.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <ctype.h>
|
||||
|
||||
int isspace(int c)
|
||||
{
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\v':
|
||||
case '\f':
|
||||
case '\r':
|
||||
case '\n':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
10
lib/itoc.c
Normal file
10
lib/itoc.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
char itoc(int i)
|
||||
{
|
||||
if (i < 10) {
|
||||
return '0' + i;
|
||||
} else {
|
||||
return 'a' + (i - 10);
|
||||
}
|
||||
}
|
111
lib/klibc.c
111
lib/klibc.c
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
** @file klibc.c
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** Additional support functions for the kernel.
|
||||
**
|
||||
*/
|
||||
|
||||
#define KERNEL_SRC
|
||||
|
||||
#include <klib.h>
|
||||
#include <cio.h>
|
||||
#include <procs.h>
|
||||
#include <support.h>
|
||||
|
||||
/**
|
||||
** Name: put_char_or_code( ch )
|
||||
**
|
||||
** Description: Prints a character on the console, unless it
|
||||
** is a non-printing character, in which case its hex code
|
||||
** is printed
|
||||
**
|
||||
** @param ch The character to be printed
|
||||
*/
|
||||
void put_char_or_code(int ch)
|
||||
{
|
||||
if (ch >= ' ' && ch < 0x7f) {
|
||||
cio_putchar(ch);
|
||||
} else {
|
||||
cio_printf("\\x%02x", ch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Name: backtrace
|
||||
**
|
||||
** Perform a stack backtrace
|
||||
**
|
||||
** @param ebp Initial EBP to use
|
||||
** @param args Number of function argument values to print
|
||||
*/
|
||||
void backtrace(uint32_t *ebp, uint_t args)
|
||||
{
|
||||
cio_puts("Trace: ");
|
||||
if (ebp == NULL) {
|
||||
cio_puts("NULL ebp, no trace possible\n");
|
||||
return;
|
||||
} else {
|
||||
cio_putchar('\n');
|
||||
}
|
||||
|
||||
while (ebp != NULL) {
|
||||
// get return address and report it and EBP
|
||||
uint32_t ret = ebp[1];
|
||||
cio_printf(" ebp %08x ret %08x args", (uint32_t)ebp, ret);
|
||||
|
||||
// print the requested number of function arguments
|
||||
for (uint_t i = 0; i < args; ++i) {
|
||||
cio_printf(" [%u] %08x", i + 1, ebp[2 + i]);
|
||||
}
|
||||
cio_putchar('\n');
|
||||
|
||||
// follow the chain
|
||||
ebp = (uint32_t *)*ebp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** kpanic - kernel-level panic routine
|
||||
**
|
||||
** usage: kpanic( msg )
|
||||
**
|
||||
** Prefix routine for panic() - can be expanded to do other things
|
||||
** (e.g., printing a stack traceback)
|
||||
**
|
||||
** @param msg[in] String containing a relevant message to be printed,
|
||||
** or NULL
|
||||
*/
|
||||
void kpanic(const char *msg)
|
||||
{
|
||||
cio_puts("\n\n***** KERNEL PANIC *****\n\n");
|
||||
|
||||
if (msg) {
|
||||
cio_printf("%s\n", msg);
|
||||
}
|
||||
|
||||
delay(DELAY_5_SEC); // approximately
|
||||
|
||||
// dump a bunch of potentially useful information
|
||||
|
||||
// dump the contents of the current PCB
|
||||
pcb_dump("Current", current, true);
|
||||
|
||||
// dump the basic info about what's in the process table
|
||||
ptable_dump_counts();
|
||||
|
||||
// dump information about the queues
|
||||
pcb_queue_dump("R", ready, true);
|
||||
pcb_queue_dump("W", waiting, true);
|
||||
pcb_queue_dump("S", sleeping, true);
|
||||
pcb_queue_dump("Z", zombie, true);
|
||||
pcb_queue_dump("I", sioread, true);
|
||||
|
||||
// perform a stack backtrace
|
||||
backtrace((uint32_t *)r_ebp(), 3);
|
||||
|
||||
// could dump other stuff here, too
|
||||
|
||||
panic("KERNEL PANIC");
|
||||
}
|
38
lib/memclr.c
38
lib/memclr.c
|
@ -1,38 +0,0 @@
|
|||
/**
|
||||
** @file memclr.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef MEMCLR_SRC_INC
|
||||
#define MEMCLR_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** memclr(buf,len)
|
||||
**
|
||||
** Initialize all bytes of a block of memory to zero
|
||||
**
|
||||
** @param buf The buffer to initialize
|
||||
** @param len Buffer size (in bytes)
|
||||
*/
|
||||
void memclr(void *buf, register uint32_t len)
|
||||
{
|
||||
register uint8_t *dest = buf;
|
||||
|
||||
/*
|
||||
** We could speed this up by unrolling it and clearing
|
||||
** words at a time (instead of bytes).
|
||||
*/
|
||||
|
||||
while (len--) {
|
||||
*dest++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
9
lib/memcmp.c
Normal file
9
lib/memcmp.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include <string.h>
|
||||
|
||||
int memcmp(const void *restrict vl, const void *restrict vr, size_t n)
|
||||
{
|
||||
const unsigned char *l = vl, *r = vr;
|
||||
for (; n && *l == *r; n--, l++, r++)
|
||||
;
|
||||
return n ? *l - *r : 0;
|
||||
}
|
46
lib/memcpy.c
46
lib/memcpy.c
|
@ -1,42 +1,10 @@
|
|||
/**
|
||||
** @file memcpy.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#ifndef MEMCPY_SRC_INC
|
||||
#define MEMCPY_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** memcpy(dst,src,len)
|
||||
**
|
||||
** Copy a block from one place to another
|
||||
**
|
||||
** May not correctly deal with overlapping buffers
|
||||
**
|
||||
** @param dst Destination buffer
|
||||
** @param src Source buffer
|
||||
** @param len Buffer size (in bytes)
|
||||
*/
|
||||
void memcpy(void *dst, register const void *src, register uint32_t len)
|
||||
void *memcpy(void *restrict dest, const void *restrict src, size_t n)
|
||||
{
|
||||
register uint8_t *dest = dst;
|
||||
register const uint8_t *source = src;
|
||||
|
||||
/*
|
||||
** We could speed this up by unrolling it and copying
|
||||
** words at a time (instead of bytes).
|
||||
*/
|
||||
|
||||
while (len--) {
|
||||
*dest++ = *source++;
|
||||
}
|
||||
char *d = dest;
|
||||
const char *s = src;
|
||||
for (; n; n--)
|
||||
*d++ = *s++;
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,49 +1,20 @@
|
|||
/**
|
||||
** @file memmove.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#ifndef MEMMOVE_SRC_INC
|
||||
#define MEMMOVE_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** memmove(dst,src,len)
|
||||
**
|
||||
** Copy a block from one place to another. Deals with overlapping
|
||||
** buffers.
|
||||
**
|
||||
** @param dst Destination buffer
|
||||
** @param src Source buffer
|
||||
** @param len Buffer size (in bytes)
|
||||
*/
|
||||
void memmove(void *dst, const void *src, register uint32_t len)
|
||||
void *memmove(void *dest, const void *src, size_t n)
|
||||
{
|
||||
register uint8_t *dest = dst;
|
||||
register const uint8_t *source = src;
|
||||
char *d = dest;
|
||||
const char *s = src;
|
||||
|
||||
/*
|
||||
** We could speed this up by unrolling it and copying
|
||||
** words at a time (instead of bytes).
|
||||
*/
|
||||
if (d == s)
|
||||
return d;
|
||||
|
||||
if (source < dest && (source + len) > dest) {
|
||||
source += len;
|
||||
dest += len;
|
||||
while (len-- > 0) {
|
||||
*--dest = *--source;
|
||||
}
|
||||
if (d < s) {
|
||||
for (; n; n--)
|
||||
*d++ = *s++;
|
||||
} else {
|
||||
while (len--) {
|
||||
*dest++ = *source++;
|
||||
}
|
||||
while (n)
|
||||
n--, d[n] = s[n];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return dest;
|
||||
}
|
||||
|
|
43
lib/memset.c
43
lib/memset.c
|
@ -1,39 +1,10 @@
|
|||
/**
|
||||
** @file memset.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#ifndef MEMSET_SRC_INC
|
||||
#define MEMSET_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** memset(buf,len,value)
|
||||
**
|
||||
** initialize all bytes of a block of memory to a specific value
|
||||
**
|
||||
** @param buf The buffer to initialize
|
||||
** @param len Buffer size (in bytes)
|
||||
** @param value Initialization value
|
||||
*/
|
||||
void memset(void *buf, register uint32_t len, register uint32_t value)
|
||||
void *memset(void *dest, int c, size_t n)
|
||||
{
|
||||
register uint8_t *bp = buf;
|
||||
|
||||
/*
|
||||
** We could speed this up by unrolling it and copying
|
||||
** words at a time (instead of bytes).
|
||||
*/
|
||||
|
||||
while (len--) {
|
||||
*bp++ = value;
|
||||
}
|
||||
unsigned char *d = dest;
|
||||
for (; n; n--) {
|
||||
*d++ = c;
|
||||
};
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
36
lib/pad.c
36
lib/pad.c
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
** @file pad.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef PAD_SRC_INC
|
||||
#define PAD_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** pad(dst,extra,padchar) - generate a padding string
|
||||
**
|
||||
** @param dst Pointer to where the padding should begin
|
||||
** @param extra How many padding bytes to add
|
||||
** @param padchar What character to pad with
|
||||
**
|
||||
** @return Pointer to the first byte after the padding
|
||||
**
|
||||
** NOTE: does NOT NUL-terminate the buffer
|
||||
*/
|
||||
char *pad(char *dst, int extra, int padchar)
|
||||
{
|
||||
while (extra > 0) {
|
||||
*dst++ = (char)padchar;
|
||||
extra -= 1;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
#endif
|
62
lib/padstr.c
62
lib/padstr.c
|
@ -1,62 +0,0 @@
|
|||
/**
|
||||
** @file padstr.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef PADSTR_SRC_INC
|
||||
#define PADSTR_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** padstr(dst,str,len,width,leftadjust,padchar - add padding characters
|
||||
** to a string
|
||||
**
|
||||
** @param dst The destination buffer
|
||||
** @param str The string to be padded
|
||||
** @param len The string length, or -1
|
||||
** @param width The desired final length of the string
|
||||
** @param leftadjust Should the string be left-justified?
|
||||
** @param padchar What character to pad with
|
||||
**
|
||||
** @return Pointer to the first byte after the padded string
|
||||
**
|
||||
** NOTE: does NOT NUL-terminate the buffer
|
||||
*/
|
||||
char *padstr(char *dst, char *str, int len, int width, int leftadjust,
|
||||
int padchar)
|
||||
{
|
||||
int extra;
|
||||
|
||||
// determine the length of the string if we need to
|
||||
if (len < 0) {
|
||||
len = strlen(str);
|
||||
}
|
||||
|
||||
// how much filler must we add?
|
||||
extra = width - len;
|
||||
|
||||
// add filler on the left if we're not left-justifying
|
||||
if (extra > 0 && !leftadjust) {
|
||||
dst = pad(dst, extra, padchar);
|
||||
}
|
||||
|
||||
// copy the string itself
|
||||
for (int i = 0; i < len; ++i) {
|
||||
*dst++ = str[i];
|
||||
}
|
||||
|
||||
// add filler on the right if we are left-justifying
|
||||
if (extra > 0 && leftadjust) {
|
||||
dst = pad(dst, extra, padchar);
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
#endif
|
537
lib/printf.c
Normal file
537
lib/printf.c
Normal file
|
@ -0,0 +1,537 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PRINTF_NUMERIC_BUF_LEN 50
|
||||
|
||||
/// options that can be set inside a specifier
|
||||
/// flags, width, precision, length, and data type
|
||||
typedef struct {
|
||||
/* flags */
|
||||
/// left justify content
|
||||
uint8_t left : 1;
|
||||
/// force sign (+/-) on numeric output
|
||||
uint8_t sign : 1;
|
||||
/// leave space if no printed sign on numeric output
|
||||
uint8_t space : 1;
|
||||
/// preceed hex/octal output with '0x'
|
||||
uint8_t hash : 1;
|
||||
/// left pads numeric output with zeros
|
||||
uint8_t zero : 1;
|
||||
uint8_t : 3;
|
||||
|
||||
/* width & precision */
|
||||
/// minimum number of characters to be printed (padding if origonal is less)
|
||||
int width;
|
||||
/// digit precision used when printing numerical answers
|
||||
int precision;
|
||||
/// if a fixed minimum width has been provided
|
||||
uint8_t width_set : 1;
|
||||
/// if the provided minimum width is in the next variable argument
|
||||
uint8_t width_varies : 1;
|
||||
/// if a fixed digit precision has been provided
|
||||
uint8_t precision_set : 1;
|
||||
/// if the provided digit precision is in the next variable argument
|
||||
uint8_t precision_varies : 1;
|
||||
uint8_t : 4;
|
||||
|
||||
/* length */
|
||||
/// what size to read argument as
|
||||
enum printf_len {
|
||||
PRINTF_LEN_CHAR,
|
||||
PRINTF_LEN_SHORT_INT,
|
||||
PRINTF_LEN_INT,
|
||||
PRINTF_LEN_LONG_INT,
|
||||
PRINTF_LEN_LONG_LONG_INT,
|
||||
PRINTF_LEN_SIZE_T,
|
||||
} len;
|
||||
|
||||
/* other */
|
||||
/// radix to print the numerical answers as
|
||||
uint8_t radix;
|
||||
/// case to print hexadecimal values as
|
||||
bool is_uppercase;
|
||||
} options_t;
|
||||
|
||||
typedef struct {
|
||||
/* input */
|
||||
/// the origonal format string
|
||||
const char *format;
|
||||
/// variable args passed in
|
||||
va_list *args;
|
||||
/// maximum allowed output length
|
||||
size_t max_len;
|
||||
/// if a maximum output length is set
|
||||
bool has_max_len;
|
||||
|
||||
/* output */
|
||||
size_t written_len;
|
||||
bool to_file;
|
||||
union {
|
||||
FILE *file;
|
||||
char *buf;
|
||||
} out;
|
||||
|
||||
/* pass 2 */
|
||||
char *output;
|
||||
} context_t;
|
||||
|
||||
static void printf_putc(context_t *ctx, char c)
|
||||
{
|
||||
// bounds check
|
||||
if (ctx->has_max_len)
|
||||
if (ctx->written_len >= ctx->max_len)
|
||||
return;
|
||||
|
||||
// write to correct
|
||||
if (ctx->to_file)
|
||||
fputc(ctx->out.file, c);
|
||||
else
|
||||
*(ctx->out.buf++) = c;
|
||||
|
||||
ctx->written_len++;
|
||||
}
|
||||
|
||||
static int parse_flag(const char **res, options_t *opts)
|
||||
{
|
||||
const char *fmt = *res;
|
||||
switch (*(fmt++)) {
|
||||
case '-':
|
||||
opts->left = 1;
|
||||
break;
|
||||
case '+':
|
||||
opts->sign = 1;
|
||||
break;
|
||||
case ' ':
|
||||
opts->space = 1;
|
||||
break;
|
||||
case '#':
|
||||
opts->zero = 1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
*res = fmt;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void parse_width(const char **res, options_t *opts)
|
||||
{
|
||||
const char *fmt = *res;
|
||||
char *end = NULL;
|
||||
|
||||
// check varies
|
||||
if (*fmt == '*') {
|
||||
opts->width_varies = true;
|
||||
*res = fmt++;
|
||||
return;
|
||||
}
|
||||
|
||||
// parse num
|
||||
long width = strtol(fmt, &end, 10);
|
||||
if (end != NULL) {
|
||||
opts->width_set = 1;
|
||||
opts->width = width;
|
||||
*res = end;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_precision(const char **res, options_t *opts)
|
||||
{
|
||||
const char *fmt = *res;
|
||||
char *end = NULL;
|
||||
|
||||
// check for dot
|
||||
if (*(fmt++) != '.')
|
||||
return;
|
||||
|
||||
// check varies
|
||||
if (*fmt == '*') {
|
||||
opts->precision_varies = true;
|
||||
*res = fmt++;
|
||||
return;
|
||||
}
|
||||
|
||||
// parse num
|
||||
long precision = strtol(fmt, &end, 10);
|
||||
if (end != NULL) {
|
||||
opts->precision_set = 1;
|
||||
opts->precision = precision;
|
||||
*res = end;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_length(const char **res, options_t *opts)
|
||||
{
|
||||
const char *fmt = *res;
|
||||
|
||||
switch (*(fmt++)) {
|
||||
// half
|
||||
case 'h':
|
||||
if (*fmt == 'h') {
|
||||
opts->len = PRINTF_LEN_CHAR;
|
||||
fmt++;
|
||||
} else {
|
||||
opts->len = PRINTF_LEN_SHORT_INT;
|
||||
}
|
||||
break;
|
||||
// long
|
||||
case 'l':
|
||||
if (*fmt == 'l') {
|
||||
opts->len = PRINTF_LEN_LONG_LONG_INT;
|
||||
fmt++;
|
||||
} else {
|
||||
opts->len = PRINTF_LEN_LONG_INT;
|
||||
}
|
||||
break;
|
||||
// size_t
|
||||
case 'z':
|
||||
opts->len = PRINTF_LEN_SIZE_T;
|
||||
break;
|
||||
default:
|
||||
opts->len = PRINTF_LEN_INT;
|
||||
return;
|
||||
}
|
||||
|
||||
*res = fmt;
|
||||
}
|
||||
|
||||
static void get_radix(char spec, options_t *opts)
|
||||
{
|
||||
switch (spec) {
|
||||
case 'x':
|
||||
case 'X':
|
||||
opts->radix = 16;
|
||||
break;
|
||||
case 'o':
|
||||
opts->radix = 8;
|
||||
break;
|
||||
default:
|
||||
opts->radix = 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void get_case(char spec, options_t *opts)
|
||||
{
|
||||
if (spec == 'X')
|
||||
opts->is_uppercase = 1;
|
||||
}
|
||||
|
||||
static char printf_itoc(int uppercase, int i)
|
||||
{
|
||||
// decimal
|
||||
if (i < 10) {
|
||||
return i + '0';
|
||||
}
|
||||
// hex
|
||||
if (uppercase) {
|
||||
return (i - 10) + 'A';
|
||||
} else {
|
||||
return (i - 10) + 'a';
|
||||
}
|
||||
}
|
||||
|
||||
static int printf_lltoa(char *buf, options_t *opts, bool is_neg,
|
||||
unsigned long long int num)
|
||||
{
|
||||
int precision = 0;
|
||||
char *start = buf;
|
||||
|
||||
// sign
|
||||
if (is_neg) {
|
||||
*(buf++) = '-';
|
||||
} else if (opts->sign) {
|
||||
*(buf++) = '+';
|
||||
} else if (opts->space) {
|
||||
*(buf++) = ' ';
|
||||
}
|
||||
|
||||
// radix specifier
|
||||
if (opts->hash) {
|
||||
if (opts->radix == 8) {
|
||||
*(buf++) = '0';
|
||||
*(buf++) = 'x';
|
||||
}
|
||||
if (opts->radix == 16) {
|
||||
*(buf++) = '0';
|
||||
*(buf++) = 'o';
|
||||
}
|
||||
}
|
||||
|
||||
// write number
|
||||
if (num == 0) {
|
||||
*(buf++) = '0';
|
||||
}
|
||||
while (num) {
|
||||
if (opts->precision_set && precision++ >= opts->precision)
|
||||
break;
|
||||
*(buf++) = printf_itoc(opts->is_uppercase, num & opts->radix);
|
||||
num /= opts->radix;
|
||||
}
|
||||
*(buf++) = '\0';
|
||||
|
||||
return buf - start;
|
||||
}
|
||||
|
||||
static void handle_int_specifier(context_t *ctx, options_t *const opts,
|
||||
bool has_sign_bit)
|
||||
{
|
||||
union {
|
||||
unsigned long long int u;
|
||||
signed long long int i;
|
||||
} num;
|
||||
bool is_neg = false;
|
||||
|
||||
// read number from arg
|
||||
switch (opts->len) {
|
||||
case PRINTF_LEN_CHAR:
|
||||
num.u = va_arg(*ctx->args, unsigned int); // char
|
||||
break;
|
||||
case PRINTF_LEN_SHORT_INT:
|
||||
num.u = va_arg(*ctx->args, unsigned int); // short int
|
||||
break;
|
||||
case PRINTF_LEN_INT:
|
||||
num.u = va_arg(*ctx->args, unsigned int);
|
||||
break;
|
||||
case PRINTF_LEN_LONG_INT:
|
||||
num.u = va_arg(*ctx->args, unsigned long int);
|
||||
break;
|
||||
case PRINTF_LEN_LONG_LONG_INT:
|
||||
num.u = va_arg(*ctx->args, unsigned long long int);
|
||||
break;
|
||||
case PRINTF_LEN_SIZE_T:
|
||||
num.u = va_arg(*ctx->args, size_t);
|
||||
break;
|
||||
}
|
||||
|
||||
// get sign if possible neg
|
||||
if (has_sign_bit) {
|
||||
if (num.i < 0) {
|
||||
num.i = -num.i;
|
||||
is_neg = true;
|
||||
}
|
||||
}
|
||||
|
||||
// get length of number and number
|
||||
char buf[PRINTF_NUMERIC_BUF_LEN];
|
||||
int buf_len = printf_lltoa(buf, opts, is_neg, num.u);
|
||||
|
||||
// get needed padding
|
||||
int padding = 0;
|
||||
if (opts->width_set && (buf_len < opts->width))
|
||||
padding = opts->width - buf_len;
|
||||
|
||||
/* print */
|
||||
// left padding
|
||||
if (opts->left == 0) {
|
||||
for (int i = 0; i < padding; i++)
|
||||
printf_putc(ctx, opts->zero ? '0' : ' ');
|
||||
}
|
||||
// number
|
||||
for (int i = 0; i < buf_len; i++)
|
||||
printf_putc(ctx, buf[i]);
|
||||
// right padding
|
||||
if (opts->left == 1) {
|
||||
for (int i = 0; i < padding; i++)
|
||||
printf_putc(ctx, opts->zero ? '0' : ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_char_specifier(context_t *ctx)
|
||||
{
|
||||
char c = va_arg(*ctx->args, int);
|
||||
printf_putc(ctx, c);
|
||||
}
|
||||
|
||||
static void handle_string_specifier(context_t *ctx, options_t *opts)
|
||||
{
|
||||
char *str = va_arg(*ctx->args, char *);
|
||||
int str_len = 0;
|
||||
|
||||
// get length of string
|
||||
if (opts->precision_set)
|
||||
str_len = opts->precision;
|
||||
else
|
||||
str_len = strlen(str);
|
||||
|
||||
// get needed padding
|
||||
int padding = 0;
|
||||
if (opts->width_set && (str_len < opts->width))
|
||||
padding = opts->width - str_len;
|
||||
|
||||
/* print */
|
||||
// left padding
|
||||
if (opts->left == 0) {
|
||||
for (int i = 0; i < padding; i++)
|
||||
printf_putc(ctx, ' ');
|
||||
}
|
||||
// string
|
||||
for (int i = 0; i < str_len; i++)
|
||||
printf_putc(ctx, str[i]);
|
||||
// right padding
|
||||
if (opts->left == 1) {
|
||||
for (int i = 0; i < padding; i++)
|
||||
printf_putc(ctx, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void do_printf(context_t *ctx)
|
||||
{
|
||||
const char *fmt = ctx->format;
|
||||
|
||||
char c = *(fmt++);
|
||||
while (c != '\0') {
|
||||
// save start of fmt for current iteration
|
||||
const char *start = fmt;
|
||||
|
||||
// ignore if not %
|
||||
if (c != '%') {
|
||||
printf_putc(ctx, c);
|
||||
continue;
|
||||
}
|
||||
|
||||
// read opts
|
||||
options_t opts = { 0 };
|
||||
while (parse_flag(&fmt, &opts))
|
||||
;
|
||||
parse_width(&fmt, &opts);
|
||||
parse_precision(&fmt, &opts);
|
||||
parse_length(&fmt, &opts);
|
||||
|
||||
// read specifier
|
||||
char spec = *(fmt++);
|
||||
get_radix(spec, &opts);
|
||||
get_case(spec, &opts);
|
||||
|
||||
// read varied width / precision
|
||||
if (opts.width_varies) {
|
||||
opts.width_set = 1;
|
||||
opts.width = va_arg(*ctx->args, int);
|
||||
}
|
||||
if (opts.precision_varies) {
|
||||
opts.precision_set = 1;
|
||||
opts.precision = va_arg(*ctx->args, int);
|
||||
}
|
||||
|
||||
switch (spec) {
|
||||
// signed int
|
||||
case 'd':
|
||||
case 'i':
|
||||
handle_int_specifier(ctx, &opts, true);
|
||||
break;
|
||||
// unsigned int
|
||||
case 'u':
|
||||
case 'o':
|
||||
case 'x':
|
||||
case 'X':
|
||||
handle_int_specifier(ctx, &opts, false);
|
||||
break;
|
||||
// character
|
||||
case 'c':
|
||||
handle_char_specifier(ctx);
|
||||
break;
|
||||
// string
|
||||
case 's':
|
||||
handle_string_specifier(ctx, &opts);
|
||||
break;
|
||||
// unknown
|
||||
default:
|
||||
// print from % to current
|
||||
for (; start < fmt; start++)
|
||||
printf_putc(ctx, *start);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printf(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
size_t sprintf(char *restrict s, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
size_t amt;
|
||||
va_start(args, format);
|
||||
amt = vsprintf(s, format, args);
|
||||
va_end(args);
|
||||
return amt;
|
||||
}
|
||||
|
||||
size_t snprintf(char *restrict s, size_t maxlen, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
size_t amt;
|
||||
va_start(args, format);
|
||||
amt = vsnprintf(s, maxlen, format, args);
|
||||
va_end(args);
|
||||
return amt;
|
||||
}
|
||||
|
||||
void vprintf(const char *format, va_list args)
|
||||
{
|
||||
vfprintf(stdout, format, args);
|
||||
}
|
||||
|
||||
size_t vsprintf(char *restrict s, const char *format, va_list args)
|
||||
{
|
||||
// create context
|
||||
context_t ctx = { 0 };
|
||||
ctx.format = format;
|
||||
ctx.args = &args;
|
||||
// sprintf buffer
|
||||
ctx.out.buf = s;
|
||||
ctx.to_file = 0;
|
||||
// print
|
||||
do_printf(&ctx);
|
||||
return ctx.written_len;
|
||||
}
|
||||
|
||||
size_t vsnprintf(char *restrict s, size_t maxlen, const char *format,
|
||||
va_list args)
|
||||
{
|
||||
// create context
|
||||
context_t ctx = { 0 };
|
||||
ctx.format = format;
|
||||
ctx.args = &args;
|
||||
// sprintf buffer
|
||||
ctx.out.buf = s;
|
||||
ctx.to_file = 0;
|
||||
// sprintf max_len
|
||||
ctx.has_max_len = 1;
|
||||
ctx.max_len = maxlen;
|
||||
// print
|
||||
do_printf(&ctx);
|
||||
return ctx.written_len;
|
||||
}
|
||||
|
||||
void fprintf(FILE *stream, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stream, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void vfprintf(FILE *stream, const char *format, va_list args)
|
||||
{
|
||||
// create context
|
||||
context_t ctx = { 0 };
|
||||
ctx.format = format;
|
||||
ctx.args = &args;
|
||||
// fprintf stream
|
||||
ctx.out.file = stream;
|
||||
ctx.to_file = 1;
|
||||
// print
|
||||
do_printf(&ctx);
|
||||
}
|
132
lib/sprint.c
132
lib/sprint.c
|
@ -1,132 +0,0 @@
|
|||
/**
|
||||
** @file sprint.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef SPRINT_SRC_INC
|
||||
#define SPRINT_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** sprint(dst,fmt,...) - formatted output into a string buffer
|
||||
**
|
||||
** @param dst The string buffer
|
||||
** @param fmt Format string
|
||||
**
|
||||
** The format string parameter is followed by zero or more additional
|
||||
** parameters which are interpreted according to the format string.
|
||||
**
|
||||
** NOTE: assumes the buffer is large enough to hold the result string
|
||||
**
|
||||
** NOTE: relies heavily on the x86 parameter passing convention
|
||||
** (parameters are pushed onto the stack in reverse order as
|
||||
** 32-bit values).
|
||||
*/
|
||||
void sprint(char *dst, char *fmt, ...)
|
||||
{
|
||||
int32_t *ap;
|
||||
char buf[12];
|
||||
char ch;
|
||||
char *str;
|
||||
int leftadjust;
|
||||
int width;
|
||||
int len;
|
||||
int padchar;
|
||||
|
||||
/*
|
||||
** Get characters from the format string and process them
|
||||
**
|
||||
** We use the "old-school" method of handling variable numbers
|
||||
** of parameters. We assume that parameters are passed on the
|
||||
** runtime stack in consecutive longwords; thus, if the first
|
||||
** parameter is at location 'x', the second is at 'x+4', the
|
||||
** third at 'x+8', etc. We use a pointer to a 32-bit thing
|
||||
** to point to the next "thing", and interpret it according
|
||||
** to the format string.
|
||||
*/
|
||||
|
||||
// get the pointer to the first "value" parameter
|
||||
ap = (int *)(&fmt) + 1;
|
||||
|
||||
// iterate through the format string
|
||||
while ((ch = *fmt++) != '\0') {
|
||||
/*
|
||||
** Is it the start of a format code?
|
||||
*/
|
||||
if (ch == '%') {
|
||||
/*
|
||||
** Yes, get the padding and width options (if there).
|
||||
** Alignment must come at the beginning, then fill,
|
||||
** then width.
|
||||
*/
|
||||
leftadjust = 0;
|
||||
padchar = ' ';
|
||||
width = 0;
|
||||
ch = *fmt++;
|
||||
if (ch == '-') {
|
||||
leftadjust = 1;
|
||||
ch = *fmt++;
|
||||
}
|
||||
if (ch == '0') {
|
||||
padchar = '0';
|
||||
ch = *fmt++;
|
||||
}
|
||||
while (ch >= '0' && ch <= '9') {
|
||||
width *= 10;
|
||||
width += ch - '0';
|
||||
ch = *fmt++;
|
||||
}
|
||||
|
||||
/*
|
||||
** What data type do we have?
|
||||
*/
|
||||
switch (ch) {
|
||||
case 'c': // characters are passed as 32-bit values
|
||||
ch = *ap++;
|
||||
buf[0] = ch;
|
||||
buf[1] = '\0';
|
||||
dst = padstr(dst, buf, 1, width, leftadjust, padchar);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
len = cvtdec(buf, *ap++);
|
||||
dst = padstr(dst, buf, len, width, leftadjust, padchar);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
str = (char *)(*ap++);
|
||||
dst = padstr(dst, str, -1, width, leftadjust, padchar);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
len = cvthex(buf, *ap++);
|
||||
dst = padstr(dst, buf, len, width, leftadjust, padchar);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
len = cvtoct(buf, *ap++);
|
||||
dst = padstr(dst, buf, len, width, leftadjust, padchar);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
len = cvtuns(buf, *ap++);
|
||||
dst = padstr(dst, buf, len, width, leftadjust, padchar);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// no, it's just an ordinary character
|
||||
*dst++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
// NUL-terminate the result
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
#endif
|
9
lib/stpcpy.c
Normal file
9
lib/stpcpy.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include <string.h>
|
||||
|
||||
char *stpcpy(char *restrict dest, const char *restrict src)
|
||||
{
|
||||
char *d = dest;
|
||||
for (; (*d = *src); d++, src++)
|
||||
;
|
||||
return d;
|
||||
}
|
10
lib/stpncpy.c
Normal file
10
lib/stpncpy.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <string.h>
|
||||
|
||||
char *stpncpy(char *restrict dest, const char *restrict src, size_t n)
|
||||
{
|
||||
char *d = dest;
|
||||
for (; (*d = *src) && n; d++, src++, n--)
|
||||
;
|
||||
memset(d, 0, n);
|
||||
return d;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/**
|
||||
** @file str2int.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef STR2INT_SRC_INC
|
||||
#define STR2INT_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** str2int(str,base) - convert a string to a number in the specified base
|
||||
**
|
||||
** @param str The string to examine
|
||||
** @param base The radix to use in the conversion
|
||||
**
|
||||
** @return The converted integer
|
||||
*/
|
||||
int str2int(register const char *str, register int base)
|
||||
{
|
||||
register int num = 0;
|
||||
register char bchar = '9';
|
||||
int sign = 1;
|
||||
|
||||
// check for leading '-'
|
||||
if (*str == '-') {
|
||||
sign = -1;
|
||||
++str;
|
||||
}
|
||||
|
||||
if (base != 10) {
|
||||
bchar = '0' + base - 1;
|
||||
}
|
||||
|
||||
// iterate through the characters
|
||||
while (*str) {
|
||||
if (*str < '0' || *str > bchar)
|
||||
break;
|
||||
num = num * base + *str - '0';
|
||||
++str;
|
||||
}
|
||||
|
||||
// return the converted value
|
||||
return (num * sign);
|
||||
}
|
||||
|
||||
#endif
|
40
lib/strcat.c
40
lib/strcat.c
|
@ -1,39 +1,7 @@
|
|||
/**
|
||||
** @file strcat.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#ifndef STRCAT_SRC_INC
|
||||
#define STRCAT_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** strcat(dst,src) - append one string to another
|
||||
**
|
||||
** @param dst The destination buffer
|
||||
** @param src The source buffer
|
||||
**
|
||||
** @return The dst parameter
|
||||
**
|
||||
** NOTE: assumes dst is large enough to hold the resulting string
|
||||
*/
|
||||
char *strcat(register char *dst, register const char *src)
|
||||
char *strcat(char *restrict dest, const char *restrict src)
|
||||
{
|
||||
register char *tmp = dst;
|
||||
|
||||
while (*dst) // find the NUL
|
||||
++dst;
|
||||
|
||||
while ((*dst++ = *src++)) // append the src string
|
||||
;
|
||||
|
||||
return (tmp);
|
||||
strcpy(dest + strlen(dest), src);
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
32
lib/strcmp.c
32
lib/strcmp.c
|
@ -1,32 +0,0 @@
|
|||
/**
|
||||
** @file strcmp.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
|
||||
#ifndef STRCMP_SRC_INC
|
||||
#define STRCMP_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** strcmp(s1,s2) - compare two NUL-terminated strings
|
||||
**
|
||||
** @param s1 The first source string
|
||||
** @param s2 The second source string
|
||||
**
|
||||
** @return negative if s1 < s2, zero if equal, and positive if s1 > s2
|
||||
*/
|
||||
int strcmp(register const char *s1, register const char *s2)
|
||||
{
|
||||
while (*s1 != 0 && (*s1 == *s2))
|
||||
++s1, ++s2;
|
||||
|
||||
return (*s1 - *s2);
|
||||
}
|
||||
|
||||
#endif
|
37
lib/strcpy.c
37
lib/strcpy.c
|
@ -1,36 +1,9 @@
|
|||
/**
|
||||
** @file strcpy.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#ifndef STRCPY_SRC_INC
|
||||
#define STRCPY_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** strcpy(dst,src) - copy a NUL-terminated string
|
||||
**
|
||||
** @param dst The destination buffer
|
||||
** @param src The source buffer
|
||||
**
|
||||
** @return The dst parameter
|
||||
**
|
||||
** NOTE: assumes dst is large enough to hold the copied string
|
||||
*/
|
||||
char *strcpy(register char *dst, register const char *src)
|
||||
char *strcpy(char *restrict dest, const char *restrict src)
|
||||
{
|
||||
register char *tmp = dst;
|
||||
|
||||
while ((*dst++ = *src++))
|
||||
char *d = dest;
|
||||
for (; (*d = *src); d++, src++)
|
||||
;
|
||||
|
||||
return (tmp);
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
34
lib/strlen.c
34
lib/strlen.c
|
@ -1,33 +1,9 @@
|
|||
/**
|
||||
** @file strlen.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#ifndef STRLEN_SRC_INC
|
||||
#define STRLEN_SRC_INC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/**
|
||||
** strlen(str) - return length of a NUL-terminated string
|
||||
**
|
||||
** @param str The string to examine
|
||||
**
|
||||
** @return The length of the string, or 0
|
||||
*/
|
||||
uint32_t strlen(register const char *str)
|
||||
size_t strlen(const char *str)
|
||||
{
|
||||
register uint32_t len = 0;
|
||||
|
||||
while (*str++) {
|
||||
++len;
|
||||
const char *p;
|
||||
for (p = str; *p != 0; p++) {
|
||||
}
|
||||
|
||||
return (len);
|
||||
return p - str;
|
||||
}
|
||||
#endif
|
||||
|
|
11
lib/strncmp.c
Normal file
11
lib/strncmp.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <string.h>
|
||||
|
||||
int strncmp(const char *restrict lhs, const char *restrict rhs, size_t n)
|
||||
{
|
||||
const unsigned char *l = (void *)lhs, *r = (void *)rhs;
|
||||
if (!n--)
|
||||
return 0;
|
||||
for (; *l && *r && n && *l == *r; l++, r++, n--)
|
||||
;
|
||||
return *l - *r;
|
||||
}
|
10
lib/strncpy.c
Normal file
10
lib/strncpy.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <string.h>
|
||||
|
||||
char *strncpy(char *restrict dest, const char *restrict src, size_t n)
|
||||
{
|
||||
char *d = dest;
|
||||
for (; (*d = *src) && n; d++, src++, n--)
|
||||
;
|
||||
memset(d, 0, n);
|
||||
return dest;
|
||||
}
|
44
lib/strtoux.c
Normal file
44
lib/strtoux.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define STRTOUX(name, type) \
|
||||
type name(const char *restrict s, char **restrict endptr, int radix) \
|
||||
{ \
|
||||
const char *s_start = s; \
|
||||
for (; isspace(*s); s++) \
|
||||
; \
|
||||
\
|
||||
if ((radix == 0 || radix == 16) && \
|
||||
(s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))) { \
|
||||
radix = 16; \
|
||||
s += 2; \
|
||||
} else if (radix == 0) { \
|
||||
if (*s == '0') { \
|
||||
radix = 8; \
|
||||
s++; \
|
||||
} else { \
|
||||
radix = 10; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
type num = 0; \
|
||||
int has_digit = 0; \
|
||||
\
|
||||
while (1) { \
|
||||
int n = ctoi(*s++); \
|
||||
if (n < 0 || n >= radix) \
|
||||
break; \
|
||||
has_digit = 1; \
|
||||
num = num * radix + n; \
|
||||
} \
|
||||
\
|
||||
if (endptr != NULL) { \
|
||||
*endptr = has_digit ? (char *)(s - 1) : (char *)s_start; \
|
||||
} \
|
||||
\
|
||||
return num; \
|
||||
}
|
||||
|
||||
STRTOUX(strtoui, unsigned int)
|
||||
STRTOUX(strtoul, unsigned long int)
|
||||
STRTOUX(strtoull, unsigned long long int)
|
53
lib/strtox.c
Normal file
53
lib/strtox.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define STRTOX(name, type) \
|
||||
type name(const char *restrict s, char **restrict endptr, int radix) \
|
||||
{ \
|
||||
const char *s_start = s; \
|
||||
for (; isspace(*s); s++) \
|
||||
; \
|
||||
\
|
||||
int sign = 0; \
|
||||
switch (*s) { \
|
||||
case '-': \
|
||||
sign = 1; /* fallthrough */ \
|
||||
case '+': \
|
||||
s++; \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
if ((radix == 0 || radix == 16) && \
|
||||
(s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))) { \
|
||||
radix = 16; \
|
||||
s += 2; \
|
||||
} else if (radix == 0) { \
|
||||
if (*s == '0') { \
|
||||
radix = 8; \
|
||||
s++; \
|
||||
} else { \
|
||||
radix = 10; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
type num = 0; \
|
||||
int has_digit = 0; \
|
||||
\
|
||||
while (1) { \
|
||||
int n = ctoi(*s++); \
|
||||
if (n < 0 || n >= radix) \
|
||||
break; \
|
||||
has_digit = 1; \
|
||||
num = num * radix + n; \
|
||||
} \
|
||||
\
|
||||
if (endptr != NULL) { \
|
||||
*endptr = has_digit ? (char *)(s - 1) : (char *)s_start; \
|
||||
} \
|
||||
\
|
||||
return sign ? -num : num; \
|
||||
}
|
||||
|
||||
STRTOX(strtoi, int)
|
||||
STRTOX(strtol, long int)
|
||||
STRTOX(strtoll, long long int)
|
170
lib/ulibc.c
170
lib/ulibc.c
|
@ -1,170 +0,0 @@
|
|||
/**
|
||||
** @file ulibc.c
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief C implementations of user-level library functions
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
** PRIVATE DEFINITIONS
|
||||
*/
|
||||
|
||||
/*
|
||||
** PRIVATE DATA TYPES
|
||||
*/
|
||||
|
||||
/*
|
||||
** PRIVATE GLOBAL VARIABLES
|
||||
*/
|
||||
|
||||
/*
|
||||
** PUBLIC GLOBAL VARIABLES
|
||||
*/
|
||||
|
||||
/*
|
||||
** PRIVATE FUNCTIONS
|
||||
*/
|
||||
|
||||
/*
|
||||
** PUBLIC FUNCTIONS
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************
|
||||
** CONVENIENT "SHORTHAND" VERSIONS OF SYSCALLS
|
||||
**********************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
** wait - wait for any child to exit
|
||||
**
|
||||
** usage: pid = wait(&status)
|
||||
**
|
||||
** Calls waitpid(0,status)
|
||||
**
|
||||
** @param status Pointer to int32_t into which the child's status is placed,
|
||||
** or NULL
|
||||
**
|
||||
** @returns The PID of the terminated child, or an error code
|
||||
*/
|
||||
int wait(int32_t *status)
|
||||
{
|
||||
return (waitpid(0, status));
|
||||
}
|
||||
|
||||
/**
|
||||
** spawn - create a new process running a different program
|
||||
**
|
||||
** usage: pid = spawn(what,args);
|
||||
**
|
||||
** Creates a new process and then execs 'what'
|
||||
**
|
||||
** @param what The program table index of the program to spawn
|
||||
** @param args The command-line argument vector for the new process
|
||||
**
|
||||
** @returns PID of the new process, or an error code
|
||||
*/
|
||||
int32_t spawn(uint_t what, char **args)
|
||||
{
|
||||
int32_t pid;
|
||||
char buf[256];
|
||||
|
||||
pid = fork();
|
||||
if (pid != 0) {
|
||||
// failure, or we are the parent
|
||||
return (pid);
|
||||
}
|
||||
|
||||
// we are the child
|
||||
pid = getpid();
|
||||
|
||||
// child inherits parent's priority level
|
||||
|
||||
exec(what, args);
|
||||
|
||||
// uh-oh....
|
||||
|
||||
sprint(buf, "Child %d exec() #%u failed\n", pid, what);
|
||||
cwrites(buf);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
return (0); // shut the compiler up
|
||||
}
|
||||
|
||||
/**
|
||||
** cwritech(ch) - write a single character to the console
|
||||
**
|
||||
** @param ch The character to write
|
||||
**
|
||||
** @returns The return value from calling write()
|
||||
*/
|
||||
int cwritech(char ch)
|
||||
{
|
||||
return (write(CHAN_CIO, &ch, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
** cwrites(str) - write a NUL-terminated string to the console
|
||||
**
|
||||
** @param str The string to write
|
||||
**
|
||||
*/
|
||||
int cwrites(const char *str)
|
||||
{
|
||||
int len = strlen(str);
|
||||
return (write(CHAN_CIO, str, len));
|
||||
}
|
||||
|
||||
/**
|
||||
** cwrite(buf,size) - write a sized buffer to the console
|
||||
**
|
||||
** @param buf The buffer to write
|
||||
** @param size The number of bytes to write
|
||||
**
|
||||
** @returns The return value from calling write()
|
||||
*/
|
||||
int cwrite(const char *buf, uint32_t size)
|
||||
{
|
||||
return (write(CHAN_CIO, buf, size));
|
||||
}
|
||||
|
||||
/**
|
||||
** swritech(ch) - write a single character to the SIO
|
||||
**
|
||||
** @param ch The character to write
|
||||
**
|
||||
** @returns The return value from calling write()
|
||||
*/
|
||||
int swritech(char ch)
|
||||
{
|
||||
return (write(CHAN_SIO, &ch, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
** swrites(str) - write a NUL-terminated string to the SIO
|
||||
**
|
||||
** @param str The string to write
|
||||
**
|
||||
** @returns The return value from calling write()
|
||||
*/
|
||||
int swrites(const char *str)
|
||||
{
|
||||
int len = strlen(str);
|
||||
return (write(CHAN_SIO, str, len));
|
||||
}
|
||||
|
||||
/**
|
||||
** swrite(buf,size) - write a sized buffer to the SIO
|
||||
**
|
||||
** @param buf The buffer to write
|
||||
** @param size The number of bytes to write
|
||||
**
|
||||
** @returns The return value from calling write()
|
||||
*/
|
||||
int swrite(const char *buf, uint32_t size)
|
||||
{
|
||||
return (write(CHAN_SIO, buf, size));
|
||||
}
|
93
lib/ulibs.S
93
lib/ulibs.S
|
@ -1,93 +0,0 @@
|
|||
/**
|
||||
** @file ulibs.S
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief assembly-language user-level library functions
|
||||
*/
|
||||
|
||||
#define ASM_SRC
|
||||
|
||||
// get the system call codes
|
||||
|
||||
#include <syscalls.h>
|
||||
|
||||
/**
|
||||
** System call stubs
|
||||
**
|
||||
** All have the same structure:
|
||||
**
|
||||
** move a code into EAX
|
||||
** generate the interrupt
|
||||
** return to the caller
|
||||
**
|
||||
** As these are simple "leaf" routines, we don't use
|
||||
** the standard enter/leave method to set up a stack
|
||||
** frame - that takes time, and we don't really need it.
|
||||
**
|
||||
** Could be modified to use the UNIX/Linux convention of
|
||||
** having the syscall code set the 'C' flag to indicate that
|
||||
** the value being returned in %EAX is an error code:
|
||||
**
|
||||
** ...
|
||||
** int $VEC_SYSCALL
|
||||
** jc set_errno
|
||||
** ret
|
||||
** ...
|
||||
**
|
||||
** .globl errno
|
||||
** set_errno:
|
||||
** movl %eax, errno
|
||||
** movl $-1, %eax
|
||||
** ret
|
||||
*/
|
||||
|
||||
#define SYSCALL(name) \
|
||||
.globl name ; \
|
||||
name: ; \
|
||||
movl $SYS_##name, %eax ; \
|
||||
int $VEC_SYSCALL ; \
|
||||
ret
|
||||
|
||||
/*
|
||||
** "real" system calls
|
||||
*/
|
||||
|
||||
SYSCALL(exit)
|
||||
SYSCALL(waitpid)
|
||||
SYSCALL(fork)
|
||||
SYSCALL(exec)
|
||||
SYSCALL(read)
|
||||
SYSCALL(write)
|
||||
SYSCALL(getpid)
|
||||
SYSCALL(getppid)
|
||||
SYSCALL(gettime)
|
||||
SYSCALL(getprio)
|
||||
SYSCALL(setprio)
|
||||
SYSCALL(kill)
|
||||
SYSCALL(sleep)
|
||||
|
||||
/*
|
||||
** This is a bogus system call; it's here so that we can test
|
||||
** our handling of out-of-range syscall codes in the syscall ISR.
|
||||
*/
|
||||
SYSCALL(bogus)
|
||||
|
||||
/*
|
||||
** Other library functions
|
||||
*/
|
||||
|
||||
/**
|
||||
** fake_exit()
|
||||
**
|
||||
** Dummy "startup" function
|
||||
**
|
||||
** calls exit(%eax) - serves as the "return to" code for
|
||||
** main() functions, in case they don't call exit() themselves
|
||||
*/
|
||||
|
||||
.globl fake_exit
|
||||
fake_exit:
|
||||
// alternate: could push a "fake exit" status
|
||||
pushl %eax // termination status returned by main()
|
||||
call exit // terminate this process
|
27
lib/uxtoa.c
Normal file
27
lib/uxtoa.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#define UXTOA(type, name) \
|
||||
char *name(unsigned type n, char *buffer, int radix) \
|
||||
{ \
|
||||
if (n == 0) { \
|
||||
buffer[0] = '0'; \
|
||||
buffer[1] = '\0'; \
|
||||
return buffer + 1; \
|
||||
} \
|
||||
char *start = buffer; \
|
||||
for (; n; n /= radix) { \
|
||||
*buffer++ = itoc(n % radix); \
|
||||
} \
|
||||
char *buf_end = buffer; \
|
||||
*buffer-- = '\0'; \
|
||||
while (buffer > start) { \
|
||||
char tmp = *start; \
|
||||
*start++ = *buffer; \
|
||||
*buffer-- = tmp; \
|
||||
} \
|
||||
return buf_end; \
|
||||
}
|
||||
|
||||
UXTOA(int, utoa)
|
||||
UXTOA(long int, ultoa)
|
||||
UXTOA(long long int, ulltoa)
|
31
lib/xtoa.c
Normal file
31
lib/xtoa.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#define XTOA(type, name) \
|
||||
char *name(type n, char *buffer, int radix) \
|
||||
{ \
|
||||
if (n == 0) { \
|
||||
buffer[0] = '0'; \
|
||||
buffer[1] = '\0'; \
|
||||
return buffer + 1; \
|
||||
} \
|
||||
if (n < 0) { \
|
||||
*buffer++ = '-'; \
|
||||
n = -n; \
|
||||
} \
|
||||
char *start = buffer; \
|
||||
for (; n; n /= radix) { \
|
||||
*buffer++ = itoc(n % radix); \
|
||||
} \
|
||||
char *buf_end = buffer; \
|
||||
*buffer-- = '\0'; \
|
||||
while (buffer > start) { \
|
||||
char tmp = *start; \
|
||||
*start++ = *buffer; \
|
||||
*buffer-- = tmp; \
|
||||
} \
|
||||
return buf_end; \
|
||||
}
|
||||
|
||||
XTOA(int, itoa)
|
||||
XTOA(long int, ltoa)
|
||||
XTOA(long long int, lltoa)
|
Loading…
Add table
Reference in a new issue