• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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