Загрузка данных


#include <stdio.h>
#include <regex.h>
#include <stdlib.h>

typedef struct {
    int i;
    int v;
    int n;
    int h;
    int c;
    int l;
    int s;
    int f;
    int o;
} Flags;

int pattern_in_string(char *line_buffer, regex_t *proc_string, int patterns_count, Flags flags);

int pattern_in_string_f(char *line_buffer, regex_t *proc_string, int patterns_count, char *filename, int show_name, int line_numb, Flags flags);

int readfile(FILE *file, regex_t *proc_string, char *filename, int show_name, int patterns_count, Flags flags);

int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "error");
        return 1;
    }
    Flags flags = {0, 0, 0, 0, 0, 0, 0, 0, 0};
    char *patterns[1024];
    int patterns_count = 0;
    char *files[1024];
    int files_count = 0;
    int exit_status = 0;
    int has_ef = 0;
    char buffer_f[1024][1024];
    int buffer_f_ind = 0;
    for (int i = 1; i < argc; i++) {
        if ((argv[i][0] == '-' && argv[i][1] == 'e' && argv[i][2] == '\0') || (argv[i][0] == '-' && argv[i][1] == 'f' && argv[i][2] == '\0')) {
            if (i + 1 < argc) {
                i++;
                has_ef = 1;
            }
            else {
                fprintf(stderr, "no pattern");
                return 1;
            }
        }
    }
    for (int j = 1; j < argc; j++) {
        if (argv[j][0] == '-' && argv[j][1] != '-') {
            for (int k = 1; argv[j][k] != '\0'; k++) {
                if (argv[j][k] == 'e') {
                    if (argv[j][k + 1] != '\0') {
                        patterns[patterns_count] = &argv[j][k + 1];
                        patterns_count += 1;
                        break;
                    }
                    else if (j + 1 < argc) {
                        patterns[patterns_count] = argv[j + 1];
                        patterns_count += 1;
                        j++;
                        break;
                    }
                    else {
                        fprintf(stderr, " no pattern after -e");
                        return 1;
                    }
                }
                else if (argv[j][k] == 'f') {
                    char *f_filename;
                    if (argv[j][k + 1] != '\0') {
                        f_filename = &argv[j][k + 1];
                    }
                    else if (j + 1 < argc) {
                        f_filename = argv[j + 1];
                        j++;
                    }
                    else {
                        fprintf(stderr, "no file after -f");
                        return 1;
                    }
                    FILE *f_file = fopen(f_filename, "r");
                    if (f_file == NULL) {
                        fprintf(stderr, "error with f_file");
                        return 1;
                    }
                    int symbol_f = fgetc(f_file);
                    buffer_f_ind = 0;
                    while (symbol_f != EOF) {
                        if (symbol_f != '\n') {
                            buffer_f[patterns_count][buffer_f_ind] = symbol_f;
                            buffer_f_ind += 1;
                        }
                        else if (symbol_f == '\n') {
                            buffer_f[patterns_count][buffer_f_ind] = '\0';
                            patterns[patterns_count] = buffer_f[patterns_count];
                            patterns_count += 1;
                            buffer_f_ind = 0;
                        }
                    symbol_f = fgetc(f_file);
                    }
                    if (ferror(f_file)) {
                        fprintf(stderr, "error with patterns file");
                        fclose(f_file);
                        return 1;
                    }
                    if (buffer_f_ind > 0) {
                        buffer_f[patterns_count][buffer_f_ind] = '\0';
                        patterns[patterns_count] = buffer_f[patterns_count];
                        patterns_count += 1;
                    }
                    fclose(f_file);
                    break;
                }
                else if (argv[j][k] == 'i') {
                    flags.i = 1;
                }
                else if (argv[j][k] == 'v') {
                    flags.v = 1;
                }
                else if (argv[j][k] == 'n') {
                    flags.n = 1;
                }
                else if (argv[j][k] == 'h') {
                    flags.h = 1;
                }
                else if (argv[j][k] == 'c') {
                    flags.c = 1;
                }
                else if (argv[j][k] == 'l') {
                    flags.l = 1;
                }
                else if (argv[j][k] == 's') {
                    flags.s = 1;
                }
                else if (argv[j][k] == 'o') {
                    flags.o = 1;
                }
                else {
                    fprintf(stderr, "wrong flag given");
                    return 1;
                }
            }
        }
    
        
        
        else if (argv[j][0] != '-' && has_ef == 1) {
            files[files_count] = argv[j];
            files_count += 1;
        }
        else if (argv[j][0] != '-' && has_ef == 0 && patterns_count == 0) {
            patterns[patterns_count] = argv[j];
            patterns_count += 1;
        }
        else if (argv[j][0] != '-' && has_ef == 0 && patterns_count == 1) {
            files[files_count] = argv[j];
            files_count += 1;
        }
        else {
            fprintf(stderr, "wrong flag");
            return 1;
        }
    }
    if (patterns_count == 0 && has_ef == 0) {
        fprintf(stderr, "no patterns given");
        return 1;
    }
    regex_t proc_string[1024];
    for (int i = 0; i < patterns_count; i++) {
        int setting = 0;
        if (flags.i == 1) {
            setting = REG_ICASE;
        }
        if (regcomp(&proc_string[i], patterns[i], setting) != 0) {
            fprintf(stderr, "error with proc");
            for (int j = 0; j < i; j++) {
                regfree(&proc_string[j]);
            }
            return 1;
        }
    }
    int show_name = 0;
    if (files_count > 1) {
        if (flags.h == 1) {
            show_name = 0;
        }
        else {
            show_name = 1;
        }
    }
    if (files_count == 0) {
        FILE *file = stdin;
        int res = readfile(file, proc_string, NULL, 0, patterns_count, flags);
        if (res == 1) {
            exit_status = 1;
        }
    }
    else {
        for (int i = 0; i < files_count; i++) {
            char *filename = files[i];
            FILE *file = fopen(filename, "r");
            if (file == NULL) {
                if (flags.s == 1) {
                    exit_status = 1;
                    continue;
                }
                else {
                    fprintf(stderr, "error with file:  %s", filename);
                    exit_status = 1;
                    continue;
                }
            }
            int res = readfile(file, proc_string, filename, show_name, patterns_count, flags);
            fclose(file);
            if (res == 1) {
                exit_status = 1;
            }
        }
    }
    for (int i = 0; i < patterns_count; i++) {
        regfree(&proc_string[i]);
    }
    return exit_status;
}


int pattern_in_string(char *line_buffer, regex_t *proc_string, int patterns_count, Flags flags) {
    for (int i = 0; i < patterns_count; i++) {
        int result = regexec(&proc_string[i], line_buffer, 0, NULL, 0);
        if (result == 0) {
            if (flags.v == 1) {
                return -1;
            }
            else {
                return 1;
            }
        }
        else if (result != REG_NOMATCH && result != 0) {
            return -2;
        }
    }
    if (flags.v == 1) {
        return 1;
    }
    else {
        return -1;
    } 
}


int pattern_in_string_f(char *line_buffer, regex_t *proc_string, int patterns_count, char *filename, int show_name, int line_numb, Flags flags) {
    regmatch_t match[1];
    int search_pos = 0;
    int result = 0;
    int coincidence = 0;
    int coincidence_start;
    int coincidence_end;
    while (1) {
        coincidence = 0;
        for (int i = 0; i < patterns_count; i++) {
            if (search_pos == 0) {
                result = regexec(&proc_string[i], &line_buffer[search_pos], 1, match, 0);
            }
            if (search_pos != 0) {
                result = regexec(&proc_string[i], &line_buffer[search_pos], 1, match, REG_NOTBOL);
            }
            if (result == 0) {
                if ((match->rm_eo - match->rm_so == 0) && line_buffer[search_pos + match->rm_eo] == '\0') {
                    continue;
                }
                else if (match->rm_eo - match->rm_so == 0) {
                    if (coincidence == 0) {
                        coincidence_start = match->rm_so;
                        coincidence_end = match->rm_eo;
                        coincidence += 1;
                    }
                    else if (coincidence > 0) {
                        if (coincidence_start > match->rm_so) {
                            coincidence_start = match->rm_so;
                            coincidence_end = match->rm_eo;
                        }
                        else if (coincidence_start == match->rm_so) {
                            if ((coincidence_end - coincidence_start) < (match->rm_eo - match->rm_so)) {
                                coincidence_start = match->rm_so;
                                coincidence_end = match->rm_eo;
                            }
                        }
                    }
                }
                else {
                    if (coincidence == 0) {
                        coincidence_start = match->rm_so;
                        coincidence_end = match->rm_eo;
                        coincidence += 1;
                    }
                    else if (coincidence > 0) {
                        if (coincidence_start > match->rm_so) {
                            coincidence_start = match->rm_so;
                            coincidence_end = match->rm_eo;
                        }
                        else if (coincidence_start == match->rm_so) {
                            if ((coincidence_end - coincidence_start) < (match->rm_eo - match->rm_so)) {
                                coincidence_start = match->rm_so;
                                coincidence_end = match->rm_eo;
                            }
                        }
                    }
                }
            }
            else if (result == REG_NOMATCH) {
                continue;
            }
            else {
                return 1;
            }
        }
        if (coincidence == 0) {
            break;
        }
        if (coincidence_end - coincidence_start != 0) {
            if (show_name == 0) {
                if (flags.n == 1) {
                    printf("%d:", line_numb);
                }
            }
            else if (show_name == 1) {
                if (flags.n == 1) {
                    printf("%s:%d:", filename, line_numb);
                }
                else {
                    printf("%s:", filename);
                }
            }
            for (int j = coincidence_start; j < coincidence_end; j++) {
                fprintf(stdout, "%c", line_buffer[j + search_pos]);
            }
            printf("\n");
            search_pos += coincidence_end;
        }
        else {
            search_pos += coincidence_end;
            search_pos += 1;
        }
    }
    return 0;
}



int readfile(FILE *file, regex_t *proc_string, char *filename, int show_name, int patterns_count, Flags flags) {
    char line_buffer[1024];
    int buff_ind = 0;
    int line_numb = 1;
    int lines_count = 0;
    int symb = fgetc(file);
    while (symb != EOF) {
        if (symb != '\n') {
            if (buff_ind < 1023) {
                line_buffer[buff_ind] = symb;
                buff_ind += 1;
            }
            else {
                fprintf(stderr, "stack overflow");
                return 1;
            }
        }
        else {
            line_buffer[buff_ind] = '\0';
            int res = pattern_in_string(line_buffer, proc_string, patterns_count, flags);
            if (res == 1) {
                if (flags.l == 1 && filename != NULL) {
                    printf("%s\n", filename);
                    return 0;
                }
                else if (flags.l == 1 && filename == NULL) {
                    printf("standard input\n");
                    return 0;
                }
                else if (flags.c == 1) {
                    lines_count += 1;
                }
                else if (flags.o == 1) {
                    if (pattern_in_string_f(line_buffer, proc_string, patterns_count, filename, show_name , line_numb, flags) == 1) {
                        fprintf(stderr, "error with flag o");
                        return 1;
                    }
                }
                else {
                    if (show_name == 0) {
                        if (flags.n == 1) {
                            printf("%d:%s\n", line_numb, line_buffer);
                        }
                        else {
                            printf("%s\n", line_buffer);
                        }
                    }
                    else if (show_name == 1) {
                        if (flags.n == 1) {
                            printf("%s:%d:%s\n", filename, line_numb, line_buffer);
                        }
                        else {
                            printf("%s:%s\n", filename, line_buffer);
                        }
                    }
                }
            }
            else if (res == -2) {
                fprintf(stderr, "error with pattern");
                return 1;
            }
            line_numb += 1;
            buff_ind = 0;
        }
        symb = fgetc(file);
    }
    if (ferror(file)) {
        if (flags.s == 1) {
            return 1;
        }
        else {
            fprintf(stderr, "error with file");
            return 1;
        }
    }
    if (buff_ind > 0) {
        line_buffer[buff_ind] = '\0';
        int res = pattern_in_string(line_buffer, proc_string, patterns_count, flags);
        if (res == 1) {
            if (flags.l == 1 && filename != NULL) {
                printf("%s\n", filename);
                return 0;
            }
            else if (flags.l == 1 && filename == NULL) {
                printf("standard input\n");
                return 0;
            }
            else if (flags.c == 1) {
                lines_count += 1;
            }
            else if (flags.o == 1) {
                if (pattern_in_string_f(line_buffer, proc_string, patterns_count, filename, show_name , line_numb, flags) == 1) {
                    fprintf(stderr, "error with flag o");
                    return 1;
                }   
            }
            else {
                if (show_name == 0) {
                    if (flags.n == 1) {
                        printf("%d:%s\n", line_numb, line_buffer);
                    }
                    else {
                        printf("%s\n", line_buffer);
                    }
                }
                else if (show_name == 1) {
                    if (flags.n == 1) {
                        printf("%s:%d:%s\n", filename, line_numb, line_buffer);
                    }
                    else {
                        printf("%s:%s\n", filename, line_buffer);
                    }
                }  
            }
        }
        else if (res == -2) {
            fprintf(stderr, "error with pattern");
            return 1;
        }

    }
    if (flags.c == 1 && flags.l == 0) {
        if (show_name == 1) {
            printf("%s:%d\n", filename, lines_count);
        }
        else if (show_name == 0) {
            printf("%d\n", lines_count);
        }
    }
    return 0;
}