@@ -224,20 +224,34 @@ function parseStubFile(string $fileName) {
224
224
$ nodeTraverser ->traverse ($ stmts );
225
225
226
226
$ funcInfos = [];
227
- $ cond = null ;
227
+ $ conds = [] ;
228
228
foreach ($ stmts as $ stmt ) {
229
229
foreach ($ stmt ->getComments () as $ comment ) {
230
230
$ 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 " );
234
240
}
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 \"" );
238
250
}
239
251
}
240
252
253
+ $ cond = empty ($ conds ) ? null : implode (' && ' , $ conds );
254
+
241
255
if ($ stmt instanceof Stmt \Nop) {
242
256
continue ;
243
257
}
@@ -272,9 +286,6 @@ function parseStubFile(string $fileName) {
272
286
273
287
function funcInfoToCode (FuncInfo $ funcInfo ): string {
274
288
$ code = '' ;
275
- if ($ funcInfo ->cond ) {
276
- $ code .= "#if {$ funcInfo ->cond }\n" ;
277
- }
278
289
if ($ funcInfo ->return ->type ) {
279
290
$ returnType = $ funcInfo ->return ->type ;
280
291
if ($ returnType ->isBuiltin ) {
@@ -326,29 +337,42 @@ function funcInfoToCode(FuncInfo $funcInfo): string {
326
337
}
327
338
328
339
$ code .= "ZEND_END_ARG_INFO() " ;
329
- if ($ funcInfo ->cond ) {
330
- $ code .= "\n#endif " ;
331
- }
332
340
return $ code ;
333
341
}
334
342
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
+
335
352
/** @param FuncInfo[] $funcInfos */
336
353
function generateArginfoCode (array $ funcInfos ): string {
337
354
$ code = "/* This is a generated file, edit the .stub.php file instead. */ " ;
338
355
$ generatedFuncInfos = [];
339
356
foreach ($ funcInfos as $ funcInfo ) {
357
+ $ code .= "\n\n" ;
358
+ if ($ funcInfo ->cond ) {
359
+ $ code .= "#if {$ funcInfo ->cond }\n" ;
360
+ }
361
+
340
362
/* 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 " ;
349
374
}
350
375
351
- $ code .= "\n\n" . funcInfoToCode ($ funcInfo );
352
376
$ generatedFuncInfos [] = $ funcInfo ;
353
377
}
354
378
return $ code . "\n" ;
0 commit comments