Coder Social home page Coder Social logo

c4go's Introduction

Go Report Card codecov GitHub license Go Go Reference

A tool for transpiling C code to Go code.

Milestones of the project:

  1. Transpiling project GNU GSL.
  2. Transpiling project GTK+.

Notes:

Installation

Installation with version generation.

# get code
go get -u github.com/Konstantin8105/c4go

# move to project source
cd $GOPATH/src/github.com/Konstantin8105/c4go

# generate version
go generate ./...

# install
go install

# testing
c4go version

Usage example

# Change your location to the folder with examples:
cd $GOPATH/src/github.com/Konstantin8105/c4go/examples/

# Transpile one file from the C example folder:
c4go transpile prime.c

# Look at the result
nano prime.go

# Check the result:
go run prime.go
# Enter a number
# 13
# The number is: 13
# Prime number.

C code of file prime.c:

#include <stdio.h>

int main()
{
    int n, c;

    printf("Enter a number\n");
    // get value
    scanf("%d", &n);
    printf("The number is: %d\n", n);

    // -------
    if (n == 2)
        printf("Prime number.\n");
    else {
        for (c = 2; c <= n - 1; c++) {
            if (n % c == 0)
                break;
        }
        if (c != n)
            printf("Not prime.\n");
        else
            printf("Prime number.\n");
    }
    return 0;
}

Go code of file prime.go:

//
//	Package - transpiled by c4go
//
//	If you have found any issues, please raise an issue at:
//	https://github.com/Konstantin8105/c4go/
//

package main

import "unsafe"
import "github.com/Konstantin8105/c4go/noarch"
import "fmt"

// main - transpiled function from  C4GO/examples/prime.c:3
func main() {
	var n int32
	var c int32
	fmt.Printf("Enter a number\n")
	// get value
	noarch.Scanf([]byte("%d\x00"), c4goUnsafeConvert_int32(&n))
	noarch.Printf([]byte("The number is: %d\n\x00"), n)
	if n == 2 {
		// -------
		fmt.Printf("Prime number.\n")
	} else {
		for c = 2; c <= n-1; c++ {
			if n%c == 0 {
				break
			}
		}
		if c != n {
			fmt.Printf("Not prime.\n")
		} else {
			fmt.Printf("Prime number.\n")
		}
	}
	return
}

// c4goUnsafeConvert_int32 : created by c4go
func c4goUnsafeConvert_int32(c4go_name *int32) []int32 {
	return (*[1000000]int32)(unsafe.Pointer(c4go_name))[:]
}

Example with binding function

C:

#include <math.h>
#include <stdio.h>

int main()
{
    int n;
    double param = 8.0, result;
    result = frexp(param, &n);
    printf("result = %5.2f\n", result);
    printf("n      = %d\n", n);
    return 0;
}

c4go add automatically C binding for function without implementation:

//
//	Package - transpiled by c4go
//
//	If you have found any issues, please raise an issue at:
//	https://github.com/Konstantin8105/c4go/
//

package main

// #include </usr/include/math.h>
import "C"

import "github.com/Konstantin8105/c4go/noarch"
import "unsafe"

// main - transpiled function from  C4GO/examples/math.c:4
func main() {
	var n int32
	var param float64 = 8
	var result float64
	result = frexp(param, c4goUnsafeConvert_int32(&n))
	noarch.Printf([]byte("result = %5.2f\n\x00"), result)
	noarch.Printf([]byte("n      = %d\n\x00"), n)
	return
}

// c4goUnsafeConvert_int32 : created by c4go
func c4goUnsafeConvert_int32(c4go_name *int32) []int32 {
	return (*[1000000]int32)(unsafe.Pointer(c4go_name))[:]
}

// frexp - add c-binding for implemention function
func frexp(arg0 float64, arg1 []int32) float64 {
 	return float64(C.frexp(C.double(arg0), (*C.int)(unsafe.Pointer(&arg1[0]))))
}

Example with C-pointers and C-arrays

#include <stdio.h>

// input argument - C-pointer
void a(int* v1) { printf("a: %d\n", *v1); }

// input argument - C-array
void b(int v1[], int size)
{
    for (size--; size >= 0; size--) {
        printf("b: %d %d\n", size, v1[size]);
    }
}

int main()
{
    // value
    int i1 = 42;
    a(&i1);
    b(&i1, 1);

    // C-array
    int i2[] = { 11, 22 };
    a(i2);
    b(i2, 2);

    // C-pointer from value
    int* i3 = &i1;
    a(i3);
    b(i3, 1);

    // C-pointer from array
    int* i4 = i2;
    a(i4);
    b(i4, 2);

    // C-pointer from array
    int* i5 = i2[1];
    a(i5);
    b(i5, 1);

    return 0;
}
//
//	Package - transpiled by c4go
//
//	If you have found any issues, please raise an issue at:
//	https://github.com/Konstantin8105/c4go/
//

package main

import "unsafe"
import "github.com/Konstantin8105/c4go/noarch"

// a - transpiled function from  C4GO/examples/ap.c:4
func a(v1 []int32) {
	// input argument - C-pointer
	noarch.Printf([]byte("a: %d\n\x00"), v1[0])
}

// b - transpiled function from  C4GO/examples/ap.c:7
func b(v1 []int32, size int32) {
	{
		// input argument - C-array
		for size -= 1; size >= 0; size-- {
			noarch.Printf([]byte("b: %d %d\n\x00"), size, v1[size])
		}
	}
}

// main - transpiled function from  C4GO/examples/ap.c:14
func main() {
	var i1 int32 = 42
	// value
	a(c4goUnsafeConvert_int32(&i1))
	b(c4goUnsafeConvert_int32(&i1), 1)
	var i2 []int32 = []int32{11, 22}
	// C-array
	a(i2)
	b(i2, 2)
	var i3 []int32 = c4goUnsafeConvert_int32(&i1)
	// C-pointer from value
	a(i3)
	b(i3, 1)
	var i4 []int32 = i2
	// C-pointer from array
	a(i4)
	b(i4, 2)
	var i5 []int32 = i2[1:]
	// C-pointer from array
	a(i5)
	b(i5, 1)

	return
}

// c4goUnsafeConvert_int32 : created by c4go
func c4goUnsafeConvert_int32(c4go_name *int32) []int32 {
	return (*[1000000]int32)(unsafe.Pointer(c4go_name))[:]
}

Example of transpilation neatvi.

# clone git repository
git clone https://github.com/aligrudi/neatvi.git

# move in folder
cd neatvi

# look in Makefile
cat Makefile

Makefile:

CC = cc
CFLAGS = -Wall -O2
LDFLAGS =

OBJS = vi.o ex.o lbuf.o mot.o sbuf.o ren.o dir.o syn.o reg.o led.o \
	uc.o term.o rset.o regex.o cmd.o conf.o

all: vi

conf.o: conf.h

%.o: %.c
	$(CC) -c $(CFLAGS) $<
vi: $(OBJS)
	$(CC) -o $@ $(OBJS) $(LDFLAGS)
clean:
rm -f *.o vi

As we see not need any specific, for example -clang-flag.

Let's try transpile:

c4go transpile *.c

Result:

panic: clang failed: exit status 1:

/temp/neatvi/reg.c:6:14: error: redefinition of 'bufs' with a different type: 'char *[256]' vs 'struct buf [8]'
static char *bufs[256];
             ^
/temp/neatvi/ex.c:35:3: note: previous definition is here
} bufs[8];
  ^
/temp/neatvi/reg.c:12:9: error: returning 'struct buf' from a function with incompatible result type 'char *'
 return bufs[c];
        ^~~~~~~
/temp/neatvi/reg.c:17:81: error: invalid operands to binary expression ('int' and 'struct buf')
 char *pre = ((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISupper) && bufs[tolower(c)] ? bufs[tolower(c)] : "";
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^  ~~~~~~~~~~~~~~~~
/temp/neatvi/reg.c:21:7: error: passing 'struct buf' to parameter of incompatible type 'void *'
 free(bufs[tolower(c)]);
      ^~~~~~~~~~~~~~~~
/usr/include/stdlib.h:483:25: note: passing argument to parameter '__ptr' here
extern void free (void *__ptr) __attribute__ ((__nothrow__ ));
                        ^
/temp/neatvi/reg.c:22:19: error: assigning to 'struct buf' from incompatible type 'char *'
 bufs[tolower(c)] = buf;
                  ^ ~~~
/temp/neatvi/reg.c:43:8: error: passing 'struct buf' to parameter of incompatible type 'void *'
  free(bufs[i]);
       ^~~~~~~
/usr/include/stdlib.h:483:25: note: passing argument to parameter '__ptr' here
extern void free (void *__ptr) __attribute__ ((__nothrow__ ));
                        ^
/temp/neatvi/regex.c:98:12: error: static declaration of 'uc_len' follows non-static declaration
static int uc_len(char *s)
           ^
/temp/neatvi/vi.h:83:5: note: previous declaration is here
int uc_len(char *s);
    ^
/temp/neatvi/regex.c:200:14: error: static declaration of 'uc_beg' follows non-static declaration
static char *uc_beg(char *beg, char *s)
             ^
/temp/neatvi/vi.h:101:7: note: previous declaration is here
char *uc_beg(char *beg, char *s);
      ^
/temp/neatvi/vi.c:635:12: error: redefinition of 'linecount'
static int linecount(char *s)
           ^
/temp/neatvi/lbuf.c:124:12: note: previous definition is here
static int linecount(char *s)
           ^
9 errors generated.


goroutine 1 [running]:
main.generateAstLines(0x1, 0x0, 0xc000010140, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
	/go/src/github.com/Konstantin8105/c4go/main.go:438 +0xd40
main.Start(0x1, 0x0, 0xc000010140, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
	/go/src/github.com/Konstantin8105/c4go/main.go:356 +0xa9
main.runCommand(0x0)
	/go/src/github.com/Konstantin8105/c4go/main.go:723 +0xa45
main.main()
	/go/src/github.com/Konstantin8105/c4go/main.go:556 +0x22

That error is good and enought information for next step of transpilation. Let's clarify one of them - we see 2 function with same function name and if you open files and compare.

/temp/neatvi/vi.c:635:12: error: redefinition of 'linecount'
static int linecount(char *s)

/temp/neatvi/lbuf.c:124:12: note: previous definition is here
static int linecount(char *s)

This is 2 absolute identical function, so we can remove one of them. I choose remove function linecount from file vi.c, because in according to error - it is duplicate.

Also remove next function in according to errors:

  • vi.c function linecount
  • regex.c function uc_len
  • regex.c function uc_bed

Next error is about duplicate of variable names:

/temp/neatvi/reg.c:6:14: error: redefinition of 'bufs' with a different type: 'char *[256]' vs 'struct buf [8]'
static char *bufs[256];
             ^
/temp/neatvi/ex.c:35:3: note: previous definition is here
} bufs[8];

Let's replace variable name in file reg.c and run:

sed -i.bak 's/bufs/bufs_postfix/g' reg.c

Now, let's try again and output in file vi.go:

c4go transpile -o vi.go *.c

Now transpiled without clang error. Look the result:

less vi.go

We see warning of lose some types:

// Warning (*ast.BinaryOperator):  /temp/neatvi/cmd.c:20 :Cannot transpile BinaryOperator with type 'int' : result type = {}. Error: operator is `=`. Cannot casting {__pid_t -> int}. err = Cannot resolve type '__pid_t' : I couldn't find an appropriate Go type for the C type '__pid_t'.

For fix that add flag -s for adding all type from C standard library:

c4go transpile -o vi.go -s *.c

Now, all is Ok. Look the result:

less vi.go

C standard library implementation

            assert.h	       1/1	         100%
             ctype.h	     13/13	         100%
             errno.h	       0/1	           0%
             float.h	          	    undefined
            iso646.h	          	    undefined
            limits.h	          	    undefined
            locale.h	       0/3	           0%
              math.h	     22/22	         100%
            setjmp.h	       0/3	           0%
            signal.h	       3/3	         100%
            stdarg.h	       4/4	         100%
            stddef.h	       4/4	         100%
             stdio.h	     37/41	        90.2%
            stdlib.h	     31/37	        83.8%
            string.h	     21/24	        87.5%
              time.h	      1/15	        6.67%
             wchar.h	      3/60	           5%
            wctype.h	      0/21	           0%

Contributing

Feel free to submit PRs or open issues. Main information from: en.cppreference.com

Testing

By default, only unit tests are run with go test. You can also include the integration tests:

go test -tags=integration ./...

Integration tests in the form of complete C programs that can be found in the tests directory.

Integration tests work like this:

  1. clang compiles the C to a binary as normal.
  2. c4go converts the C file to Go.
  3. Both binaries are executed and the output is compared. All C files will contain some output so the results can be verified.

Note

Use lastest version of clang.

If you use Ubuntu, then use command like next for choose clang version:

sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-6.0 1000

Performance

Main time of transpilation takes clang, for example run:

go test -tags=integration -run=Benchmark -bench=. -benchmem

Result looks for example:

goos: linux
goarch: amd64
pkg: github.com/Konstantin8105/c4go
BenchmarkTranspile/Full-6         	       5	 274922964 ns/op	43046865 B/op	  379676 allocs/op
BenchmarkTranspile/GoCode-6       	      20	  86806808 ns/op	36577533 B/op	  308060 allocs/op
PASS

So, transpilation time is just 30% of full time. In my point of view no need of performance optimization, see Amdahl's law.

Example of performance analyse

Please run:

# Run cpuprofiling for sqlite transpilation example
time ./scripts/sqlite.sh 

# Example of output:
#
# % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
#                                 Dload  Upload   Total   Spent    Left  Speed
#100 2217k  100 2217k    0     0   235k      0  0:00:09  0:00:09 --:--:--  357k
#Archive:  /tmp/SQLITE/sqlite-amalgamation-3250200.zip
#   creating: /tmp/SQLITE/sqlite-amalgamation-3250200/
#  inflating: /tmp/SQLITE/sqlite-amalgamation-3250200/sqlite3ext.h  
#  inflating: /tmp/SQLITE/sqlite-amalgamation-3250200/sqlite3.c  
#  inflating: /tmp/SQLITE/sqlite-amalgamation-3250200/sqlite3.h  
#  inflating: /tmp/SQLITE/sqlite-amalgamation-3250200/shell.c  
#After transpiling shell.c and sqlite3.c together, have summary: 695 warnings.
#In file sqlite.go summary : 3 warnings in go build.
#Amount unsafe package using: 2902
#
#real	0m18.434s
#user	0m14.212s
#sys	0m1.434s

# Run profiler
go tool pprof ./testdata/cpu.out

For more information, see Profiling Go Programs.

c4go's People

Contributors

alebcay avatar alexandear avatar bradleyjkemp avatar corebreaker avatar crgimenes avatar crvv avatar elliotchance avatar jnjackins avatar jorbs avatar konstantin8105 avatar lestrrat avatar pravj avatar rjalfa avatar souvikmaji avatar tboztuna avatar timothygk avatar tjyang avatar utkarshgupta-cs avatar x-tyger avatar xoviat avatar xyproto avatar yulvil avatar zoeyfyi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

c4go's Issues

Fix: Cannot casting {int -> (noreturn)}

#include <stdio.h>

int main (int argc, char *argv[]){
  FILE *fp;
  int nchars, nwords, nlines;
  int lastnblank;    /* 0 iff the last character was a space */
  char c;

  if(argc!=2){
    printf("Usage: %s filename\n", argv[0]);
    exit(0);
  }
  if((fp=fopen(argv[1],"r"))==NULL){
    perror("fopen");
    exit(0); // <<--- PROBLEM HERE
  }
}
// Warning (*ast.CallExpr):  /home/konstantin/go/src/github.com/Konstantin8105/c4go-rating/testdata/SingleCcode/counts.c:18 :Cannot casting {int -> (noreturn)}. err = Cannot resolve type '(noreturn)' : Cannot separate function '(noreturn)' : Cannot parse function '(noreturn)' : Don't found '(' in type : (noreturn)
|   | | `-CallExpr 0x33a7680 <line:18:5, col:11> 'void'
|   | |   |-ImplicitCastExpr 0x33a7668 <col:5> 'void (*)(int) __attribute__((noreturn))' <FunctionToPointerDecay>
|   | |   | `-DeclRefExpr 0x33a75f0 <col:5> 'void (int) __attribute__((noreturn))' Function 0x33a74e0 'exit' 'void (int) __attribute__((noreturn))'
|   | |   `-IntegerLiteral 0x33a7618 <col:10> 'int' 0

F: printf %u

Example of C code:

printf("Символьный литерал \'A\':\t%d\n", sizeof('A'));

Fix: panic CharacterLiteral

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    printf("Размер (в байтах) для типов данных:\n\n");
    printf("Тип данных int: \t%lu\n", sizeof(int));
    printf("Тип данных char: \t%lu\n", sizeof(char));
    printf("Символьный литерал \'A\':\t%lu\n", sizeof('A'));
    printf("Тип данных float:\t%lu\n", sizeof(float));
    printf("Тип данных double:\t%lu\n", sizeof(double));
    printf("Текст \"мой текст\":\t%lu\n", sizeof("мой текст"));

    return 0;
}
panic: cannot do unary on: &ast.CharacterLiteral{Addr:0x2c7c9e0, Pos:ast.Position{File:"/home/konstantin/go/src/github.com/Konstantin8105/c4go-rating/testdata/book-c-the-examples-and-tasks/Глава 1/1.2/main.c", Line:9, LineEnd:0, Column:72, ColumnEnd:0, StringValue:""}, Type:"int", Value:65, ChildNodes:[]ast.Node{}}

goroutine 1 [running]:
github.com/Konstantin8105/c4go/transpiler.transpileUnaryExprOrTypeTraitExpr(0xc4202dcfa0, 0xc420314140, 0xc420472590, 0xc4204725a8, 0x7fe0f0, 0x0, 0xc420472540, 0x43c5b0, 0xc42063fb40, 0x7fe0f0, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/unary.go:637 +0x320
github.com/Konstantin8105/c4go/transpiler.transpileToExpr(0x7cb220, 0xc4202dcfa0, 0xc420314140, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7fe0f0, 0x0, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/transpiler.go:201 +0x35d
github.com/Konstantin8105/c4go/transpiler.transpileCallExpr(0xc42001ad20, 0xc420314140, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/call.go:243 +0x5b3
github.com/Konstantin8105/c4go/transpiler.transpileToExpr(0x7c9ee0, 0xc42001ad20, 0xc420314140, 0xc420472a01, 0x0, 0x0, 0x0, 0x0, 0x7fe0f0, 0x0, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/transpiler.go:195 +0x96d
github.com/Konstantin8105/c4go/transpiler.transpileToStmt(0x7c9ee0, 0xc42001ad20, 0xc420314140, 0x0, 0x0, 0x7fe0f0, 0x0, 0x0, 0x7fe0f0, 0x0, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/transpiler.go:374 +0x24f
github.com/Konstantin8105/c4go/transpiler.transpileToStmts(0x7c9ee0, 0xc42001ad20, 0xc420314140, 0x7fe0f0, 0x0, 0x0, 0x0, 0x0)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/transpiler.go:266 +0x13b
github.com/Konstantin8105/c4go/transpiler.transpileCompoundStmt(0xc4203fc930, 0xc420314140, 0xc420472d80, 0xc420472d98, 0x7ca020, 0xc4203fc930, 0x3, 0xc4200001a0, 0xc4201f3a00, 0xc420020000, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/scope.go:53 +0x61e
github.com/Konstantin8105/c4go/transpiler.transpileToStmt(0x7ca020, 0xc4203fc930, 0xc420314140, 0x0, 0x0, 0x7fe0f0, 0x0, 0x0, 0x7fe0f0, 0x0, ...)

Fix: panic

/* number.c -- Reading and writing integer as character sequences .
 *             Notice that the base for the digits is the constant
 *             BASE that I have chosen to be 10. Of course, you
 *             use a different value. You might even chose to
 *             have the base as a function parameter.
 */

#include <stdio.h>
#include <assert.h>

#define BASE 10

// a is a string. cursor is a position in a such that a[cursor] is a digit.
// Return the integer value represented by the longest sequence of digits
// in a starting at cursor. On exit cursor will be at the first position
// in a that does not contain a digit. Note that we assume that the base for 
// the number is 10. 
int getNumberToken(char a[], int *cursor)
{
  int value = 0;
  assert((*cursor) >= 0 && (*cursor) < strlen(a));
  do
    {
	value = value*BASE + (int)(a[*cursor]) - (int)('0');
	(*cursor)++;
    }
  while (isdigit(a[*cursor]));
  return value;
}

// value is a positive integer. a is a character array with n positions.
// Store in a as a '\0' terminated string the representation of value as
// a string in base BASE.
void putNumberToken(int value, char a[], int n)
{
  int k;
  int h, temp;
  assert(value >= 0 && n > 0);
  // We collect the desired string in reverse order
  for (k = 0; k < n-1; ++k)
    {
      a[k] = (char)(value%BASE + (int)'0');
      value = value/BASE;
      if (value == 0) break;
    }
  if (k == 0)     // If value was 0 we still return a '0'
    a[k] = '0';
  a[++k] = '\0';
  // Now we put the string in the right order
  for (h = 0; h < k/2; ++h)
    {
      temp = a[h];
      a[h] = a[k-1-h];
      a[k-1-h] = temp;
    }
}

void main (void)
{
  char s[] = "5432";
  int k = 0;
  int val = getNumberToken(s, &k);
  char outs[256];

  printf("val = %d, k = %d\n", val, k);
  putNumberToken(val, outs, 256);
  printf("val = %s\n", outs);
}
panic: Type *ast.CallExpr is not implemented in createIfWithNotConditionAndBreak

goroutine 1 [running]:
github.com/Konstantin8105/c4go/transpiler.createIfWithNotConditionAndBreak(0x7c9ee0, 0xc4203f4af0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/branch.go:609 +0xa26
github.com/Konstantin8105/c4go/transpiler.transpileDoStmt(0xc4201974a0, 0xc4200de3c0, 0xc4204daad0, 0xc4204daae8, 0x7ca2a0, 0xc4201974a0, 0x3, 0xc4200001a0, 0xc4203f9b00, 0xc420021300, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/branch.go:556 +0x3fb
github.com/Konstantin8105/c4go/transpiler.transpileToStmt(0x7ca2a0, 0xc4201974a0, 0xc4200de3c0, 0x0, 0x0, 0x7fe0f0, 0x0, 0x0, 0x7fe0f0, 0x0, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/transpiler.go:317 +0x102c
github.com/Konstantin8105/c4go/transpiler.transpileToStmts(0x7ca2a0, 0xc4201974a0, 0xc4200de3c0, 0x7fe0f0, 0x0, 0x0, 0x0, 0x0)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/transpiler.go:266 +0x13b
github.com/Konstantin8105/c4go/transpiler.transpileCompoundStmt(0xc4200da150, 0xc4200de3c0, 0xc42057ed80, 0xc42057ed98, 0x7ca020, 0xc4200da150, 0x3, 0xc4200001a0, 0xc4203f8dc0, 0xc420021300, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/scope.go:53 +0x61e
github.com/Konstantin8105/c4go/transpiler.transpileToStmt(0x7ca020, 0xc4200da150, 0xc4200de3c0, 0x0, 0x0, 0x7fe0f0, 0x0, 0x0, 0x7fe0f0, 0x0, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/transpiler.go:334 +0xed5
github.com/Konstantin8105/c4go/transpiler.transpileToStmts(0x7ca020, 0xc4200da150, 0xc4200de3c0, 0x7fe0f0, 0x0, 0x0, 0x0, 0x0)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/transpiler.go:266 +0x13b
github.com/Konstantin8105/c4go/transpiler.transpileToBlockStmt(0x7ca020, 0xc4200da150, 0xc4200de3c0, 0xc4203fd100, 0x3, 0xc420161540, 0x2, 0x2, 0x0, 0x0, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/scope.go:71 +0x46
github.com/Konstantin8105/c4go/transpiler.transpileFunctionDecl(0xc4200e5ad0, 0xc4200de3c0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/functions.go:119 +0x26fe
github.com/Konstantin8105/c4go/transpiler.transpileToNode(0x7ca5e0, 0xc4200e5ad0, 0xc4200de3c0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/transpiler.go:434 +0x548
github.com/Konstantin8105/c4go/transpiler.transpileTranslationUnitDecl(0xc4200de3c0, 0xc420188aa0, 0xc42057f688, 0x7cb0e0, 0xc420188aa0, 0xc4200de3c0, 0x0)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/translation_unit.go:40 +0x217
github.com/Konstantin8105/c4go/transpiler.transpileToNode(0x7cb0e0, 0xc420188aa0, 0xc4200de3c0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/transpiler.go:431 +0xe1b
github.com/Konstantin8105/c4go/transpiler.TranspileAST(0x7ffdbd46bf86, 0x23, 0x6a2966, 0x4, 0xc4200de3c0, 0x7cb0e0, 0xc420188aa0, 0x12000, 0xc420198280)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/transpiler/transpiler.go:33 +0x212
main.generateGoCode(0x0, 0xc42008a040, 0x1, 0x1, 0x0, 0x0, 0x0, 0x7ffdbd46bf86, 0x23, 0x6a2966, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/main.go:347 +0x725
main.Start(0x0, 0xc42008a040, 0x1, 0x1, 0x0, 0x0, 0x0, 0x7ffdbd46bf86, 0x23, 0x6a2966, ...)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/main.go:219 +0x285
main.runCommand(0xc4200001a0)
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/main.go:488 +0x4df
main.main()
	/home/konstantin/go/src/github.com/Konstantin8105/c4go/main.go:415 +0x22

math.expf

Add test and implementation on Go for function math.h expf
Description: https://en.cppreference.com/w/c/numeric/math/exp
File for test code add : c4go/tests/math.c
Example see #155
Example of test, see

c4go/tests/math.c

Lines 218 to 230 in be1760b

diag("exp");
is_eq(exp(0), 1);
is_eq(exp(1), 2.7182818284590450908);
is_eq(exp(-1), 0.36787944117144233402);
is_eq(exp(0.5), 1.6487212707001281942);
// https://github.com/golang/go/issues/20539
disabled(is_inf(exp(1.23e300), 1));
is_eq(exp(-1.23e-300), 1);
is_eq(exp(M_PI), 23.140692632779266802);
is_eq(exp(M_E), 15.154262241479262485);
is_inf(exp(INFINITY), 1);
is_eq(exp(-INFINITY), 0);
is_nan(exp(NAN));

F: AST

// AST Error : Cannot parse line: `VarDecl 0x3ec9368 parent 0x3dcaaf0 prev 0x3ec4088 <col:4, col:15> 
col:15 used CBLAS_CallFromC 'int' extern`. could not match regexp with string

// AST Error : ^(?P<address>[0-9a-fx]+) (?:prev (?P<prev>0x[0-9a-f]+) )?(?:parent (?P<parent>0x[0-9a-
f]+) )?<(?P<position>.*)>(?P<position2> .+:\d+)?(?P<used> used)?(?P<referenced> referenced)?(?P<name>
 \w+)? '(?P<type>.+?)'(?P<type2>:'.*?')?(?P<extern> extern)?(?P<static> static)?(?P<cinit> cinit)?(?P
<register> register)?[\s]*$

Example

parse expression

		R1o = ( (2.0*w1+w2)*x1*x1 - (w1+2.0*w2)*x2*x2 + 
			 3.0*(w1+w2)*Ln*(x2-x1) - (w1-w2)*x1*x2 ) / (6.0*Ln);
		R2o = ( (w1+2.0*w2)*x2*x2 + (w1-w2)*x1*x2 -
			(2.0*w1+w2)*x1*x1 ) / (6.0*Ln);

		f01 = (  3.0*(w2+4.0*w1)*x1*x1*x1*x1 -  3.0*(w1+4.0*w2)*x2*x2*x2*x2
		      - 15.0*(w2+3.0*w1)*Ln*x1*x1*x1 + 15.0*(w1+3.0*w2)*Ln*x2*x2*x2
		      -  3.0*(w1-w2)*x1*x2*(x1*x1 + x2*x2)
		      + 20.0*(w2+2.0*w1)*Ln*Ln*x1*x1 - 20.0*(w1+2.0*w2)*Ln*Ln*x2*x2
		      + 15.0*(w1-w2)*Ln*x1*x2*(x1+x2)
		      -  3.0*(w1-w2)*x1*x1*x2*x2 - 20.0*(w1-w2)*Ln*Ln*x1*x2 ) / 360.0;

F: AST panic

// AST Error : Cannot parse line: `VarDecl 0x28f8490 <col:3, col:43> col:19 used a 'char *' register cinit`. could not match regexp with string
// AST Error : ^(?P<address>[0-9a-fx]+) (?:parent (?P<parent>0x[0-9a-f]+) )?(?:prev (?P<prev>0x[0-9a-f]+) )?<(?P<position>.*)>(?P<position2> .+:\d+)?(?P<used> used)?(?P<referenced> referenced)?(?P<name> \w+)? '(?P<type>.+?)'(?P<type2>:'.*?')?(?P<extern> extern)?(?P<static> static)?(?P<cinit> cinit)?(?P<register> register)?[\s]*$
// AST Error : 0x28f8490 <col:3, col:43> col:19 used a 'char *' register cinit

F: struct declaration

struct s* p = NULL; // tag naming an unknown struct declares it
struct s { int a; }; // definition for the struct pointed to by p
void g(void)
{
    struct s; // forward declaration of a new, local struct s
              // this hides global struct s until the end of this block
    struct s *p;  // pointer to local struct s
                  // without the forward declaration above,
                  // this would point at the file-scope s
    struct s { char* p; }; // definitions of the local struct s
}

see http://en.cppreference.com/w/c/language/struct

F: malloc

test

struct MyNums {
    char name[100];
    int size;
    int numbers[];
};
void test_array_struct()
{
    int n = 10, k;
    struct MyNums *pnt;
    pnt = malloc(sizeof(struct MyNums) + n * sizeof(int));
    strcpy(pnt->name, "Натуральные числа");
    pnt->size = n;
    for (k = 0; k < pnt->size; k++)
        pnt->numbers[k] = k + 1;
	is_eq(pnt->numbers[2],3);
	is_eq(pnt->numbers[5],6);
}

Version

Add version generate example in README.

Array to slice problem

Go code:

type behavior struct {
...
	innodefilename   [2048]byte
...
}

// problem here
noarch.Strncpy(b[0].innodefilename, argv[i], int(uint32(2048-1)))

AST:

|-CallExpr 0x2216900 <line:3492:7, col:51> 'char *'
| |-ImplicitCastExpr 0x22168e8 <col:7> 'char *(*)(char *, const char *, unsigned long)' <FunctionToPointerD
ecay>
| | `-DeclRefExpr 0x22166d8 <col:7> 'char *(char *, const char *, unsigned long)' Function 0x2162110 'strncpy' 'char *(char *, const char *, unsigned long)'
| |-ImplicitCastExpr 0x2216940 <col:15, col:18> 'char *' <ArrayToPointerDecay>
| | `-MemberExpr 0x2216740 <col:15, col:18> 'char [2048]' lvalue ->innodefilename 0x21c65d8
| |   `-ImplicitCastExpr 0x2216728 <col:15> 'struct behavior *' <LValueToRValue>
| |     `-DeclRefExpr 0x2216700 <col:15> 'struct behavior *' lvalue ParmVar 0x220aae0 'b' 'struct behavior *'
| |- ...

Type of b[0].innodefilename is array [2048]byte, but in function need a slice []byte

Paren

Remove paren
For example: 'var I int = ((((6))))'

Optimization for program.(*Program).GetComments

Showing top 40 nodes out of 120
      flat  flat%   sum%        cum   cum%
    11.63s 33.55% 33.55%     11.63s 33.55%  memeqbody
    10.43s 30.09% 63.65%     24.55s 70.83%  github.com/Konstantin8105/c4go/program.(*Program).GetComments
     2.65s  7.65% 71.29%      2.65s  7.65%  runtime.memequal
     0.67s  1.93% 73.23%      1.22s  3.52%  regexp.(*machine).tryBacktrack

See #207

Error in sputc Mac OSX.

Compiler message: syntax error: unexpected =, expecting )

in function sputc
/ __sputc - transpiled function from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/stdio.h:264

The syntax error is in this line:
}())[0] = uint8(_c)))

The whole function:
func __sputc(_c int, _p *noarch.File) (c4goDefaultReturn int) {
if func() int {
tempVar := &_p[0]._w
*tempVar --
defer func() {
}()
return *tempVar
}() >= 0 || _p[0]._w >= _p[0]._lbfsize && int(byte(_c)) != int('\n') {
return int(((func() []uint8 {
tempVar := &_p[0]._p
defer func() {
*tempVar ++
}()
return *tempVar
}())[0] = uint8(_c)))
// Warning (*ast.MemberExpr): /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/stdio.h:265 :cannot determine type for LHS 'FILE *', will use 'void *' for all fields. Is lvalue = true. n.Name = _w
// Warning (*ast.MemberExpr): /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/stdio.h:265 :cannot determine type for LHS 'FILE *', will use 'void *' for all fields. Is lvalue = true. n.Name = _lbfsize
// Warning (*ast.MemberExpr): /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/stdio.h:265 :cannot determine type for LHS 'FILE *', will use 'void *' for all fields. Is lvalue = true. n.Name = _w
// Warning (*ast.MemberExpr): /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/stdio.h:265 :cannot determine type for LHS 'FILE *', will use 'void *' for all fields. Is lvalue = true. n.Name = _lbfsize
// Warning (*ast.MemberExpr): /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/stdio.h:266 :cannot determine type for LHS 'FILE *', will use 'void *' for all fields. Is lvalue = true. n.Name = _p
} else {
return (__swbuf(_c, _p))
}
return
}

CPP: experimantal

Create ast for cpp code:

clang++ -E -C cpp2.cpp  > y.cpp
clang++ -Xclang -ast-dump -fsyntax-only y.cpp

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.