libk  Diff

Differences From Artifact [4cea7e271a]:

To Artifact [d44feffbdd]:


    31     31   
    32     32   libk is designed to fix this (in hindsight) glaring error.
    33     33   
    34     34   however, a common problem with libraries is the proliferation of inordinately long and hard-to-type function names such as `SuperWidget_Widget_Label_Font_Size_Set()`. this may be tolerable in IDEs with robust auto-complete or when referencing a highly-specific, sparsely-used library; it is however completely intolerable in the case of a core library with heavily used functionality.
    35     35   
    36     36   therefore, libk uses two slightly different naming conventions: the **short** convention, for core functions the user will call frequently, and the **full** convention, for less-commonly used functions. the inconvenience of remembering which is which will hopefully be outweighed by the keystrokes (and bytes) saved.
    37     37   
    38         -in the **full** convention, a function's name is prefixed with its module name followed by an underscore. thus, `kfile/open.c` will be invoked as `kfile_open()`.
           38  +in the **full** convention, an identifier's name is prefixed with its module name followed by an underscore. thus, `kgraft/list.c` is invoked as `kgraft_list()`.
    39     39   
    40         -in the **short** convention, the function name is prefixed by the letter `k` followed by the module's "glyph" -- a one- or two-letter sequence that represents the module, usually the first one or two characters. therefore, `kio/write.c` is invoked as `kiowrite`.
           40  +in the **short** convention, identifiers are prefixed by the letter `k` followed by the module's "glyph" -- a one- or two-letter sequence that represents the module, usually the first one or two characters. therefore, `kfile/open.c` is invoked as `kfopen`.
    41     41   
    42     42   which naming convention a module uses should be specified at the top of its documentation. if it uses the short convention, its glyph should be specified as well
    43     43   
           44  +in both naming conventions, the following rules apply:
           45  +
           46  + 1. the possible values of enumeration types are always preceded by the name of the enumeration type and an underscore. for instance, the enum `kschain_kind` has a value named `kschain_kind_block`. **exception:** an enum named `<S>_kind`, where `<S>` is a struct type, may simply use the prefix `<S>_`.
           47  + 2. macros begin with the uppercase letter `K` -- e.g. `Kmacro`. macros that can be defined by the user to alter the behavior of the api should begin with `KF` if they are on/off flags, or `KV` otherwise.
           48  + 3. capital letters are only used in macro prefixes.
           49  + 4. low-level function names are prefixed with the API they call into. for example, the function that performs the POSIX syscall `write` is named `kio_posix_fd_write`.a wrapper around the Windows function `CreateProcess()` might be called `kproc_win_createprocess`.
           50  +
    44     51   ### atoms
    45     52   
    46     53   libk uses the concept of "atoms" (small, regular strings of text) to standardize common references, such as operating systems or processor architectures.
    47     54   
    48     55   #### operating systems
    49     56   
    50     57   these atoms will be used to reference operating systems.
................................................................................
    71     78   
    72     79   these atoms will be used to reference particular system architectures. these will mostly be used in the filenames of assembly code.
    73     80   
    74     81   ## macros
    75     82   
    76     83   libk will not in any circumstance use macros to encode magic numbers, instead using typedef'd enums. all libk macros begin with the uppercase letter `K` -- e.g. `Kmacro`. macros that can be defined by the user to alter the behavior of the api should begin with `KF` if they are on/off flags, or `KV` otherwise. **macros should only be defined by the libk headers if the flag `KFclean` is *not* defined at the time of inclusion.**
    77     84   
           85  +include guards take the form of the bare module name prefixed by `KI`. so to test if `k/term.h` has been included, you could write `#ifdef KIterm`.
           86  +
    78     87   ## languages
    79     88   
    80     89   libk uses only three languages: C (\*.c, \*.h), yasm (\*.s), and make (makefile).
    81     90   
    82     91   other assemblers will probably be necessary for the more exotic targets, however.
    83     92   
    84     93   ## repository structure
................................................................................
    90     99   each function should be kept in a separate file within its module's directory. when OS or architecture-specific code is needed, the file's name should be a list of one or more of the fields [arch, OS, bits, format] separated by a `.` -- for instance, the 32-bit x86 haiku version of a function called `write` defined in assembly would be named `write.x86.haiku.32.s`. however, if a function has an extraordinarily large number of versions, they may instead be stored in a folder with the same name as the function.
    91    100   
    92    101   each module should have a header named the same thing as the module except without the `k` prefix. (e.g. the header for `kio` is `kio/io.h`) located in its folder. this is the header that the end-user will be importing, and should handle any user-defined flags to present the API the user has selected.
    93    102   
    94    103   each module directory should contain a makefile that can build that module. see **makefiles** below. all makefiles should be named `makefile` (**not** `Makefile`).
    95    104   
    96    105   each module should contain a markdown file. this file's name should be the name of the parent directory suffixed with `.md`; for instance, `kterm` should contain the file `kterm/kterm.md`. this file should document the module as thoroughly as possible 
          106  +
          107  +each module may contain any number of files of the name `exe.*.c`. this files will be treated as *tools* by the build system and compiled as executables, rather than libraries. they should be compiled to `out/$module.$tool`
    97    108   
    98    109   the repository root and each module may also contain the directory `misc`. this directory may be used to store miscellaneous data such as ABI references, developer discussions, and roadmaps. if the `misc` directory is deleted, this must not affect the library or build system's function in any way - that is, nothing outside a `misc` folder may reference a `misc` folder or anything inside it, including documentation. the `misc` directory should be removed when its contents are no longer needed. in most cases, the repository wiki and forum should be used instead of the `misc` folder.
    99    110   
   100    111   the folder `arch` in the root of the repository contains syscall tables and ABI implementations for various architectures.
   101    112   
   102    113   ## makefiles
   103    114   
   104    115   libk uses `make` as its build system. makefiles should be handwritten. there will be one global makefile in the root of the repository, and one makefile for each module.
   105    116   
   106    117   each rule should be prefixed with ${OUT}, to allow retargeting of the build-dir with the OUT environment variable. this is particularly important since the makefiles chain.
   107    118   
   108    119   the rest is TBD.
   109    120   
          121  +## design principles
          122  +
          123  +there are four overriding principles that guide the design of libk.
          124  +
          125  + 1. it should be easy to write code that uses it.
          126  + 2. it should be easy to read code that uses it.
          127  + 3. the simple, obvious way of using libk should produce the most optimal code.
          128  + 4. code that uses libk should be idiomatic C.
          129  +
          130  +for these reasons, the codebase follows a number of strict rules.
          131  + 
          132  +### booleans are banned
          133  +there are a number of reasons for this.
          134  +
          135  +the first is simply that the boolean type in C is a bit messy and libk headers are intended to import as few extra files as possible.
          136  +
          137  +the second is that boolean-using code can be hard to read. consider a struct declaration of the form `rule r = { 10, buf, true, false, true }`: the meaning of this declaration is opaque unless you've memorized the structure's definition.
          138  +
          139  +instead, libk uses enums liberally. so the above might be rewritten as e.g.:
          140  +
          141  +    rule r = { 10, buf,
          142  +		rule_kind_undialectical,
          143  +		rule_action_expropriate,
          144  +		rule_target_bourgeoisie
          145  +	};
          146  +
          147  +this makes code much more legible and has the added benefit of making the definitions easier to expand at a later date if new functionality values is needed without breaking the API or ABI.
          148  + 
   110    149   ## build process
   111    150   
   112    151   libk has a number of targets. all files generated by a `make` invocation will be stored in the folder "out" at the root of the repository. this directory may be deleted entirely to clean the repository.
   113    152   
   114         -**defs** will create the directory `out/k/` and populate it with module header files. the `k/` directory shall be suitable to copy to `/usr/include` or similar. these header files will copied by building the `defs` target of each module's makefile.
          153  +**defs** will create the directory `out/k/` and populate it with module header files. the `k/` directory shall be suitable to copy to `/usr/include` or similar. these header files will copied by building the `${OUT}/$(module).h` target of each module's makefile.
   115    154   
   116    155   **libk.so** will build the dynamically linked form of libk, according to the build variables set
   117    156   
   118    157   **libk.a** will build the statically linked form of libk, according to the build variables set
   119    158   
   120    159   **tool** will build the executables used for modules such as `kgraft`.
   121    160