pang@1: #include pang@1: #include pang@1: #include pang@1: pang@1: #define __USE_GNU pang@1: #include pang@1: paulo@4: #include paulo@4: paulo@4: #define _GNU_SOURCE paulo@4: #include paulo@4: pang@1: const size_t BUFSIZE = 5000; pang@1: paulo@9: const char *_CLR_START = "\x1B["; paulo@9: const char *_CLR_BOLD = "1;"; paulo@9: char *CLR_START; paulo@5: const char *CLR_END = "m"; paulo@5: const char *CLR_CLEAR = "\x1B[0m"; pang@1: paulo@9: char *CLR_CLR; paulo@9: paulo@9: const char *CLR_FG_RED = "31"; paulo@9: paulo@9: typedef struct _colors { paulo@9: char *name; paulo@9: char *fg; paulo@9: char *bg; paulo@9: } Colors; paulo@9: paulo@9: const Colors COLORS[] = { paulo@9: { "black", "30", "40" }, paulo@9: { "red", "31", "41" }, paulo@9: { "green", "32", "42" }, paulo@9: { "brown", "33", "43" }, paulo@9: { "blue", "34", "44" }, paulo@9: { "magenta", "35", "45" }, paulo@9: { "cyan", "36", "46" }, paulo@9: { "white", "37", "47" }, paulo@9: { "default", "39", "49" }, paulo@9: { NULL }, paulo@9: }; paulo@9: paulo@9: char *getFGColor(char *cname) paulo@9: { paulo@9: Colors *c; paulo@9: for (c = COLORS; c->name; c++) paulo@9: { paulo@9: if (strncmp(cname, c->name, strlen(c->name)) == 0) paulo@9: return c->fg; paulo@9: } paulo@9: return NULL; paulo@9: } paulo@9: paulo@9: char *getBGColor(char *cname) paulo@9: { paulo@9: Colors *c; paulo@9: for (c = COLORS; c->name; c++) paulo@9: { paulo@9: if (strncmp(cname, c->name, strlen(c->name)) == 0) paulo@9: return c->bg; paulo@9: } paulo@9: return NULL; paulo@9: } paulo@9: paulo@8: int colorLine = 0; paulo@9: int embolden = 0; paulo@9: char *g_fg = "red"; paulo@9: char *g_bg = ""; paulo@8: paulo@4: typedef enum _exit_code { paulo@4: EXIT_OK, paulo@4: EXIT_REALLOC_ERROR, paulo@4: EXIT_ARGS_ERROR, paulo@4: } Exit_code; paulo@4: paulo@3: int re_error(int errcode, const regex_t *re) paulo@3: { paulo@3: char *err_string = calloc(BUFSIZE, sizeof(char)); paulo@3: regerror(errcode, re, err_string, BUFSIZE*sizeof(char)); paulo@3: fprintf(stderr, "%s \n", err_string); paulo@3: free(err_string); paulo@3: return errcode; paulo@3: } paulo@3: paulo@4: Exit_code realloc_error() paulo@3: { paulo@3: fprintf(stderr, "realloc() failure \n"); paulo@4: return EXIT_REALLOC_ERROR; paulo@4: } paulo@4: paulo@4: Exit_code args_error() paulo@4: { paulo@4: fprintf(stderr, "Invalid or nonexistent argument. \n"); paulo@4: return EXIT_ARGS_ERROR; paulo@4: } paulo@4: paulo@4: // returns regular expression argument paulo@4: char *parseArgs(int argc, char **argv) paulo@4: { paulo@4: static struct option long_options[] = paulo@4: { paulo@8: { "line", 0, 0, 'l' }, paulo@9: { "bold", 0, 0, 'B' }, paulo@4: { 0, 0, 0, 0 }, paulo@4: }; paulo@4: paulo@4: int c; paulo@4: int l; paulo@9: while ((c = getopt_long(argc, argv, "lBf:b:", long_options, &l)) >= 0) paulo@4: { paulo@8: if (c == 'l') paulo@8: colorLine = 1; paulo@9: else if (c == 'B') paulo@9: embolden = 1; paulo@9: else if (c == 'f') paulo@9: g_fg = strdup(optarg); paulo@9: else if (c == 'b') paulo@9: g_bg = strdup(optarg); paulo@4: } paulo@4: paulo@4: if (optind >= argc) paulo@4: exit(args_error()); paulo@4: paulo@4: return argv[optind]; paulo@3: } paulo@3: pang@1: int main(int argc, char **argv) pang@1: { paulo@4: char *re_expression = parseArgs(argc, argv); paulo@4: paulo@5: //fprintf(stderr, "re_expression = %s \n", re_expression); //d/ 20100405 PBA paulo@4: pang@1: char *buf = calloc(BUFSIZE, sizeof(char)); pang@1: paulo@3: int re_err; pang@1: regex_t *re = calloc(1, sizeof(regex_t)); paulo@4: re_err = regcomp(re, re_expression, REG_EXTENDED); paulo@3: if (re_err != 0) paulo@3: exit(re_error(re_err, re)); pang@1: pang@2: regmatch_t *rem = calloc(1, sizeof(regmatch_t)); pang@1: paulo@9: if (embolden) paulo@9: { paulo@9: CLR_START = calloc(strlen(_CLR_START) + strlen(_CLR_BOLD) + 1, sizeof(char)); paulo@9: strcpy(CLR_START, _CLR_START); paulo@9: strcat(CLR_START, _CLR_BOLD); paulo@9: } paulo@9: else paulo@9: CLR_START = strdup(_CLR_START); paulo@9: paulo@9: CLR_CLR = getFGColor(g_fg); paulo@9: if (!CLR_CLR) paulo@9: exit(args_error()); paulo@9: if (strlen(g_bg) > 0) paulo@9: { paulo@9: char *fgcolor = getFGColor(g_fg); paulo@9: char *bgcolor = getBGColor(g_bg); paulo@9: if (bgcolor) paulo@9: { paulo@9: size_t l = strlen(fgcolor) + 1 + strlen(bgcolor); paulo@9: CLR_CLR = calloc((l + 1), sizeof(char)); paulo@9: if (!CLR_CLR) paulo@9: exit(realloc_error()); paulo@9: strcpy(CLR_CLR, fgcolor); paulo@9: strcat(CLR_CLR, ";"); paulo@9: strcat(CLR_CLR, bgcolor); paulo@9: } paulo@9: else paulo@9: exit(args_error()); paulo@9: } paulo@9: pang@1: size_t CLR_START_len = strlen(CLR_START); paulo@9: size_t CLR_CLR_len = strlen(CLR_CLR); pang@1: size_t CLR_END_len = strlen(CLR_END); paulo@5: size_t CLR_CLEAR_len = strlen(CLR_CLEAR); pang@1: paulo@7: char *out = NULL; paulo@7: pang@1: while (fgets(buf, BUFSIZE, stdin)) pang@1: { pang@2: int so = -1; pang@2: int eo = -1; pang@1: paulo@6: size_t out_len = strlen(buf) + 1; paulo@3: unsigned int out_pos = 0; paulo@3: unsigned int buf_pos = 0; paulo@3: paulo@4: for (re_err = 0; re_err != REG_NOMATCH;) pang@2: { paulo@3: re_err = regexec(re, &buf[buf_pos], 1, rem, 0); pang@1: paulo@3: //fprintf(stderr, "%s", &buf[buf_pos]); //d// 20100405 PBA paulo@3: pang@2: if (out_len >= (BUFSIZE - buf_pos)) pang@2: out_len = (BUFSIZE - buf_pos) - 1; pang@1: paulo@9: out = realloc(out, out_len*sizeof(char)); paulo@7: if (!out) paulo@7: exit(realloc_error()); paulo@7: paulo@8: if (colorLine) paulo@8: { paulo@8: so = 0; paulo@8: eo = out_len - 1; paulo@8: } paulo@8: else paulo@8: { paulo@8: so = rem[0].rm_so; paulo@8: eo = rem[0].rm_eo; paulo@8: } paulo@8: paulo@7: int match_len = eo - so; pang@1: paulo@3: //fprintf(stderr, "%d %d \n", so, eo); //d// 20100327 PBA pang@1: paulo@7: if (re_err != REG_NOMATCH && so >= 0 && eo >= 0 && match_len > 0) pang@1: { paulo@9: out_len += CLR_START_len + CLR_CLR_len + CLR_END_len + CLR_CLEAR_len; paulo@9: out = realloc(out, out_len*sizeof(char)); paulo@3: if (!out) paulo@3: exit(realloc_error()); paulo@3: strncpy(&out[out_pos], &buf[buf_pos], so); paulo@3: out_pos += so; paulo@3: buf_pos += so; pang@1: strncpy(&out[out_pos], CLR_START, CLR_START_len); pang@1: out_pos += CLR_START_len; paulo@9: strncpy(&out[out_pos], CLR_CLR, CLR_CLR_len); paulo@9: out_pos += CLR_CLR_len; paulo@5: strncpy(&out[out_pos], CLR_END, CLR_END_len); paulo@5: out_pos += CLR_END_len; pang@2: strncpy(&out[out_pos], &buf[buf_pos], match_len); pang@1: out_pos += match_len; paulo@5: strncpy(&out[out_pos], CLR_CLEAR, CLR_CLEAR_len); paulo@5: out_pos += CLR_CLEAR_len; pang@2: pang@2: buf_pos += match_len; pang@1: } pang@2: else paulo@5: { paulo@3: strncpy(&out[out_pos], &buf[buf_pos], out_len - out_pos); paulo@7: out[out_len - 1] = '\0'; paulo@5: } pang@1: } pang@1: pang@1: fputs(out, stdout); pang@1: } pang@1: paulo@4: return EXIT_OK; pang@1: }