Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 23 additions & 34 deletions lib/Printer/C.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<?php declare(strict_types=1);
namespace PHPCParser\Printer;

use PHPCParser\Printer;
use PHPCParser\Node;
use PHPCParser\Node\Stmt;
use PHPCParser\Node\Stmt\ValueStmt\Expr;
use PHPCParser\Node\Decl;
use PHPCParser\Node\Decl\NamedDecl\TypeDecl\TagDecl\RecordDecl;
use PHPCParser\Node\Decl\NamedDecl\TypeDecl\TagDecl\EnumDecl;
use PHPCParser\Node\Type;
use PHPCParser\Node\Decl\NamedDecl\TypeDecl\TagDecl\RecordDecl;
use PHPCParser\Node\Stmt;
use PHPCParser\Node\Stmt\ValueStmt\Expr;
use PHPCParser\Node\TranslationUnitDecl;
use PHPCParser\Node\Type;
use PHPCParser\Printer;


class C implements Printer
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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 = [
Expand Down
8 changes: 5 additions & 3 deletions test/cases/c/function_pointers.phpt
Original file line number Diff line number Diff line change
@@ -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);
typedef void *(*test_func)(int arg1_name, char *arg2_name);
typedef void A(void *b);
typedef void *(*with_void)(void);
11 changes: 11 additions & 0 deletions test/cases/c/functions.phpt
Original file line number Diff line number Diff line change
@@ -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);
18 changes: 17 additions & 1 deletion test/cases/c/typedef.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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;
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])())[];
9 changes: 7 additions & 2 deletions test/cases/c/vars.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
int baz[][];
char **qux;
int *quux;
int corge;
3 changes: 2 additions & 1 deletion test/generated/c/function_pointersTest.c
Original file line number Diff line number Diff line change
@@ -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);
5 changes: 3 additions & 2 deletions test/generated/c/function_pointersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions test/generated/c/functionsTest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

extern char** bar(char* arg1, int* arg2);
static void foobar(void);

35 changes: 35 additions & 0 deletions test/generated/c/functionsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php declare(strict_types=1);
namespace PHPCParser\Test\c;
use PHPCParser\CParser;
use PHPCParser\Printer;
use PHPCParser\Printer\Dumper;
use PHPCParser\Printer\C;
use PHPUnit\Framework\TestCase;

/**
* Note: this is a generated file, do not edit this!!!
*/
class functionsTest extends TestCase {

const EXPECTED = 'extern char **bar(char *arg1, int *arg2);
static void foobar(void);';

protected CParser $parser;
protected Printer $printer;

public function setUp(): void {
$this->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));
}
}
8 changes: 8 additions & 0 deletions test/generated/c/typedefTest.c
Original file line number Diff line number Diff line change
@@ -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])())[];
10 changes: 9 additions & 1 deletion test/generated/c/typedefTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion test/generated/c/varsTest.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

extern int foo;
int bar;
int baz[];
int baz[][];
char** qux;
int* quux, corge;

5 changes: 4 additions & 1 deletion test/generated/c/varsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down