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 }