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 }
|