/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <---- Copyright (c) 2014-2015 Datalight, Inc. All Rights Reserved Worldwide. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; use version 2 of the License. This program is distributed in the hope that it will be useful, but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Businesses and individuals that for commercial or other reasons cannot comply with the terms of the GPLv2 license may obtain a commercial license before incorporating Reliance Edge into proprietary software for distribution in any form. Visit http://www.datalight.com/reliance-edge for more information. */ /** @file @brief This header contains macros which deviate from MISRA C:2012 */ #ifndef REDDEVIATIONS_H #define REDDEVIATIONS_H /** @brief Append a suffix to a constant so that it is an unsigned 64-bit value. Usages of this macro deviate from MISRA C:2012 Rule 1.2 (advisory). The rule prohibits the use of language extensions. The ULL suffix became part of the C standard with C99. Since this code base adheres to C89, use of this suffix is a language extension. Reliance Edge needs to deal with 64-bit quantities, which by convention are explicitly suffixed. In at least one case, with the INODE_SIZE_MAX macro, the code needs a way to force a constant to be 64-bits even though its value is not so large that it would be automatically promoted to 64-bits. Thus the need for this macro and the deviation. In practice, the ULL suffix has proven to be a nearly universal extension among C89 compilers. As rule 19.2 is advisory, a deviation record is not required. This notice is the only record of the deviation. PC-Lint does not issue an error for this deviation so there is no error inhibition option. Usages of this macro also deviate from MISRA C:2012 Rule 20.10 (advisory). The rule prohibits use of the ## preprocessor operator. The code is not obscure, and the operator is used only once, so this is deemed to be safe. As rule 20.10 is advisory, a deviation record is not required. This notice is the only record of the deviation. Consistent use of this macro, even in non MISRA C code, is encouraged to make it easier to search for 64-bit values. */ #define UINT64_SUFFIX(number) (number##ULL) /** @brief Append a suffix to a constant so that it is a signed 64-bit value. Usages of this macro deviate from MISRA C:2012 Rule 1.2 (advisory). See the description of UINT64_SUFFIX() for details. Usages of this macro deviate from MISRA C:2012 Rule 20.10 (advisory). See the description of UINT64_SUFFIX() for details. */ #define INT64_SUFFIX(number) (number##LL) /** @brief Cast a pointer to a const uint8_t pointer. All usages of this macro deviate from MISRA C:2012 Rule 11.5 (advisory). Because there are no alignment requirements for a uint8_t pointer, this is safe. However, it is technically a deviation from the rule. As Rule 11.5 is advisory, a deviation record is not required. This notice and the PC-Lint error inhibition option are the only records of the deviation. */ #define CAST_VOID_PTR_TO_CONST_UINT8_PTR(PTR) ((const uint8_t *)(PTR)) /** @brief Cast a pointer to a uint8_t pointer. All usages of this macro deviate from MISRA C:2012 Rule 11.5 (advisory). Because there are no alignment requirements for a uint8_t pointer, this is safe. However, it is technically a deviation from the rule. As Rule 11.5 is advisory, a deviation record is not required. This notice and the PC-Lint error inhibition option are the only records of the deviation. */ #define CAST_VOID_PTR_TO_UINT8_PTR(PTR) ((uint8_t *)(PTR)) /** @brief Cast a pointer to a const uint32_t pointer. Usages of this macro may deviate from MISRA C:2012 Rule 11.5 (advisory). It is only used in cases where the pointer is known to be aligned, and thus it is safe to do so. As Rule 11.5 is advisory, a deviation record is not required. This notice and the PC-Lint error inhibition option are the only records of the deviation. Usages of this macro may deviate from MISRA C:2012 Rule 11.3 (required). As Rule 11.3 is required, a separate deviation record is required. Regarding the cast to (const void *): this is there to placate some compilers which emit warnings when a type with lower alignment requirements (such as const uint8_t *) is cast to a type with higher alignment requirements. In the places where this macro is used, the pointer is checked to be of sufficient alignment. */ #define CAST_CONST_UINT32_PTR(PTR) ((const uint32_t *)(const void *)(PTR)) /** @brief Cast a pointer to a pointer to (void **). Usages of this macro deviate from MISRA C:2012 Rule 11.3 (required). It is only used for populating a node structure pointer with a buffer pointer. Buffer pointers are 8-byte aligned, thus it is safe to do so. As Rule 11.3 is required, a separate deviation record is required. */ #define CAST_VOID_PTR_PTR(PTRPTR) ((void **)(PTRPTR)) /** @brief Create a two-dimensional byte array which is safely aligned. Usages of this macro deviate from MISRA C:2012 Rule 19.2 (advisory). A union is required to force alignment of the block buffers, which are used to access metadata nodes, which must be safely aligned for 64-bit types. As rule 19.2 is advisory, a deviation record is not required. This notice and the PC-Lint error inhibition option are the only records of the deviation. */ #define ALIGNED_2D_BYTE_ARRAY(un, nam, size1, size2) \ union \ { \ uint8_t nam[size1][size2]; \ uint64_t DummyAlign; \ } un /** @brief Determine whether RedMemMove() must copy memory in the forward direction, instead of in the reverse. In order to copy between overlapping memory regions, RedMemMove() must copy forward if the destination memory is lower, and backward if the destination memory is higher. Failure to do so would yield incorrect results. The only way to make this determination without gross inefficiency is to use pointer comparison. Pointer comparisons are undefined unless both pointers point within the same object or array (or one element past the end of the array); see section 6.3.8 of ANSI C89. While RedMemMove() is normally only used when memory regions overlap, which would not result in undefined behavior, it (like memmove()) is supposed to work even for non- overlapping regions, which would make this function invoke undefined behavior. Experience has shown the pointer comparisons of this sort behave intuitively on common platforms, even though the behavior is undefined. For those platforms where this is not the case, this implementation of memmove() should be replaced with an alternate one. Usages of this macro deviate from MISRA-C:2012 Rule 18.3 (required). As Rule 18.3 is required, a separate deviation record is required. */ #define MEMMOVE_MUST_COPY_FORWARD(dest, src) ((dest) < (src)) /** @brief Cast a pointer to a (const DIRENT *). Usages of this macro deviate from MISRA-C:2012 Rule 11.3 (required). It is used for populating a directory entry structure pointer with a buffer pointer. Buffer pointers are 8-byte aligned, and DIRENT only requires 4-byte alignment, thus the typecast is safe. As Rule 11.3 is required, a separate deviation record is required. */ #define CAST_CONST_DIRENT_PTR(PTR) ((const DIRENT *)(PTR)) /** @brief Determine whether a pointer is aligned. A pointer is aligned if its address is an even multiple of ::REDCONF_ALIGNMENT_SIZE. This is used in the slice-by-8 RedCrc32Update() function, which needs to know whether a pointer is aligned, since the slice-by-8 algorithm needs to access the memory in an aligned fashion, and if the pointer is not aligned, this can result in faults or suboptimal performance (depending on platform). There is no way to perform this check without deviating from MISRA C rules against casting pointers to integer types. Usage of this macro deviates from MISRA C:2012 Rule 11.4 (advisory). The main rationale the rule cites against converting pointers to integers is that the chosen integer type may not be able to represent the pointer; this is a non-issue here since we use uintptr_t. The text says the rule still applies when using uintptr_t due to concern about unaligned pointers, but that is not an issue here since the integer value of the pointer is not saved and not converted back into a pointer and dereferenced. The result of casting a pointer to a sufficiently large integer is implementation-defined, but macros similar to this one have been used by Datalight for a long time in a wide variety of environments and they have always worked as expected. As Rule 11.4 is advisory, a deviation record is not required. This notice and the PC-Lint error inhibition option are the only records of the deviation. @note PC-Lint also thinks this macro as it is used below violates Rule 11.6 (required). This is a false positive, since Rule 11.6 only applies to void pointers. Below, we use it on a pointer-to-object (uint8_t *), which is covered by Rule 11.4. */ #define IS_ALIGNED_PTR(ptr) (((uintptr_t)(ptr) & (REDCONF_ALIGNMENT_SIZE - 1U)) == 0U) #endif