Untitled

mail@pastecode.io avatar
unknown
c_cpp
7 months ago
7.6 kB
2
Indexable
Never
#define _GNU_SOURCE
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 4096

typedef struct short_flags {
  int i_flag;
  int v_flag;
  int c_flag;
  int l_flag;
  int n_flag;
  int h_flag;
  int s_flag;
  int o_flag;
} shortflags;

void short_flags_parser(char argv, shortflags *flags) {
  if (argv == 'i') flags->i_flag = 1;
  if (argv == 'v') flags->v_flag = 1;
  if (argv == 'c') flags->c_flag = 1;
  if (argv == 'l') flags->l_flag = 1;
  if (argv == 'n') flags->n_flag = 1;
  if (argv == 'h') flags->h_flag = 1;
  if (argv == 's') flags->s_flag = 1;
  if (argv == 'o') flags->o_flag = 1;
}

void add_elem_arr(char ***array, int *size, char *data) {
  char **new_array;
  *size = *size + 1;
  new_array = realloc(*array, sizeof(char *) * (*size));
  new_array[*size - 1] = malloc(sizeof(char) * strlen(data) + 1);
  strcpy(new_array[*size - 1], data);
  *array = new_array;
}

char **init_arr(char **array, char *data,
                int *size) {  //создаёт массив размером 1 где в нулевом элементе
                              //лежит название массива
  *size = 1;
  array = malloc(sizeof(char *));
  array[0] = malloc(strlen(data) * sizeof(char) + 1);
  strcpy(array[0], data);
  return array;
}
void rm_arr(char **array, int size) {
  for (int i = 0; i < size; i++) {
    free(array[i]);
  }
  free(array);
}
void print_arr(char **array, int size) {
  printf("print_arr size: %d\n", size);
  for (int i = 0; i < size; i++) {
    printf("print_arr[%d]: %s\n",i, array[i]);
  }
}
int f_flag_handler(char *filename, char ***templates, int *templates_size) {
  FILE *file = fopen(filename, "r");
  char *line = NULL;
  int err_flag = 0;
  size_t length = 0;
  if (file == NULL) {
    printf("grep: %s: No such file or directory\n", filename);
    err_flag = 1;
  } else {
    while (getline(&line, &length, file) > 0) {
      char *pos;
      if ((pos = strchr(line, '\n')) != NULL) *pos = '\0';
      add_elem_arr(templates, templates_size, line);
    }
    fclose(file);
  }
  free(line);
  return err_flag;
}
int arg_handler(int argc, char **argv, shortflags *flags, char ***templates,
                int *templates_size, char ***filenames, int *filenames_size,
                int *err_flag)  //получает массив argv
{
  for (int i = 1; i < argc; i++) {
    for (size_t j = 1; j < strlen(argv[i]); j++) {
      if (argv[i][0] == '-' && argv[i][1] != 'e' && argv[i][1] != 'f') {
        short_flags_parser(argv[i][j], flags);
      }
    }
    if (argv[i][0] != '-') {
      add_elem_arr(filenames, filenames_size, argv[i]);
    }
    if (argv[i][0] == '-' && argv[i][1] == 'e') {
      if (argv[i + 1] != NULL) {
        add_elem_arr(templates, templates_size, argv[i + 1]);
        i++;
      } else
        *err_flag = 1;
    }
    if (argv[i][0] == '-' && argv[i][1] == 'f') {
      if (argv[i + 1] != NULL) {
        if (f_flag_handler(argv[i + 1], templates, templates_size) == 1) {
          *err_flag = 1;
          break;
        }
        i++;
      } else
        *err_flag = 1;
    }
  }
  return *err_flag;
}

int fill_all_matches_one_file(shortflags *flags, char ***templates,
                              int *templates_size, char ***matches,
                              int *matches_size, FILE *file,
                              int *line_numbers) {
  int err_flag = 0;
  regex_t comp_template_storage;
  regex_t *comp_template = &comp_template_storage;
  regmatch_t pmatch;
  size_t length = 0;
  int regflag = REG_EXTENDED;
  if (flags->i_flag == 1) regflag = REG_ICASE;
  char *line = NULL;
  int line_number = 0, index = 0, v_case = 0;
  if (flags->v_flag) v_case = REG_NOMATCH;
  for (int i = 1; i < *templates_size; i++) {
    regcomp(comp_template, *templates[i], regflag);
  }
  while (getline(&line, &length, file) > 0) {
    line_number++;
    if (regexec(comp_template, line, 1, &pmatch, 0) == v_case)
      add_elem_arr(matches, matches_size, line);
    line_numbers[index] = line_number;  // -1 na vyzov
    index = index + 1;
  }
  regfree(comp_template);
  free(line);
  return err_flag;
}

int grepfile(char *filename, char ***templates, int *templates_size,
             shortflags *flags, char ***matches, int *matches_size,
             int *line_numbers) {
  int err_flag = 0;
  FILE *file = fopen(filename, "r");
  if (file == NULL) {
    if (flags->s_flag == 0)
      printf("grep: %s: No such file or directory\n", filename);
    err_flag = 1;
  } else {
    fill_all_matches_one_file(flags, templates, templates_size, matches,
                              matches_size, file, line_numbers);
    fclose(file);
  }
  return err_flag;
}

int output(char *filename, shortflags *flags, char ***matches,
           int *matches_size, int *line_numbers, char ***templates,
           int *templates_size) {
  int err_flag = 0;
  int c_counter = *matches_size - 1;
  if (flags->l_flag && c_counter >= 1) c_counter = 1;  // macos c_flag l case

  if (!flags->c_flag && !flags->l_flag) {
    int ind = 0;
    // while (matches->next != NULL) {
    for (int i = 1; i < *matches_size; i++) {
      if (!flags->h_flag) printf("%s:", filename);
      if (flags->n_flag) printf("%d:", line_numbers[ind]);
      if (!flags->o_flag) printf("%s", *matches[i]);
      if (flags->o_flag && flags->v_flag) printf("%s\n", *matches[i]);
      if (flags->o_flag && !flags->v_flag)
        // o_flag_handler(*matches[i], templates, flags);
        ind++;
      if (!flags->o_flag) printf("\n");
    }
  }
  if (flags->c_flag && c_counter > 0) {
    if (!flags->h_flag) printf("%s:%d\n", filename, c_counter);
    if (flags->h_flag) printf("%d\n", c_counter);
  }

  if (flags->l_flag && c_counter >= 1) {  // l_flag
    printf("%s\n", filename);
  }
  return err_flag;
}

int logic_handler( char ***templates, int *templates_size,shortflags *flags, char ***filenames, int *filenames_size) {
  int err_flag = 0;
  int line_numbers[MAX_SIZE];
  for (int i = 1; i < *filenames_size; i++) {
    char **matches;
    int matches_size = 0;
    matches = init_arr(matches, "root_matches", &matches_size);
    if (grepfile(*filenames[i], templates, templates_size, flags, &matches,
                 &matches_size, line_numbers) == 1)
      err_flag = 1;
    // output(*filenames[i], flags, &matches, &matches_size, line_numbers,
    //        templates, templates_size);
    rm_arr(matches, matches_size);
  }
  return err_flag;
}

int main(int argc, char *argv[]) {
  int err_flag = 0;
  if (argc > 1) {
    shortflags flags = {0, 0, 0, 0, 0, 0, 0, 0};
    char **filenames;
    int filenames_size = 0;
    filenames = init_arr(filenames, "root_filenames", &filenames_size);
    char **templates;
    int templates_size = 0;
    templates = init_arr(templates, "root_templates", &templates_size);
    if (!arg_handler(argc, argv, &flags, &templates, &templates_size,
                     &filenames, &filenames_size, &err_flag)) {
        printf("templates_size: %d\n", templates_size);
        if(templates_size > 1){
        if(logic_handler(&templates, &templates_size, &flags,  &filenames, &filenames_size)==1) err_flag = 1;
        }
    } else {
      printf(
          "grep: options require an argument -- [-ef]\nUsage: grep [OPTION]... "
          "PATTERNS [FILE]...\nTry 'grep --help' for more information.\n");
    }
    rm_arr(filenames, filenames_size);
    rm_arr(templates, templates_size);
  } else {
    printf("err: empty input\nusage: [-e pattern] [-f file] [-ivclnhso]\n");
    err_flag = 1;
  }
  return err_flag;
}