Skip to content

Commit

Permalink
Added support for some time.h functions and structures. Fixes #592 (#593
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Konstantin8105 authored and elliotchance committed Feb 9, 2018
1 parent e8a618e commit 0519754
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 20 deletions.
89 changes: 88 additions & 1 deletion noarch/time.go
@@ -1,8 +1,16 @@
package noarch

import "time"
import (
"fmt"
"time"
)

// TimeT is the representation of "time_t".
// For historical reasons, it is generally implemented as an integral value
// representing the number of seconds elapsed
// since 00:00 hours, Jan 1, 1970 UTC (i.e., a unix timestamp).
// Although libraries may implement this type using alternative time
// representations.
type TimeT int32

// NullToTimeT converts a NULL to an array of TimeT.
Expand Down Expand Up @@ -40,3 +48,82 @@ func Ctime(tloc []TimeT) []byte {
func TimeTToFloat64(t TimeT) float64 {
return float64(t)
}

// Tm - base struct in "time.h"
// Structure containing a calendar date and time broken down into its
// components
type Tm struct {
Tm_sec int
Tm_min int
Tm_hour int
Tm_mday int
Tm_mon int
Tm_year int
Tm_wday int
Tm_yday int
Tm_isdst int
// tm_gmtoff int32
// tm_zone []byte
}

// Localtime - Convert time_t to tm as local time
// Uses the value pointed by timer to fill a tm structure with the values that
// represent the corresponding time, expressed for the local timezone.
func LocalTime(timer []TimeT) (tm []Tm) {
t := time.Unix(int64(timer[0]), 0)
tm = make([]Tm, 1)
tm[0].Tm_sec = t.Second()
tm[0].Tm_min = t.Minute()
tm[0].Tm_hour = t.Hour()
tm[0].Tm_mday = t.Day()
tm[0].Tm_mon = int(t.Month()) - 1
tm[0].Tm_year = t.Year() - 1900
tm[0].Tm_wday = int(t.Weekday())
tm[0].Tm_yday = t.YearDay() - 1
return
}

// Gmtime - Convert time_t to tm as UTC time
func Gmtime(timer []TimeT) (tm []Tm) {
t := time.Unix(int64(timer[0]), 0)
t = t.UTC()
tm = make([]Tm, 1)
tm[0].Tm_sec = t.Second()
tm[0].Tm_min = t.Minute()
tm[0].Tm_hour = t.Hour()
tm[0].Tm_mday = t.Day()
tm[0].Tm_mon = int(t.Month()) - 1
tm[0].Tm_year = t.Year() - 1900
tm[0].Tm_wday = int(t.Weekday())
tm[0].Tm_yday = t.YearDay() - 1
return
}

// Mktime - Convert tm structure to time_t
// Returns the value of type time_t that represents the local time described
// by the tm structure pointed by timeptr (which may be modified).
func Mktime(tm []Tm) TimeT {
t := time.Date(tm[0].Tm_year+1900, time.Month(tm[0].Tm_mon)+1, tm[0].Tm_mday,
tm[0].Tm_hour, tm[0].Tm_min, tm[0].Tm_sec, 0, time.Now().Location())

tm[0].Tm_wday = int(t.Weekday())

return TimeT(int32(t.Unix()))
}

// constants for asctime
var wday_name = [...]string{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}
var mon_name = [...]string{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
}

// Asctime - Convert tm structure to string
func Asctime(tm []Tm) []byte {
return []byte(fmt.Sprintf("%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
wday_name[tm[0].Tm_wday],
mon_name[tm[0].Tm_mon],
tm[0].Tm_mday, tm[0].Tm_hour,
tm[0].Tm_min, tm[0].Tm_sec,
1900+tm[0].Tm_year))
}
4 changes: 4 additions & 0 deletions program/function_definition.go
Expand Up @@ -234,6 +234,10 @@ var builtInFunctionDefinitions = []string{
// time.h
"time_t time(time_t *) -> noarch.Time",
"char* ctime(const time_t *) -> noarch.Ctime",
"struct tm * localtime(const time_t *) -> noarch.LocalTime",
"struct tm * gmtime(const time_t *) -> noarch.Gmtime",
"time_t mktime(struct tm *) -> noarch.Mktime",
"char * asctime(struct tm *) -> noarch.Asctime",

// I'm not sure which header file these comes from?
"uint32 __builtin_bswap32(uint32) -> darwin.BSwap32",
Expand Down
62 changes: 57 additions & 5 deletions tests/time.c
Expand Up @@ -37,12 +37,64 @@ void test_ctime()
is_streq(s, "Fri Dec 31 HH:mm:58 1999\n");
}

int main()
void test_gmtime()
{
struct tm * timeinfo;
time_t rawtime = 80000;
timeinfo = gmtime ( &rawtime );
is_eq( timeinfo-> tm_sec , 20 );
is_eq( timeinfo-> tm_min , 13 );
is_eq( timeinfo-> tm_hour , 22 );
is_eq( timeinfo-> tm_mday , 1 );
is_eq( timeinfo-> tm_mon , 0 );
is_eq( timeinfo-> tm_year , 70 );
is_eq( timeinfo-> tm_wday , 4 );
is_eq( timeinfo-> tm_yday , 0 );
is_eq( timeinfo-> tm_isdst , 0 );
}

void test_mktime()
{
struct tm timeinfo;

timeinfo.tm_year = 2000 - 1900;
timeinfo.tm_mon = 5 - 1 ;
timeinfo.tm_mday = 20 ;
timeinfo.tm_sec = 0 ;
timeinfo.tm_min = 0 ;
timeinfo.tm_hour = 0 ;

mktime ( &timeinfo );

is_eq(timeinfo.tm_wday , 6 );
is_eq(timeinfo.tm_year , 100 );
is_eq(timeinfo.tm_mon , 4 );
is_eq(timeinfo.tm_mday , 20 );
}

void test_asctime()
{
plan(5);
time_t rawtime = 80000;
struct tm * timeinfo;
timeinfo = gmtime ( &rawtime );
is_streq(asctime(timeinfo) , "Thu Jan 1 22:13:20 1970\n" );
}

START_TEST(time)
START_TEST(ctime)
int main()
{
plan(19);

done_testing();
// sorting in according to :
// http://www.cplusplus.com/reference/ctime/clock/
START_TEST(asctime );
// TODO : START_TEST(clock );
START_TEST(ctime );
// TODO : START_TEST(difftime );
START_TEST(gmtime );
// TODO : START_TEST(localtime );
START_TEST(mktime );
// TODO : START_TEST(strftime );
START_TEST(time );

done_testing();
}
16 changes: 16 additions & 0 deletions transpiler/variables.go
Expand Up @@ -3,6 +3,7 @@ package transpiler
import (
"errors"
"fmt"
"strings"

"github.com/elliotchance/c2go/ast"
"github.com/elliotchance/c2go/program"
Expand All @@ -28,6 +29,17 @@ var structFieldTranslations = map[string]map[string]string{
"quot": "Quot",
"rem": "Rem",
},
"struct tm": {
"tm_sec": "Tm_sec",
"tm_min": "Tm_min",
"tm_hour": "Tm_hour",
"tm_mday": "Tm_mday",
"tm_mon": "Tm_mon",
"tm_year": "Tm_year",
"tm_wday": "Tm_wday",
"tm_yday": "Tm_yday",
"tm_isdst": "Tm_isdst",
},
}

func transpileDeclRefExpr(n *ast.DeclRefExpr, p *program.Program) (
Expand Down Expand Up @@ -420,6 +432,10 @@ func transpileMemberExpr(n *ast.MemberExpr, p *program.Program) (
}

// Check for member name translation.
lhsType = strings.TrimSpace(lhsType)
if lhsType[len(lhsType)-1] == '*' {
lhsType = lhsType[:len(lhsType)-len(" *")]
}
if member, ok := structFieldTranslations[lhsType]; ok {
if alias, ok := member[rhs]; ok {
rhs = alias
Expand Down
9 changes: 5 additions & 4 deletions types/resolve.go
Expand Up @@ -87,6 +87,9 @@ var simpleResolveTypes = map[string]string{
"lldiv_t": "github.com/elliotchance/c2go/noarch.LldivT",
"time_t": "github.com/elliotchance/c2go/noarch.TimeT",

// time.h
"tm": "github.com/elliotchance/c2go/noarch.Tm",

// Darwin specific
"__darwin_ct_rune_t": "github.com/elliotchance/c2go/darwin.CtRuneT",
"fpos_t": "int",
Expand Down Expand Up @@ -210,12 +213,11 @@ func ResolveType(p *program.Program, s string) (_ string, err error) {
if s[len(s)-1] == '*' {
s = s[start : len(s)-2]

for _, v := range simpleResolveTypes {
if v == s {
for k := range simpleResolveTypes {
if k == s {
return "[]" + p.ImportType(simpleResolveTypes[s]), nil
}
}

return "[]" + strings.TrimSpace(s), nil
}

Expand Down Expand Up @@ -251,7 +253,6 @@ func ResolveType(p *program.Program, s string) (_ string, err error) {
// the name and the "*". If there is an extra space it will be trimmed
// off.
t, err := ResolveType(p, strings.TrimSpace(s[:len(s)-1]))

// Pointers are always converted into slices, except with some specific
// entities that are shared in the Go libraries.
prefix := "*"
Expand Down
21 changes: 11 additions & 10 deletions types/resolve_test.go
Expand Up @@ -33,17 +33,18 @@ var resolveTestCases = []resolveTestCase{
func TestResolve(t *testing.T) {
p := program.NewProgram()

for _, testCase := range resolveTestCases {
goType, err := types.ResolveType(p, testCase.cType)
if err != nil {
t.Error(err)
continue
}
for i, testCase := range resolveTestCases {
t.Run(fmt.Sprintf("Test %d : %s", i, testCase.cType), func(t *testing.T) {
goType, err := types.ResolveType(p, testCase.cType)
if err != nil {
t.Fatal(err)
}

if goType != testCase.goType {
t.Errorf("Expected '%s' -> '%s', got '%s'",
testCase.cType, testCase.goType, goType)
}
if goType != testCase.goType {
t.Errorf("Expected '%s' -> '%s', got '%s'",
testCase.cType, testCase.goType, goType)
}
})
}
}

Expand Down

0 comments on commit 0519754

Please sign in to comment.