xref: /aosp_15_r20/external/intel-media-driver/cmrtlib/agnostic/share/cm_printf_host.h (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2017, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 #pragma once
23 
24 #include "cm_printf_base.h"
25 
26 #include <string>
27 
28 #define CM_PRINTF(f_, ...) fprintf((f_), __VA_ARGS__)
29 
30 #define PRINT_BUFFER_HEADER_SIZE    32
31 #define PRINT_PAYLOAD_ALIGN         16
32 #define PRINT_HEADER_SIZE           32
33 #define PRINT_FORMAT_STRING_SIZE    128
34 #define CM_PRINT_SIZE_WITH_PAYLOAD(msize) (PRINT_HEADER_SIZE + (msize-1) / PRINT_PAYLOAD_ALIGN * PRINT_PAYLOAD_ALIGN + PRINT_PAYLOAD_ALIGN)
35 
36 /// Structure of header:
37 /// vector<int, 8> header
38 /// [0]: Object type: matrix,vector,scalar,string, or format string.
39 /// [1]: Data type: [u]*int[136]*[6248]_t, float, or double.
40 /// [2]: width
41 /// [3]: height
42 /// [4]: tid
43 /// [5]: reserved3
44 /// [6]: Scalar lower 32bits: [u]*int[13]*[628]_t, float. Lower 32bits of double and [u]*int64_t.
45 /// [7]: Scalar upper 32bits: Upper 32bits of double and [u]*int64_t.
46 
47 typedef struct _CM_PRINT_HEADER{
48     unsigned int objectType;
49     unsigned int  dataType;
50     unsigned int  width;
51     unsigned int  height;
52     unsigned int  tid;
53     unsigned int  reserved3;
54     unsigned long long  scalar64;
55 }CM_PRINT_HEADER, *PCM_PRINT_HEADER;
56 
57 enum  PRINT_FMT_STATUS
58 {
59     PF_FAIL    = 0,
60     PF_SUCCESS = 1
61 };
62 
63 // A small class used to contain the state machine used when parsing the printf string
64 // The issue we have to deal with is that there is a format string with some directives in it - the
65 // format string is received as an object from the client as an object in memory
66 // Any arguments are then passed as separate objects in memory. How many objects are required is
67 // determined by the format string.
68 // The cleanest way to deal with this is to use a very simple recursive descent parser on the format
69 // string in order to process the arguments in the correct way
70 // Here's the grammar for printf format strings (using EBNF). Only one format directive is to be
71 // returned from the input at a time:
72 //
73 // format:
74 //       { STRING } directive
75 //
76 //
77 // directive:
78 //       PERCENT flags { width } { PERIOD precision } { length_modifier } conversion
79 //
80 // flags:
81 //       { MINUS } { PLUS } { SPACE } { ZERO } { HASH }
82 //
83 // width:
84 //         INTEGER
85 //       | STAR
86 //
87 // precision:
88 //         INTEGER
89 //       | STAR
90 //
91 // length_modifier:
92 //       hh_MOD | h_MOD | l_MOD | ll_MOD | j_MOD | t_MOD | z_MOD | L_MOD
93 //
94 // conversion:
95 //         PERCENT
96 //       | c_CONV
97 //       | s_CONV
98 //       | d_CONV
99 //       | i_CONV
100 //       | o_CONV
101 //       | x_CONV
102 //       | X_CONV
103 //       | u_CONV
104 //       | f_CONV
105 //       | F_CONV
106 //       | e_CONV
107 //       | E_CONV
108 //       | a_CONV
109 //       | A_CONV
110 //       | g_CONV
111 //       | G_CONV
112 //       | n_CONV
113 //       | p_CONV
114 //
115 // STRING    : [any ASCII character that isn't a %]+
116 // PERCENT   : '%'
117 // MINUS     : '-'
118 // PLUS      : '+'
119 // SPACE     : ' '
120 // ZERO      : '0'
121 // INTEGER   : [
122 // PERIOD    : '.'
123 // HASH      : '#'
124 // hh_MOD    : 'hh'
125 // h_MOD     : 'h'
126 // l_MOD     : 'l'
127 // ll_MOD    : 'll'
128 // j_MOD     : 'j'
129 // z_MOD     : 'z'
130 // t_MOD     : 't'
131 // L_MOD     : 'L'
132 // STAR      : '*'
133 // c_CONV    : 'c'
134 // s_CONV    : 's'
135 // d_CONV    : 'd'
136 // i_CONV    : 'i'
137 // o_CONV    : 'o'
138 // x_CONV    : 'x'
139 // X_CONV    : 'X'
140 // u_CONV    : 'u'
141 // f_CONV    : 'f'
142 // F_CONV    : 'F'
143 // e_CONV    : 'e'
144 // E_CONV    : 'E'
145 // a_CONV    : 'a'
146 // A_CONV    : 'A'
147 // g_CONV    : 'g'
148 // G_CONV    : 'G'
149 // n_CONV    : 'n'
150 // p_CONV    : 'p'
151 
152 class PFParser
153 {
154 public:
PFParser(FILE * streamout)155     PFParser(FILE* streamout) : m_inSpec(false), m_inputStart(nullptr), m_currLoc(nullptr), m_argsExpected(0),
156                  m_numMultArg(0), m_unsupported(false), m_error(false), m_streamOut(streamout) {};
SetStart(char * start)157     void SetStart(char *start)
158     {
159         m_inputStart= m_currLoc = start;
160         // Prime the system with the first token
161         getToken();
162     }
163     void DumpMemory(unsigned char * memory);
164     void Flush(void);
165 
166 protected:
167 private:
168     class Token
169     {
170     public:
171         enum TokenType { _None_, Error,
172                          String, Percent, Minus, Plus, Space, Zero, Integer, Period, Hash, Star,
173                          hh_Mod, h_Mod, l_Mod, ll_Mod, j_Mod, z_Mod, t_Mod, L_Mod,
174                          c_Conv, s_Conv, d_Conv, i_Conv, o_Conv, x_Conv, X_Conv, u_Conv, f_Conv,
175                          F_Conv, e_Conv, E_Conv, a_Conv, A_Conv, g_Conv, G_Conv, n_Conv, p_Conv,
176                          End
177         };
178 
Token()179         Token() : tokenType(_None_), tokenInt(0) {};
180         bool operator==(const Token &other) const {
181             return tokenType == other.tokenType;
182         }
183         bool operator==(const TokenType &other) const {
184             return tokenType == other;
185         }
186         bool operator!=(const Token &other) const {
187             return tokenType != other.tokenType;
188         }
189         bool operator!=(const TokenType &other) const {
190             return tokenType != other;
191         }
192 
193         TokenType tokenType;
194         std::string tokenString;
195         int tokenInt;
196     };
197 
198     bool     m_inSpec;      // Mode for lexer - in spec mode or not
199     Token    m_currToken;   // The currently lexed token
200     Token    m_prevToken;   // The previously lexed token
201     char     *m_inputStart; // The start of the input string
202     char     *m_currLoc;    // The current point of processing
203     int      m_argsExpected; // For multi-arg format directives - how many still to process
204     int      m_numMultArg;   // Total number of multi-arg format directives in total
205     int      m_args[2];      // Up to 2 int args can be used in multi-arg format directives
206     bool     m_unsupported;  // Has the latest parsed format directive contained unsupported
207                             // directives (VS doesn't support them all so we can't print them)
208     bool     m_error;        // Error in latest parsed format directive
209     FILE     *m_streamOut;   // Output stream for kernel print
210 
211     PRINT_FMT_STATUS GetNextFmtToken(char * tkn, size_t size);
212     bool outputToken(const char *tkn, PCM_PRINT_HEADER header);
213     void getToken(void);
reset(void)214     void reset(void)
215     {
216         m_inputStart = m_currLoc;
217         m_unsupported = false;
218         m_error = false;
219         m_numMultArg = m_argsExpected = 0;
220     }
221 
error()222     void error()
223     {
224         // We don't throw an error in this case
225         // Just set the error flag
226         m_error = true;
227     }
228 
229     bool accept(Token::TokenType s);
230     bool expect(Token::TokenType s);
231     int  format(void); // This function returns the number of args for the next format 0,1,2 or 3
232     int  directive(void);
233     void flags(void);
234     int  width(void);
235     int  precision(void);
236     void length_modifier(void);
237     int  conversion(void);
238 };
239 
240 void DumpAllThreadOutput( FILE *streamOut, unsigned char * dumpMem, size_t buffersize);
241