@@ -46,6 +46,7 @@ void init_grep_defaults(void)
46
46
color_set (opt -> color_filename , "" );
47
47
color_set (opt -> color_function , "" );
48
48
color_set (opt -> color_lineno , "" );
49
+ color_set (opt -> color_columnno , "" );
49
50
color_set (opt -> color_match_context , GIT_COLOR_BOLD_RED );
50
51
color_set (opt -> color_match_selected , GIT_COLOR_BOLD_RED );
51
52
color_set (opt -> color_selected , "" );
@@ -155,6 +156,7 @@ void grep_init(struct grep_opt *opt, const char *prefix)
155
156
opt -> extended_regexp_option = def -> extended_regexp_option ;
156
157
opt -> pattern_type_option = def -> pattern_type_option ;
157
158
opt -> linenum = def -> linenum ;
159
+ opt -> columnnum = def -> columnnum ;
158
160
opt -> max_depth = def -> max_depth ;
159
161
opt -> pathname = def -> pathname ;
160
162
opt -> relative = def -> relative ;
@@ -164,6 +166,7 @@ void grep_init(struct grep_opt *opt, const char *prefix)
164
166
color_set (opt -> color_filename , def -> color_filename );
165
167
color_set (opt -> color_function , def -> color_function );
166
168
color_set (opt -> color_lineno , def -> color_lineno );
169
+ color_set (opt -> color_columnno , def -> color_columnno );
167
170
color_set (opt -> color_match_context , def -> color_match_context );
168
171
color_set (opt -> color_match_selected , def -> color_match_selected );
169
172
color_set (opt -> color_selected , def -> color_selected );
@@ -1277,23 +1280,36 @@ static int match_expr_eval(struct grep_opt *opt, struct grep_expr *x, char *bol,
1277
1280
0 );
1278
1281
break ;
1279
1282
case GREP_NODE_AND :
1280
- if (!match_expr_eval (opt , x -> u .binary .left , bol , eol , ctx , col ,
1281
- icol , 0 ))
1282
- return 0 ;
1283
- h = match_expr_eval (opt , x -> u .binary .right , bol , eol , ctx , col ,
1283
+ h = match_expr_eval (opt , x -> u .binary .left , bol , eol , ctx , col ,
1284
1284
icol , 0 );
1285
+ if (h || opt -> columnnum ) {
1286
+ /*
1287
+ * Don't short-circuit AND when given --column, since a
1288
+ * NOT earlier in the tree may turn this into an OR. In
1289
+ * this case, see the below comment.
1290
+ */
1291
+ h &= match_expr_eval (opt , x -> u .binary .right , bol , eol ,
1292
+ ctx , col , icol , 0 );
1293
+ }
1285
1294
break ;
1286
1295
case GREP_NODE_OR :
1287
- if (!collect_hits )
1296
+ if (!(collect_hits || opt -> columnnum )) {
1297
+ /*
1298
+ * Don't short-circuit OR when given --column (or
1299
+ * collecting hits) to ensure we don't skip a later
1300
+ * child that would produce an earlier match.
1301
+ */
1288
1302
return (match_expr_eval (opt , x -> u .binary .left , bol , eol ,
1289
1303
ctx , col , icol , 0 ) ||
1290
1304
match_expr_eval (opt , x -> u .binary .right , bol ,
1291
1305
eol , ctx , col , icol , 0 ));
1306
+ }
1292
1307
h = match_expr_eval (opt , x -> u .binary .left , bol , eol , ctx , col ,
1293
1308
icol , 0 );
1294
- x -> u .binary .left -> hit |= h ;
1309
+ if (collect_hits )
1310
+ x -> u .binary .left -> hit |= h ;
1295
1311
h |= match_expr_eval (opt , x -> u .binary .right , bol , eol , ctx , col ,
1296
- icol , 1 );
1312
+ icol , collect_hits );
1297
1313
break ;
1298
1314
default :
1299
1315
die ("Unexpected node type (internal error) %d" , x -> node );
@@ -1316,6 +1332,7 @@ static int match_line(struct grep_opt *opt, char *bol, char *eol,
1316
1332
enum grep_context ctx , int collect_hits )
1317
1333
{
1318
1334
struct grep_pat * p ;
1335
+ int hit = 0 ;
1319
1336
1320
1337
if (opt -> extended )
1321
1338
return match_expr (opt , bol , eol , ctx , col , icol ,
@@ -1325,11 +1342,21 @@ static int match_line(struct grep_opt *opt, char *bol, char *eol,
1325
1342
for (p = opt -> pattern_list ; p ; p = p -> next ) {
1326
1343
regmatch_t tmp ;
1327
1344
if (match_one_pattern (p , bol , eol , ctx , & tmp , 0 )) {
1328
- * col = tmp .rm_so ;
1329
- return 1 ;
1345
+ hit |= 1 ;
1346
+ if (!opt -> columnnum ) {
1347
+ /*
1348
+ * Without --column, any single match on a line
1349
+ * is enough to know that it needs to be
1350
+ * printed. With --column, scan _all_ patterns
1351
+ * to find the earliest.
1352
+ */
1353
+ break ;
1354
+ }
1355
+ if (* col < 0 || tmp .rm_so < * col )
1356
+ * col = tmp .rm_so ;
1330
1357
}
1331
1358
}
1332
- return 0 ;
1359
+ return hit ;
1333
1360
}
1334
1361
1335
1362
static int match_next_pattern (struct grep_pat * p , char * bol , char * eol ,
0 commit comments