2021-08-29 15:41:41 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// Copyright 2019 The CC Authors. All rights reserved.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Use of this source code is governed by a BSD-style  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// license that can be found in the LICENSE file.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//TODO https://todo.sr.ht/~mcf/cc-issues/34  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//TODO http://mcpp.sourceforge.net/ "Provides a validation suite to test C/C++ preprocessor's conformance and quality comprehensively."  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//go:generate rm -f lexer.go  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//go:generate golex -o lexer.go lexer.l  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//go:generate rm -f ast.go  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//go:generate yy -o /dev/null -position -astImport "\"fmt\"\n\n\"modernc.org/token\"" -prettyString PrettyString -kind Case -noListKind -noPrivateHelpers -forceOptPos parser.yy  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//go:generate stringer -output stringer.go -linecomment -type=Kind,Linkage  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//go:generate sh -c "go test -run ^Example |fe"  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Package cc is a C99 compiler front end (Work in progress).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Installation  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// To install/update cc/v3 invoke:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//     $ go get [-u] modernc.org/cc/v3  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Online documentation  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// See https://godoc.org/modernc.org/cc/v3.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Status  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Most of the functionality is now working.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Supported platforms  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The code is known to work on Darwin, Linux and Windows, but the supported  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// features may vary.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Links  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Referenced from elsewhere:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  [0]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  [1]: https://www.spinellis.gr/blog/20060626/cpp.algo.pdf  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  [2]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  [3]: http://gallium.inria.fr/~fpottier/publis/jourdan-fpottier-2016.pdf  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  [4]: https://gcc.gnu.org/onlinedocs/gcc-8.3.0/gcc/Attribute-Syntax.html#Attribute-Syntax  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								package  cc  // import "modernc.org/cc/v3"  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									goscanner  "go/scanner" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									gotoken  "go/token" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"hash/maphash" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"io" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"math" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"os" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"os/exec" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"reflect" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"regexp" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"runtime" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"sort" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"strconv" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"sync" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"sync/atomic" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"modernc.org/strutil" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"modernc.org/token" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									scopeParent  StringID  =  - iota  -  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									scopeSkip 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_  Pragma  =  ( * pragma ) ( nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache        =  newPPCache ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dict         =  newDictionary ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dictStrings  [ math . MaxUint8  +  1 ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									noPos        token . Position 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									debugIncludePaths  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									debugWorkingDir    bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									isTesting          bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									isTestingMingw     bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									idPtrdiffT  =  dict . sid ( "ptrdiff_t" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									idSizeT     =  dict . sid ( "size_t" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									idWCharT    =  dict . sid ( "wchar_t" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									token4Pool  =  sync . Pool { New :  func ( )  interface { }  {  r  :=  make ( [ ] token4 ,  0 ) ;  return  & r  } }  //DONE benchmrk tuned capacity 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tokenPool   =  sync . Pool { New :  func ( )  interface { }  {  r  :=  make ( [ ] Token ,  0 ) ;  return  & r  } }   //DONE benchmrk tuned capacity 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printHooks  =  strutil . PrettyPrintHooks { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reflect . TypeOf ( Token { } ) :  func ( f  strutil . Formatter ,  v  interface { } ,  prefix ,  suffix  string )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											t  :=  v . ( Token ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( t  ==  Token { } )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											f . Format ( prefix ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											r  :=  t . Rune 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  p  :=  t . Position ( ) ;  p . IsValid ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												f . Format ( "%v: " ,  p ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s  :=  tokName ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  x  :=  s [ 0 ] ;  x  >=  '0'  &&  x  <=  '9'  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												s  =  strconv . QuoteRune ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											f . Format ( "%s" ,  s ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  s  :=  t . Value . String ( ) ;  len ( s )  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												f . Format ( " %q" ,  s ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											f . Format ( suffix ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reflect . TypeOf ( ( * operand ) ( nil ) ) :  func ( f  strutil . Formatter ,  v  interface { } ,  prefix ,  suffix  string )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											op  :=  v . ( * operand ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											f . Format ( prefix ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											f . Format ( "[%v %T(%[2]v)]" ,  op . Type ( ) ,  op . Value ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											f . Format ( suffix ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  todo ( s  string ,  args  ... interface { } )  string  {  //TODO-  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  s  ==  "" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s  =  fmt . Sprintf ( strings . Repeat ( "%v " ,  len ( args ) ) ,  args ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s  =  fmt . Sprintf ( s ,  args ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pc ,  fn ,  fl ,  _  :=  runtime . Caller ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									f  :=  runtime . FuncForPC ( pc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  fns  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  f  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fns  =  f . Name ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  x  :=  strings . LastIndex ( fns ,  "." ) ;  x  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											fns  =  fns [ x + 1 : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									r  :=  fmt . Sprintf ( "%s:%d:%s: TODOTODO %s" ,  fn ,  fl ,  fns ,  s )  //TODOOK 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fmt . Fprintf ( os . Stdout ,  "%s\n" ,  r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									os . Stdout . Sync ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  r 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  trc ( s  string ,  args  ... interface { } )  string  {  //TODO-  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  s  ==  "" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s  =  fmt . Sprintf ( strings . Repeat ( "%v " ,  len ( args ) ) ,  args ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s  =  fmt . Sprintf ( s ,  args ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pc ,  fn ,  fl ,  _  :=  runtime . Caller ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									f  :=  runtime . FuncForPC ( pc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  fns  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  f  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fns  =  f . Name ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  x  :=  strings . LastIndex ( fns ,  "." ) ;  x  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											fns  =  fns [ x + 1 : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									r  :=  fmt . Sprintf ( "%s:%d:%s: TRC %s" ,  fn ,  fl ,  fns ,  s ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fmt . Fprintf ( os . Stdout ,  "%s\n" ,  r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									os . Stdout . Sync ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  r 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  origin ( skip  int )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pc ,  fn ,  fl ,  _  :=  runtime . Caller ( skip ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									f  :=  runtime . FuncForPC ( pc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  fns  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  f  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fns  =  f . Name ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  x  :=  strings . LastIndex ( fns ,  "." ) ;  x  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											fns  =  fns [ x + 1 : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  fmt . Sprintf ( "%s:%d:%s" ,  fn ,  fl ,  fns ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// String returns a StringID for a given value.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  String ( s  string )  StringID  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  dict . sid ( s ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Linkage represents identifier linkage.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// [0]6.2.2: An identifier declared in different scopes or in the same scope  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// more than once can be made to refer to the same object or function by a  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// process called linkage. There are three kinds of linkage: External,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Internal, and None.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Linkage  int  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// StorageClass determines storage duration.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// [0]6.2.4: An object has a storage duration that determines its lifetime.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// There are three storage durations: Static, Automatic, and Allocated.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  StorageClass  int  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Pragma defines behavior of the object passed to Config.PragmaHandler.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Pragma  interface  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Error ( msg  string ,  args  ... interface { } )  // Report error. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MaxAligment ( )  int                       // Returns the current maximum alignment. May return zero. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MaxInitialAligment ( )  int                // Support #pragma pack(). Returns the maximum alignment in effect at start. May return zero. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									PopMacro ( string ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									PushMacro ( string ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SetAlignment ( n  int )  // Support #pragma pack(n) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  pragma  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tok  cppToken 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c    * cpp 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * pragma )  Error ( msg  string ,  args  ... interface { } )  {  p . c . err ( p . tok ,  msg ,  args ... )  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * pragma )  MaxAligment ( )  int  {  return  p . c . ctx . maxAlign  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * pragma )  MaxInitialAligment ( )  int  {  return  p . c . ctx . maxAlign0  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * pragma )  SetAlignment ( n  int )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  n  <=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p . Error ( "%T.SetAlignment(%d): invalid argument" ,  p ,  n ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p . c . ctx . maxAlign  =  n 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * pragma )  PushMacro ( nm  string )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									id  :=  dict . sid ( nm ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  p . c . macroStack  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p . c . macroStack  =  map [ StringID ] [ ] * Macro { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  m  :=  p . c . macros [ id ] ;  m  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p . c . macroStack [ id ]  =  append ( p . c . macroStack [ id ] ,  p . c . macros [ id ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * pragma )  PopMacro ( nm  string )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									id  :=  dict . sid ( nm ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									a  :=  p . c . macroStack [ id ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  n  :=  len ( a ) ;  n  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p . c . macros [ id ]  =  a [ n - 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p . c . macroStack [ id ]  =  a [ : n - 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// PrettyString returns a formatted representation of things produced by this package.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  PrettyString ( v  interface { } )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  strutil . PrettyString ( v ,  "" ,  "" ,  printHooks ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// StringID is a process-unique string numeric identifier. Its zero value  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// represents an empty string.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  StringID  int32  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// String implements fmt.Stringer.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( n  StringID )  String ( )  ( r  string )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  n  <  256  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  dictStrings [ byte ( n ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dict . mu . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									r  =  dict . strings [ n ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dict . mu . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  r 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Node is implemented by Token and all AST nodes.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Node  interface  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Position ( )  token . Position 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  noder  struct { }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( noder )  Position ( )  token . Position  {  panic ( internalError ( ) )  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Scope maps identifiers to definitions.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Scope  map [ StringID ] [ ] Node  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( s  * Scope )  new ( )  ( r  Scope )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  * s  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* s  =  Scope { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									r  =  Scope { scopeParent :  [ ] Node { struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										noder 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Scope 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} { Scope :  * s } } } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  r 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( s  * Scope )  declare ( nm  StringID ,  n  Node )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sc  :=  * s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  sc  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* s  =  map [ StringID ] [ ] Node { nm :  { n } } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// t := "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// if x, ok := n.(*Declarator); ok && x.IsTypedefName { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// 	t = ", typedefname" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// dbg("declared %s%s at %v in scope %p", nm, t, n.Position(), *s) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  x  :=  n . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  * Declarator ,  * StructDeclarator ,  * LabeledStatement ,  * BlockItem : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// nop 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  * StructOrUnionSpecifier ,  * EnumSpecifier ,  * Enumerator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  _ ,  ok  :=  sc [ scopeSkip ] ;  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											sc  =  sc . Parent ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										panic ( todo ( "%T" ,  x ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sc [ nm ]  =  append ( sc [ nm ] ,  n ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// t := "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// if x, ok := n.(*Declarator); ok && x.IsTypedefName { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 	t = ", typedefname" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// dbg("declared %s%s at %v in scope %p", nm, t, n.Position(), sc) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Parent returns s's outer scope, if any.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( s  Scope )  Parent ( )  Scope  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  x ,  ok  :=  s [ scopeParent ] ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  x [ 0 ] . ( struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											noder 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Scope 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) . Scope 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( s  * Scope )  typedef ( nm  StringID ,  tok  Token )  * Declarator  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									seq  :=  tok . seq 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  s  :=  * s ;  s  !=  nil ;  s  =  s . Parent ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  v  :=  range  s [ nm ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											switch  x  :=  v . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  * Declarator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ! x . isVisible ( seq )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  x . IsTypedefName  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  x 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  * Enumerator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  * EnumSpecifier ,  * StructOrUnionSpecifier ,  * StructDeclarator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// nop 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												panic ( internalError ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( s  * Scope )  declarator ( nm  StringID ,  tok  Token )  * Declarator  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									seq  :=  tok . seq 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  s  :=  * s ;  s  !=  nil ;  s  =  s . Parent ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										defs  :=  s [ nm ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  v  :=  range  defs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											switch  x  :=  v . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  * Declarator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ! x . isVisible ( seq )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												for  _ ,  v  :=  range  defs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  x ,  ok  :=  v . ( * Declarator ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														t  :=  x . Type ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  t  !=  nil  &&  t . Kind ( )  ==  Function  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															if  x . fnDef  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																return  x 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  t  !=  nil  &&  ! x . Type ( ) . IsIncomplete ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															return  x 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  x 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  * Enumerator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  * EnumSpecifier ,  * StructOrUnionSpecifier ,  * StructDeclarator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// nop 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												panic ( internalError ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( s  * Scope )  enumerator ( nm  StringID ,  tok  Token )  * Enumerator  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									seq  :=  tok . seq 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  s  :=  * s ;  s  !=  nil ;  s  =  s . Parent ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  v  :=  range  s [ nm ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											switch  x  :=  v . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  * Declarator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ! x . isVisible ( seq )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  * Enumerator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  x 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  * EnumSpecifier ,  * StructOrUnionSpecifier ,  * StructDeclarator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// nop 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												panic ( internalError ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Config3 amends behavior of translation phases 1 to 3.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Config3  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If IgnoreInclude is not nil, its MatchString method will be called by the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// preprocessor with the argument any include directive expands to. If the call 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// evaluates to is true the include directive will be ignored completely. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IgnoreInclude  * regexp . Regexp 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Name of a macro to use instead of FD_ZERO. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Note: Temporary solution will be removed/replaced 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ReplaceMacroFdZero  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Name of a macro to use instead of TCL_DEFAULT_DOUBLE_ROUNDING. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Note: Temporary solution will be removed/replaced 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ReplaceMacroTclDefaultDoubleRounding  string  // Name of a macro to use instead of TCL_DEFAULT_DOUBLE_ROUNDING. Note: Temporrary solution will be removed/replaced 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Name of a macro to use instead of TCL_IEEE_DOUBLE_ROUNDING. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Note: Temporary solution will be removed/replaced 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ReplaceMacroTclIeeeDoubleRounding  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									WorkingDir  string      // Overrides os.Getwd if non empty. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Filesystem  Filesystem  // Overrides filesystem access if not empty. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MaxSourceLine  int  // Zero: Scanner will use default buffer. Non zero: Scanner will use max(default buffer size, MaxSourceLine). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// DisableBuiltinResolution disables resolution of undefined identifiers such 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// that eg. abort, becomes the same as __builtin_abort, prototype of which is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// expected to be provided by one of the sources passed to Parse, Preprocess or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Translate. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									DisableBuiltinResolution  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									DisableTrigraphs  bool  // GCC ignores them unless -trigraphs is used: https://gcc.gnu.org/onlinedocs/cpp/Initial-processing.html 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									GCCStructs        bool  // Assume __attribute__(gcc_struct) applied to structs by default. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									//TODO MSStructs                               bool // Assume __attribute__(ms_struct) applied to structs by default. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									NoFieldAndBitfieldOverlap                bool  // Only bitfields can be grouped together. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									PreserveOnlyLastNonBlankSeparator        bool  // If PreserveWhiteSpace is true, keep only the last white space, do not combine 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									PreserveWhiteSpace                       bool  // Including also comments. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectElseExtraTokens                    bool  // Pedantic: do not silently accept "#else foo". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectEndifExtraTokens                   bool  // Pedantic: do not silently accept "#endif foo". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectFinalBackslash                     bool  // Pedantic: do not silently accept "foo\\\n". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectFunctionMacroEmptyReplacementList  bool  // Pedantic: do not silently accept "#define foo(bar)\n". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectIfdefExtraTokens                   bool  // Pedantic: do not silently accept "#ifdef foo bar". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectIfndefExtraTokens                  bool  // Pedantic: do not silently accept "#ifndef foo bar". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectIncludeNext                        bool  // Pedantic: do not silently accept "#include_next". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectInvalidVariadicMacros              bool  // Pedantic: do not silently accept "#define foo(bar...)". Standard allows only #define foo(bar, ...) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectLineExtraTokens                    bool  // Pedantic: do not silently accept "#line 1234 \"foo.c\" bar". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectMissingFinalNewline                bool  // Pedantic: do not silently accept "foo\nbar". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectUndefExtraTokens                   bool  // Pedantic: do not silently accept "#undef foo bar". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									UnsignedEnums                            bool  // GCC compatibility: enums with no negative values will have unsigned type. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  SharedFunctionDefinitions  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									M     map [ * FunctionDefinition ] struct { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m     map [ sharedFunctionDefinitionKey ] * FunctionDefinition  //TODO 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash  maphash . Hash 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  sharedFunctionDefinitionKey  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pos   StringID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									nm    StringID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash  uint64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Config amends behavior of translation phase 4 and above. Instances of Config  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// are not mutated by this package and it's safe to share/reuse them.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The *Config passed to Parse or Translate should not be mutated afterwards.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Config  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Config3 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ABI  ABI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									PragmaHandler  func ( Pragma ,  [ ] Token )  // Called on pragmas, other than #pragma STDC ..., if non nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-27 15:26:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// SharedFunctionDefinitions collects function definitions having the same 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// position and definition. This can happen, for example, when a function is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// defined in a header file included multiple times. Either within a single 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// translation unit or across translation units. In the later case just supply 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// the same SharedFunctionDefinitions in Config when translating/parsing each 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// translation unit. 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 15:41:41 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									SharedFunctionDefinitions  * SharedFunctionDefinitions 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-27 15:26:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// IncludeFileHandler, when non nil, is called by the preprocessor for every 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// successfully included file. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IncludeFileHandler  func ( pos  gotoken . Position ,  includePath  string ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 15:41:41 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									MaxErrors  int  // 0: default (10), < 0: unlimited, n: n. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									CheckExternInlineFnBodies               bool  // Translate will consider extern inline function bodies. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									DebugIncludePaths                       bool  // Output to stderr. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									DebugWorkingDir                         bool  // Output to stderr. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									DoNotTypecheckAsm                       bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									EnableAssignmentCompatibilityChecking   bool  // No such checks performed up to v3.31.0. Currently only partially implemented. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									InjectTracingCode                       bool  // Output to stderr. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									LongDoubleIsDouble                      bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									PreprocessOnly                          bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectAnonymousFields                   bool  // Pedantic: do not silently accept "struct{int;}". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectCaseRange                         bool  // Pedantic: do not silently accept "case 'a'...'z':". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectEmptyCompositeLiterals            bool  // Pedantic: do not silently accept "foo = (T){}". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectEmptyDeclarations                 bool  // Pedantic: do not silently accept "int foo(){};". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectEmptyFields                       bool  // Pedantic: do not silently accept "struct {int a;;} foo;". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectEmptyInitializerList              bool  // Pedantic: do not silently accept "foo f = {};". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectEmptyStructDeclaration            bool  // Pedantic: do not silently accept "struct{; int i}". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectEmptyStructs                      bool  // Pedantic: do not silently accept "struct foo {};". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectIncompatibleMacroRedef            bool  // Pedantic: do not silently accept "#define MIN(A,B) ...\n#define MIN(a,b) ...\n" etc. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectLabelValues                       bool  // Pedantic: do not silently accept "foo: bar(); void *ptr = &&foo;" or "goto *ptr". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectLateBinding                       bool  // Pedantic: do not silently accept void f() { g(); } void g() {} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectMissingConditionalExpr            bool  // Pedantic: do not silently accept "foo = bar ? : baz;". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectMissingDeclarationSpecifiers      bool  // Pedantic: do not silently accept "main() {}". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectMissingFinalStructFieldSemicolon  bool  // Pedantic: do not silently accept "struct{int i; int j}". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectNestedFunctionDefinitions         bool  // Pedantic: do not silently accept nested function definitons. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectParamSemicolon                    bool  // Pedantic: do not silently accept "int f(int a; int b)". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectStatementExpressions              bool  // Pedantic: do not silently accept "i = ({foo();})". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectTypeof                            bool  // Pedantic: do not silently accept "typeof foo" or "typeof(bar*)". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RejectUninitializedDeclarators          bool  // Reject int f() { int j; return j; } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									TrackAssignments                        bool  // Collect a list of LHS declarators a declarator is used in RHS or as an function argument. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									doNotSanityCheckComplexTypes            bool  // Testing only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fakeIncludes                            bool  // Testing only. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ignoreErrors                            bool  // Testing only. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ignoreIncludes                          bool  // Testing only. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ignoreUndefinedIdentifiers              bool  // Testing only. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  context  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast          * AST 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									breakCtx     Node 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									breaks       int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									casePromote  Type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cases        [ ] * LabeledStatement  // switch 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cfg          * Config 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									checkFn      * FunctionDefinition 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									closure      map [ StringID ] struct { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									continues    int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enums        map [ StringID ] Operand  //TODO putting this in alphabetical order within the struct causes crashes in VirtualBox/386 ??? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									goscanner . ErrorList 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									includePaths     [ ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									intBits          int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									intMaxWidth      int64  // Set if the preprocessor saw __INTMAX_WIDTH__. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									keywords         map [ StringID ] rune 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									maxAlign         int  // If non zero: maximum alignment of members of structures (other than zero-width bitfields). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									maxAlign0        int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									maxErrors        int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mode             mode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									modes            [ ] mode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mu               sync . Mutex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ptrdiffT         Type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									readDelta        int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sizeT            Type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									structTypes      map [ StringID ] Type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									structs          map [ StructInfo ] struct { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switches         int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sysIncludePaths  [ ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tuSize0          int64  // Sum of sizes of processed inputs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tuSources0       int32  // Number of processed inputs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									wcharT           Type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									capture         bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									evalIdentError  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  newContext ( cfg  * Config )  * context  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									maxErrors  :=  cfg . MaxErrors 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  maxErrors  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										maxErrors  =  10 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  & context { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cfg :          cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										enums :        map [ StringID ] Operand { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										keywords :     keywords , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										maxErrors :    maxErrors , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										structTypes :  map [ StringID ] Type { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										structs :      map [ StructInfo ] struct { } { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  tuSizeAdd ( n  int64 )     {  atomic . AddInt64 ( & c . tuSize0 ,  n )  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  tuSize ( )  int64         {  return  atomic . LoadInt64 ( & c . tuSize0 )  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  tuSourcesAdd ( n  int32 )  {  atomic . AddInt32 ( & c . tuSources0 ,  n )  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  tuSources ( )  int        {  return  int ( atomic . LoadInt32 ( & c . tuSources0 ) )  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  stddef ( nm  StringID ,  s  Scope ,  tok  Token )  Type  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  d  :=  s . typedef ( nm ,  tok ) ;  d  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  t  :=  d . Type ( ) ;  t  !=  nil  &&  t . Kind ( )  !=  Invalid  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  t 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . errNode ( & tok ,  "front-end: undefined: %s" ,  nm ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  noType 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  assignmentCompatibilityErrorCond ( n  Node ,  a ,  b  Type )  ( stop  bool )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! c . cfg . EnableAssignmentCompatibilityChecking  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  c . errNode ( n ,  "invalid type combination of conditional operator: %v and %v" ,  a ,  b ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  assignmentCompatibilityError ( n  Node ,  lhs ,  rhs  Type )  ( stop  bool )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! c . cfg . EnableAssignmentCompatibilityChecking  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  c . errNode ( n ,  "cannot use %v as type %v in assignment" ,  rhs ,  lhs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  errNode ( n  Node ,  msg  string ,  args  ... interface { } )  ( stop  bool )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  c . err ( n . Position ( ) ,  msg ,  args ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  err ( pos  token . Position ,  msg  string ,  args  ... interface { } )  ( stop  bool )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// dbg("FAIL "+msg, args...) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									//fmt.Printf("FAIL "+msg+"\n", args...) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  c . cfg . ignoreErrors  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s  :=  fmt . Sprintf ( msg ,  args ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									max  :=  c . maxErrors 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  max  <  0  ||  max  >  len ( c . ErrorList ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . ErrorList . Add ( gotoken . Position ( pos ) ,  s ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										stop  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  stop 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  errs ( list  goscanner . ErrorList )  ( stop  bool )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									max  :=  c . maxErrors 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  v  :=  range  list  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  max  <  0  ||  max  >  len ( c . ErrorList ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											c . ErrorList  =  append ( c . ErrorList ,  v ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  Err ( )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  x  :=  c . ErrorList . Err ( ) . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  goscanner . ErrorList : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										x  =  append ( goscanner . ErrorList ( nil ) ,  x ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  lpos  gotoken . Position 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										w  :=  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  v  :=  range  x  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  lpos . Filename  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  v . Pos . Filename  ==  lpos . Filename  &&  v . Pos . Line  ==  lpos . Line  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											x [ w ]  =  v 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											w ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											lpos  =  v . Pos 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										x  =  x [ : w ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sort . Slice ( x ,  func ( i ,  j  int )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											a  :=  x [ i ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											b  :=  x [ j ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ! a . Pos . IsValid ( )  &&  b . Pos . IsValid ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  a . Pos . IsValid ( )  &&  ! b . Pos . IsValid ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  a . Pos . Filename  <  b . Pos . Filename  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  a . Pos . Filename  >  b . Pos . Filename  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  a . Pos . Line  <  b . Pos . Line  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  a . Pos . Line  >  b . Pos . Line  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  a . Pos . Column  <  b . Pos . Column 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										a  :=  make ( [ ] string ,  0 ,  len ( x ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  v  :=  range  x  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											a  =  append ( a ,  v . Error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( "%s" ,  strings . Join ( a ,  "\n" ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  x 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  not ( n  Node ,  mode  mode )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  c . mode & mode  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  mode  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  mIntConstExpr : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											c . errNode ( n ,  "invalid integer constant expression" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											panic ( internalError ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  push ( mode  mode )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . modes  =  append ( c . modes ,  c . mode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . mode  =  mode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  pop ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									n  :=  len ( c . modes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . mode  =  c . modes [ n - 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . modes  =  c . modes [ : n - 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  statFile ( name  string ,  sys  bool )  ( os . FileInfo ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fs  :=  c . cfg . Config3 . Filesystem 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  fs  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fs  =  LocalFS ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  fs . Stat ( name ,  sys ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( c  * context )  openFile ( name  string ,  sys  bool )  ( io . ReadCloser ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fs  :=  c . cfg . Config3 . Filesystem 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  fs  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fs  =  LocalFS ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  fs . Open ( name ,  sys ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// HostConfig returns the system C preprocessor/compiler configuration, or an  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// error, if any.  The configuration is obtained by running the command named  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// by the cpp argumnent or "cpp" when it's empty.  For the predefined macros  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// list the '-dM' options is added. For the include paths lists, the option  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// '-v' is added and the output is parsed to extract the "..." include and  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// <...> include paths. To add any other options to cpp, list them in opts.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The function relies on a POSIX/GCC compatible C preprocessor installed.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Execution of HostConfig is not free, so caching of the results is  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// recommended.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  HostConfig ( cpp  string ,  opts  ... string )  ( predefined  string ,  includePaths ,  sysIncludePaths  [ ] string ,  err  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  cpp  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cpp  =  "cpp" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									args  :=  append ( append ( [ ] string { "-dM" } ,  opts ... ) ,  os . DevNull ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pre ,  err  :=  exec . Command ( cpp ,  args ... ) . Output ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  nil ,  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									args  =  append ( append ( [ ] string { "-v" } ,  opts ... ) ,  os . DevNull ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									out ,  err  :=  exec . Command ( cpp ,  args ... ) . CombinedOutput ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  nil ,  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sep  :=  "\n" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  env ( "GOOS" ,  runtime . GOOS )  ==  "windows"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sep  =  "\r\n" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									a  :=  strings . Split ( string ( out ) ,  sep ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  0 ;  i  <  len ( a ) ;  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  a [ i ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  "#include \"...\" search starts here:" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										loop : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  i  =  i  +  1 ;  i  <  len ( a ) ;  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												switch  v  :=  a [ i ] ;  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												case  strings . HasPrefix ( v ,  "#" )  ||  v  ==  "End of search list." : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break  loop 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													includePaths  =  append ( includePaths ,  strings . TrimSpace ( v ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													i ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  "#include <...> search starts here:" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  i  =  i  +  1 ;  i  <  len ( a ) ;  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												switch  v  :=  a [ i ] ;  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												case  strings . HasPrefix ( v ,  "#" )  ||  v  ==  "End of search list." : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  string ( pre ) ,  includePaths ,  sysIncludePaths ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													sysIncludePaths  =  append ( sysIncludePaths ,  strings . TrimSpace ( v ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													i ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											i ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  "" ,  nil ,  nil ,  fmt . Errorf ( "failed parsing %s -v output" ,  cpp ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  env ( key ,  val  string )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s  :=  os . Getenv ( key ) ;  s  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  val 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Token is a grammar terminal.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Token  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Rune   rune      // ';' or IDENTIFIER etc. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Sep    StringID  // If Config3.PreserveWhiteSpace is in effect: All preceding white space combined, including comments. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Value  StringID  // ";" or "foo" etc. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Src    StringID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									file   * tokenFile 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									macro  StringID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pos    int32 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									seq    int32 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Seq returns t's sequential number.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Comparing positions as in 'before', 'after' is complicated as tokens in a  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// translation unit usually come from more than one source file. Macro  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// expansion further complicates that. The solution is sequentially numbering  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the tokens as they are finally seen by the parser, so the usual arithmetic  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// '<', '>' operators can be used for that purpose.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( t  Token )  Seq ( )  int  {  return  int ( t . seq )  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Macro returns the name of a macro that expanded to this token, if any.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( t  * Token )  Macro ( )  StringID  {  return  t . macro  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// String implements fmt.Stringer.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( t  Token )  String ( )  string  {  return  t . Value . String ( )  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Position implements Node.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( t  * Token )  Position ( )  ( r  token . Position )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  t . pos  !=  0  &&  t . file  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										r  =  t . file . PositionFor ( token . Pos ( t . pos ) ,  true ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  r 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  tokStr ( toks  interface { } ,  sep  string )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  b  strings . Builder 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  x  :=  toks . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] token3 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  i ,  v  :=  range  x  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  i  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												b . WriteString ( sep ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											b . WriteString ( v . String ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] token4 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  i ,  v  :=  range  x  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  i  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												b . WriteString ( sep ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											b . WriteString ( v . String ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] cppToken : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  i ,  v  :=  range  x  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  i  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												b . WriteString ( sep ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											b . WriteString ( v . String ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] Token : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  i ,  v  :=  range  x  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  i  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												b . WriteString ( sep ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											b . WriteString ( v . String ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										panic ( internalError ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  b . String ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  internalError ( )  int  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									panic ( fmt . Errorf ( "%v: internal error" ,  origin ( 2 ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  internalErrorf ( s  string ,  args  ... interface { } )  int  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s  =  fmt . Sprintf ( s ,  args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									panic ( fmt . Errorf ( "%v: %s" ,  origin ( 2 ) ,  s ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  detectMingw ( s  string )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  strings . Contains ( s ,  "#define __MINGW" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  nodeSource ( n  ... Node )  ( r  string )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( n )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  a  [ ] * Token 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  v  :=  range  n  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Inspect ( v ,  func ( n  Node ,  _  bool )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  x ,  ok  :=  n . ( * Token ) ;  ok  &&  x . Seq ( )  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												a  =  append ( a ,  x ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sort . Slice ( a ,  func ( i ,  j  int )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  a [ i ] . Seq ( )  <  a [ j ] . Seq ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									w  :=  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									seq  :=  - 1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  v  :=  range  a  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  n  :=  v . Seq ( ) ;  n  !=  seq  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											seq  =  n 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											a [ w ]  =  v 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											w ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									a  =  a [ : w ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  b  strings . Builder 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  v  :=  range  a  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										b . WriteString ( v . Sep . String ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										b . WriteString ( v . Src . String ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  b . String ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}