Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port f2c_fixes patch from upstream #5

Merged
merged 4 commits into from
Jun 28, 2024
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

## [0.27.1] - 2024/06/28

## Changed

- ported f2c_fixes patch from https://github.com/pyodide/pyodide/pull/4822

## [0.27.0] - 2024/06/18

- pyodide-build is now developed under https://github.com/pyodide/pyodide-build.
74 changes: 64 additions & 10 deletions pyodide_build/_f2c_fixes.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ def fix_f2c_input(f2c_input_path: str) -> None:
lines = f.readlines()
new_lines = []
lines = char1_args_to_int(lines)

for line in lines:
line = fix_string_args(line)

Expand Down Expand Up @@ -91,6 +90,27 @@ def fix_f2c_input(f2c_input_path: str) -> None:

new_lines.append(line)

# We assume one function per file, since this seems quite consistently true.
# Figure out if it's supposed to be recursive. f2c can't handle the
# recursive keyword so we need to remove it and add a comment so we can tell
# it was supposed to be recursive. In fix_f2c_output, we'll remove the
# static keywords from all the variables.
is_recursive = False
for idx, line in enumerate(new_lines):
if "recursive" in line:
is_recursive = True
new_lines[idx] = new_lines[idx].replace("recursive", "")
if line.strip() == "recursive":
# If whole line was recursive, then the next line starts with an
# asterisk to indicate line continuation. Fortran is very
# persnickity so we have to remove the line continuation. Make
# sure to replace the * with a space because the number of
# pre-code characters is significant...
new_lines[idx + 1] = new_lines[idx + 1].replace("*", " ")
break
if is_recursive:
new_lines.insert(0, "C .. xxISRECURSIVExx ..\n")

with open(f2c_input_path, "w") as f:
f.writelines(new_lines)

Expand Down Expand Up @@ -194,9 +214,12 @@ def fix_f2c_output(f2c_output_path: str) -> str | None:
90 and Fortran 95.
"""
f2c_output = Path(f2c_output_path)

with open(f2c_output) as f:
lines = f.readlines()

is_recursive = any("xxISRECURSIVExx" in line for line in lines)

lines = list(regroup_lines(lines))
if "id_dist" in f2c_output_path:
# Fix implicit casts in id_dist.
lines = fix_inconsistent_decls(lines)
Expand Down Expand Up @@ -270,16 +293,45 @@ def fix_line(line: str) -> str:
if "eupd.c" in str(f2c_output):
# put signature on a single line to make replacement more
# straightforward
regrouped_lines = regroup_lines(lines)
lines = [
re.sub(r",?\s*ftnlen\s*(howmny_len|bmat_len)", "", line)
for line in regrouped_lines
re.sub(r",?\s*ftnlen\s*(howmny_len|bmat_len)", "", line) for line in lines
]

# Fix signature of c_abs to match the OpenBLAS one
if "REVCOM.c" in str(f2c_output):
lines = [line.replace("double c_abs(", "float c_abs(") for line in lines]

# Non recursive functions declare all their locals as static, ones marked
# "recursive" need them to be proper local variables. For recursive
# functions we'll replace them.
def fix_static(line: str) -> str:
static_prefix = " static"
if not line.startswith(static_prefix):
return line
line = line.removeprefix(static_prefix).strip()
# If line contains a { or " there's already an initializer and we'll get
# confused. When there's an initializer there's also only one variable
# so we don't need to do anything.
if "{" in line or '"' in line:
return line + "\n"
# split off type
type, rest = line.split(" ", 1)
# Since there is no { or " each comma separates a variable name
names = rest[:-1].split(",")
init_names = []
for name in names:
if "=" in name:
# There's already an initializer
init_names.append(name)
else:
# = {0} initializes all types to all 0s.
init_names.append(name + " = {0}")
joined_names = ",".join(init_names)
return f" {type} {joined_names};\n"

if is_recursive:
lines = list(map(fix_static, lines))

with open(f2c_output, "w") as f:
f.writelines(lines)

Expand Down Expand Up @@ -333,15 +385,18 @@ def regroup_lines(lines: Iterable[str]) -> Iterator[str]:
... static doublereal psum[52];
... extern /* Subroutine */ int dqelg_(integer *, doublereal *, doublereal *,
... doublereal *, doublereal *, integer *);
... '''))))
... '''))).strip())
/* Subroutine */ int clanhfwrp_(real *ret, char *norm, char *transr, char * uplo, integer *n, complex *a, real *work, ftnlen norm_len, ftnlen transr_len, ftnlen uplo_len){
static doublereal psum[52];
extern /* Subroutine */ int dqelg_(integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *);

"""
line_iter = iter(lines)
for line in line_iter:
if "/* Subroutine */" not in line:
if "/* Subroutine */" not in line and "static" not in line:
yield line
continue

if '"' in line:
yield line
continue

Expand All @@ -360,7 +415,7 @@ def regroup_lines(lines: Iterable[str]) -> Iterator[str]:
if is_definition:
yield joined_line
else:
yield from (x + ";" for x in joined_line.split(";")[:-1])
yield from (x + ";\n" for x in joined_line.split(";")[:-1])


def fix_inconsistent_decls(lines: list[str]) -> list[str]:
Expand Down Expand Up @@ -410,7 +465,6 @@ def fix_inconsistent_decls(lines: list[str]) -> list[str]:
}
"""
func_types = {}
lines = list(regroup_lines(lines))
for line in lines:
if not line.startswith("/* Subroutine */"):
continue
Expand Down
Loading