diff --git a/lib/Printer/C.php b/lib/Printer/C.php index ee3ccab..26930d0 100755 --- a/lib/Printer/C.php +++ b/lib/Printer/C.php @@ -1,15 +1,15 @@ 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); @@ -110,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 . $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); } @@ -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; @@ -217,8 +207,7 @@ protected function printType(Type $type, ?string $name, int $level): string { } if ($this->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); @@ -227,14 +216,16 @@ protected function printType(Type $type, ?string $name, int $level): string { if ($func->isVariadic) { $result .= $next . '...'; } - return $result . ')'; + $result .= ')'; + $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); 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); @@ -244,9 +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); - } const BINARYOPERATOR_MAP = [ 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 new file mode 100755 index 0000000..341ff21 --- /dev/null +++ b/test/cases/c/functions.phpt @@ -0,0 +1,11 @@ +--TEST-- +Test basic parsing of functions +--FILE-- + +extern char** bar(char* arg1, int* arg2); +static void foobar(void); + +--EXPECT-- + +extern char **bar(char *arg1, int *arg2); +static void foobar(void); \ No newline at end of file diff --git a/test/cases/c/typedef.phpt b/test/cases/c/typedef.phpt index 8c38a90..fc3a926 100755 --- a/test/cases/c/typedef.phpt +++ b/test/cases/c/typedef.phpt @@ -2,5 +2,21 @@ Test basic parsing of vars --FILE-- typedef void* foo; +typedef unsigned char bar[23]; +typedef long baz[][]; +typedef enum qux { + QUUX, + CORGE, +} grault; +typedef char *(*(waldos))[5]; +typedef char *(*(**hairy[][8])())[]; --EXPECT-- -typedef void * foo; \ No newline at end of file +typedef void *foo; +typedef unsigned char bar[23]; +typedef long baz[][]; +typedef enum qux { + QUUX, + CORGE, +} grault; +typedef char *(*(waldos))[5]; +typedef char *(*(**hairy[][8])())[]; \ 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/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; 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 diff --git a/test/generated/c/typedefTest.c b/test/generated/c/typedefTest.c index 63fe94d..4e76236 100644 --- a/test/generated/c/typedefTest.c +++ b/test/generated/c/typedefTest.c @@ -1 +1,9 @@ typedef void* foo; +typedef unsigned char bar[23]; +typedef long baz[][]; +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 731d65d..260f7bf 100644 --- a/test/generated/c/typedefTest.php +++ b/test/generated/c/typedefTest.php @@ -11,7 +11,15 @@ */ class typedefTest extends TestCase { - const EXPECTED = 'typedef void * foo;'; + const EXPECTED = 'typedef void *foo; +typedef unsigned char bar[23]; +typedef long baz[][]; +typedef enum qux { + QUUX, + CORGE, +} grault; +typedef char *(*(waldos))[5]; +typedef char *(*(**hairy[][8])())[];'; 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;