2607

grep_s21_grep.c

Dec 5th, 2021
604
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #define _GNU_SOURCE
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <errno.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8. #include <regex.h>
  9. #include "s21_grep.h"
  10.  
  11.  
  12. int main(int argc, char* argv[]) {
  13.     int error = 0;
  14.     struct opts grep_opt = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", ""};
  15. #if defined(__APPLE__)
  16.     if (argc > 1 && *argv[1] != '-') {
  17.         snprintf(grep_opt.pattern, MAX_LEN, "%s", argv[1]);
  18.         getopt(argc, argv, "e:ivclnhsof:");
  19.         optind++;
  20.     }
  21. #endif
  22.     for (int opt; (opt = getopt(argc, argv, "e:ivclnhsof:")) != -1;) {
  23.         // printf("opt: %c, optind: %d\n", opt, optind);
  24.         switch (opt) {
  25.             case 'e':
  26.                 grep_opt.e = 1;
  27.                 if (!strlen(grep_opt.pattern)) {
  28.                     snprintf(grep_opt.pattern, MAX_LEN, "%s", optarg);
  29.                 } else {
  30.                     snprintf(grep_opt.pattern + strlen(grep_opt.pattern),
  31.                                 MAX_LEN - strlen(grep_opt.pattern), "|%s", optarg);
  32.                 }
  33.             break;
  34.             case 'i':
  35.                 grep_opt.i = 1;
  36.             break;
  37.             case 'v':
  38.                 grep_opt.v = 1;
  39.             break;
  40.             case 'c':
  41.                 grep_opt.c = 1;
  42.             break;
  43.             case 'l':
  44.                 grep_opt.l = 1;
  45.             break;
  46.             case 'n':
  47.                 grep_opt.n = 1;
  48.             break;
  49.             case 'h':
  50.                 grep_opt.h = 1;
  51.             break;
  52.             case 's':
  53.                 grep_opt.s = 1;
  54.             break;
  55.             case 'o':
  56.                 grep_opt.o = 1;
  57.             break;
  58.             case 'f':
  59.                 grep_opt.f = 1;
  60.                 snprintf(grep_opt.file, MAX_LEN, "%s", optarg);
  61.             break;
  62.             case '?':
  63.                 error = 2;
  64.             break;
  65.         }
  66.     }
  67.     if (!error && argc > 1) {
  68.         // printf("-e: %d\n", grep_opt.e);
  69.         // printf("-e pattern: %s\n", grep_opt.pattern);
  70.         // printf("-i: %d\n", grep_opt.i);
  71.         // printf("-v: %d\n", grep_opt.v);
  72.         // printf("-c: %d\n", grep_opt.c);
  73.         // printf("-l: %d\n", grep_opt.l);
  74.         // printf("-n: %d\n", grep_opt.n);
  75.         // printf("-h: %d\n", grep_opt.h);
  76.         // printf("-s: %d\n", grep_opt.s);
  77.         // printf("-o: %d\n", grep_opt.o);
  78.         // printf("-f: %d\n", grep_opt.f);
  79.         // printf("-f file: %s\n", grep_opt.file);
  80.         int index = optind;
  81.         // printf("index: %d argc: %d\n", index, argc);
  82.         if (!grep_opt.e && !grep_opt.f && index < argc && !strlen(grep_opt.pattern)) {
  83.                 // grep_opt.e = 1;
  84.                 snprintf(grep_opt.pattern, MAX_LEN, "%s", argv[index]);
  85.                 index++;
  86.         } else {
  87.             if (grep_opt.f) {
  88.                 if (create_pattern(&grep_opt)) {
  89.                     fprintf(stderr, "%s: %s: %s\n", GREP, grep_opt.file, strerror(errno));
  90.                     error = 2;
  91.                 }
  92.             }
  93.         }
  94.         // printf("pattern: [%s]\n", grep_opt.pattern);
  95.         if ((argc - index) == 1) {                          // the only one target
  96.             grep_opt.h = 1;
  97.         }
  98.         if (!error) {
  99.             for (; index < argc; index++) {
  100.                 // printf("Non-option argument %s\n", argv[index]);
  101.                 if (output(argv[index], grep_opt)) {;
  102.                     error = 2;
  103.                 }
  104.             }
  105.         }
  106.     } else {
  107.         promt();
  108.         error = 2;
  109.     }
  110.     return error;
  111. }
  112.  
  113. int output(const char* grep_file, struct opts grep_opt) {
  114.     int error = 0;
  115.     FILE* fp;
  116.  
  117.     fp = fopen(grep_file, "rt");
  118.     if (fp) {
  119.         char* str = NULL;
  120.         size_t len_str = 0;
  121.         ssize_t num_read = 0;
  122.         size_t num_str = 0;
  123.         int while_exit = 1;                                 //  instead of break;
  124.         size_t count_sut_line = 0;
  125.         size_t count_unsut_line = 0;
  126.         while ((num_read = getline(&str, &len_str , fp)) != -1 && str && while_exit) {
  127.             if (feof(fp) && num_read > 0 && str[num_read - 1] != '\n') {
  128.                     char* new_str = (char*)realloc(str, num_read + 2);
  129.                 if (!new_str) {
  130.                     fprintf(stderr, "%s: allocation memory error\n", GREP);
  131.                     error = 2;
  132.                     break;
  133.                 } else {
  134.                     str = new_str;
  135.                     snprintf(str + num_read, num_read + 2, "%c", '\n');
  136.                 }
  137.             }
  138.             num_str++;
  139.             if (grep_opt.l) {
  140.                 if (!grep_opt.v) {
  141.                     if (!regular(str, grep_opt.pattern, grep_opt.i)) {
  142.                         printf("%s\n", grep_file);
  143.                         while_exit = 0;
  144.                     }
  145.                 } else {
  146.                     printf("%s\n", grep_file);
  147.                     while_exit = 0;
  148.                 }
  149.             } else if (grep_opt.c) {
  150.                 if (!regular(str, grep_opt.pattern, grep_opt.i)) {
  151.                     count_sut_line++;
  152.                 } else {
  153.                     count_unsut_line++;
  154.                 }
  155.             } else if (grep_opt.o) {
  156.                 if (!grep_opt.v) {
  157.                     regular_prn(str, grep_file, num_str, grep_opt);
  158.                 }
  159.             }
  160.             if (grep_opt.v && !grep_opt.l && !grep_opt.c) {
  161.                 if (grep_opt.o) {
  162. #if defined(__APPLE__)
  163.                     if (regular(str, grep_opt.pattern, grep_opt.i)) {
  164.                         print_str(str, grep_file, num_str, grep_opt);
  165.                     }
  166. #endif
  167.                 } else {
  168.                     if (regular(str, grep_opt.pattern, grep_opt.i)) {
  169.                         print_str(str, grep_file, num_str, grep_opt);
  170.                     }
  171.                 }
  172.             } else if (!grep_opt.v && !grep_opt.l && !grep_opt.c  && !grep_opt.o) {
  173.                 if (!regular(str, grep_opt.pattern, grep_opt.i)) {
  174.                     print_str(str, grep_file, num_str, grep_opt);
  175.                 }
  176.             }
  177.         }
  178.         DESTROY(str);
  179.         if (!error) {
  180.             if (grep_opt.c) {                               // output for -c
  181.                 if (!grep_opt.h) {
  182.                     printf("%s:", grep_file);
  183.                 }
  184.                 if (!grep_opt.v) {
  185.                     printf("%zu\n", count_sut_line);
  186.                 } else {
  187.                     printf("%zu\n", count_unsut_line);
  188.                 }
  189.             }
  190.         }
  191.         fclose(fp);
  192.     } else {
  193.         if (!grep_opt.s) {
  194.             fprintf(stderr, "%s: %s: %s\n", GREP, grep_file, strerror(errno));
  195.             error = 1;
  196.         }
  197.     }
  198.     return error;
  199. }
  200.  
  201.  
  202. int regular(const char* str, const char* pattern, int opt_i) {
  203.     int result;                                     // -1 - bad pattern, 0 - found, 1 - not found
  204.     regex_t rexp;
  205.  
  206.     int res_val;
  207.     if (opt_i) {
  208.         res_val = regcomp(&rexp, pattern, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | REG_ICASE);
  209.     } else {
  210.         res_val = regcomp(&rexp, pattern, REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
  211.     }
  212.     if (res_val) {
  213.         printf("Failed, bad pattern\n");
  214.         result = -1;
  215.     } else {
  216.         regmatch_t match;
  217.         result = regexec(&rexp, str, 1, &match, 0);
  218.         // printf("result: %d\n", result);
  219.         regfree(&rexp);
  220.     }
  221.     return result;
  222. }
  223.  
  224. int regular_prn(const char* str, const char* grep_file, const size_t num_str, struct opts grep_opt) {
  225.     int result = 1;                             // -1 - bad pattern, 0 - found, 1 - not found
  226.     regex_t rexp;
  227.     char* str_ptr = (char*)str;
  228.  
  229.     int res_val;
  230.     if (grep_opt.i) {
  231.         res_val = regcomp(&rexp, grep_opt.pattern, REG_EXTENDED | REG_NEWLINE | REG_ICASE);
  232.     } else {
  233.         res_val = regcomp(&rexp, grep_opt.pattern, REG_EXTENDED | REG_NEWLINE);
  234.     }
  235.     if (res_val) {
  236.         printf("Failed, bad pattern\n");
  237.         result = -1;
  238.     } else {
  239.         regmatch_t  match;
  240. #if defined(__APPLE__)
  241.         if (!grep_opt.h && !regular(str, grep_opt.pattern, grep_opt.i)) {
  242.             printf("%s:", grep_file);
  243.         }
  244.         if (grep_opt.n && !regular(str, grep_opt.pattern, grep_opt.i)) {
  245.             printf("%zu:", num_str);
  246.         }
  247.         // printf("String = \"%s pattern %s as %d\"\n\n", str, pattern, opt_i);
  248.         while (!regexec(&rexp, str_ptr, 1, &match, 0)) {
  249.             result = 0;
  250.             printf("%.*s\n", (int)(match.rm_eo - match.rm_so), str_ptr + match.rm_so);
  251.             str_ptr += match.rm_eo;
  252.         }
  253. #else
  254.         while (!regexec(&rexp, str_ptr, 1, &match, 0)) {
  255.             result = 0;
  256.             if (!grep_opt.h) {
  257.                 printf("%s:", grep_file);
  258.             }
  259.             if (grep_opt.n) {
  260.                 printf("%zu:", num_str);
  261.             }
  262.             printf("%.*s\n", (int)(match.rm_eo - match.rm_so), str_ptr + match.rm_so);
  263.             str_ptr += match.rm_eo;
  264.         }
  265. #endif
  266.         regfree(&rexp);
  267.     }
  268.     return result;
  269. }
  270.  
  271. int create_pattern(struct opts* grep_opt) {
  272.     int error = 0;
  273.     FILE* fp;
  274.  
  275.     fp = fopen(grep_opt->file, "rt");
  276.     if (fp) {
  277.         char* str = NULL;
  278.         size_t len_str = 0;
  279.         ssize_t num_read = 0;
  280.         if (!grep_opt->e) {
  281.             if ((num_read = getline(&str, &len_str , fp)) != -1 && str) {
  282.                 if (num_read > 1 && str[num_read - 1] == '\n') {
  283.                     str[num_read - 1] = '\0';
  284.                 }
  285.                 snprintf(grep_opt->pattern, MAX_LEN, "%s", str);
  286.             }
  287.         }
  288.         while ((num_read = getline(&str, &len_str , fp)) != -1 && str) {
  289.             if (num_read > 1  && str[num_read - 1] == '\n') {
  290.                 str[num_read - 1] = '\0';
  291.             }
  292.             snprintf(grep_opt->pattern + strlen(grep_opt->pattern),
  293.                         MAX_LEN - strlen(grep_opt->pattern), "|%s", str);
  294.         }
  295.         DESTROY(str);
  296.         fclose(fp);
  297.     } else {
  298.         error = 1;
  299.     }
  300.     return error;
  301. }
  302.  
  303. void print_str(const char* str, const char* grep_file, const size_t num_str, struct opts grep_opt) {
  304.     if (!grep_opt.h) {
  305.         printf("%s:", grep_file);
  306.     }
  307.     if (grep_opt.n) {
  308.         printf("%zu:", num_str);
  309.     }
  310.     printf("%s", str);
  311. }
  312.  
  313. void promt() {
  314.     fprintf(stderr, "usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]]\n");
  315.     fprintf(stderr, "\t[-e pattern] [-f file] [--binary-files=value] [--color=when]\n");
  316.     fprintf(stderr, "\t[--context[=num]] [--directories=action] [--label] [--line-buffered]\n");
  317.     fprintf(stderr, "\t[--null] [pattern] [file ...]\n");
  318. }
RAW Paste Data