From 17987da884f8ff1147f4804ce42622a001eb7210 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 10 Aug 2019 15:07:54 +0200 Subject: Expand preprocessor support in gen_stubs Support #ifdef, #ifndef, #else and nested #if's. --- scripts/dev/gen_stub.php | 68 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 22 deletions(-) (limited to 'scripts') diff --git a/scripts/dev/gen_stub.php b/scripts/dev/gen_stub.php index 59b7d448f6..993be075d7 100755 --- a/scripts/dev/gen_stub.php +++ b/scripts/dev/gen_stub.php @@ -224,20 +224,34 @@ function parseStubFile(string $fileName) { $nodeTraverser->traverse($stmts); $funcInfos = []; - $cond = null; + $conds = []; foreach ($stmts as $stmt) { foreach ($stmt->getComments() as $comment) { $text = trim($comment->getText()); - if (preg_match('/^#if\s+(.+)$/', $text, $matches)) { - if ($cond !== null) { - throw new Exception("Not implemented preprocessor directive"); + if (preg_match('/^#\s*if\s+(.+)$/', $text, $matches)) { + $conds[] = $matches[1]; + } else if (preg_match('/^#\s*ifdef\s+(.+)$/', $text, $matches)) { + $conds[] = "defined($matches[1])"; + } else if (preg_match('/^#\s*ifndef\s+(.+)$/', $text, $matches)) { + $conds[] = "!defined($matches[1])"; + } else if (preg_match('/^#\s*else$/', $text)) { + if (empty($conds)) { + throw new Exception("Encountered else without corresponding #if"); } - $cond = $matches[1]; - } else if ($text === '#endif') { - $cond = null; + $cond = array_pop($conds); + $conds[] = "!($cond)"; + } else if (preg_match('/^#\s*endif$/', $text)) { + if (empty($conds)) { + throw new Exception("Encountered #endif without corresponding #if"); + } + array_pop($conds); + } else if ($text[0] === '#') { + throw new Exception("Unrecognized preprocessor directive \"$text\""); } } + $cond = empty($conds) ? null : implode(' && ', $conds); + if ($stmt instanceof Stmt\Nop) { continue; } @@ -272,9 +286,6 @@ function parseStubFile(string $fileName) { function funcInfoToCode(FuncInfo $funcInfo): string { $code = ''; - if ($funcInfo->cond) { - $code .= "#if {$funcInfo->cond}\n"; - } if ($funcInfo->return->type) { $returnType = $funcInfo->return->type; if ($returnType->isBuiltin) { @@ -326,29 +337,42 @@ function funcInfoToCode(FuncInfo $funcInfo): string { } $code .= "ZEND_END_ARG_INFO()"; - if ($funcInfo->cond) { - $code .= "\n#endif"; - } return $code; } +function findEquivalentFuncInfo(array $generatedFuncInfos, $funcInfo): ?FuncInfo { + foreach ($generatedFuncInfos as $generatedFuncInfo) { + if ($generatedFuncInfo->equalsApartFromName($funcInfo)) { + return $generatedFuncInfo; + } + } + return null; +} + /** @param FuncInfo[] $funcInfos */ function generateArginfoCode(array $funcInfos): string { $code = "/* This is a generated file, edit the .stub.php file instead. */"; $generatedFuncInfos = []; foreach ($funcInfos as $funcInfo) { + $code .= "\n\n"; + if ($funcInfo->cond) { + $code .= "#if {$funcInfo->cond}\n"; + } + /* If there already is an equivalent arginfo structure, only emit a #define */ - foreach ($generatedFuncInfos as $generatedFuncInfo) { - if ($generatedFuncInfo->equalsApartFromName($funcInfo)) { - $code .= sprintf( - "\n\n#define arginfo_%s arginfo_%s", - $funcInfo->name, $generatedFuncInfo->name - ); - continue 2; - } + if ($generatedFuncInfo = findEquivalentFuncInfo($generatedFuncInfos, $funcInfo)) { + $code .= sprintf( + "#define arginfo_%s arginfo_%s", + $funcInfo->name, $generatedFuncInfo->name + ); + } else { + $code .= funcInfoToCode($funcInfo); + } + + if ($funcInfo->cond) { + $code .= "\n#endif"; } - $code .= "\n\n" . funcInfoToCode($funcInfo); $generatedFuncInfos[] = $funcInfo; } return $code . "\n"; -- cgit v1.2.1