gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

cpp.go (69747B)


      1 // Copyright 2019 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/v3"
      6 
      7 import (
      8 	"bytes"
      9 	"fmt"
     10 	gotoken "go/token"
     11 	"math"
     12 	"os"
     13 	"path/filepath"
     14 	"strconv"
     15 	"strings"
     16 	"sync"
     17 	"time"
     18 	"unicode/utf8"
     19 
     20 	"modernc.org/token"
     21 )
     22 
     23 const (
     24 	maxIncludeLevel = 200 // gcc, std is at least 15.
     25 )
     26 
     27 var (
     28 	_ tokenReader = (*cpp)(nil)
     29 	_ tokenWriter = (*cpp)(nil)
     30 
     31 	idCOUNTER                  = dict.sid("__COUNTER__")
     32 	idCxLimitedRange           = dict.sid("CX_LIMITED_RANGE")
     33 	idDATE                     = dict.sid("__DATE__")
     34 	idDefault                  = dict.sid("DEFAULT")
     35 	idDefined                  = dict.sid("defined")
     36 	idEmptyString              = dict.sid(`""`)
     37 	idFILE                     = dict.sid("__FILE__")
     38 	idFPContract               = dict.sid("FP_CONTRACT")
     39 	idFdZero                   = dict.sid("FD_ZERO")
     40 	idFenvAccess               = dict.sid("FENV_ACCESS")
     41 	idGNUC                     = dict.sid("__GNUC__")
     42 	idHasIncludeImpl           = dict.sid("__has_include_impl")
     43 	idIntMaxWidth              = dict.sid("__INTMAX_WIDTH__")
     44 	idL                        = dict.sid("L")
     45 	idLINE                     = dict.sid("__LINE__")
     46 	idNL                       = dict.sid("\n")
     47 	idOff                      = dict.sid("OFF")
     48 	idOn                       = dict.sid("ON")
     49 	idOne                      = dict.sid("1")
     50 	idPragmaSTDC               = dict.sid("__pragma_stdc")
     51 	idSTDC                     = dict.sid("STDC")
     52 	idTIME                     = dict.sid("__TIME__")
     53 	idTclDefaultDoubleRounding = dict.sid("TCL_DEFAULT_DOUBLE_ROUNDING")
     54 	idTclIeeeDoubleRounding    = dict.sid("TCL_IEEE_DOUBLE_ROUNDING")
     55 	idVaArgs                   = dict.sid("__VA_ARGS__")
     56 	idZero                     = dict.sid("0")
     57 
     58 	cppTokensPool = sync.Pool{New: func() interface{} { r := []cppToken{}; return &r }}
     59 
     60 	protectedMacros = hideSet{ // [0], 6.10.8, 4
     61 		dict.sid("__STDC_HOSTED__"):          {},
     62 		dict.sid("__STDC_IEC_559_COMPLEX__"): {},
     63 		dict.sid("__STDC_IEC_559__"):         {},
     64 		dict.sid("__STDC_ISO_10646__"):       {},
     65 		dict.sid("__STDC_MB_MIGHT_NEQ_WC__"): {},
     66 		dict.sid("__STDC_VERSION__"):         {},
     67 		dict.sid("__STDC__"):                 {},
     68 		idCOUNTER:                            {},
     69 		idDATE:                               {},
     70 		idFILE:                               {},
     71 		idLINE:                               {},
     72 		idTIME:                               {},
     73 	}
     74 )
     75 
     76 type tokenReader interface {
     77 	read() (cppToken, bool)
     78 	unget(cppToken)
     79 	ungets([]cppToken)
     80 }
     81 
     82 type tokenWriter interface {
     83 	write(cppToken)
     84 	writes([]cppToken)
     85 }
     86 
     87 // token4 is produced by translation phase 4.
     88 type token4 struct {
     89 	file *tokenFile //TODO sort fields
     90 	token3
     91 }
     92 
     93 func (t *token4) Position() (r token.Position) {
     94 	if t.pos != 0 && t.file != nil {
     95 		r = t.file.PositionFor(token.Pos(t.pos), true)
     96 	}
     97 	return r
     98 }
     99 
    100 type hideSet map[StringID]struct{}
    101 
    102 type cppToken struct {
    103 	token4
    104 	hs hideSet
    105 }
    106 
    107 func (t *cppToken) has(nm StringID) bool { _, ok := t.hs[nm]; return ok }
    108 
    109 type cppWriter struct {
    110 	toks []cppToken
    111 }
    112 
    113 func (w *cppWriter) write(tok cppToken)     { w.toks = append(w.toks, tok) }
    114 func (w *cppWriter) writes(toks []cppToken) { w.toks = append(w.toks, toks...) }
    115 
    116 type ungetBuf []cppToken
    117 
    118 func (u *ungetBuf) unget(t cppToken) { *u = append(*u, t) }
    119 
    120 func (u *ungetBuf) read() (t cppToken) {
    121 	s := *u
    122 	n := len(s) - 1
    123 	t = s[n]
    124 	*u = s[:n]
    125 	return t
    126 }
    127 func (u *ungetBuf) ungets(toks []cppToken) {
    128 	s := *u
    129 	for i := len(toks) - 1; i >= 0; i-- {
    130 		s = append(s, toks[i])
    131 	}
    132 	*u = s
    133 }
    134 
    135 func cppToksStr(toks []cppToken, sep string) string {
    136 	var b strings.Builder
    137 	for i, v := range toks {
    138 		if i != 0 {
    139 			b.WriteString(sep)
    140 		}
    141 		b.WriteString(v.String())
    142 	}
    143 	return b.String()
    144 }
    145 
    146 func cppToksStr2(toks [][]cppToken) string {
    147 	panic(todo(""))
    148 	var a []string
    149 	for _, v := range toks {
    150 		a = append(a, fmt.Sprintf("%q", cppToksStr(v, "|")))
    151 	}
    152 	return fmt.Sprint(a)
    153 }
    154 
    155 type cppReader struct {
    156 	buf []cppToken
    157 	ungetBuf
    158 }
    159 
    160 func (r *cppReader) read() (tok cppToken, ok bool) {
    161 	if len(r.ungetBuf) != 0 {
    162 		return r.ungetBuf.read(), true
    163 	}
    164 
    165 	if len(r.buf) == 0 {
    166 		return tok, false
    167 	}
    168 
    169 	tok = r.buf[0]
    170 	r.buf = r.buf[1:]
    171 	return tok, true
    172 }
    173 
    174 type cppScanner []cppToken
    175 
    176 func (s *cppScanner) peek() (r cppToken) {
    177 	r.char = -1
    178 	if len(*s) == 0 {
    179 		return r
    180 	}
    181 
    182 	return (*s)[0]
    183 }
    184 
    185 func (s *cppScanner) next() (r cppToken) {
    186 	r.char = -1
    187 	if len(*s) == 0 {
    188 		return r
    189 	}
    190 
    191 	*s = (*s)[1:]
    192 	return s.peek()
    193 }
    194 
    195 func (s *cppScanner) Pos() token.Pos {
    196 	if len(*s) == 0 {
    197 		return 0
    198 	}
    199 
    200 	return (*s)[0].Pos()
    201 }
    202 
    203 // Macro represents a preprocessor macro definition.
    204 type Macro struct {
    205 	fp    []StringID
    206 	repl  []token3
    207 	repl2 []Token
    208 
    209 	name token4
    210 	pos  int32
    211 
    212 	isFnLike      bool
    213 	namedVariadic bool // foo..., note no comma before ellipsis.
    214 	variadic      bool
    215 }
    216 
    217 // Position reports the position of the macro definition.
    218 func (m *Macro) Position() token.Position {
    219 	if m.pos != 0 && m.name.file != nil {
    220 		return m.name.file.PositionFor(token.Pos(m.pos), true)
    221 	}
    222 	return token.Position{}
    223 }
    224 
    225 // Parameters return the list of function-like macro parameters.
    226 func (m *Macro) Parameters() []StringID { return m.fp }
    227 
    228 // ReplacementTokens return the list of tokens m is replaced with. Tokens in
    229 // the returned list have only the Rune and Value fields valid.
    230 func (m *Macro) ReplacementTokens() []Token {
    231 	if m.repl2 != nil {
    232 		return m.repl2
    233 	}
    234 
    235 	m.repl2 = make([]Token, len(m.repl))
    236 	for i, v := range m.repl {
    237 		m.repl2[i] = Token{Rune: v.char, Value: v.value, Src: v.src}
    238 	}
    239 	return m.repl2
    240 }
    241 
    242 // IsFnLike reports whether m is a function-like macro.
    243 func (m *Macro) IsFnLike() bool { return m.isFnLike }
    244 
    245 func (m *Macro) isNamedVariadicParam(nm StringID) bool {
    246 	return m.namedVariadic && nm == m.fp[len(m.fp)-1]
    247 }
    248 
    249 func (m *Macro) param2(varArgs []cppToken, ap [][]cppToken, nm StringID, out *[]cppToken, argIndex *int) bool {
    250 	*out = nil
    251 	if nm == idVaArgs || m.isNamedVariadicParam(nm) {
    252 		if !m.variadic {
    253 			return false
    254 		}
    255 
    256 		*out = append([]cppToken(nil), varArgs...)
    257 		return true
    258 	}
    259 
    260 	for i, v := range m.fp {
    261 		if v == nm {
    262 			if i < len(ap) {
    263 				a := ap[i]
    264 				for len(a) != 0 && a[0].char == ' ' {
    265 					a = a[1:]
    266 				}
    267 				*out = a
    268 			}
    269 			if argIndex != nil {
    270 				*argIndex = i
    271 			}
    272 			return true
    273 		}
    274 	}
    275 	return false
    276 }
    277 
    278 func (m *Macro) param(varArgs []cppToken, ap [][]cppToken, nm StringID, out *[]cppToken) bool {
    279 	// trc("select (A) varArgs %q, ap %v, nm %q, out %q", cppToksStr(varArgs, "|"), cppToksStr2(ap), nm, cppToksStr(*out, "|"))
    280 	// defer func() {
    281 	// 	trc("select (A) varArgs %q, ap %v, nm %q, out %q", cppToksStr(varArgs, "|"), cppToksStr2(ap), nm, cppToksStr(*out, "|"))
    282 	// }()
    283 	return m.param2(varArgs, ap, nm, out, nil)
    284 }
    285 
    286 // --------------------------------------------------------------- Preprocessor
    287 
    288 type cpp struct {
    289 	counter      int
    290 	counterMacro Macro
    291 	ctx          *context
    292 	dateMacro    Macro
    293 	file         *tokenFile
    294 	fileMacro    Macro
    295 	in           chan []token3
    296 	inBuf        []token3
    297 	includeLevel int
    298 	lineMacro    Macro
    299 	macroStack   map[StringID][]*Macro
    300 	macros       map[StringID]*Macro
    301 	out          chan *[]token4
    302 	outBuf       *[]token4
    303 	pragmaOpBuf  []token4
    304 	rq           chan struct{}
    305 	timeMacro    Macro
    306 	ungetBuf
    307 
    308 	last rune
    309 
    310 	intmaxChecked bool
    311 	nonFirstRead  bool
    312 	seenEOF       bool
    313 	inPragmaOp    bool
    314 }
    315 
    316 func newCPP(ctx *context) *cpp {
    317 	b := token4Pool.Get().(*[]token4)
    318 	*b = (*b)[:0]
    319 	r := &cpp{
    320 		ctx:        ctx,
    321 		macroStack: map[StringID][]*Macro{},
    322 		macros:     map[StringID]*Macro{},
    323 		outBuf:     b,
    324 	}
    325 	r.counterMacro = Macro{repl: []token3{{char: PPNUMBER}}}
    326 	r.dateMacro = Macro{repl: []token3{{char: STRINGLITERAL}}}
    327 	r.timeMacro = Macro{repl: []token3{{char: STRINGLITERAL}}}
    328 	r.fileMacro = Macro{repl: []token3{{char: STRINGLITERAL}}}
    329 	r.lineMacro = Macro{repl: []token3{{char: PPNUMBER}}}
    330 	r.macros = map[StringID]*Macro{
    331 		idCOUNTER: &r.counterMacro,
    332 		idDATE:    &r.dateMacro,
    333 		idFILE:    &r.fileMacro,
    334 		idLINE:    &r.lineMacro,
    335 		idTIME:    &r.timeMacro,
    336 	}
    337 	t := time.Now()
    338 	// This macro expands to a string constant that describes the date on which the
    339 	// preprocessor is being run. The string constant contains eleven characters
    340 	// and looks like "Feb 12 1996". If the day of the month is less than 10, it is
    341 	// padded with a space on the left.
    342 	r.dateMacro.repl[0].value = dict.sid(t.Format("\"Jan _2 2006\""))
    343 	// This macro expands to a string constant that describes the time at which the
    344 	// preprocessor is being run. The string constant contains eight characters and
    345 	// looks like "23:59:01".
    346 	r.timeMacro.repl[0].value = dict.sid(t.Format("\"15:04:05\""))
    347 	return r
    348 }
    349 
    350 func (c *cpp) cppToks(toks []token3) (r []cppToken) {
    351 	r = make([]cppToken, len(toks))
    352 	for i, v := range toks {
    353 		r[i].token4.token3 = v
    354 		r[i].token4.file = c.file
    355 	}
    356 	return r
    357 }
    358 
    359 func (c *cpp) err(n node, msg string, args ...interface{}) (stop bool) {
    360 	var position token.Position
    361 	switch x := n.(type) {
    362 	case nil:
    363 	case token4:
    364 		position = x.Position()
    365 	default:
    366 		if p := n.Pos(); p.IsValid() {
    367 			position = c.file.PositionFor(p, true)
    368 		}
    369 	}
    370 	return c.ctx.err(position, msg, args...)
    371 }
    372 
    373 func (c *cpp) read() (cppToken, bool) {
    374 	if len(c.ungetBuf) != 0 {
    375 		return c.ungetBuf.read(), true
    376 	}
    377 
    378 	if len(c.inBuf) == 0 {
    379 		if c.seenEOF {
    380 			return cppToken{}, false
    381 		}
    382 
    383 		if c.nonFirstRead {
    384 			c.rq <- struct{}{}
    385 		}
    386 		c.nonFirstRead = true
    387 
    388 		var ok bool
    389 		if c.inBuf, ok = <-c.in; !ok {
    390 			c.seenEOF = true
    391 			return cppToken{}, false
    392 		}
    393 	}
    394 
    395 	tok := c.inBuf[0]
    396 	c.inBuf = c.inBuf[1:]
    397 	return cppToken{token4{token3: tok, file: c.file}, nil}, true
    398 }
    399 
    400 func (c *cpp) write(tok cppToken) {
    401 	if tok.char == ' ' && c.last == ' ' {
    402 		return
    403 	}
    404 
    405 	if c.ctx.cfg.PreprocessOnly {
    406 		switch {
    407 		case
    408 			//TODO cover ALL the bad combinations
    409 			c.last == '+' && tok.char == '+',
    410 			c.last == '+' && tok.char == INC,
    411 			c.last == '-' && tok.char == '-',
    412 			c.last == '-' && tok.char == DEC,
    413 			c.last == IDENTIFIER && tok.char == IDENTIFIER,
    414 			c.last == PPNUMBER && tok.char == '+', //TODO not when ends in a digit
    415 			c.last == PPNUMBER && tok.char == '-': //TODO not when ends in a digit
    416 
    417 			sp := tok
    418 			sp.char = ' '
    419 			sp.value = idSpace
    420 			*c.outBuf = append(*c.outBuf, sp.token4)
    421 		}
    422 	}
    423 
    424 	//dbg("%T.write %q", c, tok)
    425 	c.last = tok.char
    426 	switch {
    427 	case c.inPragmaOp:
    428 	out:
    429 		switch tok.char {
    430 		case ')':
    431 			c.inPragmaOp = false
    432 			b := c.pragmaOpBuf
    433 			if len(b) == 0 || b[0].char != '(' {
    434 				c.err(b[0], "expected (")
    435 				break
    436 			}
    437 
    438 			var a []string
    439 			for _, v := range b[1:] {
    440 				if v.char != STRINGLITERAL {
    441 					c.err(v, "expected string literal")
    442 					break out
    443 				}
    444 
    445 				a = append(a, v.String())
    446 			}
    447 
    448 			if len(a) == 0 {
    449 				break
    450 			}
    451 
    452 			for i, v := range a {
    453 				// [0], 6.10.9, 1
    454 				if v[0] == 'L' {
    455 					v = v[1:]
    456 				}
    457 				v = v[1 : len(v)-1]
    458 				v = strings.ReplaceAll(v, `\"`, `"`)
    459 				a[i] = "#pragma " + strings.ReplaceAll(v, `\\`, `\`) + "\n"
    460 			}
    461 			src := strings.Join(a, "")
    462 			s := newScanner0(c.ctx, strings.NewReader(src), tokenNewFile("", len(src)), 4096)
    463 			if ppf := s.translationPhase3(); ppf != nil {
    464 				ppf.translationPhase4(c)
    465 			}
    466 		default:
    467 			c.pragmaOpBuf = append(c.pragmaOpBuf, tok.token4)
    468 		}
    469 	default:
    470 		switch {
    471 		case tok.char == '\n':
    472 			*c.outBuf = append(*c.outBuf, tok.token4)
    473 			c.out <- c.outBuf
    474 			b := token4Pool.Get().(*[]token4)
    475 			*b = (*b)[:0]
    476 			c.outBuf = b
    477 		case tok.char == IDENTIFIER && tok.value == idPragmaOp:
    478 			if len(*c.outBuf) != 0 {
    479 				tok.char = '\n'
    480 				tok.value = 0
    481 				*c.outBuf = append(*c.outBuf, tok.token4)
    482 				c.out <- c.outBuf
    483 				b := token4Pool.Get().(*[]token4)
    484 				*b = (*b)[:0]
    485 				c.outBuf = b
    486 			}
    487 			c.inPragmaOp = true
    488 			c.pragmaOpBuf = c.pragmaOpBuf[:0]
    489 		default:
    490 			*c.outBuf = append(*c.outBuf, tok.token4)
    491 		}
    492 	}
    493 }
    494 
    495 func ltrim4(toks []token4) []token4 {
    496 	for len(toks) != 0 && toks[0].char == ' ' {
    497 		toks = toks[1:]
    498 	}
    499 	return toks
    500 }
    501 
    502 func (c *cpp) writes(toks []cppToken) {
    503 	for _, v := range toks {
    504 		c.write(v)
    505 	}
    506 }
    507 
    508 // [1]pg 1.
    509 //
    510 // expand(TS) /* recur, substitute, pushback, rescan */
    511 // {
    512 // 	if TS is {} then
    513 //		// ---------------------------------------------------------- A
    514 // 		return {};
    515 //
    516 // 	else if TS is T^HS • TS’ and T is in HS then
    517 //		//----------------------------------------------------------- B
    518 // 		return T^HS • expand(TS’);
    519 //
    520 // 	else if TS is T^HS • TS’ and T is a "()-less macro" then
    521 //		// ---------------------------------------------------------- C
    522 // 		return expand(subst(ts(T), {}, {}, HS \cup {T}, {}) • TS’ );
    523 //
    524 // 	else if TS is T^HS •(•TS’ and T is a "()’d macro" then
    525 //		// ---------------------------------------------------------- D
    526 // 		check TS’ is actuals • )^HS’ • TS’’ and actuals are "correct for T"
    527 // 		return expand(subst(ts(T), fp(T), actuals,(HS \cap HS’) \cup {T }, {}) • TS’’);
    528 //
    529 //	// ------------------------------------------------------------------ E
    530 // 	note TS must be T^HS • TS’
    531 // 	return T^HS • expand(TS’);
    532 // }
    533 func (c *cpp) expand(ts tokenReader, w tokenWriter, expandDefined bool) {
    534 	// trc("==== expand enter")
    535 start:
    536 	tok, ok := ts.read()
    537 	tok.file = c.file
    538 	// First, if TS is the empty set, the result is the empty set.
    539 	if !ok {
    540 		// ---------------------------------------------------------- A
    541 		// return {};
    542 		// trc("---- expand A")
    543 		return
    544 	}
    545 
    546 	// dbg("expand start %q", tok)
    547 	if tok.char == IDENTIFIER {
    548 		nm := tok.value
    549 		if nm == idDefined && expandDefined {
    550 			c.parseDefined(tok, ts, w)
    551 			goto start
    552 		}
    553 
    554 		// Otherwise, if the token sequence begins with a token whose
    555 		// hide set contains that token, then the result is the token
    556 		// sequence beginning with that token (including its hide set)
    557 		// followed by the result of expand on the rest of the token
    558 		// sequence.
    559 		if tok.has(nm) {
    560 			// -------------------------------------------------- B
    561 			// return T^HS • expand(TS’);
    562 			// trc("---- expand B")
    563 			// trc("expand write %q", tok)
    564 			w.write(tok)
    565 			goto start
    566 		}
    567 
    568 		m := c.macros[nm]
    569 		if m != nil && !m.isFnLike {
    570 			// Otherwise, if the token sequence begins with an
    571 			// object-like macro, the result is the expansion of
    572 			// the rest of the token sequence beginning with the
    573 			// sequence returned by subst invoked with the
    574 			// replacement token sequence for the macro, two empty
    575 			// sets, the union of the macro’s hide set and the
    576 			// macro itself, and an empty set.
    577 			switch nm {
    578 			case idLINE:
    579 				c.lineMacro.repl[0].value = dict.sid(fmt.Sprint(tok.Position().Line))
    580 			case idCOUNTER:
    581 				c.counterMacro.repl[0].value = dict.sid(fmt.Sprint(c.counter))
    582 				c.counter++
    583 			case idTclDefaultDoubleRounding:
    584 				if c.ctx.cfg.ReplaceMacroTclDefaultDoubleRounding != "" {
    585 					m = c.macros[dict.sid(c.ctx.cfg.ReplaceMacroTclDefaultDoubleRounding)]
    586 				}
    587 			case idTclIeeeDoubleRounding:
    588 				if c.ctx.cfg.ReplaceMacroTclIeeeDoubleRounding != "" {
    589 					m = c.macros[dict.sid(c.ctx.cfg.ReplaceMacroTclIeeeDoubleRounding)]
    590 				}
    591 			}
    592 			if m != nil {
    593 				// -------------------------------------------------- C
    594 				// return expand(subst(ts(T), {}, {}, HS \cup {T}, {}) • TS’ );
    595 				// trc("---- expand C")
    596 				hs := hideSet{nm: {}}
    597 				for k, v := range tok.hs {
    598 					hs[k] = v
    599 				}
    600 				os := cppTokensPool.Get().(*[]cppToken)
    601 				toks := c.subst(m, c.cppToks(m.repl), nil, nil, nil, hs, os, expandDefined)
    602 				for i := range toks {
    603 					toks[i].pos = tok.pos
    604 				}
    605 				if len(toks) == 1 {
    606 					toks[0].macro = nm
    607 				}
    608 				ts.ungets(toks)
    609 				(*os) = (*os)[:0]
    610 				cppTokensPool.Put(os)
    611 				goto start
    612 			}
    613 		}
    614 
    615 		if m != nil && m.isFnLike {
    616 			switch nm {
    617 			case idFdZero:
    618 				if c.ctx.cfg.ReplaceMacroFdZero != "" {
    619 					m = c.macros[dict.sid(c.ctx.cfg.ReplaceMacroFdZero)]
    620 				}
    621 			}
    622 			if m != nil {
    623 				// -------------------------------------------------- D
    624 				// check TS’ is actuals • )^HS’ • TS’’ and actuals are "correct for T"
    625 				// return expand(subst(ts(T), fp(T), actuals,(HS \cap HS’) \cup {T }, {}) • TS’’);
    626 				// trc("---- expand D")
    627 				hs := tok.hs
    628 				var skip []cppToken
    629 			again:
    630 				t2, ok := ts.read()
    631 				if !ok {
    632 					// dbg("expand write %q", tok)
    633 					w.write(tok)
    634 					ts.ungets(skip)
    635 					goto start
    636 				}
    637 
    638 				skip = append(skip, t2)
    639 				switch t2.char {
    640 				case '\n', ' ':
    641 					goto again
    642 				case '(':
    643 					// ok
    644 				default:
    645 					w.write(tok)
    646 					ts.ungets(skip)
    647 					goto start
    648 				}
    649 
    650 				varArgs, ap, hs2 := c.actuals(m, ts)
    651 				if nm == idHasIncludeImpl { //TODO-
    652 					if len(ap) != 1 || len(ap[0]) != 1 {
    653 						panic(todo("internal error"))
    654 					}
    655 
    656 					arg := ap[0][0].value.String()
    657 					switch {
    658 					case strings.HasPrefix(arg, `"\"`): // `"\"stdio.h\""`
    659 						arg = arg[2:len(arg)-3] + `"` // -> `"stdio.h"`
    660 					case strings.HasPrefix(arg, `"<`): // `"<stdio.h>"`
    661 						arg = arg[1 : len(arg)-1] // -> `<stdio.h>`
    662 					default:
    663 						arg = ""
    664 					}
    665 					var tok3 token3
    666 					tok3.char = PPNUMBER
    667 					tok3.value = idZero
    668 					if arg != "" {
    669 						if _, err := c.hasInclude(&tok, arg); err == nil {
    670 							tok3.value = idOne
    671 						}
    672 					}
    673 					tok := cppToken{token4{token3: tok3, file: c.file}, nil}
    674 					ts.ungets([]cppToken{tok})
    675 					goto start
    676 				}
    677 
    678 				switch {
    679 				case len(hs2) == 0:
    680 					hs2 = hideSet{nm: {}}
    681 				default:
    682 					nhs := hideSet{}
    683 					for k := range hs {
    684 						if _, ok := hs2[k]; ok {
    685 							nhs[k] = struct{}{}
    686 						}
    687 					}
    688 					nhs[nm] = struct{}{}
    689 					hs2 = nhs
    690 				}
    691 				os := cppTokensPool.Get().(*[]cppToken)
    692 				toks := c.subst(m, c.cppToks(m.repl), m.fp, varArgs, ap, hs2, os, expandDefined)
    693 				for i := range toks {
    694 					toks[i].pos = tok.pos
    695 				}
    696 				ts.ungets(toks)
    697 				(*os) = (*os)[:0]
    698 				cppTokensPool.Put(os)
    699 				goto start
    700 			}
    701 		}
    702 	}
    703 
    704 	// ------------------------------------------------------------------ E
    705 	// note TS must be T^HS • TS’
    706 	// return T^HS • expand(TS’);
    707 	// trc("---- expand E")
    708 	// trc("expand write %q", tok)
    709 	w.write(tok)
    710 	goto start
    711 }
    712 
    713 func (c *cpp) hasInclude(n Node, nm string) (rs string, err error) {
    714 	// nm0 := nm
    715 	// defer func() { //TODO-
    716 	// 	trc("nm0 %q nm %q rs %q err %v", nm0, nm, rs, err)
    717 	// }()
    718 	var (
    719 		b     byte
    720 		paths []string
    721 		sys   bool
    722 	)
    723 	switch {
    724 	case nm != "" && nm[0] == '"':
    725 		paths = c.ctx.includePaths
    726 		b = '"'
    727 	case nm != "" && nm[0] == '<':
    728 		paths = c.ctx.sysIncludePaths
    729 		sys = true
    730 		b = '>'
    731 	case nm == "":
    732 		return "", fmt.Errorf("%v: invalid empty include argument", n.Position())
    733 	default:
    734 		return "", fmt.Errorf("%v: invalid include argument %s", n.Position(), nm)
    735 	}
    736 
    737 	x := strings.IndexByte(nm[1:], b)
    738 	if x < 0 {
    739 		return "", fmt.Errorf("%v: invalid include argument %s", n.Position(), nm)
    740 	}
    741 
    742 	nm = filepath.FromSlash(nm[1 : x+1])
    743 	switch {
    744 	case filepath.IsAbs(nm):
    745 		fi, err := c.ctx.statFile(nm, sys)
    746 		if err != nil {
    747 			return "", fmt.Errorf("%v: %s", n.Position(), err)
    748 		}
    749 
    750 		if fi.IsDir() {
    751 			return "", fmt.Errorf("%v: %s is a directory, not a file", n.Position(), nm)
    752 		}
    753 
    754 		return nm, nil
    755 	default:
    756 		dir := filepath.Dir(c.file.Name())
    757 		for _, v := range paths {
    758 			if v == "@" {
    759 				v = dir
    760 			}
    761 
    762 			var p string
    763 			switch {
    764 			case strings.HasPrefix(nm, "./"):
    765 				wd := c.ctx.cfg.WorkingDir
    766 				if wd == "" {
    767 					var err error
    768 					if wd, err = os.Getwd(); err != nil {
    769 						return "", fmt.Errorf("%v: cannot determine working dir: %v", n.Position(), err)
    770 					}
    771 				}
    772 				p = filepath.Join(wd, nm)
    773 			default:
    774 				p = filepath.Join(v, nm)
    775 			}
    776 			fi, err := c.ctx.statFile(p, sys)
    777 			if err != nil || fi.IsDir() {
    778 				continue
    779 			}
    780 
    781 			return p, nil
    782 		}
    783 		wd, _ := os.Getwd()
    784 		return "", fmt.Errorf("include file not found: %s (wd %s)\nsearch paths:\n\t%s", nm, wd, strings.Join(paths, "\n\t"))
    785 	}
    786 }
    787 
    788 func (c *cpp) actuals(m *Macro, r tokenReader) (varArgs []cppToken, ap [][]cppToken, hs hideSet) {
    789 	var lvl, n int
    790 	varx := len(m.fp)
    791 	if m.namedVariadic {
    792 		varx--
    793 	}
    794 	var last rune
    795 	for {
    796 		t, ok := r.read()
    797 		if !ok {
    798 			c.err(t, "unexpected EOF")
    799 			return nil, nil, nil
    800 		}
    801 
    802 		// 6.10.3, 10
    803 		//
    804 		// Within the sequence of preprocessing tokens making up an
    805 		// invocation of a function-like macro, new-line is considered
    806 		// a normal white-space character.
    807 		if t.char == '\n' {
    808 			t.char = ' '
    809 			t.value = idSpace
    810 		}
    811 		if t.char == ' ' && last == ' ' {
    812 			continue
    813 		}
    814 
    815 		last = t.char
    816 		switch t.char {
    817 		case ',':
    818 			if lvl == 0 {
    819 				if n >= varx && (len(varArgs) != 0 || !isWhite(t.char)) {
    820 					varArgs = append(varArgs, t)
    821 				}
    822 				n++
    823 				continue
    824 			}
    825 		case ')':
    826 			if lvl == 0 {
    827 				for len(ap) < len(m.fp) {
    828 					ap = append(ap, nil)
    829 				}
    830 				for i, v := range ap {
    831 					ap[i] = c.trim(v)
    832 				}
    833 				// for i, v := range ap {
    834 				// 	dbg("%T.actuals %v/%v %q", c, i, len(ap), tokStr(v, "|"))
    835 				// }
    836 				return c.trim(varArgs), ap, t.hs
    837 			}
    838 			lvl--
    839 		case '(':
    840 			lvl++
    841 		}
    842 		if n >= varx && (len(varArgs) != 0 || !isWhite(t.char)) {
    843 			varArgs = append(varArgs, t)
    844 		}
    845 		for len(ap) <= n {
    846 			ap = append(ap, []cppToken{})
    847 		}
    848 		ap[n] = append(ap[n], t)
    849 	}
    850 }
    851 
    852 // [1]pg 2.
    853 //
    854 // subst(IS, FP, AP, HS, OS) /* substitute args, handle stringize and paste */
    855 // {
    856 // 	if IS is {} then
    857 //		// ---------------------------------------------------------- A
    858 // 		return hsadd(HS, OS);
    859 //
    860 // 	else if IS is # • T • IS’ and T is FP[i] then
    861 //		// ---------------------------------------------------------- B
    862 // 		return subst(IS’, FP, AP, HS, OS • stringize(select(i, AP)));
    863 //
    864 // 	else if IS is ## • T • IS’ and T is FP[i] then
    865 //	{
    866 //		// ---------------------------------------------------------- C
    867 // 		if select(i, AP) is {} then /* only if actuals can be empty */
    868 //			// -------------------------------------------------- D
    869 // 			return subst(IS’, FP, AP, HS, OS);
    870 // 		else
    871 //			// -------------------------------------------------- E
    872 // 			return subst(IS’, FP, AP, HS, glue(OS, select(i, AP)));
    873 // 	}
    874 //
    875 // 	else if IS is ## • T^HS’ • IS’ then
    876 //		// ---------------------------------------------------------- F
    877 // 		return subst(IS’, FP, AP, HS, glue(OS, T^HS’));
    878 //
    879 // 	else if IS is T • ##^HS’ • IS’ and T is FP[i] then
    880 //	{
    881 //		// ---------------------------------------------------------- G
    882 // 		if select(i, AP) is {} then /* only if actuals can be empty */
    883 //		{
    884 //			// -------------------------------------------------- H
    885 // 			if IS’ is T’ • IS’’ and T’ is FP[j] then
    886 //				// ------------------------------------------ I
    887 // 				return subst(IS’’, FP, AP, HS, OS • select(j, AP));
    888 // 			else
    889 //				// ------------------------------------------ J
    890 // 				return subst(IS’, FP, AP, HS, OS);
    891 // 		}
    892 //		else
    893 //			// -------------------------------------------------- K
    894 // 			return subst(##^HS’ • IS’, FP, AP, HS, OS • select(i, AP));
    895 //
    896 //	}
    897 //
    898 // 	else if IS is T • IS’ and T is FP[i] then
    899 //		// ---------------------------------------------------------- L
    900 // 		return subst(IS’, FP, AP, HS, OS • expand(select(i, AP)));
    901 //
    902 //	// ------------------------------------------------------------------ M
    903 // 	note IS must be T^HS’ • IS’
    904 // 	return subst(IS’, FP, AP, HS, OS • T^HS’);
    905 // }
    906 //
    907 // A quick overview of subst is that it walks through the input sequence, IS,
    908 // building up an output sequence, OS, by handling each token from left to
    909 // right. (The order that this operation takes is left to the implementation
    910 // also, walking from left to right is more natural since the rest of the
    911 // algorithm is constrained to this ordering.) Stringizing is easy, pasting
    912 // requires trickier handling because the operation has a bunch of
    913 // combinations. After the entire input sequence is finished, the updated hide
    914 // set is applied to the output sequence, and that is the result of subst.
    915 func (c *cpp) subst(m *Macro, is []cppToken, fp []StringID, varArgs []cppToken, ap [][]cppToken, hs hideSet, os *[]cppToken, expandDefined bool) (r []cppToken) {
    916 	var ap0 [][]cppToken
    917 	for _, v := range ap {
    918 		ap0 = append(ap0, append([]cppToken(nil), v...))
    919 	}
    920 	// trc("==== subst: is %q, fp, %v ap@%p %v", cppToksStr(is, "|"), fp, &ap, cppToksStr2(ap))
    921 start:
    922 	// trc("start: is %q, fp %v, ap@%p %v, os %q", cppToksStr(is, "|"), fp, &ap, cppToksStr2(ap), cppToksStr(*os, "|"))
    923 	if len(is) == 0 {
    924 		// ---------------------------------------------------------- A
    925 		// return hsadd(HS, OS);
    926 		// trc("---- A")
    927 		// trc("subst RETURNS %q", cppToksStr(*os, "|"))
    928 		return c.hsAdd(hs, os)
    929 	}
    930 
    931 	tok := is[0]
    932 	var arg []cppToken
    933 	if tok.char == '#' {
    934 		if len(is) > 1 && is[1].char == IDENTIFIER && m.param(varArgs, ap0, is[1].value, &arg) {
    935 			// -------------------------------------------------- B
    936 			// return subst(IS’, FP, AP, HS, OS • stringize(select(i, AP)));
    937 			// trc("---- subst B")
    938 			*os = append(*os, c.stringize(arg))
    939 			is = is[2:]
    940 			goto start
    941 		}
    942 	}
    943 
    944 	if tok.char == PPPASTE {
    945 		if len(is) > 1 && is[1].char == IDENTIFIER && m.param(varArgs, ap0, is[1].value, &arg) {
    946 			// -------------------------------------------------- C
    947 			// trc("---- subst C")
    948 			if len(arg) == 0 {
    949 				// TODO "only if actuals can be empty"
    950 				// ------------------------------------------ D
    951 				// return subst(IS’, FP, AP, HS, OS);
    952 				// trc("---- D")
    953 				if c := len(*os); c != 0 && (*os)[c-1].char == ',' {
    954 					*os = (*os)[:c-1]
    955 				}
    956 				is = is[2:]
    957 				goto start
    958 			}
    959 
    960 			// -------------------------------------------------- E
    961 			// return subst(IS’, FP, AP, HS, glue(OS, select(i, AP)));
    962 			// trc("---- subst E, arg %q", cppToksStr(arg, "|"))
    963 			*os = c.glue(*os, arg)
    964 			is = is[2:]
    965 			goto start
    966 		}
    967 
    968 		if len(is) > 1 {
    969 			// -------------------------------------------------- F
    970 			// return subst(IS’, FP, AP, HS, glue(OS, T^HS’));
    971 			// trc("---- subst F")
    972 			*os = c.glue(*os, is[1:2])
    973 			is = is[2:]
    974 			goto start
    975 		}
    976 	}
    977 
    978 	if tok.char == IDENTIFIER && (len(is) > 1 && is[1].char == PPPASTE) && m.param(varArgs, ap0, tok.value, &arg) {
    979 		// ---------------------------------------------------------- G
    980 		// trc("---- subst G")
    981 		if len(arg) == 0 {
    982 			// TODO "only if actuals can be empty"
    983 			// -------------------------------------------------- H
    984 			// trc("---- subst H")
    985 			is = is[2:] // skip T##
    986 			if len(is) > 0 && is[0].char == IDENTIFIER && m.param(varArgs, ap, is[0].value, &arg) {
    987 				// -------------------------------------------------- I
    988 				// return subst(IS’’, FP, AP, HS, OS • select(j, AP));
    989 				// trc("---- subst I")
    990 				*os = append(*os, arg...)
    991 				is = is[1:]
    992 				goto start
    993 			} else {
    994 				// -------------------------------------------------- J
    995 				// return subst(IS’, FP, AP, HS, OS);
    996 				// trc("---- subst J")
    997 				goto start
    998 			}
    999 		}
   1000 
   1001 		// ---------------------------------------------------------- K
   1002 		// return subst(##^HS’ • IS’, FP, AP, HS, OS • select(i, AP));
   1003 		// trc("---- subst K")
   1004 		*os = append(*os, arg...)
   1005 		is = is[1:]
   1006 		goto start
   1007 	}
   1008 
   1009 	ax := -1
   1010 	if tok.char == IDENTIFIER && m.param2(varArgs, ap, tok.value, &arg, &ax) {
   1011 		// ------------------------------------------ L
   1012 		// return subst(IS’, FP, AP, HS, OS • expand(select(i, AP)));
   1013 		// trc("---- subst L")
   1014 		// if toks, ok := cache[tok.value]; ok {
   1015 		// 	os = append(os, toks...)
   1016 		// 	is = is[1:]
   1017 		// 	goto start
   1018 		// }
   1019 
   1020 		sel := cppReader{buf: arg}
   1021 		var w cppWriter
   1022 		// trc("---- L(1) ap@%p %v", &ap, cppToksStr2(ap))
   1023 		c.expand(&sel, &w, expandDefined)
   1024 		// trc("---- L(2) ap@%p %v", &ap, cppToksStr2(ap))
   1025 		*os = append(*os, w.toks...)
   1026 		if ax >= 0 {
   1027 			ap[ax] = w.toks
   1028 		}
   1029 		is = is[1:]
   1030 		goto start
   1031 	}
   1032 
   1033 	// ------------------------------------------------------------------ M
   1034 	// note IS must be T^HS’ • IS’
   1035 	// return subst(IS’, FP, AP, HS, OS • T^HS’);
   1036 	*os = append(*os, tok)
   1037 	is = is[1:]
   1038 	// trc("---- subst M: is %q, os %q", cppToksStr(is, "|"), cppToksStr(*os, "|"))
   1039 	goto start
   1040 }
   1041 
   1042 // paste last of left side with first of right side
   1043 //
   1044 // [1] pg. 3
   1045 //
   1046 //TODO implement properly [0], 6.10.3.3, 2. Must rescan the resulting token(s).
   1047 //
   1048 // $ cat main.c
   1049 // #include <stdio.h>
   1050 //
   1051 // #define foo(a, b) a ## b
   1052 //
   1053 // int main() {
   1054 // 	int i = 42;
   1055 // 	i foo(+, +);
   1056 // 	printf("%i\n", i);
   1057 // 	return 0;
   1058 // }
   1059 // $ rm -f a.out ; gcc -Wall main.c && ./a.out ; echo $?
   1060 // 43
   1061 // 0
   1062 // $
   1063 //
   1064 // ----------------------------------------------------------------------------
   1065 //	glue(LS,RS ) /* paste last of left side with first of right side */
   1066 //	{
   1067 //		if LS is L^HS and RS is R^HS’ • RS’ then
   1068 //			return L&R^(HS∩HS’) • RS’;	/* undefined if L&R is invalid */
   1069 
   1070 //		// note LS must be L HS • LS’
   1071 //		return L^HS • glue(LS’,RS );
   1072 //	}
   1073 func (c *cpp) glue(ls, rs []cppToken) (out []cppToken) {
   1074 	// trc("ls %q, rs %q", cppToksStr(ls, "|"), cppToksStr(rs, "|"))
   1075 	if len(rs) == 0 {
   1076 		return ls
   1077 	}
   1078 
   1079 	if len(ls) == 0 {
   1080 		return rs
   1081 	}
   1082 
   1083 	l := ls[len(ls)-1]
   1084 	ls = ls[:len(ls)-1]
   1085 	r := rs[0]
   1086 	rs = rs[1:]
   1087 
   1088 	if l.char == IDENTIFIER && l.value == idL && r.char == STRINGLITERAL {
   1089 		l.char = LONGSTRINGLITERAL
   1090 	}
   1091 	l.value = dict.sid(l.String() + r.String())
   1092 	return append(append(ls, l), rs...)
   1093 }
   1094 
   1095 // Given a token sequence, stringize returns a single string literal token
   1096 // containing the concatenated spellings of the tokens.
   1097 //
   1098 // [1] pg. 3
   1099 func (c *cpp) stringize(s0 []cppToken) (r cppToken) {
   1100 	// 6.10.3.2
   1101 	//
   1102 	// Each occurrence of white space between the argument’s preprocessing
   1103 	// tokens becomes a single space character in the character string
   1104 	// literal.
   1105 	s := make([]cppToken, 0, len(s0))
   1106 	var last rune
   1107 	for i := range s0 {
   1108 		t := s0[i]
   1109 		if isWhite(t.char) {
   1110 			t.char = ' '
   1111 			t.value = idSpace
   1112 			if last == ' ' {
   1113 				continue
   1114 			}
   1115 		}
   1116 
   1117 		last = t.char
   1118 		s = append(s, t)
   1119 	}
   1120 
   1121 	// White space before the first preprocessing token and after the last
   1122 	// preprocessing token composing the argument is deleted.
   1123 	s = c.trim(s)
   1124 
   1125 	// The character string literal corresponding to an empty argument is
   1126 	// ""
   1127 	if len(s) == 0 {
   1128 		r.hs = nil
   1129 		r.char = STRINGLITERAL
   1130 		r.value = idEmptyString
   1131 		return r
   1132 	}
   1133 
   1134 	var a []string
   1135 	// Otherwise, the original spelling of each preprocessing token in the
   1136 	// argument is retained in the character string literal, except for
   1137 	// special handling for producing the spelling of string literals and
   1138 	// character constants: a \ character is inserted before each " and \
   1139 	// character of a character constant or string literal (including the
   1140 	// delimiting " characters), except that it is implementation-defined
   1141 	// whether a \ character is inserted before the \ character beginning a
   1142 	// universal character name.
   1143 	for _, v := range s {
   1144 		s := v.String()
   1145 		switch v.char {
   1146 		case CHARCONST, STRINGLITERAL:
   1147 			s = strings.ReplaceAll(s, `\`, `\\`)
   1148 			s = strings.ReplaceAll(s, `"`, `\"`)
   1149 		case LONGCHARCONST, LONGSTRINGLITERAL:
   1150 			panic("TODO")
   1151 		}
   1152 		a = append(a, s)
   1153 	}
   1154 	r = s[0]
   1155 	r.hs = nil
   1156 	r.char = STRINGLITERAL
   1157 	r.value = dict.sid(`"` + strings.Join(a, "") + `"`)
   1158 	return r
   1159 }
   1160 
   1161 func (c *cpp) trim(toks []cppToken) []cppToken {
   1162 	for len(toks) != 0 && isWhite(toks[0].char) {
   1163 		toks = toks[1:]
   1164 	}
   1165 	for len(toks) != 0 && isWhite(toks[len(toks)-1].char) {
   1166 		toks = toks[:len(toks)-1]
   1167 	}
   1168 	return toks
   1169 }
   1170 
   1171 func (c *cpp) hsAdd(hs hideSet, toks *[]cppToken) []cppToken {
   1172 	for i, v := range *toks {
   1173 		if v.hs == nil {
   1174 			v.hs = hideSet{}
   1175 		}
   1176 		for k, w := range hs {
   1177 			v.hs[k] = w
   1178 		}
   1179 		v.file = c.file
   1180 		(*toks)[i] = v
   1181 	}
   1182 	return *toks
   1183 }
   1184 
   1185 func (c *cpp) parseDefined(tok cppToken, r tokenReader, w tokenWriter) {
   1186 	toks := []cppToken{tok}
   1187 	if tok = c.scanToNonBlankToken(&toks, r, w); tok.char < 0 {
   1188 		return
   1189 	}
   1190 
   1191 	switch tok.char {
   1192 	case IDENTIFIER:
   1193 		// ok
   1194 	case '(':
   1195 		if tok = c.scanToNonBlankToken(&toks, r, w); tok.char < 0 {
   1196 			return
   1197 		}
   1198 
   1199 		if tok.char != IDENTIFIER {
   1200 			w.writes(toks)
   1201 			return
   1202 		}
   1203 
   1204 		tok2 := c.scanToNonBlankToken(&toks, r, w)
   1205 		if tok2.char < 0 {
   1206 			return
   1207 		}
   1208 
   1209 		if tok2.char != ')' {
   1210 			w.writes(toks)
   1211 			return
   1212 		}
   1213 	}
   1214 
   1215 	tok.char = PPNUMBER
   1216 	switch _, ok := c.macros[tok.value]; {
   1217 	case ok:
   1218 		tok.value = idOne
   1219 	default:
   1220 		tok.value = idZero
   1221 	}
   1222 	w.write(tok)
   1223 }
   1224 
   1225 func (c *cpp) scanToNonBlankToken(toks *[]cppToken, r tokenReader, w tokenWriter) cppToken {
   1226 	tok, ok := r.read()
   1227 	if !ok {
   1228 		w.writes(*toks)
   1229 		tok.char = -1
   1230 		return tok
   1231 	}
   1232 
   1233 	*toks = append(*toks, tok)
   1234 	if tok.char == ' ' || tok.char == '\n' {
   1235 		if tok, ok = r.read(); !ok {
   1236 			w.writes(*toks)
   1237 			tok.char = -1
   1238 			return tok
   1239 		}
   1240 
   1241 		*toks = append(*toks, tok)
   1242 	}
   1243 	return (*toks)[len(*toks)-1]
   1244 }
   1245 
   1246 // [0], 6.10.1
   1247 func (c *cpp) evalInclusionCondition(expr []token3) (r bool) {
   1248 	if !c.intmaxChecked {
   1249 		if m := c.macros[idIntMaxWidth]; m != nil && len(m.repl) != 0 {
   1250 			if val := c.intMaxWidth(); val != 0 && val != 64 {
   1251 				c.err(m.name, "%s is %v, but only 64 is supported", idIntMaxWidth, val)
   1252 			}
   1253 		}
   1254 		c.intmaxChecked = true
   1255 	}
   1256 
   1257 	val := c.eval(expr)
   1258 	return val != nil && c.isNonZero(val)
   1259 }
   1260 
   1261 func (c *cpp) intMaxWidth() int64 {
   1262 	if m := c.macros[idIntMaxWidth]; m != nil && len(m.repl) != 0 {
   1263 		switch x := c.eval(m.repl).(type) {
   1264 		case nil:
   1265 			return 0
   1266 		case int64:
   1267 			return x
   1268 		case uint64:
   1269 			return int64(x)
   1270 		default:
   1271 			panic(internalError())
   1272 		}
   1273 	}
   1274 	return 0
   1275 }
   1276 
   1277 func (c *cpp) eval(expr []token3) interface{} {
   1278 	toks := make([]cppToken, len(expr))
   1279 	for i, v := range expr {
   1280 		toks[i] = cppToken{token4{token3: v}, nil}
   1281 	}
   1282 	var w cppWriter
   1283 	c.expand(&cppReader{buf: toks}, &w, true)
   1284 	toks = w.toks
   1285 	p := 0
   1286 	for _, v := range toks {
   1287 		switch v.char {
   1288 		case ' ', '\n':
   1289 			// nop
   1290 		default:
   1291 			toks[p] = v
   1292 			p++
   1293 		}
   1294 	}
   1295 	toks = toks[:p]
   1296 	s := cppScanner(toks)
   1297 	val := c.expression(&s, true)
   1298 	switch s.peek().char {
   1299 	case -1, '#':
   1300 		// ok
   1301 	default:
   1302 		t := s.peek()
   1303 		c.err(t, "unexpected %s", tokName(t.char))
   1304 		return nil
   1305 	}
   1306 	return val
   1307 }
   1308 
   1309 // [0], 6.5.17 Comma operator
   1310 //
   1311 //  expression:
   1312 // 	assignment-expression
   1313 // 	expression , assignment-expression
   1314 func (c *cpp) expression(s *cppScanner, eval bool) interface{} {
   1315 	for {
   1316 		r := c.assignmentExpression(s, eval)
   1317 		if s.peek().char != ',' {
   1318 			return r
   1319 		}
   1320 
   1321 		s.next()
   1322 	}
   1323 }
   1324 
   1325 // [0], 6.5.16 Assignment operators
   1326 //
   1327 //  assignment-expression:
   1328 // 	conditional-expression
   1329 // 	unary-expression assignment-operator assignment-expression
   1330 //
   1331 //  assignment-operator: one of
   1332 // 	= *= /= %= += -= <<= >>= &= ^= |=
   1333 func (c *cpp) assignmentExpression(s *cppScanner, eval bool) interface{} {
   1334 	return c.conditionalExpression(s, eval)
   1335 }
   1336 
   1337 // [0], 6.5.15 Conditional operator
   1338 //
   1339 //  conditional-expression:
   1340 //		logical-OR-expression
   1341 //		logical-OR-expression ? expression : conditional-expression
   1342 func (c *cpp) conditionalExpression(s *cppScanner, eval bool) interface{} {
   1343 	expr := c.logicalOrExpression(s, eval)
   1344 	if s.peek().char == '?' {
   1345 		s.next()
   1346 		exprIsNonZero := c.isNonZero(expr)
   1347 		expr2 := c.conditionalExpression(s, exprIsNonZero)
   1348 		if tok := s.peek(); tok.char != ':' {
   1349 			c.err(tok, "expected ':'")
   1350 			return expr
   1351 		}
   1352 
   1353 		s.next()
   1354 		expr3 := c.conditionalExpression(s, !exprIsNonZero)
   1355 
   1356 		// [0] 6.5.15
   1357 		//
   1358 		// 5. If both the second and third operands have arithmetic type, the result
   1359 		// type that would be determined by the usual arithmetic conversions, were they
   1360 		// applied to those two operands, is the type of the result.
   1361 		x := c.operand(expr2)
   1362 		y := c.operand(expr3)
   1363 		if x != nil && y != nil {
   1364 			x, y = usualArithmeticConversions(c.ctx, nil, x, y, false)
   1365 			expr2 = c.fromOperand(x)
   1366 			expr3 = c.fromOperand(y)
   1367 		}
   1368 
   1369 		switch {
   1370 		case exprIsNonZero:
   1371 			expr = expr2
   1372 		default:
   1373 			expr = expr3
   1374 		}
   1375 	}
   1376 	return expr
   1377 }
   1378 
   1379 func (c *cpp) operand(v interface{}) Operand {
   1380 	switch x := v.(type) {
   1381 	case int64:
   1382 		return &operand{typ: &typeBase{size: 8, kind: byte(LongLong), flags: fSigned}, value: Int64Value(x)}
   1383 	case uint64:
   1384 		return &operand{typ: &typeBase{size: 8, kind: byte(ULongLong)}, value: Uint64Value(x)}
   1385 	default:
   1386 		return nil
   1387 	}
   1388 }
   1389 
   1390 func (c *cpp) fromOperand(op Operand) interface{} {
   1391 	switch x := op.Value().(type) {
   1392 	case Int64Value:
   1393 		return int64(x)
   1394 	case Uint64Value:
   1395 		return uint64(x)
   1396 	default:
   1397 		return nil
   1398 	}
   1399 }
   1400 
   1401 // [0], 6.5.14 Logical OR operator
   1402 //
   1403 //  logical-OR-expression:
   1404 //		logical-AND-expression
   1405 //		logical-OR-expression || logical-AND-expression
   1406 func (c *cpp) logicalOrExpression(s *cppScanner, eval bool) interface{} {
   1407 	lhs := c.logicalAndExpression(s, eval)
   1408 	for s.peek().char == OROR {
   1409 		s.next()
   1410 		if c.isNonZero(lhs) {
   1411 			eval = false
   1412 		}
   1413 		rhs := c.logicalAndExpression(s, eval)
   1414 		if c.isNonZero(lhs) || c.isNonZero(rhs) {
   1415 			lhs = int64(1)
   1416 		}
   1417 	}
   1418 	return lhs
   1419 }
   1420 
   1421 // [0], 6.5.13 Logical AND operator
   1422 //
   1423 //  logical-AND-expression:
   1424 //		inclusive-OR-expression
   1425 //		logical-AND-expression && inclusive-OR-expression
   1426 func (c *cpp) logicalAndExpression(s *cppScanner, eval bool) interface{} {
   1427 	lhs := c.inclusiveOrExpression(s, eval)
   1428 	for s.peek().char == ANDAND {
   1429 		s.next()
   1430 		if c.isZero(lhs) {
   1431 			eval = false
   1432 		}
   1433 		rhs := c.inclusiveOrExpression(s, eval)
   1434 		if c.isZero(lhs) || c.isZero(rhs) {
   1435 			lhs = int64(0)
   1436 		}
   1437 	}
   1438 	return lhs
   1439 }
   1440 
   1441 func (c *cpp) isZero(val interface{}) bool {
   1442 	switch x := val.(type) {
   1443 	case int64:
   1444 		return x == 0
   1445 	case uint64:
   1446 		return x == 0
   1447 	}
   1448 	panic(internalError())
   1449 }
   1450 
   1451 // [0], 6.5.12 Bitwise inclusive OR operator
   1452 //
   1453 //  inclusive-OR-expression:
   1454 //		exclusive-OR-expression
   1455 //		inclusive-OR-expression | exclusive-OR-expression
   1456 func (c *cpp) inclusiveOrExpression(s *cppScanner, eval bool) interface{} {
   1457 	lhs := c.exclusiveOrExpression(s, eval)
   1458 	for s.peek().char == '|' {
   1459 		s.next()
   1460 		rhs := c.exclusiveOrExpression(s, eval)
   1461 		if eval {
   1462 			switch x := lhs.(type) {
   1463 			case int64:
   1464 				switch y := rhs.(type) {
   1465 				case int64:
   1466 					lhs = x | y
   1467 				case uint64:
   1468 					lhs = uint64(x) | y
   1469 				}
   1470 			case uint64:
   1471 				switch y := rhs.(type) {
   1472 				case int64:
   1473 					lhs = x | uint64(y)
   1474 				case uint64:
   1475 					lhs = x | y
   1476 				}
   1477 			}
   1478 		}
   1479 	}
   1480 	return lhs
   1481 }
   1482 
   1483 // [0], 6.5.11 Bitwise exclusive OR operator
   1484 //
   1485 //  exclusive-OR-expression:
   1486 //		AND-expression
   1487 //		exclusive-OR-expression ^ AND-expression
   1488 func (c *cpp) exclusiveOrExpression(s *cppScanner, eval bool) interface{} {
   1489 	lhs := c.andExpression(s, eval)
   1490 	for s.peek().char == '^' {
   1491 		s.next()
   1492 		rhs := c.andExpression(s, eval)
   1493 		if eval {
   1494 			switch x := lhs.(type) {
   1495 			case int64:
   1496 				switch y := rhs.(type) {
   1497 				case int64:
   1498 					lhs = x ^ y
   1499 				case uint64:
   1500 					lhs = uint64(x) ^ y
   1501 				}
   1502 			case uint64:
   1503 				switch y := rhs.(type) {
   1504 				case int64:
   1505 					lhs = x ^ uint64(y)
   1506 				case uint64:
   1507 					lhs = x ^ y
   1508 				}
   1509 			}
   1510 		}
   1511 	}
   1512 	return lhs
   1513 }
   1514 
   1515 // [0], 6.5.10 Bitwise AND operator
   1516 //
   1517 //  AND-expression:
   1518 // 		equality-expression
   1519 // 		AND-expression & equality-expression
   1520 func (c *cpp) andExpression(s *cppScanner, eval bool) interface{} {
   1521 	lhs := c.equalityExpression(s, eval)
   1522 	for s.peek().char == '&' {
   1523 		s.next()
   1524 		rhs := c.equalityExpression(s, eval)
   1525 		if eval {
   1526 			switch x := lhs.(type) {
   1527 			case int64:
   1528 				switch y := rhs.(type) {
   1529 				case int64:
   1530 					lhs = x & y
   1531 				case uint64:
   1532 					lhs = uint64(x) & y
   1533 				}
   1534 			case uint64:
   1535 				switch y := rhs.(type) {
   1536 				case int64:
   1537 					lhs = x & uint64(y)
   1538 				case uint64:
   1539 					lhs = x & y
   1540 				}
   1541 			}
   1542 		}
   1543 	}
   1544 	return lhs
   1545 }
   1546 
   1547 // [0], 6.5.9 Equality operators
   1548 //
   1549 //  equality-expression:
   1550 //		relational-expression
   1551 //		equality-expression == relational-expression
   1552 //		equality-expression != relational-expression
   1553 func (c *cpp) equalityExpression(s *cppScanner, eval bool) interface{} {
   1554 	lhs := c.relationalExpression(s, eval)
   1555 	for {
   1556 		var v bool
   1557 		switch s.peek().char {
   1558 		case EQ:
   1559 			s.next()
   1560 			rhs := c.relationalExpression(s, eval)
   1561 			if eval {
   1562 				switch x := lhs.(type) {
   1563 				case int64:
   1564 					switch y := rhs.(type) {
   1565 					case int64:
   1566 						v = x == y
   1567 					case uint64:
   1568 						v = uint64(x) == y
   1569 					}
   1570 				case uint64:
   1571 					switch y := rhs.(type) {
   1572 					case int64:
   1573 						v = x == uint64(y)
   1574 					case uint64:
   1575 						v = x == y
   1576 					}
   1577 				}
   1578 			}
   1579 		case NEQ:
   1580 			s.next()
   1581 			rhs := c.relationalExpression(s, eval)
   1582 			if eval {
   1583 				switch x := lhs.(type) {
   1584 				case int64:
   1585 					switch y := rhs.(type) {
   1586 					case int64:
   1587 						v = x != y
   1588 					case uint64:
   1589 						v = uint64(x) != y
   1590 					}
   1591 				case uint64:
   1592 					switch y := rhs.(type) {
   1593 					case int64:
   1594 						v = x != uint64(y)
   1595 					case uint64:
   1596 						v = x != y
   1597 					}
   1598 				}
   1599 			}
   1600 		default:
   1601 			return lhs
   1602 		}
   1603 		switch {
   1604 		case v:
   1605 			lhs = int64(1)
   1606 		default:
   1607 			lhs = int64(0)
   1608 		}
   1609 	}
   1610 }
   1611 
   1612 // [0], 6.5.8 Relational operators
   1613 //
   1614 //  relational-expression:
   1615 //		shift-expression
   1616 //		relational-expression <  shift-expression
   1617 //		relational-expression >  shift-expression
   1618 //		relational-expression <= shift-expression
   1619 //		relational-expression >= shift-expression
   1620 func (c *cpp) relationalExpression(s *cppScanner, eval bool) interface{} {
   1621 	lhs := c.shiftExpression(s, eval)
   1622 	for {
   1623 		var v bool
   1624 		switch s.peek().char {
   1625 		case '<':
   1626 			s.next()
   1627 			rhs := c.shiftExpression(s, eval)
   1628 			if eval {
   1629 				switch x := lhs.(type) {
   1630 				case int64:
   1631 					switch y := rhs.(type) {
   1632 					case int64:
   1633 						v = x < y
   1634 					case uint64:
   1635 						v = uint64(x) < y
   1636 					}
   1637 				case uint64:
   1638 					switch y := rhs.(type) {
   1639 					case int64:
   1640 						v = x < uint64(y)
   1641 					case uint64:
   1642 						v = x < y
   1643 					}
   1644 				}
   1645 			}
   1646 		case '>':
   1647 			s.next()
   1648 			rhs := c.shiftExpression(s, eval)
   1649 			if eval {
   1650 				switch x := lhs.(type) {
   1651 				case int64:
   1652 					switch y := rhs.(type) {
   1653 					case int64:
   1654 						v = x > y
   1655 					case uint64:
   1656 						v = uint64(x) > y
   1657 					}
   1658 				case uint64:
   1659 					switch y := rhs.(type) {
   1660 					case int64:
   1661 						v = x > uint64(y)
   1662 					case uint64:
   1663 						v = x > y
   1664 					}
   1665 				}
   1666 			}
   1667 		case LEQ:
   1668 			s.next()
   1669 			rhs := c.shiftExpression(s, eval)
   1670 			if eval {
   1671 				switch x := lhs.(type) {
   1672 				case int64:
   1673 					switch y := rhs.(type) {
   1674 					case int64:
   1675 						v = x <= y
   1676 					case uint64:
   1677 						v = uint64(x) <= y
   1678 					}
   1679 				case uint64:
   1680 					switch y := rhs.(type) {
   1681 					case int64:
   1682 						v = x <= uint64(y)
   1683 					case uint64:
   1684 						v = x <= y
   1685 					}
   1686 				}
   1687 			}
   1688 		case GEQ:
   1689 			s.next()
   1690 			rhs := c.shiftExpression(s, eval)
   1691 			if eval {
   1692 				switch x := lhs.(type) {
   1693 				case int64:
   1694 					switch y := rhs.(type) {
   1695 					case int64:
   1696 						v = x >= y
   1697 					case uint64:
   1698 						v = uint64(x) >= y
   1699 					}
   1700 				case uint64:
   1701 					switch y := rhs.(type) {
   1702 					case int64:
   1703 						v = x >= uint64(y)
   1704 					case uint64:
   1705 						v = x >= y
   1706 					}
   1707 				}
   1708 			}
   1709 		default:
   1710 			return lhs
   1711 		}
   1712 		switch {
   1713 		case v:
   1714 			lhs = int64(1)
   1715 		default:
   1716 			lhs = int64(0)
   1717 		}
   1718 	}
   1719 }
   1720 
   1721 // [0], 6.5.7 Bitwise shift operators
   1722 //
   1723 //  shift-expression:
   1724 //		additive-expression
   1725 //		shift-expression << additive-expression
   1726 //		shift-expression >> additive-expression
   1727 func (c *cpp) shiftExpression(s *cppScanner, eval bool) interface{} {
   1728 	lhs := c.additiveExpression(s, eval)
   1729 	for {
   1730 		switch s.peek().char {
   1731 		case LSH:
   1732 			s.next()
   1733 			rhs := c.additiveExpression(s, eval)
   1734 			if eval {
   1735 				switch x := lhs.(type) {
   1736 				case int64:
   1737 					switch y := rhs.(type) {
   1738 					case int64:
   1739 						lhs = x << uint(y)
   1740 					case uint64:
   1741 						lhs = uint64(x) << uint(y)
   1742 					}
   1743 				case uint64:
   1744 					switch y := rhs.(type) {
   1745 					case int64:
   1746 						lhs = x << uint(y)
   1747 					case uint64:
   1748 						lhs = x << uint(y)
   1749 					}
   1750 				}
   1751 			}
   1752 		case RSH:
   1753 			s.next()
   1754 			rhs := c.additiveExpression(s, eval)
   1755 			if eval {
   1756 				switch x := lhs.(type) {
   1757 				case int64:
   1758 					switch y := rhs.(type) {
   1759 					case int64:
   1760 						lhs = x >> uint(y)
   1761 					case uint64:
   1762 						lhs = uint64(x) >> uint(y)
   1763 					}
   1764 				case uint64:
   1765 					switch y := rhs.(type) {
   1766 					case int64:
   1767 						lhs = x >> uint(y)
   1768 					case uint64:
   1769 						lhs = x >> uint(y)
   1770 					}
   1771 				}
   1772 			}
   1773 		default:
   1774 			return lhs
   1775 		}
   1776 	}
   1777 }
   1778 
   1779 // [0], 6.5.6 Additive operators
   1780 //
   1781 //  additive-expression:
   1782 //		multiplicative-expression
   1783 //		additive-expression + multiplicative-expression
   1784 //		additive-expression - multiplicative-expression
   1785 func (c *cpp) additiveExpression(s *cppScanner, eval bool) interface{} {
   1786 	lhs := c.multiplicativeExpression(s, eval)
   1787 	for {
   1788 		switch s.peek().char {
   1789 		case '+':
   1790 			s.next()
   1791 			rhs := c.multiplicativeExpression(s, eval)
   1792 			if eval {
   1793 				switch x := lhs.(type) {
   1794 				case int64:
   1795 					switch y := rhs.(type) {
   1796 					case int64:
   1797 						lhs = x + y
   1798 					case uint64:
   1799 						lhs = uint64(x) + y
   1800 					}
   1801 				case uint64:
   1802 					switch y := rhs.(type) {
   1803 					case int64:
   1804 						lhs = x + uint64(y)
   1805 					case uint64:
   1806 						lhs = x + y
   1807 					}
   1808 				}
   1809 			}
   1810 		case '-':
   1811 			s.next()
   1812 			rhs := c.multiplicativeExpression(s, eval)
   1813 			if eval {
   1814 				switch x := lhs.(type) {
   1815 				case int64:
   1816 					switch y := rhs.(type) {
   1817 					case int64:
   1818 						lhs = x - y
   1819 					case uint64:
   1820 						lhs = uint64(x) - y
   1821 					}
   1822 				case uint64:
   1823 					switch y := rhs.(type) {
   1824 					case int64:
   1825 						lhs = x - uint64(y)
   1826 					case uint64:
   1827 						lhs = x - y
   1828 					}
   1829 				}
   1830 			}
   1831 		default:
   1832 			return lhs
   1833 		}
   1834 	}
   1835 }
   1836 
   1837 // [0], 6.5.5 Multiplicative operators
   1838 //
   1839 //  multiplicative-expression:
   1840 //		unary-expression // [0], 6.10.1, 1.
   1841 //		multiplicative-expression * unary-expression
   1842 //		multiplicative-expression / unary-expression
   1843 //		multiplicative-expression % unary-expression
   1844 func (c *cpp) multiplicativeExpression(s *cppScanner, eval bool) interface{} {
   1845 	lhs := c.unaryExpression(s, eval)
   1846 	for {
   1847 		switch s.peek().char {
   1848 		case '*':
   1849 			s.next()
   1850 			rhs := c.unaryExpression(s, eval)
   1851 			if eval {
   1852 				switch x := lhs.(type) {
   1853 				case int64:
   1854 					switch y := rhs.(type) {
   1855 					case int64:
   1856 						lhs = x * y
   1857 					case uint64:
   1858 						lhs = uint64(x) * y
   1859 					}
   1860 				case uint64:
   1861 					switch y := rhs.(type) {
   1862 					case int64:
   1863 						lhs = x * uint64(y)
   1864 					case uint64:
   1865 						lhs = x * y
   1866 					}
   1867 				}
   1868 			}
   1869 		case '/':
   1870 			tok := s.next()
   1871 			rhs := c.unaryExpression(s, eval)
   1872 			if eval {
   1873 				switch x := lhs.(type) {
   1874 				case int64:
   1875 					switch y := rhs.(type) {
   1876 					case int64:
   1877 						if y == 0 {
   1878 							c.err(tok, "division by zero")
   1879 							break
   1880 						}
   1881 
   1882 						lhs = x / y
   1883 					case uint64:
   1884 						if y == 0 {
   1885 							c.err(tok, "division by zero")
   1886 							break
   1887 						}
   1888 
   1889 						lhs = uint64(x) / y
   1890 					}
   1891 				case uint64:
   1892 					switch y := rhs.(type) {
   1893 					case int64:
   1894 						if y == 0 {
   1895 							c.err(tok, "division by zero")
   1896 							break
   1897 						}
   1898 
   1899 						lhs = x / uint64(y)
   1900 					case uint64:
   1901 						if y == 0 {
   1902 							c.err(tok, "division by zero")
   1903 							break
   1904 						}
   1905 
   1906 						lhs = x / y
   1907 					}
   1908 				}
   1909 			}
   1910 		case '%':
   1911 			tok := s.next()
   1912 			rhs := c.unaryExpression(s, eval)
   1913 			if eval {
   1914 				switch x := lhs.(type) {
   1915 				case int64:
   1916 					switch y := rhs.(type) {
   1917 					case int64:
   1918 						if y == 0 {
   1919 							c.err(tok, "division by zero")
   1920 							break
   1921 						}
   1922 
   1923 						lhs = x % y
   1924 					case uint64:
   1925 						if y == 0 {
   1926 							c.err(tok, "division by zero")
   1927 							break
   1928 						}
   1929 
   1930 						lhs = uint64(x) % y
   1931 					}
   1932 				case uint64:
   1933 					switch y := rhs.(type) {
   1934 					case int64:
   1935 						if y == 0 {
   1936 							c.err(tok, "division by zero")
   1937 							break
   1938 						}
   1939 
   1940 						lhs = x % uint64(y)
   1941 					case uint64:
   1942 						if y == 0 {
   1943 							c.err(tok, "division by zero")
   1944 							break
   1945 						}
   1946 
   1947 						lhs = x % y
   1948 					}
   1949 				}
   1950 			}
   1951 		default:
   1952 			return lhs
   1953 		}
   1954 	}
   1955 }
   1956 
   1957 // [0], 6.5.3 Unary operators
   1958 //
   1959 //  unary-expression:
   1960 //		primary-expression
   1961 //		unary-operator unary-expression
   1962 //
   1963 //  unary-operator: one of
   1964 //		+ - ~ !
   1965 func (c *cpp) unaryExpression(s *cppScanner, eval bool) interface{} {
   1966 	switch s.peek().char {
   1967 	case '+':
   1968 		s.next()
   1969 		return c.unaryExpression(s, eval)
   1970 	case '-':
   1971 		s.next()
   1972 		expr := c.unaryExpression(s, eval)
   1973 		if eval {
   1974 			switch x := expr.(type) {
   1975 			case int64:
   1976 				expr = -x
   1977 			case uint64:
   1978 				expr = -x
   1979 			}
   1980 		}
   1981 		return expr
   1982 	case '~':
   1983 		s.next()
   1984 		expr := c.unaryExpression(s, eval)
   1985 		if eval {
   1986 			switch x := expr.(type) {
   1987 			case int64:
   1988 				expr = ^x
   1989 			case uint64:
   1990 				expr = ^x
   1991 			}
   1992 		}
   1993 		return expr
   1994 	case '!':
   1995 		s.next()
   1996 		expr := c.unaryExpression(s, eval)
   1997 		if eval {
   1998 			var v bool
   1999 			switch x := expr.(type) {
   2000 			case int64:
   2001 				v = x == 0
   2002 			case uint64:
   2003 				v = x == 0
   2004 			}
   2005 			switch {
   2006 			case v:
   2007 				expr = int64(1)
   2008 			default:
   2009 				expr = int64(0)
   2010 			}
   2011 		}
   2012 		return expr
   2013 	default:
   2014 		return c.primaryExpression(s, eval)
   2015 	}
   2016 }
   2017 
   2018 // [0], 6.5.1 Primary expressions
   2019 //
   2020 //  primary-expression:
   2021 //		identifier
   2022 //		constant
   2023 //		( expression )
   2024 func (c *cpp) primaryExpression(s *cppScanner, eval bool) interface{} {
   2025 	switch tok := s.peek(); tok.char {
   2026 	case CHARCONST, LONGCHARCONST:
   2027 		s.next()
   2028 		r := charConst(c.ctx, tok)
   2029 		return int64(r)
   2030 	case IDENTIFIER:
   2031 		if c.ctx.evalIdentError {
   2032 			panic("cannot evaluate identifier")
   2033 		}
   2034 
   2035 		s.next()
   2036 		if s.peek().char == '(' {
   2037 			s.next()
   2038 			n := 1
   2039 		loop:
   2040 			for n != 0 {
   2041 				switch s.peek().char {
   2042 				case '(':
   2043 					n++
   2044 				case ')':
   2045 					n--
   2046 				case -1:
   2047 					c.err(s.peek(), "expected )")
   2048 					break loop
   2049 				}
   2050 				s.next()
   2051 			}
   2052 		}
   2053 		return int64(0)
   2054 	case PPNUMBER:
   2055 		s.next()
   2056 		return c.intConst(tok)
   2057 	case '(':
   2058 		s.next()
   2059 		expr := c.expression(s, eval)
   2060 		if s.peek().char == ')' {
   2061 			s.next()
   2062 		}
   2063 		return expr
   2064 	default:
   2065 		return int64(0)
   2066 	}
   2067 }
   2068 
   2069 // [0], 6.4.4.1 Integer constants
   2070 //
   2071 //  integer-constant:
   2072 //		decimal-constant integer-suffix_opt
   2073 //		octal-constant integer-suffix_opt
   2074 //		hexadecimal-constant integer-suffix_opt
   2075 //
   2076 //  decimal-constant:
   2077 //		nonzero-digit
   2078 //		decimal-constant digit
   2079 //
   2080 //  octal-constant:
   2081 //		0
   2082 //		octal-constant octal-digit
   2083 //
   2084 //  hexadecimal-prefix: one of
   2085 //		0x 0X
   2086 //
   2087 //  integer-suffix_opt: one of
   2088 //		u ul ull l lu ll llu
   2089 func (c *cpp) intConst(tok cppToken) (r interface{}) {
   2090 	var n uint64
   2091 	s0 := tok.String()
   2092 	s := strings.TrimRight(s0, "uUlL")
   2093 	switch {
   2094 	case strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X"):
   2095 		var err error
   2096 		if n, err = strconv.ParseUint(s[2:], 16, 64); err != nil {
   2097 			c.err(tok, "%v", err)
   2098 			return int64(0)
   2099 		}
   2100 	case strings.HasPrefix(s, "0"):
   2101 		var err error
   2102 		if n, err = strconv.ParseUint(s, 8, 64); err != nil {
   2103 			c.err(tok, "%v", err)
   2104 			return int64(0)
   2105 		}
   2106 	default:
   2107 		var err error
   2108 		if n, err = strconv.ParseUint(s, 10, 64); err != nil {
   2109 			c.err(tok, "%v", err)
   2110 			return int64(0)
   2111 		}
   2112 	}
   2113 
   2114 	suffix := s0[len(s):]
   2115 	if suffix == "" {
   2116 		if n > math.MaxInt64 {
   2117 			return n
   2118 		}
   2119 
   2120 		return int64(n)
   2121 	}
   2122 
   2123 	switch suffix = strings.ToLower(suffix); suffix {
   2124 	default:
   2125 		c.err(tok, "invalid suffix: %v", s0)
   2126 		fallthrough
   2127 	case
   2128 		"l",
   2129 		"ll":
   2130 
   2131 		if n > math.MaxInt64 {
   2132 			return n
   2133 		}
   2134 
   2135 		return int64(n)
   2136 	case
   2137 		"llu",
   2138 		"lu",
   2139 		"u",
   2140 		"ul",
   2141 		"ull":
   2142 
   2143 		return n
   2144 	}
   2145 }
   2146 
   2147 func charConst(ctx *context, tok cppToken) rune {
   2148 	s := tok.String()
   2149 	switch tok.char {
   2150 	case LONGCHARCONST:
   2151 		s = s[1:] // Remove leading 'L'.
   2152 		fallthrough
   2153 	case CHARCONST:
   2154 		s = s[1 : len(s)-1] // Remove outer 's.
   2155 		if len(s) == 1 {
   2156 			return rune(s[0])
   2157 		}
   2158 
   2159 		var r rune
   2160 		var n int
   2161 		switch s[0] {
   2162 		case '\\':
   2163 			r, n = decodeEscapeSequence(ctx, tok, s)
   2164 			if r < 0 {
   2165 				r = -r
   2166 			}
   2167 		default:
   2168 			r, n = utf8.DecodeRuneInString(s)
   2169 		}
   2170 		if n != len(s) {
   2171 			ctx.errNode(&tok, "invalid character constant")
   2172 		}
   2173 		return r
   2174 	}
   2175 	panic(internalError())
   2176 }
   2177 
   2178 // escape-sequence		{simple-sequence}|{octal-escape-sequence}|{hexadecimal-escape-sequence}|{universal-character-name}
   2179 // simple-sequence		\\['\x22?\\abfnrtv]
   2180 // octal-escape-sequence	\\{octal-digit}{octal-digit}?{octal-digit}?
   2181 // hexadecimal-escape-sequence	\\x{hexadecimal-digit}+
   2182 func decodeEscapeSequence(ctx *context, tok cppToken, s string) (rune, int) {
   2183 	if s[0] != '\\' {
   2184 		panic(internalError())
   2185 	}
   2186 
   2187 	if len(s) == 1 {
   2188 		return rune(s[0]), 1
   2189 	}
   2190 
   2191 	r := rune(s[1])
   2192 	switch r {
   2193 	case '\'', '"', '?', '\\':
   2194 		return r, 2
   2195 	case 'a':
   2196 		return 7, 2
   2197 	case 'b':
   2198 		return 8, 2
   2199 	case 'e':
   2200 		return 0x1b, 2
   2201 	case 'f':
   2202 		return 12, 2
   2203 	case 'n':
   2204 		return 10, 2
   2205 	case 'r':
   2206 		return 13, 2
   2207 	case 't':
   2208 		return 9, 2
   2209 	case 'v':
   2210 		return 11, 2
   2211 	case 'x':
   2212 		v, n := 0, 2
   2213 	loop2:
   2214 		for i := 2; i < len(s); i++ {
   2215 			r := s[i]
   2216 			switch {
   2217 			case r >= '0' && r <= '9', r >= 'a' && r <= 'f', r >= 'A' && r <= 'F':
   2218 				v = v<<4 | decodeHex(r)
   2219 				n++
   2220 			default:
   2221 				break loop2
   2222 			}
   2223 		}
   2224 		return -rune(v & 0xff), n
   2225 	case 'u', 'U':
   2226 		return decodeUCN(s)
   2227 	}
   2228 
   2229 	if r < '0' || r > '7' {
   2230 		panic(internalError())
   2231 	}
   2232 
   2233 	v, n := 0, 1
   2234 	ok := false
   2235 loop:
   2236 	for i := 1; i < len(s); i++ {
   2237 		r := s[i]
   2238 		switch {
   2239 		case i < 4 && r >= '0' && r <= '7':
   2240 			ok = true
   2241 			v = v<<3 | (int(r) - '0')
   2242 			n++
   2243 		default:
   2244 			break loop
   2245 		}
   2246 	}
   2247 	if !ok {
   2248 		ctx.errNode(&tok, "invalid octal sequence")
   2249 	}
   2250 	return -rune(v), n
   2251 }
   2252 
   2253 // universal-character-name	\\u{hex-quad}|\\U{hex-quad}{hex-quad}
   2254 func decodeUCN(s string) (rune, int) {
   2255 	if s[0] != '\\' {
   2256 		panic(internalError())
   2257 	}
   2258 
   2259 	s = s[1:]
   2260 	switch s[0] {
   2261 	case 'u':
   2262 		return rune(decodeHexQuad(s[1:])), 6
   2263 	case 'U':
   2264 		return rune(decodeHexQuad(s[1:])<<16 | decodeHexQuad(s[5:])), 10
   2265 	}
   2266 	panic(internalError())
   2267 }
   2268 
   2269 // hex-quad	{hexadecimal-digit}{hexadecimal-digit}{hexadecimal-digit}{hexadecimal-digit}
   2270 func decodeHexQuad(s string) int {
   2271 	n := 0
   2272 	for i := 0; i < 4; i++ {
   2273 		n = n<<4 | decodeHex(s[i])
   2274 	}
   2275 	return n
   2276 }
   2277 
   2278 func decodeHex(r byte) int {
   2279 	switch {
   2280 	case r >= '0' && r <= '9':
   2281 		return int(r) - '0'
   2282 	default:
   2283 		x := int(r) &^ 0x20
   2284 		return x - 'A' + 10
   2285 	}
   2286 }
   2287 
   2288 func (c *cpp) isNonZero(val interface{}) bool {
   2289 	switch x := val.(type) {
   2290 	case int64:
   2291 		return x != 0
   2292 	case uint64:
   2293 		return x != 0
   2294 	}
   2295 	panic(internalError())
   2296 }
   2297 
   2298 type ppLine interface {
   2299 	getToks() []token3
   2300 }
   2301 
   2302 type ppIfGroupDirective interface {
   2303 	evalInclusionCondition(*cpp) bool
   2304 }
   2305 
   2306 type ppElifDirective struct {
   2307 	toks []token3
   2308 	expr []token3
   2309 }
   2310 
   2311 func (n *ppElifDirective) getToks() []token3 { return n.toks }
   2312 
   2313 type ppElseDirective struct {
   2314 	toks []token3
   2315 }
   2316 
   2317 func (n *ppElseDirective) getToks() []token3 { return n.toks }
   2318 
   2319 type ppEndifDirective struct {
   2320 	toks []token3
   2321 }
   2322 
   2323 func (n *ppEndifDirective) getToks() []token3 { return n.toks }
   2324 
   2325 type ppEmptyDirective struct {
   2326 	toks []token3
   2327 }
   2328 
   2329 func (n *ppEmptyDirective) getToks() []token3 { return n.toks }
   2330 
   2331 func (n *ppEmptyDirective) translationPhase4(c *cpp) {
   2332 	// nop
   2333 }
   2334 
   2335 type ppIncludeDirective struct {
   2336 	arg  []token3
   2337 	toks []token3
   2338 
   2339 	includeNext bool // false: #include, true: #include_next
   2340 }
   2341 
   2342 func (n *ppIncludeDirective) getToks() []token3 { return n.toks }
   2343 
   2344 func (n *ppIncludeDirective) translationPhase4(c *cpp) {
   2345 	if c.ctx.cfg.ignoreIncludes {
   2346 		return
   2347 	}
   2348 
   2349 	args := make([]cppToken, 0, len(n.arg))
   2350 	for _, v := range n.arg {
   2351 		switch v.char {
   2352 		case ' ', '\t', '\v', '\f':
   2353 			// nop
   2354 		default:
   2355 			args = append(args, cppToken{token4{token3: v}, nil})
   2356 		}
   2357 	}
   2358 	var sb strings.Builder
   2359 	for _, v := range args {
   2360 		sb.WriteString(v.String())
   2361 	}
   2362 	nm := strings.TrimSpace(sb.String())
   2363 	if nm == "" {
   2364 		c.err(n.toks[0], "invalid empty include argument")
   2365 		return
   2366 	}
   2367 
   2368 	switch nm[0] {
   2369 	case '"', '<':
   2370 		// ok
   2371 	default:
   2372 		var w cppWriter
   2373 		c.expand(&cppReader{buf: args}, &w, false)
   2374 		x := 0
   2375 		for _, v := range w.toks {
   2376 			switch v.char {
   2377 			case ' ', '\t', '\v', '\f':
   2378 				// nop
   2379 			default:
   2380 				w.toks[x] = v
   2381 				x++
   2382 			}
   2383 		}
   2384 		w.toks = w.toks[:x]
   2385 		nm = strings.TrimSpace(cppToksStr(w.toks, ""))
   2386 	}
   2387 	toks := n.toks
   2388 	if c.ctx.cfg.RejectIncludeNext {
   2389 		c.err(toks[0], "#include_next is a GCC extension")
   2390 		return
   2391 	}
   2392 
   2393 	if c.ctx.cfg.fakeIncludes {
   2394 		c.send([]token3{{char: STRINGLITERAL, value: dict.sid(nm), src: dict.sid(nm)}, {char: '\n', value: idNL}})
   2395 		return
   2396 	}
   2397 
   2398 	if re := c.ctx.cfg.IgnoreInclude; re != nil && re.MatchString(nm) {
   2399 		return
   2400 	}
   2401 
   2402 	if c.includeLevel == maxIncludeLevel {
   2403 		c.err(toks[0], "too many include levels")
   2404 		return
   2405 	}
   2406 
   2407 	c.includeLevel++
   2408 
   2409 	defer func() { c.includeLevel-- }()
   2410 
   2411 	var (
   2412 		b     byte
   2413 		paths []string
   2414 		sys   bool
   2415 	)
   2416 	switch {
   2417 	case nm != "" && nm[0] == '"':
   2418 		paths = c.ctx.includePaths
   2419 		b = '"'
   2420 	case nm != "" && nm[0] == '<':
   2421 		paths = c.ctx.sysIncludePaths
   2422 		sys = true
   2423 		b = '>'
   2424 	case nm == "":
   2425 		c.err(toks[0], "invalid empty include argument")
   2426 		return
   2427 	default:
   2428 		c.err(toks[0], "invalid include argument %s", nm)
   2429 		return
   2430 	}
   2431 
   2432 	x := strings.IndexByte(nm[1:], b)
   2433 	if x < 0 {
   2434 		c.err(toks[0], "invalid include argument %s", nm)
   2435 		return
   2436 	}
   2437 
   2438 	nm = filepath.FromSlash(nm[1 : x+1])
   2439 	var path string
   2440 	switch {
   2441 	case filepath.IsAbs(nm):
   2442 		path = nm
   2443 	default:
   2444 		dir := filepath.Dir(c.file.Name())
   2445 		if n.includeNext {
   2446 			nmDir, _ := filepath.Split(nm)
   2447 			for i, v := range paths {
   2448 				if w, err := filepath.Abs(v); err == nil {
   2449 					v = w
   2450 				}
   2451 				v = filepath.Join(v, nmDir)
   2452 				if v == dir {
   2453 					paths = paths[i+1:]
   2454 					break
   2455 				}
   2456 			}
   2457 		}
   2458 		for _, v := range paths {
   2459 			if v == "@" {
   2460 				v = dir
   2461 			}
   2462 
   2463 			p := filepath.Join(v, nm)
   2464 			fi, err := c.ctx.statFile(p, sys)
   2465 			if err != nil || fi.IsDir() {
   2466 				continue
   2467 			}
   2468 
   2469 			path = p
   2470 			break
   2471 		}
   2472 	}
   2473 
   2474 	if path == "" {
   2475 		wd, _ := os.Getwd()
   2476 		c.err(toks[0], "include file not found: %s (wd %s)\nsearch paths:\n\t%s", nm, wd, strings.Join(paths, "\n\t"))
   2477 		return
   2478 	}
   2479 
   2480 	if h := c.ctx.cfg.IncludeFileHandler; h != nil {
   2481 		var position gotoken.Position
   2482 		if p := toks[0].Pos(); p.IsValid() {
   2483 			position = gotoken.Position(c.file.PositionFor(p, true))
   2484 		}
   2485 		apath, err := filepath.Abs(path)
   2486 		if err != nil {
   2487 			c.err(toks[0], "%s: cannot compute absolute path: %v", path, err)
   2488 		}
   2489 		h(position, apath)
   2490 	}
   2491 	cf, err := cache.getFile(c.ctx, path, sys, false)
   2492 	if err != nil {
   2493 		c.err(toks[0], "%s: %v", path, err)
   2494 		return
   2495 	}
   2496 
   2497 	pf, err := cf.ppFile()
   2498 	if err != nil {
   2499 		c.err(toks[0], "%s: %v", path, err)
   2500 		return
   2501 	}
   2502 
   2503 	saveFile := c.file
   2504 	saveFileMacro := c.fileMacro.repl[0].value
   2505 
   2506 	c.file = pf.file
   2507 	c.fileMacro.repl[0].value = dict.sid(fmt.Sprintf("%q", c.file.Name()))
   2508 
   2509 	defer func() {
   2510 		c.file = saveFile
   2511 		c.fileMacro.repl[0].value = saveFileMacro
   2512 	}()
   2513 
   2514 	pf.translationPhase4(c)
   2515 }
   2516 
   2517 func (c *cpp) send(toks []token3) {
   2518 	c.in <- toks
   2519 	<-c.rq
   2520 }
   2521 
   2522 func (c *cpp) identicalReplacementLists(a, b []token3) bool {
   2523 	for len(a) != 0 && a[0].char == ' ' {
   2524 		a = a[1:]
   2525 	}
   2526 	for len(b) != 0 && b[0].char == ' ' {
   2527 		b = b[1:]
   2528 	}
   2529 	for len(a) != 0 && a[len(a)-1].char == ' ' {
   2530 		a = a[:len(a)-1]
   2531 	}
   2532 	for len(b) != 0 && b[len(b)-1].char == ' ' {
   2533 		b = b[:len(b)-1]
   2534 	}
   2535 	if len(a) != len(b) {
   2536 		return false
   2537 	}
   2538 
   2539 	for i, v := range a {
   2540 		w := b[i]
   2541 		if v.char != w.char || v.value != w.value {
   2542 			return false
   2543 		}
   2544 	}
   2545 	return true
   2546 }
   2547 
   2548 func stringConst(ctx *context, t cppToken) string {
   2549 	s := t.String()
   2550 	switch t.char {
   2551 	case LONGSTRINGLITERAL:
   2552 		s = s[1:] // Remove leading 'L'.
   2553 		fallthrough
   2554 	case STRINGLITERAL:
   2555 		var buf bytes.Buffer
   2556 		for i := 1; i < len(s)-1; {
   2557 			switch c := s[i]; c {
   2558 			case '\\':
   2559 				r, n := decodeEscapeSequence(ctx, t, s[i:])
   2560 				switch {
   2561 				case r < 0:
   2562 					buf.WriteByte(byte(-r))
   2563 				default:
   2564 					buf.WriteRune(r)
   2565 				}
   2566 				i += n
   2567 			default:
   2568 				buf.WriteByte(c)
   2569 				i++
   2570 			}
   2571 		}
   2572 		return buf.String()
   2573 	}
   2574 	panic(internalError())
   2575 }
   2576 
   2577 // -------------------------------------------------------- Translation phase 4
   2578 
   2579 // [0], 5.1.1.2, 4
   2580 //
   2581 // Preprocessing directives are executed, macro invocations are expanded, and
   2582 // _Pragma unary operator expressions are executed. If a character sequence
   2583 // that matches the syntax of a universal character name is produced by token
   2584 // concatenation (6.10.3.3), the behavior is undefined. A #include
   2585 // preprocessing directive causes the named header or source file to be
   2586 // processed from phase 1 through phase 4, recursively. All preprocessing
   2587 // directives are then deleted.
   2588 func (c *cpp) translationPhase4(in []source) chan *[]token4 {
   2589 	c.rq = make(chan struct{})       // Must be unbufferred
   2590 	c.in = make(chan []token3)       // Must be unbufferred
   2591 	c.out = make(chan *[]token4, 10) //DONE benchmark tuned
   2592 
   2593 	go func() {
   2594 		defer close(c.out)
   2595 
   2596 		c.expand(c, c, false)
   2597 	}()
   2598 
   2599 	go func() {
   2600 		defer close(c.in)
   2601 
   2602 		for _, v := range in {
   2603 			pf, err := v.ppFile()
   2604 			if err != nil {
   2605 				c.err(nil, "%s", err)
   2606 				break
   2607 			}
   2608 
   2609 			c.file = pf.file
   2610 			c.fileMacro.repl[0].value = dict.sid(fmt.Sprintf("%q", c.file.Name()))
   2611 			pf.translationPhase4(c)
   2612 		}
   2613 	}()
   2614 
   2615 	return c.out
   2616 }
   2617 
   2618 type ppErrorDirective struct {
   2619 	toks []token3
   2620 	msg  []token3
   2621 }
   2622 
   2623 func (n *ppErrorDirective) getToks() []token3 { return n.toks }
   2624 
   2625 func (n *ppErrorDirective) translationPhase4(c *cpp) {
   2626 	var b strings.Builder
   2627 	for _, v := range n.msg {
   2628 		b.WriteString(v.String())
   2629 	}
   2630 	c.err(n.toks[0], "%s", strings.TrimSpace(b.String()))
   2631 }
   2632 
   2633 type ppPragmaDirective struct {
   2634 	toks []token3
   2635 	args []token3
   2636 }
   2637 
   2638 func (n *ppPragmaDirective) getToks() []token3 { return n.toks }
   2639 
   2640 func (n *ppPragmaDirective) translationPhase4(c *cpp) { parsePragma(c, n.args) }
   2641 
   2642 func parsePragma(c *cpp, args0 []token3) {
   2643 	if len(args0) == 1 { // \n
   2644 		return
   2645 	}
   2646 
   2647 	if t := args0[0]; t.char == IDENTIFIER && t.value == idSTDC {
   2648 		p := t
   2649 		p.char = PRAGMASTDC
   2650 		p.value = idPragmaSTDC
   2651 		send := []token3{p, {char: ' ', value: idSpace, src: idSpace, pos: t.pos}}
   2652 		args := ltrim3(args0[1:])
   2653 		if len(args) == 0 {
   2654 			c.err(args[0], "expected argument of STDC")
   2655 			return
   2656 		}
   2657 
   2658 		if t = args[0]; t.char != IDENTIFIER {
   2659 			c.err(t, "expected identifier")
   2660 			return
   2661 		}
   2662 
   2663 		switch t.value {
   2664 		case idFPContract, idFenvAccess, idCxLimitedRange:
   2665 			// ok
   2666 		default:
   2667 			c.err(t, "expected FP_CONTRACT or FENV_ACCESS or CX_LIMITED_RANGE")
   2668 			return
   2669 		}
   2670 
   2671 		args = ltrim3(args[1:])
   2672 		if len(args) == 0 {
   2673 			c.err(args[0], "expected ON or OFF or DEFAULT")
   2674 			return
   2675 		}
   2676 
   2677 		if t = args[0]; t.char != IDENTIFIER {
   2678 			c.err(t, "expected identifier")
   2679 			return
   2680 		}
   2681 
   2682 		switch t.value {
   2683 		case idOn, idOff, idDefault:
   2684 			c.writes(c.cppToks(append(send, args0...)))
   2685 		default:
   2686 			c.err(t, "expected ON or OFF or DEFAULT")
   2687 			return
   2688 		}
   2689 	}
   2690 
   2691 	if c.ctx.cfg.PragmaHandler == nil {
   2692 		return
   2693 	}
   2694 
   2695 	var toks []cppToken
   2696 	for _, v := range args0[:len(args0)-1] {
   2697 		toks = append(toks, cppToken{token4: token4{file: c.file, token3: v}})
   2698 	}
   2699 	if len(toks) == 0 {
   2700 		return
   2701 	}
   2702 
   2703 	var toks2 []Token
   2704 	var sep StringID
   2705 	for _, tok := range toks {
   2706 		switch tok.char {
   2707 		case ' ', '\n':
   2708 			if c.ctx.cfg.PreserveOnlyLastNonBlankSeparator {
   2709 				if strings.TrimSpace(tok.value.String()) != "" {
   2710 					sep = tok.value
   2711 				}
   2712 				break
   2713 			}
   2714 
   2715 			switch {
   2716 			case sep != 0:
   2717 				sep = dict.sid(sep.String() + tok.String()) //TODO quadratic
   2718 			default:
   2719 				sep = tok.value
   2720 			}
   2721 		default:
   2722 			var t Token
   2723 			t.Rune = tok.char
   2724 			t.Sep = sep
   2725 			t.Value = tok.value
   2726 			t.file = tok.file
   2727 			t.pos = tok.pos
   2728 			toks2 = append(toks2, t)
   2729 			sep = 0
   2730 		}
   2731 	}
   2732 	if len(toks2) == 0 {
   2733 		return
   2734 	}
   2735 
   2736 	// dbg("%v: %q", c.file.PositionFor(args0[0].Pos(), true), tokStr(toks2, "|"))
   2737 	c.ctx.cfg.PragmaHandler(&pragma{tok: toks[0], c: c}, toks2)
   2738 }
   2739 
   2740 type ppNonDirective struct {
   2741 	toks []token3
   2742 }
   2743 
   2744 func (n *ppNonDirective) getToks() []token3 { return n.toks }
   2745 
   2746 func (n *ppNonDirective) translationPhase4(c *cpp) {
   2747 	// nop
   2748 }
   2749 
   2750 type ppTextLine struct {
   2751 	toks []token3
   2752 }
   2753 
   2754 func (n *ppTextLine) getToks() []token3 { return n.toks }
   2755 
   2756 func (n *ppTextLine) translationPhase4(c *cpp) { c.send(n.toks) }
   2757 
   2758 type ppLineDirective struct {
   2759 	toks    []token3
   2760 	args    []token3
   2761 	nextPos int
   2762 }
   2763 
   2764 func (n *ppLineDirective) getToks() []token3 { return n.toks }
   2765 
   2766 func (n *ppLineDirective) translationPhase4(c *cpp) {
   2767 	toks := expandArgs(c, n.args)
   2768 	if len(toks) == 0 {
   2769 		return
   2770 	}
   2771 
   2772 	switch t := toks[0]; t.char {
   2773 	case PPNUMBER:
   2774 		ln, err := strconv.ParseInt(t.String(), 10, 31)
   2775 		if err != nil || ln < 1 {
   2776 			c.err(t, "expected positive integer less or equal 2147483647")
   2777 			return
   2778 		}
   2779 
   2780 		for len(toks) != 0 && toks[0].char == ' ' {
   2781 			toks = toks[1:]
   2782 		}
   2783 		if len(toks) == 1 {
   2784 			c.file.AddLineInfo(int(n.nextPos)-1, c.file.Name(), int(ln))
   2785 			return
   2786 		}
   2787 
   2788 		toks = toks[1:]
   2789 		for len(toks) != 0 && toks[0].char == ' ' {
   2790 			toks = toks[1:]
   2791 		}
   2792 		if len(toks) == 0 {
   2793 			c.file.AddLineInfo(int(n.nextPos)-1, c.file.Name(), int(ln))
   2794 			return
   2795 		}
   2796 
   2797 		switch t := toks[0]; t.char {
   2798 		case STRINGLITERAL:
   2799 			s := t.String()
   2800 			s = s[1 : len(s)-1]
   2801 			c.file.AddLineInfo(int(n.nextPos)-1, s, int(ln))
   2802 			c.fileMacro.repl[0].value = t.value
   2803 			for len(toks) != 0 && toks[0].char == ' ' {
   2804 				toks = toks[1:]
   2805 			}
   2806 			if len(toks) != 0 && c.ctx.cfg.RejectLineExtraTokens {
   2807 				c.err(toks[0], "expected new-line")
   2808 			}
   2809 		default:
   2810 			c.err(t, "expected string literal")
   2811 			return
   2812 		}
   2813 	default:
   2814 		c.err(toks[0], "expected integer literal")
   2815 		return
   2816 	}
   2817 }
   2818 
   2819 func expandArgs(c *cpp, args []token3) []cppToken {
   2820 	var w cppWriter
   2821 	var toks []cppToken
   2822 	for _, v := range args {
   2823 		toks = append(toks, cppToken{token4: token4{file: c.file, token3: v}})
   2824 	}
   2825 	c.expand(&cppReader{buf: toks}, &w, true)
   2826 	return w.toks
   2827 }
   2828 
   2829 type ppUndefDirective struct {
   2830 	name token3
   2831 	toks []token3
   2832 }
   2833 
   2834 func (n *ppUndefDirective) getToks() []token3 { return n.toks }
   2835 
   2836 func (n *ppUndefDirective) translationPhase4(c *cpp) {
   2837 	nm := n.name.value
   2838 	if _, ok := protectedMacros[nm]; ok || nm == idDefined {
   2839 		c.err(n.name, "cannot undefine a protected name")
   2840 		return
   2841 	}
   2842 
   2843 	// dbg("#undef %s", nm)
   2844 	delete(c.macros, nm)
   2845 }
   2846 
   2847 type ppIfdefDirective struct {
   2848 	name StringID
   2849 	toks []token3
   2850 }
   2851 
   2852 func (n *ppIfdefDirective) evalInclusionCondition(c *cpp) bool { _, ok := c.macros[n.name]; return ok }
   2853 
   2854 func (n *ppIfdefDirective) getToks() []token3 { return n.toks }
   2855 
   2856 type ppIfndefDirective struct {
   2857 	name StringID
   2858 	toks []token3
   2859 }
   2860 
   2861 func (n *ppIfndefDirective) evalInclusionCondition(c *cpp) bool {
   2862 	_, ok := c.macros[n.name]
   2863 	return !ok
   2864 }
   2865 
   2866 func (n *ppIfndefDirective) getToks() []token3 { return n.toks }
   2867 
   2868 type ppIfDirective struct {
   2869 	toks []token3
   2870 	expr []token3
   2871 }
   2872 
   2873 func (n *ppIfDirective) getToks() []token3 { return n.toks }
   2874 
   2875 func (n *ppIfDirective) evalInclusionCondition(c *cpp) bool {
   2876 	return c.evalInclusionCondition(n.expr)
   2877 }
   2878 
   2879 type ppDefineObjectMacroDirective struct {
   2880 	name            token3
   2881 	toks            []token3
   2882 	replacementList []token3
   2883 }
   2884 
   2885 func (n *ppDefineObjectMacroDirective) getToks() []token3 { return n.toks }
   2886 
   2887 func (n *ppDefineObjectMacroDirective) translationPhase4(c *cpp) {
   2888 	nm := n.name.value
   2889 	m := c.macros[nm]
   2890 	if m != nil {
   2891 		if _, ok := protectedMacros[nm]; ok || nm == idDefined {
   2892 			c.err(n.name, "cannot define protected name")
   2893 			return
   2894 		}
   2895 
   2896 		if m.isFnLike {
   2897 			c.err(n.name, "redefinition of a function-like macro with an object-like one")
   2898 		}
   2899 
   2900 		if !c.identicalReplacementLists(n.replacementList, m.repl) && c.ctx.cfg.RejectIncompatibleMacroRedef {
   2901 			c.err(n.name, "redefinition with different replacement list")
   2902 			return
   2903 		}
   2904 	}
   2905 
   2906 	// find first non-blank token to claim as our location
   2907 	var pos int32
   2908 	for _, t := range n.toks {
   2909 		if t.char != ' ' {
   2910 			pos = t.pos
   2911 			break
   2912 		}
   2913 	}
   2914 
   2915 	// dbg("#define %s %s // %v", n.name, tokStr(n.replacementList, " "), c.file.PositionFor(n.name.Pos(), true))
   2916 	c.macros[nm] = &Macro{pos: pos, name: token4{token3: n.name, file: c.file}, repl: n.replacementList}
   2917 	if nm != idGNUC {
   2918 		return
   2919 	}
   2920 
   2921 	c.ctx.keywords = gccKeywords
   2922 }
   2923 
   2924 type ppDefineFunctionMacroDirective struct {
   2925 	identifierList  []token3
   2926 	toks            []token3
   2927 	replacementList []token3
   2928 
   2929 	name token3
   2930 
   2931 	namedVariadic bool // foo..., note no comma before ellipsis.
   2932 	variadic      bool
   2933 }
   2934 
   2935 func (n *ppDefineFunctionMacroDirective) getToks() []token3 { return n.toks }
   2936 
   2937 func (n *ppDefineFunctionMacroDirective) translationPhase4(c *cpp) {
   2938 	nm := n.name.value
   2939 	m := c.macros[nm]
   2940 	if m != nil {
   2941 		if _, ok := protectedMacros[nm]; ok || nm == idDefined {
   2942 			c.err(n.name, "cannot define protected name")
   2943 			return
   2944 		}
   2945 
   2946 		if !m.isFnLike && c.ctx.cfg.RejectIncompatibleMacroRedef {
   2947 			c.err(n.name, "redefinition of an object-like macro with a function-like one")
   2948 			return
   2949 		}
   2950 
   2951 		ok := len(m.fp) == len(n.identifierList)
   2952 		if ok {
   2953 			for i, v := range m.fp {
   2954 				if v != n.identifierList[i].value {
   2955 					ok = false
   2956 					break
   2957 				}
   2958 			}
   2959 		}
   2960 		if !ok && (len(n.replacementList) != 0 || len(m.repl) != 0) && c.ctx.cfg.RejectIncompatibleMacroRedef {
   2961 			c.err(n.name, "redefinition with different formal parameters")
   2962 			return
   2963 		}
   2964 
   2965 		if !c.identicalReplacementLists(n.replacementList, m.repl) && c.ctx.cfg.RejectIncompatibleMacroRedef {
   2966 			c.err(n.name, "redefinition with different replacement list")
   2967 			return
   2968 		}
   2969 
   2970 		if m.variadic != n.variadic && c.ctx.cfg.RejectIncompatibleMacroRedef {
   2971 			c.err(n.name, "redefinition differs in being variadic")
   2972 			return
   2973 		}
   2974 	}
   2975 	nms := map[StringID]struct{}{}
   2976 	for _, v := range n.identifierList {
   2977 		if _, ok := nms[v.value]; ok {
   2978 			c.err(v, "duplicate identifier %s", v.value)
   2979 		}
   2980 	}
   2981 	var fp []StringID
   2982 	for _, v := range n.identifierList {
   2983 		fp = append(fp, v.value)
   2984 	}
   2985 	// dbg("#define %s %s // %v", n.name, tokStr(n.replacementList, " "), c.file.PositionFor(n.name.Pos(), true))
   2986 	c.macros[nm] = &Macro{fp: fp, isFnLike: true, name: token4{token3: n.name, file: c.file}, repl: n.replacementList, variadic: n.variadic, namedVariadic: n.namedVariadic}
   2987 }
   2988 
   2989 // [0], 6.10.1
   2990 //
   2991 //  elif-group:
   2992 //  		# elif constant-expression new-line group_opt
   2993 type ppElifGroup struct {
   2994 	elif   *ppElifDirective
   2995 	groups []ppGroup
   2996 }
   2997 
   2998 func (n *ppElifGroup) evalInclusionCondition(c *cpp) bool {
   2999 	if !c.evalInclusionCondition(n.elif.expr) {
   3000 		return false
   3001 	}
   3002 
   3003 	for _, v := range n.groups {
   3004 		v.translationPhase4(c)
   3005 	}
   3006 	return true
   3007 }
   3008 
   3009 // [0], 6.10.1
   3010 //
   3011 //  else-group:
   3012 //  		# else new-line group_opt
   3013 type ppElseGroup struct {
   3014 	elseLine *ppElseDirective
   3015 	groups   []ppGroup
   3016 }
   3017 
   3018 func (n *ppElseGroup) translationPhase4(c *cpp) {
   3019 	if n == nil {
   3020 		return
   3021 	}
   3022 
   3023 	for _, v := range n.groups {
   3024 		v.translationPhase4(c)
   3025 	}
   3026 }
   3027 
   3028 // [0], 6.10.1
   3029 //
   3030 //  PreprocessingFile:
   3031 //  		GroupOpt
   3032 type ppFile struct {
   3033 	file   *tokenFile
   3034 	groups []ppGroup
   3035 }
   3036 
   3037 func (n *ppFile) translationPhase4(c *cpp) {
   3038 	c.ctx.tuSourcesAdd(1)
   3039 	if f := n.file; f != nil {
   3040 		c.ctx.tuSizeAdd(int64(f.Size()))
   3041 	}
   3042 	for _, v := range n.groups {
   3043 		v.translationPhase4(c)
   3044 	}
   3045 }
   3046 
   3047 // [0], 6.10.1
   3048 //
   3049 //  group-part:
   3050 //  		if-section
   3051 //  		control-line
   3052 //  		text-line
   3053 //  		# non-directive
   3054 type ppGroup interface {
   3055 	translationPhase4(*cpp)
   3056 }
   3057 
   3058 // [0], 6.10.1
   3059 //
   3060 //  if-group:
   3061 //  		# if constant-expression new-line group opt
   3062 //  		# ifdef identifier new-line group opt
   3063 //  		# ifndef identifier new-line group opt
   3064 type ppIfGroup struct {
   3065 	directive ppIfGroupDirective
   3066 	groups    []ppGroup
   3067 }
   3068 
   3069 func (n *ppIfGroup) evalInclusionCondition(c *cpp) bool {
   3070 	if !n.directive.evalInclusionCondition(c) {
   3071 		return false
   3072 	}
   3073 
   3074 	for _, v := range n.groups {
   3075 		v.translationPhase4(c)
   3076 	}
   3077 	return true
   3078 }
   3079 
   3080 // [0], 6.10.1
   3081 //
   3082 // if-section:
   3083 // 		if-group elif-groups_opt else-group_opt endif-line
   3084 type ppIfSection struct {
   3085 	ifGroup    *ppIfGroup
   3086 	elifGroups []*ppElifGroup
   3087 	elseGroup  *ppElseGroup
   3088 	endifLine  *ppEndifDirective
   3089 }
   3090 
   3091 func (n *ppIfSection) translationPhase4(c *cpp) {
   3092 	if !n.ifGroup.evalInclusionCondition(c) {
   3093 		for _, v := range n.elifGroups {
   3094 			if v.evalInclusionCondition(c) {
   3095 				return
   3096 			}
   3097 		}
   3098 
   3099 		n.elseGroup.translationPhase4(c)
   3100 	}
   3101 }