gt:                 while (scanner.findInLine("gcc version ") == null) {
context: /*
   * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  package com.oracle.svm.hosted.c.codegen;
  
  import java.io.File;
  import java.io.IOException;
  import java.io.InputStream;
  import java.nio.file.Files;
  import java.nio.file.Path;
  import java.nio.file.Paths;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.List;
  import java.util.NoSuchElementException;
  import java.util.Optional;
  import java.util.Scanner;
  import java.util.function.Consumer;
  import java.util.stream.Collectors;
  
  import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
  import org.graalvm.nativeimage.ImageSingletons;
  import org.graalvm.nativeimage.Platform;
  
  import com.oracle.svm.core.OS;
  import com.oracle.svm.core.SubstrateOptions;
  import com.oracle.svm.core.SubstrateTargetDescription;
  import com.oracle.svm.core.SubstrateUtil;
  import com.oracle.svm.core.c.libc.LibCBase;
  import com.oracle.svm.core.option.SubstrateOptionsParser;
  import com.oracle.svm.core.util.InterruptImageBuilding;
  import com.oracle.svm.core.util.UserError;
  import com.oracle.svm.hosted.c.util.FileUtils;
  import com.oracle.svm.util.ClassUtil;
  
  import jdk.vm.ci.aarch64.AArch64;
  import jdk.vm.ci.amd64.AMD64;
  import jdk.vm.ci.code.Architecture;
  
  public abstract class CCompilerInvoker {
  
      public final Path tempDirectory;
      public final CompilerInfo compilerInfo;
  
      protected CCompilerInvoker(Path tempDirectory) {
          this.tempDirectory = tempDirectory;
          try {
              this.compilerInfo = getCCompilerInfo();
          } catch (UserError.UserException err) {
              throw addSkipCheckingInfo(err);
          }
      }
  
      public static CCompilerInvoker create(Path tempDirectory) {
          OS hostOS = OS.getCurrent();
          switch (hostOS) {
              case LINUX:
                  return new LinuxCCompilerInvoker(tempDirectory);
              case DARWIN:
                  return new DarwinCCompilerInvoker(tempDirectory);
              case WINDOWS:
                  return new WindowsCCompilerInvoker(tempDirectory);
              default:
                  throw UserError.abort("No CCompilerInvoker for operating system %s", hostOS.name());
          }
      }
  
      public void verifyCompiler() {
          if (SubstrateOptions.CheckToolchain.getValue()) {
              try {
                  verify();
              } catch (UserError.UserException err) {
                  throw addSkipCheckingInfo(err);
              }
          }
      }
  
      private static UserError.UserException addSkipCheckingInfo(UserError.UserException err) {
          List<String> messages = new ArrayList<>();
          err.getMessages().forEach(messages::add);
          messages.add("To prevent native-toolchain checking provide command-line option " + SubstrateOptionsParser.commandArgument(SubstrateOptions.CheckToolchain, "-"));
          return UserError.abort(messages);
      }
  
      private static class WindowsCCompilerInvoker extends CCompilerInvoker {
  
          WindowsCCompilerInvoker(Path tempDirectory) {
              super(tempDirectory);
          }
  
          @Override
          public String asExecutableName(String basename) {
              String suffix = ".exe";
              if (basename.endsWith(suffix)) {
                  return basename;
              }
              return basename + suffix;
          }
  
          @Override
          protected String getDefaultCompiler() {
              return "cl";
          }
  
          @Override
          protected List<String> addTarget(Path target) {
              return Arrays.asList("/Fe" + target.toString());
          }
  
          @Override
          protected InputStream getCompilerErrorStream(Process compilingProcess) {
              return compilingProcess.getInputStream();
          }
  
          @Override
          protected List<String> getVersionInfoOptions() {
              return Collections.emptyList();
          }
  
          @Override
          protected CompilerInfo createCompilerInfo(Path compilerPath, Scanner outerScanner) {
              try (Scanner scanner = new Scanner(outerScanner.nextLine())) {
                  String targetArch = null;
                  /* For cl.exe the first line holds all necessary information */
                  if (scanner.hasNext("\u7528\u4E8E")) {
                      /* Simplified-Chinese has targetArch first */
                      scanner.next();
                      targetArch = scanner.next();
                  }
                  /*
                   * Some cl.exe print "... Microsoft (R) C/C++ ... ##.##.#####" while others print
                   * "...C/C++ ... Microsoft (R) ... ##.##.#####".
                   */
                  if (scanner.findInLine("Microsoft.*\\(R\\) C/C\\+\\+") == null &&
                                  scanner.findInLine("C/C\\+\\+.*Microsoft.*\\(R\\)") == null) {
                      return null;
                  }
                  scanner.useDelimiter("\\D");
                  while (!scanner.hasNextInt()) {
                      scanner.next();
                  }
                  int major = scanner.nextInt();
                  int minor0 = scanner.nextInt();
                  int minor1 = scanner.nextInt();
                  if (targetArch == null) {
                      scanner.reset();
                      while (scanner.hasNext()) {
                          /* targetArch is last token in line */
                          targetArch = scanner.next();
                      }
                  }
                  return new CompilerInfo(compilerPath, "microsoft", "C/C++ Optimizing Compiler", "cl", major, minor0, minor1, targetArch);
              } catch (NoSuchElementException e) {
                  return null;
              }
          }
  
          @Override
          protected void verify() {
              // See details on _MSC_VER at https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B
              // The constraint of `_MSC_VER >= 1912` reflects the version used for building OpenJDK8.
              if (compilerInfo.versionMajor < 19 || compilerInfo.versionMinor0 < 12) {
                  UserError.abort("Java %d native-image building on Windows requires Visual Studio 2017 version 15.5 or later (C/C++ Optimizing Compiler Version 19.12 or later).%nCompiler info detected: %s",
                                  JavaVersionUtil.JAVA_SPEC, compilerInfo);
              }
              if (guessArchitecture(compilerInfo.targetArch) != AMD64.class) {
                  String targetPrefix = compilerInfo.targetArch.matches("(.*x|i\\d)86$") ? "32-bit architecture " : "";
                  UserError.abort("Native-image building on Windows currently only supports target architecture: %s (%s%s unsupported)",
                                  AMD64.class.getSimpleName(), targetPrefix, compilerInfo.targetArch);
              }
          }
  
          @Override
          protected List<String> compileStrictOptions() {
              /*
               * On Windows `/Wall` corresponds to `-Wall -Wextra`. Therefore we use /W4 instead.
               * Options `/wd4244` and `/wd4245` are needed because our query code makes use of
               * implicit unsigned/signed conversions to detect signedness of types. `/wd4800`,
               * `/wd4804` are needed to silence warnings when querying bool types. `/wd4214` is
               * needed to make older versions of cl.exe accept bitfields larger than int-size.
               */
              return Arrays.asList("/WX", "/W4", "/wd4244", "/wd4245", "/wd4800", "/wd4804", "/wd4214");
          }
      }
  
      private static class LinuxCCompilerInvoker extends CCompilerInvoker {
  
          LinuxCCompilerInvoker(Path tempDirectory) {
              super(tempDirectory);
          }
  
          @Override
          protected String getDefaultCompiler() {
              if (Platform.includedIn(Platform.LINUX.class)) {
                  return LibCBase.singleton().getTargetCompiler();
              }
              return "gcc";
          }
  
          @Override
          protected CompilerInfo createCompilerInfo(Path compilerPath, Scanner scanner) {
              try {
                  if (scanner.findInLine("icc version ") != null) {
                      scanner.useDelimiter("[. ]");
                      int major = scanner.nextInt();
                      int minor0 = scanner.nextInt();
                      int minor1 = scanner.nextInt();
                      return new CompilerInfo(compilerPath, "intel", "Intel(R) C++ Compiler", "icc", major, minor0, minor1, "x86_64");
                  }
  
                  if (scanner.findInLine("clang version ") != null) {
                      scanner.useDelimiter("[. -]");
                      int major = scanner.nextInt();
                      int minor0 = scanner.nextInt();
                      int minor1 = scanner.nextInt();
                      String[] triplet = guessTargetTriplet(scanner);
                      return new CompilerInfo(compilerPath, "llvm", "Clang C++ Compiler", "clang", major, minor0, minor1, triplet[0]);
                  }
  
                  String[] triplet = guessTargetTriplet(scanner);
  