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