Skip to content

Commit 17987da

Browse files
committed
Expand preprocessor support in gen_stubs
Support #ifdef, #ifndef, #else and nested #if's.
1 parent d9e2d18 commit 17987da

File tree

1 file changed

+46
-22
lines changed

1 file changed

+46
-22
lines changed

scripts/dev/gen_stub.php

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -224,20 +224,34 @@ function parseStubFile(string $fileName) {
224224
$nodeTraverser->traverse($stmts);
225225

226226
$funcInfos = [];
227-
$cond = null;
227+
$conds = [];
228228
foreach ($stmts as $stmt) {
229229
foreach ($stmt->getComments() as $comment) {
230230
$text = trim($comment->getText());
231-
if (preg_match('/^#if\s+(.+)$/', $text, $matches)) {
232-
if ($cond !== null) {
233-
throw new Exception("Not implemented preprocessor directive");
231+
if (preg_match('/^#\s*if\s+(.+)$/', $text, $matches)) {
232+
$conds[] = $matches[1];
233+
} else if (preg_match('/^#\s*ifdef\s+(.+)$/', $text, $matches)) {
234+
$conds[] = "defined($matches[1])";
235+
} else if (preg_match('/^#\s*ifndef\s+(.+)$/', $text, $matches)) {
236+
$conds[] = "!defined($matches[1])";
237+
} else if (preg_match('/^#\s*else$/', $text)) {
238+
if (empty($conds)) {
239+
throw new Exception("Encountered else without corresponding #if");
234240
}
235-
$cond = $matches[1];
236-
} else if ($text === '#endif') {
237-
$cond = null;
241+
$cond = array_pop($conds);
242+
$conds[] = "!($cond)";
243+
} else if (preg_match('/^#\s*endif$/', $text)) {
244+
if (empty($conds)) {
245+
throw new Exception("Encountered #endif without corresponding #if");
246+
}
247+
array_pop($conds);
248+
} else if ($text[0] === '#') {
249+
throw new Exception("Unrecognized preprocessor directive \"$text\"");
238250
}
239251
}
240252

253+
$cond = empty($conds) ? null : implode(' && ', $conds);
254+
241255
if ($stmt instanceof Stmt\Nop) {
242256
continue;
243257
}
@@ -272,9 +286,6 @@ function parseStubFile(string $fileName) {
272286

273287
function funcInfoToCode(FuncInfo $funcInfo): string {
274288
$code = '';
275-
if ($funcInfo->cond) {
276-
$code .= "#if {$funcInfo->cond}\n";
277-
}
278289
if ($funcInfo->return->type) {
279290
$returnType = $funcInfo->return->type;
280291
if ($returnType->isBuiltin) {
@@ -326,29 +337,42 @@ function funcInfoToCode(FuncInfo $funcInfo): string {
326337
}
327338

328339
$code .= "ZEND_END_ARG_INFO()";
329-
if ($funcInfo->cond) {
330-
$code .= "\n#endif";
331-
}
332340
return $code;
333341
}
334342

343+
function findEquivalentFuncInfo(array $generatedFuncInfos, $funcInfo): ?FuncInfo {
344+
foreach ($generatedFuncInfos as $generatedFuncInfo) {
345+
if ($generatedFuncInfo->equalsApartFromName($funcInfo)) {
346+
return $generatedFuncInfo;
347+
}
348+
}
349+
return null;
350+
}
351+
335352
/** @param FuncInfo[] $funcInfos */
336353
function generateArginfoCode(array $funcInfos): string {
337354
$code = "/* This is a generated file, edit the .stub.php file instead. */";
338355
$generatedFuncInfos = [];
339356
foreach ($funcInfos as $funcInfo) {
357+
$code .= "\n\n";
358+
if ($funcInfo->cond) {
359+
$code .= "#if {$funcInfo->cond}\n";
360+
}
361+
340362
/* If there already is an equivalent arginfo structure, only emit a #define */
341-
foreach ($generatedFuncInfos as $generatedFuncInfo) {
342-
if ($generatedFuncInfo->equalsApartFromName($funcInfo)) {
343-
$code .= sprintf(
344-
"\n\n#define arginfo_%s arginfo_%s",
345-
$funcInfo->name, $generatedFuncInfo->name
346-
);
347-
continue 2;
348-
}
363+
if ($generatedFuncInfo = findEquivalentFuncInfo($generatedFuncInfos, $funcInfo)) {
364+
$code .= sprintf(
365+
"#define arginfo_%s arginfo_%s",
366+
$funcInfo->name, $generatedFuncInfo->name
367+
);
368+
} else {
369+
$code .= funcInfoToCode($funcInfo);
370+
}
371+
372+
if ($funcInfo->cond) {
373+
$code .= "\n#endif";
349374
}
350375

351-
$code .= "\n\n" . funcInfoToCode($funcInfo);
352376
$generatedFuncInfos[] = $funcInfo;
353377
}
354378
return $code . "\n";

0 commit comments

Comments
 (0)