s21_grep.c: In function ‘parse_options’:
s21_grep.c:62:31: error: implicit declaration of function ‘strdup’; did you mean ‘strcmp’? [-Werror=implicit-function-declaration]
   62 |         options->regex_file = strdup(optarg);
      |                               ^~~~~~
      |                               strcmp
s21_grep.c:62:29: error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
   62 |         options->regex_file = strdup(optarg);
      |                             ^
s21_grep.c: In function ‘reader’:
s21_grep.c:136:10: error: implicit declaration of function ‘getline’ [-Werror=implicit-function-declaration]
  136 |   while (getline(&line, &line_length, file) != -1) {
      |          ^~~~~~~#ifndef S21_GREP_H
#define S21_GREP_H
#include <getopt.h>
#include <stdio.h>
#define MAX_LINE_SIZE 256

typedef struct {
  int e;
  int i;
  int v;
  int c;
  int l;
  int n;
  int h;
  int s;
  int f;
  int o;
  char *regex_file;
} Options;

void parse_options(int argc, char *argv[], Options *options, char *pattern,
                   char **files);
void reader(FILE *file, Options *options, char *pattern, const char *file_name,
            int single);
void read_regex_file(const char *regex_file, char *pattern);

struct option long_options[] = {{"regexp", required_argument, NULL, 'e'},
                                {"ignore-case", no_argument, NULL, 'i'},
                                {"invert-match", no_argument, NULL, 'v'},
                                {"count", no_argument, NULL, 'c'},
                                {"files-with-matches", no_argument, NULL, 'l'},
                                {"line-number", no_argument, NULL, 'n'},
                                {"no-filename", no_argument, NULL, 'h'},
                                {"silent", no_argument, NULL, 's'},
                                {"file", required_argument, NULL, 'f'},
                                {"only-matching", no_argument, NULL, 'o'},
                                {NULL, 0, NULL, 0}};

#endif
#include "s21_grep.h"

#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>

int main(int argc, char *argv[]) {
  Options options = {0};
  char pattern[MAX_LINE_SIZE];
  char **files = malloc(argc * sizeof(char *));
  for (int j = 0; j < argc; j++) {
    files[j] = NULL;
  }
  pattern[0] = '\0';

  if (argc < 2) {
    exit(EXIT_FAILURE);
  }

  parse_options(argc, argv, &options, pattern, files);
  if (pattern[0] == '\0') {
    printf("Pattern is required.\n");
    exit(EXIT_FAILURE);
  }

  int i = 0;
  int single = 1;
  if (files[1] != NULL) single = 0;

  while (files[i] != NULL) {
    FILE *input_file = fopen(files[i], "r");
    if (!input_file) {
      if (!options.s) {
        printf("%s: No such file or directory\n", files[i]);
      }
      free(files[i]);
      i++;
      continue;
    }
    reader(input_file, &options, pattern, files[i], single);
    fclose(input_file);
    free(files[i]);
    i++;
  }
  free(files);
}

void parse_options(int argc, char *argv[], Options *options, char *pattern,
                   char **files) {
  int opt;
  while ((opt = getopt_long(argc, argv, "e:ivclnhsof:", long_options, NULL)) !=
         -1) {
    switch (opt) {
      case 'f':
        options->f = 1;
        options->e = 1;
        options->regex_file = strdup(optarg);
        read_regex_file(options->regex_file, pattern);
        free(options->regex_file);
        break;
      case 'e':
        options->e = 1;
        if (pattern[0] != '\0') strcat(pattern, "|");
        strcat(pattern, optarg);
        break;
      case 'i':
        options->i = 1;
        break;
      case 'v':
        options->v = 1;
        break;
      case 'c':
        options->c = 1;
        break;
      case 'l':
        options->l = 1;
        break;
      case 'n':
        options->n = 1;
        break;
      case 'h':
        options->h = 1;
        break;
      case 's':
        options->s = 1;
        break;
      case 'o':
        options->o = 1;
        break;
      default:
        printf("Illegal option %s\n", argv[optind - 1]);
        exit(1);
    }
  }

  if (!options->e && (optind < argc)) {
    for (int i = 1; i < argc; i++) {
      if (argv[i][0] != '-') {
        strcat(pattern, argv[i]);
        optind++;
        break;
      }
    }
  }
  for (int i = 0; optind < argc; optind++, i++) {
    files[i] = malloc(MAX_LINE_SIZE * sizeof(char));
    strcpy(files[i], argv[optind]);
  }
}

void reader(FILE *file, Options *options, char *pattern, const char *file_name,
            int single) {
  char *line = NULL;
  size_t line_length = 0;
  int line_number = 0;
  int match_count = 0;
  int invert_match = options->v;

  regex_t regex;
  int regex_flags = REG_EXTENDED | REG_NOSUB;

  if (options->i) {
    regex_flags |= REG_ICASE;
  }

  if (regcomp(&regex, pattern, regex_flags) != 0 && !options->s) {
    fprintf(stderr, "Error compiling regular expression\n");
    exit(EXIT_FAILURE);
  }

  while (getline(&line, &line_length, file) != -1) {
    line_number++;

    int match_result = regexec(&regex, line, 0, NULL, 0);

    if ((match_result == 0 && !invert_match) ||
        (match_result != 0 && invert_match)) {
      match_count++;

      if (options->l && !options->c) {
        printf("%s\n", file_name);
        break;
      }

      if (options->n && !options->c) {
        if (!single && !options->h) printf("%s:", file_name);
        printf("%d:", line_number);
        printf("%s", line);

      }

      else if (options->o && !options->c) {
        if (!single && !options->h) printf("%s:", file_name);
        printf("%s\n", pattern);
      } else if (!options->c) {
        if (!single && !options->h) printf("%s:", file_name);
        printf("%s", line);
      }
    }
  }

  if (line != NULL) {
    if (options->c) {
      if (!single) printf("%s:", file_name);
      printf("%d\n", match_count);
    }

    if (ferror(file)) {
      perror("Error reading line");
      regfree(&regex);
      free(line);
      exit(EXIT_FAILURE);
    }
    free(line);
    regfree(&regex);
  }
}

void read_regex_file(const char *regex_file, char *pattern) {
  FILE *file = fopen(regex_file, "r");
  if (!file) {
    printf("%s: No such file or directory\n", regex_file);
    exit(EXIT_FAILURE);
  }

  char *line = NULL;
  size_t line_length = 0;

  while (getline(&line, &line_length, file) != -1) {
    line[strcspn(line, "\n")] = '\0';

    if (strlen(pattern) > 0) {
      strcat(pattern, "|");
    }
    strcat(pattern, line);
  }
  if (line != NULL) {
    free(line);
  }

  fclose(file);
}