-
Notifications
You must be signed in to change notification settings - Fork 159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unused types, constants, vars #232
Comments
I have thought about this issue. There is not only many built-in types but also many functions that ship with the standard headers that add a lot of bloat to the output. I would prefer to build in the tool (rather than using a third party command) because it's very possible that the logic and exclusions will become more complex over time. I'm happy to strip all of this out by default and use a CLI argument like |
Example of terminal command for keeping unused types, ... - |
Example package main
import "unsafe"
import "github.com/elliotchance/c2go/noarch"
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))[:])
noarch.Printf([]byte("The number is: %d\n\x00"), 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
} May I change the |
Yes, please update the README. |
We cannot use tool package main
import "fmt"
type number int
const (
zero number = 0
one = 1
two = 2
three = 3
)
func main() {
for i := int(zero); i < int(three); i++ {
fmt.printf("%d.\t%#v\n", i, number(i))
}
} Tools show:
But this is wrong result. |
Main point of that issue is 'Clean result Go code'.
Experiment: #include<stdio.h>
int main(){
int a = 42;
printf("We have number : %d", 42);
return 0;
} Let's change little bit: #include<stdio_fake.h> // We change name of system header
int main(){
int a = 42;
printf("We have number : %d", 42);
return 0;
} Create a file void printf(const char * format, ...){
} Run a # 1 "file2.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 317 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "file2.c" 2
# 1 "./stdio_fake.h" 1
void printf(const char * format, ...){
}
# 2 "file2.c" 2
int main(){
int a = 42;
printf("We have number : %d", 42);
return 0;
} One of plus of that solution is system header files are platform indepentend. Another solution: cmd := exec.Command("clang", "-E", args.inputFile) also we know - the one simple think about result: # 28 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4 <------ IMPORTANT
typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
# 36 "/usr/include/stdio.h" 2 3 4 <------ IMPORTANT
struct _IO_FILE; We know - What file give to us any function,type,struct ,... In according to last result example - it is If we will use any of that solution or some preliminary like that, then may be we also can solve issue #237 . or we can take a time to think about another solution. |
I will prepare the prototype. |
Example of package main
import "os"
import "io/ioutil"
import "testing"
import "unsafe"
import "github.com/elliotchance/c2go/noarch"
type __int128_t int64
type __uint128_t uint64
type __builtin_ms_va_list []byte
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))[:])
noarch.Printf([]byte("The number is: %d\n\x00"), 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 TestApp(t *testing.T) {
os.Chdir("../../..")
ioutil.WriteFile("build/stdin", []byte{'7'}, 0777)
stdin, _ := os.Open("build/stdin")
noarch.Stdin = noarch.NewFile(stdin)
main()
}
func __init() {
} |
Algoritm of preprocessor:
In HEAD we see 2 important elements:
|
Problem
|
May be another solution: Need approve for action |
@elliotchance I need your approve or comment about last message |
You will not be able to split up user and system code. In simple examples this makes sense but in more complicated examples the same header file can be different when used in different ways. The safest course of action is to deal with the duplicate logic after the transpile is complete, for example, let say you run: c2go transpile foo.c bar.c Will produce This solution would take in one or more Go files and produce new files, with an extra common file: some_command foo.go bar.go Produces a It's not going to be possible to handle this duplicate code in the preprocessing stage because there are many decisions made during and after the transpiling that affect how the code is generated. It also won't be possible to split files by their include path/name. You should only rely on the input files to product output Go files with the same name. Fundamentally this is not a difficult task (to extract the duplicates to a common file). There are already tools to parse and traverse the Go code easily (you only need to pay attention to the global types and names of the top level functions) and reliably extract parts of the AST to be written to another file. I am trying to thing of a scenario where the macros in seperate files will resolve to different Go code. I can't think of any immediate examples but I have a feeling there will be some, and these will be tricky to deal with. That is a challenge for another day. As of v0.17.0 (thanks to your awesome code) we can support multiple input files that get preprocessed and transpiled into a single output file. This is a great first step. This solution would work the same way except each input file would generate its own output file (much like input C files for |
One more specific of preprocessor design - can easy solve dublicates of system include files for example: #include<stdio.h>
#include<stdio.h> // <--- Dublicate
#include<stdio.h> // <--- Dublicate
int main(){
prinf("All is OK");
return 0;
} One more: after command
In according to that - we can easy separate. For that case |
This would only work in cases where the headers are guaranteed to be exactly the same, which you can't guarantee or check for. System header files and regular header files need to be treated the same way, there is nothing special about a header file other than its name is common across some platforms. Here is a concrete example of why the will not work:
void ERROR_FUNC() {
printf("ERROR!");
}
#define ERROR_FUNC error
#include "errors.h"
#undef ERROR_FUNC
#define ERROR_FUNC error2
#include "errors.h"
// We now have two different functions from a header file that is "dynamic". This may seem like a silly example but it shows how the same header can be included to resolve to different code. You cannot deal with the duplicates at the preprocess stage, it's impossible. No compilers work like this for these reasons. You must transpile each input C file independently, then deal with the duplicates as a Go AST problem, not as a C/preprocessor problem. |
Now, idea - cleaning on postprocessor step.
@elliotchance , Please comment. |
@Konstantin8105 yes that sounds good. |
Now, we can identify location of struct, variable, ... from C source. |
Problem
After transpile that code:
We see many unused types, ... for example:
Solution
https://github.com/alecthomas/gometalinter
./unused ./demo/hello.go
I try do it by hard and result look:
The text was updated successfully, but these errors were encountered: