예제 #1
0
static int string_length(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    const wchar_t *short_options = L"q";
    const struct woption long_options[] = {{L"quiet", no_argument, 0, 'q'}, {0, 0, 0, 0}};

    bool quiet = false;
    wgetopter_t w;
    for (;;) {
        int opt = w.wgetopt_long(argc, argv, short_options, long_options, 0);

        if (opt == -1) {
            break;
        }
        switch (opt) {
            case 0: {
                break;
            }
            case 'q': {
                quiet = true;
                break;
            }
            case '?': {
                string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
                return BUILTIN_STRING_ERROR;
            }
            default: {
                DIE("unexpected opt");
                break;
            }
        }
    }

    int i = w.woptind;
    if (string_args_from_stdin(streams) && argc > i) {
        string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
        return BUILTIN_STRING_ERROR;
    }

    const wchar_t *arg;
    int nnonempty = 0;
    wcstring storage;
    while ((arg = string_get_arg(&i, argv, &storage, streams)) != 0) {
        size_t n = wcslen(arg);
        if (n > 0) {
            nnonempty++;
        }
        if (!quiet) {
            streams.out.append(to_string(n));
            streams.out.append(L'\n');
        }
    }

    return nnonempty > 0 ? BUILTIN_STRING_OK : BUILTIN_STRING_NONE;
}
예제 #2
0
static int string_escape(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv)
{
    const wchar_t *short_options = L"n";
    const struct woption long_options[] =
    {
        { L"no-quoted", no_argument, 0, 'n' },
        { 0, 0, 0, 0 }
    };

    escape_flags_t flags = ESCAPE_ALL;
    wgetopter_t w;
    for (;;)
    {
        int c = w.wgetopt_long(argc, argv, short_options, long_options, 0);

        if (c == -1)
        {
            break;
        }
        switch (c)
        {
            case 0:
                break;

            case 'n':
                flags |= ESCAPE_NO_QUOTED;
                break;

            case '?':
                string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
                return BUILTIN_STRING_ERROR;
        }
    }

    int i = w.woptind;
    if (string_args_from_stdin(streams) && argc > i)
    {
        string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
        return BUILTIN_STRING_ERROR;
    }

    int nesc = 0;
    wcstring storage;
    const wchar_t *arg;
    while ((arg = string_get_arg(&i, argv, &storage, streams)) != 0)
    {
        streams.out.append(escape(arg, flags));
        streams.out.append(L'\n');
        nesc++;
    }

    return (nesc > 0) ? BUILTIN_STRING_OK : BUILTIN_STRING_NONE;
}
예제 #3
0
static int string_split(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    options_t opts;
    opts.quiet_valid = true;
    opts.right_valid = true;
    opts.max_valid = true;
    opts.max = LONG_MAX;
    int optind;
    int retval = parse_opts(&opts, &optind, 1, argc, argv, parser, streams);
    if (retval != STATUS_CMD_OK) return retval;

    const wchar_t *sep = opts.arg1;
    const wchar_t *sep_end = sep + wcslen(sep);

    wcstring_list_t splits;
    size_t arg_count = 0;
    wcstring storage;
    const wchar_t *arg;
    while ((arg = string_get_arg(&optind, argv, &storage, streams)) != 0) {
        const wchar_t *arg_end = arg + wcslen(arg);
        if (opts.right) {
            typedef std::reverse_iterator<const wchar_t *> reverser;
            split_about(reverser(arg_end), reverser(arg), reverser(sep_end), reverser(sep), &splits,
                        opts.max);
        } else {
            split_about(arg, arg_end, sep, sep_end, &splits, opts.max);
        }
        arg_count++;
    }

    // If we are from the right, split_about gave us reversed strings, in reversed order!
    if (opts.right) {
        for (size_t j = 0; j < splits.size(); j++) {
            std::reverse(splits[j].begin(), splits[j].end());
        }
        std::reverse(splits.begin(), splits.end());
    }

    if (!opts.quiet) {
        for (wcstring_list_t::const_iterator si = splits.begin(); si != splits.end(); ++si) {
            streams.out.append(*si);
            streams.out.append(L'\n');
        }
    }

    // We split something if we have more split values than args.
    return splits.size() > arg_count ? STATUS_CMD_OK : STATUS_CMD_ERROR;
}
예제 #4
0
static int string_trim(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    options_t opts;
    opts.chars_valid = true;
    opts.left_valid = true;
    opts.right_valid = true;
    opts.quiet_valid = true;
    int optind;
    int retval = parse_opts(&opts, &optind, 0, argc, argv, parser, streams);
    if (retval != STATUS_CMD_OK) return retval;

    // If neither left or right is specified, we do both.
    if (!opts.left && !opts.right) {
        opts.left = opts.right = true;
    }

    const wchar_t *arg;
    size_t ntrim = 0;

    wcstring argstr;
    wcstring storage;
    while ((arg = string_get_arg(&optind, argv, &storage, streams)) != 0) {
        argstr = arg;
        // Begin and end are respectively the first character to keep on the left, and first
        // character to trim on the right. The length is thus end - start.
        size_t begin = 0, end = argstr.size();
        if (opts.right) {
            size_t last_to_keep = argstr.find_last_not_of(opts.chars_to_trim);
            end = (last_to_keep == wcstring::npos) ? 0 : last_to_keep + 1;
        }
        if (opts.left) {
            size_t first_to_keep = argstr.find_first_not_of(opts.chars_to_trim);
            begin = (first_to_keep == wcstring::npos ? end : first_to_keep);
        }
        assert(begin <= end && end <= argstr.size());
        ntrim += argstr.size() - (end - begin);
        if (!opts.quiet) {
            streams.out.append(wcstring(argstr, begin, end - begin));
            streams.out.append(L'\n');
        }
    }

    return ntrim > 0 ? STATUS_CMD_OK : STATUS_CMD_ERROR;
}
예제 #5
0
static int string_sub(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    options_t opts;
    opts.length_valid = true;
    opts.quiet_valid = true;
    opts.start_valid = true;
    opts.length = -1;
    int optind;
    int retval = parse_opts(&opts, &optind, 0, argc, argv, parser, streams);
    if (retval != STATUS_CMD_OK) return retval;

    int nsub = 0;
    const wchar_t *arg;
    wcstring storage;
    while ((arg = string_get_arg(&optind, argv, &storage, streams)) != NULL) {
        typedef wcstring::size_type size_type;
        size_type pos = 0;
        size_type count = wcstring::npos;
        wcstring s(arg);
        if (opts.start > 0) {
            pos = static_cast<size_type>(opts.start - 1);
        } else if (opts.start < 0) {
            assert(opts.start != LONG_MIN);  // checked above
            size_type n = static_cast<size_type>(-opts.start);
            pos = n > s.length() ? 0 : s.length() - n;
        }
        if (pos > s.length()) {
            pos = s.length();
        }

        if (opts.length >= 0) {
            count = static_cast<size_type>(opts.length);
        }

        // Note that std::string permits count to extend past end of string.
        if (!opts.quiet) {
            streams.out.append(s.substr(pos, count));
            streams.out.append(L'\n');
        }
        nsub++;
    }

    return nsub > 0 ? STATUS_CMD_OK : STATUS_CMD_ERROR;
}
예제 #6
0
static int string_escape(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    options_t opts;
    opts.no_quoted_valid = true;
    int optind;
    int retval = parse_opts(&opts, &optind, 0, argc, argv, parser, streams);
    if (retval != STATUS_CMD_OK) return retval;

    escape_flags_t flags = ESCAPE_ALL;
    if (opts.no_quoted) flags |= ESCAPE_NO_QUOTED;

    int nesc = 0;
    wcstring storage;
    const wchar_t *arg;
    while ((arg = string_get_arg(&optind, argv, &storage, streams)) != 0) {
        streams.out.append(escape_string(arg, flags));
        streams.out.append(L'\n');
        nesc++;
    }

    return nesc > 0 ? STATUS_CMD_OK : STATUS_CMD_ERROR;
}
예제 #7
0
/// Implementation of `string upper`.
static int string_upper(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    options_t opts;
    opts.quiet_valid = true;
    int optind;
    int retval = parse_opts(&opts, &optind, 0, argc, argv, parser, streams);
    if (retval != STATUS_CMD_OK) return retval;

    int n_transformed = 0;
    wcstring storage;
    while (const wchar_t *arg = string_get_arg(&optind, argv, &storage, streams)) {
        wcstring transformed(arg);
        std::transform(transformed.begin(), transformed.end(), transformed.begin(), std::towupper);
        if (wcscmp(transformed.c_str(), arg)) n_transformed++;
        if (!opts.quiet) {
            streams.out.append(transformed);
            streams.out.append(L'\n');
        }
    }

    return n_transformed > 0 ? STATUS_CMD_OK : STATUS_CMD_ERROR;
}
예제 #8
0
static int string_match(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    wchar_t *cmd = argv[0];

    options_t opts;
    opts.all_valid = true;
    opts.entire_valid = true;
    opts.ignore_case_valid = true;
    opts.invert_valid = true;
    opts.quiet_valid = true;
    opts.regex_valid = true;
    opts.index_valid = true;
    int optind;
    int retval = parse_opts(&opts, &optind, 1, argc, argv, parser, streams);
    if (retval != STATUS_CMD_OK) return retval;
    const wchar_t *pattern = opts.arg1;

    if (opts.entire && opts.index) {
        streams.err.append_format(BUILTIN_ERR_COMBO2, cmd,
                                  _(L"--enter and --index are mutually exclusive"));
        return STATUS_INVALID_ARGS;
    }

    std::unique_ptr<string_matcher_t> matcher;
    if (opts.regex) {
        matcher = make_unique<pcre2_matcher_t>(cmd, pattern, opts, streams);
    } else {
        matcher = make_unique<wildcard_matcher_t>(cmd, pattern, opts, streams);
    }

    const wchar_t *arg;
    wcstring storage;
    while ((arg = string_get_arg(&optind, argv, &storage, streams)) != 0) {
        if (!matcher->report_matches(arg)) {
            return STATUS_INVALID_ARGS;
        }
    }

    return matcher->match_count() > 0 ? STATUS_CMD_OK : STATUS_CMD_ERROR;
}
예제 #9
0
static int string_length(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    options_t opts;
    opts.quiet_valid = true;
    int optind;
    int retval = parse_opts(&opts, &optind, 0, argc, argv, parser, streams);
    if (retval != STATUS_CMD_OK) return retval;

    const wchar_t *arg;
    int nnonempty = 0;
    wcstring storage;
    while ((arg = string_get_arg(&optind, argv, &storage, streams)) != 0) {
        size_t n = wcslen(arg);
        if (n > 0) {
            nnonempty++;
        }
        if (!opts.quiet) {
            streams.out.append(to_string(n));
            streams.out.append(L'\n');
        }
    }

    return nnonempty > 0 ? STATUS_CMD_OK : STATUS_CMD_ERROR;
}
예제 #10
0
static int string_sub(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    const wchar_t *short_options = L":l:qs:";
    const struct woption long_options[] = {{L"length", required_argument, 0, 'l'},
                                           {L"quiet", no_argument, 0, 'q'},
                                           {L"start", required_argument, 0, 's'},
                                           {0, 0, 0, 0}};

    long start = 0;
    long length = -1;
    bool quiet = false;
    wgetopter_t w;
    wchar_t *endptr = NULL;
    for (;;) {
        int c = w.wgetopt_long(argc, argv, short_options, long_options, 0);

        if (c == -1) {
            break;
        }
        switch (c) {
            case 0: {
                break;
            }
            case 'l': {
                errno = 0;
                length = wcstol(w.woptarg, &endptr, 10);
                if (*endptr != L'\0' || (errno != 0 && errno != ERANGE)) {
                    string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg);
                    return BUILTIN_STRING_ERROR;
                }
                if (length < 0 || errno == ERANGE) {
                    string_error(streams, _(L"%ls: Invalid length value '%ls'\n"), argv[0],
                                 w.woptarg);
                    return BUILTIN_STRING_ERROR;
                }
                break;
            }
            case 'q': {
                quiet = true;
                break;
            }
            case 's': {
                errno = 0;
                start = wcstol(w.woptarg, &endptr, 10);
                if (*endptr != L'\0' || (errno != 0 && errno != ERANGE)) {
                    string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg);
                    return BUILTIN_STRING_ERROR;
                }
                if (start == 0 || start == LONG_MIN || errno == ERANGE) {
                    string_error(streams, _(L"%ls: Invalid start value '%ls'\n"), argv[0],
                                 w.woptarg);
                    return BUILTIN_STRING_ERROR;
                }
                break;
            }
            case ':': {
                string_error(streams, STRING_ERR_MISSING, argv[0]);
                return BUILTIN_STRING_ERROR;
            }
            case '?': {
                string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
                return BUILTIN_STRING_ERROR;
            }
            default: {
                DIE("unexpected opt");
                break;
            }
        }
    }

    int i = w.woptind;
    if (string_args_from_stdin(streams) && argc > i) {
        string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
        return BUILTIN_STRING_ERROR;
    }

    int nsub = 0;
    const wchar_t *arg;
    wcstring storage;
    while ((arg = string_get_arg(&i, argv, &storage, streams)) != NULL) {
        typedef wcstring::size_type size_type;
        size_type pos = 0;
        size_type count = wcstring::npos;
        wcstring s(arg);
        if (start > 0) {
            pos = static_cast<size_type>(start - 1);
        } else if (start < 0) {
            assert(start != LONG_MIN);  // checked above
            size_type n = static_cast<size_type>(-start);
            pos = n > s.length() ? 0 : s.length() - n;
        }
        if (pos > s.length()) {
            pos = s.length();
        }

        if (length >= 0) {
            count = static_cast<size_type>(length);
        }

        // Note that std::string permits count to extend past end of string.
        if (!quiet) {
            streams.out.append(s.substr(pos, count));
            streams.out.append(L'\n');
        }
        nsub++;
    }

    return nsub > 0 ? BUILTIN_STRING_OK : BUILTIN_STRING_NONE;
}
예제 #11
0
static int string_split(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    const wchar_t *short_options = L":m:qr";
    const struct woption long_options[] = {{L"max", required_argument, 0, 'm'},
                                           {L"quiet", no_argument, 0, 'q'},
                                           {L"right", no_argument, 0, 'r'},
                                           {0, 0, 0, 0}};

    long max = LONG_MAX;
    bool quiet = false;
    bool right = false;
    wgetopter_t w;
    for (;;) {
        int c = w.wgetopt_long(argc, argv, short_options, long_options, 0);

        if (c == -1) {
            break;
        }
        switch (c) {
            case 0: {
                break;
            }
            case 'm': {
                errno = 0;
                wchar_t *endptr = 0;
                max = wcstol(w.woptarg, &endptr, 10);
                if (*endptr != L'\0' || errno != 0) {
                    string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg);
                    return BUILTIN_STRING_ERROR;
                }
                break;
            }
            case 'q': {
                quiet = true;
                break;
            }
            case 'r': {
                right = true;
                break;
            }
            case ':': {
                string_error(streams, STRING_ERR_MISSING, argv[0]);
                return BUILTIN_STRING_ERROR;
            }
            case '?': {
                string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
                return BUILTIN_STRING_ERROR;
            }
            default: {
                DIE("unexpected opt");
                break;
            }
        }
    }

    int i = w.woptind;
    const wchar_t *sep;
    if ((sep = string_get_arg_argv(&i, argv)) == NULL) {
        string_error(streams, STRING_ERR_MISSING, argv[0]);
        return BUILTIN_STRING_ERROR;
    }
    const wchar_t *sep_end = sep + wcslen(sep);

    if (string_args_from_stdin(streams) && argc > i) {
        string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
        return BUILTIN_STRING_ERROR;
    }

    wcstring_list_t splits;
    size_t arg_count = 0;
    wcstring storage;
    const wchar_t *arg;
    while ((arg = string_get_arg(&i, argv, &storage, streams)) != 0) {
        const wchar_t *arg_end = arg + wcslen(arg);
        if (right) {
            typedef std::reverse_iterator<const wchar_t *> reverser;
            split_about(reverser(arg_end), reverser(arg), reverser(sep_end), reverser(sep), &splits,
                        max);
        } else {
            split_about(arg, arg_end, sep, sep_end, &splits, max);
        }
        arg_count++;
    }

    // If we are from the right, split_about gave us reversed strings, in reversed order!
    if (right) {
        for (size_t j = 0; j < splits.size(); j++) {
            std::reverse(splits[j].begin(), splits[j].end());
        }
        std::reverse(splits.begin(), splits.end());
    }

    if (!quiet) {
        for (wcstring_list_t::const_iterator si = splits.begin(); si != splits.end(); ++si) {
            streams.out.append(*si);
            streams.out.append(L'\n');
        }
    }

    // We split something if we have more split values than args.
    return splits.size() > arg_count ? BUILTIN_STRING_OK : BUILTIN_STRING_NONE;
}
예제 #12
0
static int string_replace(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    const wchar_t *short_options = L"aiqr";
    const struct woption long_options[] = {{L"all", no_argument, 0, 'a'},
                                           {L"ignore-case", no_argument, 0, 'i'},
                                           {L"quiet", no_argument, 0, 'q'},
                                           {L"regex", no_argument, 0, 'r'},
                                           {0, 0, 0, 0}};

    replace_options_t opts;
    bool regex = false;
    wgetopter_t w;
    for (;;) {
        int opt = w.wgetopt_long(argc, argv, short_options, long_options, 0);

        if (opt == -1) {
            break;
        }
        switch (opt) {
            case 0: {
                break;
            }
            case 'a': {
                opts.all = true;
                break;
            }
            case 'i': {
                opts.ignore_case = true;
                break;
            }
            case 'q': {
                opts.quiet = true;
                break;
            }
            case 'r': {
                regex = true;
                break;
            }
            case '?': {
                string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
                return BUILTIN_STRING_ERROR;
            }
            default: {
                DIE("unexpected opt");
                break;
            }
        }
    }

    int i = w.woptind;
    const wchar_t *pattern, *replacement;
    if ((pattern = string_get_arg_argv(&i, argv)) == 0) {
        string_error(streams, STRING_ERR_MISSING, argv[0]);
        return BUILTIN_STRING_ERROR;
    }
    if ((replacement = string_get_arg_argv(&i, argv)) == 0) {
        string_error(streams, STRING_ERR_MISSING, argv[0]);
        return BUILTIN_STRING_ERROR;
    }

    if (string_args_from_stdin(streams) && argc > i) {
        string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
        return BUILTIN_STRING_ERROR;
    }

    string_replacer_t *replacer;
    if (regex) {
        replacer = new regex_replacer_t(argv[0], pattern, replacement, opts, streams);
    } else {
        replacer = new literal_replacer_t(argv[0], pattern, replacement, opts, streams);
    }

    const wchar_t *arg;
    wcstring storage;
    while ((arg = string_get_arg(&i, argv, &storage, streams)) != 0) {
        if (!replacer->replace_matches(arg)) {
            delete replacer;
            return BUILTIN_STRING_ERROR;
        }
    }

    int rc = replacer->replace_count() > 0 ? BUILTIN_STRING_OK : BUILTIN_STRING_NONE;
    delete replacer;
    return rc;
}
예제 #13
0
static int string_join(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    const wchar_t *short_options = L"q";
    const struct woption long_options[] = {{L"quiet", no_argument, 0, 'q'}, {0, 0, 0, 0}};

    bool quiet = false;
    wgetopter_t w;
    for (;;) {
        int opt = w.wgetopt_long(argc, argv, short_options, long_options, 0);

        if (opt == -1) {
            break;
        }

        switch (opt) {
            case 0: {
                break;
            }
            case 'q': {
                quiet = true;
                break;
            }
            case '?': {
                string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
                return BUILTIN_STRING_ERROR;
            }
            default: {
                DIE("unexpected opt");
                break;
            }
        }
    }

    int i = w.woptind;
    const wchar_t *sep;
    if ((sep = string_get_arg_argv(&i, argv)) == 0) {
        string_error(streams, STRING_ERR_MISSING, argv[0]);
        return BUILTIN_STRING_ERROR;
    }

    if (string_args_from_stdin(streams) && argc > i) {
        string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
        return BUILTIN_STRING_ERROR;
    }

    int nargs = 0;
    const wchar_t *arg;
    wcstring storage;
    while ((arg = string_get_arg(&i, argv, &storage, streams)) != 0) {
        if (!quiet) {
            if (nargs > 0) {
                streams.out.append(sep);
            }
            streams.out.append(arg);
        }
        nargs++;
    }
    if (nargs > 0 && !quiet) {
        streams.out.push_back(L'\n');
    }

    return nargs > 1 ? BUILTIN_STRING_OK : BUILTIN_STRING_NONE;
}
예제 #14
0
static int string_trim(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    const wchar_t *short_options = L":c:lqr";
    const struct woption long_options[] = {{L"chars", required_argument, 0, 'c'},
                                           {L"left", no_argument, 0, 'l'},
                                           {L"quiet", no_argument, 0, 'q'},
                                           {L"right", no_argument, 0, 'r'},
                                           {0, 0, 0, 0}};

    bool do_left = 0, do_right = 0;
    bool quiet = false;
    wcstring chars_to_trim = L" \f\n\r\t";
    wgetopter_t w;
    for (;;) {
        int c = w.wgetopt_long(argc, argv, short_options, long_options, 0);

        if (c == -1) {
            break;
        }
        switch (c) {
            case 0: {
                break;
            }
            case 'c': {
                chars_to_trim = w.woptarg;
                break;
            }
            case 'l': {
                do_left = true;
                break;
            }
            case 'q': {
                quiet = true;
                break;
            }
            case 'r': {
                do_right = true;
                break;
            }
            case ':': {
                string_error(streams, STRING_ERR_MISSING, argv[0]);
                return BUILTIN_STRING_ERROR;
            }
            case '?': {
                string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
                return BUILTIN_STRING_ERROR;
            }
            default: {
                DIE("unexpected opt");
                break;
            }
        }
    }

    int i = w.woptind;
    if (string_args_from_stdin(streams) && argc > i) {
        string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
        return BUILTIN_STRING_ERROR;
    }

    // If neither left or right is specified, we do both.
    if (!do_left && !do_right) {
        do_left = true;
        do_right = true;
    }

    const wchar_t *arg;
    size_t ntrim = 0;

    wcstring argstr;
    wcstring storage;
    while ((arg = string_get_arg(&i, argv, &storage, streams)) != 0) {
        argstr = arg;
        // Begin and end are respectively the first character to keep on the left, and first
        // character to trim on the right. The length is thus end - start.
        size_t begin = 0, end = argstr.size();
        if (do_right) {
            size_t last_to_keep = argstr.find_last_not_of(chars_to_trim);
            end = (last_to_keep == wcstring::npos) ? 0 : last_to_keep + 1;
        }
        if (do_left) {
            size_t first_to_keep = argstr.find_first_not_of(chars_to_trim);
            begin = (first_to_keep == wcstring::npos ? end : first_to_keep);
        }
        assert(begin <= end && end <= argstr.size());
        ntrim += argstr.size() - (end - begin);
        if (!quiet) {
            streams.out.append(wcstring(argstr, begin, end - begin));
            streams.out.append(L'\n');
        }
    }

    return ntrim > 0 ? BUILTIN_STRING_OK : BUILTIN_STRING_NONE;
}
예제 #15
0
static int string_match(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
    const wchar_t *short_options = L"ainvqr";
    const struct woption long_options[] = {{L"all", no_argument, 0, 'a'},
                                           {L"ignore-case", no_argument, 0, 'i'},
                                           {L"index", no_argument, 0, 'n'},
                                           {L"invert", no_argument, 0, 'v'},
                                           {L"quiet", no_argument, 0, 'q'},
                                           {L"regex", no_argument, 0, 'r'},
                                           {0, 0, 0, 0}};

    match_options_t opts;
    bool regex = false;
    wgetopter_t w;
    for (;;) {
        int opt = w.wgetopt_long(argc, argv, short_options, long_options, 0);

        if (opt == -1) {
            break;
        }
        switch (opt) {
            case 0: {
                break;
            }
            case 'a': {
                opts.all = true;
                break;
            }
            case 'i': {
                opts.ignore_case = true;
                break;
            }
            case 'n': {
                opts.index = true;
                break;
            }
            case 'v': {
                opts.invert_match = true;
                break;
            }
            case 'q': {
                opts.quiet = true;
                break;
            }
            case 'r': {
                regex = true;
                break;
            }
            case '?': {
                string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
                return BUILTIN_STRING_ERROR;
            }
            default: {
                DIE("unexpected opt");
                break;
            }
        }
    }

    int i = w.woptind;
    const wchar_t *pattern;
    if ((pattern = string_get_arg_argv(&i, argv)) == 0) {
        string_error(streams, STRING_ERR_MISSING, argv[0]);
        return BUILTIN_STRING_ERROR;
    }

    if (string_args_from_stdin(streams) && argc > i) {
        string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
        return BUILTIN_STRING_ERROR;
    }

    std::unique_ptr<string_matcher_t> matcher;
    if (regex) {
        matcher = make_unique<pcre2_matcher_t>(argv[0], pattern, opts, streams);
    } else {
        matcher = make_unique<wildcard_matcher_t>(argv[0], pattern, opts, streams);
    }

    const wchar_t *arg;
    wcstring storage;
    while ((arg = string_get_arg(&i, argv, &storage, streams)) != 0) {
        if (!matcher->report_matches(arg)) {
            return BUILTIN_STRING_ERROR;
        }
    }

    int rc = matcher->match_count() > 0 ? BUILTIN_STRING_OK : BUILTIN_STRING_NONE;
    return rc;
}