diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index cf0f40070..a4571b271 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -267,6 +267,7 @@ Thomas Aldrian Thomas Brown Thomas Dybdahl Ahle Tim Hutt +Tim Paine Tim Snyder Tobias Jensen Tobias Rosenkranz diff --git a/src/flexfix b/src/flexfix index 0a64beb0c..b68646f2c 100755 --- a/src/flexfix +++ b/src/flexfix @@ -12,10 +12,48 @@ ###################################################################### # DESCRIPTION: Edits flex output to get around various broken flex issues. +import os import re +import subprocess import sys import platform + +def _flexlexer_uses_size_t() -> bool: + """Return True if the FlexLexer.h that will be used declares LexerInput with size_t.""" + candidates = [] + env_paths = os.environ.get("CPATH", "") + os.pathsep + os.environ.get("CPLUS_INCLUDE_PATH", "") + for d in env_paths.split(os.pathsep): + if d: + candidates.append(os.path.join(d, "FlexLexer.h")) + if platform.system() == "Darwin": + try: + sdk = subprocess.check_output(["xcrun", "--show-sdk-path"], + stderr=subprocess.DEVNULL).decode().strip() + if sdk: + candidates.append(os.path.join(sdk, "usr", "include", "FlexLexer.h")) + except (OSError, subprocess.CalledProcessError): + pass + candidates.extend([ + "/opt/homebrew/include/FlexLexer.h", + "/usr/local/include/FlexLexer.h", + ]) + candidates.extend(["/usr/include/FlexLexer.h"]) + for path in candidates: + try: + with open(path, "r", encoding="utf-8", errors="ignore") as fh: + text = fh.read() + except OSError: + continue + if re.search(r"\bLexerInput\s*\(\s*char\s*\*\s*\w*\s*,\s*size_t\b", text): + return True + if re.search(r"\bLexerInput\s*\(\s*char\s*\*\s*\w*\s*,\s*int\b", text): + return False + return False + + +_LEXER_USES_SIZE_T = _flexlexer_uses_size_t() + for line in sys.stdin: # Fix flex 2.6.1 warning line = re.sub(r'for \( i = 0; i < _yybytes_len; \+\+i \)', @@ -48,14 +86,12 @@ for line in sys.stdin: line = re.sub(r'(#line \d+ ".*)_pretmp', r'\1', line) # Fix 'register' storage class specifier is deprecated and incompatible with C++17 line = re.sub(r'register ', '', line) - # Change int to size_t on LexerInput/LexerOutput when using macOS Tahoe - if platform.system() == "Darwin": - try: - osv = platform.mac_ver()[0] # Example "26.2" - if len(osv) > 2 and osv[2] == "." and int(osv[:2]) >= 26: - if "::LexerInput(" in line or "::LexerOutput(" in line: - line = re.sub(r'int ', r'size_t ', line) - except IndexError as e: - print(f"Unexpected index error {e}") + # Change int to size_t on LexerInput/LexerOutput when the FlexLexer.h in use + # declares them with size_t (e.g. macOS Tahoe's system flex). Skip when the + # actual FlexLexer.h still uses int (e.g. Homebrew flex 2.6.4) to avoid an + # out-of-line-definition mismatch. + if _LEXER_USES_SIZE_T: + if "::LexerInput(" in line or "::LexerOutput(" in line: + line = re.sub(r'int ', r'size_t ', line) print(line, end='')