{"id":16442962,"url":"https://github.com/tristan957/libmerr","last_synced_at":"2025-03-23T08:32:02.943Z","repository":{"id":174683533,"uuid":"612057877","full_name":"tristan957/libmerr","owner":"tristan957","description":"C99+ library for error information","archived":false,"fork":false,"pushed_at":"2024-12-30T21:57:16.000Z","size":35,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-15T08:37:13.146Z","etag":null,"topics":["c","errors"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tristan957.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSES/Apache-2.0.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-10T05:23:08.000Z","updated_at":"2024-12-30T21:57:18.000Z","dependencies_parsed_at":"2023-07-07T13:16:10.762Z","dependency_job_id":"fab71a12-4947-4dfe-ae64-ce1ff7aa58b5","html_url":"https://github.com/tristan957/libmerr","commit_stats":null,"previous_names":["tristan957/libmerr"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristan957%2Flibmerr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristan957%2Flibmerr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristan957%2Flibmerr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristan957%2Flibmerr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tristan957","download_url":"https://codeload.github.com/tristan957/libmerr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245078067,"owners_count":20557274,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","errors"],"created_at":"2024-10-11T09:19:07.515Z","updated_at":"2025-03-23T08:32:02.474Z","avatar_url":"https://github.com/tristan957.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!--\nSPDX-License-Identifier: Apache-2.0 OR MIT\n\nSPDX-FileCopyrightText: 2023 Tristan Partin \u003ctristan@partin.io\u003e\n--\u003e\n\n# `libmerr`\n\n`libmerr` is a C99+ static library that is meant to be embedded in other\nlibraries or executables for the purposes of tracking error information.\n\nC is a notoriously bad language when it comes to error handling. Many\nsystem/POSIX/UNIX APIs will return various values on error or set\n[`errno(3)`](https://linux.die.net/man/3/errno). An integer error value can\ngenerally tell you the reason an error occurred, but it doesn't provide extra\ninformation like file, line number, or any extra context.\n\nTo overcome this issue, the authors of the\n[Heterogeneous-Memory Storage Engine](https://github.com/hse-project/hse) (HSE)\ncame up with `merr`. An `merr_t` is an error value which can encode all this\ninformation in just a 64-bit unsigned integer. This repository is essentially a\ncopy and paste of what exists within HSE. Because of that you will see the\noriginal `Micron Technology, Inc.` copyright in addition to the dual licensing\nof this code as `Apache-2.0` or `MIT` depending on what best fits within your\nconstraints.\n\n## Building/Installing\n\n`libmerr` uses the [Meson](https://mesonbuild.com) build system.\n\n```shell\nmeson setup build\nmeson compile -C build\nmeson install -C build\n```\n\n## Plain Builds\n\n`libmerr` supports a `plain` build alongside the regular build. The `plain`\nbuild is essentially just a wrapper around `(ctx \u003c\u003c 32 | errno)`. It exists in\nthe case that you want `merr()` call sites to be the same regardless of whether\nthe compiler supports the prerequisites of `libmerr`, such as the `aligned` and\n`section` function attributes. The build system will automatically pick whether\nyou need the plain build or not based on the compiler. However, a build option\n`-Dplain=enabled/auto/disabled` is available in the event you want to be\nexplicit.\n\nHere are the relevant differences between a regular build and a `plain` build:\n\n```c\n/* Layout of merr_t:\n *\n *   If the compiler supports both the section and aligned attributes and\n *   MERR_PLAIN was not requested:\n *\n *     Field   #bits  Description\n *     ------  -----  ----------\n *     63..48   16    signed offset of (merr_curr_file - merr_base) / MERR_MAX_PATH_LENGTH\n *     47..32   16    line number\n *     31..16   16    context\n *     15..0    16    error value\n *\n *   If the compiler does not support either of the section or aligned\n *   attributes, or MERR_PLAIN was requested:\n *\n *     Field   #bits  Description\n *     ------  -----  ----------\n *     63..32   32    context\n *     31..0    32    error value\n */\n```\n\n`plain` builds will not have any file or line number information attached to an\n`merr_t`. Therefore, `merr_file()` and `merr_lineno()` do not exist.\n`merr_strerror()` and `merr_strerrorx()` will not be able to output the file and\nline number of the error.\n\n## Exposing `merr_t`\n\nExposing `merr_t` directly in public APIs can be an issue if your library can be\nshared. If your library can only be consumed statically, you can ignore the\nfollowing paragraph, though it is still a good practice instead of making\n`merr_t` viral. If you choose this route, remember to tell consumers of your\nlibrary to also depend on `libmerr`.\n\n```meson\nlibmerr_dep = dependency('libmerr')\nexample_includes = include_directories('.')\n\nlib = static_library(\n  'example',\n  'libexample.c',\n  include_directions: example_includes,\n  dependencies: libmerr_dep\n)\nlib_dep = declare_dependency(\n  link_with: lib,\n  include_directories: example_includes,\n  dependencies: libmerr_dep\n)\n\npkg = import('pkgconfig')\npkg.generate(lib, requires: 'libmerr')\n```\n\n---\n\nThe first thing a consumer should do is create their own error type. Your error\ntype must be compatible with `merr_t`. `libmerr` stores the type as a pkg-config\nvariable. Or you can just know that it is always an `int64_t`.\n\n\u003c!-- Keep the above type in sync! --\u003e\n\nThe Meson way of retrieving the variable and using it:\n\n```meson\nlibmerr_dep = dependency('libmerr')\nmerr_type = libmerr_dep.get_variable('merr_type')\n\nconfigure_file(\n  input: 'libexample.h.in',\n  output: 'libexample.h',\n  configuration: {\n    'MERR_TYPE': merr_type,\n  }\n)\n```\n\nThe command line way of retrieving the variable:\n\n```shell\npkg-config --variable=merr_type libmerr\n```\n\nThe C (or C++) boilerplate for creating your own error type should be something\nlike the following:\n\n```c\n// libexample.h\n\n#include \u003cstddef.h\u003e\n#include \u003cstdint.h\u003e\n\n// You could just use int64_t here.\ntypedef @MERR_TYPE@ example_err_t;\n\nint16_t\nexample_err_ctx(example_err_t err);\n\nint\nexample_err_errno(example_err_t err);\n\nconst char *\nexample_err_file(example_err_t err);\n\nuint16_t\nexample_err_lineno(example_err_t err);\n\nsize_t\nexample_err_strerror(example_err_t err, char *buf, size_t buf_sz);\n```\n\n```c\n// libexample.c\n\n#include \u003cstddef.h\u003e\n#include \u003cstdint.h\u003e\n\n#include \u003cmerr.h\u003e\n\n#include \u003clibexample.h\u003e\n\nstatic const char *\nctx_strerror(const int ctx)\n{\n  switch (ctx) {\n  case 0:\n    /// ...\n  }\n\n  return NULL;\n}\n\nint16_t // or int32_t in the case of a plain build\nexample_err_ctx(example_err_t err)\n{\n  return merr_ctx(err);\n}\n\nint\nexample_err_errno(example_err_t err)\n{\n  return merr_errno(err);\n}\n\nconst char *\nexample_err_file(example_err_t err)\n{\n  return merr_file(err);\n}\n\nuint16_t\nexample_err_lineno(example_err_t err)\n{\n  return merr_lineno(err);\n}\n\nsize_t\nexample_err_strerror(example_err_t err, char *buf, size_t buf_sz)\n{\n  return merr_sterrorx(err, buf, buf_sz, ctx_strerror);\n}\n```\n\nRemember that you can change return types in your functions. For instance, you\ncould return an `enum` instead of an `int16_t` (or `int32_t` in the case of a\n`plain` build) for `example_err_ctx()`.\n\n## Limits\n\n`libmerr` cannot be used reliably if any of the following conditions are met:\n\n_Only the first and last bullets apply for_ `plain` _builds_.\n\n- Source files longer than `UINT16_MAX` lines.\n- More than 1024 files in the consuming project (This limit is dependent on max\n  path length, `(1 \u003c\u003c bit width of file offset) / MERR_MAX_PATH_LENGTH`).\n- Paths longer than `MERR_MAX_PATH_LENGTH` characters (Recommended to use\n  `-fmacro-prefix-map` or an equivalent).\n- Error values other than those in `errno(3)`. This could be changed in the\n  future to be generic if anyone ever wanted this capability.\n\n## Warnings\n\n- Do not try to use this library as a shared library. It will not work. _This\n  would work for_ `plain` _builds, but it is not a supported configuration\n  because it is strongly encouraged to wrap_ `merr_t` _as done in the example\n  above._\n  - For Meson users, I highly suggest using a wrap file to integrate this into\n    your project.\n\n## Contributing\n\nAll commits must be signed (`git commit --signoff`) indicating that you agree to\nthe [Developer Certificate of Origin](http://developercertificate.org).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftristan957%2Flibmerr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftristan957%2Flibmerr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftristan957%2Flibmerr/lists"}