modernc.org/cc@v1.0.1/v2/encoding.go (about) 1 // Copyright 2017 The CC Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package cc // import "modernc.org/cc/v2" 6 7 import ( 8 "encoding/binary" 9 "go/token" 10 "reflect" 11 "strconv" 12 13 "modernc.org/golex/lex" 14 "modernc.org/ir" 15 "modernc.org/strutil" 16 "modernc.org/xc" 17 ) 18 19 var ( 20 dict = xc.Dict 21 printHooks = strutil.PrettyPrintHooks{} 22 ) 23 24 func init() { 25 for k, v := range xc.PrintHooks { 26 printHooks[k] = v 27 } 28 delete(printHooks, reflect.TypeOf(token.Pos(0))) 29 lcRT := reflect.TypeOf(lex.Char{}) 30 lcH := func(f strutil.Formatter, v interface{}, prefix, suffix string) { 31 c := v.(lex.Char) 32 r := c.Rune 33 s := yySymName(int(r)) 34 if x := s[0]; x >= '0' && x <= '9' { 35 s = strconv.QuoteRune(r) 36 } 37 f.Format(prefix) 38 f.Format("%s", s) 39 f.Format(suffix) 40 } 41 42 printHooks[lcRT] = lcH 43 printHooks[reflect.TypeOf(xc.Token{})] = func(f strutil.Formatter, v interface{}, prefix, suffix string) { 44 t := v.(xc.Token) 45 if (t == xc.Token{}) { 46 return 47 } 48 49 lcH(f, t.Char, prefix, "") 50 if s := t.S(); len(s) != 0 { 51 f.Format(" %q", s) 52 } 53 f.Format(suffix) 54 } 55 for _, v := range []interface{}{ 56 (*ir.Float32Value)(nil), 57 (*ir.Float64Value)(nil), 58 (*ir.Int32Value)(nil), 59 (*ir.Int64Value)(nil), 60 (*ir.StringValue)(nil), 61 DirectDeclaratorCase(0), 62 ExprCase(0), 63 Linkage(0), 64 StorageDuration(0), 65 TypeKind(0), 66 ir.Linkage(0), 67 } { 68 printHooks[reflect.TypeOf(v)] = func(f strutil.Formatter, v interface{}, prefix, suffix string) { 69 f.Format(prefix) 70 f.Format("%v", v) 71 f.Format(suffix) 72 } 73 } 74 } 75 76 var ( 77 nopos xc.Token 78 79 // Null pointer, [0]6.3.2.3-3. 80 Null = &ir.AddressValue{} 81 82 idAsm = dict.SID("asm") 83 idAttribute = dict.SID("__attribute__") 84 idBuiltinAlloca = dict.SID("__builtin_alloca") 85 idBuiltinClasifyType = dict.SID("__builtin_classify_type") 86 idBuiltinTypesCompatible = dict.SID("__builtin_types_compatible__") // Implements __builtin_types_compatible_p 87 idBuiltinVaList = dict.SID("__builtin_va_list") 88 idChar = dict.SID("char") 89 idConst = dict.SID("const") 90 idDefine = dict.SID("define") 91 idDefined = dict.SID("defined") 92 idElif = dict.SID("elif") 93 idElse = dict.SID("else") 94 idEndif = dict.SID("endif") 95 idError = dict.SID("error") 96 idFile = dict.SID("__FILE__") 97 idFuncName = dict.SID("__func__") 98 idIf = dict.SID("if") 99 idIfdef = dict.SID("ifdef") 100 idIfndef = dict.SID("ifndef") 101 idInclude = dict.SID("include") 102 idIncludeNext = dict.SID("include_next") 103 idLine = dict.SID("line") 104 idLineMacro = dict.SID("__LINE__") 105 idMain = dict.SID("main") 106 idOne = dict.SID("1") 107 idPopMacro = dict.SID("pop_macro") 108 idPragma = dict.SID("pragma") 109 idPtrdiffT = dict.SID("ptrdiff_t") 110 idPushMacro = dict.SID("push_macro") 111 idSizeT = dict.SID("size_t") 112 idStatic = dict.SID("static") 113 idUndef = dict.SID("undef") 114 idVaArgs = dict.SID("__VA_ARGS__") 115 idVaList = dict.SID("va_list") 116 idWarning = dict.SID("warning") 117 idWcharT = dict.SID("wchar_t") 118 idZero = dict.SID("0") 119 120 protectedMacro = map[int]bool{ 121 idFile: true, 122 idLineMacro: true, 123 } 124 125 keywords = map[int]rune{ 126 dict.SID("_Alignas"): ALIGNAS, 127 dict.SID("_Alignof"): ALIGNOF, 128 dict.SID("_Atomic"): ATOMIC, 129 dict.SID("("): ATOMIC_LPAREN, 130 dict.SID("_Bool"): BOOL, 131 dict.SID("_Complex"): COMPLEX, 132 dict.SID("_Generic"): GENERIC, 133 dict.SID("_Imaginary"): IMAGINARY, 134 dict.SID("_Noreturn"): NORETURN, 135 dict.SID("_Static_assert"): STATIC_ASSERT, 136 dict.SID("_Thread_local"): THREAD_LOCAL, 137 dict.SID("auto"): AUTO, 138 dict.SID("break"): BREAK, 139 dict.SID("case"): CASE, 140 dict.SID("char"): CHAR, 141 dict.SID("const"): CONST, 142 dict.SID("continue"): CONTINUE, 143 dict.SID("default"): DEFAULT, 144 dict.SID("do"): DO, 145 dict.SID("double"): DOUBLE, 146 dict.SID("else"): ELSE, 147 dict.SID("enum"): ENUM, 148 dict.SID("extern"): EXTERN, 149 dict.SID("float"): FLOAT, 150 dict.SID("for"): FOR, 151 dict.SID("goto"): GOTO, 152 dict.SID("if"): IF, 153 dict.SID("inline"): INLINE, 154 dict.SID("int"): INT, 155 dict.SID("long"): LONG, 156 dict.SID("register"): REGISTER, 157 dict.SID("restrict"): RESTRICT, 158 dict.SID("return"): RETURN, 159 dict.SID("short"): SHORT, 160 dict.SID("signed"): SIGNED, 161 dict.SID("sizeof"): SIZEOF, 162 dict.SID("static"): STATIC, 163 dict.SID("struct"): STRUCT, 164 dict.SID("switch"): SWITCH, 165 dict.SID("typedef"): TYPEDEF, 166 dict.SID("typeof"): TYPEOF, 167 dict.SID("union"): UNION, 168 dict.SID("unsigned"): UNSIGNED, 169 dict.SID("void"): VOID, 170 dict.SID("volatile"): VOLATILE, 171 dict.SID("while"): WHILE, 172 } 173 174 tokConstVals = map[rune]int{ 175 ADDASSIGN: dict.SID("+="), 176 ALIGNAS: dict.SID("_Alignas"), 177 ALIGNOF: dict.SID("_Alignof"), 178 ANDAND: dict.SID("&&"), 179 ANDASSIGN: dict.SID("&="), 180 ARROW: dict.SID("->"), 181 ATOMIC: dict.SID("_Atomic"), 182 ATOMIC_LPAREN: dict.SID("("), 183 AUTO: dict.SID("auto"), 184 BOOL: dict.SID("_Bool"), 185 BREAK: dict.SID("break"), 186 CASE: dict.SID("case"), 187 CHAR: dict.SID("char"), 188 COMPLEX: dict.SID("_Complex"), 189 CONST: dict.SID("const"), 190 CONTINUE: dict.SID("continue"), 191 DDD: dict.SID("..."), 192 DEC: dict.SID("--"), 193 DEFAULT: dict.SID("default"), 194 DIVASSIGN: dict.SID("/="), 195 DO: dict.SID("do"), 196 DOUBLE: dict.SID("double"), 197 ELSE: dict.SID("else"), 198 ENUM: dict.SID("enum"), 199 EQ: dict.SID("=="), 200 EXTERN: dict.SID("extern"), 201 FLOAT: dict.SID("float"), 202 FOR: dict.SID("for"), 203 GENERIC: dict.SID("_Generic"), 204 GEQ: dict.SID(">="), 205 GOTO: dict.SID("goto"), 206 IF: dict.SID("if"), 207 IMAGINARY: dict.SID("_Imaginary"), 208 INC: dict.SID("++"), 209 INLINE: dict.SID("inline"), 210 INT: dict.SID("int"), 211 LEQ: dict.SID("<="), 212 LONG: dict.SID("long"), 213 LSH: dict.SID("<<"), 214 LSHASSIGN: dict.SID("<<="), 215 MODASSIGN: dict.SID("%="), 216 MULASSIGN: dict.SID("*="), 217 NEQ: dict.SID("!="), 218 NORETURN: dict.SID("_Noreturn"), 219 ORASSIGN: dict.SID("|="), 220 OROR: dict.SID("||"), 221 PPPASTE: dict.SID("##"), 222 REGISTER: dict.SID("register"), 223 RESTRICT: dict.SID("restrict"), 224 RETURN: dict.SID("return"), 225 RSH: dict.SID(">>"), 226 RSHASSIGN: dict.SID(">>="), 227 SHORT: dict.SID("short"), 228 SIGNED: dict.SID("signed"), 229 SIZEOF: dict.SID("sizeof"), 230 STATIC: dict.SID("static"), 231 STATIC_ASSERT: dict.SID("_Static_assert"), 232 STRUCT: dict.SID("struct"), 233 SUBASSIGN: dict.SID("-="), 234 SWITCH: dict.SID("switch"), 235 THREAD_LOCAL: dict.SID("_Thread_local"), 236 TYPEDEF: dict.SID("typedef"), 237 TYPEOF: dict.SID("typeof"), 238 UNION: dict.SID("union"), 239 UNSIGNED: dict.SID("unsigned"), 240 VOID: dict.SID("void"), 241 VOLATILE: dict.SID("volatile"), 242 WHILE: dict.SID("while"), 243 XORASSIGN: dict.SID("^="), 244 } 245 246 tokHasVal = map[rune]struct{}{ 247 CHARCONST: {}, 248 FLOATCONST: {}, 249 IDENTIFIER: {}, 250 INTCONST: {}, 251 LONGCHARCONST: {}, 252 LONGSTRINGLITERAL: {}, 253 NON_REPL: {}, 254 PPNUMBER: {}, 255 STRINGLITERAL: {}, 256 TYPEDEF_NAME: {}, 257 } 258 259 followSetHasTypedefName = [len(yyParseTab)]bool{} 260 261 classifyType = map[TypeKind]int{ 262 0: noTypeClass, 263 Void: voidTypeClass, 264 Ptr: pointerTypeClass, 265 Char: charTypeClass, 266 SChar: charTypeClass, 267 UChar: charTypeClass, 268 Short: integerTypeClass, 269 UShort: integerTypeClass, 270 Int: integerTypeClass, 271 UInt: integerTypeClass, 272 Long: integerTypeClass, 273 ULong: integerTypeClass, 274 LongLong: integerTypeClass, 275 ULongLong: integerTypeClass, 276 Float: realTypeClass, 277 Double: realTypeClass, 278 LongDouble: realTypeClass, 279 Bool: booleanTypeClass, 280 FloatComplex: complexTypeClass, 281 DoubleComplex: complexTypeClass, 282 LongDoubleComplex: complexTypeClass, 283 Struct: recordTypeClass, 284 Union: unionTypeClass, 285 Enum: enumeralTypeClass, 286 TypedefName: noTypeClass, 287 Function: functionTypeClass, 288 Array: arrayTypeClass, 289 } 290 ) 291 292 func init() { 293 for i, v := range yyFollow { 294 for _, v := range v { 295 if v == TYPEDEF_NAME { 296 followSetHasTypedefName[i] = true 297 } 298 } 299 } 300 } 301 302 func isUCNDigit(r rune) bool { 303 return int(r) < len(ucnDigits)<<bitShift && ucnDigits[uint(r)>>bitShift]&(1<<uint(r&bitMask)) != 0 304 } 305 306 func isUCNNonDigit(r rune) bool { 307 return int(r) < len(ucnNonDigits)<<bitShift && ucnNonDigits[uint(r)>>bitShift]&(1<<uint(r&bitMask)) != 0 308 } 309 310 func rune2class(r rune) (c int) { 311 switch { 312 case r == lex.RuneEOF: 313 return ccEOF 314 case r < 128: 315 return int(r) 316 case isUCNDigit(r): 317 return ccUCNDigit 318 case isUCNNonDigit(r): 319 return ccUCNNonDigit 320 default: 321 return ccOther 322 } 323 } 324 325 func decodeToken(b []byte, pos token.Pos) ([]byte, token.Pos, xc.Token) { 326 r, n := binary.Uvarint(b) 327 b = b[n:] 328 d, n := binary.Uvarint(b) 329 b = b[n:] 330 np := pos + token.Pos(d) 331 c := lex.NewChar(np, rune(r)) 332 var v uint64 333 if _, ok := tokHasVal[c.Rune]; ok { 334 v, n = binary.Uvarint(b) 335 b = b[n:] 336 } 337 return b, np, xc.Token{Char: c, Val: int(v)} 338 } 339 340 // TokSrc returns t in its source form. 341 func TokSrc(t xc.Token) string { 342 if x, ok := tokConstVals[t.Rune]; ok { 343 return string(dict.S(x)) 344 } 345 346 if _, ok := tokHasVal[t.Rune]; ok { 347 return string(t.S()) 348 } 349 350 return string(t.Rune) 351 } 352 353 // escape-sequence {simple-sequence}|{octal-escape-sequence}|{hexadecimal-escape-sequence}|{universal-character-name} 354 // simple-sequence \\['\x22?\\abfnrtv] 355 // octal-escape-sequence \\{octal-digit}{octal-digit}?{octal-digit}? 356 // hexadecimal-escape-sequence \\x{hexadecimal-digit}+ 357 func decodeEscapeSequence(runes []rune) (rune, int) { 358 if runes[0] != '\\' { 359 panic("internal error") 360 } 361 362 r := runes[1] 363 switch r { 364 case '\'', '"', '?', '\\': 365 return r, 2 366 case 'a': 367 return 7, 2 368 case 'b': 369 return 8, 2 370 case 'f': 371 return 12, 2 372 case 'n': 373 return 10, 2 374 case 'r': 375 return 13, 2 376 case 't': 377 return 9, 2 378 case 'v': 379 return 11, 2 380 case 'x': 381 v, n := 0, 2 382 loop2: 383 for _, r := range runes[2:] { 384 switch { 385 case r >= '0' && r <= '9', r >= 'a' && r <= 'f', r >= 'A' && r <= 'F': 386 v = v<<4 | decodeHex(r) 387 n++ 388 default: 389 break loop2 390 } 391 } 392 return -rune(v & 0xff), n 393 case 'u', 'U': 394 return decodeUCN(runes) 395 } 396 397 if r < '0' || r > '7' { 398 panic("internal error") 399 } 400 401 v, n := 0, 1 402 loop: 403 for _, r := range runes[1:] { 404 switch { 405 case r >= '0' && r <= '7': 406 v = v<<3 | (int(r) - '0') 407 n++ 408 default: 409 break loop 410 } 411 } 412 return -rune(v), n 413 } 414 415 func decodeHex(r rune) int { 416 switch { 417 case r >= '0' && r <= '9': 418 return int(r) - '0' 419 default: 420 x := int(r) &^ 0x20 421 return x - 'A' + 10 422 } 423 } 424 425 // universal-character-name \\u{hex-quad}|\\U{hex-quad}{hex-quad} 426 func decodeUCN(runes []rune) (rune, int) { 427 if runes[0] != '\\' { 428 panic("internal error") 429 } 430 431 runes = runes[1:] 432 switch runes[0] { 433 case 'u': 434 return rune(decodeHexQuad(runes[1:])), 6 435 case 'U': 436 return rune(decodeHexQuad(runes[1:])<<16 | decodeHexQuad(runes[5:])), 10 437 default: 438 panic("internal error") 439 } 440 } 441 442 // hex-quad {hexadecimal-digit}{hexadecimal-digit}{hexadecimal-digit}{hexadecimal-digit} 443 func decodeHexQuad(runes []rune) int { 444 n := 0 445 for _, r := range runes[:4] { 446 n = n<<4 | decodeHex(r) 447 } 448 return n 449 } 450 451 // Values from GCC's typeclass.h 452 const ( 453 noTypeClass = iota - 1 454 voidTypeClass 455 integerTypeClass 456 charTypeClass 457 enumeralTypeClass 458 booleanTypeClass 459 pointerTypeClass 460 referenceTypeClass 461 offsetTypeClass 462 realTypeClass 463 complexTypeClass 464 functionTypeClass 465 methodTypeClass 466 recordTypeClass 467 unionTypeClass 468 arrayTypeClass 469 stringTypeClass 470 langTypeClass 471 )