summaryrefslogtreecommitdiff
path: root/doc/macros.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/macros.rst')
-rw-r--r--doc/macros.rst149
1 files changed, 149 insertions, 0 deletions
diff --git a/doc/macros.rst b/doc/macros.rst
new file mode 100644
index 0000000..752f81e
--- /dev/null
+++ b/doc/macros.rst
@@ -0,0 +1,149 @@
+======
+Macros
+======
+
+All macros in this section are available through ``#include <libHX/defs.h>``.
+
+Preprocessor
+============
+
+.. code-block:: c
+
+ #define HX_STRINGIFY(s)HX_STRINGIFY
+
+Transforms the expansion of the argument ``s`` into a C string.
+
+
+Sizes
+=====
+
+.. code-block:: c
+
+ #define HXSIZEOF_Z16
+ #define HXSIZEOF_Z32
+ #define HXSIZEOF_Z64
+
+Expands to the size needed for a buffer (including ``\0``) to hold the base-10
+string representation of 16‑, 32‑ or 64‑bit integer (either signed or
+unsigned), respectively.
+
+Locators
+========
+
+.. code-block:: c
+
+ output_type *containerof(input_type *ptr, output_type, member);
+
+ size_t HXsizeof_member(struct_type, member);
+ output_type HXtypeof_member(struct_type, member);
+
+``containerof`` will return a pointer to the struct in which ``ptr`` is
+contained as the given member. (In C++, it is required that the encompassing
+``output_type`` has so-called "standard layout", but to date I have never found
+an implementation where this matters.)
+
+.. code-block:: c
+
+ struct foo {
+ int bar;
+ int baz;
+ };
+
+ static void test(int *ptr)
+ {
+ struct foo *self = containerof(baz, struct foo, baz);
+ }
+
+``HXsizeof_member`` and ``HXtypeof_member`` are shortcuts (mainly for the C
+language) to get the size or type of a named member in a given struct:
+
+.. code-block:: c
+
+ char padding[FIELD_SIZEOF(struct foo, baz)];
+
+In C++, one can simply use ``sizeof(foo::baz)`` and ``decltype(foo::baz)``.
+
+
+Array size
+==========
+
+.. code-block:: c
+
+ size_t ARRAY_SIZE(type array[]); /* implemented as a macro */
+
+Returns the number of elements in array. This only works with true arrays
+(``type[]``), and will fail to compile when passed a pointer-to-element
+(``type *``), which is often used for array access too.
+
+
+Compile-time build checks
+=========================
+
+.. code-block:: c
+
+ int BUILD_BUG_ON_EXPR(bool condition); /* implemented as a macro */
+ void BUILD_BUG_ON(bool condition); /* implemented as a macro */
+
+Causes the compiler to fail when condition evaluates to true. If not
+implemented for a compiler, it will be a no-op. ``BUILD_BUG_ON`` is meant to be
+used as a standalone statement, while ``BUILD_BUG_ON_EXPR`` is for when a check
+is to occur within an expression, that latter of which is useful for within
+macros when one cannot, or does not want to use multiple statements.
+
+.. code-block:: c
+
+ type DEMOTE_TO_PTR(type expr); /* macro */
+
+Changes the type of ``expr`` to pointer type. If ``expr`` is of array type
+class, changes it to a pointer to the first element. If ``expr`` is of function
+type class, changes it to a pointer to the function.
+
+.. code-block:: c
+
+ int main(void);
+ int (*fp)(void);
+ char a[123];
+ DEMOTE_TO_PTR(main); /* yields int (*)(void); */
+ DEMOTE_TO_PTR(fp); /* also yields int (*)(void); */
+ DEMOTE_TO_PTR(a); /* yields char * */
+
+
+UNIX file modes
+===============
+
+.. code-block:: c
+
+ #define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)S_IRUGO
+ #define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)S_IWUGO
+ #define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)S_IXUGO
+ #define S_IRWXUGO (S_IRUGO | S_IWUGO | S_IXUGO)S_IRWXUGO
+
+The defines make it vastly easier to specify permissions for large group of
+users. For example, if one wanted to create a file with the permissions
+``rw-r--r--`` (ignoring the umask in this description), ``S_IRUSR | S_IWUSR``
+can now be used instead of the longer ``S_IRUSR | S_IWUSR | S_IRGRP |
+S_IROTH``.
+
+
+VC runtime format specifiers
+============================
+
+The Microsoft Visual C runtime (a weak libc) uses non-standard format
+specifiers for certain types. Whereas C99 specifies ``z`` for ``size_t`` and
+``ll`` for ``long long``, MSVCRT users must use ``I`` and ``I64`` (forming
+``%Id`` instead of ``%zd`` for ``ssize_t``, for example). libHX provides two
+convenience macros for this:
+
+.. code-block:: c
+
+ #define HX_SIZET_FMT "z" or "I"HX_SIZET_FMT
+ #define HX_LONGLONG_FMT "ll" or "I64"HX_LONGLONG_FMT
+
+These may be used together with ``printf`` or ``scanf``:
+
+.. code-block:: c
+
+ printf("struct timespec is of size %" HX_SIZET_FMT "u\n",
+ sizeof(struct timespec));
+
+Take note that mingw-w64's libc *does* adhere to POSIX and so, %z can be used.