1 // Copyright 2021 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include <stdint.h> 17 18 #include "pw_log_tokenized/config.h" 19 #include "pw_preprocessor/util.h" 20 #include "pw_tokenizer/tokenize.h" 21 22 // TODO(hepler): Remove these includes. 23 #ifdef __cplusplus 24 #include "pw_log_tokenized/metadata.h" 25 #endif // __cplusplus 26 27 #ifdef _PW_LOG_TOKENIZED_GLOBAL_HANDLER_BACKWARDS_COMPAT 28 #include "pw_tokenizer/tokenize_to_global_handler_with_payload.h" 29 #endif // _PW_LOG_TOKENIZED_GLOBAL_HANDLER_BACKWARDS_COMPAT 30 31 #undef _PW_LOG_TOKENIZED_GLOBAL_HANDLER_BACKWARDS_COMPAT 32 33 // This macro implements PW_LOG using pw_tokenizer. Users must implement 34 // pw_log_tokenized_HandleLog(uint32_t metadata, uint8_t* buffer, size_t size). 35 // The log level, module token, and flags are packed into the metadata argument. 36 // 37 // Two strings are tokenized in this macro: 38 // 39 // - The log format string, tokenized in the default tokenizer domain. 40 // - Log module name, masked to 16 bits and tokenized in the 41 // "pw_log_module_names" tokenizer domain. 42 // 43 // To use this macro, implement pw_log_tokenized_HandleLog(), which is defined 44 // in pw_log_tokenized/handler.h. The log metadata can be accessed using 45 // pw::log_tokenized::Metadata. For example: 46 // 47 // extern "C" void pw_log_tokenized_HandleLog( 48 // uint32_t payload, const uint8_t data[], size_t size) { 49 // pw::log_tokenized::Metadata metadata(payload); 50 // 51 // if (metadata.level() >= kLogLevel && ModuleEnabled(metadata.module())) { 52 // EmitLogMessage(data, size, metadata.flags()); 53 // } 54 // } 55 // 56 #define PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD( \ 57 level, module, flags, message, ...) \ 58 do { \ 59 _PW_TOKENIZER_CONST uintptr_t _pw_log_tokenized_module_token = \ 60 PW_TOKENIZE_STRING_MASK("pw_log_module_names", \ 61 ((1u << PW_LOG_TOKENIZED_MODULE_BITS) - 1u), \ 62 module); \ 63 const uintptr_t _pw_log_tokenized_level = level; \ 64 PW_LOG_TOKENIZED_ENCODE_MESSAGE( \ 65 (_PW_LOG_TOKENIZED_LEVEL(_pw_log_tokenized_level) | \ 66 _PW_LOG_TOKENIZED_MODULE(_pw_log_tokenized_module_token) | \ 67 _PW_LOG_TOKENIZED_FLAGS(flags) | _PW_LOG_TOKENIZED_LINE(__LINE__)), \ 68 PW_LOG_TOKENIZED_FORMAT_STRING(message), \ 69 __VA_ARGS__); \ 70 } while (0) 71 72 // If the level field is present, clamp it to the maximum value. 73 #if PW_LOG_TOKENIZED_LEVEL_BITS == 0 74 #define _PW_LOG_TOKENIZED_LEVEL(value) ((uintptr_t)0) 75 #else 76 #define _PW_LOG_TOKENIZED_LEVEL(value) \ 77 (value < ((uintptr_t)1 << PW_LOG_TOKENIZED_LEVEL_BITS) \ 78 ? value \ 79 : ((uintptr_t)1 << PW_LOG_TOKENIZED_LEVEL_BITS) - 1) 80 #endif // PW_LOG_TOKENIZED_LEVEL_BITS 81 82 // If the line number field is present, shift it to its position. Set it to zero 83 // if the line number is too large for PW_LOG_TOKENIZED_LINE_BITS. 84 #if PW_LOG_TOKENIZED_LINE_BITS == 0 85 #define _PW_LOG_TOKENIZED_LINE(line) ((uintptr_t)0) 86 #else 87 #define _PW_LOG_TOKENIZED_LINE(line) \ 88 ((uintptr_t)(line < (1 << PW_LOG_TOKENIZED_LINE_BITS) ? line : 0) \ 89 << PW_LOG_TOKENIZED_LEVEL_BITS) 90 #endif // PW_LOG_TOKENIZED_LINE_BITS 91 92 // If the flags field is present, mask it and shift it to its position. 93 #if PW_LOG_TOKENIZED_FLAG_BITS == 0 94 #define _PW_LOG_TOKENIZED_FLAGS(value) ((uintptr_t)0) 95 #else 96 #define _PW_LOG_TOKENIZED_FLAGS(value) \ 97 (((uintptr_t)(value) & (((uintptr_t)1 << PW_LOG_TOKENIZED_FLAG_BITS) - 1)) \ 98 << (PW_LOG_TOKENIZED_LEVEL_BITS + PW_LOG_TOKENIZED_LINE_BITS)) 99 #endif // PW_LOG_TOKENIZED_FLAG_BITS 100 101 // If the module field is present, shift it to its position. 102 #if PW_LOG_TOKENIZED_MODULE_BITS == 0 103 #define _PW_LOG_TOKENIZED_MODULE(value) ((uintptr_t)0) 104 #else 105 #define _PW_LOG_TOKENIZED_MODULE(value) \ 106 ((uintptr_t)(value) << ((PW_LOG_TOKENIZED_LEVEL_BITS + \ 107 PW_LOG_TOKENIZED_LINE_BITS + \ 108 PW_LOG_TOKENIZED_FLAG_BITS))) 109 #endif // PW_LOG_TOKENIZED_MODULE_BITS 110 111 #define PW_LOG_TOKENIZED_ENCODE_MESSAGE(metadata, format, ...) \ 112 do { \ 113 PW_TOKENIZE_FORMAT_STRING( \ 114 PW_TOKENIZER_DEFAULT_DOMAIN, UINT32_MAX, format, __VA_ARGS__); \ 115 _pw_log_tokenized_EncodeTokenizedLog(metadata, \ 116 _pw_tokenizer_token, \ 117 PW_TOKENIZER_ARG_TYPES(__VA_ARGS__) \ 118 PW_COMMA_ARGS(__VA_ARGS__)); \ 119 } while (0) 120 121 PW_EXTERN_C_START 122 123 void _pw_log_tokenized_EncodeTokenizedLog(uint32_t metadata, 124 pw_tokenizer_Token token, 125 pw_tokenizer_ArgTypes types, 126 ...); 127 128 PW_EXTERN_C_END 129