github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/program/cstd.go (about)

     1  package program
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  )
     7  
     8  type stdFunction struct {
     9  	cFunc          string
    10  	includeHeader  string
    11  	functionBody   string
    12  	dependPackages []string
    13  	dependFuncStd  []string
    14  }
    15  
    16  func init() {
    17  	source := `
    18  
    19  //---
    20  // fmax returns the larger of its arguments: either x or y.
    21  // c function : double fmax(double , double )
    22  // dep pkg    : 
    23  // dep func   :
    24  func fmax(x, y float64) float64 {
    25  	if x < y {
    26  		return y
    27  	}
    28  	return x
    29  }
    30  
    31  //---
    32  // fmaxl returns the larger of its arguments: either x or y.
    33  // c function : long double fmaxl(long double , long double )
    34  // dep pkg    : 
    35  // dep func   :
    36  func fmaxl(x, y float64) float64 {
    37  	if x < y {
    38  		return y
    39  	}
    40  	return x
    41  }
    42  
    43  //---
    44  // cbrt compute cube root
    45  // c function : float cbrtf(float)
    46  // dep pkg    : math
    47  // dep func   :
    48  func cbrtf(x float32) float32 {
    49  	return float32(math.Cbrt(float64(x)))
    50  }
    51  
    52  //---
    53  // BoolToInt converts boolean value to an int, which is a common operation in C.
    54  // 0 and 1 represent false and true respectively.
    55  // c function : int BoolToInt(int)
    56  // dep pkg    : 
    57  // dep func   :
    58  func BoolToInt(x bool) int32 {
    59  	if x {
    60  		return 1
    61  	}
    62  
    63  	return 0
    64  }
    65  
    66  
    67  
    68  
    69  //---
    70  // fma returns x*y+z.
    71  // c function : double fma(double, double, double)
    72  // dep pkg    : 
    73  // dep func   :
    74  func fma(x, y, z float64) float64 {
    75  	return x*y + z
    76  }
    77  
    78  
    79  //---
    80  // fmal returns x*y+z.
    81  // c function : long double fmal(long double, long double, long double)
    82  // dep pkg    : 
    83  // dep func   :
    84  func fmal(x, y, z float64) float64 {
    85  	return x*y + z
    86  }
    87  
    88  
    89  
    90  //---
    91  // fmaf returns x*y+z.
    92  // c function : float fmaf(float, float, float)
    93  // dep pkg    : 
    94  // dep func   :
    95  func fmaf(x, y, z float32) float32 {
    96  	return x*y + z
    97  }
    98  
    99  
   100  //---
   101  // realloc is function from stdlib.h.
   102  // c function : void * realloc(void* , size_t )
   103  // dep pkg    : reflect
   104  // dep func   : memcpy
   105  func realloc(ptr interface{}, size uint32) interface{} {
   106  	if ptr == nil {
   107  		return make([]byte, size)
   108  	}
   109  	elemType := reflect.TypeOf(ptr).Elem()
   110  	ptrNew := reflect.MakeSlice(reflect.SliceOf(elemType), int(size), int(size)).Interface()
   111  	// copy elements
   112  	memcpy(ptrNew, ptr, size)
   113  	return ptrNew
   114  }
   115  
   116  
   117  //---
   118  // memcpy is function from string.h.
   119  // c function : void * memcpy( void * , const void * , size_t )
   120  // dep pkg    : reflect
   121  // dep func   :
   122  func memcpy(dst, src interface{}, size uint32) interface{} {
   123  	switch reflect.TypeOf(src).Kind() {
   124  	case reflect.Slice:
   125  		s := reflect.ValueOf(src)
   126  		d := reflect.ValueOf(dst)
   127  		if s.Len() == 0 {
   128  			return dst
   129  		}
   130  		if s.Len() > 0 {
   131  			size /= uint32(int(s.Index(0).Type().Size()))
   132  		}
   133  		var val reflect.Value
   134  		for i := 0; i < int(size); i++ {
   135  			if i < s.Len() {
   136  				val = s.Index(i)
   137  			}
   138  			d.Index(i).Set(val)
   139  		}
   140  	}
   141  	return dst
   142  }
   143  
   144  //---
   145  // __assert_fail from assert.h
   146  // c function : bool __assert_fail(const char*, const char*, unsigned int, const char*)
   147  // dep pkg    : fmt os github.com/Konstantin8105/c4go/noarch
   148  // dep func   :
   149  func __assert_fail(
   150  	expression, filePath []byte,
   151  	lineNumber uint32,
   152  	functionName []byte,
   153  ) bool {
   154  	fmt.Fprintf(
   155  		os.Stderr,
   156  		"a.out: %s:%d: %s: Assertion %s%s' failed.\n",
   157  		noarch.CStringToString(filePath),
   158  		lineNumber,
   159  		noarch.CStringToString(functionName),
   160  		string(byte(96)),
   161  		noarch.CStringToString(expression),
   162  	)
   163  	os.Exit(134)
   164  
   165  	return true
   166  }
   167  
   168  
   169  //---
   170  // tolower from ctype.h
   171  // c function : int tolower(int)
   172  // dep pkg    : unicode
   173  // dep func   :
   174  func tolower (_c int32) int32 {
   175  	return int32(unicode.ToLower(rune(_c)))
   176  }
   177  
   178  
   179  //---
   180  // toupper from ctype.h
   181  // c function : int toupper(int)
   182  // dep pkg    : unicode
   183  // dep func   :
   184  func toupper(_c int32) int32 {
   185  	return int32(unicode.ToUpper(rune(_c)))
   186  }
   187  
   188  
   189  
   190  //---
   191  // __isnanf from math.h
   192  // c function : int __isnanf(float)
   193  // dep pkg    : math
   194  // dep func   : BoolToInt
   195  func __isnanf(x float32) int32 {
   196  	return BoolToInt(math.IsNaN(float64(x)))
   197  }
   198  
   199  //---
   200  // __isinff from math.h
   201  // c function : int __isinff(float)
   202  // dep pkg    : math
   203  // dep func   : BoolToInt
   204  func __isinff(x float32) int32 {
   205  	return BoolToInt(math.IsInf(float64(x), 0))
   206  }
   207  
   208  //---
   209  // __nanf from math.h
   210  // c function : double __nanf(const char *)
   211  // dep pkg    : math
   212  // dep func   : 
   213  func __nanf(_ []byte) float64 {
   214  	return math.NaN()
   215  }
   216  
   217  //---
   218  // __inff from math.h
   219  // c function : float __inff()
   220  // dep pkg    : math
   221  // dep func   : 
   222  func __inff() float32 {
   223  	return float32(math.Inf(0))
   224  }
   225  
   226  
   227  //---
   228  // __isinf from math.h
   229  // c function : int __isinf(double)
   230  // dep pkg    : math
   231  // dep func   : BoolToInt
   232  func __isinf(x float64) int32 {
   233  	return BoolToInt(math.IsInf(x, 0))
   234  }
   235  
   236  //---
   237  // __builtin_isinf_sign from math.h
   238  // c function : int __builtin_isinf_sign(float)
   239  // dep pkg    : math
   240  // dep func   : BoolToInt
   241  func  __builtin_isinf_sign(x float32) int32 {
   242  	return BoolToInt(math.IsInf(float64(x), 0))
   243  }
   244  
   245  //---
   246  // __isinfl from math.h
   247  // c function : int __isinfl(long double)
   248  // dep pkg    : math
   249  // dep func   : BoolToInt
   250  func __isinfl(x float64) int32 {
   251  	return BoolToInt(math.IsInf(x, 0))
   252  }
   253  
   254  //---
   255  // __signbit from math.h
   256  // c function : int __signbit(double)
   257  // dep pkg    : math
   258  // dep func   : BoolToInt
   259  func __signbit(x float64) int32 {
   260  	return BoolToInt(math.Signbit(x))
   261  }
   262  
   263  //---
   264  // __signbitd from math.h
   265  // c function : int __signbitd(double)
   266  // dep pkg    : math
   267  // dep func   : BoolToInt
   268  func __signbitd(x float64) int32 {
   269  	return BoolToInt(math.Signbit(x))
   270  }
   271  
   272  //---
   273  // __signbitl from math.h
   274  // c function : int __signbitl(long double)
   275  // dep pkg    : math
   276  // dep func   : BoolToInt
   277  func __signbitl(x float64) int32 {
   278  	return BoolToInt(math.Signbit(x))
   279  }
   280  
   281  //---
   282  // __signbitf ...
   283  // c function : int __signbitf(float)
   284  // dep pkg    : math
   285  // dep func   : BoolToInt
   286  func __signbitf(x float32) int32 {
   287  	return BoolToInt(math.Signbit(float64(x)))
   288  }
   289  
   290  
   291  
   292  //---
   293  // __isnanl from math.h
   294  // c function : int __isnanl(long double)
   295  // dep pkg    : math
   296  // dep func   : BoolToInt
   297  func __isnanl(x float64) int32 {
   298  	return BoolToInt(math.IsNaN(x))
   299  }
   300  
   301  
   302  //---
   303  // __isnan from math.h
   304  // c function : int __isnan(double)
   305  // dep pkg    : math
   306  // dep func   : BoolToInt
   307  func __isnan(x float64) int32 {
   308  	return BoolToInt(math.IsNaN(x))
   309  }
   310  
   311  
   312  //---
   313  // sinhf from math.h
   314  // c function : float sinhf(float) 
   315  // dep pkg    : math
   316  // dep func   : 
   317  // sinhf compute hyperbolic sine
   318  func sinhf(a float32) float32 {
   319  	return float32(math.Sinh(float64(a)))
   320  }
   321  
   322  //---
   323  // coshf from math.h
   324  // c function : float coshf(float) 
   325  // dep pkg    : math
   326  // dep func   : 
   327  // coshf compute hyperbolic cose
   328  func coshf(a float32) float32 {
   329  	return float32(math.Cosh(float64(a)))
   330  }
   331  
   332  
   333  //---
   334  // tanhf from math.h
   335  // c function : float tanhf(float) 
   336  // dep pkg    : math
   337  // dep func   : 
   338  // tanhf compute hyperbolic tan
   339  func tanhf(a float32) float32 {
   340  	return float32(math.Tanh(float64(a)))
   341  }
   342  
   343  //---
   344  // hypotf from math.h
   345  // c function : float hypotf(float) 
   346  // dep pkg    : math
   347  // dep func   : 
   348  // hypotf compute the square root of the sum of the squares of x and y
   349  func hypotf(x, y float32) float32 {
   350  	return float32(math.Hypot(float64(x), float64(y)))
   351  }
   352  
   353  //---
   354  // copysignf from math.h
   355  // c function : float copysignf(float, float)
   356  // dep pkg    : math
   357  // dep func   : 
   358  // copysignf copies sign of y to absolute value of x
   359  func copysignf(x float32, y float32) float32 {
   360  	return float32(math.Copysign(float64(x), float64(y)))
   361  }
   362  
   363  //---
   364  // expf from math.h
   365  // c function : float expf(float )
   366  // dep pkg    : math
   367  // dep func   : 
   368  // expf : finds e^x
   369  func expf(x float32) float32 {
   370  	return float32(math.Exp(float64(x)))
   371  }
   372  
   373  //---
   374  // erff from math.h
   375  // c function : float erff(float )
   376  // dep pkg    : math
   377  // dep func   : 
   378  // erff : finds error function value of x
   379  func erff(x float32) float32 {
   380  	return float32(math.Erf(float64(x)))
   381  }
   382  
   383  //---
   384  // erfcf from math.h
   385  // c function : float erfcf(float )
   386  // dep pkg    : math
   387  // dep func   : 
   388  // erfcf : finds error function value of x
   389  func erfcf(x float32) float32 {
   390  	return float32(math.Erfc(float64(x)))
   391  }
   392  
   393  //---
   394  // lround from math.h
   395  // c function : long int lround(double )
   396  // dep pkg    : 
   397  // dep func   : lroundl
   398  func lround(x float32) int32 {
   399  	return lroundl(float64(x))
   400  }
   401  
   402  //---
   403  // lroundf from math.h
   404  // c function : long int lroundf(float )
   405  // dep pkg    : 
   406  // dep func   : lroundl
   407  func lroundf(x float32) int32 {
   408  	return lroundl(float64(x))
   409  }
   410  
   411  //---
   412  // lroundl from math.h
   413  // c function : long int lroundl(long double )
   414  // dep pkg    : math
   415  // dep func   : 
   416  func lroundl(x float64) int32 {
   417  	return int32(math.Round(x))
   418  }
   419  
   420  //---
   421  // fmin from math.h
   422  // c function : double fmin(double , double )
   423  // dep pkg    : 
   424  // dep func   : 
   425  // fmin returns the smaller of its arguments: either x or y.
   426  func fmin(x, y float64) float64 {
   427  	if x < y {
   428  		return x
   429  	}
   430  	return y
   431  }
   432  
   433  //---
   434  // fminl from math.h
   435  // c function : double fminl(long double , long double )
   436  // dep pkg    : 
   437  // dep func   : 
   438  // fmin returns the smaller of its arguments: either x or y.
   439  func fminl(x, y float64) float64 {
   440  	if x < y {
   441  		return x
   442  	}
   443  	return y
   444  }
   445  
   446  //---
   447  // fminf from math.h
   448  // c function : float fminf(float , float ) 
   449  // dep pkg    : 
   450  // dep func   : 
   451  // fminf returns the smaller of its arguments: either x or y.
   452  func fminf(x, y float32) float32 {
   453  	if x < y {
   454  		return x
   455  	}
   456  	return y
   457  }
   458  
   459  //---
   460  // fmaxf from math.h
   461  // c function : float fmaxf(float , float ) 
   462  // dep pkg    : 
   463  // dep func   : 
   464  // fmaxf returns the larger of its arguments: either x or y.
   465  func fmaxf(x, y float32) float32 {
   466  	if x < y {
   467  		return y
   468  	}
   469  	return x
   470  }
   471  
   472  //---
   473  // fdiml from math.h
   474  // c function : long double fdiml(long double,long double) 
   475  // dep pkg    : 
   476  // dep func   : 
   477  // fdiml returns the positive difference between x and y.
   478  func fdiml(x, y float64) float64 {
   479  	if x > y {
   480  		return x - y
   481  	}
   482  	return 0
   483  }
   484  
   485  
   486  //---
   487  // fdim from math.h
   488  // c function : double fdim(double, double) 
   489  // dep pkg    : 
   490  // dep func   : 
   491  // fdim returns the positive difference between x and y.
   492  func fdim(x, y float64) float64 {
   493  	if x > y {
   494  		return x - y
   495  	}
   496  	return 0
   497  }
   498  
   499  //---
   500  // fdimf from math.h
   501  // c function : float fdimf(float, float) 
   502  // dep pkg    : 
   503  // dep func   : 
   504  // fdimf returns the positive difference between x and y.
   505  func fdimf(x, y float32) float32 {
   506  	if x > y {
   507  		return x - y
   508  	}
   509  	return 0
   510  }
   511  
   512  //---
   513  // log2f from math.h
   514  // c function : float log2f(float) 
   515  // dep pkg    : math
   516  // dep func   : 
   517  // log2f returns the binary (base-2) logarithm of x.
   518  func log2f(x float32) float32 {
   519  	return float32(math.Log2(float64(x)))
   520  }
   521  
   522  
   523  //---
   524  // log1pf from math.h
   525  // c function : float log1pf(float) 
   526  // dep pkg    : math
   527  // dep func   : 
   528  // log1pf compute ln(1+arg)
   529  func log1pf(arg float32) float32 {
   530  	return float32(math.Log1p(float64(arg)))
   531  }
   532  
   533  //---
   534  // llround from math.h
   535  // c function : long long int llround(double )
   536  // dep pkg    : 
   537  // dep func   : llroundl
   538  func llround(x float32) int64 {
   539  	return llroundl(float64(x))
   540  }
   541  
   542  //---
   543  // llroundf from math.h
   544  // c function : long long int llroundf(float )
   545  // dep pkg    : 
   546  // dep func   : llroundl
   547  func llroundf(x float32) int64 {
   548  	return llroundl(float64(x))
   549  }
   550  
   551  
   552  //---
   553  // llroundl from math.h
   554  // c function : long long int llroundl(long double )
   555  // dep pkg    : math
   556  // dep func   : 
   557  func llroundl(x float64) int64 {
   558  	return int64(math.Round(x))
   559  }
   560  
   561  //---
   562  // expm1f from math.h
   563  // c function : float expm1f(float) 
   564  // dep pkg    : math
   565  // dep func   : 
   566  // expm1f returns e raised to the power x minus one: e^x-1
   567  func expm1f(x float32) float32 {
   568  	return float32(math.Expm1(float64(x)))
   569  }
   570  
   571  
   572  //---
   573  // exp2f from math.h
   574  // c function : float exp2f(float) 
   575  // dep pkg    : math
   576  // dep func   : 
   577  // exp2f Returns the base-2 exponential function of x, which is 2 raised
   578  // to the power x: 2^x
   579  func exp2f(x float32) float32 {
   580  	return float32(math.Exp2(float64(x)))
   581  }
   582  
   583  
   584  //---
   585  // __ctype_b_loc from ctype.h
   586  // c function : const unsigned short int** __ctype_b_loc()
   587  // dep pkg    : unicode
   588  // dep func   : 
   589  func __ctype_b_loc() [][]uint16 {
   590  	var characterTable []uint16
   591  
   592  	for i := 0; i < 255; i++ {
   593  		var c uint16
   594  
   595  		// Each of the bitwise expressions below were copied from the enum
   596  		// values, like _ISupper, etc.
   597  
   598  		if unicode.IsUpper(rune(i)) {
   599  			c |= ((1 << (0)) << 8)
   600  		}
   601  
   602  		if unicode.IsLower(rune(i)) {
   603  			c |= ((1 << (1)) << 8)
   604  		}
   605  
   606  		if unicode.IsLetter(rune(i)) {
   607  			c |= ((1 << (2)) << 8)
   608  		}
   609  
   610  		if unicode.IsDigit(rune(i)) {
   611  			c |= ((1 << (3)) << 8)
   612  		}
   613  
   614  		if unicode.IsDigit(rune(i)) ||
   615  			(i >= 'a' && i <= 'f') ||
   616  			(i >= 'A' && i <= 'F') {
   617  			// IsXDigit. This is the same implementation as the Mac version.
   618  			// There may be a better way to do this.
   619  			c |= ((1 << (4)) << 8)
   620  		}
   621  
   622  		if unicode.IsSpace(rune(i)) {
   623  			c |= ((1 << (5)) << 8)
   624  		}
   625  
   626  		if unicode.IsPrint(rune(i)) {
   627  			c |= ((1 << (6)) << 8)
   628  		}
   629  
   630  		// The IsSpace check is required because Go treats spaces as graphic
   631  		// characters, which C does not.
   632  		if unicode.IsGraphic(rune(i)) && !unicode.IsSpace(rune(i)) {
   633  			c |= ((1 << (7)) << 8)
   634  		}
   635  
   636  		// http://www.cplusplus.com/reference/cctype/isblank/
   637  		// The standard "C" locale considers blank characters the tab
   638  		// character ('\t') and the space character (' ').
   639  		if i == int('\t') || i == int(' ') {
   640  			c |= ((1 << (8)) >> 8)
   641  		}
   642  
   643  		if unicode.IsControl(rune(i)) {
   644  			c |= ((1 << (9)) >> 8)
   645  		}
   646  
   647  		if unicode.IsPunct(rune(i)) {
   648  			c |= ((1 << (10)) >> 8)
   649  		}
   650  
   651  		if unicode.IsLetter(rune(i)) || unicode.IsDigit(rune(i)) {
   652  			c |= ((1 << (11)) >> 8)
   653  		}
   654  
   655  		// Yes, I know this is a hideously slow way to do it but I just want to
   656  		// test if this works right now.
   657  		characterTable = append(characterTable, c)
   658  	}
   659  	return [][]uint16{characterTable}
   660  }
   661  
   662  
   663  
   664  
   665  `
   666  	// split source by parts
   667  	var (
   668  		splitter = "//---"
   669  		cFunc    = "c function :"
   670  		depPkg   = "dep pkg    :"
   671  		depFunc  = "dep func   :"
   672  	)
   673  	cs := strings.Split(source, splitter)
   674  
   675  	// Examples:
   676  	// __signbitf ...
   677  	// __inline_signbitf ...
   678  	// __builtin_signbitf ...
   679  	to := []string{"__inline_", "__builtin_"}
   680  	for i, size := 0, len(cs); i < size; i++ {
   681  		if !strings.Contains(cs[i], "__") {
   682  			continue
   683  		}
   684  		for j := range to {
   685  			part := strings.Replace(cs[i], "__", to[j], -1)
   686  			cs = append(cs, part)
   687  		}
   688  	}
   689  
   690  	for _, c := range cs {
   691  		if strings.TrimSpace(c) == "" {
   692  			continue
   693  		}
   694  		var s stdFunction
   695  		s.functionBody = c
   696  
   697  		lines := strings.Split(c, "\n")
   698  		var foundCfunc, foundDepPkg, foundDepFunc bool
   699  		for _, line := range lines {
   700  			if index := strings.Index(line, cFunc); index > 0 {
   701  				line = line[index+len(cFunc):]
   702  				s.cFunc = strings.TrimSpace(line)
   703  				if line == "" {
   704  					panic(fmt.Errorf("no function name : %v", lines))
   705  				}
   706  				foundCfunc = true
   707  			}
   708  			if index := strings.Index(line, depPkg); index > 0 {
   709  				line = line[index+len(depPkg):]
   710  				pkgs := strings.Split(line, " ")
   711  				for _, pkg := range pkgs {
   712  					if pkg == "" || strings.TrimSpace(pkg) == "" {
   713  						continue
   714  					}
   715  					s.dependPackages = append(s.dependPackages, pkg)
   716  				}
   717  				foundDepPkg = true
   718  			}
   719  			if index := strings.Index(line, depFunc); index > 0 {
   720  				line = line[index+len(depFunc):]
   721  				funcs := strings.Split(line, " ")
   722  				for _, f := range funcs {
   723  					if f == "" || strings.TrimSpace(f) == "" {
   724  						continue
   725  					}
   726  					s.dependFuncStd = append(s.dependFuncStd, f)
   727  				}
   728  				foundDepFunc = true
   729  			}
   730  		}
   731  		if !foundCfunc || !foundDepPkg || !foundDepFunc {
   732  			panic(c)
   733  		}
   734  
   735  		std = append(std, s)
   736  	}
   737  }
   738  
   739  var std []stdFunction