\( % Arcus cosine. \def\acos{\cos^{-1}} % Vector projection. \def\projection#1#2{{proj_{#1}\left(#2\right)}} % Vector rejection. \def\rejection#1#2{{rej_{#1}\left(#2\right)}} % Norm. \def\norm#1{{\left\|#1\right\|}} % Cross product. \def\cross#1#2{\mathit{cross}\left(#1,#2\right)} % Dot product. \def\dot#1#2{{#1 \cdot #2}} % Magnitude. \def\mag#1{{\left|#1\right}} \def\group#1{\left(#1\right)}} \def\sbgrp#1{\left\{#1\right\}} \)

Concepts

Modules

Programs (libraries and executables) are structured into modules each of which can be maintained and consumed individually. A module provides a compile-time and run-time protocol for its consumption by other programs. The foremost goal of these libraries are that each of them can be understood, maintained, and consumed on its own.

Names of modules

A module has a canonical name which is of the form [A-Z]([A-Z]|[a-z]|[0-9])* and should follow pascal case conventions. This canonical name gives raise to the naming the executables and libraries, files, and folders of the module as well as the names of functions, types, and macros provided by the module.

Consuming a modules at compile-time

A library with a name Name provides a single header file Name.h and a static library file [Name].lib. To consume a library, you need to make sure both files are found by the compiler of the consuming program. Also note that Name.h may include other header files of the library. Usually, there proper way to consume a library is descibed for supported compilers. Next step is to include the header file where required and link the consuming program with the static library.

Consuming a modules at run-time

A library provides declarations of functions, definitions of types, and macros - in short everything a normal C library offers. There is a restriction though: Functions of a libraries may only be used while a library handle is held. That is, before functions of a library are called, at least one library handle must be acquired by the process. When all calls have terminated and the handle is no longer required the library handle must be relinquished. You can acquire another library handle at any later point of time again.

Acquire a library handle for a library [Name] by calling the function Ring1_[Name]_ModuleHandle Mkx_[name]_ModuleHandle_acquire() and relinquish the library handle by calling void Ring1_[Name]_ModuleHandle_relinquish(Ring1_[Name]_ModuleHandle). Both functions are provided by every library. Acquisition might fail: In that case Ring1_[Name]_ModuleHandle_acquire returns Ring1_[Name]_ModuleHandle_Invalid. Ring_[Name]_ModuleHandle_relinquish silently ignores an invalid library handle.

Example: The filesystem library

The following example demonstrates how to acquire and relinquish a handle for the FileSystem library.

#incude "Ring1/FileSystem.h"
#include <stdlib.h>

int
main
  (
    int argc,
    char **argv
  )
{
  Ring1_FileSystem_ModuleHandle handle = Ring1_FileSystem_ModuleHandle_acquire();
  if (!handle) /* Or equivalently: if (Ring1_FileSystem_ModuleHandle_Invalid == handle) */
  {
    return EXIT_FAILURE;
  }
  Ring1_FileSystem_ModuleHandle_relinquish(handle);
  return EXIT_SUCCESS;
}