⚖️ A tool for transpiling C to Go.

Build Status GitHub version Go Report Card codecov GitHub license Join the chat at https://gitter.im/c2goproject Twitter GoDoc

A tool for converting C to Go.

The goals of this project are:

  1. To create a generic tool that can convert C to Go.
  2. To be cross platform (linux and mac) and work against as many clang versions as possible (the clang AST API is not stable).
  3. To be a repeatable and predictable tool (rather than doing most of the work and you have to clean up the output to get it working.)
  4. To deliver quick and small version increments.
  5. The ultimate milestone is to be able to compile the SQLite3 source code and have it working without modification. This will be the 1.0.0 release.

Installation

c2go requires Go 1.9 or newer.

go get -u github.com/elliotchance/c2go

Usage

c2go transpile myfile.c

The c2go program processes a single C file and outputs the translated code in Go. Let's use an included example, prime.c:

#include <stdio.h>
 
int main()
{
   int n, c;
 
   printf("Enter a number\n");
   scanf("%d", &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;
}
c2go transpile prime.c
go run prime.go
Enter a number
23
Prime number.

prime.go looks like:

package main

import "unsafe"

import "github.com/elliotchance/c2go/noarch"

// ... lots of system types in Go removed for brevity.

var stdin *noarch.File
var stdout *noarch.File
var stderr *noarch.File

func main() {
	__init()
	var n int
	var c int
	noarch.Printf([]byte("Enter a number\n\x00"))
	noarch.Scanf([]byte("%d\x00"), (*[1]int)(unsafe.Pointer(&n))[:])
	if n == 2 {
		noarch.Printf([]byte("Prime number.\n\x00"))
	} else {
		for c = 2; c <= n-1; func() int {
			c += 1
			return c
		}() {
			if n%c == 0 {
				break
			}
		}
		if c != n {
			noarch.Printf([]byte("Not prime.\n\x00"))
		} else {
			noarch.Printf([]byte("Prime number.\n\x00"))
		}
	}
	return
}

func __init() {
	stdin = noarch.Stdin
	stdout = noarch.Stdout
	stderr = noarch.Stderr
}

How It Works

This is the process:

  1. The C code is preprocessed with clang. This generates a larger file (pp.c), but removes all the platform-specific directives and macros.

  2. pp.c is parsed with the clang AST and dumps it in a colourful text format that looks like this. Apart from just parsing the C and dumping an AST, the AST contains all of the resolved information that a compiler would need (such as data types). This means that the code must compile successfully under clang for the AST to also be usable.

  3. Since we have all the types in the AST it's just a matter of traversing the tree in a semi-intelligent way and producing Go. Easy, right!?

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. c2go converts the C file to Go.
  3. The Go is built to produce another binary.
  4. Both binaries are executed and the output is compared. All C files will contain some output so the results can be verified.

Contributing

Contributing is done with pull requests. There is no help that is too small! :)

If you're looking for where to start I can suggest finding a simple C program (like the other examples) that does not successfully translate into Go.

Or, if you don't want to do that you can submit it as an issue so that it can be picked up by someone else.

Owner
Elliot Chance
I'm a data nerd and TDD enthusiast originally from Sydney, Australia. I love exploring new technologies and working on modern ways to solve age old problems.
Elliot Chance
Comments
  • Compile knightstour.c

    Compile knightstour.c

    This was an issue raise originally by @carstenhag with #27.

    The original ticket was fixed but the example program was very good. This issue will outline what we need to do to get knightstour.c working.

    • [x] stdio.h (#61)
    • [x] stdlib.h
    • [x] stdbool.h (#65)
    • [x] string.h
    • [x] math.h (#9)
    • [x] Better struct handling for coord and extCoord (#49)
    • [x] qsort()
    • [x] Memory allocationcalloc() and free().
    • [x] sizeof() (#102)
  • panic: could not match regexp

    panic: could not match regexp

    Test 1 Precondition: Windows 7, SP1, 32 bit Visual Studio 2015 community edition LLVM-3.9.1-win32 Windows 10 SDK (10.0.15063.468) go version go1.8.1 windows/386

    Test 2 Precondition: mac 1.9.5 go version go1.8.1 darwin/amd64

    \go\c2go>c2go transpile examples\fib.c panic: could not match regexp '(?P

    [0-9a-fx]+) <(?P.)> "(?P.?)"(?P ".*?")?' with string 'DeprecatedAttr 0x3b732f0 line:1107:12 Inherited "This function or variable may be unsafe. Consider using _snwprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details." ""'

    goroutine 1 [running]: github.com/elliotchance/c2go/ast.groupsFromRegex(0x57acb2, 0x3b, 0x120594a8, 0xd6, 0x56f0c4) E:/dev/gocode/src/github.com/elliotchance/c2go/ast/ast.go:407 +0x2a7 github.com/elliotchance/c2go/ast.parseDeprecatedAttr(0x120594a8, 0xd6, 0x571939) E:/dev/gocode/src/github.com/elliotchance/c2go/ast/deprecated_attr.go:15 +0x3f github.com/elliotchance/c2go/ast.Parse(0x120594a8, 0xd6, 0xda, 0x11c189c0) E:/dev/gocode/src/github.com/elliotchance/c2go/ast/ast.go:276 +0x1dbb main.convertLinesToNodes(0x11c7a000, 0x18a5, 0x18a5, 0x11c7a000, 0x18a5, 0x18a5) E:/dev/gocode/src/github.com/elliotchance/c2go/main.go:66 +0x165 main.Start(0x0, 0x11c4d8c0, 0xe, 0x0, 0x0, 0x56f599, 0x4, 0x11c48118, 0x8) E:/dev/gocode/src/github.com/elliotchance/c2go/main.go:191 +0x628 main.main() E:/dev/gocode/src/github.com/elliotchance/c2go/main.go:305 +0x2c2

  • Very useful

    Very useful

    I reckon this would be useful for machine learning c packages. They mostly have no other dependencies like file systems or databases but are designed to be called and return results.

    For example OCR in tesseract etc.

    I am trying to build an OCR system and so this repo might be a good approach for me.

    Could you comment on the soundness if my approach ?

  • C enum type not supported ?

    C enum type not supported ?

    The following source code runs correctly in C but produces error after transpiled to Go:

    #include <stdlib.h>
    
    #define Lgnom 255
    
    typedef char t_nom[Lgnom];
    
    enum etat {LEGER,EQUIL,LOURD};
    
    typedef struct elem {
    	       t_nom nom;
    	       struct elem *gauche;
    	       struct elem *droite;
    	       enum etat avl;
    		} t_elem;
    
    t_elem *racine;
    t_nom mot;
    
    int main()
    {
    return 0;
    }
    

    $ go run enum.go command-line-arguments ./enum.go:200: undefined: etat

  • Unions. Fixes #84

    Unions. Fixes #84

    Adding support for union types.

    It works with present tests (samples files in tests directory).

    However, some cases must be checked like anonymous types in variable declarations and union initialization subscripts.


    This change is Reviewable

  • go test & run-tests.sh failing - expected 'package', found 'EOF'

    go test & run-tests.sh failing - expected 'package', found 'EOF'

    I clone the repo, ran go get and then go test, but unfortunately it fails with a panic:

    shell@shell-virtual-machine ~/g/s/g/e/c2go> go test
    --- FAIL: TestIntegrationScripts (0.10s)
    panic: '' [recovered]
    	panic: ''
    
    goroutine 10 [running]:
    testing.tRunner.func1(0xc42006f380)
    	/usr/local/go/src/testing/testing.go:622 +0x29d
    panic(0x547960, 0xc420383a00)
    	/usr/local/go/src/runtime/panic.go:489 +0x2cf
    github.com/elliotchance/c2go.resolveType(0x0, 0x0, 0x57e87e, 0x8)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/resolve.go:167 +0xc4f
    github.com/elliotchance/c2go.(*TypedefDecl).RenderLine(0xc420372900, 0xc4201c88c0, 0x0, 0x0, 0x0, 0x0, 0x0)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/typedef_decl.go:65 +0x162
    github.com/elliotchance/c2go.Render(0xc4201c88c0, 0x551f60, 0xc420372900, 0x0, 0x0, 0x0, 0x0, 0x0)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/common.go:48 +0x102
    github.com/elliotchance/c2go.(*TranslationUnitDecl).RenderLine(0xc42028e2a0, 0xc4201c88c0, 0x0, 0x0, 0x0, 0x0, 0x0)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/translation_unit_decl.go:21 +0xa5
    github.com/elliotchance/c2go.Render(0xc4201c88c0, 0x551f00, 0xc42028e2a0, 0x0, 0x0, 0x0, 0x0, 0x0)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/common.go:48 +0x102
    github.com/elliotchance/c2go.Start(0xc4203eaf78, 0x2, 0x2, 0x21, 0x40)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/main.go:156 +0x38b
    github.com/elliotchance/c2go.TestIntegrationScripts(0xc42006f380)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/main_test.go:20 +0xbd
    testing.tRunner(0xc42006f380, 0x58b3d0)
    	/usr/local/go/src/testing/testing.go:657 +0x96
    created by testing.(*T).Run
    	/usr/local/go/src/testing/testing.go:697 +0x2ca
    exit status 2
    FAIL	github.com/elliotchance/c2go	0.111s
    

    run-tests.sh also seems to produce an empty panic:

    shell@shell-virtual-machine ~/g/s/g/e/c2go> ./run-tests.sh 
    CLANG_BIN=clang
    CLANG_VERSION=clang version 3.8.1-12ubuntu1 (tags/RELEASE_381/final)
    Target: x86_64-pc-linux-gnu
    Thread model: posix
    InstalledDir: /usr/bin
    
    tests/misc/user-input.c
    panic: ''
    
    goroutine 1 [running]:
    main.resolveType(0x0, 0x0, 0x51a90a, 0x8)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/resolve.go:167 +0xc4f
    main.(*TypedefDecl).RenderLine(0xc4200d4d80, 0xc420176000, 0x0, 0x0, 0x0, 0x0, 0x0)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/typedef_decl.go:65 +0x162
    main.Render(0xc420176000, 0x4f8ca0, 0xc4200d4d80, 0x0, 0x0, 0x0, 0x0, 0x0)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/common.go:48 +0x102
    main.(*TranslationUnitDecl).RenderLine(0xc4200a84b0, 0xc420176000, 0x0, 0x0, 0x0, 0x0, 0x0)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/translation_unit_decl.go:21 +0xa5
    main.Render(0xc420176000, 0x4f8c40, 0xc4200a84b0, 0x0, 0x0, 0x0, 0x0, 0x0)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/common.go:48 +0x102
    main.Start(0xc42000a440, 0x2, 0x2, 0x0, 0x0)
    	/home/shell/gocode/src/github.com/elliotchance/c2go/main.go:156 +0x38b
    main.main()
    	/home/shell/gocode/src/github.com/elliotchance/c2go/main.go:171 +0x49
    can't load package: package github.com/elliotchance/c2go/build: 
    main.go:1:1: expected 'package', found 'EOF'
    === out.go
    cat: build/main.go: No such file or directory
    
    
  • Add snapshot testing for command help output

    Add snapshot testing for command help output

    Saw #190 and it seems a great use case for a testing tool I was writing which automagically handles the creating and updating of snapshots from test cases: https://github.com/bradleyjkemp/cupaloy

    I've put together this PR mainly as a test of my api but it might be useful to you too.

    PR involved some minor changes to allow redirecting stderr and being able to run the command without os.Exit(1) failing the test which you might have some opinions on a better way to do this.

    Thanks!


    This change is Reviewable

  • Refactored ast nodes into separate package

    Refactored ast nodes into separate package

    All the ast nodes seemed like a good candidate for separating out into a separate package so the root folder is cleaner.

    I also merged Render() and RenderLine() into one Render() function since having both seemed redundant, this should also cover #38. This means we can get rid of all the slow reflection since all nodes now implement the ast.Node interface.

    TODO

    • [x] Remove reflection code from buildTree
    • [ ] Fix issue with the following variable declarations not working after the first test: _LIB_VERSION, _IO_2_1_stdin_, _IO_2_1_stdout_, _IO_2_1_stderr_, stdin, stdout, stderr
    • [x] Fix incorrect coverage

    If this is not how you want the project structured feel free to discard this PR.


    This change is Reviewable

  • Allow passing include directory to clang

    Allow passing include directory to clang

    I was trying out c2go on a random piece of code, and could not get past the preprocessing stage. This change adds a new flag -I to c2go, and passes it to clang invocation.


    This allows code like this:

    c2go transpile -I path/to/include foo.c

    so #include statements work


    This change is Reviewable

  • Maintain comments in Go

    Maintain comments in Go

    All of the comments are currently discarded when generating the Go output.

    This might be useful: https://stackoverflow.com/questions/25275212/how-to-extract-comments-and-match-to-declaration-with-recursiveastvisitor-in-lib

  • extern definitions confuse c2go

    extern definitions confuse c2go

    Hi, this simple example reproduce issue, t.c:

    #include<stdio.h>
    
    extern int array[];
    int array[4] = { 1, 2, 3, 4 };
    
    int main() {
    	printf("%d",array[1]) ;
         return 0;
    }
    

    may be extern declarations can be ignored ?

  • panic: unknown node type: 'BuiltinAttr 0x1d448112da0 <<invalid sloc>> Implicit 836'

    panic: unknown node type: 'BuiltinAttr 0x1d448112da0 <> Implicit 836'

    panic: unknown node type: 'BuiltinAttr 0x1d448112da0 <> Implicit 836'

    goroutine 52 [running]: github.com/elliotchance/c2go/ast.Parse({0xc000303d90, 0x37}) C:/Users/tariq/go/src/github.com/elliotchance/c2go/ast/ast.go:294 +0x2205 main.convertLinesToNodes({0xc000169420, 0x18d, 0x66?}) C:/Users/tariq/go/src/github.com/elliotchance/c2go/main.go:89 +0x115 main.convertLinesToNodesParallel.func1.2({0xc000169420?, 0x0?, 0x0?}, 0x0?) C:/Users/tariq/go/src/github.com/elliotchance/c2go/main.go:121 +0x39 created by main.convertLinesToNodesParallel.func1 C:/Users/tariq/go/src/github.com/elliotchance/c2go/main.go:119 +0x2b3

    I had this error message, please check on it.

  • FreeBSD implementation

    FreeBSD implementation

    It would be convenient if you ported to FreeBSD. Actually it's impossible to use it on FreeBSD and lot's of features need C library so, if you ported to FreeBSD you help lot's of developer

  • panic: unknown node type: 'BuiltinAttr 0x10db7b0 <<invalid sloc>> Inherited Implicit 749'

    panic: unknown node type: 'BuiltinAttr 0x10db7b0 <> Inherited Implicit 749'

    Hey, I have this problem:

    `panic: unknown node type: 'BuiltinAttr 0x10db7b0 <> Inherited Implicit 749'

    goroutine 13 [running]: github.com/elliotchance/c2go/ast.Parse({0xc0002c6549, 0x3d}) /home/smayer/go/pkg/mod/github.com/elliotchance/[email protected]/ast/ast.go:294 +0x22d4 main.convertLinesToNodes({0xc0002ce5f0, 0x1c, 0x0?}) /home/smayer/go/pkg/mod/github.com/elliotchance/[email protected]/main.go:89 +0x115 main.convertLinesToNodesParallel.func1.1({0xc0002ce5f0?, 0x0?, 0x0?}, 0x0?) /home/smayer/go/pkg/mod/github.com/elliotchance/[email protected]/main.go:113 +0x39 created by main.convertLinesToNodesParallel.func1 /home/smayer/go/pkg/mod/github.com/elliotchance/[email protected]/main.go:111 +0x1a5`

    Can you help me with that ? I just can't get any further here.

    Best regards

  • panic: runtime error: invalid memory address or nil pointer dereference

    panic: runtime error: invalid memory address or nil pointer dereference

    c2go transpile -clang-flag -M -clang-flag -MT -clang-flag compel/plugins/std/infect.d -clang-flag -MT -clang-flag compel/plugins/std/infect.o -clang-flag -O2 -clang-flag -g -clang-flag -Wall -clang-flag -Wformat-security -clang-flag -Wdeclaration-after-statement -clang-flag -Wstrict-prototypes -clang-flag -Werror -clang-flag -DCONFIG_X86_64 -clang-flag -D_FILE_OFFSET_BITS=64 -clang-flag -D_GNU_SOURCE -clang-flag -DCONFIG_COMPAT -clang-flag -iquote -clang-flag include/ -clang-flag -DCONFIG_COMPAT -clang-flag -U_FORTIFY_SOURCE -clang-flag -D_FORTIFY_SOURCE=0 -clang-flag -Wp,-U_FORTIFY_SOURCE -clang-flag -Wp,-D_FORTIFY_SOURCE=0 -clang-flag -DCR_NOGLIBC -clang-flag -I -clang-flag compel/include/uapi -clang-flag -iquote -clang-flag compel/include -clang-flag -fpie -clang-flag -fno-stack-protector -clang-flag -iquote -clang-flag compel/plugins/include -clang-flag -iquote -clang-flag compel/arch/x86/plugins/include compel/plugins/std/infect.c
    panic: runtime error: invalid memory address or nil pointer dereference
    [signal SIGSEGV: segmentation violation code=0x1 addr=0x30 pc=0x58175c]
    
    goroutine 1 [running]:
    github.com/elliotchance/c2go/preprocessor.analyzeFiles({0xc0000108e0, 0x7fc02639bfff, 0x10}, {0xc000039000, 0x203000, 0x203000}, 0x0)
    	/home/avagin/go/pkg/mod/github.com/elliotchance/[email protected]/preprocessor/preprocessor.go:203 +0x53c
    github.com/elliotchance/c2go/preprocessor.Analyze({0xc0000108e0, 0x1, 0x2}, {0xc000039000, 0x22, 0x40}, 0x38)
    	/home/avagin/go/pkg/mod/github.com/elliotchance/[email protected]/preprocessor/preprocessor.go:89 +0x73
    main.Start({0x0, 0x0, {0xc0000108e0, 0x1, 0x2}, {0xc000039000, 0x22, 0x40}, {0x0, 0x0}, ...})
    	/home/avagin/go/pkg/mod/github.com/elliotchance/[email protected]/main.go:193 +0x150
    main.runCommand()
    	/home/avagin/go/pkg/mod/github.com/elliotchance/[email protected]/main.go:429 +0x5b8
    main.main()
    	/home/avagin/go/pkg/mod/github.com/elliotchance/[email protected]/main.go:352 +0x19
    
  • docker container for c2go

    docker container for c2go

    I was wondering if someone has worked on a docker container for c2go. I see in a few issues that it can be sensitive to changes in clang. Is there any way to have a docker container with the exact version of clang that is known to work correctly on the test files?

Related tags
GoWrap is a command line tool for generating decorators for Go interfaces

GoWrap GoWrap is a command line tool that generates decorators for Go interface types using simple templates. With GoWrap you can easily add metrics,

Dec 30, 2022
Perforator is a tool for recording performance metrics over subregions of a program using the Linux "perf" interface.

Perforator Perforator is a tool for recording performance metrics over subregions of a program (e.g., functions) using the Linux "perf" interface.

Dec 15, 2022
a tool for creating exploited media files for discord

Discord-Exploits A program for creating exploited media files for discord written in Go. Usage discord-exploits is a command line utility, meaning you

Dec 29, 2021
A full-featured license tool to check and fix license headers and resolve dependencies' licenses.
A full-featured license tool to check and fix license headers and resolve dependencies' licenses.

SkyWalking Eyes A full-featured license tool to check and fix license headers and resolve dependencies' licenses. Usage You can use License-Eye in Git

Dec 26, 2022
sigurls is a reconnaissance tool, it fetches URLs from AlienVault's OTX, Common Crawl, URLScan, Github and the Wayback Machine.

sigurls is a reconnaissance tool, it fetches URLs from AlienVault's OTX, Common Crawl, URLScan, Github and the Wayback Machine. DiSCLAIMER: fe

May 22, 2021
A tool and library for using structural regular expressions.

Structural Regular Expressions sregx is a package and tool for using structural regular expressions as described by Rob Pike (link).

Dec 7, 2022
TUI grep tool respect for IntelliJ
TUI grep tool respect for IntelliJ

ilse TUI grep tool respect for IntelliJ Requirements ripgrep for fast grep bat for beautiful preview Features support HeadMatch(FirstMatch), WordMatch

Sep 27, 2022
A tool to check problems about meta files of Unity
A tool to check problems about meta files of Unity

A tool to check problems about meta files of Unity on Git repositories, and also the tool can do limited autofix for meta files of auto-generated files.

Dec 22, 2022
A tool to find redirection chains in multiple URLs
A tool to find redirection chains in multiple URLs

UnChain A tool to find redirection chains in multiple URLs Introduction UnChain automates process of finding and following `30X` redirects by extracti

Dec 12, 2022
Go tool to modify struct field tags
Go tool to modify struct field tags

Go tool to modify/update field tags in structs. gomodifytags makes it easy to update, add or delete the tags in a struct field. You can easily add new tags, update existing tags (such as appending a new key, i.e: db, xml, etc..) or remove existing tags

Jan 1, 2023
🤖🤝A tool to test and analyze storage and retrieval deal capability on the Filecoin network.

Dealbot A tool to test and analyze storage and retrieval deal capability on the Filecoin network. Getting Started Clone the repo and build: git clone

Sep 10, 2022
A simple tool to auto remove unused imports in rust

rust_strip A simple tool to remove unused imports in RUST. Call Cargo build/test Process the warning logs of unused imports Then replace the involved

Oct 15, 2022
A tool to filter URLs by parameter count or size

GoFilter A tool to filter URLs by parameter count or size. This tool requires unique sorted URL list. For example: cat hosts.txt | sort -u > sorted &&

Dec 18, 2022
A simple business indicator tool that uses a sliding window to detect whether the indicator exceeds the threshold

melon A simple business indicator tool that uses a sliding window to detect whether the indicator exceeds the threshold Usage //create the metric //th

Jul 11, 2021
A Golang tool to whitelist ASN's based on organization name

A Golang tool to whitelist ASN's based on organization name. This works by providing a list of ASN org names. This tool uses goPacket to monitor incoming traffic, capturing the IP's and checking the IP to see if it is a part of a whitelisted ASN. If it is not, it blocks that connection and future connections using iptables.

Jul 23, 2022
Chaos Engineering tool for introducing failure into syscalls

Syscall monkey Chaos Engineering tool for tampering with syscalls.

Jun 11, 2022
dontgo403 is a tool to bypass 40X errors.
dontgo403 is a tool to bypass 40X errors.

dontgo403 is a tool to bypass 40X errors. Installation git clone https://github.com/devploit/dontgo403; cd dontgo403; go get; go build Options ./dontg

Dec 28, 2022
tool for working with numbers and units

tool for working with numbers and units

Nov 26, 2022
CSPFinder is a tool to compare ROI of selling Cash Secure Put options between different tickers for different expiry dates.

CSPFinder is a tool to compare ROI of selling Cash Secure Put options between different tickers for different expiry dates. It is intended to help open new cash secured put positions.

Dec 21, 2021