├── .gitattributes ├── testsuite ├── results │ ├── nep1enumfields.nim │ ├── bug128.nim │ ├── bug141.nim │ ├── defbug.nim │ ├── block.nim │ ├── bitfield.nim │ ├── opconvertersDelete.nim │ ├── struct_directives.nim │ ├── bug107_108.nim │ ├── commaop.nim │ ├── directives.nim │ ├── opencv_templ_default.nim │ ├── flexarray.nim │ ├── inttemplateparam.nim │ ├── tskipthrow.nim │ ├── bitfieldwithheader.nim │ ├── operatorTemplate.nim │ ├── opconverters.nim │ ├── tenumnamespace.nim │ ├── nestedanonymousstruct.nim │ ├── removeduplicates.nim │ ├── tokenconcat.nim │ ├── structdefine.nim │ ├── skipsection.nim │ ├── tifdef_in_class.nim │ ├── discardables.nim │ ├── constructorcall.nim │ ├── struct_anonym_as_fields.nim │ ├── enum.nim │ ├── vincenth.nim │ ├── vincent.nim │ ├── reordertypes.nim │ ├── struct_anonym.nim │ ├── cppstatic.nim │ ├── opencv_class_ifdef.nim │ ├── pointerdecls.nim │ ├── rcl_allocator_imp_pragma.nim │ ├── tforeachloops.nim │ ├── opencv_templ_param.nim │ ├── systest2.nim │ ├── message_type_support_struct.nim │ ├── cpp11.nim │ ├── i2c_master.nim │ ├── tsyncpoints.nim │ ├── rcl_allocator.nim │ ├── rcl_error_macros.nim │ ├── nested.nim │ ├── smartptrs.nim │ ├── rcl_context.nim │ ├── rcl_arguments.nim │ ├── more11features.nim │ └── matrix.nim ├── tests │ ├── bug128.c │ ├── bug141.cpp │ ├── block.h │ ├── bitfield.h │ ├── bitfieldwithheader.hpp │ ├── opencv_templ_default.hpp │ ├── commaop.hpp │ ├── opconverters.hpp │ ├── bug107_108.cpp │ ├── struct_directives.h │ ├── tenumnamespace.hpp │ ├── defbug.h │ ├── opconvertersDelete.hpp │ ├── inttemplateparam.cpp │ ├── tskipthrow.cpp │ ├── flexarray.h │ ├── nestedanonymousstruct.h │ ├── structdefine.h │ ├── cppstatic.hpp │ ├── directives.h │ ├── constructorcall.cpp │ ├── removeduplicates.hpp │ ├── reordertypes.hpp │ ├── struct_anonym.h │ ├── nep1enumfields.h │ ├── struct_anonym_as_fields.h │ ├── discardables.h │ ├── tokenconcat.h │ ├── operatorTemplate.cpp │ ├── enum.h │ ├── opencv_class_ifdef.hpp │ ├── vincent.c │ ├── vincenth.h │ ├── cpp11.hpp │ ├── skipsection.h │ ├── pointerdecls.h │ ├── systest2.c │ ├── opencv_templ_param.hpp │ ├── i2c_master.h │ ├── nested.hpp │ ├── matrix.cpp │ └── smartptrs.cpp ├── cppkeepbodies │ ├── tifdef_in_class.cpp │ ├── tforeachloops.cpp │ ├── tsyncpoints.cpp │ └── more11features.cpp ├── cextras │ ├── rcl_allocator_imp_pragma.h │ ├── message_type_support_struct.h │ ├── rcl_allocator.h │ ├── rcl_error_macros.h │ ├── rcl_context.h │ └── rcl_arguments.h └── tester.nim ├── c2nim.nims ├── .gitignore ├── c2nim.nimble ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .travis.yml ├── compiler ├── nversion.nim ├── idents.nim ├── nimlexbase.nim ├── llstream.nim ├── wordrecg.nim ├── pathutils.nim └── lineinfos.nim ├── README.md ├── LICENSE.txt ├── mangler.nim └── c2nim.nim /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /testsuite/results/nep1enumfields.nim: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testsuite/tests/bug128.c: -------------------------------------------------------------------------------- 1 | typedef void test; -------------------------------------------------------------------------------- /testsuite/tests/bug141.cpp: -------------------------------------------------------------------------------- 1 | void x() {} 2 | -------------------------------------------------------------------------------- /testsuite/results/bug128.nim: -------------------------------------------------------------------------------- 1 | type 2 | test* = void 3 | -------------------------------------------------------------------------------- /testsuite/results/bug141.nim: -------------------------------------------------------------------------------- 1 | proc x*() = 2 | discard 3 | -------------------------------------------------------------------------------- /testsuite/tests/block.h: -------------------------------------------------------------------------------- 1 | 2 | void qsort_b( int (^ compar)(int, int) ) ; 3 | -------------------------------------------------------------------------------- /testsuite/results/defbug.nim: -------------------------------------------------------------------------------- 1 | proc func1*(i: cint): cint 2 | proc func2*(i: cint) -------------------------------------------------------------------------------- /testsuite/tests/bitfield.h: -------------------------------------------------------------------------------- 1 | struct bits { 2 | int flag:1; 3 | int opts:4; 4 | }; 5 | -------------------------------------------------------------------------------- /testsuite/results/block.nim: -------------------------------------------------------------------------------- 1 | proc qsort_b*(compar: proc (a1: cint; a2: cint): cint {.cblock.}) -------------------------------------------------------------------------------- /c2nim.nims: -------------------------------------------------------------------------------- 1 | --d:nimOldCaseObjects 2 | when (NimMajor, NimMinor) >= (1, 4): 3 | --deepcopy:on 4 | -------------------------------------------------------------------------------- /testsuite/tests/bitfieldwithheader.hpp: -------------------------------------------------------------------------------- 1 | struct bits { 2 | int flag:1; 3 | int opts:4; 4 | }; 5 | -------------------------------------------------------------------------------- /testsuite/tests/opencv_templ_default.hpp: -------------------------------------------------------------------------------- 1 | template struct ParamType {}; -------------------------------------------------------------------------------- /testsuite/tests/commaop.hpp: -------------------------------------------------------------------------------- 1 | #mangle "','" "comma" 2 | 3 | class Foo { 4 | public: 5 | int operator,(int i); 6 | }; -------------------------------------------------------------------------------- /testsuite/tests/opconverters.hpp: -------------------------------------------------------------------------------- 1 | class foo{ 2 | public: 3 | operator int () const {return val;} 4 | int val; 5 | }; -------------------------------------------------------------------------------- /testsuite/tests/bug107_108.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class Foo { 3 | public: 4 | void method(int i); 5 | }; 6 | -------------------------------------------------------------------------------- /testsuite/tests/struct_directives.h: -------------------------------------------------------------------------------- 1 | struct test { 2 | #ifdef A 3 | int a; 4 | #endif 5 | #ifdef B 6 | int b; 7 | #endif 8 | }; 9 | -------------------------------------------------------------------------------- /testsuite/results/bitfield.nim: -------------------------------------------------------------------------------- 1 | type 2 | bits* {.bycopy.} = object 3 | flag* {.bitsize: 1.}: cint 4 | opts* {.bitsize: 4.}: cint 5 | 6 | -------------------------------------------------------------------------------- /testsuite/tests/tenumnamespace.hpp: -------------------------------------------------------------------------------- 1 | namespace test { 2 | enum MyEnum { E1 = 0, E2 = 2}; 3 | } 4 | 5 | struct foo; 6 | enum bar { A = 0, B = 1}; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | nimcache 2 | testsuite/tests/*.nim 3 | testsuite/cppkeepbodies/*.nim 4 | testsuite/cextras/*.nim 5 | testsuite/tester 6 | *.exe 7 | /c2nim 8 | -------------------------------------------------------------------------------- /testsuite/tests/defbug.h: -------------------------------------------------------------------------------- 1 | #def GLIB_AVAILABLE_IN_ALL 2 | #def G_BEGIN_DECLS 3 | G_BEGIN_DECLS 4 | GLIB_AVAILABLE_IN_ALL 5 | int func1(int i); 6 | void func2(int i); 7 | -------------------------------------------------------------------------------- /testsuite/tests/opconvertersDelete.hpp: -------------------------------------------------------------------------------- 1 | #delete "`++`" 2 | #cppallops 3 | 4 | class foo{ 5 | public: 6 | int operator++() const {return val;} 7 | int val; 8 | }; -------------------------------------------------------------------------------- /testsuite/results/opconvertersDelete.nim: -------------------------------------------------------------------------------- 1 | type 2 | foo* {.importcpp: "foo", header: "opconvertersDelete.hpp", bycopy.} = object 3 | val* {.importc: "val".}: cint 4 | 5 | -------------------------------------------------------------------------------- /testsuite/tests/inttemplateparam.cpp: -------------------------------------------------------------------------------- 1 | template void foo(); -------------------------------------------------------------------------------- /testsuite/results/struct_directives.nim: -------------------------------------------------------------------------------- 1 | type 2 | test* {.bycopy.} = object 3 | when defined(A): 4 | var a*: cint 5 | when defined(B): 6 | var b*: cint 7 | 8 | -------------------------------------------------------------------------------- /testsuite/tests/tskipthrow.cpp: -------------------------------------------------------------------------------- 1 | class foo { 2 | public: 3 | foo() throw(); 4 | virtual ~foo() throw(float); 5 | int m() const throw(int); 6 | }; 7 | 8 | int bar() throw(A, B); -------------------------------------------------------------------------------- /testsuite/tests/flexarray.h: -------------------------------------------------------------------------------- 1 | typedef struct aaa 2 | { 3 | int c; 4 | int a[0]; 5 | } aaa_t; 6 | 7 | typedef struct bbb 8 | { 9 | int c; 10 | int a[]; 11 | } bbb_t; -------------------------------------------------------------------------------- /testsuite/results/bug107_108.nim: -------------------------------------------------------------------------------- 1 | type 2 | Foo*[I: static[cint]; B: static[bool]] {.bycopy.} = object 3 | 4 | 5 | proc `method`*[I: static[cint]; B: static[bool]](this: var Foo[I, B]; i: cint) -------------------------------------------------------------------------------- /testsuite/tests/nestedanonymousstruct.h: -------------------------------------------------------------------------------- 1 | 2 | typedef struct 3 | { 4 | struct 5 | { 6 | struct 7 | { 8 | int a; 9 | } meow; 10 | } meow2; 11 | } miauz; 12 | -------------------------------------------------------------------------------- /testsuite/results/commaop.nim: -------------------------------------------------------------------------------- 1 | type 2 | Foo* {.importcpp: "Foo", header: "commaop.hpp", bycopy.} = object 3 | 4 | 5 | proc `comma`*(this: var Foo; i: cint): cint {.importcpp: "#,@", 6 | header: "commaop.hpp".} -------------------------------------------------------------------------------- /testsuite/results/directives.nim: -------------------------------------------------------------------------------- 1 | when not defined(ONE): 2 | const 3 | ONE* = (1) 4 | when not defined(TWO): 5 | const 6 | TWO* = (ONE + ONE) 7 | when not defined(THREE): 8 | const 9 | THREE* = "THREEEEE" -------------------------------------------------------------------------------- /testsuite/results/opencv_templ_default.nim: -------------------------------------------------------------------------------- 1 | type 2 | ParamType*[Tp; EnumTp = void] {.importcpp: "ParamType<\'0,\'1>", 3 | header: "opencv_templ_default.hpp", bycopy.} = object 4 | 5 | -------------------------------------------------------------------------------- /testsuite/results/flexarray.nim: -------------------------------------------------------------------------------- 1 | type 2 | aaa_t* {.bycopy.} = object 3 | c*: cint 4 | a*: UncheckedArray[cint] 5 | 6 | bbb_t* {.bycopy.} = object 7 | c*: cint 8 | a*: UncheckedArray[cint] 9 | 10 | -------------------------------------------------------------------------------- /testsuite/results/inttemplateparam.nim: -------------------------------------------------------------------------------- 1 | proc foo*[T; N: static[cint]; U: static[csize_t]; C; CA: static[clong]; 2 | S: static[cshort]; T2; LL: static[clonglong]; UI: static[cuint]; 3 | US: static[cushort]]() -------------------------------------------------------------------------------- /testsuite/results/tskipthrow.nim: -------------------------------------------------------------------------------- 1 | type 2 | foo* {.bycopy.} = object 3 | 4 | 5 | proc constructfoo*(): foo {.constructor.} 6 | proc destroyfoo*(this: var foo) 7 | proc m*(this: foo): cint {.noSideEffect.} 8 | proc bar*(): cint -------------------------------------------------------------------------------- /testsuite/results/bitfieldwithheader.nim: -------------------------------------------------------------------------------- 1 | type 2 | bits* {.importcpp: "bits", header: "bitfieldwithheader.hpp", bycopy.} = object 3 | flag* {.importc: "flag", bitsize: 1.}: cint 4 | opts* {.importc: "opts", bitsize: 4.}: cint 5 | 6 | -------------------------------------------------------------------------------- /testsuite/tests/structdefine.h: -------------------------------------------------------------------------------- 1 | #define N 123 2 | 3 | struct test { 4 | #define LENGTH N 5 | int field; 6 | #define SIZE N 7 | int ary[SIZE]; 8 | }; 9 | 10 | // bug #73 11 | enum TestEnum { 12 | VALUE_1 = 1, 13 | #define TEST_ENUM_VALUE_1 VALUE_1 14 | }; 15 | -------------------------------------------------------------------------------- /testsuite/results/operatorTemplate.nim: -------------------------------------------------------------------------------- 1 | ## ! @relates cv::Vec 2 | ## ! @{ 3 | 4 | proc operatorPE*[_Tp1; _Tp2; cn: static[cint]](a: var Vec[_Tp1, cn]; 5 | b: Vec[_Tp2, cn]): var Vec[_Tp1, cn] = 6 | discard 7 | 8 | proc `+=`*[_Tp1; _Tp2; cn: static[cint]](a: var Vec[_Tp1, cn]; b: Vec[_Tp2, cn]) -------------------------------------------------------------------------------- /testsuite/tests/cppstatic.hpp: -------------------------------------------------------------------------------- 1 | class ClassA 2 | { 3 | public: 4 | static void test(); 5 | }; 6 | 7 | class ClassB 8 | { 9 | public: 10 | static void test(); 11 | }; 12 | 13 | template 14 | class ClassGeneric 15 | { 16 | public: 17 | static void test(); 18 | }; 19 | 20 | static void test(); 21 | -------------------------------------------------------------------------------- /testsuite/results/opconverters.nim: -------------------------------------------------------------------------------- 1 | type 2 | foo* {.importcpp: "foo", header: "opconverters.hpp", bycopy.} = object 3 | val* {.importc: "val".}: cint 4 | 5 | 6 | converter `int`*(this: foo): cint {.noSideEffect, 7 | importcpp: "foo::operator int", 8 | header: "opconverters.hpp".} -------------------------------------------------------------------------------- /testsuite/tests/directives.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRECTIvES_H 2 | #define DIRECTIvES_H 3 | 4 | #ifndef MY_SYMBOLS 5 | #define MY_SYMBOLS 6 | #endif 7 | 8 | #ifndef ONE 9 | #define ONE (1) 10 | #endif 11 | 12 | #ifndef TWO 13 | #define TWO (ONE + ONE) 14 | #endif 15 | 16 | #ifndef THREE 17 | #define THREE "THREEEEE" 18 | #endif 19 | 20 | #endif 21 | 22 | -------------------------------------------------------------------------------- /testsuite/results/tenumnamespace.nim: -------------------------------------------------------------------------------- 1 | type 2 | MyEnum* {.size: sizeof(cint), importcpp: "test::MyEnum", 3 | header: "tenumnamespace.hpp".} = enum 4 | E1 = 0, E2 = 2 5 | 6 | 7 | discard "forward decl of foo" 8 | type 9 | bar* {.size: sizeof(cint), importcpp: "bar", header: "tenumnamespace.hpp".} = enum 10 | A = 0, B = 1 11 | 12 | -------------------------------------------------------------------------------- /testsuite/results/nestedanonymousstruct.nim: -------------------------------------------------------------------------------- 1 | type 2 | INNER_C_STRUCT_nestedanonymousstruct_3* {.bycopy.} = object 3 | a*: cint 4 | 5 | INNER_C_STRUCT_nestedanonymousstruct_2* {.bycopy.} = object 6 | meow*: INNER_C_STRUCT_nestedanonymousstruct_3 7 | 8 | miauz* {.bycopy.} = object 9 | meow2*: INNER_C_STRUCT_nestedanonymousstruct_2 10 | 11 | -------------------------------------------------------------------------------- /testsuite/tests/constructorcall.cpp: -------------------------------------------------------------------------------- 1 | class fooBar; 2 | 3 | class foo{ 4 | public: 5 | foo(int i){ 6 | val = i; 7 | } 8 | int val; 9 | }; 10 | 11 | int bar(foo f = foo(0)){ 12 | return f.val; 13 | } 14 | 15 | 16 | int bar(fooBar f = fooBar(0)); 17 | 18 | class ConsInitList : public foo{ 19 | public: 20 | ConsInitList(int i) : foo(i) {} 21 | }; -------------------------------------------------------------------------------- /testsuite/results/removeduplicates.nim: -------------------------------------------------------------------------------- 1 | type 2 | Test* {.importcpp: "Test", header: "removeduplicates.hpp", bycopy.} = object 3 | 4 | 5 | proc cvptr*(this: var Test; idx: ptr cint): cstring {.importcpp: "cvptr", 6 | header: "removeduplicates.hpp".} 7 | proc cvptr*(this: Test; idx: ptr cint): cstring {.noSideEffect, 8 | importcpp: "cvptr", header: "removeduplicates.hpp".} -------------------------------------------------------------------------------- /testsuite/results/tokenconcat.nim: -------------------------------------------------------------------------------- 1 | type 2 | fftw_double* = cdouble 3 | 4 | ## test the toString macro operator 5 | 6 | template toStringTemplate*(x: untyped): untyped = 7 | astToStr(x) 8 | 9 | proc main*(argc: cint; argv: ptr cstring): cint = 10 | var test: fftw_double = 1.234 11 | printf("%s %f", "hello3", test) 12 | someMain(8, "7890") 13 | return 0 14 | -------------------------------------------------------------------------------- /testsuite/tests/removeduplicates.hpp: -------------------------------------------------------------------------------- 1 | #render nobody 2 | #mergeDuplicates 3 | 4 | class Test { 5 | 6 | public: 7 | char* cvptr(const int* idx); 8 | const char* cvptr(const int* idx) const; 9 | 10 | }; 11 | 12 | char* Test::cvptr(const int* idx) { 13 | 14 | } 15 | const char* Test::cvptr(const int* idx) const { 16 | 17 | } 18 | 19 | typedef const Test Test; -------------------------------------------------------------------------------- /testsuite/results/structdefine.nim: -------------------------------------------------------------------------------- 1 | const 2 | N* = 123 3 | 4 | const 5 | LENGTH* = N 6 | 7 | const 8 | SIZE* = N 9 | 10 | type 11 | test* {.bycopy.} = object 12 | field*: cint 13 | ary*: array[SIZE, cint] 14 | 15 | 16 | ## bug #73 17 | 18 | type 19 | TestEnum* = enum 20 | VALUE_1 = 1 21 | 22 | 23 | const 24 | TEST_ENUM_VALUE_1* = VALUE_1 25 | -------------------------------------------------------------------------------- /testsuite/results/skipsection.nim: -------------------------------------------------------------------------------- 1 | const 2 | thisShouldNotBeSkipped* = 1 3 | 4 | when defined(skipme) or defined(somethingelse): 5 | const 6 | thisShouldBePresent* = 1 7 | when not defined(skipme1) or defined(somethingelse): 8 | const 9 | oneMoreConstant* = 1 10 | type 11 | foo* {.bycopy.} = object 12 | x*: cint 13 | y*: cint 14 | z*: cint 15 | 16 | -------------------------------------------------------------------------------- /testsuite/tests/reordertypes.hpp: -------------------------------------------------------------------------------- 1 | #pragma c2nim reordertypes 2 | 3 | class foo{ 4 | public: 5 | operator int () const {return val;} 6 | int val; 7 | enum { F1 = 33 }; 8 | }; 9 | 10 | class bar{ 11 | public: 12 | int operator + (int b) {return val+b;} 13 | int val; 14 | enum { B1 = 44 }; 15 | }; 16 | 17 | class baz{ 18 | public: 19 | enum { Z1 = bar::B1 }; 20 | }; -------------------------------------------------------------------------------- /testsuite/tests/struct_anonym.h: -------------------------------------------------------------------------------- 1 | 2 | struct normal{ 3 | int a; 4 | int b; 5 | }; 6 | 7 | typedef struct outerStruct { 8 | struct normal a_nomal_one; 9 | 10 | int a; 11 | 12 | struct { 13 | union { 14 | int b; 15 | } a_union_in_the_struct; 16 | 17 | int c; 18 | }; 19 | 20 | union { 21 | int d; 22 | 23 | struct { 24 | int e; 25 | } a_struct_in_the_union; 26 | } a_union; 27 | }; -------------------------------------------------------------------------------- /testsuite/results/tifdef_in_class.nim: -------------------------------------------------------------------------------- 1 | type 2 | failClass1* {.bycopy.} = object 3 | tmpI*: cint 4 | 5 | 6 | proc someProc*(this: var failClass1; x: cint) 7 | type 8 | failClass2* {.bycopy.} = object 9 | tmpI*: cint 10 | when not defined(unknown): 11 | myfield*: pointer 12 | 13 | 14 | const 15 | myconst* = 122 16 | 17 | when defined(unknown): 18 | proc someIfdefProc*(this: var failClass2; x: cint) -------------------------------------------------------------------------------- /testsuite/results/discardables.nim: -------------------------------------------------------------------------------- 1 | proc AddPoint*(s: ptr Sizer; x: cint; y: cint): bool {.discardable.} 2 | proc SetSize*(w: ptr Widget; w: cint; h: cint): cint {.discardable.} 3 | ## bug # #18 4 | 5 | let diamond*: array[4, array[2, GLfloat]] = [[0.0, 1.0], [1.0, 0.0], 6 | [0.0, -1.0], [-1.0, 0.0]] 7 | 8 | ## Left point 9 | ## bug #40 10 | 11 | proc cdCanvasPattern*(canvas: ptr cdCanvas; w: cint; h: cint; pattern: ptr clong) -------------------------------------------------------------------------------- /testsuite/tests/nep1enumfields.h: -------------------------------------------------------------------------------- 1 | #nep1 2 | #reordercomments 3 | #mergeblocks 4 | #delete RmwErrorStringT 5 | #delete RmwErrorStateT 6 | 7 | 8 | 9 | /// Struct wrapping a fixed-size c string used for returning the formatted error string. 10 | typedef rcutils_error_string_t rmw_error_string_t; 11 | 12 | /// Struct which encapsulates the error state set by RMW_SET_ERROR_MSG(). 13 | typedef rcutils_error_state_t rmw_error_state_t; 14 | 15 | -------------------------------------------------------------------------------- /testsuite/results/constructorcall.nim: -------------------------------------------------------------------------------- 1 | discard "forward decl of fooBar" 2 | type 3 | foo* {.bycopy.} = object 4 | val*: cint 5 | 6 | 7 | proc constructfoo*(i: cint): foo {.constructor.} 8 | proc bar*(f: foo = constructfoo(0)): cint = 9 | discard 10 | 11 | proc bar*(f: fooBar = constructfooBar(0)): cint 12 | type 13 | ConsInitList* {.bycopy.} = object of foo 14 | 15 | 16 | proc constructConsInitList*(i: cint): ConsInitList {.constructor.} -------------------------------------------------------------------------------- /testsuite/tests/struct_anonym_as_fields.h: -------------------------------------------------------------------------------- 1 | #anonymousAsFields 2 | #reordercomments 3 | 4 | struct normal{ 5 | int a; 6 | int b; 7 | }; 8 | 9 | typedef struct outerStruct { 10 | struct normal a_nomal_one; 11 | 12 | int a; 13 | 14 | struct { 15 | union { 16 | int b; 17 | float ab; 18 | }; 19 | 20 | int c; 21 | }; 22 | 23 | union { 24 | int d; 25 | 26 | struct { 27 | int e; 28 | } a_struct_in_the_union; 29 | }; 30 | }; -------------------------------------------------------------------------------- /testsuite/cppkeepbodies/tifdef_in_class.cpp: -------------------------------------------------------------------------------- 1 | 2 | #assumedef windows 3 | 4 | class failClass1 { 5 | public: 6 | int tmpI; 7 | #ifdef windows 8 | void someProc(int x); 9 | #else 10 | void* myfield; 11 | #endif 12 | 13 | #if 0 14 | int atLeastSkipThis; 15 | #endif 16 | }; 17 | 18 | class failClass2 { 19 | public: 20 | int tmpI; 21 | #define myconst 122 22 | #ifdef unknown 23 | void someIfdefProc(int x); 24 | #else 25 | void* myfield; 26 | #endif 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /testsuite/results/struct_anonym_as_fields.nim: -------------------------------------------------------------------------------- 1 | type 2 | normal* {.bycopy.} = object 3 | a*: cint 4 | b*: cint 5 | 6 | INNER_C_STRUCT_struct_anonym_as_fields_3* {.bycopy.} = object 7 | e*: cint 8 | 9 | outerStruct* {.bycopy.} = object 10 | a_nomal_one*: normal 11 | a*: cint 12 | anon1_b*: cint 13 | anon1_ab*: cfloat 14 | c*: cint 15 | anon2_d*: cint 16 | anon2_a_struct_in_the_union*: INNER_C_STRUCT_struct_anonym_as_fields_3 17 | 18 | -------------------------------------------------------------------------------- /testsuite/tests/discardables.h: -------------------------------------------------------------------------------- 1 | #discardableprefix Add 2 | #discardableprefix Set 3 | 4 | bool AddPoint(Sizer* s, int x, int y); 5 | int SetSize(Widget* w, int w, int h); 6 | 7 | // bug # #18 8 | 9 | const GLfloat diamond[4][2] = { 10 | { 0.0, 1.0 }, // Top point 11 | { 1.0, 0.0 }, // Right point 12 | { 0.0, -1.0 }, // Bottom point 13 | { -1.0, 0.0 } }; // Left point 14 | 15 | 16 | // bug #40 17 | void cdCanvasPattern(cdCanvas* canvas, int w, int h, long const int *pattern); 18 | -------------------------------------------------------------------------------- /c2nim.nimble: -------------------------------------------------------------------------------- 1 | version = "0.9.20" 2 | author = "Andreas Rumpf" 3 | description = "c2nim is a tool to translate Ansi C code to Nim." 4 | license = "MIT" 5 | skipDirs = @["doc"] 6 | 7 | skipExt = @["nim"] 8 | 9 | bin = @["c2nim"] 10 | 11 | requires "nim >= 1.2.0" 12 | 13 | import strutils 14 | 15 | task test, "runs c2nim tests": 16 | exec "nimble build" 17 | exec "nim c --run testsuite/tester.nim" 18 | 19 | task docs, "build c2nim's docs": 20 | exec "nim rst2html --putenv:c2nimversion=$1 doc/c2nim.rst" % version 21 | -------------------------------------------------------------------------------- /testsuite/tests/tokenconcat.h: -------------------------------------------------------------------------------- 1 | #ifndef C2NIM 2 | # define CAT(x,y) x ## y 3 | # define MANGLE_DOUBLE(x,y) typedef y CAT(x,y) 4 | #else 5 | # def CAT(x,y) x ## y 6 | # def MANGLE_DOUBLE(x,y) typedef y CAT(x,y) 7 | #endif 8 | 9 | 10 | MANGLE_DOUBLE(fftw_, double); 11 | 12 | // test the toString macro operator 13 | 14 | #def toString(x) #x 15 | 16 | #define toStringTemplate(x) #x 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | fftw_double test = 1.234; 21 | printf("%s %f","hello3", test); 22 | someMain(8, toString(7890)); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /testsuite/results/enum.nim: -------------------------------------------------------------------------------- 1 | type 2 | vehicles* = enum 3 | boat = 0x01, bicycle = 4, bobycar, car = 0x10, truck 4 | 5 | const 6 | ship = boat 7 | speedboat = boat 8 | 9 | const 10 | red* = 4 11 | green* = 2 12 | blue* = 3 13 | 14 | type 15 | food* = enum 16 | cucumber = 2, bread = 4, chocolate = 6 17 | numbers* = enum 18 | nten = -10, nnine, nfour = -4, one = 1, two, three = +3, four = 4, 19 | positivenine = +9 20 | 21 | const 22 | toast = bread 23 | bun = bread 24 | 25 | const 26 | negativeten = nten 27 | aliasA* = one 28 | aliasB* = nnine 29 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: c 4 | os: linux 5 | 6 | cache: 7 | directories: 8 | - "$HOME/.nimble" 9 | - "$HOME/.choosenim" 10 | 11 | env: 12 | - CHOOSENIM_CHOOSE_VERSION="devel" 13 | - CHOOSENIM_CHOOSE_VERSION="0.20.0" 14 | - CHOOSENIM_CHOOSE_VERSION="0.19.6" 15 | 16 | install: 17 | - | 18 | curl https://nim-lang.org/choosenim/init.sh -sSf > init.sh 19 | sh init.sh -y 20 | - export PATH=$HOME/.nimble/bin:$PATH 21 | - nimble refresh -y 22 | 23 | before_script: 24 | - set -e 25 | 26 | script: 27 | - nimble install -y 28 | - nim c -r testsuite/tester.nim 29 | -------------------------------------------------------------------------------- /testsuite/tests/operatorTemplate.cpp: -------------------------------------------------------------------------------- 1 | //! @relates cv::Vec 2 | //! @{ 3 | 4 | template static inline 5 | Vec<_Tp1, cn>& operatorPE (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b) 6 | { 7 | for( int i = 0; i < cn; i++ ) 8 | a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]); 9 | return a; 10 | } 11 | 12 | template static inline 13 | Vec<_Tp1, cn>& operator+= (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b) 14 | { 15 | for( int i = 0; i < cn; i++ ) 16 | a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]); 17 | return a; 18 | } -------------------------------------------------------------------------------- /testsuite/tests/enum.h: -------------------------------------------------------------------------------- 1 | 2 | enum vehicles 3 | { 4 | car = 0x10, 5 | truck, 6 | boat = 0x01, 7 | ship = 1, 8 | speedboat = 1, 9 | bicycle = 4, 10 | bobycar 11 | }; 12 | 13 | enum 14 | { 15 | red = 4, 16 | green = 2, 17 | blue 18 | }; 19 | 20 | typedef enum food 21 | { 22 | bread = 4, 23 | toast = 4, 24 | bun = 0x04, 25 | cucumber = 2, 26 | chocolate = 6 27 | }; 28 | 29 | typedef enum numbers 30 | { 31 | one = 1, 32 | two, 33 | nten = - 10, 34 | nnine, 35 | four = 4, 36 | three = + 3, 37 | positivenine = + 9, 38 | nfour = - 4, 39 | negativeten = -10, 40 | aliasA = one, 41 | aliasB = nnine 42 | }; 43 | -------------------------------------------------------------------------------- /testsuite/tests/opencv_class_ifdef.hpp: -------------------------------------------------------------------------------- 1 | class Algorithm 2 | { 3 | public: 4 | 5 | /** 6 | * @overload 7 | */ 8 | void write(FileStorage& fs, const String& name) const; 9 | #if CV_VERSION_MAJOR < 5 10 | /** @deprecated */ 11 | void write() const; 12 | #endif 13 | 14 | iterator operator++(int); 15 | friend bool operator== (const iterator& a, const iterator& b) { return { a.m_curr == b.m_curr }; } 16 | friend bool operator!= (const iterator& a, const iterator& b) { return /* test */ a.m_curr != b.m_curr; } 17 | int test(int); 18 | 19 | protected: 20 | void writeFormat(FileStorage& fs) const; 21 | }; 22 | -------------------------------------------------------------------------------- /testsuite/cextras/rcl_allocator_imp_pragma.h: -------------------------------------------------------------------------------- 1 | #pragma c2nim clibUserPragma 2 | 3 | // 4 | //The default allocator uses malloc(), free(), calloc(), and realloc(). 5 | typedef struct rcutils_allocator_s 6 | { 7 | 8 | /// allocate: Allocate memory, given a size and the `state` pointer. 9 | void * (*allocate)(size_t size, void * state); 10 | 11 | /** allocator objects. */ 12 | void * state; 13 | 14 | 15 | } rcutils_allocator_t; 16 | 17 | 18 | /// Return a zero initialized allocator. 19 | /** 20 | * Note that this is an invalid allocator and should only be used as a placeholder. 21 | */ 22 | rcutils_allocator_t rcutils_get_zero_initialized_allocator(void); 23 | 24 | 25 | -------------------------------------------------------------------------------- /testsuite/tests/vincent.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int rand(void); 5 | 6 | int id2(void) { 7 | return (int *)1; 8 | } 9 | 10 | int id(void (*f)(void)) { 11 | f(); 12 | ((void (*)(int))f)(10); 13 | return 10; 14 | return (20+1); 15 | return (int *)id; 16 | } 17 | 18 | int main() { 19 | float f = .2, 20 | g = 2., 21 | h = 1.0+rand(), 22 | i = 1.0e+3; 23 | int j, a; 24 | for(j = 0, a = 10; j < 0; j++, a++) ; 25 | do { 26 | printf("howdy"); 27 | } while(--i, 0); 28 | if(1) 29 | printf("1"); // error from this comment 30 | else 31 | printf("2"); 32 | return '\x00'; 33 | } 34 | -------------------------------------------------------------------------------- /testsuite/results/vincenth.nim: -------------------------------------------------------------------------------- 1 | type 2 | foo* {.bycopy.} = object 3 | x*: cint 4 | y*: cint 5 | z*: cint 6 | 7 | 8 | ## C11 init syntax: 9 | 10 | let lookup*: array[2, foo] = [0: (x: 1, y: 3, z: 4), 1: (x: 2, y: 3, z: 4)] 11 | 12 | type 13 | message_type* = enum 14 | MESSAGE_TYPE_NOTICE, MESSAGE_TYPE_PRIVMSG, MESSAGE_TYPE_COUNT 15 | 16 | 17 | let cmdname*: array[MESSAGE_TYPE_COUNT, cstring] = [ 18 | MESSAGE_TYPE_PRIVMSG: "PRIVMSG", MESSAGE_TYPE_NOTICE: "NOTICE"] 19 | 20 | const 21 | EFI_FIRMWARE_VENDOR* = "INTEL" 22 | EFI_FIRMWARE_MAJOR_REVISION* = 12 23 | EFI_FIRMWARE_MINOR_REVISION* = 33 24 | EFI_FIRMWARE_REVISION* = ( 25 | (EFI_FIRMWARE_MAJOR_REVISION shl 16) or (EFI_FIRMWARE_MINOR_REVISION)) 26 | -------------------------------------------------------------------------------- /testsuite/results/vincent.nim: -------------------------------------------------------------------------------- 1 | proc rand*(): cint 2 | proc id2*(): cint = 3 | return cast[ptr cint](1) 4 | 5 | proc id*(f: proc ()): cint = 6 | f() 7 | (cast[proc (a1: cint)](f))(10) 8 | return 10 9 | return 20 + 1 10 | return cast[ptr cint](id) 11 | 12 | proc main*(): cint = 13 | var 14 | f: cfloat = 0.2 15 | g: cfloat = 2.0 16 | h: cfloat = 1.0 + rand() 17 | i: cfloat = 1.0e+3 18 | var 19 | j: cint 20 | a: cint 21 | j = 0 22 | a = 10 23 | while j < 0: 24 | ## ignored statement 25 | inc(j) 26 | inc(a) 27 | while true: 28 | printf("howdy") 29 | dec(i) 30 | if not 0: 31 | break 32 | if 1: 33 | printf("1") 34 | else: 35 | printf("2") 36 | return '\x00' 37 | -------------------------------------------------------------------------------- /testsuite/tests/vincenth.h: -------------------------------------------------------------------------------- 1 | struct foo { 2 | int x,y,z; 3 | }; 4 | 5 | // C11 init syntax: 6 | const foo lookup[2] = { 7 | [0] = {.x = 1, .y = 3, .z = 4}, 8 | [1] = {.x = 2, .y = 3, .z = 4} 9 | }; 10 | 11 | enum message_type { 12 | MESSAGE_TYPE_NOTICE, 13 | MESSAGE_TYPE_PRIVMSG, 14 | MESSAGE_TYPE_COUNT 15 | }; 16 | 17 | const char *cmdname[MESSAGE_TYPE_COUNT] = { 18 | [MESSAGE_TYPE_PRIVMSG] = "PRIVMSG", 19 | [MESSAGE_TYPE_NOTICE] = "NOTICE", 20 | }; 21 | 22 | #define EFI_FIRMWARE_VENDOR L"INTEL" // line 30 23 | #define EFI_FIRMWARE_MAJOR_REVISION 12 // line 31 24 | #define EFI_FIRMWARE_MINOR_REVISION 33 25 | #define EFI_FIRMWARE_REVISION ((EFI_FIRMWARE_MAJOR_REVISION <<16) | (EFI_FIRMWARE_MINOR_REVISION)) 26 | -------------------------------------------------------------------------------- /compiler/nversion.nim: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # The Nim Compiler 4 | # (c) Copyright 2015 Andreas Rumpf 5 | # 6 | # See the file "copying.txt", included in this 7 | # distribution, for details about the copyright. 8 | # 9 | 10 | # This module contains Nim's version. It is the only place where it needs 11 | # to be changed. 12 | 13 | const 14 | MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets? 15 | VersionAsString* = system.NimVersion 16 | RodFileVersion* = "1223" # modify this if the rod-format changes! 17 | 18 | NimCompilerApiVersion* = 3 ## Check for the existance of this before accessing it 19 | ## as older versions of the compiler API do not 20 | ## declare this. 21 | -------------------------------------------------------------------------------- /testsuite/results/reordertypes.nim: -------------------------------------------------------------------------------- 1 | const 2 | fooF1* = 33 3 | barB1* = 44 4 | 5 | type 6 | foo* {.importcpp: "foo", header: "reordertypes.hpp", bycopy.} = object 7 | val* {.importc: "val".}: cint 8 | 9 | 10 | type 11 | bar* {.importcpp: "bar", header: "reordertypes.hpp", bycopy.} = object 12 | val* {.importc: "val".}: cint 13 | 14 | 15 | type 16 | baz* {.importcpp: "baz", header: "reordertypes.hpp", bycopy.} = object 17 | 18 | 19 | const 20 | bazZ1* = B1 21 | 22 | converter `int`*(this: foo): cint {.noSideEffect, 23 | importcpp: "foo::operator int", 24 | header: "reordertypes.hpp".} 25 | proc `+`*(this: var bar; b: cint): cint {.importcpp: "(# + #)", 26 | header: "reordertypes.hpp".} -------------------------------------------------------------------------------- /testsuite/results/struct_anonym.nim: -------------------------------------------------------------------------------- 1 | type 2 | normal* {.bycopy.} = object 3 | a*: cint 4 | b*: cint 5 | 6 | INNER_C_UNION_struct_anonym_1* {.bycopy, union.} = object 7 | b*: cint 8 | 9 | INNER_C_STRUCT_struct_anonym_0* {.bycopy.} = object 10 | a_union_in_the_struct*: INNER_C_UNION_struct_anonym_1 11 | c*: cint 12 | 13 | INNER_C_STRUCT_struct_anonym_4* {.bycopy.} = object 14 | e*: cint 15 | 16 | INNER_C_UNION_struct_anonym_3* {.bycopy, union.} = object 17 | d*: cint 18 | a_struct_in_the_union*: INNER_C_STRUCT_struct_anonym_4 19 | 20 | outerStruct* {.bycopy.} = object 21 | a_nomal_one*: normal 22 | a*: cint 23 | ano_struct_anonym_2*: INNER_C_STRUCT_struct_anonym_0 24 | a_union*: INNER_C_UNION_struct_anonym_3 25 | 26 | -------------------------------------------------------------------------------- /testsuite/results/cppstatic.nim: -------------------------------------------------------------------------------- 1 | type 2 | ClassA* {.importcpp: "ClassA", header: "cppstatic.hpp", bycopy.} = object 3 | 4 | 5 | proc test*(_: `type` ClassA) {.importcpp: "ClassA::test(@)", 6 | header: "cppstatic.hpp".} 7 | type 8 | ClassB* {.importcpp: "ClassB", header: "cppstatic.hpp", bycopy.} = object 9 | 10 | 11 | proc test*(_: `type` ClassB) {.importcpp: "ClassB::test(@)", 12 | header: "cppstatic.hpp".} 13 | type 14 | ClassGeneric*[T] {.importcpp: "ClassGeneric<\'0>", header: "cppstatic.hpp", 15 | bycopy.} = object 16 | 17 | 18 | proc test*[T](_: `type` ClassGeneric[T]) {.importcpp: "ClassGeneric::test(@)", 19 | header: "cppstatic.hpp".} 20 | proc test*() {.importcpp: "test(@)", header: "cppstatic.hpp".} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | c2nim 2 | ===== 3 | 4 | c2nim is a tool to translate ANSI C code to Nim. The output is human-readable 5 | Nim code that is meant to be tweaked by hand after the translation process. 6 | c2nim is no real compiler! 7 | 8 | Please see the manual [here](doc/c2nim.rst). 9 | 10 | Installing 11 | ---------- 12 | 13 | Run `nimble install c2nim`. 14 | 15 | Translating 16 | ----------- 17 | 18 | c2nim is preliminary meant to translate C header files. Because of this, the 19 | preprocessor is part of the parser. For example: 20 | 21 | ```C 22 | #define abc 123 23 | #define xyz 789 24 | ``` 25 | 26 | Is translated into: 27 | 28 | ```Nim 29 | const 30 | abc* = 123 31 | xyz* = 789 32 | ``` 33 | 34 | c2nim is meant to translate fragments of C/C++ code and thus does not follow 35 | include files. c2nim cannot parse all of ANSI C/C++ and many constructs cannot 36 | be represented in Nim. 37 | -------------------------------------------------------------------------------- /testsuite/results/opencv_class_ifdef.nim: -------------------------------------------------------------------------------- 1 | type 2 | Algorithm* {.importcpp: "Algorithm", header: "opencv_class_ifdef.hpp", bycopy.} = object ## 3 | ## @overload 4 | ## 5 | 6 | 7 | proc write*(this: Algorithm; fs: var FileStorage; name: String) {.noSideEffect, 8 | importcpp: "write", header: "opencv_class_ifdef.hpp".} 9 | when CV_VERSION_MAJOR < 5: 10 | proc write*(this: Algorithm) {.noSideEffect, importcpp: "write", 11 | header: "opencv_class_ifdef.hpp".} 12 | ## @deprecated 13 | proc `++`*(this: var Algorithm; a2: cint): `iterator` {.importcpp: "(++ #)", 14 | header: "opencv_class_ifdef.hpp".} 15 | proc test*(this: var Algorithm; a2: cint): cint {.importcpp: "test", 16 | header: "opencv_class_ifdef.hpp".} -------------------------------------------------------------------------------- /testsuite/tests/cpp11.hpp: -------------------------------------------------------------------------------- 1 | class Event 2 | { 3 | public: 4 | Event() = default; 5 | }; 6 | 7 | std::ostream &operator << (std::ostream &out, const Enum &t); 8 | 9 | constexpr Event foo; 10 | 11 | class ConstexprConstructor { 12 | public: 13 | [[deprecated("getCenter() was renamed to getResourceDepot()")]] 14 | constexpr ConstexprConstructor(int i = 1) : id(i) {} 15 | }; 16 | // list initialization, issue #163 17 | constexpr int list_init{123}; 18 | 19 | class NonCopy { 20 | public: 21 | NonCopy() {} 22 | ~NonCopy() {} 23 | // deleted constructor, issue #165 24 | NonCopy(const NonCopy &) = delete; 25 | NonCopy &operator=(const NonCopy &) = delete; 26 | }; 27 | 28 | class VirtClass { 29 | public: 30 | VirtClass() = default; 31 | ~VirtClass() = 0; 32 | virtual void pureFunction() = 0; 33 | virtual void implementedFunction(); 34 | void concreteFunction(); 35 | }; 36 | 37 | namespace VarNS 38 | { 39 | const int my_var = 5; 40 | } 41 | -------------------------------------------------------------------------------- /testsuite/results/pointerdecls.nim: -------------------------------------------------------------------------------- 1 | ## posix signal 2 | 3 | var signal*: proc (a1: cint; a2: proc (a1: cint)): proc (a1: cint) 4 | 5 | ## str signal 6 | 7 | proc strsignal*(__sig: cint): cstring 8 | ## str signal 9 | 10 | proc strsignal_r*(__sig: cint; __strsignalbuf: cstring; __buflen: csize_t): cint 11 | ## attributes 12 | 13 | var _close*: proc (a1: pointer): cint 14 | 15 | var _read*: proc (a1: pointer; a2: cstring; a3: cint): cint 16 | 17 | ## __attribute__ 18 | 19 | proc vasprintf*(a1: cstringArray; a2: cstring; a3: __gnuc_va_list): cint 20 | proc __assert_rtn*(a1: cstring; a2: cstring; a3: cint; a4: cstring) 21 | proc malloc*(__size: csize_t): pointer 22 | ## struct attribute 23 | 24 | type 25 | _OSUnalignedU16* {.bycopy.} = object 26 | __val*: uint16_t 27 | 28 | 29 | ## other typedefs 30 | 31 | type 32 | int64_t* = clonglong 33 | uint16_t* = cushort 34 | __uint32_t* = cuint 35 | __int64_t* = clonglong 36 | __uint64_t* = culonglong 37 | __darwin_size_t* = culong 38 | -------------------------------------------------------------------------------- /testsuite/results/rcl_allocator_imp_pragma.nim: -------------------------------------------------------------------------------- 1 | type 2 | 3 | rcutils_allocator_t* {.importc: "rcutils_allocator_t", 4 | header: "rcl_allocator_imp_pragma.h", bycopy.} = object ## 5 | ## 6 | ## The default allocator uses malloc(), free(), calloc(), and realloc(). 7 | allocate* {.importc: "allocate".}: proc (size: csize_t; state: pointer): pointer ## 8 | ## allocate: Allocate memory, given a size and the `state` pointer. 9 | state* {.importc: "state".}: pointer ## allocator objects. 10 | 11 | 12 | 13 | proc rcutils_get_zero_initialized_allocator*(): rcutils_allocator_t {. 14 | importc: "rcutils_get_zero_initialized_allocator", clib.} 15 | ## 16 | ## Return a zero initialized allocator. 17 | ## 18 | ## Note that this is an invalid allocator and should only be used as a placeholder. 19 | ## -------------------------------------------------------------------------------- /testsuite/tests/skipsection.h: -------------------------------------------------------------------------------- 1 | #assumendef skipme 2 | #assumedef skipme1 3 | 4 | #def skipme2 somethingelse 5 | 6 | #ifdef skipme 7 | #ifdef innerifdef 8 | #define foo bar 9 | #else 10 | #define foo baz 11 | #endif 12 | #endif 13 | 14 | #ifndef skipme1 15 | #define thisShouldAlsoBeSkipped 1 16 | #endif 17 | 18 | #ifdef skipme1 19 | #define thisShouldNotBeSkipped 1 20 | #endif 21 | 22 | #ifndef skipme2 23 | #define thisShouldBeSkipped 1 24 | #endif 25 | 26 | #if defined(skipme) 27 | #define thisShouldAlsoBeSkipped 1 28 | #endif 29 | 30 | #if defined(__cplusplus) 31 | #define skipMeAsWell 1 32 | #endif 33 | 34 | #if defined(skipme) || defined(somethingelse) 35 | #define thisShouldBePresent 1 36 | #endif 37 | 38 | #if defined(skipme) && defined(somethingelse) 39 | #define thisShouldAlsoBeSkipped 1 40 | #endif 41 | 42 | #if !defined(skipme1) || defined(somethingelse) 43 | #define oneMoreConstant 1 44 | #endif 45 | 46 | #if defined(somethingelse) && !defined(skipme1) 47 | #define thisShouldAlsoBeSkipped 1 48 | #endif 49 | 50 | struct foo { 51 | int x,y,z; 52 | }; -------------------------------------------------------------------------------- /testsuite/tests/pointerdecls.h: -------------------------------------------------------------------------------- 1 | // posix signal 2 | void(*signal(int, void (*)(int)))(int); 3 | 4 | // str signal 5 | char *strsignal(int __sig); 6 | // str signal 7 | int strsignal_r(int __sig, char *__strsignalbuf, size_t __buflen); 8 | 9 | // attributes 10 | int (* _Nullable _close)(void *); 11 | int (* _Nullable _read) (void *, char *, int); 12 | 13 | // __attribute__ 14 | int vasprintf(char ** restrict, const char * restrict, __gnuc_va_list) __attribute__((__format__ (__printf__, 2, 0))); 15 | void __assert_rtn(const char *, const char *, int, const char *) __attribute__((__noreturn__)) __attribute__((__cold__)) ; 16 | void *malloc(size_t __size) __attribute__((__warn_unused_result__)) __attribute__((alloc_size(1))); 17 | 18 | // struct attribute 19 | struct _OSUnalignedU16 { 20 | volatile uint16_t __val; 21 | } __attribute__((__packed__)); 22 | 23 | // other typedefs 24 | typedef long long int64_t; 25 | typedef unsigned short uint16_t; 26 | typedef unsigned int __uint32_t; 27 | typedef long long __int64_t; 28 | typedef unsigned long long __uint64_t; 29 | typedef long unsigned int __darwin_size_t; -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Andreas Rumpf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /testsuite/results/tforeachloops.nim: -------------------------------------------------------------------------------- 1 | proc main*(): cint = 2 | var v: vector[cint] = [0, 1, 2, 3, 4, 5] 3 | for i in v: ## access by const reference 4 | cout shl i shl ' ' 5 | for i in v: ## access by value, the type of i is int 6 | cout shl i shl ' ' 7 | cout shl '\n' 8 | for i in v: ## access by forwarding reference, the type of i is int& 9 | cout shl i shl ' ' 10 | cout shl '\n' 11 | let cv: var auto = v 12 | for i in cv: ## access by f-d reference, the type of i is const int& 13 | cout shl i shl ' ' 14 | cout shl '\n' 15 | for n in (0, 1, 2, 3, 4, 5): ## the initializer may be a braced-init-list 16 | cout shl n shl ' ' 17 | cout shl '\n' 18 | var a: UncheckedArray[cint] = [0, 1, 2, 3, 4, 5] 19 | for n in a: ## the initializer may be an array 20 | cout shl n shl ' ' 21 | cout shl '\n' 22 | for n in a: 23 | cout shl 1 shl ' ' 24 | ## the loop variable need not be used 25 | cout shl '\n' 26 | ## 27 | ## for (auto n = v.size(); auto i : v) // the init-statement (C++20) 28 | ## std::cout << --n + i << ' '; 29 | ## std::cout << '\n'; 30 | -------------------------------------------------------------------------------- /testsuite/results/opencv_templ_param.nim: -------------------------------------------------------------------------------- 1 | type 2 | ParamType_TvectorMat*[T: vector[Mat]] {. 3 | importcpp: "ParamType_TvectorMat<\'0>", header: "opencv_templ_param.hpp", 4 | bycopy.} = object 5 | 6 | ParamType_TvectorMatconst_param_type* = vector[Mat] 7 | ParamType_TvectorMatmember_type* = vector[Mat] 8 | ParamType_Tcuint*[T: cuint] {.importcpp: "ParamType_Tcuint<\'0>", 9 | header: "opencv_templ_param.hpp", bycopy.} = object 10 | 11 | ParamType_Tcuintconst_param_type* = cuint 12 | ParamType_Tcuintmember_type* = cuint 13 | ParamType_T_TpUtypevalue_Tp*[T: _Tp; U: `type`[value[_Tp]]] {. 14 | importcpp: "ParamType_T_TpUtypevalue_Tp<\'0,\'1>", 15 | header: "opencv_templ_param.hpp", bycopy.} = object 16 | 17 | ParamType_T_TpUtypevalue_Tpconst_param_type* = `type`[_Tp] 18 | ParamType_T_TpUtypevalue_Tpmember_type* = `type`[_Tp] 19 | 20 | proc normDecl*(a: ptr Tp; b: ptr Tp; n: cint): _AccTp {.importcpp: "normDecl", 21 | importcpp: "normDecl(@)", header: "opencv_templ_param.hpp".} 22 | proc normRegular*(a: ptr Tp; b: ptr Tp; n: cint): _AccTp {. 23 | importcpp: "normRegular".} 24 | proc normL2Sqr*[_Tp; _AccTp](a: ptr _Tp; b: ptr _Tp; n: cint): _AccTp {. 25 | importcpp: "normL2Sqr".} -------------------------------------------------------------------------------- /testsuite/cppkeepbodies/tforeachloops.cpp: -------------------------------------------------------------------------------- 1 | 2 | int main() { 3 | std::vector v = {0, 1, 2, 3, 4, 5}; 4 | 5 | for (const int& i : v) // access by const reference 6 | std::cout << i << ' '; 7 | 8 | 9 | for (auto i : v) // access by value, the type of i is int 10 | std::cout << i << ' '; 11 | std::cout << '\n'; 12 | 13 | for (auto&& i : v) // access by forwarding reference, the type of i is int& 14 | std::cout << i << ' '; 15 | std::cout << '\n'; 16 | 17 | const auto& cv = v; 18 | 19 | for (auto&& i : cv) // access by f-d reference, the type of i is const int& 20 | std::cout << i << ' '; 21 | std::cout << '\n'; 22 | 23 | for (int n : {0, 1, 2, 3, 4, 5}) // the initializer may be a braced-init-list 24 | std::cout << n << ' '; 25 | std::cout << '\n'; 26 | 27 | int a[] = {0, 1, 2, 3, 4, 5}; 28 | for (int n : a) // the initializer may be an array 29 | std::cout << n << ' '; 30 | std::cout << '\n'; 31 | 32 | for ([[maybe_unused]] int n : a) 33 | std::cout << 1 << ' '; // the loop variable need not be used 34 | std::cout << '\n'; 35 | 36 | /* 37 | for (auto n = v.size(); auto i : v) // the init-statement (C++20) 38 | std::cout << --n + i << ' '; 39 | std::cout << '\n';*/ 40 | } 41 | -------------------------------------------------------------------------------- /testsuite/tests/systest2.c: -------------------------------------------------------------------------------- 1 | #ifdef C2NIM 2 | # header "iup.h" 3 | # cdecl 4 | # mangle "'GTK_'{.*}" "TGtk$1" 5 | # mangle "'PGTK_'{.*}" "PGtk$1" 6 | #endif 7 | 8 | typedef struct stupidTAG { 9 | mytype a, b; 10 | } GTK_MyStruct, *PGTK_MyStruct; 11 | 12 | typedef struct { 13 | mytype a, b; 14 | } GTK_MyStruct, *PGTK_MyStruct; 15 | 16 | int IupConvertXYToPos(PIhandle ih, int x, int y); 17 | 18 | #def FOO_0() 19 | #def FOO_1 20 | #def FOO_2(x) x 21 | 22 | FOO_0() 23 | FOO_2(FOO_1) 24 | FOO_1 25 | 26 | #ifdef C2NIM 27 | #@ 28 | proc handwrittenNim(): string = 29 | "@#" 30 | 31 | @# 32 | #endif 33 | 34 | #define foobar #@ 5 or 9 35 | @# 36 | 37 | #pure wxEdge 38 | enum wxEdge 39 | { 40 | wxLeft, wxTop, wxRight, wxBottom, wxWidth, wxHeight, 41 | wxCentre, wxCenter = wxCentre, wxCentreX, wxCentreY 42 | }; 43 | 44 | // bug #136 45 | 46 | static inline void bcf_float_set(float *ptr, uint32_t value) 47 | { 48 | union { uint32_t i; float f; } u; 49 | u.i = value; 50 | *ptr = u.f; 51 | } 52 | 53 | #isarray a 54 | 55 | void sort(int* a, int len); 56 | 57 | // bug #32 58 | 59 | int x(){ 60 | #if fii 61 | if(1) { 62 | } 63 | #else 64 | return 1; 65 | #endif 66 | } 67 | 68 | 69 | #define someU64 12333ull 70 | 71 | #define someU32 12333ul 72 | #define someI64 12333LL 73 | #define someI32 12333l 74 | -------------------------------------------------------------------------------- /testsuite/cextras/message_type_support_struct.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | typedef struct rosidl_message_type_support_t rosidl_message_type_support_t; 17 | 18 | typedef const rosidl_message_type_support_t * (* rosidl_message_typesupport_handle_function)( 19 | const rosidl_message_type_support_t *, const char *); 20 | 21 | /// Contains rosidl message type support data 22 | struct rosidl_message_type_support_t 23 | { 24 | /// String identifier for the type_support. 25 | const char * typesupport_identifier; 26 | /// Pointer to the message type support library 27 | const void * data; 28 | /// Pointer to the message type support handler function 29 | rosidl_message_typesupport_handle_function func; 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: CI 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the master branch 8 | push: 9 | branches: [ master ] 10 | pull_request: 11 | branches: [ master ] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | build: 20 | # The type of runner that the job will run on 21 | runs-on: ubuntu-latest 22 | 23 | strategy: 24 | matrix: 25 | nim: ['devel', 'version-2-0', 'version-1-6'] 26 | 27 | # Steps represent a sequence of tasks that will be executed as part of the job 28 | steps: 29 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 30 | - uses: actions/checkout@v4 31 | 32 | - name: Setup Nim 33 | uses: alaviss/setup-nim@0.1.1 34 | with: 35 | path: 'nim' 36 | version: ${{ matrix.nim }} 37 | 38 | - name: c2nim 39 | shell: bash 40 | run: | 41 | nim c c2nim 42 | # tester runs c2nim in PATH 43 | export PATH="$PWD:$PATH" 44 | nim c -r testsuite/tester.nim 45 | 46 | -------------------------------------------------------------------------------- /testsuite/tests/opencv_templ_param.hpp: -------------------------------------------------------------------------------- 1 | #cppspecialization 2 | #header 3 | #importc 4 | 5 | template<> struct ParamType > 6 | { 7 | typedef const std::vector& const_param_type; 8 | typedef std::vector member_type; 9 | 10 | static const Param type = Param::MAT_VECTOR; 11 | }; 12 | 13 | template<> struct ParamType 14 | { 15 | typedef unsigned const_param_type; 16 | typedef unsigned member_type; 17 | 18 | static const Param type = Param::UNSIGNED_INT; 19 | }; 20 | 21 | template 22 | struct ParamType<_Tp, typename std::enable_if< std::is_enum<_Tp>::value >::type> 23 | { 24 | typedef typename std::underlying_type<_Tp>::type const_param_type; 25 | typedef typename std::underlying_type<_Tp>::type member_type; 26 | 27 | static const Param type = Param::INT; 28 | }; 29 | 30 | _AccTp normDecl(const Tp* a, const Tp* b, int n); 31 | 32 | _AccTp normRegular(const Tp* a, const Tp* b, int n) 33 | { 34 | } 35 | 36 | template 37 | _AccTp normL2Sqr(const _Tp* a, const _Tp* b, int n) 38 | { 39 | _AccTp s = 0; 40 | int i= 0; 41 | 42 | for(; i <= n - 4; i += 4 ) 43 | { 44 | _AccTp v0 = _AccTp(a[i] - b[i]), v1 = _AccTp(a[i+1] - b[i+1]), v2 = _AccTp(a[i+2] - b[i+2]), v3 = _AccTp(a[i+3] - b[i+3]); 45 | s += v0*v0 + v1*v1 + v2*v2 + v3*v3; 46 | } 47 | 48 | for( ; i < n; i++ ) 49 | { 50 | _AccTp v = _AccTp(a[i] - b[i]); 51 | s += v*v; 52 | } 53 | return s; 54 | } -------------------------------------------------------------------------------- /testsuite/results/systest2.nim: -------------------------------------------------------------------------------- 1 | type 2 | TGtkMyStruct* {.importc: "GTK_MyStruct", header: "iup.h", bycopy.} = object 3 | a* {.importc: "a".}: mytype 4 | b* {.importc: "b".}: mytype 5 | 6 | PGtkMyStruct* = ptr TGtkMyStruct 7 | TGtkMyStruct* {.importc: "GTK_MyStruct", header: "iup.h", bycopy.} = object 8 | a* {.importc: "a".}: mytype 9 | b* {.importc: "b".}: mytype 10 | 11 | PGtkMyStruct* = ptr TGtkMyStruct 12 | 13 | proc IupConvertXYToPos*(ih: PIhandle; x: cint; y: cint): cint {.cdecl, 14 | importc: "IupConvertXYToPos", header: "iup.h".} 15 | proc handwrittenNim(): string = 16 | "@#" 17 | 18 | const 19 | foobar* = 5 or 9 20 | 21 | type 22 | wxEdge* {.size: sizeof(cint), pure.} = enum 23 | wxLeft, wxTop, wxRight, wxBottom, wxWidth, wxHeight, wxCentre, wxCentreX, 24 | wxCentreY 25 | 26 | const 27 | wxCenter* = wxCentre 28 | 29 | ## bug #136 30 | 31 | proc bcf_float_set*(`ptr`: ptr cfloat; value: uint32_t) {.inline, cdecl.} = 32 | type 33 | INNER_C_UNION_systest2_0 {.importc: "no_name", header: "iup.h", bycopy, 34 | union.} = object 35 | i: uint32_t 36 | f: cfloat 37 | 38 | var u: INNER_C_UNION_systest2_0 39 | u.i = value 40 | `ptr`[] = u.f 41 | 42 | proc sort*(a: ptr UncheckedArray[cint]; len: cint) {.cdecl, importc: "sort", 43 | header: "iup.h".} 44 | ## bug #32 45 | 46 | proc x*(): cint {.cdecl.} = 47 | when fii: 48 | if 1: 49 | discard 50 | else: 51 | return 1 52 | 53 | const 54 | someU64* = 12333'u64 55 | someU32* = 12333'u32 56 | someI64* = 12333'i64 57 | someI32* = 12333'i32 58 | -------------------------------------------------------------------------------- /testsuite/cextras/rcl_allocator.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | //The default allocator uses malloc(), free(), calloc(), and realloc(). 4 | //It can be obtained using rcutils_get_default_allocator(). 5 | // 6 | //The allocator should be trivially copyable. 7 | //Meaning that the struct should continue to work after being assignment 8 | //copied into a new struct. 9 | //Specifically the object pointed to by the state pointer should remain valid 10 | //until all uses of the allocator have been made. 11 | //Particular care should be taken when giving an allocator to functions like 12 | //rcutils_*_init() where it is stored within another object and used later. 13 | //Developers should note that, while the fields of a const-qualified allocator 14 | //struct cannot be modified, the state of the allocator can be modified. 15 | // 16 | typedef struct rcutils_allocator_s 17 | { 18 | 19 | /// allocate: Allocate memory, given a size and the `state` pointer. 20 | void * (*allocate)(size_t size, void * state); 21 | 22 | /// deallocate: Deallocate previously allocated memory, mimicking free(). 23 | /// more lines 24 | void (* deallocate)(void * pointer, void * state); 25 | 26 | /** reallocate: Also takes the `state` pointer. */ 27 | void * (*reallocate)(void * pointer, size_t size, void * state); 28 | 29 | void * (*zero_allocate)(size_t number_of_elements, size_t size_of_element, void * state); /// zero_allocate: Allocate memory with all elements set to zero, given a number of elements and their size. 30 | 31 | /* reallocate2: Also takes the `state` pointer. */ 32 | void * (*reallocate2)(void * pointer, size_t size, void * state); 33 | 34 | /** allocator objects. */ 35 | void * state; 36 | 37 | 38 | } rcutils_allocator_t; 39 | 40 | 41 | /// Return a zero initialized allocator. 42 | /** 43 | * Note that this is an invalid allocator and should only be used as a placeholder. 44 | */ 45 | rcutils_allocator_t rcutils_get_zero_initialized_allocator(void); 46 | 47 | 48 | -------------------------------------------------------------------------------- /testsuite/results/message_type_support_struct.nim: -------------------------------------------------------------------------------- 1 | type 2 | 3 | rosidl_message_typesupport_handle_function* = proc ( 4 | a1: ptr rosidl_message_type_support_t; a2: cstring): ptr rosidl_message_type_support_t ## 5 | ## Copyright 2015-2016 Open Source Robotics Foundation, Inc. 6 | ## 7 | ## Licensed under the Apache License, Version 2.0 (the "License"); 8 | ## you may not use this file except in compliance with the License. 9 | ## You may obtain a copy of the License at 10 | ## 11 | ## http://www.apache.org/licenses/LICENSE-2.0 12 | ## 13 | ## Unless required by applicable law or agreed to in writing, software 14 | ## distributed under the License is distributed on an "AS IS" BASIS, 15 | ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | ## See the License for the specific language governing permissions and 17 | ## limitations under the License. 18 | 19 | rosidl_message_type_support_t* {.importc: "rosidl_message_type_support_t", 20 | header: "message_type_support_struct.h", 21 | bycopy.} = object ## 22 | ## Contains rosidl message type support data 23 | typesupport_identifier* {.importc: "typesupport_identifier".}: cstring ## 24 | ## String identifier for the type_support. 25 | data* {.importc: "data".}: pointer ## Pointer to the message type support library 26 | `func`* {.importc: "func".}: rosidl_message_typesupport_handle_function ## 27 | ## Pointer to the message type support handler function 28 | 29 | -------------------------------------------------------------------------------- /testsuite/results/cpp11.nim: -------------------------------------------------------------------------------- 1 | type 2 | Event* {.importcpp: "Event", header: "cpp11.hpp", bycopy.} = object 3 | 4 | 5 | proc constructEvent*(): Event {.constructor, importcpp: "Event(@)", 6 | header: "cpp11.hpp".} 7 | proc `<<`*(`out`: var ostream; t: Enum): var ostream {.importcpp: "(# << #)", 8 | header: "cpp11.hpp".} 9 | let foo* {.importcpp: "foo", header: "cpp11.hpp".}: Event 10 | 11 | type 12 | ConstexprConstructor* {.importcpp: "ConstexprConstructor", 13 | header: "cpp11.hpp", bycopy.} = object ## deprecated("getCenter() was renamed to getResourceDepot()") 14 | 15 | 16 | proc constructConstexprConstructor*(i: cint = 1): ConstexprConstructor {. 17 | constructor, importcpp: "ConstexprConstructor(@)", header: "cpp11.hpp".} 18 | ## list initialization, issue #163 19 | 20 | let list_init* {.importcpp: "list_init", header: "cpp11.hpp".}: cint 21 | 22 | type 23 | NonCopy* {.importcpp: "NonCopy", header: "cpp11.hpp", bycopy.} = object 24 | 25 | 26 | proc constructNonCopy*(): NonCopy {.constructor, importcpp: "NonCopy(@)", 27 | header: "cpp11.hpp".} 28 | proc destroyNonCopy*(this: var NonCopy) {.importcpp: "#.~NonCopy()", 29 | header: "cpp11.hpp".} 30 | type 31 | VirtClass* {.importcpp: "VirtClass", header: "cpp11.hpp", bycopy.} = object 32 | 33 | 34 | proc constructVirtClass*(): VirtClass {.constructor, importcpp: "VirtClass(@)", 35 | header: "cpp11.hpp".} 36 | proc destroyVirtClass*(this: var VirtClass) {.importcpp: "#.~VirtClass()", 37 | header: "cpp11.hpp".} 38 | proc pureFunction*(this: var VirtClass) {.importcpp: "pureFunction", 39 | header: "cpp11.hpp".} 40 | proc implementedFunction*(this: var VirtClass) {. 41 | importcpp: "implementedFunction", header: "cpp11.hpp".} 42 | proc concreteFunction*(this: var VirtClass) {.importcpp: "concreteFunction", 43 | header: "cpp11.hpp".} 44 | let my_var* {.importcpp: "VarNS::my_var", header: "cpp11.hpp".}: cint 45 | -------------------------------------------------------------------------------- /testsuite/results/i2c_master.nim: -------------------------------------------------------------------------------- 1 | ## 2 | ## SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD 3 | ## 4 | ## SPDX-License-Identifier: Apache-2.0 5 | ## 6 | 7 | import 8 | esp_err, driver/i2c_types, hal/gpio_types 9 | 10 | ## 11 | ## @brief I2C master bus specific configurations 12 | ## 13 | 14 | type 15 | INNER_C_STRUCT_i2c_master_3* {.bycopy.} = object 16 | enable_internal_pullup* {.bitsize: 1.}: uint32_t 17 | ## !< Enable internal pullups. Note: This is not strong enough to pullup buses under high-speed frequency. Recommend proper external pull-up if possible 18 | allow_pd* {.bitsize: 1.}: uint32_t 19 | ## !< If set, the driver will backup/restore the I2C registers before/after entering/exist sleep mode. 20 | ## By this approach, the system can power off I2C's power domain. 21 | ## This can save power, but at the expense of more RAM being consumed 22 | 23 | i2c_master_bus_config_t* {.bycopy.} = object 24 | i2c_port*: i2c_port_num_t 25 | ## !< I2C port number, `-1` for auto selecting, (not include LP I2C instance) 26 | sda_io_num*: gpio_num_t 27 | ## !< GPIO number of I2C SDA signal, pulled-up internally 28 | scl_io_num*: gpio_num_t 29 | ## !< GPIO number of I2C SCL signal, pulled-up internally 30 | anon2_clk_source*: i2c_clock_source_t 31 | ## !< Clock source of I2C master bus 32 | when SOC_LP_I2C_SUPPORTED: 33 | var lp_source_clk*: lp_i2c_clock_source_t 34 | ## !< LP_UART source clock selection 35 | glitch_ignore_cnt*: uint8_t 36 | ## !< If the glitch period on the line is less than this value, it can be filtered out, typically value is 7 (unit: I2C module clock cycle) 37 | intr_priority*: cint 38 | ## !< I2C interrupt priority, if set to 0, driver will select the default priority (1,2,3). 39 | trans_queue_depth*: csize_t 40 | ## !< Depth of internal transfer queue, increase this value can support more transfers pending in the background, only valid in asynchronous transaction. (Typically max_device_num * per_transaction) 41 | flags*: INNER_C_STRUCT_i2c_master_3 42 | ## !< I2C master config flags 43 | 44 | 45 | const 46 | I2C_DEVICE_ADDRESS_NOT_USED* = (0xffff) ## !< Skip carry address bit in driver transmit and receive 47 | -------------------------------------------------------------------------------- /testsuite/cextras/rcl_error_macros.h: -------------------------------------------------------------------------------- 1 | #pragma c2nim strict 2 | #pragma c2nim header 3 | 4 | #pragma c2nim reorderTypes 5 | 6 | /// The maximum length a formatted number is allowed to have. 7 | #define RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH 20 /* "18446744073709551615"*/ 8 | 9 | /// The maximum number of formatting characters allowed. 10 | #define RCUTILS_ERROR_FORMATTING_CHARACTERS 6 /* ', at ' + ':'*/ 11 | 12 | /// The maximum formatted string length. 13 | #define RCUTILS_ERROR_MESSAGE_MAX_LENGTH 1024 14 | 15 | /// The maximum length for user defined error message 16 | /** 17 | */ 18 | #define RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH 768 19 | 20 | /// The calculated maximum length for the filename. 21 | /** 22 | */ 23 | #define RCUTILS_ERROR_STATE_FILE_MAX_LENGTH ( RCUTILS_ERROR_MESSAGE_MAX_LENGTH - RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH - RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH - RCUTILS_ERROR_FORMATTING_CHARACTERS - 1) 24 | 25 | /// Struct wrapping a fixed-size c string used for returning the formatted error string. 26 | typedef struct rcutils_error_string_s 27 | { 28 | /// The fixed-size C string used for returning the formatted error string. 29 | char str[1024]; 30 | } rcutils_error_string_t; 31 | 32 | /// Struct which encapsulates the error state set by RCUTILS_SET_ERROR_MSG(). 33 | typedef struct rcutils_error_state_s 34 | { 35 | /// User message storage, limited to RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH characters. 36 | char message[768]; 37 | /// File name, limited to what's left from RCUTILS_ERROR_STATE_MAX_SIZE characters 38 | /// after subtracting storage for others. 39 | char file[( 1024 - 768 - 20 /* "18446744073709551615"*/ - 6 /* ', at ' + ':'*/ - 1)]; 40 | /// Line number of error. 41 | uint64_t line_number; 42 | } rcutils_error_state_t; 43 | 44 | 45 | 46 | /// Forces initialization of thread-local storage if called in a newly created thread. 47 | /** 48 | * If this function is not called beforehand, then the first time the error 49 | */ 50 | __attribute__ ((visibility("default"))) 51 | __attribute__((warn_unused_result)) 52 | rcutils_ret_t 53 | rcutils_initialize_error_handling_thread_local_storage(rcutils_allocator_t allocator); 54 | 55 | /// Set the error message, as well as the file and line on which it occurred. 56 | void 57 | rcutils_set_error_state(const char * error_string, const char * file, size_t line_number); 58 | -------------------------------------------------------------------------------- /testsuite/cppkeepbodies/tsyncpoints.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | this makes no sense here; 4 | 5 | void fn(int x, int y) { 6 | cout << "blag"; 7 | } 8 | 9 | more stuff that is wrong; 10 | 11 | void fn2(int x, int y) { 12 | same shit in function; 13 | cout << "blag"; 14 | unknown; 15 | } 16 | 17 | namespace { 18 | struct Double 19 | { 20 | static_assert(std::numeric_limits::is_iec559 21 | && std::numeric_limits::digits == 53 22 | && std::numeric_limits::max_exponent == 1024, 23 | "IEEE-754 double-precision implementation required"); 24 | 25 | using value_type = double; 26 | using bits_type = uint64_t; 27 | 28 | static constexpr int32_t SignificandSize = std::numeric_limits::digits; // = p (includes the hidden bit) 29 | static constexpr int32_t ExponentBias = std::numeric_limits::max_exponent - 1 + (SignificandSize - 1); 30 | static constexpr bits_type MaxIeeeExponent = bits_type{2 * std::numeric_limits::max_exponent - 1}; 31 | static constexpr bits_type HiddenBit = bits_type{1} << (SignificandSize - 1); // = 2^(p-1) 32 | static constexpr bits_type SignificandMask = HiddenBit - 1; // = 2^(p-1) - 1 33 | static constexpr bits_type ExponentMask = MaxIeeeExponent << (SignificandSize - 1); 34 | static constexpr bits_type SignMask = ~(~bits_type{0} >> 1); 35 | 36 | bits_type bits; 37 | 38 | explicit Double(bits_type bits_) : bits(bits_) {} 39 | explicit Double(value_type value) : bits(ReinterpretBits(value)) {} 40 | 41 | bits_type PhysicalSignificand() const { 42 | return bits & SignificandMask; 43 | } 44 | 45 | bits_type PhysicalExponent() const { 46 | return (bits & ExponentMask) >> (SignificandSize - 1); 47 | } 48 | 49 | bool IsFinite() const { 50 | return (bits & ExponentMask) != ExponentMask; 51 | } 52 | 53 | bool IsInf() const { 54 | return (bits & ExponentMask) == ExponentMask && (bits & SignificandMask) == 0; 55 | } 56 | 57 | bool IsNaN() const { 58 | return (bits & ExponentMask) == ExponentMask && (bits & SignificandMask) != 0; 59 | } 60 | 61 | bool IsZero() const { 62 | return (bits & ~SignMask) == 0; 63 | } 64 | 65 | bool SignBit() const { 66 | return (bits & SignMask) != 0; 67 | } 68 | 69 | this does not parse; 70 | }; 71 | } 72 | -------------------------------------------------------------------------------- /testsuite/tests/i2c_master.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #anonymousAsFields 8 | 9 | 10 | #pragma once 11 | 12 | #include 13 | #include "esp_err.h" 14 | #include "driver/i2c_types.h" 15 | #include "hal/gpio_types.h" 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | /** 22 | * @brief I2C master bus specific configurations 23 | */ 24 | typedef struct { 25 | i2c_port_num_t i2c_port; /*!< I2C port number, `-1` for auto selecting, (not include LP I2C instance) */ 26 | gpio_num_t sda_io_num; /*!< GPIO number of I2C SDA signal, pulled-up internally */ 27 | gpio_num_t scl_io_num; /*!< GPIO number of I2C SCL signal, pulled-up internally */ 28 | union { 29 | i2c_clock_source_t clk_source; /*!< Clock source of I2C master bus */ 30 | #if SOC_LP_I2C_SUPPORTED 31 | lp_i2c_clock_source_t lp_source_clk; /*!< LP_UART source clock selection */ 32 | #endif 33 | }; 34 | uint8_t glitch_ignore_cnt; /*!< If the glitch period on the line is less than this value, it can be filtered out, typically value is 7 (unit: I2C module clock cycle)*/ 35 | int intr_priority; /*!< I2C interrupt priority, if set to 0, driver will select the default priority (1,2,3). */ 36 | size_t trans_queue_depth; /*!< Depth of internal transfer queue, increase this value can support more transfers pending in the background, only valid in asynchronous transaction. (Typically max_device_num * per_transaction)*/ 37 | struct { 38 | uint32_t enable_internal_pullup: 1; /*!< Enable internal pullups. Note: This is not strong enough to pullup buses under high-speed frequency. Recommend proper external pull-up if possible */ 39 | uint32_t allow_pd: 1; /*!< If set, the driver will backup/restore the I2C registers before/after entering/exist sleep mode. 40 | By this approach, the system can power off I2C's power domain. 41 | This can save power, but at the expense of more RAM being consumed */ 42 | } flags; /*!< I2C master config flags */ 43 | } i2c_master_bus_config_t; 44 | 45 | #define I2C_DEVICE_ADDRESS_NOT_USED (0xffff) /*!< Skip carry address bit in driver transmit and receive */ 46 | 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | -------------------------------------------------------------------------------- /testsuite/tests/nested.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | template 6 | class vector; // so that vector::iterator is maped to vectoriterator[T] and not just iterator[T] 7 | 8 | template 9 | class Foo { 10 | public: 11 | typedef int Int; 12 | typedef T BaseType; 13 | typedef T* BaseTypePtr; 14 | typedef T BasTypeArray[3]; 15 | typedef typename std::vector Vector; 16 | typedef typename std::vector::iterator Iterator; 17 | 18 | Foo(){}; 19 | 20 | //~Foo(); // this cannot be translated for now as Foo is generic 21 | 22 | typedef enum { 23 | ENUM1, ENUM2 24 | } DeepEnum; 25 | 26 | enum { 27 | MIN_DIM=5, MAX_DIM=10 28 | }; 29 | 30 | int someArray[MAX_DIM]; 31 | 32 | typedef struct { 33 | void methodeNestedStruct(){}; 34 | int i, j; 35 | } NestedStruct; 36 | 37 | 38 | typedef class irrelevantTag { 39 | public: 40 | typedef enum { 41 | ENUM3, ENUM4 42 | } VeryDeepEnum; 43 | 44 | void methodeNestedClass(){}; 45 | 46 | int i, j; 47 | } NestedClass; 48 | 49 | template 50 | class OtherNestedClass { 51 | public: 52 | typedef enum { 53 | ENUM5, ENUM6 54 | } VeryDeepEnum; 55 | T1 val1; 56 | T2 val2; 57 | 58 | // The following constructors and destructors cannot be translated 59 | // for now (both child and parent are generic) 60 | //OtherNestedClass(); 61 | //OtherNestedClass(int i); 62 | //~OtherNestedClass(); 63 | 64 | void methodeNestedClass(){}; 65 | }; 66 | 67 | //void method(NestedClass & n, NestedStruct* b, OtherNestedClass * c); 68 | // OtherNestedClass is still translated to FooOtherNestedClass[string, string], 69 | // missing T as first generic argument 70 | 71 | }; 72 | 73 | template 74 | class Bar{ 75 | public: 76 | typedef typename Foo::NestedStruct MyStruct; 77 | 78 | typedef class { 79 | public: 80 | int val; 81 | 82 | } NestedClass; 83 | 84 | template 85 | class NestedClass2 { 86 | public: 87 | T1 val; 88 | 89 | //NestedClass2(); 90 | }; 91 | }; 92 | 93 | 94 | class NoTemplate { 95 | public: 96 | typedef enum { 97 | ENUM7, ENUM8 98 | } DeepEnum; 99 | 100 | class NestedClass2 { 101 | public: 102 | int val; 103 | NestedClass2(){}; 104 | NestedClass2(int i){}; 105 | }; 106 | }; 107 | -------------------------------------------------------------------------------- /testsuite/results/tsyncpoints.nim: -------------------------------------------------------------------------------- 1 | ## !!!Ignored construct: this makes no sense here ; 2 | ## Error: token expected: ; but got: [identifier]!!! 3 | 4 | proc fn*(x: cint; y: cint) = 5 | cout shl "blag" 6 | 7 | ## !!!Ignored construct: more stuff that is wrong ; 8 | ## Error: token expected: ; but got: [identifier]!!! 9 | 10 | proc fn2*(x: cint; y: cint) = 11 | ## !!!Ignored construct: same shit in function ; 12 | ## Error: token expected: ; but got: [identifier]!!! 13 | cout shl "blag" 14 | unknown 15 | 16 | type 17 | Double* {.bycopy.} = object 18 | bits*: bits_type 19 | does*: this 20 | parse*: `not` 21 | 22 | 23 | ## !!!Ignored construct: static_assert ( std :: numeric_limits < double > :: is_iec559 && std :: numeric_limits < double > :: digits == 53 && std :: numeric_limits < double > :: max_exponent == 1024 , IEEE-754 double-precision implementation required ) ; 24 | ## Error: token expected: ) but got: ::!!! 25 | 26 | type 27 | value_type* = cdouble 28 | bits_type* = uint64_t 29 | 30 | const ## = p (includes the hidden bit) 31 | SignificandSize*: int32_t = digits[value_type] 32 | 33 | const 34 | ExponentBias*: int32_t = max_exponent[value_type] - 1 + (SignificandSize - 1) 35 | 36 | const 37 | MaxIeeeExponent*: bits_type = bits_type(2 * max_exponent[value_type] - 1) 38 | 39 | const ## = 2^(p-1) 40 | HiddenBit*: bits_type = bits_type(1) shl (SignificandSize - 1) 41 | 42 | const ## = 2^(p-1) - 1 43 | SignificandMask*: bits_type = HiddenBit - 1 44 | 45 | const 46 | ExponentMask*: bits_type = MaxIeeeExponent shl (SignificandSize - 1) 47 | 48 | const 49 | SignMask*: bits_type = not (not bits_type(0) shr 1) 50 | 51 | proc constructDouble*(bits_: bits_type): Double {.constructor.} = 52 | discard 53 | 54 | proc constructDouble*(value: value_type): Double {.constructor.} = 55 | discard 56 | 57 | proc PhysicalSignificand*(this: Double): bits_type {.noSideEffect.} = 58 | return bits and SignificandMask 59 | 60 | proc PhysicalExponent*(this: Double): bits_type {.noSideEffect.} = 61 | return (bits and ExponentMask) shr (SignificandSize - 1) 62 | 63 | proc IsFinite*(this: Double): bool {.noSideEffect.} = 64 | return (bits and ExponentMask) != ExponentMask 65 | 66 | proc IsInf*(this: Double): bool {.noSideEffect.} = 67 | return (bits and ExponentMask) == ExponentMask and 68 | (bits and SignificandMask) == 0 69 | 70 | proc IsNaN*(this: Double): bool {.noSideEffect.} = 71 | return (bits and ExponentMask) == ExponentMask and 72 | (bits and SignificandMask) != 0 73 | 74 | proc IsZero*(this: Double): bool {.noSideEffect.} = 75 | return (bits and not SignMask) == 0 76 | 77 | proc SignBit*(this: Double): bool {.noSideEffect.} = 78 | return (bits and SignMask) != 0 79 | -------------------------------------------------------------------------------- /testsuite/results/rcl_allocator.nim: -------------------------------------------------------------------------------- 1 | type 2 | 3 | rcutils_allocator_t* {.importc: "rcutils_allocator_t", 4 | header: "rcl_allocator.h", bycopy.} = object ## 5 | ## 6 | ## The default allocator uses malloc(), free(), calloc(), and realloc(). 7 | ## It can be obtained using rcutils_get_default_allocator(). 8 | ## 9 | ## The allocator should be trivially copyable. 10 | ## Meaning that the struct should continue to work after being assignment 11 | ## copied into a new struct. 12 | ## Specifically the object pointed to by the state pointer should remain valid 13 | ## until all uses of the allocator have been made. 14 | ## Particular care should be taken when giving an allocator to functions like 15 | ## rcutils_*_init() where it is stored within another object and used later. 16 | ## Developers should note that, while the fields of a const-qualified allocator 17 | ## struct cannot be modified, the state of the allocator can be modified. 18 | ## 19 | allocate* {.importc: "allocate".}: proc (size: csize_t; state: pointer): pointer ## 20 | ## allocate: Allocate memory, given a size and the `state` pointer. 21 | deallocate* {.importc: "deallocate".}: proc (pointer: pointer; 22 | state: pointer) ## deallocate: Deallocate previously allocated memory, mimicking free(). 23 | ## more lines 24 | reallocate* {.importc: "reallocate".}: proc (pointer: pointer; 25 | size: csize_t; state: pointer): pointer ## reallocate: Also takes the `state` pointer. 26 | zero_allocate* {.importc: "zero_allocate".}: proc ( 27 | number_of_elements: csize_t; size_of_element: csize_t; state: pointer): pointer ## 28 | ## zero_allocate: Allocate memory with all elements set to zero, given a number of elements and their size. 29 | reallocate2* {.importc: "reallocate2".}: proc (pointer: pointer; 30 | size: csize_t; state: pointer): pointer ## reallocate2: Also takes the `state` pointer. 31 | state* {.importc: "state".}: pointer ## allocator objects. 32 | 33 | 34 | 35 | proc rcutils_get_zero_initialized_allocator*(): rcutils_allocator_t {. 36 | importc: "rcutils_get_zero_initialized_allocator", header: "rcl_allocator.h".} 37 | ## 38 | ## Return a zero initialized allocator. 39 | ## 40 | ## Note that this is an invalid allocator and should only be used as a placeholder. 41 | ## -------------------------------------------------------------------------------- /testsuite/tester.nim: -------------------------------------------------------------------------------- 1 | # Small program that runs the test cases 2 | 3 | import strutils, os, parseopt 4 | 5 | const 6 | dotslash = when defined(posix): "./" else: "" 7 | 8 | c2nimCmd = dotslash & "c2nim $#" 9 | cpp2nimCmd = dotslash & "c2nim --cpp $#" 10 | cpp2nimCmdKeepBodies = dotslash & "c2nim --cpp --keepBodies $#" 11 | hpp2nimCmd = dotslash & "c2nim --cpp --header --cppbindstatic $#" 12 | c2nimExtrasCmd = dotslash & "c2nim --stdints --strict --header --reordercomments --mergeblocks --render:reindentlongcomments --def:RCL_PUBLIC='__attribute__ (())' --def:RCL_WARN_UNUSED='__attribute__ (())' --def:'RCL_ALIGNAS(N)=__attribute__((align))' --render:extranewlines $#" 13 | dir = "testsuite/" 14 | usage = """ 15 | c2nim test runner 16 | Usage: tester testnames [options] 17 | Runs all tests by default without any arguments given. 18 | If testnames are given, all othere tests will be skipped. Testnames are the 19 | test file names without extension. 20 | Options: 21 | -h --help Shows this help 22 | --overwrite Overwrite the test results with the current results 23 | """ 24 | 25 | var 26 | failures = 0 27 | exitEarly = false 28 | infiles = newSeq[string](0) 29 | diffTool = "diff -uNdr" 30 | overwrite = false 31 | 32 | for kind, key, val in getopt(): 33 | case kind 34 | of cmdArgument: 35 | infiles.add key 36 | of cmdLongOption, cmdShortOption: 37 | case key.normalize 38 | of "help", "h": 39 | stdout.write(usage) 40 | exitEarly = true 41 | of "diff", "d": 42 | diffTool = val 43 | of "overwrite": 44 | overwrite = true 45 | else: 46 | stdout.writeLine("[Error] unknown option: " & key) 47 | 48 | proc exec(cmd: string) = 49 | if execShellCmd(cmd) != 0: quit("FAILURE: " & cmd) 50 | 51 | proc test(t, cmd, origin: string) = 52 | let (_, name, _) = splitFile(t) 53 | if infiles.len() > 0 and not (name in infiles): 54 | return 55 | echo "TEST: ", name 56 | exec(cmd % t) 57 | let nimFile = name & ".nim" 58 | if readFile(dir & origin / nimFile) != readFile(dir & "results" / nimFile): 59 | echo "FAILURE: files differ: ", nimFile 60 | discard execShellCmd(diffTool & " " & dir & "results" / nimFile & " " & dir & origin / nimFile) 61 | failures += 1 62 | if overwrite: 63 | copyFile(dir & origin / nimFile, dir & "results" / nimFile) 64 | else: 65 | echo "SUCCESS: files identical: ", nimFile 66 | 67 | if not exitEarly: 68 | exec("nim c c2nim.nim") 69 | for t in walkFiles(dir & "tests/*.c"): 70 | test(t, c2nimCmd, "tests") 71 | for t in walkFiles(dir & "tests/*.h"): 72 | test(t, c2nimCmd, "tests") 73 | for t in walkFiles(dir & "tests/*.cpp"): 74 | test(t, cpp2nimCmd, "tests") 75 | for t in walkFiles(dir & "tests/*.hpp"): 76 | test(t, hpp2nimCmd, "tests") 77 | 78 | for t in walkFiles(dir & "cppkeepbodies/*.cpp"): 79 | test(t, cpp2nimCmdKeepBodies, "cppkeepbodies") 80 | for t in walkFiles(dir & "cextras/*.h"): 81 | test(t, c2nimExtrasCmd, "cextras") 82 | 83 | if failures > 0: quit($failures & " failures occurred.") 84 | -------------------------------------------------------------------------------- /testsuite/results/rcl_error_macros.nim: -------------------------------------------------------------------------------- 1 | const 2 | RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH* = 20 ## 3 | ## The maximum length a formatted number is allowed to have. 4 | RCUTILS_ERROR_FORMATTING_CHARACTERS* = 6 ## The maximum number of formatting characters allowed. 5 | RCUTILS_ERROR_MESSAGE_MAX_LENGTH* = 1024 ## The maximum formatted string length. 6 | RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH* = 768 ## The maximum length for user defined error message 7 | ## 8 | ## 9 | 10 | type 11 | 12 | rcutils_error_string_t* {.importc: "rcutils_error_string_t", 13 | header: "rcl_error_macros.h", bycopy.} = object ## 14 | ## Struct wrapping a fixed-size c string used for returning the formatted error string. 15 | str* {.importc: "str".}: array[1024, char] ## The fixed-size C string used for returning the formatted error string. 16 | 17 | 18 | rcutils_error_state_t* {.importc: "rcutils_error_state_t", 19 | header: "rcl_error_macros.h", bycopy.} = object ## 20 | ## Struct which encapsulates the error state set by RCUTILS_SET_ERROR_MSG(). 21 | message* {.importc: "message".}: array[768, char] ## 22 | ## User message storage, limited to RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH characters. 23 | file* {.importc: "file".}: array[(1024 - 768 - 20 - 6 - 1), char] ## 24 | ## File name, limited to what's left from RCUTILS_ERROR_STATE_MAX_SIZE characters 25 | ## after subtracting storage for others. 26 | line_number* {.importc: "line_number".}: uint64 ## 27 | ## Line number of error. 28 | 29 | 30 | const 31 | RCUTILS_ERROR_STATE_FILE_MAX_LENGTH* = (RCUTILS_ERROR_MESSAGE_MAX_LENGTH - 32 | RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH - 33 | RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH - 34 | RCUTILS_ERROR_FORMATTING_CHARACTERS - 35 | 1) ## The calculated maximum length for the filename. 36 | ## 37 | ## 38 | 39 | 40 | proc rcutils_initialize_error_handling_thread_local_storage*( 41 | allocator: rcutils_allocator_t): rcutils_ret_t {. 42 | importc: "rcutils_initialize_error_handling_thread_local_storage", 43 | header: "rcl_error_macros.h".} 44 | ## Forces initialization of thread-local storage if called in a newly created thread. 45 | ## 46 | ## If this function is not called beforehand, then the first time the error 47 | ## 48 | 49 | proc rcutils_set_error_state*(error_string: cstring; file: cstring; 50 | line_number: csize_t) {. 51 | importc: "rcutils_set_error_state", header: "rcl_error_macros.h".} 52 | ## 53 | ## Set the error message, as well as the file and line on which it occurred. -------------------------------------------------------------------------------- /testsuite/results/nested.nim: -------------------------------------------------------------------------------- 1 | ## using statement 2 | 3 | discard "forward decl of vector" 4 | type 5 | Foo*[T] {.importcpp: "Foo<\'0>", header: "nested.hpp", bycopy.} = object 6 | someArray* {.importc: "someArray".}: array[FooMAX_DIM, cint] 7 | 8 | FooInt* = cint 9 | FooBaseType*[T] = T 10 | FooBaseTypePtr*[T] = ptr T 11 | FooBasTypeArray*[T] = array[3, T] 12 | FooVector*[T] = vector[T] 13 | FooIterator*[T] = vectoriterator[T] 14 | 15 | proc constructFoo*[T](): Foo[T] {.constructor, importcpp: "Foo<\'*0>(@)", 16 | header: "nested.hpp".} 17 | type 18 | FooDeepEnum* {.size: sizeof(cint).} = enum 19 | ENUM1, ENUM2 20 | 21 | 22 | const 23 | FooMIN_DIM* = 5 24 | FooMAX_DIM* = 10 25 | 26 | proc methodeNestedStruct*[T](this: var FooNestedStruct[T]) {. 27 | importcpp: "methodeNestedStruct", header: "nested.hpp".} 28 | type 29 | FooNestedClassVeryDeepEnum* {.size: sizeof(cint).} = enum 30 | ENUM3, ENUM4 31 | 32 | 33 | proc methodeNestedClass*[T](this: var FooNestedClass[T]) {. 34 | importcpp: "methodeNestedClass", header: "nested.hpp".} 35 | type 36 | FooNestedStruct*[T] {.importcpp: "Foo<\'0>::NestedStruct", 37 | header: "nested.hpp", bycopy.} = object 38 | i* {.importc: "i".}: cint 39 | j* {.importc: "j".}: cint 40 | 41 | FooNestedClass*[T] {.importcpp: "Foo<\'0>::NestedClass", header: "nested.hpp", 42 | bycopy.} = object 43 | i* {.importc: "i".}: cint 44 | j* {.importc: "j".}: cint 45 | 46 | FooOtherNestedClass*[T; T1; T2] {.importcpp: "Foo<\'0>::OtherNestedClass<\'1,\'2>", 47 | header: "nested.hpp", bycopy.} = object 48 | val1* {.importc: "val1".}: T1 49 | val2* {.importc: "val2".}: T2 ## The following constructors and destructors cannot be translated 50 | ## for now (both child and parent are generic) 51 | ## OtherNestedClass(); 52 | ## OtherNestedClass(int i); 53 | ## ~OtherNestedClass(); 54 | 55 | FooOtherNestedClassVeryDeepEnum* {.size: sizeof(cint).} = enum 56 | ENUM5, ENUM6 57 | 58 | 59 | proc methodeNestedClass*[T; T1; T2](this: var FooOtherNestedClass[T, T1, T2]) {. 60 | importcpp: "methodeNestedClass", header: "nested.hpp".} 61 | type 62 | Bar*[T; I: static[cint]] {.importcpp: "Bar<\'0,\'1>", header: "nested.hpp", 63 | bycopy.} = object 64 | 65 | BarMyStruct*[T] = FooNestedStruct[T] 66 | BarNestedClass*[T; I: static[cint]] {.importcpp: "Bar<\'0,\'1>::NestedClass", 67 | header: "nested.hpp", bycopy.} = object 68 | val* {.importc: "val".}: cint 69 | 70 | BarNestedClass2*[T; I: static[cint]; T1] {. 71 | importcpp: "Bar<\'0,\'1>::NestedClass2<\'2>", header: "nested.hpp", bycopy.} = object 72 | val* {.importc: "val".}: T1 ## NestedClass2(); 73 | 74 | NoTemplate* {.importcpp: "NoTemplate", header: "nested.hpp", bycopy.} = object 75 | 76 | NoTemplateDeepEnum* {.size: sizeof(cint), importcpp: "NoTemplate::DeepEnum", 77 | header: "nested.hpp".} = enum 78 | ENUM7, ENUM8 79 | 80 | 81 | type 82 | NoTemplateNestedClass2* {.importcpp: "NoTemplate::NestedClass2", 83 | header: "nested.hpp", bycopy.} = object 84 | val* {.importc: "val".}: cint 85 | 86 | 87 | proc constructNoTemplateNestedClass2*(): NoTemplateNestedClass2 {.constructor, 88 | importcpp: "NoTemplate::NestedClass2(@)", header: "nested.hpp".} 89 | proc constructNoTemplateNestedClass2*(i: cint): NoTemplateNestedClass2 {. 90 | constructor, importcpp: "NoTemplate::NestedClass2(@)", header: "nested.hpp".} -------------------------------------------------------------------------------- /testsuite/cextras/rcl_context.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Open Source Robotics Foundation, Inc. 2 | // 3 | 4 | /// @file 5 | 6 | #ifndef RCL__CONTEXT_H_ 7 | #define RCL__CONTEXT_H_ 8 | 9 | #ifdef __cplusplus 10 | extern "C" 11 | { 12 | #endif 13 | 14 | #include "rmw/init.h" 15 | 16 | #include "rcl/allocator.h" 17 | #include "rcl/arguments.h" 18 | #include "rcl/init_options.h" 19 | #include "rcl/macros.h" 20 | #include "rcl/types.h" 21 | #include "rcl/visibility_control.h" 22 | 23 | /// A unique ID per context instance. 24 | typedef uint64_t rcl_context_instance_id_t; 25 | 26 | typedef struct rcl_context_impl_s rcl_context_impl_t; 27 | 28 | /// Encapsulates the non-global state of an init/shutdown cycle. 29 | /** 30 | * The context is used in the creation of top level entities like nodes and 31 | * guard conditions, as well as to shutdown a specific instance of init. 32 | * 33 | */ 34 | typedef struct rcl_context_s 35 | { 36 | /// Global arguments for all nodes which share this context. 37 | /** Typically generated by the parsing of argc/argv in rcl_init(). */ 38 | rcl_arguments_t global_arguments; 39 | 40 | /// Implementation specific pointer. 41 | rcl_context_impl_t * impl; 42 | 43 | // The assumption that this is big enough for an atomic_uint_least64_t is 44 | // In most cases it should just be a plain uint64_t. 45 | /// @cond Doxygen_Suppress 46 | #if !defined(RCL_CONTEXT_ATOMIC_INSTANCE_ID_STORAGE_SIZE) 47 | #define RCL_CONTEXT_ATOMIC_INSTANCE_ID_STORAGE_SIZE sizeof(uint_least64_t) 48 | #endif 49 | /// @endcond 50 | /// Private storage for instance ID atomic. 51 | /** 52 | * Accessing the instance id should be done using the function 53 | */ 54 | RCL_ALIGNAS(8) uint8_t instance_id_storage[RCL_CONTEXT_ATOMIC_INSTANCE_ID_STORAGE_SIZE]; 55 | } rcl_context_t; 56 | 57 | /// Return a zero initialization context object. 58 | RCL_PUBLIC 59 | RCL_WARN_UNUSED 60 | rcl_context_t 61 | rcl_get_zero_initialized_context(void); 62 | 63 | /// Finalize a context. 64 | /** 65 | * 66 | */ 67 | RCL_PUBLIC 68 | RCL_WARN_UNUSED 69 | rcl_ret_t 70 | rcl_context_fini(rcl_context_t * context); 71 | 72 | /// Return the init options used during initialization for this context. 73 | /** 74 | * 75 | * \param[in] context object from which the init options should be retrieved 76 | * \return pointer to the the init options, or 77 | * \return `NULL` if there was an error 78 | */ 79 | RCL_PUBLIC 80 | RCL_WARN_UNUSED 81 | const rcl_init_options_t * 82 | rcl_context_get_init_options(const rcl_context_t * context); 83 | 84 | /// Returns an unsigned integer that is unique to the given context, or `0` if invalid. 85 | /** 86 | */ 87 | RCL_PUBLIC 88 | RCL_WARN_UNUSED 89 | rcl_context_instance_id_t 90 | rcl_context_get_instance_id(const rcl_context_t * context); 91 | 92 | /// Returns the context domain id. 93 | /** 94 | */ 95 | RCL_PUBLIC 96 | RCL_WARN_UNUSED 97 | rcl_ret_t 98 | rcl_context_get_domain_id(rcl_context_t * context, size_t * domain_id); 99 | 100 | /// Return `true` if the given context is currently valid, otherwise `false`. 101 | /** 102 | * If context is `NULL`, then `false` is returned. 103 | * If context is zero-initialized, then `false` is returned. 104 | * If context is uninitialized, then it is undefined behavior. 105 | * 106 | */ 107 | RCL_PUBLIC 108 | RCL_WARN_UNUSED 109 | bool 110 | rcl_context_is_valid(const rcl_context_t * context); 111 | 112 | /// Return pointer to the rmw context if the given context is currently valid, otherwise `NULL`. 113 | /** 114 | * If context is `NULL`, then `NULL` is returned. 115 | * If context is zero-initialized, then `NULL` is returned. 116 | * If context is uninitialized, then it is undefined behavior. 117 | * 118 | */ 119 | RCL_PUBLIC 120 | RCL_WARN_UNUSED 121 | rmw_context_t * 122 | rcl_context_get_rmw_context(rcl_context_t * context); 123 | 124 | #ifdef __cplusplus 125 | } 126 | #endif 127 | 128 | #endif // RCL__CONTEXT_H_ 129 | -------------------------------------------------------------------------------- /compiler/idents.nim: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # The Nim Compiler 4 | # (c) Copyright 2012 Andreas Rumpf 5 | # 6 | # See the file "copying.txt", included in this 7 | # distribution, for details about the copyright. 8 | # 9 | 10 | # Identifier handling 11 | # An identifier is a shared immutable string that can be compared by its 12 | # id. This module is essential for the compiler's performance. 13 | 14 | import 15 | hashes, strutils, wordrecg 16 | 17 | type 18 | TIdObj* = object of RootObj 19 | id*: int # unique id; use this for comparisons and not the pointers 20 | 21 | PIdObj* = ref TIdObj 22 | PIdent* = ref TIdent 23 | TIdent*{.acyclic.} = object of TIdObj 24 | s*: string 25 | next*: PIdent # for hash-table chaining 26 | h*: Hash # hash value of s 27 | 28 | IdentCache* = ref object 29 | buckets: array[0..4096 * 2 - 1, PIdent] 30 | wordCounter: int 31 | idAnon*, idDelegator*, emptyIdent*: PIdent 32 | 33 | proc resetIdentCache*() = discard 34 | 35 | proc cmpIgnoreStyle*(a, b: cstring, blen: int): int = 36 | if a[0] != b[0]: return 1 37 | var i = 0 38 | var j = 0 39 | result = 1 40 | while j < blen: 41 | while a[i] == '_': inc(i) 42 | while b[j] == '_': inc(j) 43 | # tolower inlined: 44 | var aa = a[i] 45 | var bb = b[j] 46 | if aa >= 'A' and aa <= 'Z': aa = chr(ord(aa) + (ord('a') - ord('A'))) 47 | if bb >= 'A' and bb <= 'Z': bb = chr(ord(bb) + (ord('a') - ord('A'))) 48 | result = ord(aa) - ord(bb) 49 | if (result != 0) or (aa == '\0'): break 50 | inc(i) 51 | inc(j) 52 | if result == 0: 53 | if a[i] != '\0': result = 1 54 | 55 | proc cmpExact(a, b: cstring, blen: int): int = 56 | var i = 0 57 | var j = 0 58 | result = 1 59 | while j < blen: 60 | var aa = a[i] 61 | var bb = b[j] 62 | result = ord(aa) - ord(bb) 63 | if (result != 0) or (aa == '\0'): break 64 | inc(i) 65 | inc(j) 66 | if result == 0: 67 | if a[i] != '\0': result = 1 68 | 69 | proc getIdent*(ic: IdentCache; identifier: cstring, length: int, h: Hash): PIdent = 70 | var idx = h and high(ic.buckets) 71 | result = ic.buckets[idx] 72 | var last: PIdent = nil 73 | var id = 0 74 | while result != nil: 75 | if cmpExact(cstring(result.s), identifier, length) == 0: 76 | if last != nil: 77 | # make access to last looked up identifier faster: 78 | last.next = result.next 79 | result.next = ic.buckets[idx] 80 | ic.buckets[idx] = result 81 | return 82 | elif cmpIgnoreStyle(cstring(result.s), identifier, length) == 0: 83 | assert((id == 0) or (id == result.id)) 84 | id = result.id 85 | last = result 86 | result = result.next 87 | new(result) 88 | result.h = h 89 | result.s = newString(length) 90 | for i in 0 ..< length: result.s[i] = identifier[i] 91 | result.next = ic.buckets[idx] 92 | ic.buckets[idx] = result 93 | if id == 0: 94 | inc(ic.wordCounter) 95 | result.id = -ic.wordCounter 96 | else: 97 | result.id = id 98 | 99 | proc getIdent*(ic: IdentCache; identifier: string): PIdent = 100 | result = getIdent(ic, cstring(identifier), len(identifier), 101 | hashIgnoreStyle(identifier)) 102 | 103 | proc getIdent*(ic: IdentCache; identifier: string, h: Hash): PIdent = 104 | result = getIdent(ic, cstring(identifier), len(identifier), h) 105 | 106 | proc newIdentCache*(): IdentCache = 107 | result = IdentCache() 108 | result.idAnon = result.getIdent":anonymous" 109 | result.wordCounter = 1 110 | result.idDelegator = result.getIdent":delegator" 111 | result.emptyIdent = result.getIdent("") 112 | # initialize the keywords: 113 | for s in succ(low(specialWords)) .. high(specialWords): 114 | result.getIdent(specialWords[s], hashIgnoreStyle(specialWords[s])).id = ord(s) 115 | 116 | proc whichKeyword*(id: PIdent): TSpecialWord = 117 | if id.id < 0: result = wInvalid 118 | else: result = TSpecialWord(id.id) 119 | -------------------------------------------------------------------------------- /testsuite/cextras/rcl_arguments.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Open Source Robotics Foundation, Inc. 2 | 3 | /// @file 4 | 5 | #ifndef RCL__ARGUMENTS_H_ 6 | #define RCL__ARGUMENTS_H_ 7 | 8 | #include "rcl/allocator.h" 9 | #include "rcl/allocator.h" 10 | #include "rcl/log_level.h" 11 | #include "rcl/macros.h" 12 | #include "rcl/types.h" 13 | #include "rcl/visibility_control.h" 14 | #include "rcl_yaml_param_parser/types.h" 15 | 16 | #ifdef __cplusplus 17 | extern "C" 18 | { 19 | #endif 20 | 21 | enum RCUTILS_LOG_SEVERITY 22 | { 23 | RCUTILS_LOG_SEVERITY_UNSET = 0, ///< The unset log level 24 | RCUTILS_LOG_SEVERITY_DEBUG = 10, ///< The debug log level 25 | RCUTILS_LOG_SEVERITY_INFO = 20, ///< The info log level 26 | RCUTILS_LOG_SEVERITY_WARN = 30, ///< The warn log level 27 | RCUTILS_LOG_SEVERITY_ERROR = 40, ///< The error log level 28 | RCUTILS_LOG_SEVERITY_FATAL = 50, ///< The fatal log level 29 | }; 30 | 31 | #pragma c2nim mergeblocks 32 | #pragma c2nim delete g_rcutils_log_severity_names 33 | #pragma c2nim reordercomments 34 | 35 | // The names of severity levels. 36 | __attribute__ ((visibility("default"))) 37 | extern const char * const g_rcutils_log_severity_names[RCUTILS_LOG_SEVERITY_FATAL + 1]; 38 | 39 | /// Return a rcl_arguments_t struct with members initialized to `NULL`. 40 | RCL_PUBLIC 41 | RCL_WARN_UNUSED 42 | rcl_arguments_t 43 | rcl_get_zero_initialized_arguments(void); 44 | 45 | _Static_assert(sizeof((constructrcutils_error_string_t)) == 46 | (768 + (1024 - 768 - 20 - 6 - 1) + 20 + 6 + 1), "Maximum length calculations incorrect"); 47 | 48 | typedef struct rcl_arguments_impl_s rcl_arguments_impl_t; 49 | 50 | /// Hold output of parsing command line arguments. 51 | typedef struct rcl_arguments_s 52 | { 53 | /// Private implementation pointer. 54 | rcl_arguments_impl_t * impl; 55 | } rcl_arguments_t; 56 | 57 | 58 | 59 | /// The command-line flag that delineates the start of ROS arguments. 60 | #define RCL_ROS_ARGS_FLAG "--ros-args" 61 | 62 | /// The suffix of the ROS flag to enable or disable external library 63 | /// logging (must be preceded with --enable- or --disable-). 64 | #define RCL_LOG_EXT_LIB_FLAG_SUFFIX "external-lib-logs" 65 | 66 | /// Return a rcl_arguments_t struct with members initialized to `NULL`. 67 | RCL_PUBLIC 68 | RCL_WARN_UNUSED 69 | rcl_arguments_t 70 | rcl_get_zero_initialized_arguments(void); 71 | 72 | /// Parse command line arguments into a structure usable by code. 73 | /** 74 | * \sa rcl_get_zero_initialized_arguments() 75 | * 76 | */ 77 | RCL_PUBLIC 78 | RCL_WARN_UNUSED 79 | rcl_ret_t 80 | rcl_parse_arguments( 81 | int argc, 82 | const char * const * argv, 83 | rcl_allocator_t allocator, 84 | rcl_arguments_t * args_output); 85 | 86 | /// Return the number of arguments that were not ROS specific arguments. 87 | /** 88 | */ 89 | RCL_ALIGNAS(8) 90 | RCL_WARN_UNUSED 91 | int 92 | rcl_arguments_get_count_unparsed( 93 | const rcl_arguments_t * args); 94 | 95 | RCL_PUBLIC 96 | RCL_WARN_UNUSED 97 | rcl_ret_t 98 | rcl_arguments_get_unparsed( 99 | const rcl_arguments_t * args, 100 | rcl_allocator_t allocator, 101 | int ** output_unparsed_indices); 102 | 103 | RCL_PUBLIC 104 | RCL_WARN_UNUSED 105 | int 106 | rcl_arguments_get_count_unparsed_ros( 107 | const rcl_arguments_t * args); 108 | 109 | RCL_PUBLIC 110 | RCL_WARN_UNUSED 111 | rcl_ret_t 112 | rcl_arguments_get_unparsed_ros( 113 | const rcl_arguments_t * args, 114 | rcl_allocator_t allocator, 115 | int ** output_unparsed_ros_indices); 116 | 117 | RCL_PUBLIC 118 | RCL_WARN_UNUSED 119 | int 120 | rcl_arguments_get_param_files_count( 121 | const rcl_arguments_t * args); 122 | 123 | 124 | RCL_PUBLIC 125 | RCL_WARN_UNUSED 126 | rcl_ret_t 127 | rcl_arguments_get_param_files( 128 | const rcl_arguments_t * arguments, 129 | rcl_allocator_t allocator, 130 | char *** parameter_files); 131 | 132 | RCL_PUBLIC 133 | RCL_WARN_UNUSED 134 | rcl_ret_t 135 | rcl_arguments_get_param_overrides( 136 | const rcl_arguments_t * arguments, 137 | rcl_params_t ** parameter_overrides); 138 | 139 | RCL_PUBLIC 140 | RCL_WARN_UNUSED 141 | rcl_ret_t 142 | rcl_remove_ros_arguments( 143 | const char * const * argv, 144 | const rcl_arguments_t * args, 145 | rcl_allocator_t allocator, 146 | int * nonros_argc, 147 | const char *** nonros_argv); 148 | 149 | RCL_PUBLIC 150 | RCL_WARN_UNUSED 151 | rcl_ret_t 152 | rcl_arguments_get_log_levels( 153 | const rcl_arguments_t * arguments, 154 | rcl_log_levels_t * log_levels); 155 | 156 | RCL_PUBLIC 157 | RCL_WARN_UNUSED 158 | rcl_ret_t 159 | rcl_arguments_copy( 160 | const rcl_arguments_t * args, 161 | rcl_arguments_t * args_out); 162 | 163 | RCL_PUBLIC 164 | RCL_WARN_UNUSED 165 | rcl_ret_t 166 | rcl_arguments_fini( 167 | rcl_arguments_t * args); 168 | 169 | #ifdef __cplusplus 170 | } 171 | #endif 172 | 173 | #endif // RCL__ARGUMENTS_H_ 174 | -------------------------------------------------------------------------------- /testsuite/results/smartptrs.nim: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2008-2014 the Urho3D project. 3 | ## 4 | ## Permission is hereby granted, free of charge, to any person obtaining a copy 5 | ## of this software and associated documentation files (the "Software"), to deal 6 | ## in the Software without restriction, including without limitation the rights 7 | ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | ## copies of the Software, and to permit persons to whom the Software is 9 | ## furnished to do so, subject to the following conditions: 10 | ## 11 | ## The above copyright notice and this permission notice shall be included in 12 | ## all copies or substantial portions of the Software. 13 | ## 14 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | ## THE SOFTWARE. 21 | ## 22 | 23 | import 24 | RefCounted 25 | 26 | ## Shared pointer template class with intrusive reference counting. 27 | 28 | type 29 | SharedPtr*[T] {.bycopy.} = object ## Construct a null shared pointer. 30 | ## Prevent direct assignment from a shared pointer of another type. 31 | 32 | 33 | proc constructSharedPtr*[T](): SharedPtr[T] {.constructor.} 34 | proc constructSharedPtr*[T](rhs: SharedPtr[T]): SharedPtr[T] {.constructor.} 35 | proc constructSharedPtr*[T](`ptr`: ptr T): SharedPtr[T] {.constructor.} 36 | proc destroySharedPtr*[T](this: var SharedPtr[T]) 37 | proc `->`*[T](this: SharedPtr[T]): ptr T {.noSideEffect.} 38 | proc `*`*[T](this: SharedPtr[T]): var T {.noSideEffect.} 39 | proc `[]`*[T](this: var SharedPtr[T]; index: cint): var T 40 | proc `<`*[T](this: SharedPtr[T]; rhs: SharedPtr[T]): bool {.noSideEffect.} 41 | proc `==`*[T](this: SharedPtr[T]; rhs: SharedPtr[T]): bool {.noSideEffect.} 42 | proc Reset*[T](this: var SharedPtr[T]) 43 | proc Detach*[T](this: var SharedPtr[T]) 44 | proc StaticCast*[T; U](this: var SharedPtr[T]; rhs: SharedPtr[U]) 45 | proc DynamicCast*[T; U](this: var SharedPtr[T]; rhs: SharedPtr[U]) 46 | proc Null*[T](this: SharedPtr[T]): bool {.noSideEffect.} 47 | proc NotNull*[T](this: SharedPtr[T]): bool {.noSideEffect.} 48 | proc Get*[T](this: SharedPtr[T]): ptr T {.noSideEffect.} 49 | proc Refs*[T](this: SharedPtr[T]): cint {.noSideEffect.} 50 | proc WeakRefs*[T](this: SharedPtr[T]): cint {.noSideEffect.} 51 | proc RefCountPtr*[T](this: SharedPtr[T]): ptr RefCount {.noSideEffect.} 52 | proc ToHash*[T](this: SharedPtr[T]): cuint {.noSideEffect.} 53 | ## Perform a static cast from one shared pointer type to another. 54 | 55 | proc StaticCast*[T; U](`ptr`: SharedPtr[U]): SharedPtr[T] = 56 | discard 57 | 58 | ## Perform a dynamic cast from one weak pointer type to another. 59 | 60 | proc DynamicCast*[T; U](`ptr`: SharedPtr[U]): SharedPtr[T] = 61 | discard 62 | 63 | ## Weak pointer template class with intrusive reference counting. Does not keep the object pointed to alive. 64 | 65 | type 66 | WeakPtr*[T] {.bycopy.} = object ## Construct a null weak pointer. 67 | ## Prevent direct assignment from a weak pointer of different type. 68 | ## Pointer to the RefCount structure. 69 | 70 | 71 | proc constructWeakPtr*[T](): WeakPtr[T] {.constructor.} 72 | proc constructWeakPtr*[T](rhs: WeakPtr[T]): WeakPtr[T] {.constructor.} 73 | proc constructWeakPtr*[T](rhs: SharedPtr[T]): WeakPtr[T] {.constructor.} 74 | proc constructWeakPtr*[T](`ptr`: ptr T): WeakPtr[T] {.constructor.} 75 | proc destroyWeakPtr*[T](this: var WeakPtr[T]) 76 | proc Lock*[T](this: WeakPtr[T]): SharedPtr[T] {.noSideEffect.} 77 | proc Get*[T](this: WeakPtr[T]): ptr T {.noSideEffect.} 78 | proc `->`*[T](this: WeakPtr[T]): ptr T {.noSideEffect.} 79 | proc `*`*[T](this: WeakPtr[T]): var T {.noSideEffect.} 80 | proc `[]`*[T](this: var WeakPtr[T]; index: cint): var T 81 | proc `==`*[T](this: WeakPtr[T]; rhs: WeakPtr[T]): bool {.noSideEffect.} 82 | proc `<`*[T](this: WeakPtr[T]; rhs: WeakPtr[T]): bool {.noSideEffect.} 83 | proc Reset*[T](this: var WeakPtr[T]) 84 | proc StaticCast*[T; U](this: var WeakPtr[T]; rhs: WeakPtr[U]) 85 | proc DynamicCast*[T; U](this: var WeakPtr[T]; rhs: WeakPtr[U]) 86 | proc Null*[T](this: WeakPtr[T]): bool {.noSideEffect.} 87 | proc NotNull*[T](this: WeakPtr[T]): bool {.noSideEffect.} 88 | proc Refs*[T](this: WeakPtr[T]): cint {.noSideEffect.} 89 | proc WeakRefs*[T](this: WeakPtr[T]): cint {.noSideEffect.} 90 | proc Expired*[T](this: WeakPtr[T]): bool {.noSideEffect.} 91 | proc RefCountPtr*[T](this: WeakPtr[T]): ptr RefCount {.noSideEffect.} 92 | proc ToHash*[T](this: WeakPtr[T]): cuint {.noSideEffect.} 93 | ## Perform a static cast from one weak pointer type to another. 94 | 95 | proc StaticCast*[T; U](`ptr`: WeakPtr[U]): WeakPtr[T] = 96 | discard 97 | 98 | ## Perform a dynamic cast from one weak pointer type to another. 99 | 100 | proc DynamicCast*[T; U](`ptr`: WeakPtr[U]): WeakPtr[T] = 101 | discard 102 | -------------------------------------------------------------------------------- /testsuite/results/rcl_context.nim: -------------------------------------------------------------------------------- 1 | ## Copyright 2018 Open Source Robotics Foundation, Inc. 2 | ## 3 | ## @file 4 | 5 | import 6 | rmw/init, rcl/allocator, rcl/arguments, rcl/init_options, rcl/macros, 7 | rcl/types, rcl/visibility_control 8 | 9 | type 10 | 11 | rcl_context_instance_id_t* = uint64 ## A unique ID per context instance. 12 | 13 | rcl_context_impl_t* = rcl_context_impl_s 14 | 15 | rcl_context_t* {.importc: "rcl_context_t", header: "rcl_context.h", bycopy.} = object ## 16 | ## Encapsulates the non-global state of an init/shutdown cycle. 17 | ## 18 | ## The context is used in the creation of top level entities like nodes and 19 | ## guard conditions, as well as to shutdown a specific instance of init. 20 | ## 21 | ## 22 | global_arguments* {.importc: "global_arguments".}: rcl_arguments_t ## 23 | ## Global arguments for all nodes which share this context. 24 | ## Typically generated by the parsing of argc/argv in rcl_init(). 25 | impl* {.importc: "impl".}: ptr rcl_context_impl_t ## 26 | ## Implementation specific pointer. 27 | ## The assumption that this is big enough for an atomic_uint_least64_t is 28 | ## In most cases it should just be a plain uint64_t. 29 | ## @cond Doxygen_Suppress 30 | when not defined(RCL_CONTEXT_ATOMIC_INSTANCE_ID_STORAGE_SIZE): 31 | const 32 | RCL_CONTEXT_ATOMIC_INSTANCE_ID_STORAGE_SIZE* = sizeof((uint_least64_t)) 33 | ## @endcond 34 | ## Private storage for instance ID atomic. 35 | instance_id_storage* {.importc: "instance_id_storage".}: array[ 36 | RCL_CONTEXT_ATOMIC_INSTANCE_ID_STORAGE_SIZE, uint8] ## 37 | ## 38 | ## Accessing the instance id should be done using the function 39 | ## 40 | 41 | 42 | 43 | proc rcl_get_zero_initialized_context*(): rcl_context_t {. 44 | importc: "rcl_get_zero_initialized_context", header: "rcl_context.h".} 45 | ## 46 | ## Return a zero initialization context object. 47 | 48 | proc rcl_context_fini*(context: ptr rcl_context_t): rcl_ret_t {. 49 | importc: "rcl_context_fini", header: "rcl_context.h".} 50 | ## 51 | ## Finalize a context. 52 | ## 53 | ## 54 | ## 55 | 56 | proc rcl_context_get_init_options*(context: ptr rcl_context_t): ptr rcl_init_options_t {. 57 | importc: "rcl_context_get_init_options", header: "rcl_context.h".} 58 | ## 59 | ## Return the init options used during initialization for this context. 60 | ## 61 | ## 62 | ## \param[in] context object from which the init options should be retrieved 63 | ## \return pointer to the the init options, or 64 | ## \return `NULL` if there was an error 65 | ## 66 | 67 | proc rcl_context_get_instance_id*(context: ptr rcl_context_t): rcl_context_instance_id_t {. 68 | importc: "rcl_context_get_instance_id", header: "rcl_context.h".} 69 | ## 70 | ## Returns an unsigned integer that is unique to the given context, or `0` if invalid. 71 | ## 72 | ## 73 | 74 | proc rcl_context_get_domain_id*(context: ptr rcl_context_t; 75 | domain_id: ptr csize_t): rcl_ret_t {. 76 | importc: "rcl_context_get_domain_id", header: "rcl_context.h".} 77 | ## 78 | ## Returns the context domain id. 79 | ## 80 | ## 81 | 82 | proc rcl_context_is_valid*(context: ptr rcl_context_t): bool {. 83 | importc: "rcl_context_is_valid", header: "rcl_context.h".} 84 | ## 85 | ## Return `true` if the given context is currently valid, otherwise `false`. 86 | ## 87 | ## If context is `NULL`, then `false` is returned. 88 | ## If context is zero-initialized, then `false` is returned. 89 | ## If context is uninitialized, then it is undefined behavior. 90 | ## 91 | ## 92 | 93 | proc rcl_context_get_rmw_context*(context: ptr rcl_context_t): ptr rmw_context_t {. 94 | importc: "rcl_context_get_rmw_context", header: "rcl_context.h".} 95 | ## 96 | ## Return pointer to the rmw context if the given context is currently valid, otherwise `NULL`. 97 | ## 98 | ## If context is `NULL`, then `NULL` is returned. 99 | ## If context is zero-initialized, then `NULL` is returned. 100 | ## If context is uninitialized, then it is undefined behavior. 101 | ## 102 | ## -------------------------------------------------------------------------------- /testsuite/results/rcl_arguments.nim: -------------------------------------------------------------------------------- 1 | ## Copyright 2018 Open Source Robotics Foundation, Inc. 2 | ## @file 3 | 4 | import 5 | rcl/allocator, rcl/log_level, rcl/macros, rcl/types, rcl/visibility_control, 6 | rcl_yaml_param_parser/types 7 | 8 | type 9 | 10 | RCUTILS_LOG_SEVERITY* {.size: sizeof(cint).} = enum 11 | RCUTILS_LOG_SEVERITY_UNSET = 0, ## < The unset log level 12 | RCUTILS_LOG_SEVERITY_DEBUG = 10, ## < The debug log level 13 | RCUTILS_LOG_SEVERITY_INFO = 20, ## < The info log level 14 | RCUTILS_LOG_SEVERITY_WARN = 30, ## < The warn log level 15 | RCUTILS_LOG_SEVERITY_ERROR = 40, ## < The error log level 16 | RCUTILS_LOG_SEVERITY_FATAL = 50 ## < The fatal log level 17 | 18 | 19 | ## The names of severity levels. 20 | 21 | 22 | proc rcl_get_zero_initialized_arguments*(): rcl_arguments_t {. 23 | importc: "rcl_get_zero_initialized_arguments", header: "rcl_arguments.h".} 24 | ## 25 | ## Return a rcl_arguments_t struct with members initialized to `NULL`. 26 | _Static_assert(sizeof(((constructrcutils_error_string_t))) == 27 | (768 + (1024 - 768 - 20 - 6 - 1) + 20 + 6 + 1), 28 | "Maximum length calculations incorrect") 29 | type 30 | 31 | rcl_arguments_impl_t* = rcl_arguments_impl_s 32 | 33 | rcl_arguments_t* {.importc: "rcl_arguments_t", header: "rcl_arguments.h", 34 | bycopy.} = object ## Hold output of parsing command line arguments. 35 | impl* {.importc: "impl".}: ptr rcl_arguments_impl_t ## 36 | ## Private implementation pointer. 37 | 38 | 39 | const 40 | RCL_ROS_ARGS_FLAG* = "--ros-args" ## The command-line flag that delineates the start of ROS arguments. 41 | RCL_LOG_EXT_LIB_FLAG_SUFFIX* = "external-lib-logs" ## 42 | ## The suffix of the ROS flag to enable or disable external library 43 | ## logging (must be preceded with --enable- or --disable-). 44 | 45 | 46 | proc rcl_get_zero_initialized_arguments*(): rcl_arguments_t {. 47 | importc: "rcl_get_zero_initialized_arguments", header: "rcl_arguments.h".} 48 | ## 49 | ## Return a rcl_arguments_t struct with members initialized to `NULL`. 50 | 51 | proc rcl_parse_arguments*(argc: cint; argv: cstringArray; 52 | allocator: rcl_allocator_t; 53 | args_output: ptr rcl_arguments_t): rcl_ret_t {. 54 | importc: "rcl_parse_arguments", header: "rcl_arguments.h".} 55 | ## 56 | ## Parse command line arguments into a structure usable by code. 57 | ## 58 | ## \sa rcl_get_zero_initialized_arguments() 59 | ## 60 | ## 61 | 62 | proc rcl_arguments_get_count_unparsed*(args: ptr rcl_arguments_t): cint {. 63 | importc: "rcl_arguments_get_count_unparsed", header: "rcl_arguments.h".} 64 | ## 65 | ## Return the number of arguments that were not ROS specific arguments. 66 | ## 67 | ## 68 | 69 | proc rcl_arguments_get_unparsed*(args: ptr rcl_arguments_t; 70 | allocator: rcl_allocator_t; 71 | output_unparsed_indices: ptr ptr cint): rcl_ret_t {. 72 | importc: "rcl_arguments_get_unparsed", header: "rcl_arguments.h".} 73 | 74 | proc rcl_arguments_get_count_unparsed_ros*(args: ptr rcl_arguments_t): cint {. 75 | importc: "rcl_arguments_get_count_unparsed_ros", header: "rcl_arguments.h".} 76 | 77 | proc rcl_arguments_get_unparsed_ros*(args: ptr rcl_arguments_t; 78 | allocator: rcl_allocator_t; 79 | output_unparsed_ros_indices: ptr ptr cint): rcl_ret_t {. 80 | importc: "rcl_arguments_get_unparsed_ros", header: "rcl_arguments.h".} 81 | 82 | proc rcl_arguments_get_param_files_count*(args: ptr rcl_arguments_t): cint {. 83 | importc: "rcl_arguments_get_param_files_count", header: "rcl_arguments.h".} 84 | 85 | proc rcl_arguments_get_param_files*(arguments: ptr rcl_arguments_t; 86 | allocator: rcl_allocator_t; 87 | parameter_files: ptr cstringArray): rcl_ret_t {. 88 | importc: "rcl_arguments_get_param_files", header: "rcl_arguments.h".} 89 | 90 | proc rcl_arguments_get_param_overrides*(arguments: ptr rcl_arguments_t; 91 | parameter_overrides: ptr ptr rcl_params_t): rcl_ret_t {. 92 | importc: "rcl_arguments_get_param_overrides", header: "rcl_arguments.h".} 93 | 94 | proc rcl_remove_ros_arguments*(argv: cstringArray; args: ptr rcl_arguments_t; 95 | allocator: rcl_allocator_t; 96 | nonros_argc: ptr cint; 97 | nonros_argv: ptr cstringArray): rcl_ret_t {. 98 | importc: "rcl_remove_ros_arguments", header: "rcl_arguments.h".} 99 | 100 | proc rcl_arguments_get_log_levels*(arguments: ptr rcl_arguments_t; 101 | log_levels: ptr rcl_log_levels_t): rcl_ret_t {. 102 | importc: "rcl_arguments_get_log_levels", header: "rcl_arguments.h".} 103 | 104 | proc rcl_arguments_copy*(args: ptr rcl_arguments_t; 105 | args_out: ptr rcl_arguments_t): rcl_ret_t {. 106 | importc: "rcl_arguments_copy", header: "rcl_arguments.h".} 107 | 108 | proc rcl_arguments_fini*(args: ptr rcl_arguments_t): rcl_ret_t {. 109 | importc: "rcl_arguments_fini", header: "rcl_arguments.h".} -------------------------------------------------------------------------------- /testsuite/cppkeepbodies/more11features.cpp: -------------------------------------------------------------------------------- 1 | 2 | #def static_assert(x, y) 3 | 4 | struct Double 5 | { 6 | static_assert(std::numeric_limits::is_iec559 7 | && std::numeric_limits::digits == 53 8 | && std::numeric_limits::max_exponent == 1024, 9 | "IEEE-754 double-precision implementation required"); 10 | 11 | using value_type = double; 12 | using bits_type = uint64_t; 13 | 14 | static constexpr int32_t SignificandSize = std::numeric_limits::digits; // = p (includes the hidden bit) 15 | static constexpr int32_t ExponentBias = std::numeric_limits::max_exponent - 1 + (SignificandSize - 1); 16 | static constexpr bits_type MaxIeeeExponent = bits_type{2 * std::numeric_limits::max_exponent - 1}; 17 | static constexpr bits_type HiddenBit = bits_type{1} << (SignificandSize - 1); // = 2^(p-1) 18 | static constexpr bits_type SignificandMask = HiddenBit - 1; // = 2^(p-1) - 1 19 | static constexpr bits_type ExponentMask = MaxIeeeExponent << (SignificandSize - 1); 20 | static constexpr bits_type SignMask = ~(~bits_type{0} >> 1); 21 | 22 | bits_type bits; 23 | 24 | explicit Double(bits_type bits_) : bits(bits_) {} 25 | explicit Double(value_type value) : bits(ReinterpretBits(value)) {} 26 | 27 | }; 28 | 29 | #include 30 | #include 31 | 32 | int main(){ 33 | std::vector foo(10); 34 | return 0; 35 | } 36 | 37 | #define MYIGNORE 38 | #define MYCDECL __cdecl 39 | 40 | int test1() { int x = 1; return (x); } 41 | int MYCDECL test2() { int x = 2; return (x); } 42 | 43 | #if defined(MYIGNORE) 44 | int myVar; 45 | 46 | MYIGNORE int test3() { 47 | myVar = test1(); 48 | myVar = myVar + test2(); 49 | return(myVar); 50 | } 51 | 52 | #endif 53 | 54 | #ifdef MYIGNORE 55 | 56 | MYIGNORE int test4() { 57 | myVar = test1(); 58 | myVar = myVar + test2(); 59 | return(myVar); 60 | } 61 | 62 | #endif 63 | 64 | #ifdef DEBUG 65 | # define OUT(x) printf("%s\n", x) 66 | #else 67 | # define OUT(x) 68 | #endif 69 | 70 | // bug #190 71 | 72 | #def Q_DISABLE_COPY(MyClass) \ 73 | MyClass(const MyClass &) = delete; \ 74 | MyClass &operator=(const MyClass &) = delete; 75 | 76 | #define Q_CORE_EXPORT 77 | 78 | class Q_CORE_EXPORT QObjectData 79 | { 80 | Q_DISABLE_COPY(QObjectData) 81 | public: 82 | QObjectData() = default; 83 | virtual ~QObjectData() = 0; 84 | QObject *q_ptr; 85 | QObject *parent; 86 | QObjectList children; 87 | 88 | uint isWidget : 1; 89 | uint blockSig : 1; 90 | uint wasDeleted : 1; 91 | uint isDeletingChildren : 1; 92 | uint sendChildEvents : 1; 93 | uint receiveChildEvents : 1; 94 | uint isWindow : 1; // for QWindow 95 | uint deleteLaterCalled : 1; 96 | uint unused : 24; 97 | int postedEvents; 98 | QDynamicMetaObjectData *metaObject; 99 | QBindingStorage bindingStorage; 100 | QMetaObject *dynamicMetaObject() const override final; 101 | }; 102 | 103 | // C++ lambdas 104 | 105 | auto ex1 = [] (int x) { std::cout << x << '\n'; }; 106 | 107 | auto ex2 = [] () { code; }; 108 | 109 | auto ex3 = [](float f, int a) { return a*f; }; 110 | auto ex4 = [](MyClass t) -> int { auto a = t.compute(); return a; }; 111 | auto ex5 = [](int a, int b) { return a < b; }; 112 | 113 | auto myLambda = [](int a) -> double { return 2.0 * a; }; 114 | 115 | auto myLambda = [](int a) mutable { std::cout << a; }; 116 | 117 | auto baz = [] () { 118 | int x = 10; 119 | if ( x < 20) 120 | return x * 1.1; 121 | else 122 | return x * 2.1; 123 | }; 124 | 125 | int x = 1, y = 1; 126 | [&]() { ++x; ++y; }(); // <-- call () 127 | 128 | 129 | int main() { 130 | int x = 10; 131 | int y = 11; 132 | // Captures With an Initializer 133 | auto foo = [z = x+y]() { std::cout << z << '\n'; }; 134 | foo(); 135 | 136 | std::unique_ptr p(new int{10}); 137 | auto foo = [x=10] () mutable { ++x; }; 138 | auto bar = [ptr=std::move(p)] {}; 139 | auto baz = [p=std::move(p)] {}; 140 | } 141 | 142 | // decltype 143 | int i; 144 | 145 | decltype(i+3) j; 146 | 147 | typedef std::function Foo; 148 | 149 | // bug #78 150 | for (int i = 0; i < 44; i++) { 151 | if (a[i]) continue; 152 | print(a[i]); 153 | } 154 | 155 | // smart def vs define heuristic: 156 | #define for_each(x) for(int i = 0; i < x; ++i) 157 | 158 | #define other(x) for(int i = 0; i < x; ++i) printf(i); 159 | 160 | template 161 | class Foo { 162 | public: 163 | Foo(){ 164 | for_each(89) printf(i); 165 | other(13); 166 | 167 | }; 168 | }; 169 | 170 | // bug #59 171 | 172 | enum class Color { red, green = 20, blue }; 173 | 174 | class MyClass { 175 | Color color; 176 | public: 177 | void (*warning)(const char*, ...); // <- this fails!! 178 | void *warning(const char*, ...); 179 | 180 | 181 | T& value() &; 182 | T&& value() &&; 183 | T const& value() const&; 184 | }; 185 | 186 | void* MyClass::warning(const char*, ...) { 187 | int bodyHere; 188 | switch (this->color) { 189 | using enum Color; 190 | case red: ; 191 | case green: 192 | bodyHere = 123; 193 | case blue: ; 194 | } 195 | 196 | if (auto f = (5+6); f != 0) { 197 | printf(R"(I love syntactic sugar!\n)"); 198 | printf(R"xxx(I love syntactic sugar!\n)xxx"); 199 | } 200 | } 201 | 202 | 203 | typedef struct { 204 | int x, y, z; 205 | } Coord; 206 | 207 | constexpr Coord arr[3] = { 208 | {1, 2, 3}, {4, 5, 6}, {7, 8, 9} 209 | }; 210 | 211 | // test 'noexcept': 212 | 213 | void stuff() noexcept(x = x + 1); 214 | 215 | int raisesNothing() noexcept { 216 | } 217 | -------------------------------------------------------------------------------- /testsuite/results/more11features.nim: -------------------------------------------------------------------------------- 1 | type 2 | Double* {.bycopy.} = object 3 | bits*: bits_type 4 | 5 | value_type* = cdouble 6 | bits_type* = uint64_t 7 | 8 | const ## = p (includes the hidden bit) 9 | SignificandSize*: int32_t = digits[value_type] 10 | 11 | const 12 | ExponentBias*: int32_t = max_exponent[value_type] - 1 + (SignificandSize - 1) 13 | 14 | const 15 | MaxIeeeExponent*: bits_type = bits_type(2 * max_exponent[value_type] - 1) 16 | 17 | const ## = 2^(p-1) 18 | HiddenBit*: bits_type = bits_type(1) shl (SignificandSize - 1) 19 | 20 | const ## = 2^(p-1) - 1 21 | SignificandMask*: bits_type = HiddenBit - 1 22 | 23 | const 24 | ExponentMask*: bits_type = MaxIeeeExponent shl (SignificandSize - 1) 25 | 26 | const 27 | SignMask*: bits_type = not (not bits_type(0) shr 1) 28 | 29 | proc constructDouble*(bits_: bits_type): Double {.constructor.} = 30 | discard 31 | 32 | proc constructDouble*(value: value_type): Double {.constructor.} = 33 | discard 34 | 35 | proc main*(): cint = 36 | var foo: vector[int64_t] = vector[int64_t](10) 37 | return 0 38 | 39 | proc test1*(): cint = 40 | var x: cint = 1 41 | return x 42 | 43 | proc test2*(): cint {.cdecl.} = 44 | var x: cint = 2 45 | return x 46 | 47 | var myVar*: cint 48 | 49 | proc test3*(): cint = 50 | myVar = test1() 51 | myVar = myVar + test2() 52 | return myVar 53 | 54 | proc test4*(): cint = 55 | myVar = test1() 56 | myVar = myVar + test2() 57 | return myVar 58 | 59 | when defined(DEBUG): 60 | template OUT*(x: untyped): untyped = 61 | printf("%s\n", x) 62 | 63 | else: 64 | discard 65 | ## bug #190 66 | 67 | type 68 | QObjectData* {.bycopy.} = object 69 | q_ptr*: ptr QObject 70 | parent*: ptr QObject 71 | children*: QObjectList 72 | isWidget* {.bitsize: 1.}: uint 73 | blockSig* {.bitsize: 1.}: uint 74 | wasDeleted* {.bitsize: 1.}: uint 75 | isDeletingChildren* {.bitsize: 1.}: uint 76 | sendChildEvents* {.bitsize: 1.}: uint 77 | receiveChildEvents* {.bitsize: 1.}: uint 78 | isWindow* {.bitsize: 1.}: uint ## for QWindow 79 | deleteLaterCalled* {.bitsize: 1.}: uint 80 | unused* {.bitsize: 24.}: uint 81 | postedEvents*: cint 82 | metaObject*: ptr QDynamicMetaObjectData 83 | bindingStorage*: QBindingStorage 84 | 85 | 86 | proc constructQObjectData*(): QObjectData {.constructor.} 87 | proc destroyQObjectData*(this: var QObjectData) 88 | proc dynamicMetaObject*(this: QObjectData): ptr QMetaObject {.noSideEffect.} 89 | ## C++ lambdas 90 | 91 | var ex1*: auto = (proc (x: cint): auto = 92 | cout shl x shl '\n') 93 | 94 | var ex2*: auto = (proc (): auto = 95 | code) 96 | 97 | var ex3*: auto = (proc (f: cfloat; a: cint): auto = 98 | return a * f) 99 | 100 | var ex4*: auto = (proc (t: MyClass): cint = 101 | var a: auto = t.compute() 102 | return a) 103 | 104 | var ex5*: auto = (proc (a: cint; b: cint): auto = 105 | return a < b) 106 | 107 | var myLambda*: auto = (proc (a: cint): cdouble = 108 | return 2.0 * a) 109 | 110 | var myLambda*: auto = (proc (a: cint): auto = 111 | cout shl a) 112 | 113 | var baz*: auto = (proc (): auto = 114 | var x: cint = 10 115 | if x < 20: 116 | return x * 1.1 117 | else: 118 | return x * 2.1 119 | ) 120 | 121 | var 122 | x*: cint = 1 123 | y*: cint = 1 124 | 125 | (proc (): auto = 126 | inc(x) 127 | inc(y))() 128 | ## <-- call () 129 | 130 | proc main*(): cint = 131 | var x: cint = 10 132 | var y: cint = 11 133 | ## Captures With an Initializer 134 | var foo: auto = (proc (): auto = 135 | cout shl z shl '\n') 136 | foo() 137 | var p: unique_ptr[cint] = unique_ptr[cint](new(int(10))) 138 | var foo: auto = (proc (): auto = 139 | inc(x)) 140 | var bar: auto = (proc (): auto = discard ) 141 | var baz: auto = (proc (): auto = discard ) 142 | 143 | ## decltype 144 | 145 | var i*: cint 146 | 147 | var j*: typeof(i + 3) 148 | 149 | type 150 | Foo* = function[proc ()] 151 | 152 | ## bug #78 153 | 154 | var i*: cint = 0 155 | 156 | while i < 44: 157 | if a[i]: 158 | inc(i) 159 | continue 160 | print(a[i]) 161 | inc(i) 162 | ## smart def vs define heuristic: 163 | 164 | template other*(x: untyped): void = 165 | var i*: cint = 0 166 | while i < x: 167 | printf(i) 168 | inc(i) 169 | 170 | type 171 | Foo*[T] {.bycopy.} = object 172 | 173 | 174 | proc constructFoo*[T](): Foo[T] {.constructor.} = 175 | var i: cint = 0 176 | while i < 89: 177 | printf(i) 178 | inc(i) 179 | other(13) 180 | 181 | ## bug #59 182 | 183 | type 184 | Color* = enum 185 | red, green = 20, blue 186 | 187 | 188 | type 189 | MyClass* {.bycopy.} = object 190 | color*: Color 191 | warning*: proc (a1: cstring) {.varargs.} ## <- this fails!! 192 | 193 | 194 | proc warning*(this: var MyClass; a2: cstring): pointer {.varargs.} 195 | proc value*(this: var MyClass): var T 196 | proc value*(this: var MyClass): var T 197 | proc value*(this: MyClass): T {.noSideEffect.} 198 | proc warning*(this: var MyClass; a2: cstring): pointer {.varargs.} = 199 | var bodyHere: cint 200 | case this.color 201 | of red: 202 | ## ignored statement 203 | of green: 204 | bodyHere = 123 205 | of blue: 206 | ## ignored statement 207 | if ( 208 | var f: auto = (5 + 6) 209 | f != 0): 210 | printf("(I love syntactic sugar!\\n") 211 | printf("(I love syntactic sugar!\\n") 212 | 213 | type 214 | Coord* {.bycopy.} = object 215 | x*: cint 216 | y*: cint 217 | z*: cint 218 | 219 | 220 | const 221 | arr*: array[3, Coord] = [Coord(x: 1, y: 2, z: 3), Coord(x: 4, y: 5, z: 6), 222 | Coord(x: 7, y: 8, z: 9)] 223 | 224 | ## test 'noexcept': 225 | 226 | proc stuff*() 227 | proc raisesNothing*(): cint {.raises: [].} = 228 | discard 229 | -------------------------------------------------------------------------------- /compiler/nimlexbase.nim: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # The Nim Compiler 4 | # (c) Copyright 2012 Andreas Rumpf 5 | # 6 | # See the file "copying.txt", included in this 7 | # distribution, for details about the copyright. 8 | # 9 | 10 | # Base Object of a lexer with efficient buffer handling. In fact 11 | # I believe that this is the most efficient method of buffer 12 | # handling that exists! Only at line endings checks are necessary 13 | # if the buffer needs refilling. 14 | 15 | import 16 | llstream, strutils 17 | 18 | const 19 | Lrz* = ' ' 20 | Apo* = '\'' 21 | Tabulator* = '\x09' 22 | ESC* = '\x1B' 23 | CR* = '\x0D' 24 | FF* = '\x0C' 25 | LF* = '\x0A' 26 | BEL* = '\x07' 27 | BACKSPACE* = '\x08' 28 | VT* = '\x0B' 29 | 30 | const 31 | EndOfFile* = '\0' # end of file marker 32 | # A little picture makes everything clear :-) 33 | # buf: 34 | # "Example Text\n ha!" bufLen = 17 35 | # ^pos = 0 ^ sentinel = 12 36 | # 37 | NewLines* = {CR, LF} 38 | 39 | type 40 | TBaseLexer* = object of RootObj 41 | bufpos*: int 42 | buf*: string 43 | stream*: PLLStream # we read from this stream 44 | lineNumber*: int # the current line number 45 | # private data: 46 | sentinel*: int 47 | lineStart*: int # index of last line start in buffer 48 | offsetBase*: int # use ``offsetBase + bufpos`` to get the offset 49 | 50 | 51 | proc openBaseLexer*(L: var TBaseLexer, inputstream: PLLStream, 52 | bufLen: int = 8192) 53 | # 8K is a reasonable buffer size 54 | proc closeBaseLexer*(L: var TBaseLexer) 55 | proc getCurrentLine*(L: TBaseLexer, marker: bool = true): string 56 | proc getColNumber*(L: TBaseLexer, pos: int): int 57 | proc handleCR*(L: var TBaseLexer, pos: int): int 58 | # Call this if you scanned over CR in the buffer; it returns the 59 | # position to continue the scanning from. `pos` must be the position 60 | # of the CR. 61 | proc handleLF*(L: var TBaseLexer, pos: int): int 62 | # Call this if you scanned over LF in the buffer; it returns the the 63 | # position to continue the scanning from. `pos` must be the position 64 | # of the LF. 65 | # implementation 66 | 67 | proc closeBaseLexer(L: var TBaseLexer) = 68 | llStreamClose(L.stream) 69 | 70 | proc fillBuffer(L: var TBaseLexer) = 71 | var 72 | charsRead, toCopy, s: int # all are in characters, 73 | # not bytes (in case this 74 | # is not the same) 75 | oldBufLen: int 76 | # we know here that pos == L.sentinel, but not if this proc 77 | # is called the first time by initBaseLexer() 78 | assert(L.sentinel < L.buf.len) 79 | toCopy = L.buf.len - L.sentinel - 1 80 | assert(toCopy >= 0) 81 | if toCopy > 0: 82 | moveMem(addr L.buf[0], addr L.buf[L.sentinel + 1], toCopy) 83 | # "moveMem" handles overlapping regions 84 | charsRead = llStreamRead(L.stream, addr L.buf[toCopy], L.sentinel + 1) 85 | s = toCopy + charsRead 86 | if charsRead < L.sentinel + 1: 87 | L.buf[s] = EndOfFile # set end marker 88 | L.sentinel = s 89 | else: 90 | # compute sentinel: 91 | dec(s) # BUGFIX (valgrind) 92 | while true: 93 | assert(s < L.buf.len) 94 | while (s >= 0) and not (L.buf[s] in NewLines): dec(s) 95 | if s >= 0: 96 | # we found an appropriate character for a sentinel: 97 | L.sentinel = s 98 | break 99 | else: 100 | # rather than to give up here because the line is too long, 101 | # double the buffer's size and try again: 102 | oldBufLen = L.buf.len 103 | L.buf.setLen(L.buf.len * 2) 104 | assert(L.buf.len - oldBufLen == oldBufLen) 105 | charsRead = llStreamRead(L.stream, addr(L.buf[oldBufLen]), 106 | oldBufLen) 107 | if charsRead < oldBufLen: 108 | L.buf[oldBufLen + charsRead] = EndOfFile 109 | L.sentinel = oldBufLen + charsRead 110 | break 111 | s = L.buf.len - 1 112 | 113 | proc fillBaseLexer(L: var TBaseLexer, pos: int): int = 114 | assert(pos <= L.sentinel) 115 | if pos < L.sentinel: 116 | result = pos + 1 # nothing to do 117 | else: 118 | fillBuffer(L) 119 | L.offsetBase += pos + 1 120 | L.bufpos = 0 121 | result = 0 122 | L.lineStart = result 123 | 124 | proc handleCR(L: var TBaseLexer, pos: int): int = 125 | assert(L.buf[pos] == CR) 126 | inc(L.lineNumber) 127 | result = fillBaseLexer(L, pos) 128 | if L.buf[result] == LF: 129 | result = fillBaseLexer(L, result) 130 | 131 | proc handleLF(L: var TBaseLexer, pos: int): int = 132 | assert(L.buf[pos] == LF) 133 | inc(L.lineNumber) 134 | result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result; 135 | 136 | proc skipUTF8BOM(L: var TBaseLexer) = 137 | if L.buf[0] == '\xEF' and L.buf[1] == '\xBB' and L.buf[2] == '\xBF': 138 | inc(L.bufpos, 3) 139 | inc(L.lineStart, 3) 140 | 141 | proc openBaseLexer(L: var TBaseLexer, inputstream: PLLStream, bufLen = 8192) = 142 | assert(bufLen > 0) 143 | L.bufpos = 0 144 | L.offsetBase = 0 145 | L.buf = newString(bufLen) 146 | L.sentinel = bufLen - 1 147 | L.lineStart = 0 148 | L.lineNumber = 1 # lines start at 1 149 | L.stream = inputstream 150 | fillBuffer(L) 151 | skipUTF8BOM(L) 152 | 153 | proc getColNumber(L: TBaseLexer, pos: int): int = 154 | result = abs(pos - L.lineStart) 155 | 156 | proc getCurrentLine*(L: TBaseLexer, marker: bool = true): string = 157 | result = "" 158 | var i = L.lineStart 159 | while not (L.buf[i] in {CR, LF, EndOfFile}): 160 | add(result, L.buf[i]) 161 | inc(i) 162 | result.add("\n") 163 | if marker: 164 | result.add(spaces(getColNumber(L, L.bufpos)) & '^' & "\n") 165 | -------------------------------------------------------------------------------- /mangler.nim: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # c2nim - C to Nim source converter 4 | # (c) Copyright 2015 Andreas Rumpf 5 | # 6 | # See the file "copying.txt", included in this 7 | # distribution, for details about the copyright. 8 | # 9 | 10 | ## Implements support for name mangling. 11 | 12 | const skDontMangle = skUnknown 13 | 14 | proc `=~`(s: string, a: openArray[string]): bool = 15 | for x in a: 16 | if s.startsWith(x): return true 17 | 18 | proc nep1(s: string, k: TSymKind): string = 19 | let allUpper = allCharsInSet(s, {'A'..'Z', '0'..'9', '_'}) 20 | if allUpper and k in {skConst, skEnumField, skVar}: 21 | return s 22 | var L = s.len 23 | while L > 0 and s[L-1] == '_': dec L 24 | result = newStringOfCap(L) 25 | var i = 0 26 | while i < L and s[i] == '_': inc i 27 | case k 28 | of skType, skGenericParam: 29 | # Types should start with a capital unless builtins like 'int' etc.: 30 | if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string", 31 | "char", "byte", "bool", "openArray", "seq", "array", "void", 32 | "pointer", "float", "csize_t", "cdouble", "cchar", "cschar", 33 | "cshort", "cu", "nil", "expr", "stmt", "typedesc", "auto", "any", 34 | "range", "openarray", "varargs", "set", "cfloat"]: 35 | result.add s[i] 36 | else: 37 | result.add toUpperAscii(s[i]) 38 | of skConst, skEnumField: 39 | # for 'const' we keep how it's spelt; either upper case or lower case: 40 | result.add s[i] 41 | else: 42 | # as a special rule, don't transform 'L' to 'l' 43 | if L == 1 and s[L-1] == 'L': result.add 'L' 44 | else: 45 | result.add toLowerAscii(s[i]) 46 | inc i 47 | while i < L: 48 | if s[i] == '_': 49 | let before = i-1 50 | while i < L and s[i] == '_': inc i 51 | if before >= 0 and s[before] in {'A'..'Z'}: 52 | # don't skip '_' as it's essential for e.g. 'GC_disable' 53 | result.add('_') 54 | result.add s[i] 55 | else: 56 | result.add toUpperAscii(s[i]) 57 | elif allUpper: 58 | result.add toLowerAscii(s[i]) 59 | else: 60 | result.add s[i] 61 | inc i 62 | 63 | proc mangleRules(s: string, p: Parser; kind: TSymKind): string = 64 | block mangle: 65 | result = s 66 | for pattern, frmt in items(p.options.mangleRules): 67 | if result.match(pattern): 68 | result = result.replacef(pattern, frmt) 69 | if pfNoMultiMangle in p.options.flags: 70 | break mangle 71 | block prefixes: 72 | for prefix in items(p.options.prefixes): 73 | if result.startsWith(prefix): 74 | result = result.substr(prefix.len) 75 | break prefixes 76 | block suffixes: 77 | for suffix in items(p.options.suffixes): 78 | if result.endsWith(suffix): 79 | setLen(result, result.len - suffix.len) 80 | break suffixes 81 | if p.options.followNep1 and kind != skDontMangle: 82 | result = nep1(result, kind) 83 | 84 | proc mangleName(s: string, p: Parser; kind: TSymKind): string = 85 | if p.options.toMangle.hasKey(s): result = p.options.toMangle[s] 86 | else: result = mangleRules(s, p, kind) 87 | 88 | proc isPrivate(s: string, p: Parser): bool = 89 | for pattern in items(p.options.privateRules): 90 | if s.match(pattern): return true 91 | 92 | proc mangledIdent(ident: string, p: Parser; kind: TSymKind): PNode = 93 | result = newNodeP(nkIdent, p) 94 | result.ident = getIdent(mangleName(ident, p, kind)) 95 | 96 | proc getHeaderPair(p: Parser): PNode = 97 | let pre = p.options.headerPrefix 98 | if p.options.headerOverride.len > 0: 99 | newIdentPair("header", pre & p.options.headerOverride, p) 100 | else: 101 | newIdentStrLitPair("header", pre & p.header, p) 102 | 103 | proc addImportToPragma(pragmas: PNode, ident: string, p: Parser) = 104 | if pfImportc in p.options.flags: 105 | discard # already added importc pragma 106 | else: 107 | addSon(pragmas, newIdentStrLitPair(p.options.importcLit, p.currentNamespace & ident, p)) 108 | if pfClibUserPragma in p.options.flags: 109 | addSon(pragmas, newIdentNodeP("clib", p)) 110 | elif p.options.dynlibSym.len > 0: 111 | addSon(pragmas, newIdentPair("dynlib", p.options.dynlibSym, p)) 112 | else: 113 | addSon(pragmas, getHeaderPair(p)) 114 | 115 | proc exportSym(p: Parser, i: PNode, origName: string): PNode = 116 | assert i.kind in {nkIdent, nkAccQuoted} 117 | if p.scopeCounter == 0 and not isPrivate(origName, p): 118 | result = newNodeI(nkPostfix, i.info) 119 | addSon(result, newIdentNode(getIdent("*"), i.info), i) 120 | else: 121 | result = i 122 | 123 | proc varIdent(ident: string, p: Parser; section: TNodeKind): PNode = 124 | result = exportSym(p, mangledIdent(ident, p, skVar), ident) 125 | # a 'const' cannot be importcpp'ed: 126 | if p.scopeCounter > 0 or section == nkConstSection: return 127 | if p.options.dynlibSym.len > 0 or p.options.useHeader: 128 | var a = result 129 | result = newNodeP(nkPragmaExpr, p) 130 | var pragmas = newNodeP(nkPragma, p) 131 | addSon(result, a) 132 | addSon(result, pragmas) 133 | addImportToPragma(pragmas, ident, p) 134 | 135 | proc fieldIdent(ident: string, p: Parser): PNode = 136 | result = exportSym(p, mangledIdent(ident, p, skField), ident) 137 | if p.scopeCounter > 0: return 138 | if p.options.useHeader: 139 | var a = result 140 | result = newNodeP(nkPragmaExpr, p) 141 | var pragmas = newNodeP(nkPragma, p) 142 | addSon(result, a) 143 | addSon(result, pragmas) 144 | addSon(pragmas, newIdentStrLitPair("importc", ident, p)) 145 | 146 | proc doImport(ident: string, pragmas: PNode, p: Parser) = 147 | if p.options.dynlibSym.len > 0 or p.options.useHeader: 148 | addImportToPragma(pragmas, p.currentNamespace & ident, p) 149 | 150 | proc doImportCpp(ident: string, pragmas: PNode, p: Parser) = 151 | if p.options.dynlibSym.len > 0 or p.options.useHeader: 152 | addSon(pragmas, newIdentStrLitPair("importcpp", ident, p)) 153 | if p.options.dynlibSym.len > 0: 154 | addSon(pragmas, newIdentPair("dynlib", p.options.dynlibSym, p)) 155 | else: 156 | addSon(pragmas, getHeaderPair(p)) 157 | -------------------------------------------------------------------------------- /compiler/llstream.nim: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # The Nim Compiler 4 | # (c) Copyright 2012 Andreas Rumpf 5 | # 6 | # See the file "copying.txt", included in this 7 | # distribution, for details about the copyright. 8 | # 9 | 10 | ## Low-level streams for high performance. 11 | 12 | import 13 | strutils, pathutils 14 | 15 | # support '-d:useGnuReadline' for backwards compatibility: 16 | when not defined(windows) and (defined(useGnuReadline) or defined(useLinenoise)): 17 | import rdstdin 18 | 19 | type 20 | TLLRepl* = proc (s: PLLStream, buf: pointer, bufLen: int): int 21 | TLLStreamKind* = enum # enum of different stream implementations 22 | llsNone, # null stream: reading and writing has no effect 23 | llsString, # stream encapsulates a string 24 | llsFile, # stream encapsulates a file 25 | llsStdIn # stream encapsulates stdin 26 | TLLStream* = object of RootObj 27 | kind*: TLLStreamKind # accessible for low-level access (lexbase uses this) 28 | f*: File 29 | s*: string 30 | rd*, wr*: int # for string streams 31 | lineOffset*: int # for fake stdin line numbers 32 | repl*: TLLRepl # gives stdin control to clients 33 | 34 | PLLStream* = ref TLLStream 35 | 36 | proc llStreamOpen*(data: string): PLLStream = 37 | new(result) 38 | result.s = data 39 | result.kind = llsString 40 | 41 | proc llStreamOpen*(f: File): PLLStream = 42 | new(result) 43 | result.f = f 44 | result.kind = llsFile 45 | 46 | proc llStreamOpen*(filename: AbsoluteFile, mode: FileMode): PLLStream = 47 | new(result) 48 | result.kind = llsFile 49 | if not open(result.f, filename.string, mode): result = nil 50 | 51 | proc llStreamOpen*(): PLLStream = 52 | new(result) 53 | result.kind = llsNone 54 | 55 | proc llReadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int 56 | proc llStreamOpenStdIn*(r: TLLRepl = llReadFromStdin): PLLStream = 57 | new(result) 58 | result.kind = llsStdIn 59 | result.s = "" 60 | result.lineOffset = -1 61 | result.repl = r 62 | 63 | proc llStreamClose*(s: PLLStream) = 64 | case s.kind 65 | of llsNone, llsString, llsStdIn: 66 | discard 67 | of llsFile: 68 | close(s.f) 69 | 70 | when not declared(readLineFromStdin): 71 | # fallback implementation: 72 | proc readLineFromStdin(prompt: string, line: var string): bool = 73 | stderr.write(prompt) 74 | result = readLine(stdin, line) 75 | if not result: 76 | stderr.write("\n") 77 | quit(0) 78 | 79 | proc endsWith*(x: string, s: set[char]): bool = 80 | var i = x.len-1 81 | while i >= 0 and x[i] == ' ': dec(i) 82 | if i >= 0 and x[i] in s: 83 | result = true 84 | 85 | const 86 | LineContinuationOprs = {'+', '-', '*', '/', '\\', '<', '>', '!', '?', '^', 87 | '|', '%', '&', '$', '@', '~', ','} 88 | AdditionalLineContinuationOprs = {'#', ':', '='} 89 | 90 | proc endsWithOpr*(x: string): bool = 91 | result = x.endsWith(LineContinuationOprs) 92 | 93 | proc continueLine(line: string, inTripleString: bool): bool {.inline.} = 94 | result = inTripleString or line.len > 0 and ( 95 | line[0] == ' ' or 96 | line.endsWith(LineContinuationOprs+AdditionalLineContinuationOprs)) 97 | 98 | proc countTriples(s: string): int = 99 | var i = 0 100 | while i < s.len: 101 | if s[i] == '"' and s[i+1] == '"' and s[i+2] == '"': 102 | inc result 103 | inc i, 2 104 | inc i 105 | 106 | proc llReadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int = 107 | s.s = "" 108 | s.rd = 0 109 | var line = newStringOfCap(120) 110 | var triples = 0 111 | while readLineFromStdin(if s.s.len == 0: ">>> " else: "... ", line): 112 | add(s.s, line) 113 | add(s.s, "\n") 114 | inc triples, countTriples(line) 115 | if not continueLine(line, (triples and 1) == 1): break 116 | inc(s.lineOffset) 117 | result = min(bufLen, len(s.s) - s.rd) 118 | if result > 0: 119 | copyMem(buf, addr(s.s[s.rd]), result) 120 | inc(s.rd, result) 121 | 122 | proc llStreamRead*(s: PLLStream, buf: pointer, bufLen: int): int = 123 | case s.kind 124 | of llsNone: 125 | result = 0 126 | of llsString: 127 | result = min(bufLen, len(s.s) - s.rd) 128 | if result > 0: 129 | copyMem(buf, addr(s.s[0 + s.rd]), result) 130 | inc(s.rd, result) 131 | of llsFile: 132 | result = readBuffer(s.f, buf, bufLen) 133 | of llsStdIn: 134 | result = s.repl(s, buf, bufLen) 135 | 136 | proc llStreamReadLine*(s: PLLStream, line: var string): bool = 137 | setLen(line, 0) 138 | case s.kind 139 | of llsNone: 140 | result = true 141 | of llsString: 142 | while s.rd < len(s.s): 143 | case s.s[s.rd] 144 | of '\x0D': 145 | inc(s.rd) 146 | if s.s[s.rd] == '\x0A': inc(s.rd) 147 | break 148 | of '\x0A': 149 | inc(s.rd) 150 | break 151 | else: 152 | add(line, s.s[s.rd]) 153 | inc(s.rd) 154 | result = line.len > 0 or s.rd < len(s.s) 155 | of llsFile: 156 | result = readLine(s.f, line) 157 | of llsStdIn: 158 | result = readLine(stdin, line) 159 | 160 | proc llStreamWrite*(s: PLLStream, data: string) = 161 | case s.kind 162 | of llsNone, llsStdIn: 163 | discard 164 | of llsString: 165 | add(s.s, data) 166 | inc(s.wr, len(data)) 167 | of llsFile: 168 | write(s.f, data) 169 | 170 | proc llStreamWriteln*(s: PLLStream, data: string) = 171 | llStreamWrite(s, data) 172 | llStreamWrite(s, "\n") 173 | 174 | proc llStreamWrite*(s: PLLStream, data: char) = 175 | var c: char 176 | case s.kind 177 | of llsNone, llsStdIn: 178 | discard 179 | of llsString: 180 | add(s.s, data) 181 | inc(s.wr) 182 | of llsFile: 183 | c = data 184 | discard writeBuffer(s.f, addr(c), sizeof(c)) 185 | 186 | proc llStreamWrite*(s: PLLStream, buf: pointer, buflen: int) = 187 | case s.kind 188 | of llsNone, llsStdIn: 189 | discard 190 | of llsString: 191 | if buflen > 0: 192 | setLen(s.s, len(s.s) + buflen) 193 | copyMem(addr(s.s[0 + s.wr]), buf, buflen) 194 | inc(s.wr, buflen) 195 | of llsFile: 196 | discard writeBuffer(s.f, buf, buflen) 197 | 198 | proc llStreamReadAll*(s: PLLStream): string = 199 | const 200 | bufSize = 2048 201 | case s.kind 202 | of llsNone, llsStdIn: 203 | result = "" 204 | of llsString: 205 | if s.rd == 0: result = s.s 206 | else: result = substr(s.s, s.rd) 207 | s.rd = len(s.s) 208 | of llsFile: 209 | result = newString(bufSize) 210 | var bytes = readBuffer(s.f, addr(result[0]), bufSize) 211 | var i = bytes 212 | while bytes == bufSize: 213 | setLen(result, i + bufSize) 214 | bytes = readBuffer(s.f, addr(result[i + 0]), bufSize) 215 | inc(i, bytes) 216 | setLen(result, i) 217 | -------------------------------------------------------------------------------- /compiler/wordrecg.nim: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # The Nim Compiler 4 | # (c) Copyright 2015 Andreas Rumpf 5 | # 6 | # See the file "copying.txt", included in this 7 | # distribution, for details about the copyright. 8 | # 9 | 10 | # This module contains a word recognizer, i.e. a simple 11 | # procedure which maps special words to an enumeration. 12 | # It is primarily needed because Pascal's case statement 13 | # does not support strings. Without this the code would 14 | # be slow and unreadable. 15 | 16 | from strutils import cmpIgnoreStyle 17 | 18 | # Keywords must be kept sorted and within a range 19 | 20 | type 21 | TSpecialWord* = enum 22 | wInvalid, 23 | 24 | wAddr, wAnd, wAs, wAsm, 25 | wBind, wBlock, wBreak, wCase, wCast, wConcept, wConst, 26 | wContinue, wConverter, wDefer, wDiscard, wDistinct, wDiv, wDo, 27 | wElif, wElse, wEnd, wEnum, wExcept, wExport, 28 | wFinally, wFor, wFrom, wFunc, wIf, wImport, wIn, 29 | wInclude, wInterface, wIs, wIsnot, wIterator, wLet, 30 | wMacro, wMethod, wMixin, wMod, wNil, 31 | wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, 32 | wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar, 33 | wWhen, wWhile, wXor, wYield, 34 | 35 | wColon, wColonColon, wEquals, wDot, wDotDot, 36 | wStar, wMinus, 37 | wMagic, wThread, wFinal, wProfiler, wMemTracker, wObjChecks, 38 | wIntDefine, wStrDefine, wBoolDefine 39 | 40 | wCursor, 41 | 42 | wImmediate, wConstructor, wDestructor, wDelegator, wOverride, 43 | wImportCpp, wImportObjC, 44 | wImportCompilerProc, 45 | wImportc, wExportc, wExportNims, wIncompleteStruct, wRequiresInit, 46 | wAlign, wNodecl, wPure, wSideEffect, wHeader, 47 | wNoSideEffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib, 48 | wCompilerProc, wCore, wProcVar, wBase, wUsed, 49 | wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef, 50 | wLineDir, wStackTrace, wLineTrace, wLink, wCompile, 51 | wLinksys, wDeprecated, wVarargs, wCallconv, wBreakpoint, wDebugger, 52 | wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline, 53 | wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangeChecks, 54 | wBoundChecks, wOverflowChecks, wNilChecks, 55 | wFloatChecks, wNanChecks, wInfChecks, wStyleChecks, 56 | wNonReloadable, wExecuteOnReload, 57 | wAssertions, wPatterns, wTrMacros, wWarnings, 58 | wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags, 59 | wDeadCodeElimUnused, # deprecated, dead code elim always happens 60 | wSafecode, wPackage, wNoForward, wReorder, wNoRewrite, wNoDestroy, 61 | wPragma, 62 | wCompileTime, wNoInit, 63 | wPassc, wPassl, wBorrow, wDiscardable, 64 | wFieldChecks, 65 | wWatchPoint, wSubsChar, 66 | wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, 67 | wInjectStmt, wExperimental, 68 | wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, 69 | wAsmNoStackFrame, 70 | wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks, 71 | wPartial, wExplain, wLiftLocals, 72 | 73 | wAuto, wBool, wCatch, wChar, wClass, wCompl 74 | wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast, 75 | wExplicit, wExtern, wFalse, wFloat, wFriend, 76 | wGoto, wInt, wLong, wMutable, wNamespace, wNew, wOperator, 77 | wPrivate, wProtected, wPublic, wRegister, wReinterpret_cast, wRestrict, 78 | wShort, wSigned, wSizeof, wStatic_cast, wStruct, wSwitch, 79 | wThis, wThrow, wTrue, wTypedef, wTypeid, wTypeof, wTypename, 80 | wUnion, wPacked, wUnsigned, wVirtual, wVoid, wVolatile, wWchar_t, 81 | 82 | wAlignas, wAlignof, wConstexpr, wDecltype, wNullptr, wNoexcept, 83 | wThread_local, wStatic_assert, wChar16_t, wChar32_t, 84 | 85 | wStdIn, wStdOut, wStdErr, 86 | 87 | wInOut, wByCopy, wByRef, wOneWay, 88 | wBitsize 89 | 90 | TSpecialWords* = set[TSpecialWord] 91 | 92 | const 93 | oprLow* = ord(wColon) 94 | oprHigh* = ord(wDotDot) 95 | 96 | nimKeywordsLow* = ord(wAsm) 97 | nimKeywordsHigh* = ord(wYield) 98 | 99 | ccgKeywordsLow* = ord(wAuto) 100 | ccgKeywordsHigh* = ord(wOneWay) 101 | 102 | cppNimSharedKeywords* = { 103 | wAsm, wBreak, wCase, wConst, wContinue, wDo, wElse, wEnum, wExport, 104 | wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile, wUsing} 105 | 106 | specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["", 107 | 108 | "addr", "and", "as", "asm", 109 | "bind", "block", "break", "case", "cast", 110 | "concept", "const", "continue", "converter", 111 | "defer", "discard", "distinct", "div", "do", 112 | "elif", "else", "end", "enum", "except", "export", 113 | "finally", "for", "from", "func", "if", 114 | "import", "in", "include", "interface", "is", "isnot", "iterator", 115 | "let", 116 | "macro", "method", "mixin", "mod", "nil", "not", "notin", 117 | "object", "of", "or", 118 | "out", "proc", "ptr", "raise", "ref", "return", 119 | "shl", "shr", "static", 120 | "template", "try", "tuple", "type", "using", "var", 121 | "when", "while", "xor", 122 | "yield", 123 | 124 | ":", "::", "=", ".", "..", 125 | "*", "-", 126 | "magic", "thread", "final", "profiler", "memtracker", "objchecks", 127 | "intdefine", "strdefine", "booldefine", 128 | 129 | "cursor", 130 | 131 | "immediate", "constructor", "destructor", "delegator", "override", 132 | "importcpp", "importobjc", 133 | "importcompilerproc", "importc", "exportc", "exportnims", 134 | "incompletestruct", 135 | "requiresinit", "align", "nodecl", "pure", "sideeffect", 136 | "header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib", 137 | "compilerproc", "core", "procvar", "base", "used", 138 | "fatal", "error", "warning", "hint", "line", 139 | "push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace", 140 | "link", "compile", "linksys", "deprecated", "varargs", 141 | "callconv", "breakpoint", "debugger", "nimcall", "stdcall", 142 | "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "closure", 143 | "noconv", "on", "off", "checks", "rangechecks", "boundchecks", 144 | "overflowchecks", "nilchecks", 145 | "floatchecks", "nanchecks", "infchecks", "stylechecks", 146 | "nonreloadable", "executeonreload", 147 | 148 | "assertions", "patterns", "trmacros", "warnings", "hints", 149 | "optimization", "raises", "writes", "reads", "size", "effects", "tags", 150 | "deadcodeelim", # deprecated, dead code elim always happens 151 | "safecode", "package", "noforward", "reorder", "norewrite", "nodestroy", 152 | "pragma", 153 | "compiletime", "noinit", 154 | "passc", "passl", "borrow", "discardable", "fieldchecks", 155 | "watchpoint", 156 | "subschar", "acyclic", "shallow", "unroll", "linearscanend", 157 | "computedgoto", "injectstmt", "experimental", 158 | "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", 159 | "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked", 160 | "guard", "locks", "partial", "explain", "liftlocals", 161 | 162 | "auto", "bool", "catch", "char", "class", "compl", 163 | "const_cast", "default", "delete", "double", 164 | "dynamic_cast", "explicit", "extern", "false", 165 | "float", "friend", "goto", "int", "long", "mutable", 166 | "namespace", "new", "operator", 167 | "private", "protected", "public", "register", "reinterpret_cast", "restrict", 168 | "short", "signed", "sizeof", "static_cast", "struct", "switch", 169 | "this", "throw", "true", "typedef", "typeid", "typeof", 170 | "typename", "union", "packed", "unsigned", "virtual", "void", "volatile", 171 | "wchar_t", 172 | 173 | "alignas", "alignof", "constexpr", "decltype", "nullptr", "noexcept", 174 | "thread_local", "static_assert", "char16_t", "char32_t", 175 | 176 | "stdin", "stdout", "stderr", 177 | 178 | "inout", "bycopy", "byref", "oneway", 179 | "bitsize" 180 | ] 181 | 182 | proc findStr*(a: openArray[string], s: string): int = 183 | for i in low(a) .. high(a): 184 | if cmpIgnoreStyle(a[i], s) == 0: 185 | return i 186 | result = - 1 187 | 188 | proc canonPragmaSpelling*(w: TSpecialWord): string = 189 | case w 190 | of wNoSideEffect: "noSideEffect" 191 | of wImportCompilerProc: "importCompilerProc" 192 | of wIncompleteStruct: "incompleteStruct" 193 | of wRequiresInit: "requiresInit" 194 | of wSideEffect: "sideEffect" 195 | of wLineDir: "lineDir" 196 | of wStackTrace: "stackTrace" 197 | of wLineTrace: "lineTrace" 198 | of wRangeChecks: "rangeChecks" 199 | of wBoundChecks: "boundChecks" 200 | of wOverflowChecks: "overflowChecks" 201 | of wNilChecks: "nilChecks" 202 | of wFloatChecks: "floatChecks" 203 | of wNanChecks: "nanChecks" 204 | of wInfChecks: "infChecks" 205 | of wStyleChecks: "styleChecks" 206 | of wNonReloadable: "nonReloadable" 207 | of wExecuteOnReload: "executeOnReload" 208 | of wDeadCodeElimUnused: "deadCodeElim" 209 | of wCompileTime: "compileTime" 210 | of wFieldChecks: "fieldChecks" 211 | of wLinearScanEnd: "linearScanEnd" 212 | of wComputedGoto: "computedGoto" 213 | of wInjectStmt: "injectStmt" 214 | of wAsmNoStackFrame: "asmNoStackframe" 215 | of wImplicitStatic: "implicitStatic" 216 | of wCodegenDecl: "codegenDecl" 217 | of wLiftLocals: "liftLocals" 218 | else: specialWords[w] 219 | -------------------------------------------------------------------------------- /testsuite/results/matrix.nim: -------------------------------------------------------------------------------- 1 | ## ////////////////////////////////////////////////////////////////////////// 2 | ## Name: wx/matrix.h 3 | ## Purpose: wxTransformMatrix class. NOT YET USED 4 | ## Author: Chris Breeze, Julian Smart 5 | ## Modified by: Klaas Holwerda 6 | ## Created: 01/02/97 7 | ## RCS-ID: $Id$ 8 | ## Copyright: (c) Julian Smart, Chris Breeze 9 | ## Licence: wxWindows licence 10 | ## ////////////////////////////////////////////////////////////////////////// 11 | 12 | ## ! headerfiles="matrix.h wx/object.h" 13 | 14 | import 15 | wx/object, wx/math 16 | 17 | ## ! codefiles="matrix.cpp" 18 | ## A simple 3x3 matrix. This may be replaced by a more general matrix 19 | ## class some day. 20 | ## 21 | ## Note: this is intended to be used in wxDC at some point to replace 22 | ## the current system of scaling/translation. It is not yet used. 23 | 24 | ## :definition 25 | ## A 3x3 matrix to do 2D transformations. 26 | ## It can be used to map data to window coordinates, 27 | ## and also for manipulating your own data. 28 | ## For example drawing a picture (composed of several primitives) 29 | ## at a certain coordinate and angle within another parent picture. 30 | ## At all times m_isIdentity is set if the matrix itself is an Identity matrix. 31 | ## It is used where possible to optimize calculations. 32 | 33 | type 34 | wxTransformMatrix* {.importcpp: "wxTransformMatrix", header: "wxmatrix.h", 35 | bycopy.} = object of wxObject[string, string[ubyte]] 36 | m_matrix* {.importc: "m_matrix".}: array[3, array[3, cdouble]] 37 | m_isIdentity* {.importc: "m_isIdentity".}: bool 38 | 39 | 40 | proc constructwxTransformMatrix*(): wxTransformMatrix {.constructor, 41 | importcpp: "wxTransformMatrix(@)", header: "wxmatrix.h".} 42 | proc constructwxTransformMatrix*(mat: wxTransformMatrix): wxTransformMatrix {. 43 | constructor, importcpp: "wxTransformMatrix(@)", header: "wxmatrix.h".} 44 | proc destroywxTransformMatrix*(this: var wxTransformMatrix) {. 45 | importcpp: "#.~wxTransformMatrix()", header: "wxmatrix.h".} 46 | proc GetValue*(this: wxTransformMatrix; col: cint; row: cint): cdouble {. 47 | noSideEffect, importcpp: "GetValue", header: "wxmatrix.h".} 48 | proc SetValue*(this: var wxTransformMatrix; col: cint; row: cint; value: cdouble) {. 49 | importcpp: "SetValue", header: "wxmatrix.h".} 50 | proc `==`*(this: wxTransformMatrix; mat: wxTransformMatrix): bool {. 51 | noSideEffect, importcpp: "(# == #)", header: "wxmatrix.h".} 52 | proc `*=`*(this: var wxTransformMatrix; t: cdouble) {.importcpp: "(# *= #)", 53 | header: "wxmatrix.h".} 54 | proc `/=`*(this: var wxTransformMatrix; t: cdouble) {.importcpp: "(# /= #)", 55 | header: "wxmatrix.h".} 56 | proc `+=`*(this: var wxTransformMatrix; m: wxTransformMatrix) {. 57 | importcpp: "(# += #)", header: "wxmatrix.h".} 58 | proc `-=`*(this: var wxTransformMatrix; m: wxTransformMatrix) {. 59 | importcpp: "(# -= #)", header: "wxmatrix.h".} 60 | proc `*=`*(this: var wxTransformMatrix; m: wxTransformMatrix) {. 61 | importcpp: "(# *= #)", header: "wxmatrix.h".} 62 | proc `*`*(this: wxTransformMatrix; t: cdouble): wxTransformMatrix {. 63 | noSideEffect, importcpp: "(# * #)", header: "wxmatrix.h".} 64 | proc `/`*(this: wxTransformMatrix; t: cdouble): wxTransformMatrix {. 65 | noSideEffect, importcpp: "(# / #)", header: "wxmatrix.h".} 66 | proc `+`*(this: wxTransformMatrix; m: wxTransformMatrix): wxTransformMatrix {. 67 | noSideEffect, importcpp: "(# + #)", header: "wxmatrix.h".} 68 | proc `-`*(this: wxTransformMatrix; m: wxTransformMatrix): wxTransformMatrix {. 69 | noSideEffect, importcpp: "(# - #)", header: "wxmatrix.h".} 70 | proc `*`*(this: wxTransformMatrix; m: wxTransformMatrix): wxTransformMatrix {. 71 | noSideEffect, importcpp: "(# * #)", header: "wxmatrix.h".} 72 | proc `-`*(this: wxTransformMatrix): wxTransformMatrix {.noSideEffect, 73 | importcpp: "(- #)", header: "wxmatrix.h".} 74 | proc `()`*(this: var wxTransformMatrix; col: cint; row: cint): var cdouble {. 75 | importcpp: "#(@)", header: "wxmatrix.h".} 76 | proc `()`*(this: wxTransformMatrix; col: cint; row: cint): cdouble {. 77 | noSideEffect, importcpp: "#(@)", header: "wxmatrix.h".} 78 | proc Invert*(this: var wxTransformMatrix): bool {.importcpp: "Invert", 79 | header: "wxmatrix.h".} 80 | proc Identity*(this: var wxTransformMatrix): bool {.importcpp: "Identity", 81 | header: "wxmatrix.h".} 82 | proc IsIdentity*(this: wxTransformMatrix): bool {.inline, noSideEffect.} = 83 | return m_isIdentity 84 | 85 | proc IsIdentity1*(this: wxTransformMatrix): bool {.inline, noSideEffect, 86 | importcpp: "IsIdentity1", header: "wxmatrix.h".} 87 | proc Scale*(this: var wxTransformMatrix; scale: cdouble): bool {. 88 | importcpp: "Scale", header: "wxmatrix.h".} 89 | proc Scale*(this: var wxTransformMatrix; xs: cdouble; ys: cdouble; xc: cdouble; 90 | yc: cdouble): var wxTransformMatrix {.importcpp: "Scale", 91 | header: "wxmatrix.h".} 92 | proc Mirror*(this: var wxTransformMatrix; x: bool = true; y: bool = false): var wxTransformMatrix[ 93 | cfloat] {.importcpp: "Mirror", header: "wxmatrix.h".} 94 | proc Translate*(this: var wxTransformMatrix; x: cdouble; y: cdouble): bool {. 95 | importcpp: "Translate", header: "wxmatrix.h".} 96 | proc Rotate*(this: var wxTransformMatrix; angle: cdouble): bool {. 97 | importcpp: "Rotate", header: "wxmatrix.h".} 98 | proc Rotate*(this: var wxTransformMatrix; r: cdouble; x: cdouble; y: cdouble): var wxTransformMatrix {. 99 | importcpp: "Rotate", header: "wxmatrix.h".} 100 | proc TransformX*(this: wxTransformMatrix; x: cdouble): cdouble {.inline, 101 | noSideEffect, importcpp: "TransformX", header: "wxmatrix.h".} 102 | proc TransformY*(this: wxTransformMatrix; y: cdouble): cdouble {.inline, 103 | noSideEffect, importcpp: "TransformY", header: "wxmatrix.h".} 104 | proc TransformPoint*(this: wxTransformMatrix; x: cdouble; y: cdouble; 105 | tx: var cdouble; ty: var cdouble): bool {.noSideEffect, 106 | importcpp: "TransformPoint", header: "wxmatrix.h".} 107 | proc InverseTransformPoint*(this: wxTransformMatrix; x: cdouble; y: cdouble; 108 | tx: var cdouble; ty: var cdouble): bool {. 109 | noSideEffect, importcpp: "InverseTransformPoint", header: "wxmatrix.h".} 110 | proc Get_scaleX*(this: var wxTransformMatrix): cdouble {. 111 | importcpp: "Get_scaleX", header: "wxmatrix.h".} 112 | proc Get_scaleY*(this: var wxTransformMatrix): cdouble {. 113 | importcpp: "Get_scaleY", header: "wxmatrix.h".} 114 | proc GetRotation*(this: var wxTransformMatrix): cdouble {. 115 | importcpp: "GetRotation", header: "wxmatrix.h".} 116 | proc SetRotation*(this: var wxTransformMatrix; rotation: cdouble) {. 117 | importcpp: "SetRotation", header: "wxmatrix.h".} 118 | ## 119 | ## Chris Breeze reported, that 120 | ## some functions of wxTransformMatrix cannot work because it is not 121 | ## known if he matrix has been inverted. Be careful when using it. 122 | ## 123 | ## Transform X value from logical to device 124 | ## warning: this function can only be used for this purpose 125 | ## because no rotation is involved when mapping logical to device coordinates 126 | ## mirror and scaling for x and y will be part of the matrix 127 | ## if you have a matrix that is rotated, eg a shape containing a matrix to place 128 | ## it in the logical coordinate system, use TransformPoint 129 | 130 | proc TransformX*(this: wxTransformMatrix; x: cdouble): cdouble {.inline, 131 | noSideEffect.} = 132 | ## normally like this, but since no rotation is involved (only mirror and scale) 133 | ## we can do without Y -> m_matrix[1]{0] is -sin(rotation angle) and therefore zero 134 | ## (x * m_matrix[0][0] + y * m_matrix[1][0] + m_matrix[2][0])) 135 | return if m_isIdentity: x else: (x * m_matrix[0][0] + m_matrix[2][0]) 136 | 137 | ## Transform Y value from logical to device 138 | ## warning: this function can only be used for this purpose 139 | ## because no rotation is involved when mapping logical to device coordinates 140 | ## mirror and scaling for x and y will be part of the matrix 141 | ## if you have a matrix that is rotated, eg a shape containing a matrix to place 142 | ## it in the logical coordinate system, use TransformPoint 143 | 144 | proc TransformY*(this: wxTransformMatrix; y: cdouble): cdouble {.inline, 145 | noSideEffect.} = 146 | ## normally like this, but since no rotation is involved (only mirror and scale) 147 | ## we can do without X -> m_matrix[0]{1] is sin(rotation angle) and therefore zero 148 | ## (x * m_matrix[0][1] + y * m_matrix[1][1] + m_matrix[2][1])) 149 | return if m_isIdentity: y else: (y * m_matrix[1][1] + m_matrix[2][1]) 150 | 151 | ## Is the matrix the identity matrix? 152 | ## Each operation checks whether the result is still the identity matrix and sets a flag. 153 | 154 | proc IsIdentity1*(this: wxTransformMatrix): bool {.inline, noSideEffect.} = 155 | return wxIsSameDouble(m_matrix[0][0], 1.0) and 156 | wxIsSameDouble(m_matrix[1][1], 1.0) and 157 | wxIsSameDouble(m_matrix[2][2], 1.0) and 158 | wxIsSameDouble(m_matrix[1][0], 0.0) and 159 | wxIsSameDouble(m_matrix[2][0], 0.0) and 160 | wxIsSameDouble(m_matrix[0][1], 0.0) and 161 | wxIsSameDouble(m_matrix[2][1], 0.0) and 162 | wxIsSameDouble(m_matrix[0][2], 0.0) and 163 | wxIsSameDouble(m_matrix[1][2], 0.0) 164 | 165 | ## Calculates the determinant of a 2 x 2 matrix 166 | 167 | proc wxCalculateDet*(a11: cdouble; a21: cdouble; a12: cdouble; a22: cdouble): cdouble {. 168 | inline.} = 169 | return a11 * a22 - a12 * a21 170 | -------------------------------------------------------------------------------- /compiler/pathutils.nim: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # The Nim Compiler 4 | # (c) Copyright 2018 Andreas Rumpf 5 | # 6 | # See the file "copying.txt", included in this 7 | # distribution, for details about the copyright. 8 | # 9 | 10 | ## Path handling utilities for Nim. Strictly typed code in order 11 | ## to avoid the never ending time sink in getting path handling right. 12 | ## Might be a candidate for the stdlib later. 13 | 14 | import os, strutils 15 | 16 | type 17 | AbsoluteFile* = distinct string 18 | AbsoluteDir* = distinct string 19 | RelativeFile* = distinct string 20 | RelativeDir* = distinct string 21 | 22 | proc isEmpty*(x: AbsoluteFile): bool {.inline.} = x.string.len == 0 23 | proc isEmpty*(x: AbsoluteDir): bool {.inline.} = x.string.len == 0 24 | proc isEmpty*(x: RelativeFile): bool {.inline.} = x.string.len == 0 25 | proc isEmpty*(x: RelativeDir): bool {.inline.} = x.string.len == 0 26 | 27 | proc copyFile*(source, dest: AbsoluteFile) = 28 | os.copyFile(source.string, dest.string) 29 | 30 | proc removeFile*(x: AbsoluteFile) {.borrow.} 31 | 32 | proc splitFile*(x: AbsoluteFile): tuple[dir: AbsoluteDir, name, ext: string] = 33 | let (a, b, c) = splitFile(x.string) 34 | result = (dir: AbsoluteDir(a), name: b, ext: c) 35 | 36 | proc extractFilename*(x: AbsoluteFile): string {.borrow.} 37 | 38 | proc fileExists*(x: AbsoluteFile): bool {.borrow.} 39 | proc dirExists*(x: AbsoluteDir): bool {.borrow.} 40 | 41 | proc quoteShell*(x: AbsoluteFile): string {.borrow.} 42 | proc quoteShell*(x: AbsoluteDir): string {.borrow.} 43 | 44 | proc cmpPaths*(x, y: AbsoluteDir): int {.borrow.} 45 | 46 | proc createDir*(x: AbsoluteDir) {.borrow.} 47 | 48 | type 49 | PathIter = object 50 | i, prev: int 51 | notFirst: bool 52 | 53 | proc hasNext(it: PathIter; x: string): bool = 54 | it.i < x.len 55 | 56 | proc next(it: var PathIter; x: string): (int, int) = 57 | it.prev = it.i 58 | if not it.notFirst and x[it.i] in {DirSep, AltSep}: 59 | # absolute path: 60 | inc it.i 61 | else: 62 | while it.i < x.len and x[it.i] notin {DirSep, AltSep}: inc it.i 63 | if it.i > it.prev: 64 | result = (it.prev, it.i-1) 65 | elif hasNext(it, x): 66 | result = next(it, x) 67 | 68 | # skip all separators: 69 | while it.i < x.len and x[it.i] in {DirSep, AltSep}: inc it.i 70 | it.notFirst = true 71 | 72 | iterator dirs(x: string): (int, int) = 73 | var it: PathIter 74 | while hasNext(it, x): yield next(it, x) 75 | 76 | when false: 77 | iterator dirs(x: string): (int, int) = 78 | var i = 0 79 | var first = true 80 | while i < x.len: 81 | let prev = i 82 | if first and x[i] in {DirSep, AltSep}: 83 | # absolute path: 84 | inc i 85 | else: 86 | while i < x.len and x[i] notin {DirSep, AltSep}: inc i 87 | if i > prev: 88 | yield (prev, i-1) 89 | first = false 90 | # skip all separators: 91 | while i < x.len and x[i] in {DirSep, AltSep}: inc i 92 | 93 | proc isDot(x: string; bounds: (int, int)): bool = 94 | bounds[1] == bounds[0] and x[bounds[0]] == '.' 95 | 96 | proc isDotDot(x: string; bounds: (int, int)): bool = 97 | bounds[1] == bounds[0] + 1 and x[bounds[0]] == '.' and x[bounds[0]+1] == '.' 98 | 99 | proc isSlash(x: string; bounds: (int, int)): bool = 100 | bounds[1] == bounds[0] and x[bounds[0]] in {DirSep, AltSep} 101 | 102 | const canonDirSep = when isMainModule: '/' else: DirSep 103 | 104 | proc canon(x: string; result: var string; state: var int) = 105 | # state: 0th bit set if isAbsolute path. Other bits count 106 | # the number of path components. 107 | for b in dirs(x): 108 | if (state shr 1 == 0) and isSlash(x, b): 109 | result.add canonDirSep 110 | state = state or 1 111 | elif result.len > (state and 1) and isDotDot(x, b): 112 | var d = result.len 113 | # f/.. 114 | while (d-1) > (state and 1) and result[d-1] notin {DirSep, AltSep}: 115 | dec d 116 | if d > 0: setLen(result, d-1) 117 | elif isDot(x, b): 118 | discard "discard the dot" 119 | elif b[1] >= b[0]: 120 | if result.len > 0 and result[^1] notin {DirSep, AltSep}: 121 | result.add canonDirSep 122 | result.add substr(x, b[0], b[1]) 123 | inc state, 2 124 | 125 | proc canon(x: string): string = 126 | # - Turn multiple slashes into single slashes. 127 | # - Resolve '/foo/../bar' to '/bar'. 128 | # - Remove './' from the path. 129 | result = newStringOfCap(x.len) 130 | var state = 0 131 | canon(x, result, state) 132 | 133 | when FileSystemCaseSensitive: 134 | template `!=?`(a, b: char): bool = toLowerAscii(a) != toLowerAscii(b) 135 | else: 136 | template `!=?`(a, b: char): bool = a != b 137 | 138 | proc relativeTo(full, base: string; sep = canonDirSep): string = 139 | if full.len == 0: return "" 140 | var f, b: PathIter 141 | var ff = (0, -1) 142 | var bb = (0, -1) # (int, int) 143 | result = newStringOfCap(full.len) 144 | # skip the common prefix: 145 | while f.hasNext(full) and b.hasNext(base): 146 | ff = next(f, full) 147 | bb = next(b, base) 148 | let diff = ff[1] - ff[0] 149 | if diff != bb[1] - bb[0]: break 150 | var same = true 151 | for i in 0..diff: 152 | if full[i + ff[0]] !=? base[i + bb[0]]: 153 | same = false 154 | break 155 | if not same: break 156 | ff = (0, -1) 157 | bb = (0, -1) 158 | # for i in 0..diff: 159 | # result.add base[i + bb[0]] 160 | 161 | # /foo/bar/xxx/ -- base 162 | # /foo/bar/baz -- full path 163 | # ../baz 164 | # every directory that is in 'base', needs to add '..' 165 | while true: 166 | if bb[1] >= bb[0]: 167 | if result.len > 0 and result[^1] != sep: 168 | result.add sep 169 | result.add ".." 170 | if not b.hasNext(base): break 171 | bb = b.next(base) 172 | 173 | # add the rest of 'full': 174 | while true: 175 | if ff[1] >= ff[0]: 176 | if result.len > 0 and result[^1] != sep: 177 | result.add sep 178 | for i in 0..ff[1] - ff[0]: 179 | result.add full[i + ff[0]] 180 | if not f.hasNext(full): break 181 | ff = f.next(full) 182 | 183 | when true: 184 | proc eqImpl(x, y: string): bool = 185 | when FileSystemCaseSensitive: 186 | result = cmpIgnoreCase(canon x, canon y) == 0 187 | else: 188 | result = canon(x) == canon(y) 189 | 190 | proc `==`*(x, y: AbsoluteFile): bool = eqImpl(x.string, y.string) 191 | proc `==`*(x, y: AbsoluteDir): bool = eqImpl(x.string, y.string) 192 | proc `==`*(x, y: RelativeFile): bool = eqImpl(x.string, y.string) 193 | proc `==`*(x, y: RelativeDir): bool = eqImpl(x.string, y.string) 194 | 195 | proc `/`*(base: AbsoluteDir; f: RelativeFile): AbsoluteFile = 196 | #assert isAbsolute(base.string) 197 | assert(not isAbsolute(f.string)) 198 | result = AbsoluteFile newStringOfCap(base.string.len + f.string.len) 199 | var state = 0 200 | canon(base.string, result.string, state) 201 | canon(f.string, result.string, state) 202 | 203 | proc `/`*(base: AbsoluteDir; f: RelativeDir): AbsoluteDir = 204 | #assert isAbsolute(base.string) 205 | assert(not isAbsolute(f.string)) 206 | result = AbsoluteDir newStringOfCap(base.string.len + f.string.len) 207 | var state = 0 208 | canon(base.string, result.string, state) 209 | canon(f.string, result.string, state) 210 | 211 | proc relativeTo*(fullPath: AbsoluteFile, baseFilename: AbsoluteDir; 212 | sep = canonDirSep): RelativeFile = 213 | RelativeFile(relativeTo(fullPath.string, baseFilename.string, sep)) 214 | 215 | proc toAbsolute*(file: string; base: AbsoluteDir): AbsoluteFile = 216 | if isAbsolute(file): result = AbsoluteFile(file) 217 | else: result = base / RelativeFile file 218 | 219 | proc changeFileExt*(x: AbsoluteFile; ext: string): AbsoluteFile {.borrow.} 220 | proc changeFileExt*(x: RelativeFile; ext: string): RelativeFile {.borrow.} 221 | 222 | proc addFileExt*(x: AbsoluteFile; ext: string): AbsoluteFile {.borrow.} 223 | proc addFileExt*(x: RelativeFile; ext: string): RelativeFile {.borrow.} 224 | 225 | proc writeFile*(x: AbsoluteFile; content: string) {.borrow.} 226 | 227 | when isMainModule: 228 | doAssert canon"/foo/../bar" == "/bar" 229 | doAssert canon"foo/../bar" == "bar" 230 | 231 | doAssert canon"/f/../bar///" == "/bar" 232 | doAssert canon"f/..////bar" == "bar" 233 | 234 | doAssert canon"../bar" == "../bar" 235 | doAssert canon"/../bar" == "/../bar" 236 | 237 | doAssert canon("foo/../../bar/") == "../bar" 238 | doAssert canon("./bla/blob/") == "bla/blob" 239 | doAssert canon(".hiddenFile") == ".hiddenFile" 240 | doAssert canon("./bla/../../blob/./zoo.nim") == "../blob/zoo.nim" 241 | 242 | doAssert canon("C:/file/to/this/long") == "C:/file/to/this/long" 243 | doAssert canon("") == "" 244 | doAssert canon("foobar") == "foobar" 245 | doAssert canon("f/////////") == "f" 246 | 247 | doAssert relativeTo("/foo/bar//baz.nim", "/foo") == "bar/baz.nim" 248 | 249 | doAssert relativeTo("/Users/me/bar/z.nim", "/Users/other/bad") == "../../me/bar/z.nim" 250 | 251 | doAssert relativeTo("/Users/me/bar/z.nim", "/Users/other") == "../me/bar/z.nim" 252 | doAssert relativeTo("/Users///me/bar//z.nim", "//Users/") == "me/bar/z.nim" 253 | doAssert relativeTo("/Users/me/bar/z.nim", "/Users/me") == "bar/z.nim" 254 | doAssert relativeTo("", "/users/moo") == "" 255 | doAssert relativeTo("foo", "") == "foo" 256 | 257 | doAssert AbsoluteDir"/Users/me///" / RelativeFile"z.nim" == AbsoluteFile"/Users/me/z.nim" 258 | doAssert relativeTo("/foo/bar.nim", "/foo/") == "bar.nim" 259 | 260 | when isMainModule and defined(windows): 261 | let nasty = string(AbsoluteDir(r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\linkedPkgs\pkgB-#head\../../simplePkgs/pkgB-#head/") / RelativeFile"pkgA/module.nim") 262 | doAssert nasty.replace('/', '\\') == r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\simplePkgs\pkgB-#head\pkgA\module.nim" 263 | -------------------------------------------------------------------------------- /testsuite/tests/matrix.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Name: wx/matrix.h 3 | // Purpose: wxTransformMatrix class. NOT YET USED 4 | // Author: Chris Breeze, Julian Smart 5 | // Modified by: Klaas Holwerda 6 | // Created: 01/02/97 7 | // RCS-ID: $Id$ 8 | // Copyright: (c) Julian Smart, Chris Breeze 9 | // Licence: wxWindows licence 10 | ///////////////////////////////////////////////////////////////////////////// 11 | 12 | #ifndef _WX_MATRIXH__ 13 | #define _WX_MATRIXH__ 14 | 15 | //! headerfiles="matrix.h wx/object.h" 16 | #include "wx/object.h" 17 | #include "wx/math.h" 18 | 19 | //! codefiles="matrix.cpp" 20 | 21 | // A simple 3x3 matrix. This may be replaced by a more general matrix 22 | // class some day. 23 | // 24 | // Note: this is intended to be used in wxDC at some point to replace 25 | // the current system of scaling/translation. It is not yet used. 26 | 27 | #def WXDLLIMPEXP_CORE 28 | #header "wxmatrix.h" 29 | #keepbodies 30 | 31 | //:definition 32 | // A 3x3 matrix to do 2D transformations. 33 | // It can be used to map data to window coordinates, 34 | // and also for manipulating your own data. 35 | // For example drawing a picture (composed of several primitives) 36 | // at a certain coordinate and angle within another parent picture. 37 | // At all times m_isIdentity is set if the matrix itself is an Identity matrix. 38 | // It is used where possible to optimize calculations. 39 | class WXDLLIMPEXP_CORE wxTransformMatrix: public wxObject> 40 | { 41 | public: 42 | wxTransformMatrix(void); 43 | wxTransformMatrix(const wxTransformMatrix& mat); 44 | 45 | ~wxTransformMatrix(void); 46 | 47 | //get the value in the matrix at col,row 48 | //rows are horizontal (second index of m_matrix member) 49 | //columns are vertical (first index of m_matrix member) 50 | double GetValue(int col, int row) const; 51 | 52 | //set the value in the matrix at col,row 53 | //rows are horizontal (second index of m_matrix member) 54 | //columns are vertical (first index of m_matrix member) 55 | void SetValue(int col, int row, double value); 56 | 57 | void operator = (const wxTransformMatrix& mat); 58 | bool operator == (const wxTransformMatrix& mat) const; 59 | bool operator != (const module::gah::wxTransformMatrix& mat) const; 60 | 61 | //multiply every element by t 62 | wxTransformMatrix& operator*=(const double& t); 63 | //divide every element by t 64 | wxTransformMatrix& operator/=(const double& t); 65 | //add matrix m to this t 66 | wxTransformMatrix& operator+=(const wxTransformMatrix& m); 67 | //subtract matrix m from this 68 | wxTransformMatrix& operator-=(const wxTransformMatrix& m); 69 | //multiply matrix m with this 70 | wxTransformMatrix& operator*=(const wxTransformMatrix& m); 71 | 72 | // constant operators 73 | 74 | //multiply every element by t and return result 75 | wxTransformMatrix operator*(const double& t) const; 76 | //divide this matrix by t and return result 77 | wxTransformMatrix operator/(const double& t) const; 78 | //add matrix m to this and return result 79 | wxTransformMatrix operator+(const wxTransformMatrix& m) const; 80 | //subtract matrix m from this and return result 81 | wxTransformMatrix operator-(const wxTransformMatrix& m) const; 82 | //multiply this by matrix m and return result 83 | wxTransformMatrix operator*(const wxTransformMatrix& m) const; 84 | wxTransformMatrix operator-() const; 85 | 86 | //rows are horizontal (second index of m_matrix member) 87 | //columns are vertical (first index of m_matrix member) 88 | double& operator()(int col, int row); 89 | 90 | //rows are horizontal (second index of m_matrix member) 91 | //columns are vertical (first index of m_matrix member) 92 | double operator()(int col, int row) const; 93 | 94 | // Invert matrix 95 | bool Invert(void); 96 | 97 | // Make into identity matrix 98 | bool Identity(void); 99 | 100 | // Is the matrix the identity matrix? 101 | // Only returns a flag, which is set whenever an operation 102 | // is done. 103 | inline bool IsIdentity(void) const { return m_isIdentity; } 104 | 105 | // This does an actual check. 106 | inline bool IsIdentity1(void) const ; 107 | 108 | //Scale by scale (isotropic scaling i.e. the same in x and y): 109 | //!ex: 110 | //!code: | scale 0 0 | 111 | //!code: matrix' = | 0 scale 0 | x matrix 112 | //!code: | 0 0 scale | 113 | bool Scale(double scale); 114 | 115 | //Scale with center point and x/y scale 116 | // 117 | //!ex: 118 | //!code: | xs 0 xc(1-xs) | 119 | //!code: matrix' = | 0 ys yc(1-ys) | x matrix 120 | //!code: | 0 0 1 | 121 | wxTransformMatrix& Scale(const double &xs, const double &ys,const double &xc, const double &yc); 122 | 123 | // mirror a matrix in x, y 124 | //!ex: 125 | //!code: | -1 0 0 | 126 | //!code: matrix' = | 0 -1 0 | x matrix 127 | //!code: | 0 0 1 | 128 | wxTransformMatrix& Mirror(bool x=true, bool y=false); 129 | // Translate by dx, dy: 130 | //!ex: 131 | //!code: | 1 0 dx | 132 | //!code: matrix' = | 0 1 dy | x matrix 133 | //!code: | 0 0 1 | 134 | bool Translate(double x, double y); 135 | 136 | // Rotate clockwise by the given number of degrees: 137 | //!ex: 138 | //!code: | cos sin 0 | 139 | //!code: matrix' = | -sin cos 0 | x matrix 140 | //!code: | 0 0 1 | 141 | bool Rotate(double angle); 142 | 143 | //Rotate counter clockwise with point of rotation 144 | // 145 | //!ex: 146 | //!code: | cos(r) -sin(r) x(1-cos(r))+y(sin(r)| 147 | //!code: matrix' = | sin(r) cos(r) y(1-cos(r))-x(sin(r)| x matrix 148 | //!code: | 0 0 1 | 149 | wxTransformMatrix& Rotate(const double &r, const double &x, const double &y); 150 | 151 | // Transform X value from logical to device 152 | inline double TransformX(double x) const; 153 | 154 | // Transform Y value from logical to device 155 | inline double TransformY(double y) const; 156 | 157 | // Transform a point from logical to device coordinates 158 | bool TransformPoint(double x, double y, double& tx, double& ty) const; 159 | 160 | // Transform a point from device to logical coordinates. 161 | // Example of use: 162 | // wxTransformMatrix mat = dc.GetTransformation(); 163 | // mat.Invert(); 164 | // mat.InverseTransformPoint(x, y, x1, y1); 165 | // OR (shorthand:) 166 | // dc.LogicalToDevice(x, y, x1, y1); 167 | // The latter is slightly less efficient if we're doing several 168 | // conversions, since the matrix is inverted several times. 169 | // N.B. 'this' matrix is the inverse at this point 170 | bool InverseTransformPoint(double x, double y, double& tx, double& ty) const; 171 | 172 | double Get_scaleX(); 173 | double Get_scaleY(); 174 | double GetRotation(); 175 | void SetRotation(double rotation); 176 | 177 | 178 | public: 179 | double m_matrix[3][3]; 180 | bool m_isIdentity; 181 | }; 182 | 183 | 184 | /* 185 | Chris Breeze reported, that 186 | some functions of wxTransformMatrix cannot work because it is not 187 | known if he matrix has been inverted. Be careful when using it. 188 | */ 189 | 190 | // Transform X value from logical to device 191 | // warning: this function can only be used for this purpose 192 | // because no rotation is involved when mapping logical to device coordinates 193 | // mirror and scaling for x and y will be part of the matrix 194 | // if you have a matrix that is rotated, eg a shape containing a matrix to place 195 | // it in the logical coordinate system, use TransformPoint 196 | inline double wxTransformMatrix::TransformX(double x) const 197 | { 198 | //normally like this, but since no rotation is involved (only mirror and scale) 199 | //we can do without Y -> m_matrix[1]{0] is -sin(rotation angle) and therefore zero 200 | //(x * m_matrix[0][0] + y * m_matrix[1][0] + m_matrix[2][0])) 201 | return (m_isIdentity ? x : (x * m_matrix[0][0] + m_matrix[2][0])); 202 | } 203 | 204 | // Transform Y value from logical to device 205 | // warning: this function can only be used for this purpose 206 | // because no rotation is involved when mapping logical to device coordinates 207 | // mirror and scaling for x and y will be part of the matrix 208 | // if you have a matrix that is rotated, eg a shape containing a matrix to place 209 | // it in the logical coordinate system, use TransformPoint 210 | inline double wxTransformMatrix::TransformY(double y) const 211 | { 212 | //normally like this, but since no rotation is involved (only mirror and scale) 213 | //we can do without X -> m_matrix[0]{1] is sin(rotation angle) and therefore zero 214 | //(x * m_matrix[0][1] + y * m_matrix[1][1] + m_matrix[2][1])) 215 | return (m_isIdentity ? y : (y * m_matrix[1][1] + m_matrix[2][1])); 216 | } 217 | 218 | 219 | // Is the matrix the identity matrix? 220 | // Each operation checks whether the result is still the identity matrix and sets a flag. 221 | inline bool wxTransformMatrix::IsIdentity1(void) const 222 | { 223 | return 224 | ( wxIsSameDouble(m_matrix[0][0], 1.0) && 225 | wxIsSameDouble(m_matrix[1][1], 1.0) && 226 | wxIsSameDouble(m_matrix[2][2], 1.0) && 227 | wxIsSameDouble(m_matrix[1][0], 0.0) && 228 | wxIsSameDouble(m_matrix[2][0], 0.0) && 229 | wxIsSameDouble(m_matrix[0][1], 0.0) && 230 | wxIsSameDouble(m_matrix[2][1], 0.0) && 231 | wxIsSameDouble(m_matrix[0][2], 0.0) && 232 | wxIsSameDouble(m_matrix[1][2], 0.0) ); 233 | } 234 | 235 | // Calculates the determinant of a 2 x 2 matrix 236 | inline double wxCalculateDet(double a11, double a21, double a12, double a22) 237 | { 238 | return a11 * a22 - a12 * a21; 239 | } 240 | 241 | #endif // _WX_MATRIXH__ 242 | -------------------------------------------------------------------------------- /c2nim.nim: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # c2nim - C to Nim source converter 4 | # (c) Copyright 2015 Andreas Rumpf 5 | # 6 | # See the file "copying.txt", included in this 7 | # distribution, for details about the copyright. 8 | # 9 | 10 | import std / [strutils, os, osproc, times, md5, parseopt, strscans, sequtils, tables] 11 | 12 | import compiler/ [llstream, ast, renderer, options, msgs, nversion] 13 | 14 | import clexer, cparser, postprocessor 15 | 16 | when declared(NimCompilerApiVersion): 17 | import compiler / [lineinfos, pathutils] 18 | 19 | proc extractVersion(): string {.compileTime.} = 20 | let nimbleFile = staticRead("c2nim.nimble") 21 | for line in splitLines(nimbleFile): 22 | if scanf(line, "version$s=$s\"$+\"", result): break 23 | assert '.' in result 24 | 25 | const 26 | Version = extractVersion() 27 | Usage = """ 28 | c2nim - C to Nim source converter 29 | (c) 2016 Andreas Rumpf 30 | Usage: c2nim [options] [optionfile(s)] inputfile(s) [options] 31 | Optionfiles are C files with the 'c2nim' extension. These are parsed like 32 | other C files but produce no output file. 33 | Options: 34 | -o, --out:FILE set output filename 35 | --strict do not produce an output file if an error occurred 36 | --cpp process C++ input file 37 | --dynlib:SYMBOL import from dynlib: SYMBOL will be used for the import 38 | --header:HEADER_FILE import from a HEADER_FILE (discouraged!) 39 | --header import from the given header file 40 | --cdecl annotate procs with ``{.cdecl.}`` 41 | --noconv annotate procs with ``{.noconv.}`` 42 | --stdcall annotate procs with ``{.stdcall.}`` 43 | --importc annotate procs with ``{.importc.}`` 44 | --importDefines import C defines as procs or vars with ``{.importc.}`` 45 | --skipFuncDefines skip C proc defines 46 | --importFuncDefines import C define funcs as procs with ``{.importc.}`` 47 | --def:SYM='macro()' define a C macro that gets replaced with the given 48 | definition. It's parsed by the lexer. Use it to fix 49 | function attributes: ``--def:PUBLIC='__attribute__ ()'`` 50 | --reordercomments reorder C comments to match Nim's postfix style 51 | --ref convert typ* to ref typ (default: ptr typ) 52 | --prefix:PREFIX strip prefix for the generated Nim identifiers 53 | (multiple --prefix options are supported) 54 | --suffix:SUFFIX strip suffix for the generated Nim identifiers 55 | (multiple --suffix options are supported) 56 | --mangle:PEG=FORMAT extra PEG expression to mangle identifiers, 57 | for example `--mangle:'{u?}int{\d+}_t=$1int$2'` to 58 | convert C to Nim equivalents 59 | (multiple --mangle options are supported) 60 | --stdints Mangle C stdint's into Nim style int's 61 | --paramPrefix:PREFIX add prefix to parameter name of the generated Nim proc 62 | --headerPrefix:PREFIX add prefix to C header files of generated Nim imports 63 | --assumedef:IDENT skips #ifndef sections for the given C identifier 64 | (multiple --assumedef options are supported) 65 | --assumendef:IDENT skips #ifdef sections for the given C identifier 66 | (multiple --assumendef options are supported) 67 | --skipinclude do not convert ``#include`` to ``import`` 68 | --typeprefixes generate ``T`` and ``P`` type prefixes 69 | --nep1 follow 'NEP 1': Style Guide for Nim Code 70 | --skipcomments do not copy comments 71 | --delete:IDENT post process option to delete nodes with matching 72 | idents for procs, types, or vars 73 | --mergeBlocks merge similar adjacent blocks like two let sections 74 | --mergeDuplicates merge similar adjacent blocks like two let sections 75 | --ignoreRValueRefs translate C++'s ``T&&`` to ``T`` instead ``of var T`` 76 | --keepBodies keep C++'s method bodies 77 | --cppBindStatic bind cpp methods to their types 78 | --concat concat the list of files into a single .nim file 79 | --concat:all concat the list of files including c2nim files 80 | --debug prints a c2nim stack trace in case of an error 81 | --exportdll:PREFIX produce a DLL wrapping the C++ code 82 | --render:OPT various render options. See c2nim.rst for more docs 83 | -v, --version write c2nim's version 84 | -h, --help show this help 85 | """ 86 | 87 | proc isCppFile(s: string): bool = 88 | splitFile(s).ext.toLowerAscii in [".cpp", ".cxx", ".hpp"] 89 | 90 | when not declared(NimCompilerApiVersion): 91 | type AbsoluteFile = string 92 | 93 | proc parse(infile: string, options: PParserOptions; dllExport: var PNode): PNode = 94 | var stream = llStreamOpen(AbsoluteFile infile, fmRead) 95 | if stream == nil: 96 | when declared(NimCompilerApiVersion): 97 | rawMessage(gConfig, errGenerated, "cannot open file: " & infile) 98 | else: 99 | rawMessage(errGenerated, "cannot open file: " & infile) 100 | let isCpp = pfCpp notin options.flags and isCppFile(infile) 101 | var p: Parser 102 | if isCpp: options.flags.incl pfCpp 103 | openParser(p, infile, stream, options) 104 | result = parseUnit(p).postprocess(options.flags, options.deletes) 105 | closeParser(p) 106 | if isCpp: options.flags.excl pfCpp 107 | if options.exportPrefix.len > 0: 108 | let dllprocs = exportAsDll(result, options.exportPrefix) 109 | assert dllprocs.kind == nkStmtList 110 | if dllExport.isNil: 111 | dllExport = dllprocs 112 | else: 113 | for x in dllprocs: dllExport.add x 114 | 115 | proc isC2nimFile(s: string): bool = splitFile(s).ext.toLowerAscii == ".c2nim" 116 | 117 | proc parseDefines(val: string): seq[ref Token] = 118 | let tpath = getTempDir() / "macro_" & getMD5(val) & ".h" 119 | let tfl = (open(tpath, fmReadWrite), tpath) 120 | let ss = llStreamOpen(val) 121 | var lex: Lexer 122 | openLexer(lex, tfl[1], ss) 123 | var tk = new Token 124 | var idx = 0 125 | result = newSeq[ref Token]() 126 | while tk.xkind != pxEof: 127 | tk = new Token 128 | lex.getTok(tk[]) 129 | if tk.xkind == pxEof: 130 | break 131 | result.add tk 132 | inc idx 133 | if idx > 1_000: raise newException(Exception, "parse error") 134 | tfl[0].close() 135 | tfl[1].removeFile() 136 | 137 | proc parseDefineArgs(parserOptions: var PParserOptions, val: string) = 138 | let defs = val.split("=") 139 | var mc: cparser.Macro 140 | let macs = parseDefines(defs[0]) 141 | let toks = parseDefines(defs[1]) 142 | mc.name = macs[0].s 143 | mc.params = -1 144 | mc.body = toks 145 | for m in macs[1..^1]: 146 | if m.xkind == pxParLe: mc.params = 0 147 | if m.xkind == pxSymbol: inc mc.params 148 | parserOptions.macros.add(mc) 149 | 150 | var dummy: PNode 151 | 152 | when not compiles(renderModule(dummy, "")): 153 | # newer versions of 'renderModule' take 2 parameters. We workaround this 154 | # problem here: 155 | proc renderModule(tree: PNode; filename: string, renderFlags: TRenderFlags) = 156 | renderModule(tree, filename, filename, renderFlags) 157 | 158 | proc myRenderModule(tree: PNode; filename: string, renderFlags: TRenderFlags) = 159 | # also ensure we produced no trailing whitespace: 160 | let tmpFile = filename & ".tmp" 161 | renderModule(tree, tmpFile, renderFlags) 162 | 163 | let b = readFile(tmpFile) 164 | removeFile(tmpFile) 165 | let L = b.len 166 | var i = 0 167 | let f = open(filename, fmWrite) 168 | while i < L: 169 | let ch = b[i] 170 | if ch > ' ': 171 | f.write(ch) 172 | elif ch == ' ': 173 | let j = i 174 | while i < L and b[i] == ' ': inc i 175 | if i < L and b[i] == '\L': 176 | f.write('\L') 177 | else: 178 | for ii in j..i-1: 179 | f.write(' ') 180 | dec i 181 | elif ch == '\L': 182 | f.write('\L') 183 | else: 184 | f.write(ch) 185 | inc(i) 186 | f.close 187 | 188 | proc main(infiles: seq[string], 189 | outfile: var string, 190 | options: PParserOptions, 191 | concat: bool) = 192 | var start = getTime() 193 | var dllexport: PNode = nil 194 | var infiles = infiles 195 | 196 | if concat: 197 | var tree = newNode(nkStmtList) 198 | for infile in infiles: 199 | let m = parse(infile.addFileExt("h"), options, dllexport) 200 | if not isC2nimFile(infile): 201 | if outfile.len == 0: 202 | outfile = changeFileExt(infile, "nim") 203 | if not isC2nimFile(infile) or pfC2NimInclude in options.flags: 204 | for n in m: tree.add(n) 205 | myRenderModule(tree, outfile, options.renderFlags) 206 | else: 207 | for infile in infiles: 208 | let m = parse(infile, options, dllexport) 209 | if not isC2nimFile(infile): 210 | if outfile.len > 0: 211 | myRenderModule(m, outfile, options.renderFlags) 212 | outfile = "" 213 | else: 214 | let outfile = changeFileExt(infile, "nim") 215 | myRenderModule(m, outfile, options.renderFlags) 216 | if dllexport != nil: 217 | let (path, name, _) = infiles[0].splitFile 218 | let outfile = path / name & "_dllimpl" & ".nim" 219 | myRenderModule(dllexport, outfile, options.renderFlags) 220 | when declared(NimCompilerApiVersion): 221 | rawMessage(gConfig, hintSuccessX, [$gLinesCompiled, $(getTime() - start), 222 | formatSize(getTotalMem()), ""]) 223 | else: 224 | rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start), 225 | formatSize(getTotalMem()), ""]) 226 | 227 | var 228 | infiles = newSeq[string](0) 229 | outfile = "" 230 | concat = false 231 | parserOptions = newParserOptions() 232 | 233 | for kind, key, val in getopt(): 234 | case kind 235 | of cmdArgument: 236 | infiles.add key 237 | of cmdLongOption, cmdShortOption: 238 | case key.normalize 239 | of "help", "h": 240 | stdout.write(Usage) 241 | quit(0) 242 | of "version", "v": 243 | stdout.write(Version & "\n") 244 | quit(0) 245 | of "o", "out": outfile = val 246 | of "concat": 247 | concat = true 248 | if val == "all": 249 | incl(parserOptions.flags, pfC2NimInclude) 250 | of "spliceheader": 251 | quit "[Error] 'spliceheader' doesn't exist anymore" & 252 | " use a list of files and --concat instead" 253 | of "exportdll": 254 | parserOptions.exportPrefix = val 255 | of "def": 256 | parserOptions.parseDefineArgs(val) 257 | of "render": 258 | if not parserOptions.renderFlags.setOption(val): 259 | quit("[Error] unknown option: " & key) 260 | else: 261 | if not parserOptions.setOption(key, val): 262 | quit("[Error] unknown option: " & key) 263 | of cmdEnd: assert(false) 264 | if infiles.len == 0: 265 | # no filename has been given, so we show the help: 266 | stdout.write(Usage) 267 | else: 268 | main(infiles, outfile, parserOptions, concat) 269 | -------------------------------------------------------------------------------- /compiler/lineinfos.nim: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # The Nim Compiler 4 | # (c) Copyright 2018 Andreas Rumpf 5 | # 6 | # See the file "copying.txt", included in this 7 | # distribution, for details about the copyright. 8 | # 9 | 10 | ## This module contains the ``TMsgKind`` enum as well as the 11 | ## ``TLineInfo`` object. 12 | 13 | import ropes, tables, pathutils 14 | 15 | const 16 | explanationsBaseUrl* = "https://nim-lang.org/docs/manual" 17 | 18 | type 19 | TMsgKind* = enum 20 | errUnknown, errInternal, errIllFormedAstX, errCannotOpenFile, 21 | errXExpected, 22 | errGridTableNotImplemented, 23 | errGeneralParseError, 24 | errNewSectionExpected, 25 | errInvalidDirectiveX, 26 | errGenerated, 27 | errUser, 28 | warnCannotOpenFile, 29 | warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit, 30 | warnDeprecated, warnConfigDeprecated, 31 | warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel, 32 | warnUnknownSubstitutionX, warnLanguageXNotSupported, 33 | warnFieldXNotSupported, warnCommentXIgnored, 34 | warnTypelessParam, 35 | warnUseBase, warnWriteToForeignHeap, warnUnsafeCode, 36 | warnEachIdentIsTuple, 37 | warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2, 38 | warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed, 39 | warnInconsistentSpacing, warnCaseTransition, warnSyntaxError, warnUser, 40 | hintSuccess, hintSuccessX, hintCC, 41 | hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, 42 | hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, 43 | hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, 44 | hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern, 45 | hintExecuting, hintLinking, hintDependency, 46 | hintSource, hintPerformance, hintStackTrace, hintGCStats, 47 | hintGlobalVar, hintExpandMacro, 48 | hintUser, hintUserRaw, 49 | hintExtendedContext 50 | 51 | const 52 | MsgKindToStr*: array[TMsgKind, string] = [ 53 | errUnknown: "unknown error", 54 | errInternal: "internal error: $1", 55 | errIllFormedAstX: "illformed AST: $1", 56 | errCannotOpenFile: "cannot open '$1'", 57 | errXExpected: "'$1' expected", 58 | errGridTableNotImplemented: "grid table is not implemented", 59 | errGeneralParseError: "general parse error", 60 | errNewSectionExpected: "new section expected", 61 | errInvalidDirectiveX: "invalid directive: '$1'", 62 | errGenerated: "$1", 63 | errUser: "$1", 64 | warnCannotOpenFile: "cannot open '$1'", 65 | warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored", 66 | warnXIsNeverRead: "'$1' is never read", 67 | warnXmightNotBeenInit: "'$1' might not have been initialized", 68 | warnDeprecated: "$1", 69 | warnConfigDeprecated: "config file '$1' is deprecated", 70 | warnSmallLshouldNotBeUsed: "'l' should not be used as an identifier; may look like '1' (one)", 71 | warnUnknownMagic: "unknown magic '$1' might crash the compiler", 72 | warnRedefinitionOfLabel: "redefinition of label '$1'", 73 | warnUnknownSubstitutionX: "unknown substitution '$1'", 74 | warnLanguageXNotSupported: "language '$1' not supported", 75 | warnFieldXNotSupported: "field '$1' not supported", 76 | warnCommentXIgnored: "comment '$1' ignored", 77 | warnTypelessParam: "'$1' has no type. Typeless parameters are deprecated; only allowed for 'template'", 78 | warnUseBase: "use {.base.} for base methods; baseless methods are deprecated", 79 | warnWriteToForeignHeap: "write to foreign heap", 80 | warnUnsafeCode: "unsafe code: '$1'", 81 | warnEachIdentIsTuple: "each identifier is a tuple", 82 | warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.", 83 | warnProveField: "cannot prove that field '$1' is accessible", 84 | warnProveIndex: "cannot prove index '$1' is valid", 85 | warnGcUnsafe: "not GC-safe: '$1'", 86 | warnGcUnsafe2: "$1", 87 | warnUninit: "'$1' might not have been initialized", 88 | warnGcMem: "'$1' uses GC'ed memory", 89 | warnDestructor: "usage of a type with a destructor in a non destructible context. This will become a compile time error in the future.", 90 | warnLockLevel: "$1", 91 | warnResultShadowed: "Special variable 'result' is shadowed.", 92 | warnInconsistentSpacing: "Number of spaces around '$#' is not consistent", 93 | warnCaseTransition: "Potential object case transition, instantiate new object instead", 94 | warnSyntaxError: "$1", 95 | warnUser: "$1", 96 | hintSuccess: "operation successful: $#", 97 | hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#; $#)", 98 | hintCC: "CC: \'$1\'", # unused 99 | hintLineTooLong: "line too long", 100 | hintXDeclaredButNotUsed: "'$1' is declared but not used", 101 | hintConvToBaseNotNeeded: "conversion to base object is not needed", 102 | hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless", 103 | hintExprAlwaysX: "expression evaluates always to '$1'", 104 | hintQuitCalled: "quit() called", 105 | hintProcessing: "$1", 106 | hintCodeBegin: "generated code listing:", 107 | hintCodeEnd: "end of listing", 108 | hintConf: "used config file '$1'", 109 | hintPath: "added path: '$1'", 110 | hintConditionAlwaysTrue: "condition is always true: '$1'", 111 | hintConditionAlwaysFalse: "condition is always false: '$1'", 112 | hintName: "$1", 113 | hintPattern: "$1", 114 | hintExecuting: "$1", 115 | hintLinking: "", 116 | hintDependency: "$1", 117 | hintSource: "$1", 118 | hintPerformance: "$1", 119 | hintStackTrace: "$1", 120 | hintGCStats: "$1", 121 | hintGlobalVar: "global variable declared here", 122 | hintExpandMacro: "expanded macro: $1", 123 | hintUser: "$1", 124 | hintUserRaw: "$1", 125 | hintExtendedContext: "$1", 126 | ] 127 | 128 | const 129 | WarningsToStr* = ["CannotOpenFile", "OctalEscape", 130 | "XIsNeverRead", "XmightNotBeenInit", 131 | "Deprecated", "ConfigDeprecated", 132 | "SmallLshouldNotBeUsed", "UnknownMagic", 133 | "RedefinitionOfLabel", "UnknownSubstitutionX", 134 | "LanguageXNotSupported", "FieldXNotSupported", 135 | "CommentXIgnored", 136 | "TypelessParam", "UseBase", "WriteToForeignHeap", 137 | "UnsafeCode", "EachIdentIsTuple", 138 | "ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit", 139 | "GcMem", "Destructor", "LockLevel", "ResultShadowed", 140 | "Spacing", "CaseTransition", "SyntaxError", "User"] 141 | 142 | HintsToStr* = [ 143 | "Success", "SuccessX", "CC", "LineTooLong", 144 | "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", 145 | "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", 146 | "Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency", 147 | "Source", "Performance", "StackTrace", "GCStats", "GlobalVar", "ExpandMacro", 148 | "User", "UserRaw", "ExtendedContext", 149 | ] 150 | 151 | const 152 | fatalMin* = errUnknown 153 | fatalMax* = errInternal 154 | errMin* = errUnknown 155 | errMax* = errUser 156 | warnMin* = warnCannotOpenFile 157 | warnMax* = pred(hintSuccess) 158 | hintMin* = hintSuccess 159 | hintMax* = high(TMsgKind) 160 | 161 | static: 162 | doAssert HintsToStr.len == ord(hintMax) - ord(hintMin) + 1 163 | doAssert WarningsToStr.len == ord(warnMax) - ord(warnMin) + 1 164 | 165 | type 166 | TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints 167 | TNoteKinds* = set[TNoteKind] 168 | 169 | proc computeNotesVerbosity(): array[0..3, TNoteKinds] = 170 | result[3] = {low(TNoteKind)..high(TNoteKind)} - {} 171 | result[2] = result[3] - {hintStackTrace, warnUninit, hintExtendedContext} 172 | result[1] = result[2] - {warnProveField, warnProveIndex, 173 | warnGcUnsafe, hintPath, hintDependency, hintCodeBegin, hintCodeEnd, 174 | hintSource, hintGlobalVar, hintGCStats} 175 | result[0] = result[1] - {hintSuccessX, hintSuccess, hintConf, 176 | hintProcessing, hintPattern, hintExecuting, hintLinking, hintCC} 177 | 178 | const 179 | NotesVerbosity* = computeNotesVerbosity() 180 | errXMustBeCompileTime* = "'$1' can only be used in compile-time context" 181 | errArgsNeedRunOption* = "arguments can only be given if the '--run' option is selected" 182 | 183 | type 184 | TFileInfo* = object 185 | fullPath*: AbsoluteFile # This is a canonical full filesystem path 186 | projPath*: RelativeFile # This is relative to the project's root 187 | shortName*: string # short name of the module 188 | quotedName*: Rope # cached quoted short name for codegen 189 | # purposes 190 | quotedFullName*: Rope # cached quoted full name for codegen 191 | # purposes 192 | 193 | lines*: seq[string] # the source code of the module 194 | # used for better error messages and 195 | # embedding the original source in the 196 | # generated code 197 | dirtyFile*: AbsoluteFile # the file that is actually read into memory 198 | # and parsed; usually "" but is used 199 | # for 'nimsuggest' 200 | hash*: string # the checksum of the file 201 | dirty*: bool # for 'nimfix' / 'nimpretty' like tooling 202 | when defined(nimpretty): 203 | fullContent*: string 204 | FileIndex* = distinct int32 205 | TLineInfo* = object # This is designed to be as small as possible, 206 | # because it is used 207 | # in syntax nodes. We save space here by using 208 | # two int16 and an int32. 209 | # On 64 bit and on 32 bit systems this is 210 | # only 8 bytes. 211 | line*: uint16 212 | col*: int16 213 | fileIndex*: FileIndex 214 | when defined(nimpretty): 215 | offsetA*, offsetB*: int 216 | commentOffsetA*, commentOffsetB*: int 217 | 218 | TErrorOutput* = enum 219 | eStdOut 220 | eStdErr 221 | 222 | TErrorOutputs* = set[TErrorOutput] 223 | 224 | ERecoverableError* = object of ValueError 225 | ESuggestDone* = object of ValueError 226 | 227 | proc `==`*(a, b: FileIndex): bool {.borrow.} 228 | 229 | proc raiseRecoverableError*(msg: string) {.noinline.} = 230 | raise newException(ERecoverableError, msg) 231 | 232 | const 233 | InvalidFileIdx* = FileIndex(-1) 234 | 235 | proc unknownLineInfo*(): TLineInfo = 236 | result.line = uint16(0) 237 | result.col = int16(-1) 238 | result.fileIndex = InvalidFileIdx 239 | 240 | type 241 | Severity* {.pure.} = enum ## VS Code only supports these three 242 | Hint, Warning, Error 243 | 244 | const 245 | trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions 246 | # are produced within comments and string literals 247 | commandLineIdx* = FileIndex(-3) 248 | 249 | type 250 | MsgConfig* = object ## does not need to be stored in the incremental cache 251 | trackPos*: TLineInfo 252 | trackPosAttached*: bool ## whether the tracking position was attached to 253 | ## some close token. 254 | 255 | errorOutputs*: TErrorOutputs 256 | msgContext*: seq[tuple[info: TLineInfo, detail: string]] 257 | lastError*: TLineInfo 258 | filenameToIndexTbl*: Table[string, FileIndex] 259 | fileInfos*: seq[TFileInfo] 260 | systemFileIdx*: FileIndex 261 | 262 | 263 | proc initMsgConfig*(): MsgConfig = 264 | result.msgContext = @[] 265 | result.lastError = unknownLineInfo() 266 | result.filenameToIndexTbl = initTable[string, FileIndex]() 267 | result.fileInfos = @[] 268 | result.errorOutputs = {eStdOut, eStdErr} 269 | -------------------------------------------------------------------------------- /testsuite/tests/smartptrs.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2008-2014 the Urho3D project. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #pragma once 24 | 25 | #include "RefCounted.h" 26 | 27 | #include 28 | #include 29 | 30 | namespace Urho3D 31 | { 32 | 33 | /// Shared pointer template class with intrusive reference counting. 34 | template class SharedPtr 35 | { 36 | public: 37 | /// Construct a null shared pointer. 38 | SharedPtr() : 39 | ptr_(0) 40 | { 41 | } 42 | 43 | /// Copy-construct from another shared pointer. 44 | SharedPtr(const SharedPtr& rhs) : 45 | ptr_(rhs.ptr_) 46 | { 47 | AddRef(); 48 | } 49 | 50 | /// Construct from a raw pointer. 51 | explicit SharedPtr(T* ptr) : 52 | ptr_(ptr) 53 | { 54 | AddRef(); 55 | } 56 | 57 | /// Destruct. Release the object reference. 58 | ~SharedPtr() 59 | { 60 | ReleaseRef(); 61 | } 62 | 63 | /// Assign from another shared pointer. 64 | SharedPtr& operator = (const SharedPtr& rhs) 65 | { 66 | if (ptr_ == rhs.ptr_) 67 | return *this; 68 | 69 | ReleaseRef(); 70 | ptr_ = rhs.ptr_; 71 | AddRef(); 72 | 73 | return *this; 74 | } 75 | 76 | /// Assign from a raw pointer. 77 | SharedPtr& operator = (T* ptr) 78 | { 79 | if (ptr_ == ptr) 80 | return *this; 81 | 82 | ReleaseRef(); 83 | ptr_ = ptr; 84 | AddRef(); 85 | 86 | return *this; 87 | } 88 | 89 | /// Point to the object. 90 | T* operator -> () const { assert(ptr_); return ptr_; } 91 | /// Dereference the object. 92 | T& operator * () const { assert(ptr_); return *ptr_; } 93 | /// Subscript the object if applicable. 94 | T& operator [] (const int index) { assert(ptr_); return ptr_[index]; } 95 | /// Test for less than with another shared pointer. 96 | bool operator < (const SharedPtr& rhs) const { return ptr_ < rhs.ptr_; } 97 | /// Test for equality with another shared pointer. 98 | bool operator == (const SharedPtr& rhs) const { return ptr_ == rhs.ptr_; } 99 | /// Test for inequality with another shared pointer. 100 | bool operator != (const SharedPtr& rhs) const { return ptr_ != rhs.ptr_; } 101 | 102 | /// Reset to null and release the object reference. 103 | void Reset() { ReleaseRef(); } 104 | 105 | /// Detach without destroying the object even if the refcount goes zero. To be used for scripting language interoperation. 106 | void Detach() 107 | { 108 | if (ptr_) 109 | { 110 | RefCount* refCount = RefCountPtr(); 111 | ++refCount->refs_; // 2 refs 112 | Reset(); // 1 ref 113 | --refCount->refs_; // 0 refs 114 | } 115 | } 116 | 117 | /// Perform a static cast from a shared pointer of another type. 118 | template void StaticCast(const SharedPtr& rhs) 119 | { 120 | ReleaseRef(); 121 | ptr_ = static_cast(rhs.Get()); 122 | AddRef(); 123 | } 124 | 125 | /// Perform a dynamic cast from a shared pointer of another type. 126 | template void DynamicCast(const SharedPtr& rhs) 127 | { 128 | ReleaseRef(); 129 | ptr_ = dynamic_cast(rhs.Get()); 130 | AddRef(); 131 | } 132 | 133 | /// Check if the pointer is null. 134 | bool Null() const { return ptr_ == 0; } 135 | /// Check if the pointer is not null. 136 | bool NotNull() const { return ptr_ != 0; } 137 | /// Return the raw pointer. 138 | T* Get() const { return ptr_; } 139 | /// Return the object's reference count, or 0 if the pointer is null. 140 | int Refs() const { return ptr_ ? ptr_->Refs() : 0; } 141 | /// Return the object's weak reference count, or 0 if the pointer is null. 142 | int WeakRefs() const { return ptr_ ? ptr_->WeakRefs() : 0; } 143 | /// Return pointer to the RefCount structure. 144 | RefCount* RefCountPtr() const { return ptr_ ? ptr_->RefCountPtr() : 0; } 145 | /// Return hash value for HashSet & HashMap. 146 | unsigned ToHash() const; 147 | 148 | private: 149 | /// Prevent direct assignment from a shared pointer of another type. 150 | template SharedPtr& operator = (const SharedPtr& rhs); 151 | 152 | /// Add a reference to the object pointed to. 153 | void AddRef() 154 | { 155 | if (ptr_) 156 | ptr_->AddRef(); 157 | } 158 | 159 | /// Release the object reference and delete it if necessary. 160 | void ReleaseRef() 161 | { 162 | if (ptr_) 163 | { 164 | ptr_->ReleaseRef(); 165 | ptr_ = 0; 166 | } 167 | } 168 | 169 | /// Pointer to the object. 170 | T* ptr_; 171 | }; 172 | 173 | /// Perform a static cast from one shared pointer type to another. 174 | template SharedPtr StaticCast(const SharedPtr& ptr) 175 | { 176 | SharedPtr ret; 177 | ret.StaticCast(ptr); 178 | return ret; 179 | } 180 | 181 | /// Perform a dynamic cast from one weak pointer type to another. 182 | template SharedPtr DynamicCast(const SharedPtr& ptr) 183 | { 184 | SharedPtr ret; 185 | ret.DynamicCast(ptr); 186 | return ret; 187 | } 188 | 189 | /// Weak pointer template class with intrusive reference counting. Does not keep the object pointed to alive. 190 | template class WeakPtr 191 | { 192 | public: 193 | /// Construct a null weak pointer. 194 | WeakPtr() : 195 | ptr_(0), 196 | refCount_(0) 197 | { 198 | } 199 | 200 | /// Copy-construct from another weak pointer. 201 | WeakPtr(const WeakPtr& rhs) : 202 | ptr_(rhs.ptr_), 203 | refCount_(rhs.refCount_) 204 | { 205 | AddRef(); 206 | } 207 | 208 | /// Construct from a shared pointer. 209 | WeakPtr(const SharedPtr& rhs) : 210 | ptr_(rhs.Get()), 211 | refCount_(rhs.RefCountPtr()) 212 | { 213 | AddRef(); 214 | } 215 | 216 | /// Construct from a raw pointer. 217 | explicit WeakPtr(T* ptr) : 218 | ptr_(ptr), 219 | refCount_(ptr ? ptr->RefCountPtr() : 0) 220 | { 221 | AddRef(); 222 | } 223 | 224 | /// Destruct. Release the weak reference to the object. 225 | ~WeakPtr() 226 | { 227 | ReleaseRef(); 228 | } 229 | 230 | /// Assign from a shared pointer. 231 | WeakPtr& operator = (const SharedPtr& rhs) 232 | { 233 | if (ptr_ == rhs.Get() && refCount_ == rhs.RefCountPtr()) 234 | return *this; 235 | 236 | ReleaseRef(); 237 | ptr_ = rhs.Get(); 238 | refCount_ = rhs.RefCountPtr(); 239 | AddRef(); 240 | 241 | return *this; 242 | } 243 | 244 | /// Assign from a weak pointer. 245 | WeakPtr& operator = (const WeakPtr& rhs) 246 | { 247 | if (ptr_ == rhs.ptr_ && refCount_ == rhs.refCount_) 248 | return *this; 249 | 250 | ReleaseRef(); 251 | ptr_ = rhs.ptr_; 252 | refCount_ = rhs.refCount_; 253 | AddRef(); 254 | 255 | return *this; 256 | } 257 | 258 | /// Assign from a raw pointer. 259 | WeakPtr& operator = (T* ptr) 260 | { 261 | RefCount* refCount = ptr ? ptr->RefCountPtr() : 0; 262 | 263 | if (ptr_ == ptr && refCount_ == refCount) 264 | return *this; 265 | 266 | ReleaseRef(); 267 | ptr_ = ptr; 268 | refCount_ = refCount; 269 | AddRef(); 270 | 271 | return *this; 272 | } 273 | 274 | /// Convert to a shared pointer. If expired, return a null shared pointer. 275 | SharedPtr Lock() const 276 | { 277 | if (Expired()) 278 | return SharedPtr(); 279 | else 280 | return SharedPtr(ptr_); 281 | } 282 | 283 | /// Return raw pointer. If expired, return null. 284 | T* Get() const 285 | { 286 | if (Expired()) 287 | return 0; 288 | else 289 | return ptr_; 290 | } 291 | 292 | /// Point to the object. 293 | T* operator -> () const 294 | { 295 | T* rawPtr = Get(); 296 | assert(rawPtr); 297 | return rawPtr; 298 | } 299 | 300 | /// Dereference the object. 301 | T& operator * () const 302 | { 303 | T* rawPtr = Get(); 304 | assert(rawPtr); 305 | return *rawPtr; 306 | } 307 | 308 | /// Subscript the object if applicable. 309 | T& operator [] (const int index) 310 | { 311 | T* rawPtr = Get(); 312 | assert(rawPtr); 313 | return (*rawPtr)[index]; 314 | } 315 | 316 | /// Test for equality with another weak pointer. 317 | bool operator == (const WeakPtr& rhs) const { return ptr_ == rhs.ptr_ && refCount_ == rhs.refCount_; } 318 | /// Test for inequality with another weak pointer. 319 | bool operator != (const WeakPtr& rhs) const { return ptr_ != rhs.ptr_ || refCount_ != rhs.refCount_; } 320 | /// Test for less than with another weak pointer. 321 | bool operator < (const WeakPtr& rhs) const { return ptr_ < rhs.ptr_; } 322 | 323 | /// Reset to null and release the weak reference. 324 | void Reset() { ReleaseRef(); } 325 | 326 | /// Perform a static cast from a weak pointer of another type. 327 | template void StaticCast(const WeakPtr& rhs) 328 | { 329 | ReleaseRef(); 330 | ptr_ = static_cast(rhs.Get()); 331 | refCount_ = rhs.refCount_; 332 | AddRef(); 333 | } 334 | 335 | /// Perform a dynamic cast from a weak pointer of another type. 336 | template void DynamicCast(const WeakPtr& rhs) 337 | { 338 | ReleaseRef(); 339 | ptr_ = dynamic_cast(rhs.Get()); 340 | 341 | if (ptr_) 342 | { 343 | refCount_ = rhs.refCount_; 344 | AddRef(); 345 | } 346 | else 347 | refCount_ = 0; 348 | } 349 | 350 | /// Check if the pointer is null. 351 | bool Null() const { return refCount_ == 0; } 352 | /// Check if the pointer is not null. 353 | bool NotNull() const { return refCount_ != 0; } 354 | /// Return the object's reference count, or 0 if null pointer or if object has expired. 355 | int Refs() const { return (refCount_ && refCount_->refs_ >= 0) ? refCount_->refs_ : 0; } 356 | 357 | /// Return the object's weak reference count. 358 | int WeakRefs() const 359 | { 360 | if (!Expired()) 361 | return ptr_->WeakRefs(); 362 | else 363 | return refCount_ ? refCount_->weakRefs_ : 0; 364 | } 365 | 366 | /// Return whether the object has expired. If null pointer, always return true. 367 | bool Expired() const { return refCount_ ? refCount_->refs_ < 0 : true; } 368 | /// Return pointer to the RefCount structure. 369 | RefCount* RefCountPtr() const { return refCount_; } 370 | /// Return hash value for HashSet & HashMap. 371 | unsigned ToHash() const; 372 | 373 | private: 374 | /// Prevent direct assignment from a weak pointer of different type. 375 | template WeakPtr& operator = (const WeakPtr& rhs); 376 | 377 | /// Add a weak reference to the object pointed to. 378 | void AddRef() 379 | { 380 | if (refCount_) 381 | { 382 | assert(refCount_->weakRefs_ >= 0); 383 | ++(refCount_->weakRefs_); 384 | } 385 | } 386 | 387 | /// Release the weak reference. Delete the Refcount structure if necessary. 388 | void ReleaseRef() 389 | { 390 | if (refCount_) 391 | { 392 | assert(refCount_->weakRefs_ > 0); 393 | --(refCount_->weakRefs_); 394 | 395 | if (Expired() && !refCount_->weakRefs_) 396 | delete refCount_; 397 | } 398 | 399 | ptr_ = 0; 400 | refCount_ = 0; 401 | } 402 | 403 | /// Pointer to the object. 404 | T* ptr_; 405 | /// Pointer to the RefCount structure. 406 | RefCount* refCount_; 407 | }; 408 | 409 | /// Perform a static cast from one weak pointer type to another. 410 | template WeakPtr StaticCast(const WeakPtr& ptr) 411 | { 412 | WeakPtr ret; 413 | ret.StaticCast(ptr); 414 | return ret; 415 | } 416 | 417 | /// Perform a dynamic cast from one weak pointer type to another. 418 | template WeakPtr DynamicCast(const WeakPtr& ptr) 419 | { 420 | WeakPtr ret; 421 | ret.DynamicCast(ptr); 422 | return ret; 423 | } 424 | 425 | } 426 | --------------------------------------------------------------------------------