# Contributing Guidelines

*This project is constantly evolving, and as such, this file may be out of date.*

## Map

- `apps/` Builtin applications.
- `boot/` Contains files for booting the operating system.
	- `x86/` ...on x86.
		- `esfs-stage1.s` Loads `loader.s` from the start of a EsFS volume and passes control to it.
		- `esfs-stage2.s` Provides basic read-only EsFS functions for `loader.s`.
		- `loader.s` Loads the kernel and passes control to it.
		- `mbr.s` Finds and loads a bootable partition.
		- `uefi.c` UEFI bootloader first stage.
		- `uefi_loader.s` UEFI bootloader second stage.
		- `vbe.s` Sets the VBE graphics mode.
- `desktop/` Contains files for Desktop, which provides both the desktop environment, and a layer between applications and the kernel.
	- `api.cpp` API initialisation and internal messaging.
	- `api.s` API functions that must be implemented in assembly.
	- `calculator.cpp` Evaluates basic math expressions.
	- `crti.s, ctrn.s` Global constructors and destructors setup.
	- `cstdlib.cpp` Provides the system call interface for the POSIX subsystem.
	- `desktop.cpp` Desktop. Manages windows and the taskbar.
	- `glue.cpp` Entry point for applications using the POSIX subsystem.
	- `gui.cpp` The GUI.
	- `icons.header` A list of available icons.
	- `list_view.cpp` A list view control for the GUI.
	- `os.header` The header file containing the API's definitions.
	- `prefix.h` The header file prefix for C/C++.
	- `renderer.cpp` Provides visual style management and software rendering.
	- `renderer2.cpp` Vector graphics rendering.
	- `start.cpp` Entry point for all applications.
	- `syscall.cpp` Kernel system call wrappers.
	- `text.cpp` Text rendering and text-based GUI elements.
- `drivers/` Kernel drivers.
	- `acpi.cpp` A layer between the kernel and ACPICA. Also starts application processors on SMP systems.
	- `ata.cpp` A ATA/IDE driver.
	- `esfs2.cpp` The EssenceFS filesystem driver.
	- `fat.cpp` The FAT12 filesystem driver.
	- `hda.cpp` Intel HD Audio driver.
	- `pci.cpp` Finds devices on the PCI bus.
	- `ps2.cpp` A driver for PS/2 keyboard and mice.
	- `vbe.cpp` Basic VBE SVGA driver.
	- `vga.cpp` Basic VGA driver.
- `kernel/` The kernel and its drivers.
	- `audio.cpp` Audio system.
	- `config.mtsrc` System configuration. Describes all the modules that should be built, and when they should be loaded.
	- `devices.cpp` The device and IO manager.
	- `elf.cpp` Parses and loads ELF executables and kernel modules.
	- `graphics.cpp` Graphics system. Mostly deprecated.
	- `kernel.h` Internal kernel definitions. Includes all other source files in the kernel.
	- `main.cpp` Kernel initilisation and shutdown.
	- `memory.cpp` Physical, virtual and shared memory management.
	- `module.h` Kernel API available to driver modules.
	- `objects.cpp` Manages object and handles shared between the kernel and applications.
	- `posix.cpp` The (optional) POSIX subsystem.
	- `scheduler.cpp` A scheduler, and manager of threads and processes.
	- `symbols.cpp` Locating kernel symbols.
	- `synchronisation.cpp` Defines synchronisation primitives. Closely linked with the scheduler.
	- `syscall.cpp` Defers system calls to other parts of the kernel.
	- `terminal.cpp` Kernel debugging and serial output. 
	- `vfs.cpp` The virtual filesystem.
	- `windows.cpp` The window manager. Passes messages from HID devices to applications.
	- `x86_64.cpp` Code for the x64 architecture.
	- `x86_64.h` Definitions specific to the x64 architecture.
	- `x86_64.s` Assembly code for the x64 architecture.
- `ports/` A mess of ported applications. Enter with caution.
- `res/` Resources, such as fonts and visual styles.
	- `Fonts` Fonts used by the GUI.
	- `Icons` Icon packs used by the GUI.
	- `Sample Images` Sample images.
	- `Themes` Themes for the user interface..
- `shared/` Shared code between the componenets of the operating system.
	- `arena.cpp` Fixed-size allocations.
	- `avl_tree.cpp` Balanced binary tree, and maps.
	- `bitset.cpp` Managing sparse bitsets.
	- `common.cpp` Common functions.
	- `format_string.cpp` Locale-dependent text formatter.
	- `hash.cpp` Hash functions.
	- `heap.cpp` Heap allocator.
	- `linked_list.cpp` Doubly-linked lists.
	- `stb_ds.h`, `stb_image.h`, `stb_sprintf.h` STB libraries.
	- `style_parser.cpp` Parsing visual style specifiers.
	- `unicode.cpp` Functions for managing Unicode and UTF-8 strings.
	- `vga_font.cpp` A fallback bitmap font.
- `util/` Utilities for building the operating system.
	- `build.c` The build system.
	- `esfs2.h` A version of EssenceFS for use on linux from the command line.
	- `header_generator.c` Language independent header generation. 
	- `render_svg.c` Renders SVG icons.

## Code Style

Functions and structures names use `PascalCase`.
Variables use `camelCase`, while constants and macros use `SCREAMING_SNAKE_CASE`.

Tabs are `\t`, and are 8 characters in size.

Braces are placed at the end of the line: 

    if (a > b) {
        ...
    }
    
Blocks are always surrounded by newlines, and always have braces.

    int x = 5;
    
    if (x < 6) {
        x++; // Postfix operators are preferred.
    }
    
Exception: If there are lot of short, linked blocks, then they may be written like this-

    if (width == DIMENSION_PUSH) { bool a = grid->widths[i] == DIMENSION_PUSH; grid->widths[i] = DIMENSION_PUSH; if (!a) pushH++; }
    else if (grid->widths[i] < width && grid->widths[i] != DIMENSION_PUSH) grid->widths[i] = width;
    if (height == DIMENSION_PUSH) { bool a = grid->heights[j] == DIMENSION_PUSH; grid->heights[j] = DIMENSION_PUSH; if (!a) pushV++; }
    else if (grid->heights[j] < height && grid->heights[j] != DIMENSION_PUSH) grid->heights[j] = height;

Function names are always descriptive, and use prepositions and conjuctions if neccesary. 

    EsFileReadAll // Symbols provided by the API are prefixed with Es-.
    EsDrawSurface
    EsMemoryZero
    
Variable names are usually descriptive, but sometimes shortened names are used for short-lived variables.

    EsMessage m = {};
    m.type = OS_MESSAGE_MEASURE;
	EsMessagePost(&m);

Operators are padded with spaces on either side.

    bounds.left = (grid->bounds.left + grid->bounds.right) / 2 - 4;
    
A space should be placed between a cast and its expression.

    int x = (float) y;

Although the operating system is written in C++, most C++ features are avoided.
However, the kernel uses a lot of member functions.

    struct Window {
        void Update(bool fromUser);
        void SetCursorStyle(OSCursorStyle style);
        void NeedWMTimer(int hz);
        void Destroy();
        bool Move(OSRectangle &newBounds);
        void ClearImage();

        Mutex mutex; // Mutex for drawing to the window. Also needed when moving the window.
        Surface *surface;
        OSPoint position;
        size_t width, height;
        ...
    }
    
Default arguments often provided as functions grow over time.

There is no limit on function size. However, you should avoid regularly exceeding 120 columns.

Pointers are declared like this: `Type *name;`.

Identifiers may be prefixed with `i`, `e` or `c` to indicate inclusive, exclusive or C-style-zero-terminated-string respectively.

## Kernel and Driver Development

See `module.h` for definitions available to driver developers. See `drivers/fat.cpp` and `drivers/ata.cpp` for simple examples of the driver API.

The following subroutines may be of interest:

    void KWaitMicroseconds(uint64_t mcs); // Spin until a given number of microseconds have elapsed.
    void EsPrint(const char *format, ...); // Print a message to serial output. (Ctrl+Alt+3 in Qemu)
    void KernelPanic(const char *format, ...); // Print a message and halt the OS.
    Defer(<statement>); // Defer a statement. Deferred statements will be executed in reverse order when they go out of scope.
    size_t EsCStringLength(const char *string); // Get the length of a zero-terminated string.
    void EsMemoryCopy(void *destination, const void *source, size_t bytes); // Copy memory forwards.
    void EsMemoryZero(void *destination, size_t bytes); // Zero a buffer.
    void EsMemoryMove(void *start, void *end, intptr_t amount, bool zeroEmptySpace); // Move a memory region left (amount < 0) or right (amount > 0).
    int EsMemoryCopy(const void *a, const void *b, size_t bytes); // Compare two memory regions. Returns 0 if equal.
    uint8_t EsSumBytes(uint8_t *source, size_t bytes); // Calculate the 8-bit sum of the bytes in a buffer.
    size_t EsStringFormat(char *buffer, size_t bufferLength, const char *format, ...); // Format a string. Returns the length.
    uint8_t EsGetRandomByte(); // Get a non-secure random byte.
    void EsSort(void *base, size_t count, size_t size, int (*compare)(const void *, const void *, void *), void *callbackArgument); // Sort an array of count items of size size.
    uint32_t CalculateCRC32(void *buffer, size_t length); // Calculate the CRC32 checksum of a buffer.
    void ProcessorEnableInterrupts(); // Enable interrupts.
    void ProcessorDisableInterrupts(); // Disable interrupts. Critical interrupts, such as TLB shootdown IPIs, will remain enabled.
    void ProcessorOut<x>(uint16_t port, uint<x>_t value); // Write to an IO port.
    uint<x>_t ProcessorIn<x>(uint16_t port); // Read from an IO port.
    uint64_t ProcessorReadTimeStamp(); // Read the time stamp in ticks. acpi.timestampTicksPerMs gives the number of ticks per millisecond.
    bool KRegisterIRQ(uintptr_t interruptIndex, IRQHandler handler, void *context, const char *cOwner); // Register an IRQ handler. Returns false if the IRQ could not be registered. The handler should return false if its devices was not responsible for the IRQ.
    void *MMMapPhysical(MMSpace *space /* = kernelMMSpace */, uintptr_t offset, size_t bytes); // Memory mapped IO.
    void *EsHeapAllocate(size_t size, bool zero); // Allocate memory from the heap.
    void EsHeapFree(void *pointer); // Free memory from the heap.
    bool KThreadCreate(const char *cName, void (*startAddress)(uintptr_t), uintptr_t argument = 0); // Create a thread.

Synchronisation:

    void Mutex::Acquire();
    void Mutex::Release();
    void Mutex::AssertLocked();

    void Spinlock::Acquire(); // Disables interrupts.
    void Spinlock::Release();
    void Spinlock::AssertLocked();

    bool Event::Set();
    void Event::Reset();
    bool Event::Pool();
    bool Event::Wait(uintptr_t timeoutMs); // Return false on timeout.
    // event.autoReset determines whether the event will automatically reset after Poll() or Wait() return.

Linked lists:

    LinkedList<T>::InsertStart(LinkedItem<T> *item); // Insert an item at the start of a linked list.
    LinkedList<T>::InsertEnd(LinkedItem<T> *item); // Insert an item at the end of a linked list.
    LinkedList<T>::Remove(LinkedItem<T> *item); // Remove an item from a linked list.
    
    struct LinkedList<T> {
        LinkedItem<T> *firstItem; // The start of the linked list.
        LinkedItem<T> *lastItem; // The end of the linked list.
        size_t count; // The number of items in the linked list.
    }

    struct LinkedItem<T> {
        LinkedItem<T> *previousItem; // The previous item in the linked list.
        LinkedItem<T> *nextItem; // The next item in the linked list.
        LinkedList<T> *list; // The list the item is in.
	T *thisItem; // A pointer to the item itself.
    }

## Contributors

Put your name here!

- nakst
- Brett R. Toomey
- vtlmks
- Aleksander Birkeland