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  )