Skip to content

Commit 83e3a9e

Browse files
committed
add C API check tool to mx python-capi-forwards
1 parent e43231d commit 83e3a9e

File tree

1 file changed

+49
-0
lines changed
  • graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi

1 file changed

+49
-0
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiCodeGen.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import java.io.IOException;
5353
import java.nio.file.Files;
5454
import java.nio.file.Path;
55+
import java.nio.file.Paths;
5556
import java.util.ArrayList;
5657
import java.util.Arrays;
5758
import java.util.Collections;
@@ -62,6 +63,7 @@
6263
import java.util.function.IntFunction;
6364
import java.util.stream.Collectors;
6465
import java.util.stream.IntStream;
66+
import java.util.stream.Stream;
6567

6668
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltinRegistry;
6769
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin;
@@ -480,13 +482,60 @@ private static boolean generateBuiltinRegistry(List<CApiBuiltinDesc> javaBuiltin
480482
return writeGenerated(Path.of("com.oracle.graal.python", "src", "com", "oracle", "graal", "python", "builtins", "modules", "cext", "PythonCextBuiltinRegistry.java"), lines);
481483
}
482484

485+
private static void checkUnimplementedAPI(Path path, List<CApiBuiltinDesc> additionalBuiltins) {
486+
List<String> lines;
487+
try {
488+
lines = Files.readAllLines(path);
489+
} catch (IOException e) {
490+
System.out.println(" Error while reading " + path + ": " + e.getMessage());
491+
return;
492+
}
493+
boolean msg = false;
494+
for (CApiBuiltinDesc builtin : additionalBuiltins) {
495+
if (builtin.call == NotImplemented) {
496+
for (int i = 0; i < lines.size(); i++) {
497+
String line = lines.get(i);
498+
int offset = line.indexOf(builtin.name);
499+
// avoid recognizing, e.g. "_PyObject_CallMethodId" in
500+
// "_PyObject_CallMethodIdNoArgs"
501+
if (offset > 0 && Character.isUnicodeIdentifierPart(line.charAt(offset - 1))) {
502+
continue;
503+
}
504+
if (offset + builtin.name.length() < line.length() && Character.isUnicodeIdentifierPart(line.charAt(offset + builtin.name.length()))) {
505+
continue;
506+
}
507+
if (line.contains(builtin.name)) {
508+
if (!msg) {
509+
msg = true;
510+
System.out.println("Checking " + path);
511+
}
512+
System.out.println(" " + builtin.name + " used in " + path + " line " + (i + 1) + ": " + line);
513+
}
514+
}
515+
}
516+
}
517+
}
518+
483519
/**
484520
* Entry point for the "mx python-capi-forwards" command.
485521
*/
486522
public static void main(String[] args) throws IOException {
487523
List<CApiBuiltinDesc> javaBuiltins = CApiFunction.getJavaBuiltinDefinitions();
488524
List<CApiBuiltinDesc> additionalBuiltins = CApiFunction.getOtherBuiltinDefinitions();
489525

526+
/*
527+
* Calling with arguments "check <path>" will recursively check all files in the path for
528+
* unimplemented C API functions.
529+
*/
530+
if (args.length == 2 && "check".equals(args[0])) {
531+
System.out.println("Checking usages of unimplemented API:");
532+
String path = args[1];
533+
try (Stream<Path> stream = Files.walk(Paths.get(path))) {
534+
stream.filter(Files::isRegularFile).forEach(p -> checkUnimplementedAPI(p, additionalBuiltins));
535+
}
536+
return;
537+
}
538+
490539
List<CApiBuiltinDesc> allBuiltins = new ArrayList<>();
491540
allBuiltins.addAll(additionalBuiltins);
492541
for (var entry : javaBuiltins) {

0 commit comments

Comments
 (0)