Handout
This commit is contained in:
43
utils/flake.lock
generated
Normal file
43
utils/flake.lock
generated
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1740560979,
|
||||
"narHash": "sha256-Vr3Qi346M+8CjedtbyUevIGDZW8LcA1fTG0ugPY/Hic=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5135c59491985879812717f4c9fea69604e7f26f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs",
|
||||
"systems": "systems"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1680978846,
|
||||
"narHash": "sha256-Gtqg8b/v49BFDpDetjclCYXm8mAnTrUzR0JnE2nv5aw=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "x86_64-linux",
|
||||
"rev": "2ecfcac5e15790ba6ce360ceccddb15ad16d08a8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "x86_64-linux",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
58
utils/flake.nix
Normal file
58
utils/flake.nix
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file allows you to run `nix develop` to get a shell with all external dependencies (`make` plus the tools it calls) of this repo (and maybe some beyond).
|
||||
* The only thing required is an installation of the "Nix" package manager for Linux (/WSL) or MacOS: https://nixos.org/download/
|
||||
*/
|
||||
{
|
||||
description = ''
|
||||
The educational operating system StuBS.
|
||||
'';
|
||||
inputs = {
|
||||
|
||||
# The rolling-release of the Nix(OS) package definitions. Use `nix flake lock` to update
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
|
||||
# Some boilerplate:
|
||||
systems.url = "github:nix-systems/x86_64-linux"; # no cross compiling and only x86(_64) for now (darwin (MacOS) might work)
|
||||
};
|
||||
outputs =
|
||||
inputs:
|
||||
let
|
||||
lib = inputs.nixpkgs.lib;
|
||||
eachSystem =
|
||||
f:
|
||||
lib.foldAttrs lib.mergeAttrs { } (
|
||||
map (s: lib.mapAttrs (_: v: { ${s} = v; }) (f s)) (import inputs.systems)
|
||||
);
|
||||
in
|
||||
{ }
|
||||
// (eachSystem (
|
||||
localSystem:
|
||||
let
|
||||
pkgs = import inputs.nixpkgs { system = localSystem; };
|
||||
in
|
||||
{
|
||||
|
||||
# The shell environment definition used by `nix develop`:
|
||||
devShells.default = pkgs.mkShell.override { stdenv = pkgs.clangStdenv; } {
|
||||
nativeBuildInputs =
|
||||
with pkgs;
|
||||
[
|
||||
# for all tasks and maintenance
|
||||
gdb
|
||||
qemu_kvm
|
||||
nasm
|
||||
ccache
|
||||
util-linux # mkfs.minix
|
||||
git
|
||||
python3
|
||||
bear # make compile_commands.json
|
||||
clang-tools # for clangd and clang-format
|
||||
]
|
||||
++ (lib.filter (
|
||||
pkg: lib.isDerivation pkg && pkg.pname or "" != "glibc"
|
||||
) pkgs.stdenv.allowedRequisites); # basic tools + compilers (gcc/g++)
|
||||
};
|
||||
|
||||
}
|
||||
));
|
||||
}
|
||||
27
utils/math.h
Normal file
27
utils/math.h
Normal file
@@ -0,0 +1,27 @@
|
||||
// vim: set noet ts=4 sw=4:
|
||||
|
||||
/*! \file
|
||||
* \brief General purpose \ref Math "math functions"
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "../types.h"
|
||||
|
||||
/*! \brief Basic math helper functions
|
||||
*/
|
||||
namespace Math {
|
||||
template <typename T>
|
||||
T abs(T a) {
|
||||
return (a >= 0 ? a : -a);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T min(T a, T b) {
|
||||
return a > b ? b : a;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T max(T a, T b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
} // namespace Math
|
||||
17
utils/size.h
Normal file
17
utils/size.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*! \file
|
||||
* \brief Template function to determine the length of an array
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
/* \brief Helper to retrieve the number of elements in an array
|
||||
* (Warning: template magic)
|
||||
* \param Array
|
||||
* \return Number of elements
|
||||
*/
|
||||
template <class T, size_t N>
|
||||
constexpr size_t size(T (& /*unused*/)[N]) {
|
||||
return N;
|
||||
}
|
||||
117
utils/string.cc
Normal file
117
utils/string.cc
Normal file
@@ -0,0 +1,117 @@
|
||||
#include "string.h"
|
||||
|
||||
extern "C" char *strchrnul(const char *s, int c) {
|
||||
if (s != nullptr) {
|
||||
while (*s != '\0') {
|
||||
if (*s == c) {
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
return const_cast<char *>(s);
|
||||
}
|
||||
|
||||
extern "C" char *strchr(const char *s, int c) {
|
||||
if (s != nullptr) {
|
||||
s = strchrnul(s, c);
|
||||
if (*s == c) {
|
||||
return const_cast<char *>(s);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" int strcmp(const char *s1, const char *s2) {
|
||||
if (s1 == nullptr || s2 == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (*s1 == *s2++) {
|
||||
if (*s1++ == '\0') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return static_cast<int>(*s1) - static_cast<int>(*(s2 - 1));
|
||||
}
|
||||
|
||||
extern "C" int strncmp(const char *s1, const char *s2, size_t n) {
|
||||
if (s1 != nullptr && s2 != nullptr) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (s1[i] != s2[i]) {
|
||||
return static_cast<int>(s1[i]) - static_cast<int>(s2[i]);
|
||||
} else if (s1[i] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" size_t strlen(const char *s) {
|
||||
size_t len = 0;
|
||||
if (s != nullptr) {
|
||||
while (*s++ != '\0') {
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
extern "C" char *strcpy(char *dest, const char *src) { // NOLINT
|
||||
char *r = dest;
|
||||
if (dest != nullptr && src != nullptr) {
|
||||
while ((*dest++ = *src++) != '\0') {
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" char *strncpy(char *dest, const char *src, size_t n) {
|
||||
char *r = dest;
|
||||
if (dest != nullptr && src != nullptr) {
|
||||
while ((n--) != 0 && (*dest++ = *src++) != '\0') {
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" void *memcpy(void *__restrict__ dest, void const *__restrict__ src,
|
||||
size_t size) {
|
||||
uint8_t *destination = reinterpret_cast<uint8_t *>(dest);
|
||||
uint8_t const *source = (uint8_t const *)src;
|
||||
|
||||
for (size_t i = 0; i != size; ++i) {
|
||||
destination[i] = source[i];
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
extern "C" void *memmove(void *dest, void const *src, size_t size) {
|
||||
uint8_t *destination = reinterpret_cast<uint8_t *>(dest);
|
||||
uint8_t const *source = reinterpret_cast<uint8_t const *>(src);
|
||||
|
||||
if (source > destination) {
|
||||
for (size_t i = 0; i != size; ++i) {
|
||||
destination[i] = source[i];
|
||||
}
|
||||
} else {
|
||||
for (size_t i = size; i != 0; --i) {
|
||||
destination[i - 1] = source[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
extern "C" void *memset(void *dest, int pattern, size_t size) {
|
||||
uint8_t *destination = reinterpret_cast<uint8_t *>(dest);
|
||||
|
||||
for (size_t i = 0; i != size; ++i) {
|
||||
destination[i] = static_cast<uint8_t>(pattern);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
109
utils/string.h
Normal file
109
utils/string.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*! \file
|
||||
* \brief General purpose \ref string "String functions"
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
/*! \defgroup string String function
|
||||
* \brief String functions as provided by `%string.h` in the C standard
|
||||
*library
|
||||
*/
|
||||
|
||||
/*! \brief Find the first occurrence of a character in a string
|
||||
* \ingroup string
|
||||
* \param s string to
|
||||
* \param c character to find
|
||||
* \return Pointer to first occurrence of the character
|
||||
* or to null byte at the end of the string if not found
|
||||
*/
|
||||
extern "C" char *strchrnul(const char *s, int c);
|
||||
|
||||
/*! \brief Find the first occurrence of a character in a string
|
||||
* \ingroup string
|
||||
* \param s string to
|
||||
* \param c character to find
|
||||
* \return Pointer to first occurrence of the character
|
||||
* or to nullptr if not found
|
||||
*/
|
||||
extern "C" char *strchr(const char *s, int c);
|
||||
|
||||
/*! \brief Compare two strings
|
||||
* \ingroup string
|
||||
* \param s1 first string
|
||||
* \param s2 second string
|
||||
* \return an integer less than, equal to, or greater than zero if first string
|
||||
* is found, respectively, to be less than, to match, or be greater than second
|
||||
* string
|
||||
*/
|
||||
extern "C" int strcmp(const char *s1, const char *s2);
|
||||
|
||||
/*! \brief Compare two strings
|
||||
* \ingroup string
|
||||
* \param s1 first string
|
||||
* \param s2 second string
|
||||
* \param n number of bytes to compare
|
||||
* \return an integer less than, equal to, or greater than zero if the given
|
||||
* number of bytes of the first string are found, respectively, to be less than,
|
||||
* to match, or be greater than second string
|
||||
*/
|
||||
extern "C" int strncmp(const char *s1, const char *s2, size_t n);
|
||||
|
||||
/*! \brief Calculate the length of a string
|
||||
* \ingroup string
|
||||
* \param s pointer to a string
|
||||
* \return number of bytes in the string
|
||||
*/
|
||||
extern "C" size_t strlen(const char *s);
|
||||
|
||||
/*! \brief Copy the contents of a string
|
||||
* including the terminating null byte (`\0`)
|
||||
* \ingroup string
|
||||
* \param dest destination string buffer
|
||||
* \param src source string buffer
|
||||
* \return a pointer to the destination string buffer
|
||||
* \note Beware of buffer overruns!
|
||||
*/
|
||||
extern "C" char *strcpy(char *dest, const char *src); // NOLINT
|
||||
|
||||
/*! \brief Copy the contents of a string up to a maximum length
|
||||
* or the terminating null byte (`\0`), whatever comes first.
|
||||
* \ingroup string
|
||||
* \param dest destination string buffer
|
||||
* \param src source string buffer
|
||||
* \param n maximum number of bytes to copy
|
||||
* \return a pointer to the destination string buffer
|
||||
* \note If there is no null byte (`\0`) among the first `n` bytes, the
|
||||
* destination will not be null-terminated!
|
||||
*/
|
||||
extern "C" char *strncpy(char *dest, const char *src, size_t n);
|
||||
|
||||
/*! \brief Copy a memory area
|
||||
* \ingroup string
|
||||
* \param dest destination buffer
|
||||
* \param src source buffer
|
||||
* \param size number of bytes to copy
|
||||
* \return pointer to destination
|
||||
* \note The memory must not overlap!
|
||||
*/
|
||||
extern "C" void *memcpy(void *__restrict__ dest, void const *__restrict__ src,
|
||||
size_t size);
|
||||
|
||||
/*! \brief Copy a memory area
|
||||
* while the source may overlap with the destination
|
||||
* \ingroup string
|
||||
* \param dest destination buffer
|
||||
* \param src source buffer
|
||||
* \param size number of bytes to copy
|
||||
* \return pointer to destination
|
||||
*/
|
||||
extern "C" void *memmove(void *dest, void const *src, size_t size);
|
||||
|
||||
/*! \brief Fill a memory area with a pattern
|
||||
* \ingroup string
|
||||
* \param dest destination buffer
|
||||
* \param pattern single byte pattern
|
||||
* \param size number of bytes to fill with pattern
|
||||
* \return pointer to destination
|
||||
*/
|
||||
extern "C" void *memset(void *dest, int pattern, size_t size);
|
||||
Reference in New Issue
Block a user