annotate rcg.c @ 16:74cf5cfa3ec1

rcg.c: add usage help statement
author paulo@thepaulopc
date Thu, 18 Nov 2010 00:31:44 -0800
parents acf12a2e872d
children e618a3ff2027
rev   line source
pang@1 1 #include <stdio.h>
pang@1 2 #include <stdlib.h>
pang@1 3 #include <regex.h>
pang@1 4
pang@1 5 #include <string.h>
pang@1 6
paulo@4 7 #include <unistd.h>
paulo@4 8
paulo@4 9 #define _GNU_SOURCE
paulo@4 10 #include <getopt.h>
paulo@4 11
pang@1 12 const size_t BUFSIZE = 5000;
pang@1 13
paulo@9 14 const char *_CLR_START = "\x1B[";
paulo@9 15 const char *_CLR_BOLD = "1;";
paulo@9 16 char *CLR_START;
paulo@5 17 const char *CLR_END = "m";
paulo@5 18 const char *CLR_CLEAR = "\x1B[0m";
pang@1 19
paulo@9 20 typedef struct _colors {
paulo@9 21 char *name;
paulo@9 22 char *fg;
paulo@9 23 char *bg;
paulo@9 24 } Colors;
paulo@9 25
paulo@9 26 const Colors COLORS[] = {
paulo@9 27 { "black", "30", "40" },
paulo@9 28 { "red", "31", "41" },
paulo@9 29 { "green", "32", "42" },
paulo@9 30 { "brown", "33", "43" },
paulo@9 31 { "blue", "34", "44" },
paulo@9 32 { "magenta", "35", "45" },
paulo@9 33 { "cyan", "36", "46" },
paulo@9 34 { "white", "37", "47" },
paulo@9 35 { "default", "39", "49" },
paulo@9 36 { NULL },
paulo@9 37 };
paulo@9 38
paulo@9 39 char *getFGColor(char *cname)
paulo@9 40 {
paulo@9 41 Colors *c;
paulo@9 42 for (c = COLORS; c->name; c++)
paulo@9 43 {
paulo@9 44 if (strncmp(cname, c->name, strlen(c->name)) == 0)
paulo@9 45 return c->fg;
paulo@9 46 }
paulo@9 47 return NULL;
paulo@9 48 }
paulo@9 49
paulo@9 50 char *getBGColor(char *cname)
paulo@9 51 {
paulo@9 52 Colors *c;
paulo@9 53 for (c = COLORS; c->name; c++)
paulo@9 54 {
paulo@9 55 if (strncmp(cname, c->name, strlen(c->name)) == 0)
paulo@9 56 return c->bg;
paulo@9 57 }
paulo@9 58 return NULL;
paulo@9 59 }
paulo@9 60
paulo@8 61 int colorLine = 0;
paulo@9 62 int embolden = 0;
paulo@12 63 char *g_fg = "";
paulo@9 64 char *g_bg = "";
paulo@8 65
paulo@4 66 typedef enum _exit_code {
paulo@4 67 EXIT_OK,
paulo@4 68 EXIT_REALLOC_ERROR,
paulo@4 69 EXIT_ARGS_ERROR,
paulo@4 70 } Exit_code;
paulo@4 71
paulo@3 72 int re_error(int errcode, const regex_t *re)
paulo@3 73 {
paulo@3 74 char *err_string = calloc(BUFSIZE, sizeof(char));
paulo@3 75 regerror(errcode, re, err_string, BUFSIZE*sizeof(char));
paulo@3 76 fprintf(stderr, "%s \n", err_string);
paulo@3 77 free(err_string);
paulo@3 78 return errcode;
paulo@3 79 }
paulo@3 80
paulo@4 81 Exit_code realloc_error()
paulo@3 82 {
paulo@3 83 fprintf(stderr, "realloc() failure \n");
paulo@4 84 return EXIT_REALLOC_ERROR;
paulo@4 85 }
paulo@4 86
paulo@4 87 Exit_code args_error()
paulo@4 88 {
paulo@16 89 char *usage = "\
paulo@16 90 Usage: rcg [options] <PATTERN> \n\
paulo@16 91 \n\
paulo@16 92 Options: \n\
paulo@16 93 -l, --line Highlight whole line \n\
paulo@16 94 -B, --bold Bold \n\
paulo@16 95 -b <color> Background color \n\
paulo@16 96 -f <color> Foreground color \n\
paulo@16 97 \n\
paulo@16 98 <color> can be one of the following: \n\
paulo@16 99 ";
paulo@16 100
paulo@16 101 fprintf(stdout, usage);
paulo@16 102
paulo@16 103 Colors *c;
paulo@16 104 for (c = COLORS; c->name; c++)
paulo@16 105 fprintf(stdout, " %s \n", c->name);
paulo@16 106
paulo@4 107 return EXIT_ARGS_ERROR;
paulo@4 108 }
paulo@4 109
paulo@4 110 // returns regular expression argument
paulo@4 111 char *parseArgs(int argc, char **argv)
paulo@4 112 {
paulo@4 113 static struct option long_options[] =
paulo@4 114 {
paulo@8 115 { "line", 0, 0, 'l' },
paulo@9 116 { "bold", 0, 0, 'B' },
paulo@4 117 { 0, 0, 0, 0 },
paulo@4 118 };
paulo@4 119
paulo@4 120 int c;
paulo@4 121 int l;
paulo@9 122 while ((c = getopt_long(argc, argv, "lBf:b:", long_options, &l)) >= 0)
paulo@4 123 {
paulo@8 124 if (c == 'l')
paulo@8 125 colorLine = 1;
paulo@9 126 else if (c == 'B')
paulo@9 127 embolden = 1;
paulo@9 128 else if (c == 'f')
paulo@9 129 g_fg = strdup(optarg);
paulo@9 130 else if (c == 'b')
paulo@9 131 g_bg = strdup(optarg);
paulo@4 132 }
paulo@4 133
paulo@4 134 if (optind >= argc)
paulo@4 135 exit(args_error());
paulo@4 136
paulo@4 137 return argv[optind];
paulo@3 138 }
paulo@3 139
pang@1 140 int main(int argc, char **argv)
pang@1 141 {
paulo@4 142 char *re_expression = parseArgs(argc, argv);
paulo@4 143
paulo@5 144 //fprintf(stderr, "re_expression = %s \n", re_expression); //d/ 20100405 PBA
paulo@4 145
pang@1 146 char *buf = calloc(BUFSIZE, sizeof(char));
pang@1 147
paulo@3 148 int re_err;
pang@1 149 regex_t *re = calloc(1, sizeof(regex_t));
paulo@13 150 re_err = regcomp(re, re_expression, REG_EXTENDED | REG_NEWLINE);
paulo@3 151 if (re_err != 0)
paulo@3 152 exit(re_error(re_err, re));
pang@1 153
pang@2 154 regmatch_t *rem = calloc(1, sizeof(regmatch_t));
pang@1 155
paulo@9 156 if (embolden)
paulo@9 157 {
paulo@9 158 CLR_START = calloc(strlen(_CLR_START) + strlen(_CLR_BOLD) + 1, sizeof(char));
paulo@9 159 strcpy(CLR_START, _CLR_START);
paulo@9 160 strcat(CLR_START, _CLR_BOLD);
paulo@9 161 }
paulo@9 162 else
paulo@9 163 CLR_START = strdup(_CLR_START);
paulo@9 164
paulo@12 165 if (strlen(g_fg) == 0 && strlen(g_bg) == 0)
paulo@12 166 g_fg = "red";
paulo@12 167 else if (strlen(g_fg) == 0 && strlen(g_bg) > 0)
paulo@12 168 g_fg = "default";
paulo@12 169
paulo@12 170 char *fgcolor = getFGColor(g_fg);
paulo@12 171 if (!fgcolor)
paulo@9 172 exit(args_error());
paulo@12 173
paulo@12 174 char *clr = strdup(fgcolor);
paulo@9 175 if (strlen(g_bg) > 0)
paulo@9 176 {
paulo@9 177 char *bgcolor = getBGColor(g_bg);
paulo@9 178 if (bgcolor)
paulo@9 179 {
paulo@12 180 size_t l = strlen(clr) + 1 + strlen(bgcolor);
paulo@12 181 clr = realloc(clr, (l + 1)*sizeof(char));
paulo@12 182 if (!clr)
paulo@9 183 exit(realloc_error());
paulo@12 184 strcat(clr, ";");
paulo@12 185 strcat(clr, bgcolor);
paulo@9 186 }
paulo@9 187 else
paulo@9 188 exit(args_error());
paulo@9 189 }
paulo@9 190
paulo@7 191 char *out = NULL;
paulo@7 192
pang@1 193 while (fgets(buf, BUFSIZE, stdin))
pang@1 194 {
pang@2 195 int so = -1;
pang@2 196 int eo = -1;
pang@1 197
paulo@6 198 size_t out_len = strlen(buf) + 1;
paulo@3 199 unsigned int out_pos = 0;
paulo@3 200 unsigned int buf_pos = 0;
paulo@3 201
paulo@4 202 for (re_err = 0; re_err != REG_NOMATCH;)
pang@2 203 {
paulo@3 204 re_err = regexec(re, &buf[buf_pos], 1, rem, 0);
pang@1 205
paulo@3 206 //fprintf(stderr, "%s", &buf[buf_pos]); //d// 20100405 PBA
paulo@3 207
pang@2 208 if (out_len >= (BUFSIZE - buf_pos))
pang@2 209 out_len = (BUFSIZE - buf_pos) - 1;
pang@1 210
paulo@9 211 out = realloc(out, out_len*sizeof(char));
paulo@7 212 if (!out)
paulo@7 213 exit(realloc_error());
paulo@7 214
paulo@13 215 so = rem[0].rm_so;
paulo@13 216 eo = rem[0].rm_eo;
paulo@13 217
paulo@13 218 int match_len = eo - so;
paulo@13 219
paulo@13 220 if (colorLine && match_len > 0)
paulo@8 221 {
paulo@8 222 so = 0;
paulo@12 223 eo = out_len - 2;
paulo@13 224 match_len = eo - so;
paulo@8 225 }
pang@1 226
paulo@3 227 //fprintf(stderr, "%d %d \n", so, eo); //d// 20100327 PBA
pang@1 228
paulo@7 229 if (re_err != REG_NOMATCH && so >= 0 && eo >= 0 && match_len > 0)
pang@1 230 {
paulo@14 231 size_t CLR_STRING_len = strlen(CLR_START) + strlen(clr) + strlen(CLR_END) + strlen(CLR_CLEAR);
paulo@14 232
paulo@14 233 out_len += CLR_STRING_len;
paulo@9 234 out = realloc(out, out_len*sizeof(char));
paulo@3 235 if (!out)
paulo@3 236 exit(realloc_error());
pang@2 237
paulo@15 238 snprintf(&out[out_pos], out_len, "%.*s%s%s%s%.*s%s", so, &buf[buf_pos], CLR_START, clr, CLR_END, match_len, &buf[buf_pos + so], CLR_CLEAR);
paulo@14 239
paulo@14 240 buf_pos += match_len + so;
paulo@14 241 out_pos += CLR_STRING_len + match_len + so;
pang@1 242 }
pang@2 243 else
paulo@5 244 {
paulo@3 245 strncpy(&out[out_pos], &buf[buf_pos], out_len - out_pos);
paulo@7 246 out[out_len - 1] = '\0';
paulo@13 247 re_err = REG_NOMATCH;
paulo@5 248 }
pang@1 249 }
pang@1 250
pang@1 251 fputs(out, stdout);
paulo@10 252 fflush(stdout);
pang@1 253 }
pang@1 254
paulo@4 255 return EXIT_OK;
pang@1 256 }