getopt_long method

int getopt_long(
  1. int argc,
  2. List<String> argv,
  3. String optstring,
  4. List<Option> longopts, [
  5. List<int>? longindex,
])

Parses long options in addition to short options.

Implementation

int getopt_long(int argc, List<String> argv, String optstring, List<Option> longopts, [List<int>? longindex]) {
  _optarg = null;

  if (_optind >= argc || _optind < 0) {
    return -1;
  }

  String arg = argv[_optind];

  if (arg.isEmpty || arg[0] != '-' || arg == '-') {
    return -1;
  }

  if (arg == '--') {
    _optind++;
    return -1;
  }

  // Handle long options
  if (arg.startsWith('--')) {
    String opt = arg.substring(2);
    String? eqArg;
    int eqIdx = opt.indexOf('=');
    if (eqIdx != -1) {
      eqArg = opt.substring(eqIdx + 1);
      opt = opt.substring(0, eqIdx);
    }

    int matchIdx = -1;
    bool ambiguous = false;

    for (int i = 0; i < longopts.length; i++) {
      if (longopts[i].name == opt) {
        matchIdx = i;
        ambiguous = false;
        break;
      } else if (longopts[i].name.startsWith(opt)) {
        if (matchIdx == -1) {
          matchIdx = i;
        } else {
          ambiguous = true;
        }
      }
    }

    if (ambiguous) {
      _printError(argv[0], "option '--$opt' is ambiguous");
      _optind++;
      return '?'.codeUnitAt(0);
    }

    if (matchIdx != -1) {
      if (longindex != null && longindex.isNotEmpty) {
        longindex[0] = matchIdx;
      }

      var option = longopts[matchIdx];

      if (option.has_arg == required_argument) {
        if (eqArg != null) {
          _optarg = eqArg;
          _optind++;
        } else if (_optind + 1 < argc) {
          _optarg = argv[_optind + 1];
          _optind += 2;
        } else {
          _printError(argv[0], "option '--${option.name}' requires an argument");
          _optind++;
          return optstring.startsWith(':') ? ':'.codeUnitAt(0) : '?'.codeUnitAt(0);
        }
      } else if (option.has_arg == optional_argument) {
        if (eqArg != null) {
          _optarg = eqArg;
        } else {
          _optarg = null;
        }
        _optind++;
      } else {
        // no_argument
        if (eqArg != null) {
          _printError(argv[0], "option '--${option.name}' doesn't allow an argument");
          _optind++;
          return '?'.codeUnitAt(0);
        }
        _optind++;
      }

      if (option.flag != null && option.flag!.isNotEmpty) {
        option.flag![0] = option.val;
        return 0;
      }
      return option.val;
    }

    // If we are here, long option not found
    _printError(argv[0], "unrecognized option '--$opt'");
    _optind++;
    return '?'.codeUnitAt(0);
  }

  // Fall back to short options
  return getopt(argc, argv, optstring);
}