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