codegen_c.h (10127B)
1 #ifndef CODEGEN_C_H 2 #define CODEGEN_C_H 3 4 #include <assert.h> 5 #include <stdarg.h> 6 7 #include "symbols.h" 8 #include "parser.h" 9 #include "codegen.h" 10 11 /* -DFLATCC_PORTABLE may help if inttypes.h is missing. */ 12 #ifndef PRId64 13 #include <inttypes.h> 14 #endif 15 16 #define __FLATCC_ERROR_TYPE "INTERNAL_ERROR_UNEXPECTED_TYPE" 17 18 #ifndef gen_panic 19 #define gen_panic(context, msg) fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg), assert(0), exit(-1) 20 #endif 21 22 23 static inline void token_name(fb_token_t *t, int *n, const char **s) { 24 *n = (int)t->len; 25 *s = t->text; 26 } 27 28 typedef char fb_symbol_text_t[FLATCC_NAME_BUFSIZ]; 29 typedef struct fb_scoped_name fb_scoped_name_t; 30 31 /* Should be zeroed because scope is cached across updates. */ 32 struct fb_scoped_name { 33 fb_symbol_text_t text; 34 fb_scope_t *scope; 35 int scope_len, len, total_len; 36 }; 37 38 #define fb_clear(x) (memset(&(x), 0, sizeof(x))) 39 40 /* Returns length or -1 if length exceeds namespace max. */ 41 int __flatcc_fb_copy_scope(fb_scope_t *scope, char *buf); 42 #define fb_copy_scope __flatcc_fb_copy_scope 43 44 void __flatcc_fb_scoped_symbol_name(fb_scope_t *scope, fb_symbol_t *sym, fb_scoped_name_t *sn); 45 #define fb_scoped_symbol_name __flatcc_fb_scoped_symbol_name 46 47 static inline void fb_compound_name(fb_compound_type_t *ct, fb_scoped_name_t *sn) 48 { 49 fb_scoped_symbol_name(ct->scope, &ct->symbol, sn); 50 } 51 52 static inline void symbol_name(fb_symbol_t *sym, int *n, const char **s) { 53 token_name(sym->ident, n, s); 54 } 55 56 static inline const char *scalar_type_ns(fb_scalar_type_t scalar_type, const char *ns) 57 { 58 return scalar_type == fb_bool ? ns : ""; 59 } 60 61 static inline const char *scalar_type_prefix(fb_scalar_type_t scalar_type) 62 { 63 const char *tname; 64 switch (scalar_type) { 65 case fb_ulong: 66 tname = "uint64"; 67 break; 68 case fb_uint: 69 tname = "uint32"; 70 break; 71 case fb_ushort: 72 tname = "uint16"; 73 break; 74 case fb_char: 75 tname = "char"; 76 break; 77 case fb_ubyte: 78 tname = "uint8"; 79 break; 80 case fb_bool: 81 tname = "bool"; 82 break; 83 case fb_long: 84 tname = "int64"; 85 break; 86 case fb_int: 87 tname = "int32"; 88 break; 89 case fb_short: 90 tname = "int16"; 91 break; 92 case fb_byte: 93 tname = "int8"; 94 break; 95 case fb_float: 96 tname = "float"; 97 break; 98 case fb_double: 99 tname = "double"; 100 break; 101 default: 102 gen_panic(0, "internal error: unexpected type during code generation"); 103 tname = __FLATCC_ERROR_TYPE; 104 break; 105 } 106 return tname; 107 } 108 109 static inline const char *scalar_type_name(fb_scalar_type_t scalar_type) 110 { 111 const char *tname; 112 switch (scalar_type) { 113 case fb_ulong: 114 tname = "uint64_t"; 115 break; 116 case fb_uint: 117 tname = "uint32_t"; 118 break; 119 case fb_ushort: 120 tname = "uint16_t"; 121 break; 122 case fb_char: 123 tname = "char"; 124 break; 125 case fb_ubyte: 126 tname = "uint8_t"; 127 break; 128 case fb_bool: 129 tname = "bool_t"; 130 break; 131 case fb_long: 132 tname = "int64_t"; 133 break; 134 case fb_int: 135 tname = "int32_t"; 136 break; 137 case fb_short: 138 tname = "int16_t"; 139 break; 140 case fb_byte: 141 tname = "int8_t"; 142 break; 143 case fb_float: 144 tname = "float"; 145 break; 146 case fb_double: 147 tname = "double"; 148 break; 149 default: 150 gen_panic(0, "internal error: unexpected type during code generation"); 151 tname = __FLATCC_ERROR_TYPE; 152 break; 153 } 154 return tname; 155 } 156 157 static inline const char *scalar_vector_type_name(fb_scalar_type_t scalar_type) 158 { 159 const char *tname; 160 switch (scalar_type) { 161 case fb_ulong: 162 tname = "uint64_vec_t"; 163 break; 164 case fb_uint: 165 tname = "uint32_vec_t"; 166 break; 167 case fb_ushort: 168 tname = "uint16_vec_t"; 169 break; 170 case fb_char: 171 tname = "char_vec_t"; 172 break; 173 case fb_ubyte: 174 tname = "uint8_vec_t"; 175 break; 176 case fb_bool: 177 tname = "uint8_vec_t"; 178 break; 179 case fb_long: 180 tname = "int64_vec_t"; 181 break; 182 case fb_int: 183 tname = "int32_vec_t"; 184 break; 185 case fb_short: 186 tname = "int16_vec_t"; 187 break; 188 case fb_byte: 189 tname = "int8_vec_t"; 190 break; 191 case fb_float: 192 tname = "float_vec_t"; 193 break; 194 case fb_double: 195 tname = "double_vec_t"; 196 break; 197 default: 198 gen_panic(0, "internal error: unexpected type during code generation"); 199 tname = __FLATCC_ERROR_TYPE; 200 break; 201 } 202 return tname; 203 } 204 205 /* Only for integers. */ 206 static inline const char *scalar_cast(fb_scalar_type_t scalar_type) 207 { 208 const char *cast; 209 switch (scalar_type) { 210 case fb_ulong: 211 cast = "UINT64_C"; 212 break; 213 case fb_uint: 214 cast = "UINT32_C"; 215 break; 216 case fb_ushort: 217 cast = "UINT16_C"; 218 break; 219 case fb_char: 220 cast = "char"; 221 break; 222 case fb_ubyte: 223 cast = "UINT8_C"; 224 break; 225 case fb_bool: 226 cast = "UINT8_C"; 227 break; 228 case fb_long: 229 cast = "INT64_C"; 230 break; 231 case fb_int: 232 cast = "INT32_C"; 233 break; 234 case fb_short: 235 cast = "INT16_C"; 236 break; 237 case fb_byte: 238 cast = "INT8_C"; 239 break; 240 default: 241 gen_panic(0, "internal error: unexpected type during code generation"); 242 cast = ""; 243 break; 244 } 245 return cast; 246 } 247 248 typedef char fb_literal_t[100]; 249 250 static inline size_t print_literal(fb_scalar_type_t scalar_type, const fb_value_t *value, fb_literal_t literal) 251 { 252 const char *cast; 253 254 switch (value->type) { 255 case vt_uint: 256 cast = scalar_cast(scalar_type); 257 return (size_t)sprintf(literal, "%s(%"PRIu64")", cast, (uint64_t)value->u); 258 break; 259 case vt_int: 260 cast = scalar_cast(scalar_type); 261 return (size_t)sprintf(literal, "%s(%"PRId64")", cast, (int64_t)value->i); 262 break; 263 case vt_bool: 264 cast = scalar_cast(scalar_type); 265 return (size_t)sprintf(literal, "%s(%u)", cast, (unsigned)value->b); 266 break; 267 case vt_float: 268 /* 269 * .9g ensures sufficient precision in 32-bit floats and 270 * .17g ensures sufficient precision for 64-bit floats (double). 271 * The '#' forces a decimal point that would not be printed 272 * for integers which would result in the wrong type in C 273 * source. 274 */ 275 if (scalar_type == fb_float) { 276 return (size_t)sprintf(literal, "%#.9gf", (float)value->f); 277 } else { 278 return (size_t)sprintf(literal, "%#.17g", (double)value->f); 279 } 280 break; 281 default: 282 gen_panic(0, "internal error: unexpected type during code generation"); 283 *literal = 0; 284 return 0; 285 } 286 } 287 288 static inline const char *scalar_suffix(fb_scalar_type_t scalar_type) 289 { 290 const char *suffix; 291 switch (scalar_type) { 292 case fb_ulong: 293 suffix = "ULL"; 294 break; 295 case fb_uint: 296 suffix = "UL"; 297 break; 298 case fb_ushort: 299 suffix = "U"; 300 break; 301 case fb_char: 302 suffix = ""; 303 break; 304 case fb_ubyte: 305 suffix = "U"; 306 break; 307 case fb_bool: 308 suffix = "U"; 309 break; 310 case fb_long: 311 suffix = "LL"; 312 break; 313 case fb_int: 314 suffix = "L"; 315 break; 316 case fb_short: 317 suffix = ""; 318 break; 319 case fb_byte: 320 suffix = ""; 321 break; 322 case fb_double: 323 suffix = ""; 324 break; 325 case fb_float: 326 suffix = "F"; 327 break; 328 default: 329 gen_panic(0, "internal error: unexpected type during code generation"); 330 suffix = ""; 331 break; 332 } 333 return suffix; 334 } 335 336 /* See also: https://github.com/philsquared/Catch/issues/376 */ 337 static inline int gen_prologue(fb_output_t *out) 338 { 339 if (out->opts->cgen_pragmas) { 340 fprintf(out->fp, "#include \"flatcc/flatcc_prologue.h\"\n"); 341 } 342 return 0; 343 } 344 345 static inline int gen_epilogue(fb_output_t *out) 346 { 347 if (out->opts->cgen_pragmas) { 348 fprintf(out->fp, "#include \"flatcc/flatcc_epilogue.h\"\n"); 349 } 350 return 0; 351 } 352 353 /* This assumes the output context is named out which it is by convention. */ 354 #define indent() (out->indent++) 355 #define unindent() { assert(out->indent); out->indent--; } 356 #define margin() { out->tmp_indent = out->indent; out->indent = 0; } 357 #define unmargin() { out->indent = out->tmp_indent; } 358 359 /* Redefine names to avoid polluting library namespace. */ 360 361 int __flatcc_fb_init_output_c(fb_output_t *out, fb_options_t *opts); 362 #define fb_init_output_c __flatcc_fb_init_output_c 363 364 int __flatcc_fb_open_output_file(fb_output_t *out, const char *name, size_t len, const char *ext); 365 #define fb_open_output_file __flatcc_fb_open_output_file 366 367 void __flatcc_fb_close_output_file(fb_output_t *out); 368 #define fb_close_output_file __flatcc_fb_close_output_file 369 370 void __flatcc_fb_gen_c_includes(fb_output_t *out, const char *ext, const char *extup); 371 #define fb_gen_c_includes __flatcc_fb_gen_c_includes 372 373 int __flatcc_fb_gen_common_c_header(fb_output_t *out); 374 #define fb_gen_common_c_header __flatcc_fb_gen_common_c_header 375 376 int __flatcc_fb_gen_common_c_builder_header(fb_output_t *out); 377 #define fb_gen_common_c_builder_header __flatcc_fb_gen_common_c_builder_header 378 379 int __flatcc_fb_gen_c_reader(fb_output_t *out); 380 #define fb_gen_c_reader __flatcc_fb_gen_c_reader 381 382 int __flatcc_fb_gen_c_builder(fb_output_t *out); 383 #define fb_gen_c_builder __flatcc_fb_gen_c_builder 384 385 int __flatcc_fb_gen_c_verifier(fb_output_t *out); 386 #define fb_gen_c_verifier __flatcc_fb_gen_c_verifier 387 388 int __flatcc_fb_gen_c_sorter(fb_output_t *out); 389 #define fb_gen_c_sorter __flatcc_fb_gen_c_sorter 390 391 int __flatcc_fb_gen_c_json_parser(fb_output_t *out); 392 #define fb_gen_c_json_parser __flatcc_fb_gen_c_json_parser 393 394 int __flatcc_fb_gen_c_json_printer(fb_output_t *out); 395 #define fb_gen_c_json_printer __flatcc_fb_gen_c_json_printer 396 397 #endif /* CODEGEN_C_H */