modernc.org/cc@v1.0.1/cc.go (about)

     1  // Copyright 2016 The CC Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:generate go run generate.go
     6  //go:generate golex -o trigraphs.go trigraphs.l
     7  //go:generate golex -o scanner.go scanner.l
     8  //go:generate stringer -type Kind
     9  //go:generate stringer -type Linkage
    10  //go:generate stringer -type Namespace
    11  //go:generate stringer -type Scope
    12  //go:generate go run generate.go -2
    13  
    14  // Package cc is a C99 compiler front end.
    15  //
    16  // Changelog
    17  //
    18  // 2020-07-13 This package is no longer maintained. Please see the v3 version at
    19  //
    20  // 	https://modernc.org/cc/v3
    21  //
    22  // Links
    23  //
    24  // Referenced from elsewhere:
    25  //
    26  //  [0]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
    27  //  [1]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1406.pdf
    28  //  [2]: https://github.com/rsc/c2go/blob/fc8cbfad5a47373828c81c7a56cccab8b221d310/cc/cc.y
    29  //  [3]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
    30  package cc // import "modernc.org/cc"
    31  
    32  import (
    33  	"bufio"
    34  	"bytes"
    35  	"fmt"
    36  	"go/token"
    37  	"os"
    38  	"os/exec"
    39  	"runtime"
    40  	"strings"
    41  
    42  	"modernc.org/golex/lex"
    43  	"modernc.org/mathutil"
    44  	"modernc.org/strutil"
    45  	"modernc.org/xc"
    46  )
    47  
    48  const (
    49  	fakeTime = "__TESTING_TIME__"
    50  
    51  	gccPredefine = `
    52  #define __PRETTY_FUNCTION__ __func__
    53  #define __asm asm
    54  #define __attribute(x)
    55  #define __attribute__(x)
    56  #define __builtin___memcpy_chk(x, y, z, t) __BUILTIN___MEMCPY_CHK()
    57  #define __builtin___memset_chk(x, y, z, ...) __BUILTIN___MEMSET_CHK()
    58  #define __builtin_alloca(x) __BUILTIN_ALLOCA()
    59  #define __builtin_classify_type(x) __BUILTIN_CLASSIFY_TYPE()
    60  #define __builtin_constant_p(exp) __BUILTIN_CONSTANT_P()
    61  #define __builtin_isgreater(x, y) __BUILTIN_ISGREATER()
    62  #define __builtin_isless(x, y) __BUILTIN_ISLESS()
    63  #define __builtin_isunordered(x, y) __BUILTIN_ISUNORDERED()
    64  #define __builtin_longjmp(x, y) __BUILTIN_LONGJMP()
    65  #define __builtin_malloc(x) __BUILTIN_MALLOC()
    66  #define __builtin_memmove(x, y, z) __BUILTIN_MEMMOVE()
    67  #define __builtin_mempcpy(x, y, z) __BUILTIN_MEMPCPY()
    68  #define __builtin_mul_overflow(a, b, c) __BUILTIN_MUL_OVERFLOW()
    69  #define __builtin_offsetof(type, member) ((%[1]v)(&((type *)0)->member))
    70  #define __builtin_signbit(x) __BUILTIN_SIGNBIT()
    71  #define __builtin_va_arg(ap, type) ( *( type* )ap )
    72  #define __builtin_va_end(x)
    73  #define __builtin_va_list void*
    74  #define __builtin_va_start(x, y)
    75  #define __complex _Complex
    76  #define __complex__ _Complex
    77  #define __const
    78  #define __extension__
    79  #define __imag__
    80  #define __inline inline
    81  #define __real(x) __REAL()
    82  #define __real__
    83  #define __restrict
    84  #define __sync_fetch_and_add(x, y, ...) __SYNC_FETCH_AND_ADD()
    85  #define __sync_val_compare_and_swap(x, y, z, ...) __SYNC_VAL_COMPARE_AND_SWAP()
    86  #define __typeof typeof
    87  #define __volatile volatile
    88  %[1]v __builtin_object_size (void*, int);
    89  %[1]v __builtin_strlen(char*);
    90  %[1]v __builtin_strspn(char*, char*);
    91  _Bool __BUILTIN_MUL_OVERFLOW();
    92  char* __builtin___stpcpy_chk(char*, char*, %[1]v);
    93  char* __builtin_stpcpy(char*, char*);
    94  char* __builtin_strchr(char*, int);
    95  char* __builtin_strcpy(char*, char*);
    96  char* __builtin_strdup(char*);
    97  char* __builtin_strncpy(char*, char*, %[1]v);
    98  double _Complex __builtin_cpow(double _Complex, _Complex double);
    99  double __REAL();
   100  double __builtin_copysign(double, double);
   101  double __builtin_copysignl(long double, long double);
   102  double __builtin_inff();
   103  double __builtin_modf(double, double*);
   104  double __builtin_modfl(long double, long double*);
   105  double __builtin_nanf(char *);
   106  float _Complex __builtin_conjf(float _Complex);
   107  float __builtin_ceilf(float);
   108  float __builtin_copysignf(float, float);
   109  float __builtin_modff(float, float*);
   110  int __BUILTIN_CLASSIFY_TYPE();
   111  int __BUILTIN_CONSTANT_P();
   112  int __BUILTIN_ISGREATER();
   113  int __BUILTIN_ISLESS();
   114  int __BUILTIN_ISUNORDERED();
   115  int __BUILTIN_SIGNBIT();
   116  int __builtin___snprintf_chk (char*, %[1]v, int, %[1]v, char*, ...);
   117  int __builtin___sprintf_chk (char*, int, %[1]v, char*, ...);
   118  int __builtin___vsnprintf_chk (char*, %[1]v, int, %[1]v, char*, void*);
   119  int __builtin___vsprintf_chk (char*, int, %[1]v, char*, void*);
   120  int __builtin_abs(int);
   121  int __builtin_clrsb(int);
   122  int __builtin_clrsbl(long);
   123  int __builtin_clrsbll(long long);
   124  int __builtin_clz(unsigned int);
   125  int __builtin_clzl(unsigned long);
   126  int __builtin_clzll(unsigned long long);
   127  int __builtin_constant_p (exp);
   128  int __builtin_ctz(unsigned int x);
   129  int __builtin_ctzl(unsigned long);
   130  int __builtin_ctzll(unsigned long long);
   131  int __builtin_ffs(int);
   132  int __builtin_ffsl(long);
   133  int __builtin_ffsll(long long);
   134  int __builtin_isinf(double);
   135  int __builtin_isinff(float);
   136  int __builtin_isinfl(long double);
   137  int __builtin_memcmp(void*, void*, %[1]v);
   138  int __builtin_parity (unsigned);
   139  int __builtin_parityl(unsigned long);
   140  int __builtin_parityll (unsigned long long);
   141  int __builtin_popcount (unsigned int x);
   142  int __builtin_popcountl (unsigned long);
   143  int __builtin_popcountll (unsigned long long);
   144  int __builtin_printf(char*, ...);
   145  int __builtin_puts(char*);
   146  int __builtin_setjmp(void*);
   147  int __builtin_strcmp(char*, char*);
   148  int __builtin_strncmp(char*, char*, %[1]v);
   149  long __builtin_expect(long, long);
   150  long long strlen (char*);
   151  unsigned __builtin_bswap32 (unsigned x);
   152  unsigned long long __builtin_bswap64 (unsigned long long x);
   153  unsigned short __builtin_bswap16 (unsigned short x);
   154  void __BUILTIN_LONGJMP();
   155  void __SYNC_FETCH_AND_ADD();
   156  void __SYNC_VAL_COMPARE_AND_SWAP();
   157  void __builtin_abort(void);
   158  void __builtin_bcopy(void*, void*, %[1]v);
   159  void __builtin_bzero(void*, %[1]v);
   160  void __builtin_prefetch (void*, ...);
   161  void __builtin_stack_restore(void*);
   162  void __builtin_trap (void);
   163  void __builtin_unreachable (void);
   164  void __builtin_unwind_init();
   165  void __builtin_va_arg_pack ();
   166  void __builtin_va_copy(void*, void*);
   167  void* __BUILTIN_ALLOCA();
   168  void* __BUILTIN_MALLOC();
   169  void* __BUILTIN_MEMMOVE();
   170  void* __BUILTIN_MEMPCPY();
   171  void* __BUILTIN___MEMCPY_CHK();
   172  void* __BUILTIN___MEMSET_CHK();
   173  void* __builtin_alloca(int);
   174  void* __builtin_apply (void (*)(), void*, %[1]v);
   175  void* __builtin_apply_args();
   176  void* __builtin_extract_return_addr(void *);
   177  void* __builtin_frame_address(unsigned int);
   178  void* __builtin_memcpy(void*, void*, long long);
   179  void* __builtin_memset(void*, int, long long);
   180  void* __builtin_return_address (unsigned int);
   181  void* __builtin_stack_save();
   182  void* memcpy(void*, void*, long long);
   183  void* memset(void*, int, long long);
   184  `
   185  )
   186  
   187  // ImportPath returns the import path of this package or an error, if any.
   188  func ImportPath() (string, error) { return strutil.ImportPath() }
   189  
   190  // HostConfig executes HostCppConfig with the cpp argument set to "cpp". For
   191  // more info please see the documentation of HostCppConfig.
   192  func HostConfig(opts ...string) (predefined string, includePaths, sysIncludePaths []string, err error) {
   193  	return HostCppConfig("cpp", opts...)
   194  }
   195  
   196  // HostCppConfig returns the system C preprocessor configuration, or an error,
   197  // if any.  The configuration is obtained by running the cpp command. For the
   198  // predefined macros list the '-dM' options is added. For the include paths
   199  // lists, the option '-v' is added and the output is parsed to extract the
   200  // "..." include and <...> include paths. To add any other options to cpp, list
   201  // them in opts.
   202  //
   203  // The function relies on a POSIX compatible C preprocessor installed.
   204  // Execution of HostConfig is not free, so caching the results is recommended
   205  // whenever possible.
   206  func HostCppConfig(cpp string, opts ...string) (predefined string, includePaths, sysIncludePaths []string, err error) {
   207  	args := append(append([]string{"-dM"}, opts...), os.DevNull)
   208  	// cross-compile e.g. win64 -> win32
   209  	if runtime.GOARCH == "386" {
   210  		args = append(args, "-m32")
   211  	}
   212  	pre, err := exec.Command(cpp, args...).Output()
   213  	if err != nil {
   214  		return "", nil, nil, err
   215  	}
   216  
   217  	args = append(append([]string{"-v"}, opts...), os.DevNull)
   218  	out, err := exec.Command(cpp, args...).CombinedOutput()
   219  	if err != nil {
   220  		return "", nil, nil, err
   221  	}
   222  
   223  	sep := "\n"
   224  	if runtime.GOOS == "windows" {
   225  		sep = "\r\n"
   226  	}
   227  
   228  	a := strings.Split(string(out), sep)
   229  	for i := 0; i < len(a); {
   230  		switch a[i] {
   231  		case "#include \"...\" search starts here:":
   232  		loop:
   233  			for i = i + 1; i < len(a); {
   234  				switch v := a[i]; {
   235  				case strings.HasPrefix(v, "#") || v == "End of search list.":
   236  					break loop
   237  				default:
   238  					includePaths = append(includePaths, strings.TrimSpace(v))
   239  					i++
   240  				}
   241  			}
   242  		case "#include <...> search starts here:":
   243  			for i = i + 1; i < len(a); {
   244  				switch v := a[i]; {
   245  				case strings.HasPrefix(v, "#") || v == "End of search list.":
   246  					return string(pre), includePaths, sysIncludePaths, nil
   247  				default:
   248  					sysIncludePaths = append(sysIncludePaths, strings.TrimSpace(v))
   249  					i++
   250  				}
   251  			}
   252  		default:
   253  			i++
   254  		}
   255  	}
   256  	return "", nil, nil, fmt.Errorf("failed parsing %s -v output", cpp)
   257  }
   258  
   259  type tweaks struct {
   260  	allowCompatibleTypedefRedefinitions bool              // typedef int foo; typedef int foo;
   261  	comments                            map[token.Pos]int //
   262  	devTest                             bool              //
   263  	disablePredefinedLineMacro          bool              // __LINE__ will not expand.
   264  	enableAlignof                       bool              //
   265  	enableAlternateKeywords             bool              // __asm__ etc.
   266  	enableAnonymousStructFields         bool              //
   267  	enableAsm                           bool              //
   268  	enableBuiltinClassifyType           bool              // __builtin_classify_type(expr)
   269  	enableBuiltinConstantP              bool              // __builtin_constant_p(expr)
   270  	enableComputedGotos                 bool              // var = &&label; goto *var;
   271  	enableDefineOmitCommaBeforeDDD      bool              // #define foo(a, b...)
   272  	enableDlrInIdentifiers              bool              // foo$bar
   273  	enableEmptyDeclarations             bool              // ; // C++11
   274  	enableEmptyDefine                   bool              // #define
   275  	enableEmptyStructs                  bool              // struct foo {};
   276  	enableImaginarySuffix               bool              // 4.2i
   277  	enableImplicitFuncDef               bool              // int f() { return g(); } int g() { return 42; }
   278  	enableImplicitIntType               bool              // eg. 'static i;' is the same as 'static int i;'.
   279  	enableIncludeNext                   bool              //
   280  	enableLegacyDesignators             bool              // { a: 42 }
   281  	enableNonConstStaticInitExpressions bool              // static int *p = &i;
   282  	enableNoreturn                      bool              //
   283  	enableOmitConditionalOperand        bool              // x ? : y == x ? x : y
   284  	enableOmitFuncArgTypes              bool              // f(a) becomes the same as int f(int a).
   285  	enableOmitFuncRetType               bool              // f() becomes the same as int f().
   286  	enableParenCompoundStmt             bool              // ({...}), see [3]
   287  	enableStaticAssert                  bool              // _Static_assert
   288  	enableTrigraphs                     bool              // ??=define foo(bar)
   289  	enableTypeof                        bool              //
   290  	enableUndefExtraTokens              bool              // #undef foo(bar)
   291  	enableUnsignedEnums                 bool              // If no enum member is negative, enum type will be unsigned.
   292  	enableWarnings                      bool              // #warning
   293  	enableWideBitFieldTypes             bool              // long long v : 2;
   294  	enableWideEnumValues                bool              // enum { v = X } for X wider than 32bits
   295  	gccEmu                              bool              //
   296  	mode99c                             bool              //
   297  	preprocessOnly                      bool              //
   298  }
   299  
   300  func (t *tweaks) doGccEmu() *tweaks {
   301  	t.allowCompatibleTypedefRedefinitions = true
   302  	t.enableAlignof = true
   303  	t.enableAlternateKeywords = true
   304  	t.enableAnonymousStructFields = true
   305  	t.enableAsm = true
   306  	t.enableDefineOmitCommaBeforeDDD = true
   307  	t.enableDlrInIdentifiers = true
   308  	t.enableEmptyDefine = true
   309  	t.enableEmptyStructs = true
   310  	t.enableIncludeNext = true
   311  	t.enableNonConstStaticInitExpressions = true
   312  	t.enableNoreturn = true
   313  	t.enableOmitFuncRetType = true
   314  	t.enableStaticAssert = true
   315  	t.enableTypeof = true
   316  	t.enableUndefExtraTokens = true
   317  	t.enableWarnings = false
   318  	return t
   319  }
   320  
   321  func exampleAST(rule int, src string) interface{} {
   322  	report := xc.NewReport()
   323  	report.IgnoreErrors = true
   324  	r := bytes.NewBufferString(src)
   325  	r0, _, _ := r.ReadRune()
   326  	lx, err := newLexer(
   327  		fmt.Sprintf("example%v.c", rule),
   328  		len(src)+1, // Plus final injected NL
   329  		r,
   330  		report,
   331  		(&tweaks{gccEmu: true}).doGccEmu(),
   332  	)
   333  	lx.Unget(lex.NewChar(token.Pos(lx.File.Base()), r0))
   334  	lx.model = &Model{ // 64 bit
   335  		Items: map[Kind]ModelItem{
   336  			Ptr:               {8, 8, 8, nil},
   337  			Void:              {0, 1, 1, nil},
   338  			Char:              {1, 1, 1, nil},
   339  			SChar:             {1, 1, 1, nil},
   340  			UChar:             {1, 1, 1, nil},
   341  			Short:             {2, 2, 2, nil},
   342  			UShort:            {2, 2, 2, nil},
   343  			Int:               {4, 4, 4, nil},
   344  			UInt:              {4, 4, 4, nil},
   345  			Long:              {8, 8, 8, nil},
   346  			ULong:             {8, 8, 8, nil},
   347  			LongLong:          {8, 8, 8, nil},
   348  			ULongLong:         {8, 8, 8, nil},
   349  			Float:             {4, 4, 4, nil},
   350  			Double:            {8, 8, 8, nil},
   351  			LongDouble:        {8, 8, 8, nil},
   352  			Bool:              {1, 1, 1, nil},
   353  			FloatComplex:      {8, 8, 8, nil},
   354  			DoubleComplex:     {16, 16, 16, nil},
   355  			LongDoubleComplex: {16, 16, 16, nil},
   356  		},
   357  		tweaks: &tweaks{},
   358  	}
   359  
   360  	lx.model.initialize(lx)
   361  	if err != nil {
   362  		panic(err)
   363  	}
   364  
   365  	lx.exampleRule = rule
   366  	yyParse(lx)
   367  	return lx.example
   368  }
   369  
   370  func ppParseString(fn, src string, report *xc.Report, tweaks *tweaks) (*PreprocessingFile, error) {
   371  	sz := len(src)
   372  	lx, err := newLexer(fn, sz+1, bytes.NewBufferString(src), report, tweaks)
   373  	if err != nil {
   374  		return nil, err
   375  	}
   376  
   377  	lx.Unget(lex.NewChar(token.Pos(lx.File.Base()), PREPROCESSING_FILE))
   378  	yyParse(lx)
   379  	return lx.preprocessingFile, nil
   380  }
   381  
   382  func ppParse(fn string, report *xc.Report, tweaks *tweaks) (*PreprocessingFile, error) {
   383  	o := xc.Files.Once(fn, func() interface{} {
   384  		f, err := os.Open(fn)
   385  		if err != nil {
   386  			return err
   387  		}
   388  
   389  		defer f.Close()
   390  
   391  		fi, err := os.Stat(fn)
   392  		if err != nil {
   393  			return nil
   394  		}
   395  
   396  		sz := fi.Size()
   397  		if sz > mathutil.MaxInt-1 {
   398  			return fmt.Errorf("%s: file size too big: %v", fn, sz)
   399  		}
   400  
   401  		lx, err := newLexer(fn, int(sz)+1, bufio.NewReader(f), report, tweaks)
   402  		if err != nil {
   403  			return err
   404  		}
   405  
   406  		lx.Unget(lex.NewChar(token.Pos(lx.File.Base()), PREPROCESSING_FILE))
   407  		if yyParse(lx) != 0 {
   408  			return report.Errors(true)
   409  		}
   410  
   411  		return lx.preprocessingFile
   412  	})
   413  	switch r := o.Value(); x := r.(type) {
   414  	case error:
   415  		return nil, x
   416  	case *PreprocessingFile:
   417  		return x, nil
   418  	default:
   419  		panic("internal error")
   420  	}
   421  }
   422  
   423  // Opt is a configuration/setup function that can be passed to the Parser
   424  // function.
   425  type Opt func(*lexer)
   426  
   427  // KeepComments makes the parser keep comments.
   428  func KeepComments() Opt {
   429  	return func(l *lexer) { l.tweaks.comments = map[token.Pos]int{} }
   430  }
   431  
   432  // EnableBuiltinClassifyType makes the parser handle specially
   433  //
   434  //	__builtin_constant_p(expr)
   435  //
   436  // See https://gcc.gnu.org/onlinedocs/gccint/Varargs.html
   437  func EnableBuiltinClassifyType() Opt {
   438  	return func(l *lexer) { l.tweaks.enableBuiltinClassifyType = true }
   439  }
   440  
   441  // Mode99c turns on support for the 99c compiler.
   442  func Mode99c() Opt {
   443  	return func(l *lexer) { l.tweaks.mode99c = true }
   444  }
   445  
   446  // EnableBuiltinConstantP makes the parser handle specially
   447  //
   448  //	__builtin_constant_p(expr)
   449  //
   450  // See https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
   451  func EnableBuiltinConstantP() Opt {
   452  	return func(l *lexer) { l.tweaks.enableBuiltinConstantP = true }
   453  }
   454  
   455  // EnableImplicitIntType makes the parser accept non standard omitting type
   456  // specifier. For example
   457  //
   458  //	static i;
   459  //
   460  // becomes the same as
   461  //
   462  //	static int i;
   463  //
   464  func EnableImplicitIntType() Opt {
   465  	return func(l *lexer) { l.tweaks.enableImplicitIntType = true }
   466  }
   467  
   468  // EnableOmitConditionalOperand makes the parser accept non standard
   469  //
   470  //	x ? : y
   471  //
   472  // See https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Conditionals.html#Conditionals
   473  func EnableOmitConditionalOperand() Opt {
   474  	return func(l *lexer) { l.tweaks.enableOmitConditionalOperand = true }
   475  }
   476  
   477  // EnableComputedGotos makes the parser accept non standard
   478  //
   479  //	variable = &&label;
   480  //	goto *variable;
   481  //
   482  // See https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Labels-as-Values.html
   483  func EnableComputedGotos() Opt {
   484  	return func(l *lexer) { l.tweaks.enableComputedGotos = true }
   485  }
   486  
   487  // EnableUnsignedEnums makes the parser handle choose unsigned int as the type
   488  // of an enumeration with no negative members.
   489  func EnableUnsignedEnums() Opt {
   490  	return func(l *lexer) { l.tweaks.enableUnsignedEnums = true }
   491  }
   492  
   493  // EnableLegacyDesignators makes the parser accept legacy designators
   494  //
   495  //	{ a: 42 } // Obsolete since GCC 2.5, standard is { .a=42 }
   496  //
   497  // See https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
   498  func EnableLegacyDesignators() Opt {
   499  	return func(l *lexer) { l.tweaks.enableLegacyDesignators = true }
   500  }
   501  
   502  // AllowCompatibleTypedefRedefinitions makes the parser accept compatible
   503  // typedef redefinitions.
   504  //
   505  //	typedef int foo;
   506  //	typedef int foo; // ok with this option.
   507  //	typedef long int foo; // never ok.
   508  //
   509  func AllowCompatibleTypedefRedefinitions() Opt {
   510  	return func(l *lexer) { l.tweaks.allowCompatibleTypedefRedefinitions = true }
   511  }
   512  
   513  // EnableParenthesizedCompoundStatemen makes the parser accept non standard
   514  //
   515  //	({ ... })
   516  //
   517  // as an expression. See [3].
   518  func EnableParenthesizedCompoundStatemen() Opt {
   519  	return func(l *lexer) { l.tweaks.enableParenCompoundStmt = true }
   520  }
   521  
   522  // EnableImaginarySuffix makes the parser accept non standard
   523  //
   524  //	4.2i, 5.6j etc
   525  //
   526  // See https://gcc.gnu.org/onlinedocs/gcc/Complex.html
   527  func EnableImaginarySuffix() Opt {
   528  	return func(l *lexer) { l.tweaks.enableImaginarySuffix = true }
   529  }
   530  
   531  // EnableNonConstStaticInitExpressions makes the parser accept non standard
   532  //
   533  //	static int i = f();
   534  //
   535  // [0], 6.7.8/4: All the expressions in an initializer for an object that has
   536  // static storage duration shall be constant expressions or string literals.
   537  func EnableNonConstStaticInitExpressions() Opt {
   538  	return func(l *lexer) { l.tweaks.enableNonConstStaticInitExpressions = true }
   539  }
   540  
   541  // EnableAnonymousStructFields makes the parser accept non standard
   542  //
   543  //	struct {
   544  //		int i;
   545  //		struct {
   546  //			int j;
   547  //		};
   548  //		int k;
   549  //	};
   550  func EnableAnonymousStructFields() Opt {
   551  	return func(l *lexer) { l.tweaks.enableAnonymousStructFields = true }
   552  }
   553  
   554  // EnableOmitFuncRetType makes the parser accept non standard
   555  //
   556  //	f() // Same as int f().
   557  func EnableOmitFuncRetType() Opt {
   558  	return func(l *lexer) { l.tweaks.enableOmitFuncRetType = true }
   559  }
   560  
   561  // EnableOmitFuncArgTypes makes the parser accept non standard
   562  //
   563  //	f(a) // Same as int f(int a).
   564  func EnableOmitFuncArgTypes() Opt {
   565  	return func(l *lexer) { l.tweaks.enableOmitFuncArgTypes = true }
   566  }
   567  
   568  // EnableEmptyDeclarations makes the parser accept non standard
   569  //
   570  //	; // C++11 empty declaration
   571  func EnableEmptyDeclarations() Opt {
   572  	return func(l *lexer) { l.tweaks.enableEmptyDeclarations = true }
   573  }
   574  
   575  // EnableIncludeNext makes the parser accept non standard
   576  //
   577  //	#include_next "foo.h"
   578  func EnableIncludeNext() Opt {
   579  	return func(l *lexer) { l.tweaks.enableIncludeNext = true }
   580  }
   581  
   582  // EnableDefineOmitCommaBeforeDDD makes the parser accept non standard
   583  //
   584  //	#define foo(a, b...) // Note the missing comma after identifier list.
   585  func EnableDefineOmitCommaBeforeDDD() Opt {
   586  	return func(l *lexer) { l.tweaks.enableDefineOmitCommaBeforeDDD = true }
   587  }
   588  
   589  // EnableAlternateKeywords makes the parser accept, for example, non standard
   590  //
   591  //	__asm__
   592  //
   593  // as an equvalent of keyowrd asm (which first hast be permitted by EnableAsm).
   594  func EnableAlternateKeywords() Opt {
   595  	return func(l *lexer) { l.tweaks.enableAlternateKeywords = true }
   596  }
   597  
   598  // EnableDlrInIdentifiers makes the parser accept non standard
   599  //
   600  //	int foo$bar
   601  func EnableDlrInIdentifiers() Opt {
   602  	return func(l *lexer) { l.tweaks.enableDlrInIdentifiers = true }
   603  }
   604  
   605  // EnableEmptyDefine makes the parser accept non standard
   606  //
   607  //	#define
   608  func EnableEmptyDefine() Opt {
   609  	return func(l *lexer) { l.tweaks.enableEmptyDefine = true }
   610  }
   611  
   612  // EnableImplicitFuncDef makes the parser accept non standard
   613  //
   614  //	int f() {
   615  //		return g(); // g is undefined, but assumed to be returning int.
   616  //	}
   617  func EnableImplicitFuncDef() Opt {
   618  	return func(l *lexer) { l.tweaks.enableImplicitFuncDef = true }
   619  }
   620  
   621  // EnableEmptyStructs makes the parser accept non standard
   622  //
   623  //	struct foo {};
   624  func EnableEmptyStructs() Opt {
   625  	return func(l *lexer) { l.tweaks.enableEmptyStructs = true }
   626  }
   627  
   628  // EnableUndefExtraTokens makes the parser accept non standard
   629  //
   630  //	#undef foo(bar)
   631  func EnableUndefExtraTokens() Opt {
   632  	return func(l *lexer) { l.tweaks.enableUndefExtraTokens = true }
   633  }
   634  
   635  // EnableWideEnumValues makes the parser accept non standard
   636  //
   637  //	enum { v = X }; for X wider than 32 bits.
   638  func EnableWideEnumValues() Opt {
   639  	return func(l *lexer) { l.tweaks.enableWideEnumValues = true }
   640  }
   641  
   642  // EnableWideBitFieldTypes makes the parser accept non standard bitfield
   643  // types (i.e, long long and unsigned long long).
   644  //
   645  //	unsigned long long bits : 2;
   646  func EnableWideBitFieldTypes() Opt {
   647  	return func(l *lexer) { l.tweaks.enableWideBitFieldTypes = true }
   648  }
   649  
   650  // SysIncludePaths option configures where to search for system include files
   651  // (eg. <name.h>). Multiple SysIncludePaths options may be used, the resulting
   652  // search path list is produced by appending the option arguments in order of
   653  // appearance.
   654  func SysIncludePaths(paths []string) Opt {
   655  	return func(l *lexer) {
   656  		var err error
   657  		if l.sysIncludePaths, err = dedupAbsPaths(append(l.sysIncludePaths, fromSlashes(paths)...)); err != nil {
   658  			l.report.Err(0, "synIncludepaths option: %v", err)
   659  		}
   660  		l.sysIncludePaths = l.sysIncludePaths[:len(l.sysIncludePaths):len(l.sysIncludePaths)]
   661  	}
   662  }
   663  
   664  // IncludePaths option configures where to search for include files (eg.
   665  // "name.h").  Multiple IncludePaths options may be used, the resulting search
   666  // path list is produced by appending the option arguments in order of
   667  // appearance.
   668  func IncludePaths(paths []string) Opt {
   669  	return func(l *lexer) {
   670  		var err error
   671  		if l.includePaths, err = dedupAbsPaths(append(l.includePaths, fromSlashes(paths)...)); err != nil {
   672  			l.report.Err(0, "includepaths option: %v", err)
   673  		}
   674  		l.includePaths = l.includePaths[:len(l.includePaths):len(l.includePaths)]
   675  	}
   676  }
   677  
   678  // YyDebug sets the parser debug level.
   679  func YyDebug(n int) Opt {
   680  	return func(*lexer) { yyDebug = n }
   681  }
   682  
   683  // Cpp registers a preprocessor hook function which is called for every line,
   684  // or group of lines the preprocessor produces before it is consumed by the
   685  // parser. The token slice must not be modified by the hook.
   686  func Cpp(f func([]xc.Token)) Opt {
   687  	return func(lx *lexer) { lx.cpp = f }
   688  }
   689  
   690  // ErrLimit limits the number of calls to the error reporting methods.  After
   691  // the limit is reached, all errors are reported using log.Print and then
   692  // log.Fatal() is called with a message about too many errors.  To disable
   693  // error limit, set ErrLimit to value less or equal zero.  Default value is 10.
   694  func ErrLimit(n int) Opt {
   695  	return func(lx *lexer) { lx.report.ErrLimit = n }
   696  }
   697  
   698  // Trigraphs enables processing of trigraphs.
   699  func Trigraphs() Opt { return func(lx *lexer) { lx.tweaks.enableTrigraphs = true } }
   700  
   701  // EnableAsm enables recognizing the reserved word asm.
   702  func EnableAsm() Opt { return func(lx *lexer) { lx.tweaks.enableAsm = true } }
   703  
   704  // EnableNoreturn enables recognizing the reserved word _Noreturn.
   705  func EnableNoreturn() Opt { return func(lx *lexer) { lx.tweaks.enableNoreturn = true } }
   706  
   707  // EnableTypeOf enables recognizing the reserved word typeof.
   708  func EnableTypeOf() Opt { return func(lx *lexer) { lx.tweaks.enableTypeof = true } }
   709  
   710  // EnableAlignOf enables recognizing the reserved word _Alignof.
   711  func EnableAlignOf() Opt { return func(lx *lexer) { lx.tweaks.enableAlignof = true } }
   712  
   713  // EnableStaticAssert enables recognizing the reserved word _Static_assert.
   714  func EnableStaticAssert() Opt { return func(lx *lexer) { lx.tweaks.enableStaticAssert = true } }
   715  
   716  // CrashOnError is an debugging option.
   717  func CrashOnError() Opt { return func(lx *lexer) { lx.report.PanicOnError = true } }
   718  
   719  func disableWarnings() Opt      { return func(lx *lexer) { lx.tweaks.enableWarnings = false } }
   720  func gccEmu() Opt               { return func(lx *lexer) { lx.tweaks.gccEmu = true } }
   721  func getTweaks(dst *tweaks) Opt { return func(lx *lexer) { *dst = *lx.tweaks } }
   722  func nopOpt() Opt               { return func(*lexer) {} }
   723  func preprocessOnly() Opt       { return func(lx *lexer) { lx.tweaks.preprocessOnly = true } }
   724  
   725  func devTest() Opt {
   726  	return func(lx *lexer) { lx.tweaks.devTest = true }
   727  }
   728  
   729  func disablePredefinedLineMacro() Opt {
   730  	return func(lx *lexer) { lx.tweaks.disablePredefinedLineMacro = true }
   731  }
   732  
   733  // Parse defines any macros in predefine. Then Parse preprocesses and parses
   734  // the translation unit consisting of files in paths. The m communicates the
   735  // scalar types model and opts allow to amend parser behavior. m cannot be
   736  // reused and passed to Parse again.
   737  func Parse(predefine string, paths []string, m *Model, opts ...Opt) (*TranslationUnit, error) {
   738  	if m == nil {
   739  		return nil, fmt.Errorf("invalid nil model passed")
   740  	}
   741  
   742  	if m.initialized {
   743  		return nil, fmt.Errorf("invalid reused model passed")
   744  	}
   745  
   746  	fromSlashes(paths)
   747  	report := xc.NewReport()
   748  	lx0 := &lexer{tweaks: &tweaks{enableWarnings: true}, report: report}
   749  	for _, opt := range opts {
   750  		opt(lx0)
   751  	}
   752  	m.tweaks = lx0.tweaks
   753  	if err := report.Errors(true); err != nil {
   754  		return nil, err
   755  	}
   756  
   757  	if lx0.tweaks.devTest {
   758  		predefine += fmt.Sprintf(`
   759  #define __DATE__ %q
   760  #define __TIME__ %q
   761  `, xc.Dict.S(idTDate), fakeTime)
   762  	}
   763  
   764  	if t := lx0.tweaks; t.gccEmu {
   765  		t.doGccEmu()
   766  	}
   767  
   768  	m.initialize(lx0)
   769  	if err := m.sanityCheck(); err != nil {
   770  		report.Err(0, "%s", err.Error())
   771  		return nil, report.Errors(true)
   772  	}
   773  
   774  	if lx0.tweaks.gccEmu {
   775  		dts := debugTypeStrings
   776  		debugTypeStrings = false
   777  		predefine += fmt.Sprintf(gccPredefine, m.getSizeType(lx0))
   778  		debugTypeStrings = dts
   779  	}
   780  	tweaks := lx0.tweaks
   781  	predefined, err := ppParseString("<predefine>", predefine, report, tweaks)
   782  	if err != nil {
   783  		return nil, err
   784  	}
   785  
   786  	ch := make(chan []xc.Token, 1000)
   787  	macros := newMacros()
   788  	stop := make(chan int, 1)
   789  	go func() {
   790  		defer close(ch)
   791  
   792  		newPP(ch, lx0.includePaths, lx0.sysIncludePaths, macros, false, m, report, tweaks).preprocessingFile(predefined)
   793  		for _, path := range paths {
   794  			select {
   795  			case <-stop:
   796  				return
   797  			default:
   798  			}
   799  			pf, err := ppParse(path, report, tweaks)
   800  			if err != nil {
   801  				report.Err(0, err.Error())
   802  				return
   803  			}
   804  
   805  			newPP(ch, lx0.includePaths, lx0.sysIncludePaths, macros, true, m, report, tweaks).preprocessingFile(pf)
   806  		}
   807  	}()
   808  
   809  	if err := report.Errors(true); err != nil { // Do not parse if preprocessing already failed.
   810  		go func() {
   811  			for range ch { // Drain.
   812  			}
   813  		}()
   814  		stop <- 1
   815  		return nil, err
   816  	}
   817  
   818  	lx := newSimpleLexer(lx0.cpp, report, tweaks)
   819  	lx.ch = ch
   820  	lx.state = lsTranslationUnit0
   821  	lx.model = m
   822  	if lx.tweaks.preprocessOnly {
   823  		var lval yySymType
   824  		for lval.Token.Rune != lex.RuneEOF {
   825  			lx.Lex(&lval)
   826  		}
   827  		return nil, report.Errors(true)
   828  	}
   829  
   830  	yyParse(lx)
   831  	stop <- 1
   832  	for range ch { // Drain.
   833  	}
   834  	if tu := lx.translationUnit; tu != nil {
   835  		tu.Macros = macros.macros()
   836  		tu.Model = m
   837  		tu.Comments = lx0.tweaks.comments
   838  		if c := tu.Comments; c != nil {
   839  			for _, v := range tu.Declarations.Identifiers {
   840  				switch x := v.Node.(type) {
   841  				case *DirectDeclarator:
   842  					pos0 := x.Declarator.Pos()
   843  					if !pos0.IsValid() {
   844  						pos0 = x.Pos()
   845  					}
   846  					if !pos0.IsValid() {
   847  						break
   848  					}
   849  
   850  					if comment(lx0.tweaks, x, x.Declarator) != 0 {
   851  						break
   852  					}
   853  
   854  					for p := x.prev; p != nil; {
   855  						y := p.Node.(*DirectDeclarator)
   856  						if n := comment(lx0.tweaks, y, y.Declarator); n != 0 {
   857  							pos := y.DirectDeclarator.Pos()
   858  							if !pos.IsValid() {
   859  								pos = y.Pos()
   860  							}
   861  							c[pos0] = n
   862  							break
   863  						}
   864  						p2 := p.Node.(*DirectDeclarator).prev
   865  						if p2 == p {
   866  							break
   867  						}
   868  
   869  						p = p2
   870  					}
   871  				default:
   872  					panic(fmt.Errorf("%T", x))
   873  				}
   874  			}
   875  		}
   876  	}
   877  	return lx.translationUnit, report.Errors(true)
   878  }