From 605210413f7616e4205651769bc88d33387a32d8 Mon Sep 17 00:00:00 2001 From: Dirk Adler Date: Sun, 26 Apr 2020 22:34:48 +0200 Subject: [PATCH 1/6] Add typedef array to test case --- test/cases/c/typedef.phpt | 6 +++++- test/generated/c/typedefTest.c | 2 ++ test/generated/c/typedefTest.php | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/test/cases/c/typedef.phpt b/test/cases/c/typedef.phpt index 8c38a90..16fd2c2 100755 --- a/test/cases/c/typedef.phpt +++ b/test/cases/c/typedef.phpt @@ -2,5 +2,9 @@ Test basic parsing of vars --FILE-- typedef void* foo; +typedef unsigned char bar[23]; +typedef long baz[][]; --EXPECT-- -typedef void * foo; \ No newline at end of file +typedef void *foo; +typedef unsigned char bar[23]; +typedef long baz[][]; \ No newline at end of file diff --git a/test/generated/c/typedefTest.c b/test/generated/c/typedefTest.c index 63fe94d..fe2d474 100644 --- a/test/generated/c/typedefTest.c +++ b/test/generated/c/typedefTest.c @@ -1 +1,3 @@ typedef void* foo; +typedef unsigned char bar[23]; +typedef long baz[][]; diff --git a/test/generated/c/typedefTest.php b/test/generated/c/typedefTest.php index 731d65d..fd93d67 100644 --- a/test/generated/c/typedefTest.php +++ b/test/generated/c/typedefTest.php @@ -11,7 +11,9 @@ */ class typedefTest extends TestCase { - const EXPECTED = 'typedef void * foo;'; + const EXPECTED = 'typedef void *foo; +typedef unsigned char bar[23]; +typedef long baz[][];'; protected CParser $parser; protected Printer $printer; From 6a48f2f9537c907e1af185a8d69de607dc92f64a Mon Sep 17 00:00:00 2001 From: Dirk Adler Date: Mon, 27 Apr 2020 09:24:35 +0200 Subject: [PATCH 2/6] Print array in typedef correctly * more test cases * force * to right side of space --- lib/Printer/C.php | 20 +++++--------------- test/cases/c/functions.phpt | 11 +++++++++++ test/cases/c/typedef.phpt | 11 ++++++++++- test/cases/c/vars.phpt | 9 +++++++-- test/generated/c/typedefTest.c | 5 +++++ test/generated/c/typedefTest.php | 6 +++++- test/generated/c/varsTest.c | 4 +++- test/generated/c/varsTest.php | 5 ++++- 8 files changed, 50 insertions(+), 21 deletions(-) create mode 100755 test/cases/c/functions.phpt diff --git a/lib/Printer/C.php b/lib/Printer/C.php index ee3ccab..02d372a 100755 --- a/lib/Printer/C.php +++ b/lib/Printer/C.php @@ -51,10 +51,7 @@ public function printNode(Node $node, int $level): string { protected function printDecl(Decl $decl, int $level): string { if ($decl instanceof Decl\NamedDecl\TypeDecl\TypedefNameDecl\TypedefDecl) { - if ($this->isFunction($decl->type)) { - return 'typedef ' . $this->printType($decl->type, $decl->name, $level); - } - return 'typedef ' . $this->printType($decl->type, null, $level) . ' ' . $decl->name; + return 'typedef ' . $this->printType($decl->type, $decl->name, $level); } if ($decl instanceof Decl\NamedDecl\ValueDecl\DeclaratorDecl\VarDecl) { $result = $this->printType($decl->type, $decl->name, $level); @@ -125,7 +122,7 @@ protected function printDecl(Decl $decl, int $level): string { $type = $type->parent; } $return .= $this->printType($type->return, null, $level); - $return .= ' ' . $decl->name . '('; + $return .= $decl->name . '('; $next = ''; foreach ($type->params as $idx => $param) { $return .= $next . $this->printType($param, $type->paramNames[$idx], $level); @@ -157,20 +154,13 @@ protected function printCompoundStmt(Stmt\CompoundStmt $stmts, int $level): stri Type\AttributedType::KIND_AUTO => 'auto', Type\AttributedType::KIND_REGISTER => 'register', Type\AttributedType::KIND_CONST => 'const', - Type\AttributedType::KIND_RESTRICT => 'restrict', - Type\AttributedType::KIND_VOLATILE => 'volatile', + Type\AttributedType::KIND_RESTRICT => 'restrict', + Type\AttributedType::KIND_VOLATILE => 'volatile', Type\AttributedType::KIND_ATOMIC => 'atomic', Type\AttributedType::KIND_INLINE => 'inline', Type\AttributedType::KIND_NORETURN => 'noreturn', ]; - protected function isFunction(Type $type): bool { - if ($type instanceof Type\FunctionType\FunctionProtoType) { - return true; - } - return $this->isFunctionPointer($type); - } - protected function isFunctionPointer(Type $type): bool { if (!$type instanceof Type\PointerType) { return false; @@ -186,7 +176,7 @@ protected function isFunctionPointer(Type $type): bool { protected function printType(Type $type, ?string $name, int $level): string { if ($type instanceof Type\BuiltinType || $type instanceof Type\TypedefType) { - return $type->name . ($name !== null ? ' ' . $name : ''); + return $type->name . ($name !== null ? ' ' . $name : ' '); } if ($type instanceof Type\TagType\RecordType) { return $this->printDecl($type->decl, $level) . ($name !== null ? ' ' . $name : '') ; diff --git a/test/cases/c/functions.phpt b/test/cases/c/functions.phpt new file mode 100755 index 0000000..2ac35f9 --- /dev/null +++ b/test/cases/c/functions.phpt @@ -0,0 +1,11 @@ +--TEST-- +Test basic parsing of functions +--FILE-- + +extern char** bar(char* bar); +void foobar(void *qux); + +--EXPECT-- + +extern char **bar(char *bar); +void foobar(void *qux); \ No newline at end of file diff --git a/test/cases/c/typedef.phpt b/test/cases/c/typedef.phpt index 16fd2c2..8e02603 100755 --- a/test/cases/c/typedef.phpt +++ b/test/cases/c/typedef.phpt @@ -4,7 +4,16 @@ Test basic parsing of vars typedef void* foo; typedef unsigned char bar[23]; typedef long baz[][]; +typedef enum qux { + QUUX, + CORGE, +} grault; + --EXPECT-- typedef void *foo; typedef unsigned char bar[23]; -typedef long baz[][]; \ No newline at end of file +typedef long baz[][]; +typedef enum qux { + QUUX, + CORGE, +} grault; \ No newline at end of file diff --git a/test/cases/c/vars.phpt b/test/cases/c/vars.phpt index 4c86bad..ddd44b0 100755 --- a/test/cases/c/vars.phpt +++ b/test/cases/c/vars.phpt @@ -4,10 +4,15 @@ Test basic parsing of vars extern int foo; int bar; -int baz[]; +int baz[][]; +char** qux; +int* quux, corge; --EXPECT-- extern int foo; int bar; -int baz[]; \ No newline at end of file +int baz[][]; +char **qux; +int *quux; +int corge; \ No newline at end of file diff --git a/test/generated/c/typedefTest.c b/test/generated/c/typedefTest.c index fe2d474..e3f4d88 100644 --- a/test/generated/c/typedefTest.c +++ b/test/generated/c/typedefTest.c @@ -1,3 +1,8 @@ typedef void* foo; typedef unsigned char bar[23]; typedef long baz[][]; +typedef enum qux { + QUUX, + CORGE, +} grault; + diff --git a/test/generated/c/typedefTest.php b/test/generated/c/typedefTest.php index fd93d67..d39cf23 100644 --- a/test/generated/c/typedefTest.php +++ b/test/generated/c/typedefTest.php @@ -13,7 +13,11 @@ class typedefTest extends TestCase { const EXPECTED = 'typedef void *foo; typedef unsigned char bar[23]; -typedef long baz[][];'; +typedef long baz[][]; +typedef enum qux { + QUUX, + CORGE, +} grault;'; protected CParser $parser; protected Printer $printer; diff --git a/test/generated/c/varsTest.c b/test/generated/c/varsTest.c index 6ffa61e..345705b 100644 --- a/test/generated/c/varsTest.c +++ b/test/generated/c/varsTest.c @@ -1,5 +1,7 @@ extern int foo; int bar; -int baz[]; +int baz[][]; +char** qux; +int* quux, corge; diff --git a/test/generated/c/varsTest.php b/test/generated/c/varsTest.php index c01aa22..b4cbaac 100644 --- a/test/generated/c/varsTest.php +++ b/test/generated/c/varsTest.php @@ -13,7 +13,10 @@ class varsTest extends TestCase { const EXPECTED = 'extern int foo; int bar; -int baz[];'; +int baz[][]; +char **qux; +int *quux; +int corge;'; protected CParser $parser; protected Printer $printer; From bcb90dc0b8a8cb8bd522213279dfc4192d2f799d Mon Sep 17 00:00:00 2001 From: Dirk Adler Date: Wed, 29 Apr 2020 23:15:04 +0200 Subject: [PATCH 3/6] Print parenthesis and arrays as return values correctly --- lib/Printer/C.php | 21 ++++++++++----------- test/cases/c/typedef.phpt | 7 +++++-- test/generated/c/typedefTest.c | 3 ++- test/generated/c/typedefTest.php | 4 +++- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/lib/Printer/C.php b/lib/Printer/C.php index 02d372a..36eb9ab 100755 --- a/lib/Printer/C.php +++ b/lib/Printer/C.php @@ -1,15 +1,15 @@ isFunctionPointer($type)) { $func = $type->parent->parent; - // function pointer - $result = $this->printType($func->return, null, $level) . '(*' . $name . ')('; + $result = '(*' . $name . ')('; $next = ''; foreach ($func->params as $idx => $param) { $result .= $next . $this->printType($param, $func->paramNames[$idx], $level); @@ -217,14 +216,15 @@ protected function printType(Type $type, ?string $name, int $level): string { if ($func->isVariadic) { $result .= $next . '...'; } - return $result . ')'; + $result .= ')'; + return $this->printType($func->return, $result, $level); } if ($type instanceof Type\PointerType) { $subType = $this->printType($type->parent, '__NAME_PLACEHOLDER__', $level); return str_replace('__NAME_PLACEHOLDER__', '*' . $name, $subType); } if ($type instanceof Type\ParenType) { - return '(' . $this->printType($type->parent, $name, $level) . ')'; + return $this->printType($type->parent, '(' . $name . ')', $level); } if ($type instanceof Type\ArrayType\IncompleteArrayType) { $subType = $this->printType($type->parent, '__NAME_PLACEHOLDER__', $level); @@ -232,11 +232,10 @@ protected function printType(Type $type, ?string $name, int $level): string { } if ($type instanceof Type\ArrayType\ConstantArrayType) { $subType = $this->printType($type->parent, '__NAME_PLACEHOLDER__', $level); - return str_replace('__NAME_PLACEHOLDER__', $name . '[' . $this->printExpr($type->size, $level) . ']', $subType); + return str_replace('__NAME_PLACEHOLDER__', $name . '[' . $this->printExpr($type->size, $level) . ']' , $subType); } var_dump($type); - } const BINARYOPERATOR_MAP = [ diff --git a/test/cases/c/typedef.phpt b/test/cases/c/typedef.phpt index 8e02603..fc3a926 100755 --- a/test/cases/c/typedef.phpt +++ b/test/cases/c/typedef.phpt @@ -8,7 +8,8 @@ typedef enum qux { QUUX, CORGE, } grault; - +typedef char *(*(waldos))[5]; +typedef char *(*(**hairy[][8])())[]; --EXPECT-- typedef void *foo; typedef unsigned char bar[23]; @@ -16,4 +17,6 @@ typedef long baz[][]; typedef enum qux { QUUX, CORGE, -} grault; \ No newline at end of file +} grault; +typedef char *(*(waldos))[5]; +typedef char *(*(**hairy[][8])())[]; \ No newline at end of file diff --git a/test/generated/c/typedefTest.c b/test/generated/c/typedefTest.c index e3f4d88..4e76236 100644 --- a/test/generated/c/typedefTest.c +++ b/test/generated/c/typedefTest.c @@ -5,4 +5,5 @@ typedef enum qux { QUUX, CORGE, } grault; - +typedef char *(*(waldos))[5]; +typedef char *(*(**hairy[][8])())[]; diff --git a/test/generated/c/typedefTest.php b/test/generated/c/typedefTest.php index d39cf23..260f7bf 100644 --- a/test/generated/c/typedefTest.php +++ b/test/generated/c/typedefTest.php @@ -17,7 +17,9 @@ class typedefTest extends TestCase { typedef enum qux { QUUX, CORGE, -} grault;'; +} grault; +typedef char *(*(waldos))[5]; +typedef char *(*(**hairy[][8])())[];'; protected CParser $parser; protected Printer $printer; From 16b24ab910b2347b7e4b0f74b681cb6b7e4c8a85 Mon Sep 17 00:00:00 2001 From: Dirk Adler Date: Fri, 1 May 2020 10:06:37 +0200 Subject: [PATCH 4/6] Print void as function param without trailing space --- lib/Printer/C.php | 6 +++--- test/cases/c/function_pointers.phpt | 8 +++++--- test/cases/c/functions.phpt | 8 ++++---- test/generated/c/function_pointersTest.c | 3 ++- test/generated/c/function_pointersTest.php | 5 +++-- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/Printer/C.php b/lib/Printer/C.php index 36eb9ab..98a8896 100755 --- a/lib/Printer/C.php +++ b/lib/Printer/C.php @@ -125,7 +125,7 @@ protected function printDecl(Decl $decl, int $level): string { $return .= $decl->name . '('; $next = ''; foreach ($type->params as $idx => $param) { - $return .= $next . $this->printType($param, $type->paramNames[$idx], $level); + $return .= $next . trim($this->printType($param, $type->paramNames[$idx], $level)); $next = ', '; } if ($type->isVariadic) { @@ -197,7 +197,7 @@ protected function printType(Type $type, ?string $name, int $level): string { $result = $this->printType($type->return, $name, $level) . '('; $next = ''; foreach ($type->params as $idx => $param) { - $result .= $next . $this->printType($param, $type->paramNames[$idx], $level); + $result .= $next . trim($this->printType($param, $type->paramNames[$idx], $level)); $next = ', '; } if ($type->isVariadic) { @@ -210,7 +210,7 @@ protected function printType(Type $type, ?string $name, int $level): string { $result = '(*' . $name . ')('; $next = ''; foreach ($func->params as $idx => $param) { - $result .= $next . $this->printType($param, $func->paramNames[$idx], $level); + $result .= $next . trim($this->printType($param, $func->paramNames[$idx], $level)); $next = ', '; } if ($func->isVariadic) { diff --git a/test/cases/c/function_pointers.phpt b/test/cases/c/function_pointers.phpt index 4fe30df..093753b 100755 --- a/test/cases/c/function_pointers.phpt +++ b/test/cases/c/function_pointers.phpt @@ -1,9 +1,11 @@ --TEST-- Test basic parsing of function pointers --FILE-- -typedef void *(*test_func)(int arg_name); +typedef void *(*test_func)(int arg1_name, char *arg2_name); typedef void A(void * b); +typedef void *(*with_void)(void); --EXPECT-- -typedef void *(*test_func)(int arg_name); -typedef void A(void *b); \ No newline at end of file +typedef void *(*test_func)(int arg1_name, char *arg2_name); +typedef void A(void *b); +typedef void *(*with_void)(void); \ No newline at end of file diff --git a/test/cases/c/functions.phpt b/test/cases/c/functions.phpt index 2ac35f9..6aa5ba0 100755 --- a/test/cases/c/functions.phpt +++ b/test/cases/c/functions.phpt @@ -2,10 +2,10 @@ Test basic parsing of functions --FILE-- -extern char** bar(char* bar); -void foobar(void *qux); +extern char** bar(char* arg1, int* arg2); +void foobar(void); --EXPECT-- -extern char **bar(char *bar); -void foobar(void *qux); \ No newline at end of file +extern char **bar(char *arg1, int *arg2); +void foobar(void); \ No newline at end of file diff --git a/test/generated/c/function_pointersTest.c b/test/generated/c/function_pointersTest.c index c7575c0..3a184d3 100644 --- a/test/generated/c/function_pointersTest.c +++ b/test/generated/c/function_pointersTest.c @@ -1,3 +1,4 @@ -typedef void *(*test_func)(int arg_name); +typedef void *(*test_func)(int arg1_name, char *arg2_name); typedef void A(void * b); +typedef void *(*with_void)(void); diff --git a/test/generated/c/function_pointersTest.php b/test/generated/c/function_pointersTest.php index 8c30cd8..f74f511 100644 --- a/test/generated/c/function_pointersTest.php +++ b/test/generated/c/function_pointersTest.php @@ -11,8 +11,9 @@ */ class function_pointersTest extends TestCase { - const EXPECTED = 'typedef void *(*test_func)(int arg_name); -typedef void A(void *b);'; + const EXPECTED = 'typedef void *(*test_func)(int arg1_name, char *arg2_name); +typedef void A(void *b); +typedef void *(*with_void)(void);'; protected CParser $parser; protected Printer $printer; From a34d3ffb0288c84176babf06e4ec5136d7ca463c Mon Sep 17 00:00:00 2001 From: Dirk Adler Date: Fri, 1 May 2020 12:25:21 +0200 Subject: [PATCH 5/6] Revert trim approach and print void without trailing space by nesting --- lib/Printer/C.php | 31 +++++++++++++------------- test/cases/c/functions.phpt | 4 ++-- test/generated/c/functionsTest.c | 4 ++++ test/generated/c/functionsTest.php | 35 ++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 17 deletions(-) create mode 100644 test/generated/c/functionsTest.c create mode 100644 test/generated/c/functionsTest.php diff --git a/lib/Printer/C.php b/lib/Printer/C.php index 98a8896..c296fe2 100755 --- a/lib/Printer/C.php +++ b/lib/Printer/C.php @@ -107,35 +107,35 @@ protected function printDecl(Decl $decl, int $level): string { } if ($decl instanceof Decl\NamedDecl\ValueDecl\DeclaratorDecl\FunctionDecl) { $type = $decl->type; - $return = ''; + $attribute = ''; while ($type instanceof Type\AttributedType) { switch ($type->kind) { case Type\AttributedType::KIND_STATIC: - $return .= 'static '; + $attribute .= 'static '; break; case Type\AttributedType::KIND_INLINE: - $return .= 'inline '; + $attribute .= 'inline '; break; default: throw new \LogicException('Unknown function attributed type qualifier: ' . $type->kind); } $type = $type->parent; } - $return .= $this->printType($type->return, null, $level); - $return .= $decl->name . '('; + $result = $decl->name . '('; $next = ''; foreach ($type->params as $idx => $param) { - $return .= $next . trim($this->printType($param, $type->paramNames[$idx], $level)); + $result .= $next . $this->printType($param, $type->paramNames[$idx], $level); $next = ', '; } if ($type->isVariadic) { - $return .= $next . '...'; + $result .= $next . '...'; } - $return .= ')'; + $result .= ')'; if ($decl->stmts !== null) { - $return .= $this->printCompoundStmt($decl->stmts, $level); + $result .= $this->printCompoundStmt($decl->stmts, $level); } - return $return; + $subType = $this->printType($type->return, '__NAME_PLACEHOLDER__', $level); + return $attribute . str_replace('__NAME_PLACEHOLDER__', $result, $subType); } var_dump($decl); } @@ -176,7 +176,7 @@ protected function isFunctionPointer(Type $type): bool { protected function printType(Type $type, ?string $name, int $level): string { if ($type instanceof Type\BuiltinType || $type instanceof Type\TypedefType) { - return $type->name . ($name !== null ? ' ' . $name : ' '); + return $type->name . ($name !== null ? ' ' . $name : ''); } if ($type instanceof Type\TagType\RecordType) { return $this->printDecl($type->decl, $level) . ($name !== null ? ' ' . $name : '') ; @@ -197,7 +197,7 @@ protected function printType(Type $type, ?string $name, int $level): string { $result = $this->printType($type->return, $name, $level) . '('; $next = ''; foreach ($type->params as $idx => $param) { - $result .= $next . trim($this->printType($param, $type->paramNames[$idx], $level)); + $result .= $next . $this->printType($param, $type->paramNames[$idx], $level); $next = ', '; } if ($type->isVariadic) { @@ -210,14 +210,15 @@ protected function printType(Type $type, ?string $name, int $level): string { $result = '(*' . $name . ')('; $next = ''; foreach ($func->params as $idx => $param) { - $result .= $next . trim($this->printType($param, $func->paramNames[$idx], $level)); + $result .= $next . $this->printType($param, $func->paramNames[$idx], $level); $next = ', '; } if ($func->isVariadic) { $result .= $next . '...'; } $result .= ')'; - return $this->printType($func->return, $result, $level); + $subType = $this->printType($func->return, '__NAME_PLACEHOLDER__', $level); + return str_replace('__NAME_PLACEHOLDER__', $result, $subType); } if ($type instanceof Type\PointerType) { $subType = $this->printType($type->parent, '__NAME_PLACEHOLDER__', $level); @@ -234,7 +235,7 @@ protected function printType(Type $type, ?string $name, int $level): string { $subType = $this->printType($type->parent, '__NAME_PLACEHOLDER__', $level); return str_replace('__NAME_PLACEHOLDER__', $name . '[' . $this->printExpr($type->size, $level) . ']' , $subType); } - + var_dump($type); } diff --git a/test/cases/c/functions.phpt b/test/cases/c/functions.phpt index 6aa5ba0..341ff21 100755 --- a/test/cases/c/functions.phpt +++ b/test/cases/c/functions.phpt @@ -3,9 +3,9 @@ Test basic parsing of functions --FILE-- extern char** bar(char* arg1, int* arg2); -void foobar(void); +static void foobar(void); --EXPECT-- extern char **bar(char *arg1, int *arg2); -void foobar(void); \ No newline at end of file +static void foobar(void); \ No newline at end of file diff --git a/test/generated/c/functionsTest.c b/test/generated/c/functionsTest.c new file mode 100644 index 0000000..543e6a4 --- /dev/null +++ b/test/generated/c/functionsTest.c @@ -0,0 +1,4 @@ + +extern char** bar(char* arg1, int* arg2); +static void foobar(void); + diff --git a/test/generated/c/functionsTest.php b/test/generated/c/functionsTest.php new file mode 100644 index 0000000..255994d --- /dev/null +++ b/test/generated/c/functionsTest.php @@ -0,0 +1,35 @@ +parser = new CParser; + $this->parser->addSearchPath(__DIR__); + $this->parser->addSearchPath(__DIR__ . '/../../include'); + $this->printer = new C; + } + + /** + * @textdox Test basic parsing of functions + */ + public function testCode() { + $translationUnit = $this->parser->parse(__DIR__ . '/functionsTest.c'); + $actual = $this->printer->print($translationUnit); + $this->assertEquals(self::EXPECTED, trim($actual)); + } +} \ No newline at end of file From 792aa881aaa4cd4e7fb1bda777dfd640661795a3 Mon Sep 17 00:00:00 2001 From: Dirk Adler Date: Fri, 1 May 2020 12:36:10 +0200 Subject: [PATCH 6/6] Minor code style --- lib/Printer/C.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Printer/C.php b/lib/Printer/C.php index c296fe2..26930d0 100755 --- a/lib/Printer/C.php +++ b/lib/Printer/C.php @@ -233,9 +233,8 @@ protected function printType(Type $type, ?string $name, int $level): string { } if ($type instanceof Type\ArrayType\ConstantArrayType) { $subType = $this->printType($type->parent, '__NAME_PLACEHOLDER__', $level); - return str_replace('__NAME_PLACEHOLDER__', $name . '[' . $this->printExpr($type->size, $level) . ']' , $subType); + return str_replace('__NAME_PLACEHOLDER__', $name . '[' . $this->printExpr($type->size, $level) . ']', $subType); } - var_dump($type); }